Synopsis - Cross-Reference
File: /Synopsis/Parsers/Cxx/Decoder.cc1// 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: