Synopsis - Cross-Reference

File: /Synopsis/Parsers/Cxx/Decoder.cc
  1//
  2// Copyright (C) 2002 Stephen Davies
  3// Copyright (C) 2002 Stefan Seefeld
  4// All rights reserved.
  5// Licensed to the public under the terms of the GNU LGPL (>= 2),
  6// see the file COPYING for details.
  7//
  8
  9#include "Decoder.hh"
 10#include "Types.hh"
 11#include "Builder.hh"
 12#include "STrace.hh"
 13#include "TypeIdFormatter.hh"
 14#include "Lookup.hh"
 15#include <iostream>
 16#include <sstream>
 17
 18using namespace Synopsis;
 19
 20Decoder::Decoder(Builder* builder)
 21        : m_builder(builder)
 22{
 23    m_lookup = m_builder->lookup();
 24}
 25
 26std::string Decoder::decodeName()
 27{
 28    size_t length = *m_iter++ - 0x80;
 29    std::string name(length, '\0');
 30    std::copy(m_iter, m_iter + length, name.begin());
 31    m_iter += length;
 32    return name;
 33}
 34
 35std::string Decoder::decodeName(code_iter iter)
 36{
 37    size_t length = *iter++ - 0x80;
 38    std::string name(length, '\0');
 39    std::copy(iter, iter + length, name.begin());
 40    iter += length;
 41    return name;
 42}
 43
 44std::string Decoder::decodeName(const PTree::Encoding &e)
 45{
 46    PTree::Encoding::iterator i = e.begin();
 47    size_t length = (const unsigned char)(*i++) - 0x80;
 48    std::string name(reinterpret_cast<const char *>(&*i), length);
 49    return name;
 50}
 51
 52void Decoder::decodeQualName(std::vector<std::string>& names)
 53{
 54    STrace trace("Decoder::decodeQualName");
 55    if (*m_iter++ != 'Q')
 56        return;
 57    int scopes = *m_iter++ - 0x80;
 58    while (scopes--)
 59    {
 60        // Only handle names here
 61        if (*m_iter >= 0x80)
 62        { // Name
 63            names.push_back(decodeName());
 64        }
 65        else if (*m_iter == 'T')
 66        {
 67            // Template :(
 68            ++m_iter;
 69            TypeIdFormatter f;
 70            std::ostringstream name;
 71            name << decodeName();
 72            char sep = '<';
 73            code_iter tend = m_iter;
 74            tend += *m_iter++ - 0x80;
 75            while (m_iter <= tend)
 76                name << sep << f.format(decodeType());
 77            name << '>';
 78            names.push_back(name.str());
 79        }
 80        else
 81        {
 82            LOG("Warning: Unknown type inside Q name: " << *m_iter);
 83            LOG("         String was: " << m_string);
 84            // FIXME: provide << operator for m_string !
 85            // 	    std::cerr << "         Decoding " << m_string << std::endl;
 86            throw ERROR("Unknown type inside Q name");
 87        }
 88    }
 89}
 90
 91void Decoder::init(const PTree::Encoding &e)
 92{
 93  m_string = code(e.begin(), e.end());
 94  m_iter = m_string.begin();
 95}
 96
 97Types::Type* Decoder::decodeType()
 98{
 99    STrace trace("Decoder::decodeType()");
100    code_iter end = m_string.end();
101    std::vector<std::string> premod, postmod;
102    std::string name;
103    Types::Type *baseType = 0;
104
105    // Loop forever until broken
106    while (m_iter != end && !name.length() && !baseType)
107    {
108        int c = *m_iter++;
109        switch (c)
110        {
111        case 'P':
112            postmod.insert(postmod.begin(), "*");
113            break;
114        case 'R':
115            postmod.insert(postmod.begin(), "&");
116            break;
117        case 'S':
118            premod.push_back("signed");
119            break;
120        case 'U':
121            premod.push_back("unsigned");
122            break;
123        case 'C':
124            premod.push_back("const");
125            break;
126        case 'V':
127            premod.push_back("volatile");
128            break;
129        case 'A':
130	{
131	  std::string array("[");
132	  while (*m_iter != '_') array.push_back(*m_iter++);
133	  array.push_back(']');
134	  ++m_iter;
135	  premod.push_back(array);
136	  break;
137	}
138        case '*':
139            {
140                ScopedName n;
141                n.push_back("*");
142                baseType = new Types::Dependent(n);
143                break;
144            }
145        case 'i':
146            name = "int";
147            break;
148        case 'v':
149            name = "void";
150            break;
151        case 'b':
152            name = "bool";
153            break;
154        case 's':
155            name = "short";
156            break;
157        case 'c':
158            name = "char";
159            break;
160        case 'w':
161            name = "wchar_t";
162            break;
163        case 'l':
164            name = "long";
165            break;
166        case 'j':
167            name = "long long";
168            break;
169        case 'f':
170            name = "float";
171            break;
172        case 'd':
173            name = "double";
174            break;
175        case 'r':
176            name = "long double";
177            break;
178        case 'e':
179            name = "...";
180            break;
181        case '?':
182            return 0;
183        case 'Q':
184            baseType = decodeQualType();
185            break;
186        case '_':
187            --m_iter;
188            return 0; // end of func params
189        case 'F':
190            baseType = decodeFuncPtr(postmod);
191            break;
192        case 'T':
193            baseType = decodeTemplate();
194            break;
195        case 'M':
196            // Pointer to member. Format is same as for named types
197            name = decodeName() + "::*";
198            break;
199        default:
200            if (c > 0x80)
201            {
202                --m_iter;
203                name = decodeName();
204                break;
205            }
206            // FIXME
207            // 	    std::cerr << "\nUnknown char decoding '"<<m_string<<"': "
208            // 		 << char(c) << " " << c << " at "
209            // 		 << (m_iter - m_string.begin()) << std::endl;
210        } // switch
211    } // while
212    if (!baseType && !name.length())
213    {
214        // FIXME
215        // 	std::cerr << "no type or name found decoding " << m_string << std::endl;
216        return 0;
217    }
218    if (!baseType)
219        baseType = m_lookup->lookupType(name);
220    if (premod.empty() && postmod.empty())
221        return baseType;
222    Types::Type* ret = new Types::Modifier(baseType, premod, postmod);
223    return ret;
224}
225
226Types::Type* Decoder::decodeQualType()
227{
228    STrace trace("Decoder::decodeQualType()");
229    // Qualified type: first is num of scopes, each a name.
230    int scopes = *m_iter++ - 0x80;
231    std::vector<std::string> names;
232    std::vector<Types::Type*> types; // if parameterized
233    while (scopes--)
234    {
235        // Only handle two things here: names and templates
236        if (*m_iter >= 0x80)
237        { // Name
238            names.push_back(decodeName());
239        }
240        else if (*m_iter == 'T')
241        {
242            // Template :(
243            ++m_iter;
244            std::string tname = decodeName();
245            code_iter tend = m_iter;
246            tend += *m_iter++ - 0x80;
247            while (m_iter <= tend)
248                types.push_back(decodeType());
249            names.push_back(tname);
250        }
251        else
252        {
253            //std::cerr << "Warning: Unknown type inside Q: " << *m_iter << std::endl;
254            // FIXME
255            //std::cerr << "         Decoding " << m_string << std::endl;
256        }
257    }
258    // Ask for qualified lookup
259    Types::Type* baseType;
260    try
261    {
262        baseType = m_lookup->lookupType(names);
263    }
264    catch (...)
265    {
266        // Ignore error, and return an Unknown instead
267        return new Types::Unknown(names);
268    }
269    // If the type is a template, then parameterize it with the params found
270    // in the T decoding
271    if (types.size())
272    {
273        Types::Declared* declared = dynamic_cast<Types::Declared*>(baseType);
274        ASG::ClassTemplate* tempclas = declared ? dynamic_cast<ASG::ClassTemplate*>(declared->declaration()) : 0;
275        Types::Template* templType = tempclas ? tempclas->template_id() : 0;
276        if (templType && types.size())
277        {
278            return new Types::Parameterized(templType, types);
279        }
280    }
281    return baseType;
282}
283
284Types::Type* Decoder::decodeFuncPtr(std::vector<std::string>& postmod)
285{
286    // Function ptr. Encoded same as function
287    Types::Type::Mods premod;
288    // Move * from postmod to funcptr's premod. This makes the output be
289    // "void (*convert)()" instead of "void (convert)()*"
290    if (postmod.size() > 0 && postmod[0] == "*")
291    {
292        premod.push_back(postmod.front());
293        postmod.erase(postmod.begin());
294    }
295    Types::Type::vector params;
296    while (1)
297    {
298        Types::Type* type = decodeType();
299        if (type)
300            params.push_back(type);
301        else
302            break;
303    }
304    ++m_iter; // skip over '_'
305    Types::Type* returnType = decodeType();
306    Types::Type* ret = new Types::FuncPtr(returnType, premod, params);
307    return ret;
308}
309
310Types::Parameterized* Decoder::decodeTemplate()
311{
312    STrace trace("Decoder::decodeTemplate()");
313
314    // Template type: Name first, then size of arg field, then arg
315    // types eg: T6vector54cell <-- 5 is len of 4cell
316    if (*m_iter == 'T')
317        ++m_iter;
318    std::string name = decodeName();
319    code_iter tend = m_iter;
320    tend += *m_iter++ - 0x80;
321    std::vector<Types::Type*> types;
322    while (m_iter <= tend)
323        types.push_back(decodeType());
324    Types::Type* type = m_lookup->lookupType(name);
325    // if type is declared and declaration is class and class is template..
326    Types::Declared* declared = dynamic_cast<Types::Declared*>(type);
327    Types::Named* templ = 0;
328    if (declared)
329    {
330      if (ASG::ClassTemplate* t_class = dynamic_cast<ASG::ClassTemplate*>(declared->declaration()))
331        templ = t_class->template_id();
332      else if (ASG::Forward* t_forward = dynamic_cast<ASG::Forward*>
333               (declared->declaration()))
334        templ = t_forward->template_id();
335    }
336    else if (Types::Dependent* d = dynamic_cast<Types::Dependent*>(type))
337      templ = d;
338//     if (templ)
339//       std::cout << "creating Parameterized for " << name << ' ' << templ->name() << std::endl;
340//     else
341//       std::cout << "no template found for " << name << ' ' << typeid(type).name() << std::endl;
342    return new Types::Parameterized(templ, types);
343}
344
345// vim: set ts=8 sts=4 sw=4 et: