|
|
1.1 ! root 1: /* Demangler for GNU C++ ! 2: Copyright 1989, 1991 Free Software Foundation, Inc. ! 3: Written by James Clark ([email protected]) ! 4: Rewritten by Fred Fish ([email protected]) for ARM and Lucid demangling ! 5: ! 6: This file is part of the libiberty library. ! 7: Libiberty is free software; you can redistribute it and/or ! 8: modify it under the terms of the GNU Library General Public ! 9: License as published by the Free Software Foundation; either ! 10: version 2 of the License, or (at your option) any later version. ! 11: ! 12: Libiberty is distributed in the hope that it will be useful, ! 13: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 15: Library General Public License for more details. ! 16: ! 17: You should have received a copy of the GNU Library General Public ! 18: License along with libiberty; see the file COPYING.LIB. If ! 19: not, write to the Free Software Foundation, Inc., 675 Mass Ave, ! 20: Cambridge, MA 02139, USA. */ ! 21: ! 22: /* This is for g++ 1.95.03 (November 13 version). */ ! 23: ! 24: /* This file exports two functions; cplus_mangle_opname and cplus_demangle. ! 25: ! 26: This file imports xmalloc and xrealloc, which are like malloc and ! 27: realloc except that they generate a fatal error if there is no ! 28: available memory. */ ! 29: ! 30: #ifdef NeXT ! 31: #define xmalloc(l) malloc(l) ! 32: #define xrealloc(p, l) realloc(p, l) ! 33: #endif /* NeXT */ ! 34: ! 35: #include <demangle.h> ! 36: #undef CURRENT_DEMANGLING_STYLE ! 37: #define CURRENT_DEMANGLING_STYLE work->options ! 38: #include <ctype.h> ! 39: #include <string.h> ! 40: #include <stdio.h> ! 41: ! 42: /* In order to allow a single demangler executable to demangle strings ! 43: using various common values of CPLUS_MARKER, as well as any specific ! 44: one set at compile time, we maintain a string containing all the ! 45: commonly used ones, and check to see if the marker we are looking for ! 46: is in that string. CPLUS_MARKER is usually '$' on systems where the ! 47: assembler can deal with that. Where the assembler can't, it's usually ! 48: '.' (but on many systems '.' is used for other things). We put the ! 49: current defined CPLUS_MARKER first (which defaults to '$'), followed ! 50: by the next most common value, followed by an explicit '$' in case ! 51: the value of CPLUS_MARKER is not '$'. ! 52: ! 53: We could avoid this if we could just get g++ to tell us what the actual ! 54: cplus marker character is as part of the debug information, perhaps by ! 55: ensuring that it is the character that terminates the gcc<n>_compiled ! 56: marker symbol (FIXME). */ ! 57: ! 58: #if !defined (CPLUS_MARKER) ! 59: #define CPLUS_MARKER '$' ! 60: #endif ! 61: ! 62: enum demangling_styles current_demangling_style = gnu_demangling; ! 63: ! 64: static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; ! 65: ! 66: void ! 67: set_cplus_marker_for_demangling (ch) ! 68: int ch; ! 69: { ! 70: cplus_markers[0] = ch; ! 71: } ! 72: ! 73: /* Stuff that is shared between sub-routines. ! 74: * Using a shared structure allows cplus_demangle to be reentrant. */ ! 75: ! 76: struct work_stuff ! 77: { ! 78: int options; ! 79: char **typevec; ! 80: int ntypes; ! 81: int typevec_size; ! 82: int constructor; ! 83: int destructor; ! 84: int static_type; /* A static member function */ ! 85: int const_type; /* A const member function */ ! 86: }; ! 87: ! 88: #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) ! 89: #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) ! 90: ! 91: static CONST struct optable ! 92: { ! 93: CONST char *in; ! 94: CONST char *out; ! 95: int flags; ! 96: } optable[] = { ! 97: "nw", " new", DMGL_ANSI, /* new (1.92, ansi) */ ! 98: "dl", " delete", DMGL_ANSI, /* new (1.92, ansi) */ ! 99: "new", " new", 0, /* old (1.91, and 1.x) */ ! 100: "delete", " delete", 0, /* old (1.91, and 1.x) */ ! 101: "as", "=", DMGL_ANSI, /* ansi */ ! 102: "ne", "!=", DMGL_ANSI, /* old, ansi */ ! 103: "eq", "==", DMGL_ANSI, /* old, ansi */ ! 104: "ge", ">=", DMGL_ANSI, /* old, ansi */ ! 105: "gt", ">", DMGL_ANSI, /* old, ansi */ ! 106: "le", "<=", DMGL_ANSI, /* old, ansi */ ! 107: "lt", "<", DMGL_ANSI, /* old, ansi */ ! 108: "plus", "+", 0, /* old */ ! 109: "pl", "+", DMGL_ANSI, /* ansi */ ! 110: "apl", "+=", DMGL_ANSI, /* ansi */ ! 111: "minus", "-", 0, /* old */ ! 112: "mi", "-", DMGL_ANSI, /* ansi */ ! 113: "ami", "-=", DMGL_ANSI, /* ansi */ ! 114: "mult", "*", 0, /* old */ ! 115: "ml", "*", DMGL_ANSI, /* ansi */ ! 116: "amu", "*=", DMGL_ANSI, /* ansi (ARM/Lucid) */ ! 117: "aml", "*=", DMGL_ANSI, /* ansi (GNU/g++) */ ! 118: "convert", "+", 0, /* old (unary +) */ ! 119: "negate", "-", 0, /* old (unary -) */ ! 120: "trunc_mod", "%", 0, /* old */ ! 121: "md", "%", DMGL_ANSI, /* ansi */ ! 122: "amd", "%=", DMGL_ANSI, /* ansi */ ! 123: "trunc_div", "/", 0, /* old */ ! 124: "dv", "/", DMGL_ANSI, /* ansi */ ! 125: "adv", "/=", DMGL_ANSI, /* ansi */ ! 126: "truth_andif", "&&", 0, /* old */ ! 127: "aa", "&&", DMGL_ANSI, /* ansi */ ! 128: "truth_orif", "||", 0, /* old */ ! 129: "oo", "||", DMGL_ANSI, /* ansi */ ! 130: "truth_not", "!", 0, /* old */ ! 131: "nt", "!", DMGL_ANSI, /* ansi */ ! 132: "postincrement","++", 0, /* old */ ! 133: "pp", "++", DMGL_ANSI, /* ansi */ ! 134: "postdecrement","--", 0, /* old */ ! 135: "mm", "--", DMGL_ANSI, /* ansi */ ! 136: "bit_ior", "|", 0, /* old */ ! 137: "or", "|", DMGL_ANSI, /* ansi */ ! 138: "aor", "|=", DMGL_ANSI, /* ansi */ ! 139: "bit_xor", "^", 0, /* old */ ! 140: "er", "^", DMGL_ANSI, /* ansi */ ! 141: "aer", "^=", DMGL_ANSI, /* ansi */ ! 142: "bit_and", "&", 0, /* old */ ! 143: "ad", "&", DMGL_ANSI, /* ansi */ ! 144: "aad", "&=", DMGL_ANSI, /* ansi */ ! 145: "bit_not", "~", 0, /* old */ ! 146: "co", "~", DMGL_ANSI, /* ansi */ ! 147: "call", "()", 0, /* old */ ! 148: "cl", "()", DMGL_ANSI, /* ansi */ ! 149: "alshift", "<<", 0, /* old */ ! 150: "ls", "<<", DMGL_ANSI, /* ansi */ ! 151: "als", "<<=", DMGL_ANSI, /* ansi */ ! 152: "arshift", ">>", 0, /* old */ ! 153: "rs", ">>", DMGL_ANSI, /* ansi */ ! 154: "ars", ">>=", DMGL_ANSI, /* ansi */ ! 155: "component", "->", 0, /* old */ ! 156: "pt", "->", DMGL_ANSI, /* ansi; Lucid C++ form */ ! 157: "rf", "->", DMGL_ANSI, /* ansi; ARM/GNU form */ ! 158: "indirect", "*", 0, /* old */ ! 159: "method_call", "->()", 0, /* old */ ! 160: "addr", "&", 0, /* old (unary &) */ ! 161: "array", "[]", 0, /* old */ ! 162: "vc", "[]", DMGL_ANSI, /* ansi */ ! 163: "compound", ", ", 0, /* old */ ! 164: "cm", ", ", DMGL_ANSI, /* ansi */ ! 165: "cond", "?:", 0, /* old */ ! 166: "cn", "?:", DMGL_ANSI, /* psuedo-ansi */ ! 167: "max", ">?", 0, /* old */ ! 168: "mx", ">?", DMGL_ANSI, /* psuedo-ansi */ ! 169: "min", "<?", 0, /* old */ ! 170: "mn", "<?", DMGL_ANSI, /* psuedo-ansi */ ! 171: "nop", "", 0, /* old (for operator=) */ ! 172: "rm", "->*", DMGL_ANSI, /* ansi */ ! 173: }; ! 174: ! 175: ! 176: typedef struct string /* Beware: these aren't required to be */ ! 177: { /* '\0' terminated. */ ! 178: char *b; /* pointer to start of string */ ! 179: char *p; /* pointer after last character */ ! 180: char *e; /* pointer after end of allocated space */ ! 181: } string; ! 182: ! 183: #define STRING_EMPTY(str) ((str) -> b == (str) -> p) ! 184: #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ ! 185: string_prepend(str, " ");} ! 186: #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ ! 187: string_append(str, " ");} ! 188: ! 189: #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/cfront virtual table prefix */ ! 190: #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ ! 191: ! 192: /* Prototypes for local functions */ ! 193: ! 194: static char * ! 195: mop_up PARAMS ((struct work_stuff *, string *, int)); ! 196: ! 197: #if 0 ! 198: static int ! 199: demangle_method_args PARAMS ((struct work_stuff *work, CONST char **, string *)); ! 200: #endif ! 201: ! 202: static int ! 203: demangle_template PARAMS ((struct work_stuff *work, CONST char **, string *)); ! 204: ! 205: static int ! 206: demangle_qualified PARAMS ((struct work_stuff *, CONST char **, string *, ! 207: int)); ! 208: ! 209: static int ! 210: demangle_class PARAMS ((struct work_stuff *, CONST char **, string *)); ! 211: ! 212: static int ! 213: demangle_fund_type PARAMS ((struct work_stuff *, CONST char **, string *)); ! 214: ! 215: static int ! 216: demangle_signature PARAMS ((struct work_stuff *, CONST char **, string *)); ! 217: ! 218: static int ! 219: demangle_prefix PARAMS ((struct work_stuff *, CONST char **, string *)); ! 220: ! 221: static int ! 222: gnu_special PARAMS ((struct work_stuff *, CONST char **, string *)); ! 223: ! 224: static int ! 225: cfront_special PARAMS ((struct work_stuff *, CONST char **, string *)); ! 226: ! 227: static void ! 228: string_need PARAMS ((string *, int)); ! 229: ! 230: static void ! 231: string_delete PARAMS ((string *)); ! 232: ! 233: static void ! 234: string_init PARAMS ((string *)); ! 235: ! 236: static void ! 237: string_clear PARAMS ((string *)); ! 238: ! 239: #if 0 ! 240: static int ! 241: string_empty PARAMS ((string *)); ! 242: #endif ! 243: ! 244: static void ! 245: string_append PARAMS ((string *, CONST char *)); ! 246: ! 247: static void ! 248: string_appends PARAMS ((string *, string *)); ! 249: ! 250: static void ! 251: string_appendn PARAMS ((string *, CONST char *, int)); ! 252: ! 253: static void ! 254: string_prepend PARAMS ((string *, CONST char *)); ! 255: ! 256: static void ! 257: string_prependn PARAMS ((string *, CONST char *, int)); ! 258: ! 259: static int ! 260: get_count PARAMS ((CONST char **, int *)); ! 261: ! 262: static int ! 263: consume_count PARAMS ((CONST char **)); ! 264: ! 265: static int ! 266: demangle_args PARAMS ((struct work_stuff *, CONST char **, string *)); ! 267: ! 268: static int ! 269: do_type PARAMS ((struct work_stuff *, CONST char **, string *)); ! 270: ! 271: static int ! 272: do_arg PARAMS ((struct work_stuff *, CONST char **, string *)); ! 273: ! 274: static void ! 275: demangle_function_name PARAMS ((struct work_stuff *, CONST char **, string *, ! 276: CONST char *)); ! 277: ! 278: static void ! 279: remember_type PARAMS ((struct work_stuff *, CONST char *, int)); ! 280: ! 281: static void ! 282: forget_types PARAMS ((struct work_stuff *)); ! 283: ! 284: static void ! 285: string_prepends PARAMS ((string *, string *)); ! 286: ! 287: /* Translate count to integer, consuming tokens in the process. ! 288: Conversion terminates on the first non-digit character. */ ! 289: ! 290: static int ! 291: consume_count (type) ! 292: CONST char **type; ! 293: { ! 294: int count = 0; ! 295: ! 296: do ! 297: { ! 298: count *= 10; ! 299: count += **type - '0'; ! 300: (*type)++; ! 301: } while (isdigit (**type)); ! 302: return (count); ! 303: } ! 304: ! 305: /* Takes operator name as e.g. "++" and returns mangled ! 306: operator name (e.g. "postincrement_expr"), or NULL if not found. ! 307: ! 308: If OPTIONS & DMGL_ANSI == 1, return the ANSI name; ! 309: if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ ! 310: ! 311: char * ! 312: cplus_mangle_opname (opname, options) ! 313: char *opname; ! 314: int options; ! 315: { ! 316: int i; ! 317: int len; ! 318: ! 319: len = strlen (opname); ! 320: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 321: { ! 322: if (strlen (optable[i].out) == len ! 323: && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) ! 324: && memcmp (optable[i].out, opname, len) == 0) ! 325: return ((char *)optable[i].in); ! 326: } ! 327: return (0); ! 328: } ! 329: ! 330: /* check to see whether MANGLED can match TEXT in the first TEXT_LEN ! 331: characters. */ ! 332: ! 333: int cplus_match (mangled, text, text_len) ! 334: CONST char *mangled; ! 335: char *text; ! 336: int text_len; ! 337: { ! 338: if (strncmp (mangled, text, text_len) != 0) { ! 339: return(0); /* cannot match either */ ! 340: } else { ! 341: return(1); /* matches mangled, may match demangled */ ! 342: } ! 343: } ! 344: ! 345: /* char *cplus_demangle (const char *name, int options) ! 346: ! 347: If NAME is a mangled function name produced by GNU C++, then ! 348: a pointer to a malloced string giving a C++ representation ! 349: of the name will be returned; otherwise NULL will be returned. ! 350: It is the caller's responsibility to free the string which ! 351: is returned. ! 352: ! 353: The OPTIONS arg may contain one or more of the following bits: ! 354: ! 355: DMGL_ANSI ANSI qualifiers such as `const' and `void' are ! 356: included. ! 357: DMGL_PARAMS Function parameters are included. ! 358: ! 359: For example, ! 360: ! 361: cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" ! 362: cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" ! 363: cplus_demangle ("foo__1Ai", 0) => "A::foo" ! 364: ! 365: cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" ! 366: cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" ! 367: cplus_demangle ("foo__1Afe", 0) => "A::foo" ! 368: ! 369: Note that any leading underscores, or other such characters prepended by ! 370: the compilation system, are presumed to have already been stripped from ! 371: TYPE. */ ! 372: ! 373: char * ! 374: cplus_demangle (mangled, options) ! 375: CONST char *mangled; ! 376: int options; ! 377: { ! 378: string decl; ! 379: int success = 0; ! 380: struct work_stuff work[1]; ! 381: char *demangled = NULL; ! 382: ! 383: if ((mangled != NULL) && (*mangled != '\0')) ! 384: { ! 385: memset ((char *) work, 0, sizeof (work)); ! 386: work -> options = options; ! 387: if ((work->options & DMGL_STYLE_MASK) == 0) ! 388: work->options |= (int)current_demangling_style & DMGL_STYLE_MASK; ! 389: ! 390: string_init (&decl); ! 391: ! 392: /* First check to see if gnu style demangling is active and if the ! 393: string to be demangled contains a CPLUS_MARKER. If so, attempt to ! 394: recognize one of the gnu special forms rather than looking for a ! 395: standard prefix. In particular, don't worry about whether there ! 396: is a "__" string in the mangled string. Consider "_$_5__foo" for ! 397: example. */ ! 398: ! 399: if ((AUTO_DEMANGLING || GNU_DEMANGLING)) ! 400: { ! 401: success = gnu_special (work, &mangled, &decl); ! 402: } ! 403: if (!success) ! 404: { ! 405: success = demangle_prefix (work, &mangled, &decl); ! 406: } ! 407: if (success && (*mangled != '\0')) ! 408: { ! 409: success = demangle_signature (work, &mangled, &decl); ! 410: } ! 411: demangled = mop_up (work, &decl, success); ! 412: } ! 413: return (demangled); ! 414: } ! 415: ! 416: static char * ! 417: mop_up (work, declp, success) ! 418: struct work_stuff *work; ! 419: string *declp; ! 420: int success; ! 421: { ! 422: int i; ! 423: char *demangled = NULL; ! 424: ! 425: /* Discard the remembered types, if any. */ ! 426: ! 427: forget_types (work); ! 428: if (work -> typevec != NULL) ! 429: { ! 430: free ((char *) work -> typevec); ! 431: } ! 432: ! 433: /* If demangling was successful, ensure that the demangled string is null ! 434: terminated and return it. Otherwise, free the demangling decl. */ ! 435: ! 436: if (!success) ! 437: { ! 438: string_delete (declp); ! 439: } ! 440: else ! 441: { ! 442: string_appendn (declp, "", 1); ! 443: demangled = declp -> b; ! 444: } ! 445: return (demangled); ! 446: } ! 447: ! 448: /* ! 449: ! 450: LOCAL FUNCTION ! 451: ! 452: demangle_signature -- demangle the signature part of a mangled name ! 453: ! 454: SYNOPSIS ! 455: ! 456: static int ! 457: demangle_signature (struct work_stuff *work, const char **mangled, ! 458: string *declp); ! 459: ! 460: DESCRIPTION ! 461: ! 462: Consume and demangle the signature portion of the mangled name. ! 463: ! 464: DECLP is the string where demangled output is being built. At ! 465: entry it contains the demangled root name from the mangled name ! 466: prefix. I.E. either a demangled operator name or the root function ! 467: name. In some special cases, it may contain nothing. ! 468: ! 469: *MANGLED points to the current unconsumed location in the mangled ! 470: name. As tokens are consumed and demangling is performed, the ! 471: pointer is updated to continuously point at the next token to ! 472: be consumed. ! 473: ! 474: Demangling GNU style mangled names is nasty because there is no ! 475: explicit token that marks the start of the outermost function ! 476: argument list. ! 477: */ ! 478: ! 479: static int ! 480: demangle_signature (work, mangled, declp) ! 481: struct work_stuff *work; ! 482: CONST char **mangled; ! 483: string *declp; ! 484: { ! 485: int success = 1; ! 486: int func_done = 0; ! 487: int expect_func = 0; ! 488: CONST char *oldmangled; ! 489: ! 490: while (success && (**mangled != '\0')) ! 491: { ! 492: switch (**mangled) ! 493: { ! 494: case 'Q': ! 495: oldmangled = *mangled; ! 496: success = demangle_qualified (work, mangled, declp, 1); ! 497: if (success) ! 498: { ! 499: remember_type (work, oldmangled, *mangled - oldmangled); ! 500: } ! 501: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 502: { ! 503: expect_func = 1; ! 504: } ! 505: break; ! 506: ! 507: case 'S': ! 508: /* Static member function */ ! 509: (*mangled)++; ! 510: work -> static_type = 1; ! 511: break; ! 512: ! 513: case 'C': ! 514: /* a const member function */ ! 515: (*mangled)++; ! 516: work -> const_type = 1; ! 517: break; ! 518: ! 519: case '0': case '1': case '2': case '3': case '4': ! 520: case '5': case '6': case '7': case '8': case '9': ! 521: oldmangled = *mangled; ! 522: success = demangle_class (work, mangled, declp); ! 523: if (success) ! 524: { ! 525: remember_type (work, oldmangled, *mangled - oldmangled); ! 526: } ! 527: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 528: { ! 529: expect_func = 1; ! 530: } ! 531: break; ! 532: ! 533: case 'F': ! 534: /* Function */ ! 535: /* ARM style demangling includes a specific 'F' character after ! 536: the class name. For GNU style, it is just implied. So we can ! 537: safely just consume any 'F' at this point and be compatible ! 538: with either style. */ ! 539: ! 540: func_done = 1; ! 541: (*mangled)++; ! 542: ! 543: /* For lucid/cfront style we have to forget any types we might ! 544: have remembered up to this point, since they were not argument ! 545: types. GNU style considers all types seen as available for ! 546: back references. See comment in demangle_args() */ ! 547: ! 548: if (LUCID_DEMANGLING || CFRONT_DEMANGLING) ! 549: { ! 550: forget_types (work); ! 551: } ! 552: success = demangle_args (work, mangled, declp); ! 553: break; ! 554: ! 555: case 't': ! 556: /* Template */ ! 557: success = demangle_template (work, mangled, declp); ! 558: break; ! 559: ! 560: case '_': ! 561: /* At the outermost level, we cannot have a return type specified, ! 562: so if we run into another '_' at this point we are dealing with ! 563: a mangled name that is either bogus, or has been mangled by ! 564: some algorithm we don't know how to deal with. So just ! 565: reject the entire demangling. */ ! 566: success = 0; ! 567: break; ! 568: ! 569: default: ! 570: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 571: { ! 572: /* Assume we have stumbled onto the first outermost function ! 573: argument token, and start processing args. */ ! 574: func_done = 1; ! 575: success = demangle_args (work, mangled, declp); ! 576: } ! 577: else ! 578: { ! 579: /* Non-GNU demanglers use a specific token to mark the start ! 580: of the outermost function argument tokens. Typically 'F', ! 581: for ARM-demangling, for example. So if we find something ! 582: we are not prepared for, it must be an error. */ ! 583: success = 0; ! 584: } ! 585: break; ! 586: } ! 587: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 588: { ! 589: if (success && expect_func) ! 590: { ! 591: func_done = 1; ! 592: success = demangle_args (work, mangled, declp); ! 593: } ! 594: } ! 595: } ! 596: if (success && !func_done) ! 597: { ! 598: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 599: { ! 600: /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and ! 601: bar__3fooi is 'foo::bar(int)'. We get here when we find the ! 602: first case, and need to ensure that the '(void)' gets added to ! 603: the current declp. Note that with ARM, the first case ! 604: represents the name of a static data member 'foo::bar', ! 605: which is in the current declp, so we leave it alone. */ ! 606: success = demangle_args (work, mangled, declp); ! 607: } ! 608: } ! 609: if (success && work -> static_type && PRINT_ARG_TYPES) ! 610: { ! 611: string_append (declp, " static"); ! 612: } ! 613: if (success && work -> const_type && PRINT_ARG_TYPES) ! 614: { ! 615: string_append (declp, " const"); ! 616: } ! 617: return (success); ! 618: } ! 619: ! 620: #if 0 ! 621: ! 622: static int ! 623: demangle_method_args (work, mangled, declp) ! 624: struct work_stuff *work; ! 625: CONST char **mangled; ! 626: string *declp; ! 627: { ! 628: int success = 0; ! 629: ! 630: if (work -> static_type) ! 631: { ! 632: string_append (declp, *mangled + 1); ! 633: *mangled += strlen (*mangled); ! 634: success = 1; ! 635: } ! 636: else ! 637: { ! 638: success = demangle_args (work, mangled, declp); ! 639: } ! 640: return (success); ! 641: } ! 642: ! 643: #endif ! 644: ! 645: static int ! 646: demangle_template (work, mangled, declp) ! 647: struct work_stuff *work; ! 648: CONST char **mangled; ! 649: string *declp; ! 650: { ! 651: int i; ! 652: string tname; ! 653: string trawname; ! 654: int is_pointer; ! 655: int is_real; ! 656: int is_integral; ! 657: int r; ! 658: int need_comma = 0; ! 659: int success = 0; ! 660: int done; ! 661: CONST char *old_p; ! 662: int symbol_len; ! 663: string temp; ! 664: ! 665: (*mangled)++; ! 666: string_init (&tname); ! 667: string_init (&trawname); ! 668: /* get template name */ ! 669: if (!get_count (mangled, &r)) ! 670: { ! 671: return (0); ! 672: } ! 673: string_appendn (&tname, *mangled, r); ! 674: string_appendn (&trawname, *mangled, r); ! 675: #ifndef NeXT ! 676: string_appendn (&trawname, "", 1); ! 677: #endif /* NeXT */ ! 678: *mangled += r; ! 679: string_append (&tname, "<"); ! 680: /* get size of template parameter list */ ! 681: if (!get_count (mangled, &r)) ! 682: { ! 683: return (0); ! 684: } ! 685: for (i = 0; i < r; i++) ! 686: { ! 687: if (need_comma) ! 688: { ! 689: string_append (&tname, ", "); ! 690: } ! 691: /* Z for type parameters */ ! 692: if (**mangled == 'Z') ! 693: { ! 694: (*mangled)++; ! 695: success = do_type (work, mangled, &temp); ! 696: #ifndef NeXT ! 697: string_appendn (&temp, "", 1); ! 698: #endif /* !NeXT */ ! 699: if (success) ! 700: { ! 701: #ifdef NeXT ! 702: string_appends (&tname, &temp); ! 703: #else ! 704: string_append (&tname, temp.b); ! 705: #endif /* NeXT */ ! 706: } ! 707: string_delete(&temp); ! 708: if (!success) ! 709: { ! 710: break; ! 711: } ! 712: } ! 713: else ! 714: { ! 715: /* otherwise, value parameter */ ! 716: old_p = *mangled; ! 717: is_pointer = 0; ! 718: is_real = 0; ! 719: is_integral = 0; ! 720: done = 0; ! 721: success = do_type (work, mangled, &temp); ! 722: #ifndef NeXT ! 723: string_appendn (&temp, "", 1); ! 724: #endif /* !NeXT */ ! 725: if (success) ! 726: { ! 727: #ifdef NeXT ! 728: string_appends (&tname, &temp); ! 729: #else ! 730: string_append (&tname, temp.b); ! 731: #endif /* NeXT */ ! 732: } ! 733: string_delete(&temp); ! 734: if (!success) ! 735: { ! 736: break; ! 737: } ! 738: string_append (&tname, "="); ! 739: while (*old_p && !done) ! 740: { ! 741: switch (*old_p) ! 742: { ! 743: case 'P': ! 744: case 'R': ! 745: done = is_pointer = 1; ! 746: break; ! 747: case 'C': /* const */ ! 748: case 'S': /* explicitly signed [char] */ ! 749: case 'U': /* unsigned */ ! 750: case 'V': /* volatile */ ! 751: case 'F': /* function */ ! 752: case 'M': /* member function */ ! 753: case 'O': /* ??? */ ! 754: old_p++; ! 755: continue; ! 756: case 'Q': /* repetition of following */ ! 757: case 'T': /* remembered type */ ! 758: abort (); ! 759: break; ! 760: case 'v': /* void */ ! 761: abort (); ! 762: break; ! 763: case 'x': /* long long */ ! 764: case 'l': /* long */ ! 765: case 'i': /* int */ ! 766: case 's': /* short */ ! 767: case 'c': /* char */ ! 768: done = is_integral = 1; ! 769: break; ! 770: case 'r': /* long double */ ! 771: case 'd': /* double */ ! 772: case 'f': /* float */ ! 773: done = is_real = 1; ! 774: break; ! 775: default: ! 776: abort (); ! 777: } ! 778: } ! 779: if (is_integral) ! 780: { ! 781: if (**mangled == 'm') ! 782: { ! 783: string_appendn (&tname, "-", 1); ! 784: (*mangled)++; ! 785: } ! 786: while (isdigit (**mangled)) ! 787: { ! 788: string_appendn (&tname, *mangled, 1); ! 789: (*mangled)++; ! 790: } ! 791: } ! 792: else if (is_real) ! 793: { ! 794: if (**mangled == 'm') ! 795: { ! 796: string_appendn (&tname, "-", 1); ! 797: (*mangled)++; ! 798: } ! 799: while (isdigit (**mangled)) ! 800: { ! 801: string_appendn (&tname, *mangled, 1); ! 802: (*mangled)++; ! 803: } ! 804: if (**mangled == '.') /* fraction */ ! 805: { ! 806: string_appendn (&tname, ".", 1); ! 807: (*mangled)++; ! 808: while (isdigit (**mangled)) ! 809: { ! 810: string_appendn (&tname, *mangled, 1); ! 811: (*mangled)++; ! 812: } ! 813: } ! 814: if (**mangled == 'e') /* exponent */ ! 815: { ! 816: string_appendn (&tname, "e", 1); ! 817: (*mangled)++; ! 818: while (isdigit (**mangled)) ! 819: { ! 820: string_appendn (&tname, *mangled, 1); ! 821: (*mangled)++; ! 822: } ! 823: } ! 824: } ! 825: else if (is_pointer) ! 826: { ! 827: if (!get_count (mangled, &symbol_len)) ! 828: { ! 829: success = 0; ! 830: break; ! 831: } ! 832: string_appendn (&tname, *mangled, symbol_len); ! 833: *mangled += symbol_len; ! 834: } ! 835: } ! 836: need_comma = 1; ! 837: } ! 838: string_append (&tname, ">::"); ! 839: if (work -> destructor) ! 840: { ! 841: string_append (&tname, "~"); ! 842: } ! 843: if (work -> constructor || work -> destructor) ! 844: { ! 845: #ifdef NeXT ! 846: string_appends (&tname, &temp); ! 847: #else ! 848: string_append (&tname, trawname.b); ! 849: #endif /* NeXT */ ! 850: } ! 851: #ifdef NeXT ! 852: { ! 853: char buf[16]; ! 854: sprintf(buf, "%d", trawname.p - trawname.b); ! 855: string_prepend(&trawname, buf); ! 856: remember_type(work, trawname.b, trawname.p - trawname.b); ! 857: } ! 858: #endif /* NeXT */ ! 859: string_delete(&trawname); ! 860: ! 861: if (!success) ! 862: { ! 863: string_delete(&tname); ! 864: } ! 865: else ! 866: { ! 867: #ifdef NeXT ! 868: string_prepends (declp, &tname); ! 869: #else ! 870: string_prepend (declp, tname.b); ! 871: #endif /* NeXT */ ! 872: string_delete (&tname); ! 873: ! 874: if (work -> static_type) ! 875: { ! 876: string_append (declp, *mangled + 1); ! 877: *mangled += strlen (*mangled); ! 878: #ifndef NeXT ! 879: success = 1; ! 880: #endif /* !NeXT */ ! 881: } ! 882: #ifdef NeXT ! 883: success = 1; ! 884: #else ! 885: else ! 886: { ! 887: success = demangle_args (work, mangled, declp); ! 888: } ! 889: #endif /* NeXT */ ! 890: } ! 891: return (success); ! 892: } ! 893: ! 894: /* ! 895: ! 896: LOCAL FUNCTION ! 897: ! 898: demangle_class -- demangle a mangled class sequence ! 899: ! 900: SYNOPSIS ! 901: ! 902: static int ! 903: demangle_class (struct work_stuff *work, const char **mangled, ! 904: strint *declp) ! 905: ! 906: DESCRIPTION ! 907: ! 908: DECLP points to the buffer into which demangling is being done. ! 909: ! 910: *MANGLED points to the current token to be demangled. On input, ! 911: it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) ! 912: On exit, it points to the next token after the mangled class on ! 913: success, or the first unconsumed token on failure. ! 914: ! 915: If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then ! 916: we are demangling a constructor or destructor. In this case ! 917: we prepend "class::class" or "class::~class" to DECLP. ! 918: ! 919: Otherwise, we prepend "class::" to the current DECLP. ! 920: ! 921: Reset the constructor/destructor flags once they have been ! 922: "consumed". This allows demangle_class to be called later during ! 923: the same demangling, to do normal class demangling. ! 924: ! 925: Returns 1 if demangling is successful, 0 otherwise. ! 926: ! 927: */ ! 928: ! 929: static int ! 930: demangle_class (work, mangled, declp) ! 931: struct work_stuff *work; ! 932: CONST char **mangled; ! 933: string *declp; ! 934: { ! 935: int n; ! 936: int success = 0; ! 937: ! 938: n = consume_count (mangled); ! 939: if (strlen (*mangled) >= n) ! 940: { ! 941: if (work -> constructor || work -> destructor) ! 942: { ! 943: string_prependn (declp, *mangled, n); ! 944: if (work -> destructor) ! 945: { ! 946: string_prepend (declp, "~"); ! 947: } ! 948: work -> constructor = work -> destructor = 0; ! 949: } ! 950: string_prepend (declp, "::"); ! 951: string_prependn (declp, *mangled, n); ! 952: *mangled += n; ! 953: success = 1; ! 954: } ! 955: return (success); ! 956: } ! 957: ! 958: /* ! 959: ! 960: LOCAL FUNCTION ! 961: ! 962: demangle_prefix -- consume the mangled name prefix and find signature ! 963: ! 964: SYNOPSIS ! 965: ! 966: static int ! 967: demangle_prefix (struct work_stuff *work, const char **mangled, ! 968: string *declp); ! 969: ! 970: DESCRIPTION ! 971: ! 972: Consume and demangle the prefix of the mangled name. ! 973: ! 974: DECLP points to the string buffer into which demangled output is ! 975: placed. On entry, the buffer is empty. On exit it contains ! 976: the root function name, the demangled operator name, or in some ! 977: special cases either nothing or the completely demangled result. ! 978: ! 979: MANGLED points to the current pointer into the mangled name. As each ! 980: token of the mangled name is consumed, it is updated. Upon entry ! 981: the current mangled name pointer points to the first character of ! 982: the mangled name. Upon exit, it should point to the first character ! 983: of the signature if demangling was successful, or to the first ! 984: unconsumed character if demangling of the prefix was unsuccessful. ! 985: ! 986: Returns 1 on success, 0 otherwise. ! 987: */ ! 988: ! 989: static int ! 990: demangle_prefix (work, mangled, declp) ! 991: struct work_stuff *work; ! 992: CONST char **mangled; ! 993: string *declp; ! 994: { ! 995: int success = 1; ! 996: CONST char *scan; ! 997: int i; ! 998: ! 999: /* This block of code is a reduction in strength time optimization ! 1000: of: ! 1001: scan = strstr (*mangled, "__"); */ ! 1002: ! 1003: { ! 1004: scan = *mangled; ! 1005: ! 1006: do { ! 1007: scan = strchr (scan, '_'); ! 1008: } while (scan != NULL && *++scan != '_'); ! 1009: ! 1010: if (scan != NULL) --scan; ! 1011: } ! 1012: ! 1013: if (scan != NULL) ! 1014: { ! 1015: /* We found a sequence of two or more '_', ensure that we start at ! 1016: the last pair in the sequence. */ ! 1017: i = strspn (scan, "_"); ! 1018: if (i > 2) ! 1019: { ! 1020: scan += (i - 2); ! 1021: } ! 1022: } ! 1023: ! 1024: if (scan == NULL) ! 1025: { ! 1026: success = 0; ! 1027: } ! 1028: else if (work -> static_type) ! 1029: { ! 1030: if (!isdigit (scan[0]) && (scan[0] != 't')) ! 1031: { ! 1032: success = 0; ! 1033: } ! 1034: } ! 1035: #ifdef NeXT ! 1036: else if ((scan == *mangled) && (isdigit (scan[2]) || (scan[2] == 't'))) ! 1037: { ! 1038: /* A GNU style constructor starts with "__<digit>" or "__t". */ ! 1039: #else ! 1040: else if ((scan == *mangled) && (isdigit (scan[2]) || (scan[2] == 'Q'))) ! 1041: { ! 1042: /* A GNU style constructor starts with "__<digit>" or "__Q". */ ! 1043: #endif /* NeXT */ ! 1044: work -> constructor = 1; ! 1045: *mangled = scan + 2; ! 1046: } ! 1047: else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't')) ! 1048: { ! 1049: /* Mangled name starts with "__". Skip over any leading '_' characters, ! 1050: then find the next "__" that separates the prefix from the signature. ! 1051: */ ! 1052: if (!(CFRONT_DEMANGLING || LUCID_DEMANGLING) ! 1053: || (cfront_special (work, mangled, declp) == 0)) ! 1054: { ! 1055: while (*scan == '_') ! 1056: { ! 1057: scan++; ! 1058: } ! 1059: if ((scan = strstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) ! 1060: { ! 1061: /* No separator (I.E. "__not_mangled"), or empty signature ! 1062: (I.E. "__not_mangled_either__") */ ! 1063: success = 0; ! 1064: } ! 1065: else ! 1066: { ! 1067: demangle_function_name (work, mangled, declp, scan); ! 1068: } ! 1069: } ! 1070: } ! 1071: else if (*(scan + 2) != '\0') ! 1072: { ! 1073: /* Mangled name does not start with "__" but does have one somewhere ! 1074: in there with non empty stuff after it. Looks like a global ! 1075: function name. */ ! 1076: demangle_function_name (work, mangled, declp, scan); ! 1077: } ! 1078: else ! 1079: { ! 1080: /* Doesn't look like a mangled name */ ! 1081: success = 0; ! 1082: } ! 1083: return (success); ! 1084: } ! 1085: ! 1086: /* ! 1087: ! 1088: LOCAL FUNCTION ! 1089: ! 1090: gnu_special -- special handling of gnu mangled strings ! 1091: ! 1092: SYNOPSIS ! 1093: ! 1094: static int ! 1095: gnu_special (struct work_stuff *work, const char **mangled, ! 1096: string *declp); ! 1097: ! 1098: ! 1099: DESCRIPTION ! 1100: ! 1101: Process some special GNU style mangling forms that don't fit ! 1102: the normal pattern. For example: ! 1103: ! 1104: _$_3foo (destructor for class foo) ! 1105: _vt$foo (foo virtual table) ! 1106: _vt$foo$bar (foo::bar virtual table) ! 1107: _3foo$varname (static data member) ! 1108: */ ! 1109: ! 1110: static int ! 1111: gnu_special (work, mangled, declp) ! 1112: struct work_stuff *work; ! 1113: CONST char **mangled; ! 1114: string *declp; ! 1115: { ! 1116: int n; ! 1117: int success = 1; ! 1118: CONST char *p; ! 1119: ! 1120: if ((*mangled)[0] == '_' ! 1121: && strchr (cplus_markers, (*mangled)[1]) != NULL ! 1122: && (*mangled)[2] == '_') ! 1123: { ! 1124: /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ ! 1125: (*mangled) += 3; ! 1126: work -> destructor = 1; ! 1127: } ! 1128: else if ((*mangled)[0] == '_' ! 1129: && (*mangled)[1] == 'v' ! 1130: && (*mangled)[2] == 't' ! 1131: && strchr (cplus_markers, (*mangled)[3]) != NULL) ! 1132: { ! 1133: /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" ! 1134: and create the decl. Note that we consume the entire mangled ! 1135: input string, which means that demangle_signature has no work ! 1136: to do. */ ! 1137: (*mangled) += 4; ! 1138: while (**mangled != '\0') ! 1139: { ! 1140: n = strcspn (*mangled, cplus_markers); ! 1141: string_appendn (declp, *mangled, n); ! 1142: (*mangled) += n; ! 1143: if (**mangled != '\0') ! 1144: { ! 1145: string_append (declp, "::"); ! 1146: (*mangled)++; ! 1147: } ! 1148: } ! 1149: string_append (declp, " virtual table"); ! 1150: } ! 1151: else if ((*mangled)[0] == '_' ! 1152: && isdigit ((*mangled)[1]) ! 1153: && (p = strpbrk (*mangled, cplus_markers)) != NULL) ! 1154: { ! 1155: /* static data member, "_3foo$varname" for example */ ! 1156: (*mangled)++; ! 1157: p++; ! 1158: n = consume_count (mangled); ! 1159: string_appendn (declp, *mangled, n); ! 1160: string_append (declp, "::"); ! 1161: n = strlen (p); ! 1162: string_appendn (declp, p, n); ! 1163: (*mangled) = p + n; ! 1164: } ! 1165: else ! 1166: { ! 1167: success = 0; ! 1168: } ! 1169: return (success); ! 1170: } ! 1171: ! 1172: /* ! 1173: ! 1174: LOCAL FUNCTION ! 1175: ! 1176: cfront_special -- special handling of cfront/lucid mangled strings ! 1177: ! 1178: SYNOPSIS ! 1179: ! 1180: static int ! 1181: cfront_special (struct work_stuff *work, const char **mangled, ! 1182: string *declp); ! 1183: ! 1184: ! 1185: DESCRIPTION ! 1186: ! 1187: Process some special cfront style mangling forms that don't fit ! 1188: the normal pattern. For example: ! 1189: ! 1190: __vtbl__3foo (foo virtual table) ! 1191: __vtbl__3foo__3bar (bar::foo virtual table) ! 1192: ! 1193: */ ! 1194: ! 1195: static int ! 1196: cfront_special (work, mangled, declp) ! 1197: struct work_stuff *work; ! 1198: CONST char **mangled; ! 1199: string *declp; ! 1200: { ! 1201: int n; ! 1202: int i; ! 1203: int success = 1; ! 1204: CONST char *p; ! 1205: ! 1206: if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) ! 1207: { ! 1208: /* Found a cfront style virtual table, get past ARM_VTABLE_STRING ! 1209: and create the decl. Note that we consume the entire mangled ! 1210: input string, which means that demangle_signature has no work ! 1211: to do. */ ! 1212: (*mangled) += ARM_VTABLE_STRLEN; ! 1213: while (**mangled != '\0') ! 1214: { ! 1215: n = consume_count (mangled); ! 1216: string_prependn (declp, *mangled, n); ! 1217: (*mangled) += n; ! 1218: if ((*mangled)[0] == '_' && (*mangled)[1] == '_') ! 1219: { ! 1220: string_prepend (declp, "::"); ! 1221: (*mangled) += 2; ! 1222: } ! 1223: } ! 1224: string_append (declp, " virtual table"); ! 1225: } ! 1226: else ! 1227: { ! 1228: success = 0; ! 1229: } ! 1230: return (success); ! 1231: } ! 1232: ! 1233: /* ! 1234: ! 1235: LOCAL FUNCTION ! 1236: ! 1237: demangle_qualified -- demangle 'Q' qualified name strings ! 1238: ! 1239: SYNOPSIS ! 1240: ! 1241: static int ! 1242: demangle_qualified (struct work_stuff *, const char *mangled, ! 1243: string *result, int isfuncname); ! 1244: ! 1245: DESCRIPTION ! 1246: ! 1247: Demangle a qualified name, such as "Q25Outer5Inner" which is ! 1248: the mangled form of "Outer::Inner". The demangled output is ! 1249: appended to the result string. ! 1250: ! 1251: If isfuncname is nonzero, then the qualified name we are building ! 1252: is going to be used as a member function name, so if it is a ! 1253: constructor or destructor function, append an appropriate ! 1254: constructor or destructor name. I.E. for the above example, ! 1255: the result for use as a constructor is "Outer::Inner::Inner" ! 1256: and the result for use as a destructor is "Outer::Inner::~Inner". ! 1257: ! 1258: BUGS ! 1259: ! 1260: Numeric conversion is ASCII dependent (FIXME). ! 1261: ! 1262: */ ! 1263: ! 1264: static int ! 1265: demangle_qualified (work, mangled, result, isfuncname) ! 1266: struct work_stuff *work; ! 1267: CONST char **mangled; ! 1268: string *result; ! 1269: int isfuncname; ! 1270: { ! 1271: int qualifiers; ! 1272: int namelength; ! 1273: int success = 0; ! 1274: ! 1275: qualifiers = (*mangled)[1] - '0'; ! 1276: if (qualifiers > 0 && qualifiers < 10) ! 1277: { ! 1278: /* Assume success until we discover otherwise. Skip over the 'Q', the ! 1279: qualifier count, and any '_' between the qualifier count and the ! 1280: first name (cfront qualified names). */ ! 1281: ! 1282: success = 1; ! 1283: if ((*mangled)[2] == '_') ! 1284: { ! 1285: (*mangled)++; ! 1286: } ! 1287: (*mangled) += 2; ! 1288: ! 1289: ! 1290: /* Pick off the names and append them to the result string as they ! 1291: are found, separated by '::'. */ ! 1292: ! 1293: while (qualifiers-- > 0) ! 1294: { ! 1295: namelength = consume_count (mangled); ! 1296: if (strlen (*mangled) < namelength) ! 1297: { ! 1298: /* Simple sanity check failed */ ! 1299: success = 0; ! 1300: break; ! 1301: } ! 1302: string_appendn (result, *mangled, namelength); ! 1303: if (qualifiers > 0) ! 1304: { ! 1305: string_appendn (result, "::", 2); ! 1306: } ! 1307: *mangled += namelength; ! 1308: } ! 1309: ! 1310: /* If we are using the result as a function name, we need to append ! 1311: the appropriate '::' separated constructor or destructor name. ! 1312: We do this here because this is the most convenient place, where ! 1313: we already have a pointer to the name and the length of the name. */ ! 1314: ! 1315: if (isfuncname && (work -> constructor || work -> destructor)) ! 1316: { ! 1317: string_appendn (result, "::", 2); ! 1318: if (work -> destructor) ! 1319: { ! 1320: string_append (result, "~"); ! 1321: } ! 1322: string_appendn (result, (*mangled) - namelength, namelength); ! 1323: } ! 1324: } ! 1325: return (success); ! 1326: } ! 1327: ! 1328: /* ! 1329: ! 1330: LOCAL FUNCTION ! 1331: ! 1332: get_count -- convert an ascii count to integer, consuming tokens ! 1333: ! 1334: SYNOPSIS ! 1335: ! 1336: static int ! 1337: get_count (const char **type, int *count) ! 1338: ! 1339: DESCRIPTION ! 1340: ! 1341: Return 0 if no conversion is performed, 1 if a string is converted. ! 1342: */ ! 1343: ! 1344: static int ! 1345: get_count (type, count) ! 1346: CONST char **type; ! 1347: int *count; ! 1348: { ! 1349: CONST char *p; ! 1350: int n; ! 1351: ! 1352: if (!isdigit (**type)) ! 1353: { ! 1354: return (0); ! 1355: } ! 1356: else ! 1357: { ! 1358: *count = **type - '0'; ! 1359: (*type)++; ! 1360: if (isdigit (**type)) ! 1361: { ! 1362: p = *type; ! 1363: n = *count; ! 1364: do ! 1365: { ! 1366: n *= 10; ! 1367: n += *p - '0'; ! 1368: p++; ! 1369: } ! 1370: while (isdigit (*p)); ! 1371: if (*p == '_') ! 1372: { ! 1373: *type = p + 1; ! 1374: *count = n; ! 1375: } ! 1376: } ! 1377: } ! 1378: return (1); ! 1379: } ! 1380: ! 1381: /* result will be initialised here; it will be freed on failure */ ! 1382: ! 1383: static int ! 1384: do_type (work, mangled, result) ! 1385: struct work_stuff *work; ! 1386: CONST char **mangled; ! 1387: string *result; ! 1388: { ! 1389: int n; ! 1390: int done; ! 1391: int success; ! 1392: string decl; ! 1393: CONST char *remembered_type; ! 1394: int constp; ! 1395: int volatilep; ! 1396: ! 1397: string_init (&decl); ! 1398: string_init (result); ! 1399: ! 1400: done = 0; ! 1401: success = 1; ! 1402: while (success && !done) ! 1403: { ! 1404: int member; ! 1405: switch (**mangled) ! 1406: { ! 1407: ! 1408: /* A pointer type */ ! 1409: case 'P': ! 1410: (*mangled)++; ! 1411: string_prepend (&decl, "*"); ! 1412: break; ! 1413: ! 1414: /* A reference type */ ! 1415: case 'R': ! 1416: (*mangled)++; ! 1417: string_prepend (&decl, "&"); ! 1418: break; ! 1419: ! 1420: /* A back reference to a previously seen type */ ! 1421: case 'T': ! 1422: (*mangled)++; ! 1423: if (!get_count (mangled, &n) || n >= work -> ntypes) ! 1424: { ! 1425: success = 0; ! 1426: } ! 1427: else ! 1428: { ! 1429: remembered_type = work -> typevec[n]; ! 1430: mangled = &remembered_type; ! 1431: } ! 1432: break; ! 1433: ! 1434: /* A function */ ! 1435: case 'F': ! 1436: (*mangled)++; ! 1437: if (!STRING_EMPTY (&decl) && decl.b[0] == '*') ! 1438: { ! 1439: string_prepend (&decl, "("); ! 1440: string_append (&decl, ")"); ! 1441: } ! 1442: /* After picking off the function args, we expect to either find the ! 1443: function return type (preceded by an '_') or the end of the ! 1444: string. */ ! 1445: if (!demangle_args (work, mangled, &decl) ! 1446: || (**mangled != '_' && **mangled != '\0')) ! 1447: { ! 1448: success = 0; ! 1449: } ! 1450: if (success && (**mangled == '_')) ! 1451: { ! 1452: (*mangled)++; ! 1453: } ! 1454: break; ! 1455: ! 1456: case 'M': ! 1457: case 'O': ! 1458: { ! 1459: constp = 0; ! 1460: volatilep = 0; ! 1461: ! 1462: member = **mangled == 'M'; ! 1463: (*mangled)++; ! 1464: if (!isdigit (**mangled)) ! 1465: { ! 1466: success = 0; ! 1467: break; ! 1468: } ! 1469: n = consume_count (mangled); ! 1470: if (strlen (*mangled) < n) ! 1471: { ! 1472: success = 0; ! 1473: break; ! 1474: } ! 1475: string_append (&decl, ")"); ! 1476: string_prepend (&decl, "::"); ! 1477: string_prependn (&decl, *mangled, n); ! 1478: string_prepend (&decl, "("); ! 1479: *mangled += n; ! 1480: if (member) ! 1481: { ! 1482: if (**mangled == 'C') ! 1483: { ! 1484: (*mangled)++; ! 1485: constp = 1; ! 1486: } ! 1487: if (**mangled == 'V') ! 1488: { ! 1489: (*mangled)++; ! 1490: volatilep = 1; ! 1491: } ! 1492: if (*(*mangled)++ != 'F') ! 1493: { ! 1494: success = 0; ! 1495: break; ! 1496: } ! 1497: } ! 1498: if ((member && !demangle_args (work, mangled, &decl)) ! 1499: || **mangled != '_') ! 1500: { ! 1501: success = 0; ! 1502: break; ! 1503: } ! 1504: (*mangled)++; ! 1505: if (! PRINT_ANSI_QUALIFIERS) ! 1506: { ! 1507: break; ! 1508: } ! 1509: if (constp) ! 1510: { ! 1511: APPEND_BLANK (&decl); ! 1512: string_append (&decl, "const"); ! 1513: } ! 1514: if (volatilep) ! 1515: { ! 1516: APPEND_BLANK (&decl); ! 1517: string_append (&decl, "volatile"); ! 1518: } ! 1519: break; ! 1520: } ! 1521: ! 1522: case 'C': ! 1523: if ((*mangled)[1] == 'P') ! 1524: { ! 1525: (*mangled)++; ! 1526: if (PRINT_ANSI_QUALIFIERS) ! 1527: { ! 1528: if (!STRING_EMPTY (&decl)) ! 1529: { ! 1530: string_prepend (&decl, " "); ! 1531: } ! 1532: string_prepend (&decl, "const"); ! 1533: } ! 1534: break; ! 1535: } ! 1536: ! 1537: /* fall through */ ! 1538: default: ! 1539: done = 1; ! 1540: break; ! 1541: } ! 1542: } ! 1543: ! 1544: switch (**mangled) ! 1545: { ! 1546: /* A qualified name, such as "Outer::Inner". */ ! 1547: case 'Q': ! 1548: success = demangle_qualified (work, mangled, result, 0); ! 1549: break; ! 1550: ! 1551: default: ! 1552: success = demangle_fund_type (work, mangled, result); ! 1553: break; ! 1554: } ! 1555: ! 1556: if (success) ! 1557: { ! 1558: if (!STRING_EMPTY (&decl)) ! 1559: { ! 1560: string_append (result, " "); ! 1561: string_appends (result, &decl); ! 1562: } ! 1563: } ! 1564: else ! 1565: { ! 1566: string_delete (result); ! 1567: } ! 1568: string_delete (&decl); ! 1569: return (success); ! 1570: } ! 1571: ! 1572: /* Given a pointer to a type string that represents a fundamental type ! 1573: argument (int, long, unsigned int, etc) in TYPE, a pointer to the ! 1574: string in which the demangled output is being built in RESULT, and ! 1575: the WORK structure, decode the types and add them to the result. ! 1576: ! 1577: For example: ! 1578: ! 1579: "Ci" => "const int" ! 1580: "Sl" => "signed long" ! 1581: "CUs" => "const unsigned short" ! 1582: ! 1583: */ ! 1584: ! 1585: static int ! 1586: demangle_fund_type (work, mangled, result) ! 1587: struct work_stuff *work; ! 1588: CONST char **mangled; ! 1589: string *result; ! 1590: { ! 1591: int done = 0; ! 1592: int success = 1; ! 1593: int n; ! 1594: ! 1595: /* First pick off any type qualifiers. There can be more than one. */ ! 1596: ! 1597: while (!done) ! 1598: { ! 1599: switch (**mangled) ! 1600: { ! 1601: case 'C': ! 1602: (*mangled)++; ! 1603: if (PRINT_ANSI_QUALIFIERS) ! 1604: { ! 1605: APPEND_BLANK (result); ! 1606: string_append (result, "const"); ! 1607: } ! 1608: break; ! 1609: case 'U': ! 1610: (*mangled)++; ! 1611: APPEND_BLANK (result); ! 1612: string_append (result, "unsigned"); ! 1613: break; ! 1614: case 'S': /* signed char only */ ! 1615: (*mangled)++; ! 1616: APPEND_BLANK (result); ! 1617: string_append (result, "signed"); ! 1618: break; ! 1619: case 'V': ! 1620: (*mangled)++; ! 1621: if (PRINT_ANSI_QUALIFIERS) ! 1622: { ! 1623: APPEND_BLANK (result); ! 1624: string_append (result, "volatile"); ! 1625: } ! 1626: break; ! 1627: default: ! 1628: done = 1; ! 1629: break; ! 1630: } ! 1631: } ! 1632: ! 1633: /* Now pick off the fundamental type. There can be only one. */ ! 1634: ! 1635: switch (**mangled) ! 1636: { ! 1637: case '\0': ! 1638: case '_': ! 1639: break; ! 1640: case 'v': ! 1641: (*mangled)++; ! 1642: APPEND_BLANK (result); ! 1643: string_append (result, "void"); ! 1644: break; ! 1645: case 'x': ! 1646: (*mangled)++; ! 1647: APPEND_BLANK (result); ! 1648: string_append (result, "long long"); ! 1649: break; ! 1650: case 'l': ! 1651: (*mangled)++; ! 1652: APPEND_BLANK (result); ! 1653: string_append (result, "long"); ! 1654: break; ! 1655: case 'i': ! 1656: (*mangled)++; ! 1657: APPEND_BLANK (result); ! 1658: string_append (result, "int"); ! 1659: break; ! 1660: case 's': ! 1661: (*mangled)++; ! 1662: APPEND_BLANK (result); ! 1663: string_append (result, "short"); ! 1664: break; ! 1665: case 'c': ! 1666: (*mangled)++; ! 1667: APPEND_BLANK (result); ! 1668: string_append (result, "char"); ! 1669: break; ! 1670: case 'r': ! 1671: (*mangled)++; ! 1672: APPEND_BLANK (result); ! 1673: string_append (result, "long double"); ! 1674: break; ! 1675: case 'd': ! 1676: (*mangled)++; ! 1677: APPEND_BLANK (result); ! 1678: string_append (result, "double"); ! 1679: break; ! 1680: case 'f': ! 1681: (*mangled)++; ! 1682: APPEND_BLANK (result); ! 1683: string_append (result, "float"); ! 1684: break; ! 1685: case 'G': ! 1686: (*mangled)++; ! 1687: if (!isdigit (**mangled)) ! 1688: { ! 1689: success = 0; ! 1690: break; ! 1691: } ! 1692: /* fall through */ ! 1693: /* An explicit type, such as "6mytype" or "7integer" */ ! 1694: case '0': ! 1695: case '1': ! 1696: case '2': ! 1697: case '3': ! 1698: case '4': ! 1699: case '5': ! 1700: case '6': ! 1701: case '7': ! 1702: case '8': ! 1703: case '9': ! 1704: n = consume_count (mangled); ! 1705: if (strlen (*mangled) < n) ! 1706: { ! 1707: success = 0; ! 1708: break; ! 1709: } ! 1710: APPEND_BLANK (result); ! 1711: string_appendn (result, *mangled, n); ! 1712: *mangled += n; ! 1713: break; ! 1714: default: ! 1715: success = 0; ! 1716: break; ! 1717: } ! 1718: ! 1719: return (success); ! 1720: } ! 1721: ! 1722: /* `result' will be initialized in do_type; it will be freed on failure */ ! 1723: ! 1724: static int ! 1725: do_arg (work, mangled, result) ! 1726: struct work_stuff *work; ! 1727: CONST char **mangled; ! 1728: string *result; ! 1729: { ! 1730: CONST char *start = *mangled; ! 1731: ! 1732: if (!do_type (work, mangled, result)) ! 1733: { ! 1734: return (0); ! 1735: } ! 1736: else ! 1737: { ! 1738: remember_type (work, start, *mangled - start); ! 1739: return (1); ! 1740: } ! 1741: } ! 1742: ! 1743: static void ! 1744: remember_type (work, start, len) ! 1745: struct work_stuff *work; ! 1746: CONST char *start; ! 1747: int len; ! 1748: { ! 1749: char *tem; ! 1750: ! 1751: if (work -> ntypes >= work -> typevec_size) ! 1752: { ! 1753: if (work -> typevec_size == 0) ! 1754: { ! 1755: work -> typevec_size = 3; ! 1756: work -> typevec = ! 1757: (char **) xmalloc (sizeof (char *) * work -> typevec_size); ! 1758: } ! 1759: else ! 1760: { ! 1761: work -> typevec_size *= 2; ! 1762: work -> typevec = ! 1763: (char **) xrealloc ((char *)work -> typevec, ! 1764: sizeof (char *) * work -> typevec_size); ! 1765: } ! 1766: } ! 1767: tem = (char *) xmalloc (len + 1); ! 1768: memcpy (tem, start, len); ! 1769: tem[len] = '\0'; ! 1770: work -> typevec[work -> ntypes++] = tem; ! 1771: } ! 1772: ! 1773: /* Forget the remembered types, but not the type vector itself. */ ! 1774: ! 1775: static void ! 1776: forget_types (work) ! 1777: struct work_stuff *work; ! 1778: { ! 1779: int i; ! 1780: ! 1781: while (work -> ntypes > 0) ! 1782: { ! 1783: i = --(work -> ntypes); ! 1784: if (work -> typevec[i] != NULL) ! 1785: { ! 1786: free (work -> typevec[i]); ! 1787: work -> typevec[i] = NULL; ! 1788: } ! 1789: } ! 1790: } ! 1791: ! 1792: /* Process the argument list part of the signature, after any class spec ! 1793: has been consumed, as well as the first 'F' character (if any). For ! 1794: example: ! 1795: ! 1796: "__als__3fooRT0" => process "RT0" ! 1797: "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" ! 1798: ! 1799: DECLP must be already initialised, usually non-empty. It won't be freed ! 1800: on failure. ! 1801: ! 1802: Note that g++ differs significantly from cfront and lucid style mangling ! 1803: with regards to references to previously seen types. For example, given ! 1804: the source fragment: ! 1805: ! 1806: class foo { ! 1807: public: ! 1808: foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); ! 1809: }; ! 1810: ! 1811: foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } ! 1812: void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } ! 1813: ! 1814: g++ produces the names: ! 1815: ! 1816: __3fooiRT0iT2iT2 ! 1817: foo__FiR3fooiT1iT1 ! 1818: ! 1819: while lcc (and presumably cfront as well) produces: ! 1820: ! 1821: foo__FiR3fooT1T2T1T2 ! 1822: __ct__3fooFiR3fooT1T2T1T2 ! 1823: ! 1824: Note that g++ bases it's type numbers starting at zero and counts all ! 1825: previously seen types, while lucid/cfront bases it's type numbers starting ! 1826: at one and only considers types after it has seen the 'F' character ! 1827: indicating the start of the function args. For lucid/cfront style, we ! 1828: account for this difference by discarding any previously seen types when ! 1829: we see the 'F' character, and subtracting one from the type number ! 1830: reference. ! 1831: ! 1832: */ ! 1833: ! 1834: static int ! 1835: demangle_args (work, mangled, declp) ! 1836: struct work_stuff *work; ! 1837: CONST char **mangled; ! 1838: string *declp; ! 1839: { ! 1840: string arg; ! 1841: int need_comma = 0; ! 1842: int r; ! 1843: int t; ! 1844: CONST char *tem; ! 1845: char temptype; ! 1846: ! 1847: if (PRINT_ARG_TYPES) ! 1848: { ! 1849: string_append (declp, "("); ! 1850: if (**mangled == '\0') ! 1851: { ! 1852: string_append (declp, "void"); ! 1853: } ! 1854: } ! 1855: ! 1856: while (**mangled != '_' && **mangled != '\0' && **mangled != 'e') ! 1857: { ! 1858: if ((**mangled == 'N') || (**mangled == 'T')) ! 1859: { ! 1860: temptype = *(*mangled)++; ! 1861: ! 1862: if (temptype == 'N') ! 1863: { ! 1864: if (!get_count (mangled, &r)) ! 1865: { ! 1866: return (0); ! 1867: } ! 1868: } ! 1869: else ! 1870: { ! 1871: r = 1; ! 1872: } ! 1873: if (!get_count (mangled, &t)) ! 1874: { ! 1875: return (0); ! 1876: } ! 1877: if (LUCID_DEMANGLING || CFRONT_DEMANGLING) ! 1878: { ! 1879: t--; ! 1880: } ! 1881: /* Validate the type index. Protect against illegal indices from ! 1882: malformed type strings. */ ! 1883: if ((t < 0) || (t >= work -> ntypes)) ! 1884: { ! 1885: return (0); ! 1886: } ! 1887: while (--r >= 0) ! 1888: { ! 1889: tem = work -> typevec[t]; ! 1890: if (need_comma && PRINT_ARG_TYPES) ! 1891: { ! 1892: string_append (declp, ", "); ! 1893: } ! 1894: if (!do_arg (work, &tem, &arg)) ! 1895: { ! 1896: return (0); ! 1897: } ! 1898: if (PRINT_ARG_TYPES) ! 1899: { ! 1900: string_appends (declp, &arg); ! 1901: } ! 1902: string_delete (&arg); ! 1903: need_comma = 1; ! 1904: } ! 1905: } ! 1906: else ! 1907: { ! 1908: if (need_comma & PRINT_ARG_TYPES) ! 1909: { ! 1910: string_append (declp, ", "); ! 1911: } ! 1912: if (!do_arg (work, mangled, &arg)) ! 1913: { ! 1914: return (0); ! 1915: } ! 1916: if (PRINT_ARG_TYPES) ! 1917: { ! 1918: string_appends (declp, &arg); ! 1919: } ! 1920: string_delete (&arg); ! 1921: need_comma = 1; ! 1922: } ! 1923: } ! 1924: ! 1925: if (**mangled == 'e') ! 1926: { ! 1927: (*mangled)++; ! 1928: if (PRINT_ARG_TYPES) ! 1929: { ! 1930: if (need_comma) ! 1931: { ! 1932: string_append (declp, ","); ! 1933: } ! 1934: string_append (declp, "..."); ! 1935: } ! 1936: } ! 1937: ! 1938: if (PRINT_ARG_TYPES) ! 1939: { ! 1940: string_append (declp, ")"); ! 1941: } ! 1942: return (1); ! 1943: } ! 1944: ! 1945: static void ! 1946: demangle_function_name (work, mangled, declp, scan) ! 1947: struct work_stuff *work; ! 1948: CONST char **mangled; ! 1949: string *declp; ! 1950: CONST char *scan; ! 1951: { ! 1952: int i; ! 1953: int len; ! 1954: string type; ! 1955: CONST char *tem; ! 1956: ! 1957: string_appendn (declp, (*mangled), scan - (*mangled)); ! 1958: string_need (declp, 1); ! 1959: *(declp -> p) = '\0'; ! 1960: ! 1961: /* Consume the function name, including the "__" separating the name ! 1962: from the signature. We are guaranteed that SCAN points to the ! 1963: separator. */ ! 1964: ! 1965: (*mangled) = scan + 2; ! 1966: ! 1967: if (LUCID_DEMANGLING || CFRONT_DEMANGLING) ! 1968: { ! 1969: ! 1970: /* See if we have an ARM style constructor or destructor operator. ! 1971: If so, then just record it, clear the decl, and return. ! 1972: We can't build the actual constructor/destructor decl until later, ! 1973: when we recover the class name from the signature. */ ! 1974: ! 1975: if (strcmp (declp -> b, "__ct") == 0) ! 1976: { ! 1977: work -> constructor = 1; ! 1978: string_clear (declp); ! 1979: return; ! 1980: } ! 1981: else if (strcmp (declp -> b, "__dt") == 0) ! 1982: { ! 1983: work -> destructor = 1; ! 1984: string_clear (declp); ! 1985: return; ! 1986: } ! 1987: } ! 1988: ! 1989: if (declp->p - declp->b >= 3 ! 1990: && declp->b[0] == 'o' ! 1991: && declp->b[1] == 'p' ! 1992: && strchr (cplus_markers, declp->b[2]) != NULL) ! 1993: { ! 1994: /* see if it's an assignment expression */ ! 1995: if (declp->p - declp->b >= 10 /* op$assign_ */ ! 1996: && memcmp (declp->b + 3, "assign_", 7) == 0) ! 1997: { ! 1998: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 1999: { ! 2000: len = declp->p - declp->b - 10; ! 2001: if (strlen (optable[i].in) == len ! 2002: && memcmp (optable[i].in, declp->b + 10, len) == 0) ! 2003: { ! 2004: string_clear (declp); ! 2005: string_append (declp, "operator"); ! 2006: string_append (declp, optable[i].out); ! 2007: string_append (declp, "="); ! 2008: break; ! 2009: } ! 2010: } ! 2011: } ! 2012: else ! 2013: { ! 2014: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2015: { ! 2016: int len = declp->p - declp->b - 3; ! 2017: if (strlen (optable[i].in) == len ! 2018: && memcmp (optable[i].in, declp->b + 3, len) == 0) ! 2019: { ! 2020: string_clear (declp); ! 2021: string_append (declp, "operator"); ! 2022: string_append (declp, optable[i].out); ! 2023: break; ! 2024: } ! 2025: } ! 2026: } ! 2027: } ! 2028: else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type$", 5) == 0) ! 2029: { ! 2030: /* type conversion operator */ ! 2031: tem = declp->b + 5; ! 2032: if (do_type (work, &tem, &type)) ! 2033: { ! 2034: string_clear (declp); ! 2035: string_append (declp, "operator "); ! 2036: string_appends (declp, &type); ! 2037: string_delete (&type); ! 2038: } ! 2039: } ! 2040: else if (declp->b[2] == 'o' && declp->b[3] == 'p') ! 2041: { ! 2042: /* ANSI. */ ! 2043: /* type conversion operator. */ ! 2044: tem = declp->b + 4; ! 2045: if (do_type (work, &tem, &type)) ! 2046: { ! 2047: string_clear (declp); ! 2048: string_append (declp, "operator "); ! 2049: string_appends (declp, &type); ! 2050: string_delete (&type); ! 2051: } ! 2052: } ! 2053: else if (declp->b[0] == '_' && declp->b[1] == '_' ! 2054: && declp->b[2] >= 'a' && declp->b[2] <= 'z' ! 2055: && declp->b[3] >= 'a' && declp->b[3] <= 'z') ! 2056: { ! 2057: if (declp->b[4] == '\0') ! 2058: { ! 2059: /* Operator. */ ! 2060: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2061: { ! 2062: if (strlen (optable[i].in) == 2 ! 2063: && memcmp (optable[i].in, declp->b + 2, 2) == 0) ! 2064: { ! 2065: string_clear (declp); ! 2066: string_append (declp, "operator"); ! 2067: string_append (declp, optable[i].out); ! 2068: break; ! 2069: } ! 2070: } ! 2071: } ! 2072: else ! 2073: { ! 2074: if (declp->b[2] == 'a' && declp->b[5] == '\0') ! 2075: { ! 2076: /* Assignment. */ ! 2077: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2078: { ! 2079: if (strlen (optable[i].in) == 3 ! 2080: && memcmp (optable[i].in, declp->b + 2, 3) == 0) ! 2081: { ! 2082: string_clear (declp); ! 2083: string_append (declp, "operator"); ! 2084: string_append (declp, optable[i].out); ! 2085: break; ! 2086: } ! 2087: } ! 2088: } ! 2089: } ! 2090: } ! 2091: } ! 2092: ! 2093: /* a mini string-handling package */ ! 2094: ! 2095: static void ! 2096: string_need (s, n) ! 2097: string *s; ! 2098: int n; ! 2099: { ! 2100: int tem; ! 2101: ! 2102: if (s->b == NULL) ! 2103: { ! 2104: if (n < 32) ! 2105: { ! 2106: n = 32; ! 2107: } ! 2108: s->p = s->b = (char *) xmalloc (n); ! 2109: s->e = s->b + n; ! 2110: } ! 2111: else if (s->e - s->p < n) ! 2112: { ! 2113: tem = s->p - s->b; ! 2114: n += tem; ! 2115: n *= 2; ! 2116: s->b = (char *) xrealloc (s->b, n); ! 2117: s->p = s->b + tem; ! 2118: s->e = s->b + n; ! 2119: } ! 2120: } ! 2121: ! 2122: static void ! 2123: string_delete (s) ! 2124: string *s; ! 2125: { ! 2126: if (s->b != NULL) ! 2127: { ! 2128: free (s->b); ! 2129: s->b = s->e = s->p = NULL; ! 2130: } ! 2131: } ! 2132: ! 2133: static void ! 2134: string_init (s) ! 2135: string *s; ! 2136: { ! 2137: s->b = s->p = s->e = NULL; ! 2138: } ! 2139: ! 2140: static void ! 2141: string_clear (s) ! 2142: string *s; ! 2143: { ! 2144: s->p = s->b; ! 2145: } ! 2146: ! 2147: #if 0 ! 2148: ! 2149: static int ! 2150: string_empty (s) ! 2151: string *s; ! 2152: { ! 2153: return (s->b == s->p); ! 2154: } ! 2155: ! 2156: #endif ! 2157: ! 2158: static void ! 2159: string_append (p, s) ! 2160: string *p; ! 2161: CONST char *s; ! 2162: { ! 2163: int n; ! 2164: if (s == NULL || *s == '\0') ! 2165: return; ! 2166: n = strlen (s); ! 2167: string_need (p, n); ! 2168: memcpy (p->p, s, n); ! 2169: p->p += n; ! 2170: } ! 2171: ! 2172: static void ! 2173: string_appends (p, s) ! 2174: string *p, *s; ! 2175: { ! 2176: int n; ! 2177: ! 2178: if (s->b != s->p) ! 2179: { ! 2180: n = s->p - s->b; ! 2181: string_need (p, n); ! 2182: memcpy (p->p, s->b, n); ! 2183: p->p += n; ! 2184: } ! 2185: } ! 2186: ! 2187: static void ! 2188: string_appendn (p, s, n) ! 2189: string *p; ! 2190: CONST char *s; ! 2191: int n; ! 2192: { ! 2193: if (n != 0) ! 2194: { ! 2195: string_need (p, n); ! 2196: memcpy (p->p, s, n); ! 2197: p->p += n; ! 2198: } ! 2199: } ! 2200: ! 2201: static void ! 2202: string_prepend (p, s) ! 2203: string *p; ! 2204: CONST char *s; ! 2205: { ! 2206: if (s != NULL && *s != '\0') ! 2207: { ! 2208: string_prependn (p, s, strlen (s)); ! 2209: } ! 2210: } ! 2211: ! 2212: static void ! 2213: string_prepends (p, s) ! 2214: string *p, *s; ! 2215: { ! 2216: if (s->b != s->p) ! 2217: { ! 2218: string_prependn (p, s->b, s->p - s->b); ! 2219: } ! 2220: } ! 2221: ! 2222: static void ! 2223: string_prependn (p, s, n) ! 2224: string *p; ! 2225: CONST char *s; ! 2226: int n; ! 2227: { ! 2228: char *q; ! 2229: ! 2230: if (n != 0) ! 2231: { ! 2232: string_need (p, n); ! 2233: for (q = p->p - 1; q >= p->b; q--) ! 2234: { ! 2235: q[n] = q[0]; ! 2236: } ! 2237: memcpy (p->b, s, n); ! 2238: p->p += n; ! 2239: } ! 2240: } ! 2241: ! 2242: /* To generate a standalone demangler program for testing purposes, just ! 2243: compile and link this file with -DMAIN. When run, it demangles each ! 2244: command line arg, or each stdin string, and prints the result on stdout. */ ! 2245: ! 2246: #ifdef MAIN ! 2247: ! 2248: static void ! 2249: demangle_it (mangled_name) ! 2250: char *mangled_name; ! 2251: { ! 2252: char *result; ! 2253: ! 2254: result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI); ! 2255: if (result == NULL) ! 2256: { ! 2257: printf ("%s\n", mangled_name); ! 2258: } ! 2259: else ! 2260: { ! 2261: printf ("%s\n", result); ! 2262: free (result); ! 2263: } ! 2264: } ! 2265: ! 2266: PTR ! 2267: xmalloc (size) ! 2268: long size; ! 2269: { ! 2270: PTR newmem; ! 2271: ! 2272: if ((newmem = malloc ((int) size)) == NULL) ! 2273: { ! 2274: fprintf (stderr, "\nCan't allocate %u bytes\n", size); ! 2275: exit (1); ! 2276: } ! 2277: return (newmem); ! 2278: } ! 2279: ! 2280: PTR ! 2281: xrealloc (oldmem, size) ! 2282: PTR oldmem; ! 2283: long size; ! 2284: { ! 2285: PTR newmem; ! 2286: ! 2287: if ((newmem = realloc ((char *) oldmem, (int) size)) == NULL) ! 2288: { ! 2289: fprintf (stderr, "\nCan't reallocate %u bytes\n", size); ! 2290: exit (1); ! 2291: } ! 2292: return (newmem); ! 2293: } ! 2294: ! 2295: main (argc, argv) ! 2296: int argc; ! 2297: char **argv; ! 2298: { ! 2299: char mangled_name[128]; ! 2300: char *result; ! 2301: int c; ! 2302: extern char *optarg; ! 2303: extern int optind; ! 2304: ! 2305: while ((c = getopt (argc, argv, "s:?")) != EOF) ! 2306: { ! 2307: switch (c) ! 2308: { ! 2309: case '?': ! 2310: fprintf (stderr, "usage: demangle [-s style] [arg1 [arg2]] ...\n"); ! 2311: fprintf (stderr, "style = { gnu, lucid, cfront }\n"); ! 2312: fprintf (stderr, "reads args from stdin if none supplied\n"); ! 2313: exit (0); ! 2314: break; ! 2315: case 's': ! 2316: if (strcmp (optarg, "gnu") == 0) ! 2317: { ! 2318: current_demangling_style = gnu_demangling; ! 2319: } ! 2320: else if (strcmp (optarg, "lucid") == 0) ! 2321: { ! 2322: current_demangling_style = lucid_demangling; ! 2323: } ! 2324: else if (strcmp (optarg, "cfront") == 0) ! 2325: { ! 2326: current_demangling_style = cfront_demangling; ! 2327: } ! 2328: else ! 2329: { ! 2330: fprintf (stderr, "unknown demangling style `%s'\n", optarg); ! 2331: exit (1); ! 2332: } ! 2333: break; ! 2334: } ! 2335: } ! 2336: if (optind < argc) ! 2337: { ! 2338: for ( ; optind < argc; optind++) ! 2339: { ! 2340: demangle_it (argv[optind]); ! 2341: } ! 2342: } ! 2343: else ! 2344: { ! 2345: while (gets (mangled_name)) ! 2346: { ! 2347: demangle_it (mangled_name); ! 2348: } ! 2349: } ! 2350: } ! 2351: ! 2352: #endif /* main */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.