Synopsis - Cross-Reference
File: /Synopsis/Parsers/C/ASGTranslator.cc1// 2// Copyright (C) 2005 Stefan Seefeld 3// All rights reserved. 4// Licensed to the public under the terms of the GNU LGPL (>= 2), 5// see the file COPYING for details. 6// 7 8#include "ASGTranslator.hh" 9#include <Synopsis/Trace.hh> 10#include <Synopsis/PTree/Writer.hh> // for PTree::reify 11#include <Support/Path.hh> 12 13using namespace Synopsis; 14 15namespace 16{ 17 ScopedName sname(std::string const &name) { return ScopedName(name);} 18 19class UnknownSymbol : public std::runtime_error 20{ 21public: 22 explicit UnknownSymbol(std::string const &n) 23 : std::runtime_error("Unknown symbol: " + n) {} 24}; 25 26} 27#define qname(arg) qname_(Python::Tuple(arg)) 28 29ASGTranslator::ASGTranslator(std::string const &filename, 30 std::string const &base_path, bool primary_file_only, 31 Synopsis::IR ir, bool v, bool d) 32 : asg_kit_("C"), 33 sf_kit_("C"), 34 declarations_(ir.declarations()), 35 types_(ir.types()), 36 files_(ir.files()), 37 raw_filename_(filename), 38 base_path_(base_path), 39 primary_file_only_(primary_file_only), 40 lineno_(0), 41 verbose_(v), 42 debug_(d), 43 buffer_(0), 44 declaration_(0), 45 defines_class_or_enum_(false) 46{ 47 Trace trace("ASGTranslator::ASGTranslator", Trace::TRANSLATION); 48 49 Python::Module qn = Python::Module::import("Synopsis.QualifiedName"); 50 qname_ = qn.attr("QualifiedCxxName"); 51 52 // determine canonical filenames 53 Path path = Path(raw_filename_).abs(); 54 std::string long_filename = path.str(); 55 path.strip(base_path_); 56 std::string short_filename = path.str(); 57 58 SourceFile file = files_.get(short_filename); 59 if (file) 60 file_ = file; 61 else 62 { 63 file_ = sf_kit_.create_source_file(short_filename, long_filename); 64 files_.set(short_filename, file_); 65 } 66 file_.set_primary(true); 67 68 Python::Object define = types_.attr("__setitem__"); 69 types_.set(qname(sname("char")), asg_kit_.create_builtin_type_id(sname("char"))); 70 types_.set(qname(sname("short")), asg_kit_.create_builtin_type_id(sname("short"))); 71 types_.set(qname(sname("int")), asg_kit_.create_builtin_type_id(sname("int"))); 72 types_.set(qname(sname("long")), asg_kit_.create_builtin_type_id(sname("long"))); 73 types_.set(qname(sname("unsigned")), asg_kit_.create_builtin_type_id(sname("unsigned"))); 74 types_.set(qname(sname("unsigned long")), asg_kit_.create_builtin_type_id(sname("unsigned long"))); 75 types_.set(qname(sname("float")), asg_kit_.create_builtin_type_id(sname("float"))); 76 types_.set(qname(sname("double")), asg_kit_.create_builtin_type_id(sname("double"))); 77 types_.set(qname(sname("void")), asg_kit_.create_builtin_type_id(sname("void"))); 78 types_.set(qname(sname("...")), asg_kit_.create_builtin_type_id(sname("..."))); 79 types_.set(qname(sname("long long")), asg_kit_.create_builtin_type_id(sname("long long"))); 80 types_.set(qname(sname("long double")), asg_kit_.create_builtin_type_id(sname("long double"))); 81 // some GCC extensions... 82 types_.set(qname(sname("__builtin_va_list")), asg_kit_.create_builtin_type_id(sname("__builtin_va_list"))); 83} 84 85void ASGTranslator::translate(PTree::Node *ptree, Buffer &buffer) 86{ 87 Trace trace("ASGTranslator::translate", Trace::TRANSLATION); 88 buffer_ = &buffer; 89 ptree->accept(this); 90} 91 92void ASGTranslator::visit(PTree::List *node) 93{ 94 if (node->car()) node->car()->accept(this); 95 if (node->cdr()) node->cdr()->accept(this); 96} 97 98void ASGTranslator::visit(PTree::Declarator *declarator) 99{ 100 Trace trace("ASGTranslator::visit(PTree::Declarator *)", Trace::TRANSLATION); 101 trace << declarator; 102 if (!declaration_ || !PTree::first(declarator)) return; // empty 103 104 bool visible = update_position(declarator); 105 PTree::Encoding name = declarator->encoded_name(); 106 PTree::Encoding type = declarator->encoded_type(); 107 if (type.is_function()) 108 { 109 trace << "declare function " << name << " (" << type << ')' 110 << raw_filename_ << ':' << lineno_; 111 112 ASG::TypeIdList parameter_types; 113 ASG::TypeId return_type = lookup_function_types(type, parameter_types); 114 ASG::Function::Parameters parameters; 115 PTree::Node *p = PTree::rest(declarator); 116 while (p && p->car() && *p->car() != '(') p = PTree::rest(p); 117 translate_parameters(PTree::second(p), parameter_types, parameters); 118 119 size_t length = (name.front() - 0x80); 120 ScopedName sname(std::string(name.begin() + 1, name.begin() + 1 + length)); 121 ASG::Modifiers pre; 122 ASG::Modifiers post; 123 ASG::Function function = asg_kit_.create_function(file_, lineno_, 124 "function", 125 pre, 126 return_type, 127 post, 128 sname, 129 sname.get(0)); 130 function.parameters().extend(parameters); 131 if (declaration_) add_comments(function, declaration_->get_comments()); 132 add_comments(function, declarator->get_comments()); 133 if (visible) declare(function); 134 } 135 else 136 { 137 ASG::TypeId t = lookup(type); 138 size_t length = (name.front() - 0x80); 139 ScopedName sname; 140 if (scope_.size()) sname = scope_.top().name(); 141 sname.append(std::string(name.begin() + 1, name.begin() + 1 + length)); 142 143 std::string vtype; 144 if (scope_.size()) 145 { 146 vtype = scope_.top().type(); 147 if (vtype == "class" || vtype == "struct" || vtype == "union") 148 vtype = "data member"; 149 else if (vtype == "function") 150 vtype = "local variable"; 151 } 152 else 153 vtype += "variable"; 154 ASG::Variable variable = asg_kit_.create_variable(file_, lineno_, 155 vtype, sname, t, false); 156 if (declaration_) add_comments(variable, declaration_->get_comments()); 157 add_comments(variable, declarator->get_comments()); 158 if (visible) declare(variable); 159 } 160} 161 162void ASGTranslator::visit(PTree::Declaration *declaration) 163{ 164 Trace trace("ASGTranslator::visit(PTree::Declaration *)", Trace::TRANSLATION); 165 // Cache the declaration while traversing the individual declarators; 166 // the comments are passed through. 167 declaration_ = declaration; 168 visit(static_cast<PTree::List *>(declaration)); 169 declaration_ = 0; 170} 171 172void ASGTranslator::visit(PTree::FunctionDefinition *def) 173{ 174 Trace trace("ASGTranslator::visit(PTree::FunctionDefinition *)", Trace::TRANSLATION); 175 // Cache the declaration while traversing the individual declarators; 176 // the comments are passed through. 177 declaration_ = def; 178 // Only traverse declaration-specifier-seq and declarator, but not body 179 if (PTree::first(def)) PTree::first(def)->accept(this); 180 PTree::second(def)->accept(this); 181 declaration_ = 0; 182} 183 184void ASGTranslator::visit(PTree::ClassSpec *class_spec) 185{ 186 Trace trace("ASGTranslator::visit(PTree::ClassSpec *)", Trace::TRANSLATION); 187 188 bool visible = update_position(class_spec); 189 190 size_t size = PTree::length(class_spec); 191 if (size == 2) // forward declaration ? 192 { 193 // [ class|struct <name> ] 194 PTree::Encoding t = class_spec->encoded_name(); 195 try 196 { 197 ASG::TypeId tt = lookup(t); 198 // The type is known, thus nothing to do. Move on. 199 return; 200 } 201 catch (UnknownSymbol const &e) {} 202 std::string type = PTree::reify(PTree::first(class_spec)); 203 std::string name = PTree::reify(PTree::second(class_spec)); 204 ScopedName sname(name); 205 206 ASG::Forward forward = asg_kit_.create_forward(file_, lineno_, 207 type, sname); 208 add_comments(forward, class_spec->get_comments()); 209 if (visible) 210 { 211 declare(forward); 212 declare_type(sname, forward); 213 } 214 else 215 declare_type(sname); 216 217 defines_class_or_enum_ = true; 218 return; 219 } 220 221 std::string type = PTree::reify(PTree::first(class_spec)); 222 std::string name; 223 PTree::ClassBody *body = 0; 224 225 if (size == 4) // struct definition 226 { 227 // [ class|struct <name> <inheritance> [{ body }] ] 228 229 name = PTree::reify(PTree::second(class_spec)); 230 body = static_cast<PTree::ClassBody *>(PTree::nth(class_spec, 3)); 231 } 232 else if (size == 3) // anonymous struct definition 233 { 234 // [ struct [nil nil] [{ ... }] ] 235 236 PTree::Encoding ename = class_spec->encoded_name(); 237 size_t length = (ename.front() - 0x80); 238 name = std::string(ename.begin() + 1, ename.begin() + 1 + length); 239 body = static_cast<PTree::ClassBody *>(PTree::nth(class_spec, 2)); 240 } 241 242 ScopedName sname(name); 243 ASG::Class class_ = asg_kit_.create_class(file_, lineno_, type, sname); 244 add_comments(class_, class_spec->get_comments()); 245 if (visible) 246 { 247 declare(class_); 248 declare_type(sname, class_); 249 } 250 else 251 declare_type(sname); 252 253 scope_.push(class_); 254 defines_class_or_enum_ = false; 255 body->accept(this); 256 scope_.pop(); 257 defines_class_or_enum_ = true; 258} 259 260void ASGTranslator::visit(PTree::EnumSpec *enum_spec) 261{ 262 Trace trace("ASGTranslator::visit(PTree::EnumSpec *)", Trace::TRANSLATION); 263 264 bool visible = update_position(enum_spec); 265 std::string name; 266 267 if (!PTree::second(enum_spec)) //anonymous 268 { 269 PTree::Encoding ename = enum_spec->encoded_name(); 270 size_t length = (ename.front() - 0x80); 271 name = std::string(ename.begin() + 1, ename.begin() + 1 + length); 272 } 273 else 274 name = PTree::reify(PTree::second(enum_spec)); 275 276 ASG::Enumerators enumerators; 277 PTree::Node *enode = PTree::second(PTree::third(enum_spec)); 278 279 PTree::Encoding t = enum_spec->encoded_name(); 280 try 281 { 282 ASG::TypeId tt = lookup(t); 283 // The type is known. If we find a body, this is a parse error: 284// if (enode) 285// throw std::runtime_error("redefinition of 'enum " + name + "'"); 286 287 // Else it may be an elaborate specifier, or a forward declaration. 288 // Nothing to do. Move on. 289 return; 290 } 291 catch (UnknownSymbol const &e) {} 292 293 294 295 296 297 ASG::Enumerator enumerator; 298 while (enode) 299 { 300 // quite a costly way to update the line number... 301 update_position(enode); 302 PTree::Node *penumor = PTree::first(enode); 303 if (penumor->is_atom()) 304 { 305 // Just a name 306 ScopedName sname(PTree::reify(penumor)); 307 enumerator = asg_kit_.create_enumerator(file_, lineno_, sname, ""); 308 add_comments(enumerator, static_cast<PTree::CommentedAtom *>(penumor)->get_comments()); 309 } 310 else 311 { 312 // Name = Value 313 ScopedName sname(PTree::reify(PTree::first(penumor))); 314 std::string value; 315 if (PTree::length(penumor) == 3) 316 value = PTree::reify(PTree::third(penumor)); 317 enumerator = asg_kit_.create_enumerator(file_, lineno_, sname, value); 318 add_comments(enumerator, static_cast<PTree::CommentedAtom *>(penumor)->get_comments()); 319 } 320 enumerators.append(enumerator); 321 enode = PTree::rest(enode); 322 // Skip comma 323 if (enode && enode->car() && *enode->car() == ',') enode = PTree::rest(enode); 324 } 325 // Add a dummy enumerator at the end to absorb trailing comments. 326 PTree::Node *close = PTree::third(PTree::third(enum_spec)); 327 ASG::Builtin eos = asg_kit_.create_builtin(file_, lineno_, 328 "EOS", sname(std::string("EOS"))); 329 add_comments(eos, static_cast<PTree::CommentedAtom *>(close)); 330 enumerators.append(eos); 331 332 // Create ASG.Enum object 333 ASG::Enum enum_ = asg_kit_.create_enum(file_, lineno_, name, enumerators); 334 add_comments(enum_, enum_spec); 335 336 if (visible) 337 { 338 declare(enum_); 339 declare_type(ScopedName(name), enum_); 340 } 341 else 342 declare_type(ScopedName(name)); 343 344 defines_class_or_enum_ = true; 345} 346 347void ASGTranslator::visit(PTree::Typedef *typed) 348{ 349 Trace trace("ASGTranslator::visit(PTree::Typedef *)", Trace::TRANSLATION); 350 defines_class_or_enum_ = false; 351 352 bool visible = update_position(typed); 353 354 // the second child node may be an inlined class spec, i.e. 355 // typedef struct {...} type; 356 PTree::second(typed)->accept(this); 357 for (PTree::Node *d = PTree::third(typed); d; d = PTree::tail(d, 2)) 358 { 359 if(PTree::type_of(d->car()) != Token::ntDeclarator) // is this check necessary 360 continue; 361 362 PTree::Declarator *declarator = static_cast<PTree::Declarator *>(d->car()); 363 PTree::Encoding name = declarator->encoded_name(); 364 PTree::Encoding type = declarator->encoded_type(); 365 trace << "declare type " << name << " (" << type << ')' 366 << raw_filename_ << ':' << lineno_; 367 assert(name.is_simple_name()); 368 size_t length = (name.front() - 0x80); 369 ScopedName sname(std::string(name.begin() + 1, name.begin() + 1 + length)); 370 ASG::TypeId alias = lookup(type); 371 ASG::Declaration declaration = asg_kit_.create_typedef(file_, lineno_, 372 "typedef", 373 sname, 374 alias, defines_class_or_enum_); 375 add_comments(declaration, declarator->get_comments()); 376 if (visible) 377 { 378 declare(declaration); 379 declare_type(sname, declaration); 380 } 381 else 382 declare_type(sname); 383 } 384 defines_class_or_enum_ = false; 385} 386 387void ASGTranslator::translate_parameters(PTree::Node *node, 388 ASG::TypeIdList types, 389 ASG::Function::Parameters ¶meters) 390{ 391 Trace trace("ASGTranslator::translate_parameters", Trace::TRANSLATION); 392 if (PTree::length(node) == 1 && *node->car() == "void") return; 393 while (node) 394 { 395 // A parameter has a type, possibly a name and possibly a value. 396 // Treat the value as a string, i.e. don't analyse the expression further. 397 std::string name, value; 398 ASG::Modifiers premods, postmods; 399 if (*node->car() == ',') 400 node = node->cdr(); 401 PTree::Node *parameter = PTree::first(node); 402 403 ASG::TypeId type = types.get(0); 404 types.del(0); // pop one value 405 if (PTree::length(parameter) == 3) 406 { 407 PTree::Declarator *decl = static_cast<PTree::Declarator*>(PTree::nth(parameter, 2)); 408 name = PTree::reify(decl->name()); 409 value = PTree::reify(decl->initializer()); 410 411 // Skip keywords (eg: register) which are Leaves 412 PTree::Node *atom = PTree::nth(parameter, 0); 413 if (atom) premods.append(PTree::reify(atom)); 414 } 415 ASG::Parameter p = asg_kit_.create_parameter(premods, type, postmods, 416 name, value); 417 parameters.append(p); 418 node = PTree::rest(node); 419 } 420} 421 422void ASGTranslator::add_comments(ASG::Declaration declarator, PTree::Node *c) 423{ 424 Trace trace("ASGTranslator::add_comments", Trace::TRANSLATION); 425 if (!declarator || !c) return; 426 427 Python::List comments; 428 429 // Loop over all comments in the list 430 // If the last comment is separated from the declaration by more than a single '\n', 431 // we add a None to the list. 432 bool suspect = false; 433 for (PTree::Node *next = PTree::rest(c); c && !c->is_atom(); next = PTree::rest(c)) 434 { 435 PTree::Node *first = PTree::first(c); 436 if (!first || !first->is_atom()) 437 { 438 c = next; 439 continue; 440 } 441 // Check if comment is continued, eg: consecutive C++ comments 442 while (next && PTree::first(next) && PTree::first(next)->is_atom()) 443 { 444 if (!strncmp(first->position() + first->length() - 2, "*/", 2)) 445 break; 446 if (strncmp(PTree::first(next)->position(), "//", 2)) 447 break; 448 char const *next_pos = PTree::first(next)->position(); 449 char const *start_pos = PTree::first(c)->position(); 450 char const *curr_pos = start_pos + PTree::first(c)->length(); 451 // Must only be whitespace between current comment and next 452 // and only one newline 453 int newlines = 0; 454 while (curr_pos < next_pos && strchr(" \t\r\n", *curr_pos)) 455 if (*curr_pos == '\n' && newlines > 0) 456 break; 457 else if (*curr_pos++ == '\n') 458 ++newlines; 459 if (curr_pos < next_pos) 460 break; 461 // Current comment stretches to end of next 462 int len = int(next_pos - start_pos + PTree::first(next)->length()); 463 c->set_car(first = new PTree::Atom(start_pos, len)); 464 // Skip the combined comment 465 next = PTree::rest(next); 466 } 467 suspect = false; 468 char const *pos = first->position() + first->length(); 469 while (*pos && strchr(" \t\r", *pos)) ++pos; 470 if (*pos == '\n') 471 { 472 ++pos; 473 // Found only allowed \n 474 while (*pos && strchr(" \t\r", *pos)) ++pos; 475 if (*pos == '\n' || !strncmp(pos, "/*", 2)) suspect = true; 476 } 477 Python::Object comment = PTree::reify(first); 478 comments.append(comment); 479 480// if (links_) links_->long_span(first, "file-comment"); 481 // Set first to 0 so we dont accidentally do them twice (eg: 482 // when parsing expressions) 483 c->set_car(0); 484 c = next; 485 } 486 if (suspect) comments.append(Python::Object()); 487 declarator.annotations().set("comments", comments); 488} 489 490bool ASGTranslator::update_position(PTree::Node *node) 491{ 492 Trace trace("ASGTranslator::update_position", Trace::TRANSLATION); 493 494 std::string filename; 495 lineno_ = buffer_->origin(node->begin(), filename); 496 497 if (filename != raw_filename_) 498 { 499 if (primary_file_only_) 500 // raw_filename_ remains the primary file's name 501 // and all declarations from elsewhere are ignored 502 return false; 503 raw_filename_ = filename; 504 505 // determine canonical filenames 506 Path path = Path(filename).abs(); 507 std::string long_filename = path.str(); 508 path.strip(base_path_); 509 std::string short_filename = path.str(); 510 511 SourceFile file = files_.get(short_filename); 512 if (file) 513 file_ = file; 514 else 515 { 516 file_ = sf_kit_.create_source_file(short_filename, long_filename); 517 files_.set(short_filename, file_); 518 } 519 } 520 return true; 521} 522 523ASG::TypeId ASGTranslator::lookup(PTree::Encoding const &name) 524{ 525 Trace trace("ASGTranslator::lookup", Trace::SYMBOLLOOKUP); 526 trace << name; 527 name_ = name; 528 ASG::TypeId type; 529 decode_type(name.begin(), type); 530 return type; 531} 532 533ASG::TypeId ASGTranslator::lookup_function_types(PTree::Encoding const &name, 534 ASG::TypeIdList ¶meters) 535{ 536 Trace trace("ASGTranslator::lookup_function_types", Trace::SYMBOLLOOKUP); 537 trace << name; 538 name_ = name; 539 540 PTree::Encoding::iterator i = name.begin(); 541 assert(*i == 'F'); 542 ++i; 543 while (true) 544 { 545 ASG::TypeId parameter; 546 i = decode_type(i, parameter); 547 if (parameter) 548 parameters.append(parameter); 549 else 550 break; 551 } 552 ++i; // skip over '_' 553 ASG::TypeId return_type; 554 i = decode_type(i, return_type); 555 return return_type; 556} 557 558void ASGTranslator::declare(ASG::Declaration declaration) 559{ 560 if (scope_.size()) 561 scope_.top().declarations().append(declaration); 562 else 563 declarations_.append(declaration); 564 file_.declarations().append(declaration); 565} 566 567ASG::TypeId ASGTranslator::declare_type(ScopedName name, 568 ASG::Declaration declaration) 569{ 570 Trace trace("ASGTranslator::declare_type", Trace::SYMBOLLOOKUP); 571 trace << name; 572 ASG::TypeId type = asg_kit_.create_declared_type_id(name, declaration); 573 types_.set(qname(name), type); 574 return type; 575} 576 577ASG::TypeId ASGTranslator::declare_type(ScopedName name) 578{ 579 Trace trace("ASGTranslator::declare_type(unknown)", Trace::SYMBOLLOOKUP); 580 trace << name; 581 ASG::TypeId type = asg_kit_.create_unknown_type_id(name); 582 types_.set(qname(name), type); 583 return type; 584} 585 586// This is almost a verbatim copy of the Decoder::decode 587// methods from Synopsis/Parsers/Cxx/syn/decoder.cc 588// with some minor modifications to disable the C++ specific things. 589// FIXME: this ought to be part of SymbolLookup::Type. 590PTree::Encoding::iterator ASGTranslator::decode_name(PTree::Encoding::iterator i, 591 std::string &name) 592{ 593 Trace trace("ASGTranslator::decode_name", Trace::PARSING); 594 size_t length = *i++ - 0x80; 595 name = std::string(length, '\0'); 596 std::copy(i, i + length, name.begin()); 597 i += length; 598 return i; 599} 600 601PTree::Encoding::iterator ASGTranslator::decode_type(PTree::Encoding::iterator i, 602 ASG::TypeId &type) 603{ 604 Trace trace("ASGTranslator::decode_type", Trace::PARSING); 605 ASG::Modifiers premod, postmod; 606 std::string name; 607 ASG::TypeId base; 608 609 // Loop forever until broken 610 while (i != name_.end() && !name.length() && !base) 611 { 612 int c = *i++; 613 switch (c) 614 { 615 case 'P': 616 postmod.insert(0, "*"); 617 break; 618// case 'R': 619// postmod.insert(0, "&"); 620// break; 621 case 'S': 622 premod.append("signed"); 623 break; 624 case 'U': 625 premod.append("unsigned"); 626 break; 627 case 'C': 628 premod.append("const"); 629 break; 630 case 'V': 631 premod.append("volatile"); 632 break; 633 case 'A': 634 { 635 std::string array("["); 636 while (*i != '_') array.push_back(*i++); 637 array.push_back(']'); 638 ++i; 639 postmod.append(array); 640 break; 641 } 642// case '*': 643// { 644// ScopedName n; 645// n.push_back("*"); 646// base = new Types::Dependent(n); 647// break; 648// } 649 case 'i': 650 name = "int"; 651 break; 652 case 'v': 653 name = "void"; 654 break; 655// case 'b': 656// name = "bool"; 657// break; 658 case 's': 659 name = "short"; 660 break; 661 case 'c': 662 name = "char"; 663 break; 664// case 'w': 665// name = "wchar_t"; 666// break; 667 case 'l': 668 name = "long"; 669 break; 670 case 'j': 671 name = "long long"; 672 break; 673 case 'f': 674 name = "float"; 675 break; 676 case 'd': 677 name = "double"; 678 break; 679 case 'r': 680 name = "long double"; 681 break; 682 case 'e': 683 name = "..."; 684 break; 685 case '?': 686 name = "int"; // in C, no return type spec defaults to int 687 break; 688// case 'Q': 689// base = decodeQualType(); 690// break; 691 case '_': 692 --i; 693 type = ASG::TypeId(); 694 return i; // end of func params 695 case 'F': 696 i = decode_func_ptr(i, base, postmod); 697 break; 698// case 'T': 699// base = decodeTemplate(); 700// break; 701// case 'M': 702// // Pointer to member. Format is same as for named types 703// name = decodeName() + "::*"; 704// break; 705 default: 706 if (c > 0x80) 707 { 708 --i; 709 i = decode_name(i, name); 710 break; 711 } 712 // FIXME 713 // std::cerr << "\nUnknown char decoding '"<<m_string<<"': " 714 // << char(c) << " " << c << " at " 715 // << (m_iter - m_string.begin()) << std::endl; 716 } // switch 717 } // while 718 if (!base && !name.length()) 719 { 720 // FIXME 721 // std::cerr << "no type or name found decoding " << m_string << std::endl; 722 type = ASG::TypeId(); 723 return i; 724 } 725 if (!base) 726 { 727 base = types_.get(qname(sname(name))); 728 if (!base) throw UnknownSymbol(name); 729 } 730 if (premod.empty() && postmod.empty()) 731 type = base; 732 else 733 type = asg_kit_.create_modifier_type_id(base, premod, postmod); 734 735 return i; 736} 737 738PTree::Encoding::iterator ASGTranslator::decode_func_ptr(PTree::Encoding::iterator i, 739 ASG::TypeId &type, 740 ASG::Modifiers &postmod) 741{ 742 Trace trace("ASGTranslator::decode_func_ptr", Trace::PARSING); 743 // Function ptr. Encoded same as function 744 ASG::Modifiers premod; 745 // Move * from postmod to funcptr's premod. This makes the output be 746 // "void (*convert)()" instead of "void (convert)()*" 747 if (postmod.size() > 0 && postmod.get(0) == "*") 748 { 749 premod.append(postmod.get(0)); 750 postmod.erase(postmod.begin()); 751 } 752 ASG::TypeIdList parameters; 753 while (true) 754 { 755 ASG::TypeId parameter; 756 i = decode_type(i, parameter); 757 if (parameter) 758 parameters.append(parameter); 759 else 760 break; 761 } 762 ++i; // skip over '_' 763 i = decode_type(i, type); 764 type = asg_kit_.create_function_type_id(type, premod, parameters); 765 return i; 766}