|
|
1.1 ! root 1: /* Demangler for GNU C++ ! 2: Copyright 1989, 1991, 1994, 1995 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., 59 Temple Place - Suite 330, ! 20: Boston, MA 02111-1307, USA. */ ! 21: ! 22: /* This file exports two functions; cplus_mangle_opname and cplus_demangle. ! 23: ! 24: This file imports xmalloc and xrealloc, which are like malloc and ! 25: realloc except that they generate a fatal error if there is no ! 26: available memory. */ ! 27: ! 28: #include <ctype.h> ! 29: #include <string.h> ! 30: #include <stdio.h> ! 31: ! 32: #include <demangle.h> ! 33: #undef CURRENT_DEMANGLING_STYLE ! 34: #define CURRENT_DEMANGLING_STYLE work->options ! 35: ! 36: extern char *xmalloc PARAMS((unsigned)); ! 37: extern char *xrealloc PARAMS((char *, unsigned)); ! 38: ! 39: char * ! 40: mystrstr (s1, s2) ! 41: char *s1, *s2; ! 42: { ! 43: register char *p = s1; ! 44: register int len = strlen (s2); ! 45: ! 46: for (; (p = strchr (p, *s2)) != 0; p++) ! 47: { ! 48: if (strncmp (p, s2, len) == 0) ! 49: { ! 50: return (p); ! 51: } ! 52: } ! 53: return (0); ! 54: } ! 55: ! 56: /* In order to allow a single demangler executable to demangle strings ! 57: using various common values of CPLUS_MARKER, as well as any specific ! 58: one set at compile time, we maintain a string containing all the ! 59: commonly used ones, and check to see if the marker we are looking for ! 60: is in that string. CPLUS_MARKER is usually '$' on systems where the ! 61: assembler can deal with that. Where the assembler can't, it's usually ! 62: '.' (but on many systems '.' is used for other things). We put the ! 63: current defined CPLUS_MARKER first (which defaults to '$'), followed ! 64: by the next most common value, followed by an explicit '$' in case ! 65: the value of CPLUS_MARKER is not '$'. ! 66: ! 67: We could avoid this if we could just get g++ to tell us what the actual ! 68: cplus marker character is as part of the debug information, perhaps by ! 69: ensuring that it is the character that terminates the gcc<n>_compiled ! 70: marker symbol (FIXME). */ ! 71: ! 72: #if !defined (CPLUS_MARKER) ! 73: #define CPLUS_MARKER '$' ! 74: #endif ! 75: ! 76: enum demangling_styles current_demangling_style = gnu_demangling; ! 77: ! 78: static char cplus_markers[] = { CPLUS_MARKER, '.', '$', '\0' }; ! 79: ! 80: void ! 81: set_cplus_marker_for_demangling (ch) ! 82: int ch; ! 83: { ! 84: cplus_markers[0] = ch; ! 85: } ! 86: ! 87: /* Stuff that is shared between sub-routines. ! 88: * Using a shared structure allows cplus_demangle to be reentrant. */ ! 89: ! 90: struct work_stuff ! 91: { ! 92: int options; ! 93: char **typevec; ! 94: int ntypes; ! 95: int typevec_size; ! 96: int constructor; ! 97: int destructor; ! 98: int static_type; /* A static member function */ ! 99: int const_type; /* A const member function */ ! 100: }; ! 101: ! 102: #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI) ! 103: #define PRINT_ARG_TYPES (work -> options & DMGL_PARAMS) ! 104: ! 105: static const struct optable ! 106: { ! 107: const char *in; ! 108: const char *out; ! 109: int flags; ! 110: } optable[] = { ! 111: {"nw", " new", DMGL_ANSI}, /* new (1.92, ansi) */ ! 112: {"dl", " delete", DMGL_ANSI}, /* new (1.92, ansi) */ ! 113: {"new", " new", 0}, /* old (1.91, and 1.x) */ ! 114: {"delete", " delete", 0}, /* old (1.91, and 1.x) */ ! 115: {"vn", " new []", DMGL_ANSI}, /* GNU, pending ansi */ ! 116: {"vd", " delete []", DMGL_ANSI}, /* GNU, pending ansi */ ! 117: {"as", "=", DMGL_ANSI}, /* ansi */ ! 118: {"ne", "!=", DMGL_ANSI}, /* old, ansi */ ! 119: {"eq", "==", DMGL_ANSI}, /* old, ansi */ ! 120: {"ge", ">=", DMGL_ANSI}, /* old, ansi */ ! 121: {"gt", ">", DMGL_ANSI}, /* old, ansi */ ! 122: {"le", "<=", DMGL_ANSI}, /* old, ansi */ ! 123: {"lt", "<", DMGL_ANSI}, /* old, ansi */ ! 124: {"plus", "+", 0}, /* old */ ! 125: {"pl", "+", DMGL_ANSI}, /* ansi */ ! 126: {"apl", "+=", DMGL_ANSI}, /* ansi */ ! 127: {"minus", "-", 0}, /* old */ ! 128: {"mi", "-", DMGL_ANSI}, /* ansi */ ! 129: {"ami", "-=", DMGL_ANSI}, /* ansi */ ! 130: {"mult", "*", 0}, /* old */ ! 131: {"ml", "*", DMGL_ANSI}, /* ansi */ ! 132: {"amu", "*=", DMGL_ANSI}, /* ansi (ARM/Lucid) */ ! 133: {"aml", "*=", DMGL_ANSI}, /* ansi (GNU/g++) */ ! 134: {"convert", "+", 0}, /* old (unary +) */ ! 135: {"negate", "-", 0}, /* old (unary -) */ ! 136: {"trunc_mod", "%", 0}, /* old */ ! 137: {"md", "%", DMGL_ANSI}, /* ansi */ ! 138: {"amd", "%=", DMGL_ANSI}, /* ansi */ ! 139: {"trunc_div", "/", 0}, /* old */ ! 140: {"dv", "/", DMGL_ANSI}, /* ansi */ ! 141: {"adv", "/=", DMGL_ANSI}, /* ansi */ ! 142: {"truth_andif", "&&", 0}, /* old */ ! 143: {"aa", "&&", DMGL_ANSI}, /* ansi */ ! 144: {"truth_orif", "||", 0}, /* old */ ! 145: {"oo", "||", DMGL_ANSI}, /* ansi */ ! 146: {"truth_not", "!", 0}, /* old */ ! 147: {"nt", "!", DMGL_ANSI}, /* ansi */ ! 148: {"postincrement","++", 0}, /* old */ ! 149: {"pp", "++", DMGL_ANSI}, /* ansi */ ! 150: {"postdecrement","--", 0}, /* old */ ! 151: {"mm", "--", DMGL_ANSI}, /* ansi */ ! 152: {"bit_ior", "|", 0}, /* old */ ! 153: {"or", "|", DMGL_ANSI}, /* ansi */ ! 154: {"aor", "|=", DMGL_ANSI}, /* ansi */ ! 155: {"bit_xor", "^", 0}, /* old */ ! 156: {"er", "^", DMGL_ANSI}, /* ansi */ ! 157: {"aer", "^=", DMGL_ANSI}, /* ansi */ ! 158: {"bit_and", "&", 0}, /* old */ ! 159: {"ad", "&", DMGL_ANSI}, /* ansi */ ! 160: {"aad", "&=", DMGL_ANSI}, /* ansi */ ! 161: {"bit_not", "~", 0}, /* old */ ! 162: {"co", "~", DMGL_ANSI}, /* ansi */ ! 163: {"call", "()", 0}, /* old */ ! 164: {"cl", "()", DMGL_ANSI}, /* ansi */ ! 165: {"alshift", "<<", 0}, /* old */ ! 166: {"ls", "<<", DMGL_ANSI}, /* ansi */ ! 167: {"als", "<<=", DMGL_ANSI}, /* ansi */ ! 168: {"arshift", ">>", 0}, /* old */ ! 169: {"rs", ">>", DMGL_ANSI}, /* ansi */ ! 170: {"ars", ">>=", DMGL_ANSI}, /* ansi */ ! 171: {"component", "->", 0}, /* old */ ! 172: {"pt", "->", DMGL_ANSI}, /* ansi; Lucid C++ form */ ! 173: {"rf", "->", DMGL_ANSI}, /* ansi; ARM/GNU form */ ! 174: {"indirect", "*", 0}, /* old */ ! 175: {"method_call", "->()", 0}, /* old */ ! 176: {"addr", "&", 0}, /* old (unary &) */ ! 177: {"array", "[]", 0}, /* old */ ! 178: {"vc", "[]", DMGL_ANSI}, /* ansi */ ! 179: {"compound", ", ", 0}, /* old */ ! 180: {"cm", ", ", DMGL_ANSI}, /* ansi */ ! 181: {"cond", "?:", 0}, /* old */ ! 182: {"cn", "?:", DMGL_ANSI}, /* pseudo-ansi */ ! 183: {"max", ">?", 0}, /* old */ ! 184: {"mx", ">?", DMGL_ANSI}, /* pseudo-ansi */ ! 185: {"min", "<?", 0}, /* old */ ! 186: {"mn", "<?", DMGL_ANSI}, /* pseudo-ansi */ ! 187: {"nop", "", 0}, /* old (for operator=) */ ! 188: {"rm", "->*", DMGL_ANSI} /* ansi */ ! 189: }; ! 190: ! 191: ! 192: typedef struct string /* Beware: these aren't required to be */ ! 193: { /* '\0' terminated. */ ! 194: char *b; /* pointer to start of string */ ! 195: char *p; /* pointer after last character */ ! 196: char *e; /* pointer after end of allocated space */ ! 197: } string; ! 198: ! 199: #define STRING_EMPTY(str) ((str) -> b == (str) -> p) ! 200: #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ ! 201: string_prepend(str, " ");} ! 202: #define APPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ ! 203: string_append(str, " ");} ! 204: ! 205: #define ARM_VTABLE_STRING "__vtbl__" /* Lucid/ARM virtual table prefix */ ! 206: #define ARM_VTABLE_STRLEN 8 /* strlen (ARM_VTABLE_STRING) */ ! 207: ! 208: /* Prototypes for local functions */ ! 209: ! 210: static char * ! 211: mop_up PARAMS ((struct work_stuff *, string *, int)); ! 212: ! 213: #if 0 ! 214: static int ! 215: demangle_method_args PARAMS ((struct work_stuff *work, const char **, string *)); ! 216: #endif ! 217: ! 218: static int ! 219: demangle_template PARAMS ((struct work_stuff *work, const char **, string *, ! 220: string *)); ! 221: ! 222: static int ! 223: demangle_qualified PARAMS ((struct work_stuff *, const char **, string *, ! 224: int, int)); ! 225: ! 226: static int ! 227: demangle_class PARAMS ((struct work_stuff *, const char **, string *)); ! 228: ! 229: static int ! 230: demangle_fund_type PARAMS ((struct work_stuff *, const char **, string *)); ! 231: ! 232: static int ! 233: demangle_signature PARAMS ((struct work_stuff *, const char **, string *)); ! 234: ! 235: static int ! 236: demangle_prefix PARAMS ((struct work_stuff *, const char **, string *)); ! 237: ! 238: static int ! 239: gnu_special PARAMS ((struct work_stuff *, const char **, string *)); ! 240: ! 241: static int ! 242: arm_special PARAMS ((struct work_stuff *, const char **, string *)); ! 243: ! 244: static void ! 245: string_need PARAMS ((string *, int)); ! 246: ! 247: static void ! 248: string_delete PARAMS ((string *)); ! 249: ! 250: static void ! 251: string_init PARAMS ((string *)); ! 252: ! 253: static void ! 254: string_clear PARAMS ((string *)); ! 255: ! 256: #if 0 ! 257: static int ! 258: string_empty PARAMS ((string *)); ! 259: #endif ! 260: ! 261: static void ! 262: string_append PARAMS ((string *, const char *)); ! 263: ! 264: static void ! 265: string_appends PARAMS ((string *, string *)); ! 266: ! 267: static void ! 268: string_appendn PARAMS ((string *, const char *, int)); ! 269: ! 270: static void ! 271: string_prepend PARAMS ((string *, const char *)); ! 272: ! 273: static void ! 274: string_prependn PARAMS ((string *, const char *, int)); ! 275: ! 276: static int ! 277: get_count PARAMS ((const char **, int *)); ! 278: ! 279: static int ! 280: consume_count PARAMS ((const char **)); ! 281: ! 282: static int ! 283: demangle_args PARAMS ((struct work_stuff *, const char **, string *)); ! 284: ! 285: static int ! 286: do_type PARAMS ((struct work_stuff *, const char **, string *)); ! 287: ! 288: static int ! 289: do_arg PARAMS ((struct work_stuff *, const char **, string *)); ! 290: ! 291: static void ! 292: demangle_function_name PARAMS ((struct work_stuff *, const char **, string *, ! 293: const char *)); ! 294: ! 295: static void ! 296: remember_type PARAMS ((struct work_stuff *, const char *, int)); ! 297: ! 298: static void ! 299: forget_types PARAMS ((struct work_stuff *)); ! 300: ! 301: static void ! 302: string_prepends PARAMS ((string *, string *)); ! 303: ! 304: /* Translate count to integer, consuming tokens in the process. ! 305: Conversion terminates on the first non-digit character. ! 306: Trying to consume something that isn't a count results in ! 307: no consumption of input and a return of 0. */ ! 308: ! 309: static int ! 310: consume_count (type) ! 311: const char **type; ! 312: { ! 313: int count = 0; ! 314: ! 315: while (isdigit (**type)) ! 316: { ! 317: count *= 10; ! 318: count += **type - '0'; ! 319: (*type)++; ! 320: } ! 321: return (count); ! 322: } ! 323: ! 324: int ! 325: cplus_demangle_opname (opname, result, options) ! 326: char *opname; ! 327: char *result; ! 328: int options; ! 329: { ! 330: int len, i, len1, ret; ! 331: string type; ! 332: struct work_stuff work[1]; ! 333: const char *tem; ! 334: ! 335: len = strlen(opname); ! 336: result[0] = '\0'; ! 337: ret = 0; ! 338: work->options = options; ! 339: ! 340: if (opname[0] == '_' && opname[1] == '_' ! 341: && opname[2] == 'o' && opname[3] == 'p') ! 342: { ! 343: /* ANSI. */ ! 344: /* type conversion operator. */ ! 345: tem = opname + 4; ! 346: if (do_type (work, &tem, &type)) ! 347: { ! 348: strcat (result, "operator "); ! 349: strncat (result, type.b, type.p - type.b); ! 350: string_delete (&type); ! 351: ret = 1; ! 352: } ! 353: } ! 354: else if (opname[0] == '_' && opname[1] == '_' ! 355: && opname[2] >= 'a' && opname[2] <= 'z' ! 356: && opname[3] >= 'a' && opname[3] <= 'z') ! 357: { ! 358: if (opname[4] == '\0') ! 359: { ! 360: /* Operator. */ ! 361: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 362: { ! 363: if (strlen (optable[i].in) == 2 ! 364: && memcmp (optable[i].in, opname + 2, 2) == 0) ! 365: { ! 366: strcat (result, "operator"); ! 367: strcat (result, optable[i].out); ! 368: ret = 1; ! 369: break; ! 370: } ! 371: } ! 372: } ! 373: else ! 374: { ! 375: if (opname[2] == 'a' && opname[5] == '\0') ! 376: { ! 377: /* Assignment. */ ! 378: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 379: { ! 380: if (strlen (optable[i].in) == 3 ! 381: && memcmp (optable[i].in, opname + 2, 3) == 0) ! 382: { ! 383: strcat (result, "operator"); ! 384: strcat (result, optable[i].out); ! 385: ret = 1; ! 386: break; ! 387: } ! 388: } ! 389: } ! 390: } ! 391: } ! 392: else if (len >= 3 ! 393: && opname[0] == 'o' ! 394: && opname[1] == 'p' ! 395: && strchr (cplus_markers, opname[2]) != NULL) ! 396: { ! 397: /* see if it's an assignment expression */ ! 398: if (len >= 10 /* op$assign_ */ ! 399: && memcmp (opname + 3, "assign_", 7) == 0) ! 400: { ! 401: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 402: { ! 403: len1 = len - 10; ! 404: if (strlen (optable[i].in) == len1 ! 405: && memcmp (optable[i].in, opname + 10, len1) == 0) ! 406: { ! 407: strcat (result, "operator"); ! 408: strcat (result, optable[i].out); ! 409: strcat (result, "="); ! 410: ret = 1; ! 411: break; ! 412: } ! 413: } ! 414: } ! 415: else ! 416: { ! 417: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 418: { ! 419: len1 = len - 3; ! 420: if (strlen (optable[i].in) == len1 ! 421: && memcmp (optable[i].in, opname + 3, len1) == 0) ! 422: { ! 423: strcat (result, "operator"); ! 424: strcat (result, optable[i].out); ! 425: ret = 1; ! 426: break; ! 427: } ! 428: } ! 429: } ! 430: } ! 431: else if (len >= 5 && memcmp (opname, "type", 4) == 0 ! 432: && strchr (cplus_markers, opname[4]) != NULL) ! 433: { ! 434: /* type conversion operator */ ! 435: tem = opname + 5; ! 436: if (do_type (work, &tem, &type)) ! 437: { ! 438: strcat (result, "operator "); ! 439: strncat (result, type.b, type.p - type.b); ! 440: string_delete (&type); ! 441: ret = 1; ! 442: } ! 443: } ! 444: return ret; ! 445: ! 446: } ! 447: /* Takes operator name as e.g. "++" and returns mangled ! 448: operator name (e.g. "postincrement_expr"), or NULL if not found. ! 449: ! 450: If OPTIONS & DMGL_ANSI == 1, return the ANSI name; ! 451: if OPTIONS & DMGL_ANSI == 0, return the old GNU name. */ ! 452: ! 453: char * ! 454: cplus_mangle_opname (opname, options) ! 455: char *opname; ! 456: int options; ! 457: { ! 458: int i; ! 459: int len; ! 460: ! 461: len = strlen (opname); ! 462: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 463: { ! 464: if (strlen (optable[i].out) == len ! 465: && (options & DMGL_ANSI) == (optable[i].flags & DMGL_ANSI) ! 466: && memcmp (optable[i].out, opname, len) == 0) ! 467: return ((char *)optable[i].in); ! 468: } ! 469: return (0); ! 470: } ! 471: ! 472: /* check to see whether MANGLED can match TEXT in the first TEXT_LEN ! 473: characters. */ ! 474: ! 475: int cplus_match (mangled, text, text_len) ! 476: const char *mangled; ! 477: char *text; ! 478: int text_len; ! 479: { ! 480: if (strncmp (mangled, text, text_len) != 0) { ! 481: return(0); /* cannot match either */ ! 482: } else { ! 483: return(1); /* matches mangled, may match demangled */ ! 484: } ! 485: } ! 486: ! 487: /* char *cplus_demangle (const char *mangled, int options) ! 488: ! 489: If MANGLED is a mangled function name produced by GNU C++, then ! 490: a pointer to a malloced string giving a C++ representation ! 491: of the name will be returned; otherwise NULL will be returned. ! 492: It is the caller's responsibility to free the string which ! 493: is returned. ! 494: ! 495: The OPTIONS arg may contain one or more of the following bits: ! 496: ! 497: DMGL_ANSI ANSI qualifiers such as `const' and `void' are ! 498: included. ! 499: DMGL_PARAMS Function parameters are included. ! 500: ! 501: For example, ! 502: ! 503: cplus_demangle ("foo__1Ai", DMGL_PARAMS) => "A::foo(int)" ! 504: cplus_demangle ("foo__1Ai", DMGL_PARAMS | DMGL_ANSI) => "A::foo(int)" ! 505: cplus_demangle ("foo__1Ai", 0) => "A::foo" ! 506: ! 507: cplus_demangle ("foo__1Afe", DMGL_PARAMS) => "A::foo(float,...)" ! 508: cplus_demangle ("foo__1Afe", DMGL_PARAMS | DMGL_ANSI)=> "A::foo(float,...)" ! 509: cplus_demangle ("foo__1Afe", 0) => "A::foo" ! 510: ! 511: Note that any leading underscores, or other such characters prepended by ! 512: the compilation system, are presumed to have already been stripped from ! 513: MANGLED. */ ! 514: ! 515: char * ! 516: cplus_demangle (mangled, options) ! 517: const char *mangled; ! 518: int options; ! 519: { ! 520: string decl; ! 521: int success = 0; ! 522: struct work_stuff work[1]; ! 523: char *demangled = NULL; ! 524: ! 525: if ((mangled != NULL) && (*mangled != '\0')) ! 526: { ! 527: memset ((char *) work, 0, sizeof (work)); ! 528: work -> options = options; ! 529: if ((work->options & DMGL_STYLE_MASK) == 0) ! 530: work->options |= (int)current_demangling_style & DMGL_STYLE_MASK; ! 531: ! 532: string_init (&decl); ! 533: ! 534: /* First check to see if gnu style demangling is active and if the ! 535: string to be demangled contains a CPLUS_MARKER. If so, attempt to ! 536: recognize one of the gnu special forms rather than looking for a ! 537: standard prefix. In particular, don't worry about whether there ! 538: is a "__" string in the mangled string. Consider "_$_5__foo" for ! 539: example. */ ! 540: ! 541: if ((AUTO_DEMANGLING || GNU_DEMANGLING)) ! 542: { ! 543: success = gnu_special (work, &mangled, &decl); ! 544: } ! 545: if (!success) ! 546: { ! 547: success = demangle_prefix (work, &mangled, &decl); ! 548: } ! 549: if (success && (*mangled != '\0')) ! 550: { ! 551: success = demangle_signature (work, &mangled, &decl); ! 552: } ! 553: if (work->constructor == 2) ! 554: { ! 555: string_prepend(&decl, "global constructors keyed to "); ! 556: work->constructor = 0; ! 557: } ! 558: else if (work->destructor == 2) ! 559: { ! 560: string_prepend(&decl, "global destructors keyed to "); ! 561: work->destructor = 0; ! 562: } ! 563: demangled = mop_up (work, &decl, success); ! 564: } ! 565: return (demangled); ! 566: } ! 567: ! 568: static char * ! 569: mop_up (work, declp, success) ! 570: struct work_stuff *work; ! 571: string *declp; ! 572: int success; ! 573: { ! 574: char *demangled = NULL; ! 575: ! 576: /* Discard the remembered types, if any. */ ! 577: ! 578: forget_types (work); ! 579: if (work -> typevec != NULL) ! 580: { ! 581: free ((char *) work -> typevec); ! 582: } ! 583: ! 584: /* If demangling was successful, ensure that the demangled string is null ! 585: terminated and return it. Otherwise, free the demangling decl. */ ! 586: ! 587: if (!success) ! 588: { ! 589: string_delete (declp); ! 590: } ! 591: else ! 592: { ! 593: string_appendn (declp, "", 1); ! 594: demangled = declp -> b; ! 595: } ! 596: return (demangled); ! 597: } ! 598: ! 599: /* ! 600: ! 601: LOCAL FUNCTION ! 602: ! 603: demangle_signature -- demangle the signature part of a mangled name ! 604: ! 605: SYNOPSIS ! 606: ! 607: static int ! 608: demangle_signature (struct work_stuff *work, const char **mangled, ! 609: string *declp); ! 610: ! 611: DESCRIPTION ! 612: ! 613: Consume and demangle the signature portion of the mangled name. ! 614: ! 615: DECLP is the string where demangled output is being built. At ! 616: entry it contains the demangled root name from the mangled name ! 617: prefix. I.E. either a demangled operator name or the root function ! 618: name. In some special cases, it may contain nothing. ! 619: ! 620: *MANGLED points to the current unconsumed location in the mangled ! 621: name. As tokens are consumed and demangling is performed, the ! 622: pointer is updated to continuously point at the next token to ! 623: be consumed. ! 624: ! 625: Demangling GNU style mangled names is nasty because there is no ! 626: explicit token that marks the start of the outermost function ! 627: argument list. ! 628: */ ! 629: ! 630: static int ! 631: demangle_signature (work, mangled, declp) ! 632: struct work_stuff *work; ! 633: const char **mangled; ! 634: string *declp; ! 635: { ! 636: int success = 1; ! 637: int func_done = 0; ! 638: int expect_func = 0; ! 639: const char *oldmangled = NULL; ! 640: string trawname; ! 641: string tname; ! 642: ! 643: while (success && (**mangled != '\0')) ! 644: { ! 645: switch (**mangled) ! 646: { ! 647: case 'Q': ! 648: oldmangled = *mangled; ! 649: success = demangle_qualified (work, mangled, declp, 1, 0); ! 650: if (success) ! 651: { ! 652: remember_type (work, oldmangled, *mangled - oldmangled); ! 653: } ! 654: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 655: { ! 656: expect_func = 1; ! 657: } ! 658: oldmangled = NULL; ! 659: break; ! 660: ! 661: case 'S': ! 662: /* Static member function */ ! 663: if (oldmangled == NULL) ! 664: { ! 665: oldmangled = *mangled; ! 666: } ! 667: (*mangled)++; ! 668: work -> static_type = 1; ! 669: break; ! 670: ! 671: case 'C': ! 672: /* a const member function */ ! 673: if (oldmangled == NULL) ! 674: { ! 675: oldmangled = *mangled; ! 676: } ! 677: (*mangled)++; ! 678: work -> const_type = 1; ! 679: break; ! 680: ! 681: case '0': case '1': case '2': case '3': case '4': ! 682: case '5': case '6': case '7': case '8': case '9': ! 683: if (oldmangled == NULL) ! 684: { ! 685: oldmangled = *mangled; ! 686: } ! 687: success = demangle_class (work, mangled, declp); ! 688: if (success) ! 689: { ! 690: remember_type (work, oldmangled, *mangled - oldmangled); ! 691: } ! 692: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 693: { ! 694: expect_func = 1; ! 695: } ! 696: oldmangled = NULL; ! 697: break; ! 698: ! 699: case 'F': ! 700: /* Function */ ! 701: /* ARM style demangling includes a specific 'F' character after ! 702: the class name. For GNU style, it is just implied. So we can ! 703: safely just consume any 'F' at this point and be compatible ! 704: with either style. */ ! 705: ! 706: oldmangled = NULL; ! 707: func_done = 1; ! 708: (*mangled)++; ! 709: ! 710: /* For lucid/ARM style we have to forget any types we might ! 711: have remembered up to this point, since they were not argument ! 712: types. GNU style considers all types seen as available for ! 713: back references. See comment in demangle_args() */ ! 714: ! 715: if (LUCID_DEMANGLING || ARM_DEMANGLING) ! 716: { ! 717: forget_types (work); ! 718: } ! 719: success = demangle_args (work, mangled, declp); ! 720: break; ! 721: ! 722: case 't': ! 723: /* G++ Template */ ! 724: string_init(&trawname); ! 725: string_init(&tname); ! 726: if (oldmangled == NULL) ! 727: { ! 728: oldmangled = *mangled; ! 729: } ! 730: success = demangle_template (work, mangled, &tname, &trawname); ! 731: if (success) ! 732: { ! 733: remember_type (work, oldmangled, *mangled - oldmangled); ! 734: } ! 735: string_append(&tname, "::"); ! 736: string_prepends(declp, &tname); ! 737: if (work -> destructor & 1) ! 738: { ! 739: string_prepend (&trawname, "~"); ! 740: string_appends (declp, &trawname); ! 741: work->destructor -= 1; ! 742: } ! 743: if ((work->constructor & 1) || (work->destructor & 1)) ! 744: { ! 745: string_appends (declp, &trawname); ! 746: work->constructor -= 1; ! 747: } ! 748: string_delete(&trawname); ! 749: string_delete(&tname); ! 750: oldmangled = NULL; ! 751: expect_func = 1; ! 752: break; ! 753: ! 754: case '_': ! 755: /* At the outermost level, we cannot have a return type specified, ! 756: so if we run into another '_' at this point we are dealing with ! 757: a mangled name that is either bogus, or has been mangled by ! 758: some algorithm we don't know how to deal with. So just ! 759: reject the entire demangling. */ ! 760: success = 0; ! 761: break; ! 762: ! 763: default: ! 764: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 765: { ! 766: /* Assume we have stumbled onto the first outermost function ! 767: argument token, and start processing args. */ ! 768: func_done = 1; ! 769: success = demangle_args (work, mangled, declp); ! 770: } ! 771: else ! 772: { ! 773: /* Non-GNU demanglers use a specific token to mark the start ! 774: of the outermost function argument tokens. Typically 'F', ! 775: for ARM-demangling, for example. So if we find something ! 776: we are not prepared for, it must be an error. */ ! 777: success = 0; ! 778: } ! 779: break; ! 780: } ! 781: /* ! 782: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 783: */ ! 784: { ! 785: if (success && expect_func) ! 786: { ! 787: func_done = 1; ! 788: success = demangle_args (work, mangled, declp); ! 789: } ! 790: } ! 791: } ! 792: if (success && !func_done) ! 793: { ! 794: if (AUTO_DEMANGLING || GNU_DEMANGLING) ! 795: { ! 796: /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and ! 797: bar__3fooi is 'foo::bar(int)'. We get here when we find the ! 798: first case, and need to ensure that the '(void)' gets added to ! 799: the current declp. Note that with ARM, the first case ! 800: represents the name of a static data member 'foo::bar', ! 801: which is in the current declp, so we leave it alone. */ ! 802: success = demangle_args (work, mangled, declp); ! 803: } ! 804: } ! 805: if (success && work -> static_type && PRINT_ARG_TYPES) ! 806: { ! 807: string_append (declp, " static"); ! 808: } ! 809: if (success && work -> const_type && PRINT_ARG_TYPES) ! 810: { ! 811: string_append (declp, " const"); ! 812: } ! 813: return (success); ! 814: } ! 815: ! 816: #if 0 ! 817: ! 818: static int ! 819: demangle_method_args (work, mangled, declp) ! 820: struct work_stuff *work; ! 821: const char **mangled; ! 822: string *declp; ! 823: { ! 824: int success = 0; ! 825: ! 826: if (work -> static_type) ! 827: { ! 828: string_append (declp, *mangled + 1); ! 829: *mangled += strlen (*mangled); ! 830: success = 1; ! 831: } ! 832: else ! 833: { ! 834: success = demangle_args (work, mangled, declp); ! 835: } ! 836: return (success); ! 837: } ! 838: ! 839: #endif ! 840: ! 841: static int ! 842: demangle_template (work, mangled, tname, trawname) ! 843: struct work_stuff *work; ! 844: const char **mangled; ! 845: string *tname; ! 846: string *trawname; ! 847: { ! 848: int i; ! 849: int is_pointer; ! 850: int is_real; ! 851: int is_integral; ! 852: int is_char; ! 853: int is_bool; ! 854: int r; ! 855: int need_comma = 0; ! 856: int success = 0; ! 857: int done; ! 858: const char *old_p; ! 859: const char *start; ! 860: int symbol_len; ! 861: string temp; ! 862: ! 863: (*mangled)++; ! 864: start = *mangled; ! 865: /* get template name */ ! 866: if ((r = consume_count (mangled)) == 0 || strlen (*mangled) < r) ! 867: { ! 868: return (0); ! 869: } ! 870: if (trawname) ! 871: string_appendn (trawname, *mangled, r); ! 872: string_appendn (tname, *mangled, r); ! 873: *mangled += r; ! 874: string_append (tname, "<"); ! 875: /* get size of template parameter list */ ! 876: if (!get_count (mangled, &r)) ! 877: { ! 878: return (0); ! 879: } ! 880: for (i = 0; i < r; i++) ! 881: { ! 882: if (need_comma) ! 883: { ! 884: string_append (tname, ", "); ! 885: } ! 886: /* Z for type parameters */ ! 887: if (**mangled == 'Z') ! 888: { ! 889: (*mangled)++; ! 890: /* temp is initialized in do_type */ ! 891: success = do_type (work, mangled, &temp); ! 892: if (success) ! 893: { ! 894: string_appends (tname, &temp); ! 895: } ! 896: string_delete(&temp); ! 897: if (!success) ! 898: { ! 899: break; ! 900: } ! 901: } ! 902: else ! 903: { ! 904: /* otherwise, value parameter */ ! 905: old_p = *mangled; ! 906: is_pointer = 0; ! 907: is_real = 0; ! 908: is_integral = 0; ! 909: is_char = 0; ! 910: done = 0; ! 911: /* temp is initialized in do_type */ ! 912: success = do_type (work, mangled, &temp); ! 913: /* ! 914: if (success) ! 915: { ! 916: string_appends (tname, &temp); ! 917: } ! 918: */ ! 919: string_delete(&temp); ! 920: if (!success) ! 921: { ! 922: break; ! 923: } ! 924: /* ! 925: string_append (tname, "="); ! 926: */ ! 927: while (*old_p && !done) ! 928: { ! 929: switch (*old_p) ! 930: { ! 931: case 'P': ! 932: case 'p': ! 933: case 'R': ! 934: done = is_pointer = 1; ! 935: break; ! 936: case 'C': /* const */ ! 937: case 'S': /* explicitly signed [char] */ ! 938: case 'U': /* unsigned */ ! 939: case 'V': /* volatile */ ! 940: case 'F': /* function */ ! 941: case 'M': /* member function */ ! 942: case 'O': /* ??? */ ! 943: old_p++; ! 944: continue; ! 945: case 'Q': /* qualified name */ ! 946: done = is_integral = 1; ! 947: break; ! 948: case 'T': /* remembered type */ ! 949: abort (); ! 950: break; ! 951: case 'v': /* void */ ! 952: abort (); ! 953: break; ! 954: case 'x': /* long long */ ! 955: case 'l': /* long */ ! 956: case 'i': /* int */ ! 957: case 's': /* short */ ! 958: case 'w': /* wchar_t */ ! 959: done = is_integral = 1; ! 960: break; ! 961: case 'b': /* bool */ ! 962: done = is_bool = 1; ! 963: break; ! 964: case 'c': /* char */ ! 965: done = is_char = 1; ! 966: break; ! 967: case 'r': /* long double */ ! 968: case 'd': /* double */ ! 969: case 'f': /* float */ ! 970: done = is_real = 1; ! 971: break; ! 972: default: ! 973: /* it's probably user defined type, let's assume ! 974: it's integral, it seems hard to figure out ! 975: what it really is */ ! 976: done = is_integral = 1; ! 977: } ! 978: } ! 979: if (is_integral) ! 980: { ! 981: if (**mangled == 'm') ! 982: { ! 983: string_appendn (tname, "-", 1); ! 984: (*mangled)++; ! 985: } ! 986: while (isdigit (**mangled)) ! 987: { ! 988: string_appendn (tname, *mangled, 1); ! 989: (*mangled)++; ! 990: } ! 991: } ! 992: else if (is_char) ! 993: { ! 994: char tmp[2]; ! 995: int val; ! 996: if (**mangled == 'm') ! 997: { ! 998: string_appendn (tname, "-", 1); ! 999: (*mangled)++; ! 1000: } ! 1001: string_appendn (tname, "'", 1); ! 1002: val = consume_count(mangled); ! 1003: if (val == 0) ! 1004: { ! 1005: success = 0; ! 1006: break; ! 1007: } ! 1008: tmp[0] = (char)val; ! 1009: tmp[1] = '\0'; ! 1010: string_appendn (tname, &tmp[0], 1); ! 1011: string_appendn (tname, "'", 1); ! 1012: } ! 1013: else if (is_bool) ! 1014: { ! 1015: int val = consume_count (mangled); ! 1016: if (val == 0) ! 1017: string_appendn (tname, "false", 5); ! 1018: else if (val == 1) ! 1019: string_appendn (tname, "true", 4); ! 1020: else ! 1021: success = 0; ! 1022: } ! 1023: else if (is_real) ! 1024: { ! 1025: if (**mangled == 'm') ! 1026: { ! 1027: string_appendn (tname, "-", 1); ! 1028: (*mangled)++; ! 1029: } ! 1030: while (isdigit (**mangled)) ! 1031: { ! 1032: string_appendn (tname, *mangled, 1); ! 1033: (*mangled)++; ! 1034: } ! 1035: if (**mangled == '.') /* fraction */ ! 1036: { ! 1037: string_appendn (tname, ".", 1); ! 1038: (*mangled)++; ! 1039: while (isdigit (**mangled)) ! 1040: { ! 1041: string_appendn (tname, *mangled, 1); ! 1042: (*mangled)++; ! 1043: } ! 1044: } ! 1045: if (**mangled == 'e') /* exponent */ ! 1046: { ! 1047: string_appendn (tname, "e", 1); ! 1048: (*mangled)++; ! 1049: while (isdigit (**mangled)) ! 1050: { ! 1051: string_appendn (tname, *mangled, 1); ! 1052: (*mangled)++; ! 1053: } ! 1054: } ! 1055: } ! 1056: else if (is_pointer) ! 1057: { ! 1058: if (!get_count (mangled, &symbol_len)) ! 1059: { ! 1060: success = 0; ! 1061: break; ! 1062: } ! 1063: string_appendn (tname, *mangled, symbol_len); ! 1064: *mangled += symbol_len; ! 1065: } ! 1066: } ! 1067: need_comma = 1; ! 1068: } ! 1069: if (tname->p[-1] == '>') ! 1070: string_append (tname, " "); ! 1071: string_append (tname, ">"); ! 1072: ! 1073: /* ! 1074: if (work -> static_type) ! 1075: { ! 1076: string_append (declp, *mangled + 1); ! 1077: *mangled += strlen (*mangled); ! 1078: success = 1; ! 1079: } ! 1080: else ! 1081: { ! 1082: success = demangle_args (work, mangled, declp); ! 1083: } ! 1084: } ! 1085: */ ! 1086: return (success); ! 1087: } ! 1088: ! 1089: static int ! 1090: arm_pt (work, mangled, n, anchor, args) ! 1091: struct work_stuff *work; ! 1092: const char *mangled; ! 1093: int n; ! 1094: const char **anchor, **args; ! 1095: { ! 1096: /* ARM template? */ ! 1097: if (ARM_DEMANGLING && (*anchor = mystrstr (mangled, "__pt__"))) ! 1098: { ! 1099: int len; ! 1100: *args = *anchor + 6; ! 1101: len = consume_count (args); ! 1102: if (*args + len == mangled + n && **args == '_') ! 1103: { ! 1104: ++*args; ! 1105: return 1; ! 1106: } ! 1107: } ! 1108: return 0; ! 1109: } ! 1110: ! 1111: static void ! 1112: demangle_arm_pt (work, mangled, n, declp) ! 1113: struct work_stuff *work; ! 1114: const char **mangled; ! 1115: int n; ! 1116: string *declp; ! 1117: { ! 1118: const char *p; ! 1119: const char *args; ! 1120: const char *e = *mangled + n; ! 1121: ! 1122: /* ARM template? */ ! 1123: if (arm_pt (work, *mangled, n, &p, &args)) ! 1124: { ! 1125: string arg; ! 1126: string_init (&arg); ! 1127: string_appendn (declp, *mangled, p - *mangled); ! 1128: string_append (declp, "<"); ! 1129: /* should do error checking here */ ! 1130: while (args < e) { ! 1131: string_clear (&arg); ! 1132: do_type (work, &args, &arg); ! 1133: string_appends (declp, &arg); ! 1134: string_append (declp, ","); ! 1135: } ! 1136: string_delete (&arg); ! 1137: --declp->p; ! 1138: string_append (declp, ">"); ! 1139: } ! 1140: else ! 1141: { ! 1142: string_appendn (declp, *mangled, n); ! 1143: } ! 1144: *mangled += n; ! 1145: } ! 1146: ! 1147: static int ! 1148: demangle_class_name (work, mangled, declp) ! 1149: struct work_stuff *work; ! 1150: const char **mangled; ! 1151: string *declp; ! 1152: { ! 1153: int n; ! 1154: int success = 0; ! 1155: ! 1156: n = consume_count (mangled); ! 1157: if (strlen (*mangled) >= n) ! 1158: { ! 1159: demangle_arm_pt (work, mangled, n, declp); ! 1160: success = 1; ! 1161: } ! 1162: ! 1163: return (success); ! 1164: } ! 1165: ! 1166: /* ! 1167: ! 1168: LOCAL FUNCTION ! 1169: ! 1170: demangle_class -- demangle a mangled class sequence ! 1171: ! 1172: SYNOPSIS ! 1173: ! 1174: static int ! 1175: demangle_class (struct work_stuff *work, const char **mangled, ! 1176: strint *declp) ! 1177: ! 1178: DESCRIPTION ! 1179: ! 1180: DECLP points to the buffer into which demangling is being done. ! 1181: ! 1182: *MANGLED points to the current token to be demangled. On input, ! 1183: it points to a mangled class (I.E. "3foo", "13verylongclass", etc.) ! 1184: On exit, it points to the next token after the mangled class on ! 1185: success, or the first unconsumed token on failure. ! 1186: ! 1187: If the CONSTRUCTOR or DESTRUCTOR flags are set in WORK, then ! 1188: we are demangling a constructor or destructor. In this case ! 1189: we prepend "class::class" or "class::~class" to DECLP. ! 1190: ! 1191: Otherwise, we prepend "class::" to the current DECLP. ! 1192: ! 1193: Reset the constructor/destructor flags once they have been ! 1194: "consumed". This allows demangle_class to be called later during ! 1195: the same demangling, to do normal class demangling. ! 1196: ! 1197: Returns 1 if demangling is successful, 0 otherwise. ! 1198: ! 1199: */ ! 1200: ! 1201: static int ! 1202: demangle_class (work, mangled, declp) ! 1203: struct work_stuff *work; ! 1204: const char **mangled; ! 1205: string *declp; ! 1206: { ! 1207: int success = 0; ! 1208: string class_name; ! 1209: ! 1210: string_init (&class_name); ! 1211: if (demangle_class_name (work, mangled, &class_name)) ! 1212: { ! 1213: if ((work->constructor & 1) || (work->destructor & 1)) ! 1214: { ! 1215: string_prepends (declp, &class_name); ! 1216: if (work -> destructor & 1) ! 1217: { ! 1218: string_prepend (declp, "~"); ! 1219: work -> destructor -= 1; ! 1220: } ! 1221: else ! 1222: { ! 1223: work -> constructor -= 1; ! 1224: } ! 1225: } ! 1226: string_prepend (declp, "::"); ! 1227: string_prepends (declp, &class_name); ! 1228: success = 1; ! 1229: } ! 1230: string_delete (&class_name); ! 1231: return (success); ! 1232: } ! 1233: ! 1234: /* ! 1235: ! 1236: LOCAL FUNCTION ! 1237: ! 1238: demangle_prefix -- consume the mangled name prefix and find signature ! 1239: ! 1240: SYNOPSIS ! 1241: ! 1242: static int ! 1243: demangle_prefix (struct work_stuff *work, const char **mangled, ! 1244: string *declp); ! 1245: ! 1246: DESCRIPTION ! 1247: ! 1248: Consume and demangle the prefix of the mangled name. ! 1249: ! 1250: DECLP points to the string buffer into which demangled output is ! 1251: placed. On entry, the buffer is empty. On exit it contains ! 1252: the root function name, the demangled operator name, or in some ! 1253: special cases either nothing or the completely demangled result. ! 1254: ! 1255: MANGLED points to the current pointer into the mangled name. As each ! 1256: token of the mangled name is consumed, it is updated. Upon entry ! 1257: the current mangled name pointer points to the first character of ! 1258: the mangled name. Upon exit, it should point to the first character ! 1259: of the signature if demangling was successful, or to the first ! 1260: unconsumed character if demangling of the prefix was unsuccessful. ! 1261: ! 1262: Returns 1 on success, 0 otherwise. ! 1263: */ ! 1264: ! 1265: static int ! 1266: demangle_prefix (work, mangled, declp) ! 1267: struct work_stuff *work; ! 1268: const char **mangled; ! 1269: string *declp; ! 1270: { ! 1271: int success = 1; ! 1272: const char *scan; ! 1273: int i; ! 1274: ! 1275: if (strlen(*mangled) >= 11 && strncmp(*mangled, "_GLOBAL_", 8) == 0) ! 1276: { ! 1277: char *marker = strchr (cplus_markers, (*mangled)[8]); ! 1278: if (marker != NULL && *marker == (*mangled)[10]) ! 1279: { ! 1280: if ((*mangled)[9] == 'D') ! 1281: { ! 1282: /* it's a GNU global destructor to be executed at program exit */ ! 1283: (*mangled) += 11; ! 1284: work->destructor = 2; ! 1285: if (gnu_special (work, mangled, declp)) ! 1286: return success; ! 1287: } ! 1288: else if ((*mangled)[9] == 'I') ! 1289: { ! 1290: /* it's a GNU global constructor to be executed at program init */ ! 1291: (*mangled) += 11; ! 1292: work->constructor = 2; ! 1293: if (gnu_special (work, mangled, declp)) ! 1294: return success; ! 1295: } ! 1296: } ! 1297: } ! 1298: else if (ARM_DEMANGLING && strncmp(*mangled, "__std__", 7) == 0) ! 1299: { ! 1300: /* it's a ARM global destructor to be executed at program exit */ ! 1301: (*mangled) += 7; ! 1302: work->destructor = 2; ! 1303: } ! 1304: else if (ARM_DEMANGLING && strncmp(*mangled, "__sti__", 7) == 0) ! 1305: { ! 1306: /* it's a ARM global constructor to be executed at program initial */ ! 1307: (*mangled) += 7; ! 1308: work->constructor = 2; ! 1309: } ! 1310: ! 1311: /* This block of code is a reduction in strength time optimization ! 1312: of: ! 1313: scan = mystrstr (*mangled, "__"); */ ! 1314: ! 1315: { ! 1316: scan = *mangled; ! 1317: ! 1318: do { ! 1319: scan = strchr (scan, '_'); ! 1320: } while (scan != NULL && *++scan != '_'); ! 1321: ! 1322: if (scan != NULL) --scan; ! 1323: } ! 1324: ! 1325: if (scan != NULL) ! 1326: { ! 1327: /* We found a sequence of two or more '_', ensure that we start at ! 1328: the last pair in the sequence. */ ! 1329: i = strspn (scan, "_"); ! 1330: if (i > 2) ! 1331: { ! 1332: scan += (i - 2); ! 1333: } ! 1334: } ! 1335: ! 1336: if (scan == NULL) ! 1337: { ! 1338: success = 0; ! 1339: } ! 1340: else if (work -> static_type) ! 1341: { ! 1342: if (!isdigit (scan[0]) && (scan[0] != 't')) ! 1343: { ! 1344: success = 0; ! 1345: } ! 1346: } ! 1347: else if ((scan == *mangled) && ! 1348: (isdigit (scan[2]) || (scan[2] == 'Q') || (scan[2] == 't'))) ! 1349: { ! 1350: /* The ARM says nothing about the mangling of local variables. ! 1351: But cfront mangles local variables by prepending __<nesting_level> ! 1352: to them. As an extension to ARM demangling we handle this case. */ ! 1353: if ((LUCID_DEMANGLING || ARM_DEMANGLING) && isdigit (scan[2])) ! 1354: { ! 1355: *mangled = scan + 2; ! 1356: consume_count (mangled); ! 1357: string_append (declp, *mangled); ! 1358: *mangled += strlen (*mangled); ! 1359: success = 1; ! 1360: } ! 1361: else ! 1362: { ! 1363: /* A GNU style constructor starts with __[0-9Qt]. But cfront uses ! 1364: names like __Q2_3foo3bar for nested type names. So don't accept ! 1365: this style of constructor for cfront demangling. */ ! 1366: if (!(LUCID_DEMANGLING || ARM_DEMANGLING)) ! 1367: work -> constructor += 1; ! 1368: *mangled = scan + 2; ! 1369: } ! 1370: } ! 1371: else if ((scan == *mangled) && !isdigit (scan[2]) && (scan[2] != 't')) ! 1372: { ! 1373: /* Mangled name starts with "__". Skip over any leading '_' characters, ! 1374: then find the next "__" that separates the prefix from the signature. ! 1375: */ ! 1376: if (!(ARM_DEMANGLING || LUCID_DEMANGLING) ! 1377: || (arm_special (work, mangled, declp) == 0)) ! 1378: { ! 1379: while (*scan == '_') ! 1380: { ! 1381: scan++; ! 1382: } ! 1383: if ((scan = mystrstr (scan, "__")) == NULL || (*(scan + 2) == '\0')) ! 1384: { ! 1385: /* No separator (I.E. "__not_mangled"), or empty signature ! 1386: (I.E. "__not_mangled_either__") */ ! 1387: success = 0; ! 1388: } ! 1389: else ! 1390: { ! 1391: demangle_function_name (work, mangled, declp, scan); ! 1392: } ! 1393: } ! 1394: } ! 1395: else if (ARM_DEMANGLING && scan[2] == 'p' && scan[3] == 't') ! 1396: { ! 1397: /* Cfront-style parameterized type. Handled later as a signature. */ ! 1398: success = 1; ! 1399: ! 1400: /* ARM template? */ ! 1401: demangle_arm_pt (work, mangled, strlen (*mangled), declp); ! 1402: } ! 1403: else if (*(scan + 2) != '\0') ! 1404: { ! 1405: /* Mangled name does not start with "__" but does have one somewhere ! 1406: in there with non empty stuff after it. Looks like a global ! 1407: function name. */ ! 1408: demangle_function_name (work, mangled, declp, scan); ! 1409: } ! 1410: else ! 1411: { ! 1412: /* Doesn't look like a mangled name */ ! 1413: success = 0; ! 1414: } ! 1415: ! 1416: if (!success && (work->constructor == 2 || work->destructor == 2)) ! 1417: { ! 1418: string_append (declp, *mangled); ! 1419: *mangled += strlen (*mangled); ! 1420: success = 1; ! 1421: } ! 1422: return (success); ! 1423: } ! 1424: ! 1425: /* ! 1426: ! 1427: LOCAL FUNCTION ! 1428: ! 1429: gnu_special -- special handling of gnu mangled strings ! 1430: ! 1431: SYNOPSIS ! 1432: ! 1433: static int ! 1434: gnu_special (struct work_stuff *work, const char **mangled, ! 1435: string *declp); ! 1436: ! 1437: ! 1438: DESCRIPTION ! 1439: ! 1440: Process some special GNU style mangling forms that don't fit ! 1441: the normal pattern. For example: ! 1442: ! 1443: _$_3foo (destructor for class foo) ! 1444: _vt$foo (foo virtual table) ! 1445: _vt$foo$bar (foo::bar virtual table) ! 1446: __vt_foo (foo virtual table, new style with thunks) ! 1447: _3foo$varname (static data member) ! 1448: _Q22rs2tu$vw (static data member) ! 1449: __t6vector1Zii (constructor with template) ! 1450: __thunk_4__$_7ostream (virtual function thunk) ! 1451: */ ! 1452: ! 1453: static int ! 1454: gnu_special (work, mangled, declp) ! 1455: struct work_stuff *work; ! 1456: const char **mangled; ! 1457: string *declp; ! 1458: { ! 1459: int n; ! 1460: int success = 1; ! 1461: const char *p; ! 1462: ! 1463: if ((*mangled)[0] == '_' ! 1464: && strchr (cplus_markers, (*mangled)[1]) != NULL ! 1465: && (*mangled)[2] == '_') ! 1466: { ! 1467: /* Found a GNU style destructor, get past "_<CPLUS_MARKER>_" */ ! 1468: (*mangled) += 3; ! 1469: work -> destructor += 1; ! 1470: } ! 1471: else if ((*mangled)[0] == '_' ! 1472: && (((*mangled)[1] == '_' ! 1473: && (*mangled)[2] == 'v' ! 1474: && (*mangled)[3] == 't' ! 1475: && (*mangled)[4] == '_') ! 1476: || ((*mangled)[1] == 'v' ! 1477: && (*mangled)[2] == 't' ! 1478: && strchr (cplus_markers, (*mangled)[3]) != NULL))) ! 1479: { ! 1480: /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>" ! 1481: and create the decl. Note that we consume the entire mangled ! 1482: input string, which means that demangle_signature has no work ! 1483: to do. */ ! 1484: if ((*mangled)[2] == 'v') ! 1485: (*mangled) += 5; /* New style, with thunks: "__vt_" */ ! 1486: else ! 1487: (*mangled) += 4; /* Old style, no thunks: "_vt<CPLUS_MARKER>" */ ! 1488: while (**mangled != '\0') ! 1489: { ! 1490: p = strpbrk (*mangled, cplus_markers); ! 1491: switch (**mangled) ! 1492: { ! 1493: case 'Q': ! 1494: success = demangle_qualified (work, mangled, declp, 0, 1); ! 1495: break; ! 1496: case 't': ! 1497: success = demangle_template (work, mangled, declp, 0); ! 1498: break; ! 1499: default: ! 1500: if (isdigit(*mangled[0])) ! 1501: { ! 1502: n = consume_count(mangled); ! 1503: } ! 1504: else ! 1505: { ! 1506: n = strcspn (*mangled, cplus_markers); ! 1507: } ! 1508: string_appendn (declp, *mangled, n); ! 1509: (*mangled) += n; ! 1510: } ! 1511: ! 1512: if (success && ((p == NULL) || (p == *mangled))) ! 1513: { ! 1514: if (p != NULL) ! 1515: { ! 1516: string_append (declp, "::"); ! 1517: (*mangled)++; ! 1518: } ! 1519: } ! 1520: else ! 1521: { ! 1522: success = 0; ! 1523: break; ! 1524: } ! 1525: } ! 1526: if (success) ! 1527: string_append (declp, " virtual table"); ! 1528: } ! 1529: else if ((*mangled)[0] == '_' ! 1530: && (strchr("0123456789Qt", (*mangled)[1]) != NULL) ! 1531: && (p = strpbrk (*mangled, cplus_markers)) != NULL) ! 1532: { ! 1533: /* static data member, "_3foo$varname" for example */ ! 1534: (*mangled)++; ! 1535: switch (**mangled) ! 1536: { ! 1537: case 'Q': ! 1538: success = demangle_qualified (work, mangled, declp, 0, 1); ! 1539: break; ! 1540: case 't': ! 1541: success = demangle_template (work, mangled, declp, 0); ! 1542: break; ! 1543: default: ! 1544: n = consume_count (mangled); ! 1545: string_appendn (declp, *mangled, n); ! 1546: (*mangled) += n; ! 1547: } ! 1548: if (success && (p == *mangled)) ! 1549: { ! 1550: /* Consumed everything up to the cplus_marker, append the ! 1551: variable name. */ ! 1552: (*mangled)++; ! 1553: string_append (declp, "::"); ! 1554: n = strlen (*mangled); ! 1555: string_appendn (declp, *mangled, n); ! 1556: (*mangled) += n; ! 1557: } ! 1558: else ! 1559: { ! 1560: success = 0; ! 1561: } ! 1562: } ! 1563: else if (strncmp (*mangled, "__thunk_", 8) == 0) ! 1564: { ! 1565: int delta = ((*mangled) += 8, consume_count (mangled)); ! 1566: char *method = cplus_demangle (++*mangled, work->options); ! 1567: if (method) ! 1568: { ! 1569: char buf[50]; ! 1570: sprintf (buf, "virtual function thunk (delta:%d) for ", -delta); ! 1571: string_append (declp, buf); ! 1572: string_append (declp, method); ! 1573: free (method); ! 1574: n = strlen (*mangled); ! 1575: (*mangled) += n; ! 1576: } ! 1577: else ! 1578: { ! 1579: success = 0; ! 1580: } ! 1581: } ! 1582: else ! 1583: { ! 1584: success = 0; ! 1585: } ! 1586: return (success); ! 1587: } ! 1588: ! 1589: /* ! 1590: ! 1591: LOCAL FUNCTION ! 1592: ! 1593: arm_special -- special handling of ARM/lucid mangled strings ! 1594: ! 1595: SYNOPSIS ! 1596: ! 1597: static int ! 1598: arm_special (struct work_stuff *work, const char **mangled, ! 1599: string *declp); ! 1600: ! 1601: ! 1602: DESCRIPTION ! 1603: ! 1604: Process some special ARM style mangling forms that don't fit ! 1605: the normal pattern. For example: ! 1606: ! 1607: __vtbl__3foo (foo virtual table) ! 1608: __vtbl__3foo__3bar (bar::foo virtual table) ! 1609: ! 1610: */ ! 1611: ! 1612: static int ! 1613: arm_special (work, mangled, declp) ! 1614: struct work_stuff *work; ! 1615: const char **mangled; ! 1616: string *declp; ! 1617: { ! 1618: int n; ! 1619: int success = 1; ! 1620: const char *scan; ! 1621: ! 1622: if (strncmp (*mangled, ARM_VTABLE_STRING, ARM_VTABLE_STRLEN) == 0) ! 1623: { ! 1624: /* Found a ARM style virtual table, get past ARM_VTABLE_STRING ! 1625: and create the decl. Note that we consume the entire mangled ! 1626: input string, which means that demangle_signature has no work ! 1627: to do. */ ! 1628: scan = *mangled + ARM_VTABLE_STRLEN; ! 1629: while (*scan != '\0') /* first check it can be demangled */ ! 1630: { ! 1631: n = consume_count (&scan); ! 1632: if (n==0) ! 1633: { ! 1634: return (0); /* no good */ ! 1635: } ! 1636: scan += n; ! 1637: if (scan[0] == '_' && scan[1] == '_') ! 1638: { ! 1639: scan += 2; ! 1640: } ! 1641: } ! 1642: (*mangled) += ARM_VTABLE_STRLEN; ! 1643: while (**mangled != '\0') ! 1644: { ! 1645: n = consume_count (mangled); ! 1646: string_prependn (declp, *mangled, n); ! 1647: (*mangled) += n; ! 1648: if ((*mangled)[0] == '_' && (*mangled)[1] == '_') ! 1649: { ! 1650: string_prepend (declp, "::"); ! 1651: (*mangled) += 2; ! 1652: } ! 1653: } ! 1654: string_append (declp, " virtual table"); ! 1655: } ! 1656: else ! 1657: { ! 1658: success = 0; ! 1659: } ! 1660: return (success); ! 1661: } ! 1662: ! 1663: /* ! 1664: ! 1665: LOCAL FUNCTION ! 1666: ! 1667: demangle_qualified -- demangle 'Q' qualified name strings ! 1668: ! 1669: SYNOPSIS ! 1670: ! 1671: static int ! 1672: demangle_qualified (struct work_stuff *, const char *mangled, ! 1673: string *result, int isfuncname, int append); ! 1674: ! 1675: DESCRIPTION ! 1676: ! 1677: Demangle a qualified name, such as "Q25Outer5Inner" which is ! 1678: the mangled form of "Outer::Inner". The demangled output is ! 1679: prepended or appended to the result string according to the ! 1680: state of the append flag. ! 1681: ! 1682: If isfuncname is nonzero, then the qualified name we are building ! 1683: is going to be used as a member function name, so if it is a ! 1684: constructor or destructor function, append an appropriate ! 1685: constructor or destructor name. I.E. for the above example, ! 1686: the result for use as a constructor is "Outer::Inner::Inner" ! 1687: and the result for use as a destructor is "Outer::Inner::~Inner". ! 1688: ! 1689: BUGS ! 1690: ! 1691: Numeric conversion is ASCII dependent (FIXME). ! 1692: ! 1693: */ ! 1694: ! 1695: static int ! 1696: demangle_qualified (work, mangled, result, isfuncname, append) ! 1697: struct work_stuff *work; ! 1698: const char **mangled; ! 1699: string *result; ! 1700: int isfuncname; ! 1701: int append; ! 1702: { ! 1703: int qualifiers; ! 1704: int namelength; ! 1705: int success = 1; ! 1706: const char *p; ! 1707: char num[2]; ! 1708: string temp; ! 1709: ! 1710: string_init (&temp); ! 1711: switch ((*mangled)[1]) ! 1712: { ! 1713: case '_': ! 1714: /* GNU mangled name with more than 9 classes. The count is preceded ! 1715: by an underscore (to distinguish it from the <= 9 case) and followed ! 1716: by an underscore. */ ! 1717: p = *mangled + 2; ! 1718: qualifiers = atoi (p); ! 1719: if (!isdigit (*p) || *p == '0') ! 1720: success = 0; ! 1721: ! 1722: /* Skip the digits. */ ! 1723: while (isdigit (*p)) ! 1724: ++p; ! 1725: ! 1726: if (*p != '_') ! 1727: success = 0; ! 1728: ! 1729: *mangled = p + 1; ! 1730: break; ! 1731: ! 1732: case '1': ! 1733: case '2': ! 1734: case '3': ! 1735: case '4': ! 1736: case '5': ! 1737: case '6': ! 1738: case '7': ! 1739: case '8': ! 1740: case '9': ! 1741: /* The count is in a single digit. */ ! 1742: num[0] = (*mangled)[1]; ! 1743: num[1] = '\0'; ! 1744: qualifiers = atoi (num); ! 1745: ! 1746: /* If there is an underscore after the digit, skip it. This is ! 1747: said to be for ARM-qualified names, but the ARM makes no ! 1748: mention of such an underscore. Perhaps cfront uses one. */ ! 1749: if ((*mangled)[2] == '_') ! 1750: { ! 1751: (*mangled)++; ! 1752: } ! 1753: (*mangled) += 2; ! 1754: break; ! 1755: ! 1756: case '0': ! 1757: default: ! 1758: success = 0; ! 1759: } ! 1760: ! 1761: if (!success) ! 1762: return success; ! 1763: ! 1764: /* Pick off the names and collect them in the temp buffer in the order ! 1765: in which they are found, separated by '::'. */ ! 1766: ! 1767: while (qualifiers-- > 0) ! 1768: { ! 1769: if (*mangled[0] == '_') ! 1770: *mangled = *mangled + 1; ! 1771: if (*mangled[0] == 't') ! 1772: { ! 1773: success = demangle_template(work, mangled, &temp, 0); ! 1774: if (!success) break; ! 1775: } ! 1776: else ! 1777: { ! 1778: namelength = consume_count (mangled); ! 1779: if (strlen (*mangled) < namelength) ! 1780: { ! 1781: /* Simple sanity check failed */ ! 1782: success = 0; ! 1783: break; ! 1784: } ! 1785: string_appendn (&temp, *mangled, namelength); ! 1786: *mangled += namelength; ! 1787: } ! 1788: if (qualifiers > 0) ! 1789: { ! 1790: string_appendn (&temp, "::", 2); ! 1791: } ! 1792: } ! 1793: ! 1794: /* If we are using the result as a function name, we need to append ! 1795: the appropriate '::' separated constructor or destructor name. ! 1796: We do this here because this is the most convenient place, where ! 1797: we already have a pointer to the name and the length of the name. */ ! 1798: ! 1799: if (isfuncname && (work->constructor & 1 || work->destructor & 1)) ! 1800: { ! 1801: string_appendn (&temp, "::", 2); ! 1802: if (work -> destructor & 1) ! 1803: { ! 1804: string_append (&temp, "~"); ! 1805: } ! 1806: string_appendn (&temp, (*mangled) - namelength, namelength); ! 1807: } ! 1808: ! 1809: /* Now either prepend the temp buffer to the result, or append it, ! 1810: depending upon the state of the append flag. */ ! 1811: ! 1812: if (append) ! 1813: { ! 1814: string_appends (result, &temp); ! 1815: } ! 1816: else ! 1817: { ! 1818: if (!STRING_EMPTY (result)) ! 1819: { ! 1820: string_appendn (&temp, "::", 2); ! 1821: } ! 1822: string_prepends (result, &temp); ! 1823: } ! 1824: ! 1825: string_delete (&temp); ! 1826: return (success); ! 1827: } ! 1828: ! 1829: /* ! 1830: ! 1831: LOCAL FUNCTION ! 1832: ! 1833: get_count -- convert an ascii count to integer, consuming tokens ! 1834: ! 1835: SYNOPSIS ! 1836: ! 1837: static int ! 1838: get_count (const char **type, int *count) ! 1839: ! 1840: DESCRIPTION ! 1841: ! 1842: Return 0 if no conversion is performed, 1 if a string is converted. ! 1843: */ ! 1844: ! 1845: static int ! 1846: get_count (type, count) ! 1847: const char **type; ! 1848: int *count; ! 1849: { ! 1850: const char *p; ! 1851: int n; ! 1852: ! 1853: if (!isdigit (**type)) ! 1854: { ! 1855: return (0); ! 1856: } ! 1857: else ! 1858: { ! 1859: *count = **type - '0'; ! 1860: (*type)++; ! 1861: if (isdigit (**type)) ! 1862: { ! 1863: p = *type; ! 1864: n = *count; ! 1865: do ! 1866: { ! 1867: n *= 10; ! 1868: n += *p - '0'; ! 1869: p++; ! 1870: } ! 1871: while (isdigit (*p)); ! 1872: if (*p == '_') ! 1873: { ! 1874: *type = p + 1; ! 1875: *count = n; ! 1876: } ! 1877: } ! 1878: } ! 1879: return (1); ! 1880: } ! 1881: ! 1882: /* result will be initialised here; it will be freed on failure */ ! 1883: ! 1884: static int ! 1885: do_type (work, mangled, result) ! 1886: struct work_stuff *work; ! 1887: const char **mangled; ! 1888: string *result; ! 1889: { ! 1890: int n; ! 1891: int done; ! 1892: int success; ! 1893: string decl; ! 1894: const char *remembered_type; ! 1895: int constp; ! 1896: int volatilep; ! 1897: ! 1898: string_init (&decl); ! 1899: string_init (result); ! 1900: ! 1901: done = 0; ! 1902: success = 1; ! 1903: while (success && !done) ! 1904: { ! 1905: int member; ! 1906: switch (**mangled) ! 1907: { ! 1908: ! 1909: /* A pointer type */ ! 1910: case 'P': ! 1911: case 'p': ! 1912: (*mangled)++; ! 1913: string_prepend (&decl, "*"); ! 1914: break; ! 1915: ! 1916: /* A reference type */ ! 1917: case 'R': ! 1918: (*mangled)++; ! 1919: string_prepend (&decl, "&"); ! 1920: break; ! 1921: ! 1922: /* An array */ ! 1923: case 'A': ! 1924: { ! 1925: const char *p = ++(*mangled); ! 1926: ! 1927: string_prepend (&decl, "("); ! 1928: string_append (&decl, ")["); ! 1929: /* Copy anything up until the next underscore (the size of the ! 1930: array). */ ! 1931: while (**mangled && **mangled != '_') ! 1932: ++(*mangled); ! 1933: if (**mangled == '_') ! 1934: { ! 1935: string_appendn (&decl, p, *mangled - p); ! 1936: string_append (&decl, "]"); ! 1937: *mangled += 1; ! 1938: } ! 1939: else ! 1940: success = 0; ! 1941: break; ! 1942: } ! 1943: ! 1944: /* A back reference to a previously seen type */ ! 1945: case 'T': ! 1946: (*mangled)++; ! 1947: if (!get_count (mangled, &n) || n >= work -> ntypes) ! 1948: { ! 1949: success = 0; ! 1950: } ! 1951: else ! 1952: { ! 1953: remembered_type = work -> typevec[n]; ! 1954: mangled = &remembered_type; ! 1955: } ! 1956: break; ! 1957: ! 1958: /* A function */ ! 1959: case 'F': ! 1960: (*mangled)++; ! 1961: if (!STRING_EMPTY (&decl) && decl.b[0] == '*') ! 1962: { ! 1963: string_prepend (&decl, "("); ! 1964: string_append (&decl, ")"); ! 1965: } ! 1966: /* After picking off the function args, we expect to either find the ! 1967: function return type (preceded by an '_') or the end of the ! 1968: string. */ ! 1969: if (!demangle_args (work, mangled, &decl) ! 1970: || (**mangled != '_' && **mangled != '\0')) ! 1971: { ! 1972: success = 0; ! 1973: } ! 1974: if (success && (**mangled == '_')) ! 1975: { ! 1976: (*mangled)++; ! 1977: } ! 1978: break; ! 1979: ! 1980: case 'M': ! 1981: case 'O': ! 1982: { ! 1983: constp = 0; ! 1984: volatilep = 0; ! 1985: ! 1986: member = **mangled == 'M'; ! 1987: (*mangled)++; ! 1988: if (!isdigit (**mangled)) ! 1989: { ! 1990: success = 0; ! 1991: break; ! 1992: } ! 1993: n = consume_count (mangled); ! 1994: if (strlen (*mangled) < n) ! 1995: { ! 1996: success = 0; ! 1997: break; ! 1998: } ! 1999: string_append (&decl, ")"); ! 2000: string_prepend (&decl, "::"); ! 2001: string_prependn (&decl, *mangled, n); ! 2002: string_prepend (&decl, "("); ! 2003: *mangled += n; ! 2004: if (member) ! 2005: { ! 2006: if (**mangled == 'C') ! 2007: { ! 2008: (*mangled)++; ! 2009: constp = 1; ! 2010: } ! 2011: if (**mangled == 'V') ! 2012: { ! 2013: (*mangled)++; ! 2014: volatilep = 1; ! 2015: } ! 2016: if (*(*mangled)++ != 'F') ! 2017: { ! 2018: success = 0; ! 2019: break; ! 2020: } ! 2021: } ! 2022: if ((member && !demangle_args (work, mangled, &decl)) ! 2023: || **mangled != '_') ! 2024: { ! 2025: success = 0; ! 2026: break; ! 2027: } ! 2028: (*mangled)++; ! 2029: if (! PRINT_ANSI_QUALIFIERS) ! 2030: { ! 2031: break; ! 2032: } ! 2033: if (constp) ! 2034: { ! 2035: APPEND_BLANK (&decl); ! 2036: string_append (&decl, "const"); ! 2037: } ! 2038: if (volatilep) ! 2039: { ! 2040: APPEND_BLANK (&decl); ! 2041: string_append (&decl, "volatile"); ! 2042: } ! 2043: break; ! 2044: } ! 2045: case 'G': ! 2046: (*mangled)++; ! 2047: break; ! 2048: ! 2049: case 'C': ! 2050: (*mangled)++; ! 2051: /* ! 2052: if ((*mangled)[1] == 'P') ! 2053: { ! 2054: */ ! 2055: if (PRINT_ANSI_QUALIFIERS) ! 2056: { ! 2057: if (!STRING_EMPTY (&decl)) ! 2058: { ! 2059: string_prepend (&decl, " "); ! 2060: } ! 2061: string_prepend (&decl, "const"); ! 2062: } ! 2063: break; ! 2064: /* ! 2065: } ! 2066: */ ! 2067: ! 2068: /* fall through */ ! 2069: default: ! 2070: done = 1; ! 2071: break; ! 2072: } ! 2073: } ! 2074: ! 2075: switch (**mangled) ! 2076: { ! 2077: /* A qualified name, such as "Outer::Inner". */ ! 2078: case 'Q': ! 2079: success = demangle_qualified (work, mangled, result, 0, 1); ! 2080: break; ! 2081: ! 2082: default: ! 2083: success = demangle_fund_type (work, mangled, result); ! 2084: break; ! 2085: } ! 2086: ! 2087: if (success) ! 2088: { ! 2089: if (!STRING_EMPTY (&decl)) ! 2090: { ! 2091: string_append (result, " "); ! 2092: string_appends (result, &decl); ! 2093: } ! 2094: } ! 2095: else ! 2096: { ! 2097: string_delete (result); ! 2098: } ! 2099: string_delete (&decl); ! 2100: return (success); ! 2101: } ! 2102: ! 2103: /* Given a pointer to a type string that represents a fundamental type ! 2104: argument (int, long, unsigned int, etc) in TYPE, a pointer to the ! 2105: string in which the demangled output is being built in RESULT, and ! 2106: the WORK structure, decode the types and add them to the result. ! 2107: ! 2108: For example: ! 2109: ! 2110: "Ci" => "const int" ! 2111: "Sl" => "signed long" ! 2112: "CUs" => "const unsigned short" ! 2113: ! 2114: */ ! 2115: ! 2116: static int ! 2117: demangle_fund_type (work, mangled, result) ! 2118: struct work_stuff *work; ! 2119: const char **mangled; ! 2120: string *result; ! 2121: { ! 2122: int done = 0; ! 2123: int success = 1; ! 2124: ! 2125: /* First pick off any type qualifiers. There can be more than one. */ ! 2126: ! 2127: while (!done) ! 2128: { ! 2129: switch (**mangled) ! 2130: { ! 2131: case 'C': ! 2132: (*mangled)++; ! 2133: if (PRINT_ANSI_QUALIFIERS) ! 2134: { ! 2135: APPEND_BLANK (result); ! 2136: string_append (result, "const"); ! 2137: } ! 2138: break; ! 2139: case 'U': ! 2140: (*mangled)++; ! 2141: APPEND_BLANK (result); ! 2142: string_append (result, "unsigned"); ! 2143: break; ! 2144: case 'S': /* signed char only */ ! 2145: (*mangled)++; ! 2146: APPEND_BLANK (result); ! 2147: string_append (result, "signed"); ! 2148: break; ! 2149: case 'V': ! 2150: (*mangled)++; ! 2151: if (PRINT_ANSI_QUALIFIERS) ! 2152: { ! 2153: APPEND_BLANK (result); ! 2154: string_append (result, "volatile"); ! 2155: } ! 2156: break; ! 2157: default: ! 2158: done = 1; ! 2159: break; ! 2160: } ! 2161: } ! 2162: ! 2163: /* Now pick off the fundamental type. There can be only one. */ ! 2164: ! 2165: switch (**mangled) ! 2166: { ! 2167: case '\0': ! 2168: case '_': ! 2169: break; ! 2170: case 'v': ! 2171: (*mangled)++; ! 2172: APPEND_BLANK (result); ! 2173: string_append (result, "void"); ! 2174: break; ! 2175: case 'x': ! 2176: (*mangled)++; ! 2177: APPEND_BLANK (result); ! 2178: string_append (result, "long long"); ! 2179: break; ! 2180: case 'l': ! 2181: (*mangled)++; ! 2182: APPEND_BLANK (result); ! 2183: string_append (result, "long"); ! 2184: break; ! 2185: case 'i': ! 2186: (*mangled)++; ! 2187: APPEND_BLANK (result); ! 2188: string_append (result, "int"); ! 2189: break; ! 2190: case 's': ! 2191: (*mangled)++; ! 2192: APPEND_BLANK (result); ! 2193: string_append (result, "short"); ! 2194: break; ! 2195: case 'b': ! 2196: (*mangled)++; ! 2197: APPEND_BLANK (result); ! 2198: string_append (result, "bool"); ! 2199: break; ! 2200: case 'c': ! 2201: (*mangled)++; ! 2202: APPEND_BLANK (result); ! 2203: string_append (result, "char"); ! 2204: break; ! 2205: case 'w': ! 2206: (*mangled)++; ! 2207: APPEND_BLANK (result); ! 2208: string_append (result, "wchar_t"); ! 2209: break; ! 2210: case 'r': ! 2211: (*mangled)++; ! 2212: APPEND_BLANK (result); ! 2213: string_append (result, "long double"); ! 2214: break; ! 2215: case 'd': ! 2216: (*mangled)++; ! 2217: APPEND_BLANK (result); ! 2218: string_append (result, "double"); ! 2219: break; ! 2220: case 'f': ! 2221: (*mangled)++; ! 2222: APPEND_BLANK (result); ! 2223: string_append (result, "float"); ! 2224: break; ! 2225: case 'G': ! 2226: (*mangled)++; ! 2227: if (!isdigit (**mangled)) ! 2228: { ! 2229: success = 0; ! 2230: break; ! 2231: } ! 2232: /* fall through */ ! 2233: /* An explicit type, such as "6mytype" or "7integer" */ ! 2234: case '0': ! 2235: case '1': ! 2236: case '2': ! 2237: case '3': ! 2238: case '4': ! 2239: case '5': ! 2240: case '6': ! 2241: case '7': ! 2242: case '8': ! 2243: case '9': ! 2244: APPEND_BLANK (result); ! 2245: if (!demangle_class_name (work, mangled, result)) { ! 2246: --result->p; ! 2247: success = 0; ! 2248: } ! 2249: break; ! 2250: case 't': ! 2251: success = demangle_template(work,mangled, result, 0); ! 2252: break; ! 2253: default: ! 2254: success = 0; ! 2255: break; ! 2256: } ! 2257: ! 2258: return (success); ! 2259: } ! 2260: ! 2261: /* `result' will be initialized in do_type; it will be freed on failure */ ! 2262: ! 2263: static int ! 2264: do_arg (work, mangled, result) ! 2265: struct work_stuff *work; ! 2266: const char **mangled; ! 2267: string *result; ! 2268: { ! 2269: const char *start = *mangled; ! 2270: ! 2271: if (!do_type (work, mangled, result)) ! 2272: { ! 2273: return (0); ! 2274: } ! 2275: else ! 2276: { ! 2277: remember_type (work, start, *mangled - start); ! 2278: return (1); ! 2279: } ! 2280: } ! 2281: ! 2282: static void ! 2283: remember_type (work, start, len) ! 2284: struct work_stuff *work; ! 2285: const char *start; ! 2286: int len; ! 2287: { ! 2288: char *tem; ! 2289: ! 2290: if (work -> ntypes >= work -> typevec_size) ! 2291: { ! 2292: if (work -> typevec_size == 0) ! 2293: { ! 2294: work -> typevec_size = 3; ! 2295: work -> typevec = ! 2296: (char **) xmalloc (sizeof (char *) * work -> typevec_size); ! 2297: } ! 2298: else ! 2299: { ! 2300: work -> typevec_size *= 2; ! 2301: work -> typevec = ! 2302: (char **) xrealloc ((char *)work -> typevec, ! 2303: sizeof (char *) * work -> typevec_size); ! 2304: } ! 2305: } ! 2306: tem = xmalloc (len + 1); ! 2307: memcpy (tem, start, len); ! 2308: tem[len] = '\0'; ! 2309: work -> typevec[work -> ntypes++] = tem; ! 2310: } ! 2311: ! 2312: /* Forget the remembered types, but not the type vector itself. */ ! 2313: ! 2314: static void ! 2315: forget_types (work) ! 2316: struct work_stuff *work; ! 2317: { ! 2318: int i; ! 2319: ! 2320: while (work -> ntypes > 0) ! 2321: { ! 2322: i = --(work -> ntypes); ! 2323: if (work -> typevec[i] != NULL) ! 2324: { ! 2325: free (work -> typevec[i]); ! 2326: work -> typevec[i] = NULL; ! 2327: } ! 2328: } ! 2329: } ! 2330: ! 2331: /* Process the argument list part of the signature, after any class spec ! 2332: has been consumed, as well as the first 'F' character (if any). For ! 2333: example: ! 2334: ! 2335: "__als__3fooRT0" => process "RT0" ! 2336: "complexfunc5__FPFPc_PFl_i" => process "PFPc_PFl_i" ! 2337: ! 2338: DECLP must be already initialised, usually non-empty. It won't be freed ! 2339: on failure. ! 2340: ! 2341: Note that g++ differs significantly from ARM and lucid style mangling ! 2342: with regards to references to previously seen types. For example, given ! 2343: the source fragment: ! 2344: ! 2345: class foo { ! 2346: public: ! 2347: foo::foo (int, foo &ia, int, foo &ib, int, foo &ic); ! 2348: }; ! 2349: ! 2350: foo::foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } ! 2351: void foo (int, foo &ia, int, foo &ib, int, foo &ic) { ia = ib = ic; } ! 2352: ! 2353: g++ produces the names: ! 2354: ! 2355: __3fooiRT0iT2iT2 ! 2356: foo__FiR3fooiT1iT1 ! 2357: ! 2358: while lcc (and presumably other ARM style compilers as well) produces: ! 2359: ! 2360: foo__FiR3fooT1T2T1T2 ! 2361: __ct__3fooFiR3fooT1T2T1T2 ! 2362: ! 2363: Note that g++ bases it's type numbers starting at zero and counts all ! 2364: previously seen types, while lucid/ARM bases it's type numbers starting ! 2365: at one and only considers types after it has seen the 'F' character ! 2366: indicating the start of the function args. For lucid/ARM style, we ! 2367: account for this difference by discarding any previously seen types when ! 2368: we see the 'F' character, and subtracting one from the type number ! 2369: reference. ! 2370: ! 2371: */ ! 2372: ! 2373: static int ! 2374: demangle_args (work, mangled, declp) ! 2375: struct work_stuff *work; ! 2376: const char **mangled; ! 2377: string *declp; ! 2378: { ! 2379: string arg; ! 2380: int need_comma = 0; ! 2381: int r; ! 2382: int t; ! 2383: const char *tem; ! 2384: char temptype; ! 2385: ! 2386: if (PRINT_ARG_TYPES) ! 2387: { ! 2388: string_append (declp, "("); ! 2389: if (**mangled == '\0') ! 2390: { ! 2391: string_append (declp, "void"); ! 2392: } ! 2393: } ! 2394: ! 2395: while (**mangled != '_' && **mangled != '\0' && **mangled != 'e') ! 2396: { ! 2397: if ((**mangled == 'N') || (**mangled == 'T')) ! 2398: { ! 2399: temptype = *(*mangled)++; ! 2400: ! 2401: if (temptype == 'N') ! 2402: { ! 2403: if (!get_count (mangled, &r)) ! 2404: { ! 2405: return (0); ! 2406: } ! 2407: } ! 2408: else ! 2409: { ! 2410: r = 1; ! 2411: } ! 2412: if (ARM_DEMANGLING && work -> ntypes >= 10) ! 2413: { ! 2414: /* If we have 10 or more types we might have more than a 1 digit ! 2415: index so we'll have to consume the whole count here. This ! 2416: will lose if the next thing is a type name preceded by a ! 2417: count but it's impossible to demangle that case properly ! 2418: anyway. Eg if we already have 12 types is T12Pc "(..., type1, ! 2419: Pc, ...)" or "(..., type12, char *, ...)" */ ! 2420: if ((t = consume_count(mangled)) == 0) ! 2421: { ! 2422: return (0); ! 2423: } ! 2424: } ! 2425: else ! 2426: { ! 2427: if (!get_count (mangled, &t)) ! 2428: { ! 2429: return (0); ! 2430: } ! 2431: } ! 2432: if (LUCID_DEMANGLING || ARM_DEMANGLING) ! 2433: { ! 2434: t--; ! 2435: } ! 2436: /* Validate the type index. Protect against illegal indices from ! 2437: malformed type strings. */ ! 2438: if ((t < 0) || (t >= work -> ntypes)) ! 2439: { ! 2440: return (0); ! 2441: } ! 2442: while (--r >= 0) ! 2443: { ! 2444: tem = work -> typevec[t]; ! 2445: if (need_comma && PRINT_ARG_TYPES) ! 2446: { ! 2447: string_append (declp, ", "); ! 2448: } ! 2449: if (!do_arg (work, &tem, &arg)) ! 2450: { ! 2451: return (0); ! 2452: } ! 2453: if (PRINT_ARG_TYPES) ! 2454: { ! 2455: string_appends (declp, &arg); ! 2456: } ! 2457: string_delete (&arg); ! 2458: need_comma = 1; ! 2459: } ! 2460: } ! 2461: else ! 2462: { ! 2463: if (need_comma & PRINT_ARG_TYPES) ! 2464: { ! 2465: string_append (declp, ", "); ! 2466: } ! 2467: if (!do_arg (work, mangled, &arg)) ! 2468: { ! 2469: return (0); ! 2470: } ! 2471: if (PRINT_ARG_TYPES) ! 2472: { ! 2473: string_appends (declp, &arg); ! 2474: } ! 2475: string_delete (&arg); ! 2476: need_comma = 1; ! 2477: } ! 2478: } ! 2479: ! 2480: if (**mangled == 'e') ! 2481: { ! 2482: (*mangled)++; ! 2483: if (PRINT_ARG_TYPES) ! 2484: { ! 2485: if (need_comma) ! 2486: { ! 2487: string_append (declp, ","); ! 2488: } ! 2489: string_append (declp, "..."); ! 2490: } ! 2491: } ! 2492: ! 2493: if (PRINT_ARG_TYPES) ! 2494: { ! 2495: string_append (declp, ")"); ! 2496: } ! 2497: return (1); ! 2498: } ! 2499: ! 2500: static void ! 2501: demangle_function_name (work, mangled, declp, scan) ! 2502: struct work_stuff *work; ! 2503: const char **mangled; ! 2504: string *declp; ! 2505: const char *scan; ! 2506: { ! 2507: int i; ! 2508: int len; ! 2509: string type; ! 2510: const char *tem; ! 2511: ! 2512: string_appendn (declp, (*mangled), scan - (*mangled)); ! 2513: string_need (declp, 1); ! 2514: *(declp -> p) = '\0'; ! 2515: ! 2516: /* Consume the function name, including the "__" separating the name ! 2517: from the signature. We are guaranteed that SCAN points to the ! 2518: separator. */ ! 2519: ! 2520: (*mangled) = scan + 2; ! 2521: ! 2522: if (LUCID_DEMANGLING || ARM_DEMANGLING) ! 2523: { ! 2524: ! 2525: /* See if we have an ARM style constructor or destructor operator. ! 2526: If so, then just record it, clear the decl, and return. ! 2527: We can't build the actual constructor/destructor decl until later, ! 2528: when we recover the class name from the signature. */ ! 2529: ! 2530: if (strcmp (declp -> b, "__ct") == 0) ! 2531: { ! 2532: work -> constructor += 1; ! 2533: string_clear (declp); ! 2534: return; ! 2535: } ! 2536: else if (strcmp (declp -> b, "__dt") == 0) ! 2537: { ! 2538: work -> destructor += 1; ! 2539: string_clear (declp); ! 2540: return; ! 2541: } ! 2542: } ! 2543: ! 2544: if (declp->p - declp->b >= 3 ! 2545: && declp->b[0] == 'o' ! 2546: && declp->b[1] == 'p' ! 2547: && strchr (cplus_markers, declp->b[2]) != NULL) ! 2548: { ! 2549: /* see if it's an assignment expression */ ! 2550: if (declp->p - declp->b >= 10 /* op$assign_ */ ! 2551: && memcmp (declp->b + 3, "assign_", 7) == 0) ! 2552: { ! 2553: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2554: { ! 2555: len = declp->p - declp->b - 10; ! 2556: if (strlen (optable[i].in) == len ! 2557: && memcmp (optable[i].in, declp->b + 10, len) == 0) ! 2558: { ! 2559: string_clear (declp); ! 2560: string_append (declp, "operator"); ! 2561: string_append (declp, optable[i].out); ! 2562: string_append (declp, "="); ! 2563: break; ! 2564: } ! 2565: } ! 2566: } ! 2567: else ! 2568: { ! 2569: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2570: { ! 2571: int len = declp->p - declp->b - 3; ! 2572: if (strlen (optable[i].in) == len ! 2573: && memcmp (optable[i].in, declp->b + 3, len) == 0) ! 2574: { ! 2575: string_clear (declp); ! 2576: string_append (declp, "operator"); ! 2577: string_append (declp, optable[i].out); ! 2578: break; ! 2579: } ! 2580: } ! 2581: } ! 2582: } ! 2583: else if (declp->p - declp->b >= 5 && memcmp (declp->b, "type", 4) == 0 ! 2584: && strchr (cplus_markers, declp->b[4]) != NULL) ! 2585: { ! 2586: /* type conversion operator */ ! 2587: tem = declp->b + 5; ! 2588: if (do_type (work, &tem, &type)) ! 2589: { ! 2590: string_clear (declp); ! 2591: string_append (declp, "operator "); ! 2592: string_appends (declp, &type); ! 2593: string_delete (&type); ! 2594: } ! 2595: } ! 2596: else if (declp->b[0] == '_' && declp->b[1] == '_' ! 2597: && declp->b[2] == 'o' && declp->b[3] == 'p') ! 2598: { ! 2599: /* ANSI. */ ! 2600: /* type conversion operator. */ ! 2601: tem = declp->b + 4; ! 2602: if (do_type (work, &tem, &type)) ! 2603: { ! 2604: string_clear (declp); ! 2605: string_append (declp, "operator "); ! 2606: string_appends (declp, &type); ! 2607: string_delete (&type); ! 2608: } ! 2609: } ! 2610: else if (declp->b[0] == '_' && declp->b[1] == '_' ! 2611: && declp->b[2] >= 'a' && declp->b[2] <= 'z' ! 2612: && declp->b[3] >= 'a' && declp->b[3] <= 'z') ! 2613: { ! 2614: if (declp->b[4] == '\0') ! 2615: { ! 2616: /* Operator. */ ! 2617: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2618: { ! 2619: if (strlen (optable[i].in) == 2 ! 2620: && memcmp (optable[i].in, declp->b + 2, 2) == 0) ! 2621: { ! 2622: string_clear (declp); ! 2623: string_append (declp, "operator"); ! 2624: string_append (declp, optable[i].out); ! 2625: break; ! 2626: } ! 2627: } ! 2628: } ! 2629: else ! 2630: { ! 2631: if (declp->b[2] == 'a' && declp->b[5] == '\0') ! 2632: { ! 2633: /* Assignment. */ ! 2634: for (i = 0; i < sizeof (optable) / sizeof (optable[0]); i++) ! 2635: { ! 2636: if (strlen (optable[i].in) == 3 ! 2637: && memcmp (optable[i].in, declp->b + 2, 3) == 0) ! 2638: { ! 2639: string_clear (declp); ! 2640: string_append (declp, "operator"); ! 2641: string_append (declp, optable[i].out); ! 2642: break; ! 2643: } ! 2644: } ! 2645: } ! 2646: } ! 2647: } ! 2648: } ! 2649: ! 2650: /* a mini string-handling package */ ! 2651: ! 2652: static void ! 2653: string_need (s, n) ! 2654: string *s; ! 2655: int n; ! 2656: { ! 2657: int tem; ! 2658: ! 2659: if (s->b == NULL) ! 2660: { ! 2661: if (n < 32) ! 2662: { ! 2663: n = 32; ! 2664: } ! 2665: s->p = s->b = xmalloc (n); ! 2666: s->e = s->b + n; ! 2667: } ! 2668: else if (s->e - s->p < n) ! 2669: { ! 2670: tem = s->p - s->b; ! 2671: n += tem; ! 2672: n *= 2; ! 2673: s->b = xrealloc (s->b, n); ! 2674: s->p = s->b + tem; ! 2675: s->e = s->b + n; ! 2676: } ! 2677: } ! 2678: ! 2679: static void ! 2680: string_delete (s) ! 2681: string *s; ! 2682: { ! 2683: if (s->b != NULL) ! 2684: { ! 2685: free (s->b); ! 2686: s->b = s->e = s->p = NULL; ! 2687: } ! 2688: } ! 2689: ! 2690: static void ! 2691: string_init (s) ! 2692: string *s; ! 2693: { ! 2694: s->b = s->p = s->e = NULL; ! 2695: } ! 2696: ! 2697: static void ! 2698: string_clear (s) ! 2699: string *s; ! 2700: { ! 2701: s->p = s->b; ! 2702: } ! 2703: ! 2704: #if 0 ! 2705: ! 2706: static int ! 2707: string_empty (s) ! 2708: string *s; ! 2709: { ! 2710: return (s->b == s->p); ! 2711: } ! 2712: ! 2713: #endif ! 2714: ! 2715: static void ! 2716: string_append (p, s) ! 2717: string *p; ! 2718: const char *s; ! 2719: { ! 2720: int n; ! 2721: if (s == NULL || *s == '\0') ! 2722: return; ! 2723: n = strlen (s); ! 2724: string_need (p, n); ! 2725: memcpy (p->p, s, n); ! 2726: p->p += n; ! 2727: } ! 2728: ! 2729: static void ! 2730: string_appends (p, s) ! 2731: string *p, *s; ! 2732: { ! 2733: int n; ! 2734: ! 2735: if (s->b != s->p) ! 2736: { ! 2737: n = s->p - s->b; ! 2738: string_need (p, n); ! 2739: memcpy (p->p, s->b, n); ! 2740: p->p += n; ! 2741: } ! 2742: } ! 2743: ! 2744: static void ! 2745: string_appendn (p, s, n) ! 2746: string *p; ! 2747: const char *s; ! 2748: int n; ! 2749: { ! 2750: if (n != 0) ! 2751: { ! 2752: string_need (p, n); ! 2753: memcpy (p->p, s, n); ! 2754: p->p += n; ! 2755: } ! 2756: } ! 2757: ! 2758: static void ! 2759: string_prepend (p, s) ! 2760: string *p; ! 2761: const char *s; ! 2762: { ! 2763: if (s != NULL && *s != '\0') ! 2764: { ! 2765: string_prependn (p, s, strlen (s)); ! 2766: } ! 2767: } ! 2768: ! 2769: static void ! 2770: string_prepends (p, s) ! 2771: string *p, *s; ! 2772: { ! 2773: if (s->b != s->p) ! 2774: { ! 2775: string_prependn (p, s->b, s->p - s->b); ! 2776: } ! 2777: } ! 2778: ! 2779: static void ! 2780: string_prependn (p, s, n) ! 2781: string *p; ! 2782: const char *s; ! 2783: int n; ! 2784: { ! 2785: char *q; ! 2786: ! 2787: if (n != 0) ! 2788: { ! 2789: string_need (p, n); ! 2790: for (q = p->p - 1; q >= p->b; q--) ! 2791: { ! 2792: q[n] = q[0]; ! 2793: } ! 2794: memcpy (p->b, s, n); ! 2795: p->p += n; ! 2796: } ! 2797: } ! 2798: ! 2799: /* To generate a standalone demangler program for testing purposes, ! 2800: just compile and link this file with -DMAIN and libiberty.a. When ! 2801: run, it demangles each command line arg, or each stdin string, and ! 2802: prints the result on stdout. */ ! 2803: ! 2804: #ifdef MAIN ! 2805: ! 2806: static void ! 2807: demangle_it (mangled_name) ! 2808: char *mangled_name; ! 2809: { ! 2810: char *result; ! 2811: ! 2812: result = cplus_demangle (mangled_name, DMGL_PARAMS | DMGL_ANSI); ! 2813: if (result == NULL) ! 2814: { ! 2815: printf ("%s\n", mangled_name); ! 2816: } ! 2817: else ! 2818: { ! 2819: printf ("%s\n", result); ! 2820: free (result); ! 2821: } ! 2822: } ! 2823: ! 2824: #include "getopt.h" ! 2825: ! 2826: static char *program_name; ! 2827: static char *program_version = VERSION; ! 2828: ! 2829: static void ! 2830: usage (stream, status) ! 2831: FILE *stream; ! 2832: int status; ! 2833: { ! 2834: fprintf (stream, "\ ! 2835: Usage: %s [-_] [-n] [-s {gnu,lucid,arm}] [--strip-underscores]\n\ ! 2836: [--no-strip-underscores] [--format={gnu,lucid,arm}]\n\ ! 2837: [--help] [--version] [arg...]\n", ! 2838: program_name); ! 2839: exit (status); ! 2840: } ! 2841: ! 2842: #define MBUF_SIZE 512 ! 2843: char mbuffer[MBUF_SIZE]; ! 2844: ! 2845: /* Defined in the automatically-generated underscore.c. */ ! 2846: extern int prepends_underscore; ! 2847: ! 2848: int strip_underscore = 0; ! 2849: ! 2850: static struct option long_options[] = { ! 2851: {"strip-underscores", no_argument, 0, '_'}, ! 2852: {"format", required_argument, 0, 's'}, ! 2853: {"help", no_argument, 0, 'h'}, ! 2854: {"no-strip-underscores", no_argument, 0, 'n'}, ! 2855: {"version", no_argument, 0, 'v'}, ! 2856: {0, no_argument, 0, 0} ! 2857: }; ! 2858: ! 2859: int ! 2860: main (argc, argv) ! 2861: int argc; ! 2862: char **argv; ! 2863: { ! 2864: char *result; ! 2865: int c; ! 2866: ! 2867: program_name = argv[0]; ! 2868: ! 2869: strip_underscore = prepends_underscore; ! 2870: ! 2871: while ((c = getopt_long (argc, argv, "_ns:", long_options, (int *) 0)) != EOF) ! 2872: { ! 2873: switch (c) ! 2874: { ! 2875: case '?': ! 2876: usage (stderr, 1); ! 2877: break; ! 2878: case 'h': ! 2879: usage (stdout, 0); ! 2880: case 'n': ! 2881: strip_underscore = 0; ! 2882: break; ! 2883: case 'v': ! 2884: printf ("GNU %s version %s\n", program_name, program_version); ! 2885: exit (0); ! 2886: case '_': ! 2887: strip_underscore = 1; ! 2888: break; ! 2889: case 's': ! 2890: if (strcmp (optarg, "gnu") == 0) ! 2891: { ! 2892: current_demangling_style = gnu_demangling; ! 2893: } ! 2894: else if (strcmp (optarg, "lucid") == 0) ! 2895: { ! 2896: current_demangling_style = lucid_demangling; ! 2897: } ! 2898: else if (strcmp (optarg, "arm") == 0) ! 2899: { ! 2900: current_demangling_style = arm_demangling; ! 2901: } ! 2902: else ! 2903: { ! 2904: fprintf (stderr, "%s: unknown demangling style `%s'\n", ! 2905: program_name, optarg); ! 2906: exit (1); ! 2907: } ! 2908: break; ! 2909: } ! 2910: } ! 2911: ! 2912: if (optind < argc) ! 2913: { ! 2914: for ( ; optind < argc; optind++) ! 2915: { ! 2916: demangle_it (argv[optind]); ! 2917: } ! 2918: } ! 2919: else ! 2920: { ! 2921: for (;;) ! 2922: { ! 2923: int i = 0; ! 2924: c = getchar (); ! 2925: /* Try to read a label. */ ! 2926: while (c != EOF && (isalnum(c) || c == '_' || c == '$' || c == '.')) ! 2927: { ! 2928: if (i >= MBUF_SIZE-1) ! 2929: break; ! 2930: mbuffer[i++] = c; ! 2931: c = getchar (); ! 2932: } ! 2933: if (i > 0) ! 2934: { ! 2935: int skip_first = 0; ! 2936: ! 2937: if (mbuffer[0] == '.') ! 2938: ++skip_first; ! 2939: if (strip_underscore && mbuffer[skip_first] == '_') ! 2940: ++skip_first; ! 2941: ! 2942: if (skip_first > i) ! 2943: skip_first = i; ! 2944: ! 2945: mbuffer[i] = 0; ! 2946: ! 2947: result = cplus_demangle (mbuffer + skip_first, ! 2948: DMGL_PARAMS | DMGL_ANSI); ! 2949: if (result) ! 2950: { ! 2951: if (mbuffer[0] == '.') ! 2952: putc ('.', stdout); ! 2953: fputs (result, stdout); ! 2954: free (result); ! 2955: } ! 2956: else ! 2957: fputs (mbuffer, stdout); ! 2958: ! 2959: fflush (stdout); ! 2960: } ! 2961: if (c == EOF) ! 2962: break; ! 2963: putchar (c); ! 2964: } ! 2965: } ! 2966: ! 2967: exit (0); ! 2968: } ! 2969: ! 2970: static void ! 2971: fatal (str) ! 2972: char *str; ! 2973: { ! 2974: fprintf (stderr, "%s: %s\n", program_name, str); ! 2975: exit (1); ! 2976: } ! 2977: ! 2978: char * malloc (); ! 2979: char * realloc (); ! 2980: ! 2981: char * ! 2982: xmalloc (size) ! 2983: unsigned size; ! 2984: { ! 2985: register char *value = (char *) malloc (size); ! 2986: if (value == 0) ! 2987: fatal ("virtual memory exhausted"); ! 2988: return value; ! 2989: } ! 2990: ! 2991: char * ! 2992: xrealloc (ptr, size) ! 2993: char *ptr; ! 2994: unsigned size; ! 2995: { ! 2996: register char *value = (char *) realloc (ptr, size); ! 2997: if (value == 0) ! 2998: fatal ("virtual memory exhausted"); ! 2999: return value; ! 3000: } ! 3001: #endif /* main */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.