|
|
1.1 ! root 1: /* Demangler for GNU C++ ! 2: Copyright (C) 1989, 1992 Free Software Foundation, Inc. ! 3: written by James Clark ([email protected]) ! 4: ! 5: This program is free software; you can redistribute it and/or modify ! 6: it under the terms of the GNU General Public License as published by ! 7: the Free Software Foundation; either version 2, or (at your option) ! 8: any later version. ! 9: ! 10: This program is distributed in the hope that it will be useful, ! 11: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 13: GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 18: ! 19: /* This is for g++ 1.36.1 (November 6 version). It will probably ! 20: require changes for any other version. ! 21: ! 22: Modified for g++ 1.36.2 (November 18 version). ! 23: ! 24: Modified for g++ 1.90.06 (December 31 version). ! 25: ! 26: Modified for g++ 1.95.03 (November 13 verison). */ ! 27: ! 28: /* This file exports one function ! 29: ! 30: char *cplus_demangle (const char *name) ! 31: ! 32: If NAME is a mangled function name produced by GNU C++, then ! 33: a pointer to a malloced string giving a C++ representation ! 34: of the name will be returned; otherwise NULL will be returned. ! 35: It is the caller's responsibility to free the string which ! 36: is returned. ! 37: ! 38: For example, ! 39: ! 40: cplus_demangle ("_foo__1Ai") ! 41: ! 42: returns ! 43: ! 44: "A::foo(int)" ! 45: ! 46: This file imports xmalloc and xrealloc, which are like malloc and ! 47: realloc except that they generate a fatal error if there is no ! 48: available memory. */ ! 49: ! 50: /* #define nounderscore 1 /* define this is names don't start with _ */ ! 51: ! 52: #include <stdio.h> ! 53: #include <ctype.h> ! 54: ! 55: #ifdef USG ! 56: #include <memory.h> ! 57: #include <string.h> ! 58: #else ! 59: #include <strings.h> ! 60: #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n)) ! 61: #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n)) ! 62: #define strchr index ! 63: #define strrchr rindex ! 64: #endif ! 65: ! 66: /* This is '$' on systems where the assembler can deal with that. ! 67: Where the assembler can't, it's '.' (but on many systems '.' is ! 68: used for other things). */ ! 69: #if !defined (CPLUS_MARKER) ! 70: #define CPLUS_MARKER '$' ! 71: #endif ! 72: ! 73: #ifndef __STDC__ ! 74: #define const ! 75: #endif ! 76: ! 77: #ifdef __STDC__ ! 78: extern char *cplus_demangle (const char *type); ! 79: #else ! 80: extern char *cplus_demangle (); ! 81: #endif ! 82: ! 83: #ifdef __STDC__ ! 84: extern char *xmalloc (int); ! 85: extern char *xrealloc (char *, int); ! 86: extern void free (char *); ! 87: #else ! 88: extern char *xmalloc (); ! 89: extern char *xrealloc (); ! 90: extern void free (); ! 91: #endif ! 92: ! 93: static char **typevec = 0; ! 94: static int ntypes = 0; ! 95: static int typevec_size = 0; ! 96: ! 97: static struct { ! 98: const char *in; ! 99: const char *out; ! 100: } optable[] = { ! 101: "nw", " new", /* new (1.92, ansi) */ ! 102: "dl", " delete", /* new (1.92, ansi) */ ! 103: "new", " new", /* old (1.91) */ ! 104: "delete", " delete", /* old (1.91) */ ! 105: "ne", "!=", /* old, ansi */ ! 106: "eq", "==", /* old, ansi */ ! 107: "ge", ">=", /* old, ansi */ ! 108: "gt", ">", /* old, ansi */ ! 109: "le", "<=", /* old, ansi */ ! 110: "lt", "<", /* old, ansi */ ! 111: "plus", "+", /* old */ ! 112: "pl", "+", /* ansi */ ! 113: "apl", "+=", /* ansi */ ! 114: "minus", "-", /* old */ ! 115: "mi", "-", /* ansi */ ! 116: "ami", "-=", /* ansi */ ! 117: "mult", "*", /* old */ ! 118: "ml", "*", /* ansi */ ! 119: "aml", "*=", /* ansi */ ! 120: "convert", "+", /* old (unary +) */ ! 121: "negate", "-", /* old (unary -) */ ! 122: "trunc_mod", "%", /* old */ ! 123: "md", "%", /* ansi */ ! 124: "amd", "%=", /* ansi */ ! 125: "trunc_div", "/", /* old */ ! 126: "dv", "/", /* ansi */ ! 127: "adv", "/=", /* ansi */ ! 128: "truth_andif", "&&", /* old */ ! 129: "aa", "&&", /* ansi */ ! 130: "truth_orif", "||", /* old */ ! 131: "oo", "||", /* ansi */ ! 132: "truth_not", "!", /* old */ ! 133: "nt", "!", /* ansi */ ! 134: "postincrement", "++", /* old */ ! 135: "pp", "++", /* ansi */ ! 136: "postdecrement", "--", /* old */ ! 137: "mm", "--", /* ansi */ ! 138: "bit_ior", "|", /* old */ ! 139: "or", "|", /* ansi */ ! 140: "aor", "|=", /* ansi */ ! 141: "bit_xor", "^", /* old */ ! 142: "er", "^", /* ansi */ ! 143: "aer", "^=", /* ansi */ ! 144: "bit_and", "&", /* old */ ! 145: "ad", "&", /* ansi */ ! 146: "aad", "&=", /* ansi */ ! 147: "bit_not", "~", /* old */ ! 148: "co", "~", /* ansi */ ! 149: "call", "()", /* old */ ! 150: "cl", "()", /* ansi */ ! 151: "cond", "?:", /* old */ ! 152: "alshift", "<<", /* old */ ! 153: "ls", "<<", /* ansi */ ! 154: "als", "<<=", /* ansi */ ! 155: "arshift", ">>", /* old */ ! 156: "rs", ">>", /* ansi */ ! 157: "ars", ">>=", /* ansi */ ! 158: "component", "->", /* old */ ! 159: "rf", "->", /* ansi */ ! 160: "indirect", "*", /* old */ ! 161: "method_call", "->()", /* old */ ! 162: "addr", "&", /* old (unary &) */ ! 163: "array", "[]", /* old */ ! 164: "vc", "[]", /* ansi */ ! 165: "compound", ",", /* old */ ! 166: "cm", ",", /* ansi */ ! 167: "nop", "", /* old (for operator=) */ ! 168: }; ! 169: ! 170: /* Beware: these aren't '\0' terminated. */ ! 171: ! 172: typedef struct { ! 173: char *b; /* pointer to start of string */ ! 174: char *p; /* pointer after last character */ ! 175: char *e; /* pointer after end of allocated space */ ! 176: } string; ! 177: ! 178: #ifdef __STDC__ ! 179: static void string_need (string *s, int n); ! 180: static void string_delete (string *s); ! 181: static void string_init (string *s); ! 182: static void string_clear (string *s); ! 183: static int string_empty (string *s); ! 184: static void string_append (string *p, const char *s); ! 185: static void string_appends (string *p, string *s); ! 186: static void string_appendn (string *p, const char *s, int n); ! 187: static void string_prepend (string *p, const char *s); ! 188: #if 0 ! 189: static void string_prepends (string *p, string *s); ! 190: #endif ! 191: static void string_prependn (string *p, const char *s, int n); ! 192: static int get_count (const char **type, int *count); ! 193: static int do_args (const char **type, string *decl); ! 194: static int do_type (const char **type, string *result); ! 195: static int do_arg (const char **type, string *result); ! 196: static int do_args (const char **type, string *decl); ! 197: static void munge_function_name (string *name); ! 198: static void remember_type (const char *type, int len); ! 199: #else ! 200: static void string_need (); ! 201: static void string_delete (); ! 202: static void string_init (); ! 203: static void string_clear (); ! 204: static int string_empty (); ! 205: static void string_append (); ! 206: static void string_appends (); ! 207: static void string_appendn (); ! 208: static void string_prepend (); ! 209: static void string_prepends (); ! 210: static void string_prependn (); ! 211: static int get_count (); ! 212: static int do_args (); ! 213: static int do_type (); ! 214: static int do_arg (); ! 215: static int do_args (); ! 216: static void munge_function_name (); ! 217: static void remember_type (); ! 218: #endif ! 219: ! 220: int ! 221: get_simple_count (type, res) ! 222: char **type; ! 223: int *res; ! 224: { ! 225: int n = 0, success = 1;; ! 226: ! 227: do ! 228: { ! 229: n *= 10; ! 230: n += **type - '0'; ! 231: *type += 1; ! 232: } ! 233: while (isdigit (**type)); ! 234: if (strlen (*type) < n) ! 235: { ! 236: success = 0; ! 237: } ! 238: ! 239: *res = n; ! 240: return success; ! 241: } ! 242: ! 243: char * ! 244: cplus_demangle (type) ! 245: const char *type; ! 246: { ! 247: string decl; ! 248: int n; ! 249: int success = 0; ! 250: int constructor = 0; ! 251: int destructor = 0; ! 252: int static_type = 0; ! 253: int const_flag = 0; ! 254: int i; ! 255: const char *p; ! 256: #ifndef LONGERNAMES ! 257: const char *premangle; ! 258: #endif ! 259: ! 260: if (type == NULL || *type == '\0') ! 261: return NULL; ! 262: #ifndef nounderscore ! 263: if (*type++ != '_') ! 264: return NULL; ! 265: #endif ! 266: p = type; ! 267: while (*p != '\0' && !(*p == '_' && p[1] == '_')) ! 268: p++; ! 269: if (*p == '\0') ! 270: { ! 271: /* destructor */ ! 272: if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_') ! 273: { ! 274: destructor = 1; ! 275: p = type; ! 276: } ! 277: /* static data member */ ! 278: else if (*type != '_' && (strchr (type, CPLUS_MARKER) != NULL)) ! 279: { ! 280: static_type = 1; ! 281: p = type; ! 282: } ! 283: /* virtual table "_vt$" */ ! 284: else if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER) ! 285: { ! 286: int n = strlen (type + 4) + 14 + 1; ! 287: char *tem = (char *) xmalloc (n); ! 288: strcpy (tem, type + 4); ! 289: strcat (tem, " virtual table"); ! 290: return tem; ! 291: } ! 292: else return NULL; ! 293: } ! 294: ! 295: string_init (&decl); ! 296: ! 297: if (static_type) ! 298: { ! 299: if (!isdigit (p[0]) && ('t' != p[0])) ! 300: { ! 301: string_delete (&decl); ! 302: return NULL; ! 303: } ! 304: } ! 305: else if (destructor) ! 306: { ! 307: if (!isdigit (p[3])&& ('t' != p[3])) ! 308: { ! 309: string_delete (&decl); ! 310: return NULL; ! 311: } ! 312: p += 3; ! 313: } ! 314: else if (p == type) ! 315: { ! 316: if (!isdigit (p[2]) && ('t' != p[2])) ! 317: { ! 318: p += 1; ! 319: while (*p != '\0' && !(*p == '_' && p[1] == '_')) ! 320: p++; ! 321: string_appendn (&decl, type, p - type); ! 322: string_appendn (&decl, "", 1); ! 323: munge_function_name (&decl); ! 324: if (decl.b[0] == '_') ! 325: { ! 326: string_delete (&decl); ! 327: return NULL; ! 328: } ! 329: else ! 330: p += 2; ! 331: } ! 332: else ! 333: { ! 334: constructor = 1; ! 335: p += 2; ! 336: } ! 337: } ! 338: else ! 339: { ! 340: string_appendn (&decl, type, p - type); ! 341: decl.p[0] = '0'; ! 342: munge_function_name (&decl); ! 343: p += 2; ! 344: } ! 345: ! 346: #ifndef LONGERNAMES ! 347: premangle = p; ! 348: #endif ! 349: switch (*p) ! 350: { ! 351: case 'C': ! 352: /* a const member function */ ! 353: if (!isdigit (p[1])) ! 354: { ! 355: string_delete (&decl); ! 356: return NULL; ! 357: } ! 358: p += 1; ! 359: const_flag = 1; ! 360: /* fall through */ ! 361: case '0': ! 362: case '1': ! 363: case '2': ! 364: case '3': ! 365: case '4': ! 366: case '5': ! 367: case '6': ! 368: case '7': ! 369: case '8': ! 370: case '9': ! 371: n = 0; ! 372: do ! 373: { ! 374: n *= 10; ! 375: n += *p - '0'; ! 376: p += 1; ! 377: } ! 378: while (isdigit (*p)); ! 379: if (strlen (p) < n) ! 380: { ! 381: string_delete (&decl); ! 382: return NULL; ! 383: } ! 384: if (constructor || destructor) ! 385: { ! 386: string_appendn (&decl, p, n); ! 387: string_append (&decl, "::"); ! 388: if (destructor) ! 389: string_append(&decl, "~"); ! 390: string_appendn (&decl, p, n); ! 391: } ! 392: else ! 393: { ! 394: string_prepend (&decl, "::"); ! 395: string_prependn (&decl, p, n); ! 396: } ! 397: p += n; ! 398: #ifndef LONGERNAMES ! 399: remember_type (premangle, p - premangle); ! 400: #endif ! 401: if (static_type) ! 402: { ! 403: string_append(&decl, p+1); ! 404: p += strlen(p); ! 405: success = 1; ! 406: } ! 407: else ! 408: success = do_args (&p, &decl); ! 409: if (const_flag) ! 410: string_append (&decl, " const"); ! 411: break; ! 412: case 'F': ! 413: p += 1; ! 414: success = do_args (&p, &decl); ! 415: break; ! 416: /* template additions */ ! 417: case 't': ! 418: p += 1; ! 419: { ! 420: int r, i; ! 421: int non_empty = 0; ! 422: string tname; ! 423: string trawname; ! 424: ! 425: string temp; ! 426: int need_comma = 0; ! 427: ! 428: string_init(&tname); ! 429: string_init(&trawname); ! 430: ! 431: /* get template name */ ! 432: if (!get_simple_count (&p, &r)) ! 433: { ! 434: string_delete (&decl); ! 435: return 0; ! 436: } ! 437: string_appendn (&tname, p, r); ! 438: string_appendn (&trawname, p, r); ! 439: string_appendn (&trawname, "", 1); ! 440: p += r; ! 441: string_append (&tname, "<"); ! 442: /* get size of template parameter list */ ! 443: if (!get_count (&p, &r)) ! 444: return 0; ! 445: for (i = 0; i < r; i++) ! 446: { ! 447: if (need_comma) ! 448: string_append (&tname, ", "); ! 449: /* Z for type parameters */ ! 450: if (*p == 'Z') ! 451: { ! 452: p += 1; ! 453: ! 454: success = do_type (&p, &temp); ! 455: string_appendn (&temp, "", 1); ! 456: if (success) ! 457: string_append (&tname, temp.b); ! 458: string_delete(&temp); ! 459: if (!success) ! 460: break; ! 461: } ! 462: /* otherwise, value parameter */ ! 463: else ! 464: { ! 465: const char *old_p = p; ! 466: int is_pointer = 0; ! 467: int is_real = 0; ! 468: int is_integral = 0; ! 469: int done = 0; ! 470: ! 471: success = do_type (&p, &temp); ! 472: string_appendn (&temp, "", 1); ! 473: if (success) ! 474: string_append (&tname, temp.b); ! 475: string_delete(&temp); ! 476: if (!success) ! 477: break; ! 478: string_append (&tname, "="); ! 479: while (*old_p && !done) ! 480: { ! 481: switch (*old_p) ! 482: { ! 483: case 'P': ! 484: case 'R': ! 485: done = is_pointer = 1; ! 486: break; ! 487: case 'C': /* const */ ! 488: case 'U': /* unsigned */ ! 489: case 'V': /* volatile */ ! 490: case 'F': /* function */ ! 491: case 'M': /* member function */ ! 492: case 'O': /* ??? */ ! 493: old_p++; ! 494: continue; ! 495: case 'Q': /* repetition of following */ ! 496: case 'T': /* remembered type */ ! 497: abort(); ! 498: break; ! 499: case 'v': /* void */ ! 500: abort(); ! 501: break; ! 502: case 'x': /* long long */ ! 503: case 'l': /* long */ ! 504: case 'i': /* int */ ! 505: case 's': /* short */ ! 506: case 'c': /* char */ ! 507: done = is_integral = 1; ! 508: break; ! 509: case 'r': /* long double */ ! 510: case 'd': /* double */ ! 511: case 'f': /* float */ ! 512: done = is_real = 1; ! 513: break; ! 514: default: ! 515: abort(); ! 516: } ! 517: } ! 518: if (is_integral) ! 519: { ! 520: if (*p == 'm') ! 521: { ! 522: string_appendn (&tname, "-", 1); ! 523: p++; ! 524: } ! 525: while (isdigit (*p)) ! 526: { ! 527: string_appendn (&tname, p, 1); ! 528: p++; ! 529: } ! 530: } ! 531: else if (is_real) ! 532: { ! 533: if (*p == 'm') ! 534: { ! 535: string_appendn (&tname, "-", 1); ! 536: p++; ! 537: } ! 538: while (isdigit (*p)) ! 539: { ! 540: string_appendn (&tname, p, 1); ! 541: p++; ! 542: } ! 543: if (*p == '.') /* fraction */ ! 544: { ! 545: string_appendn (&tname, ".", 1); ! 546: p++; ! 547: while (isdigit (*p)) ! 548: { ! 549: string_appendn (&tname, p, 1); ! 550: p++; ! 551: } ! 552: } ! 553: if (*p == 'e') /* exponent */ ! 554: { ! 555: string_appendn (&tname, "e", 1); ! 556: p++; ! 557: while (isdigit (*p)) ! 558: { ! 559: string_appendn (&tname, p, 1); ! 560: p++; ! 561: } ! 562: } ! 563: } ! 564: else if (is_pointer) ! 565: { ! 566: int symbol_len; ! 567: ! 568: if (!get_count (&p, &symbol_len)) ! 569: { ! 570: success = 0; ! 571: break; ! 572: } ! 573: string_appendn (&tname, p, symbol_len); ! 574: p += symbol_len; ! 575: } ! 576: } ! 577: need_comma = 1; ! 578: } ! 579: string_append (&tname, ">::"); ! 580: if (destructor) ! 581: string_append(&tname, "~"); ! 582: if (constructor || destructor) { ! 583: string_appendn (&trawname, "", 1); ! 584: string_append (&tname, trawname.b); ! 585: } ! 586: string_delete(&trawname); ! 587: ! 588: if (!success) { ! 589: string_delete(&tname); ! 590: return 0; ! 591: } ! 592: string_appendn (&tname, "", 1); ! 593: string_prepend (&decl, tname.b); ! 594: string_delete (&tname); ! 595: ! 596: if (static_type) ! 597: { ! 598: string_append (&decl, p+1); ! 599: p += strlen (p); ! 600: success = 1; ! 601: } ! 602: else ! 603: success = do_args (&p, &decl); ! 604: break; ! 605: } ! 606: } ! 607: ! 608: for (i = 0; i < ntypes; i++) ! 609: if (typevec[i] != NULL) ! 610: free (typevec[i]); ! 611: ntypes = 0; ! 612: if (typevec != NULL) ! 613: { ! 614: free ((char *)typevec); ! 615: typevec = NULL; ! 616: typevec_size = 0; ! 617: } ! 618: ! 619: if (success) ! 620: { ! 621: string_appendn (&decl, "", 1); ! 622: return decl.b; ! 623: } ! 624: else ! 625: { ! 626: string_delete (&decl); ! 627: return NULL; ! 628: } ! 629: } ! 630: ! 631: static int ! 632: get_count (type, count) ! 633: const char **type; ! 634: int *count; ! 635: { ! 636: if (!isdigit (**type)) ! 637: return 0; ! 638: *count = **type - '0'; ! 639: *type += 1; ! 640: /* see flush_repeats in cp-method.c */ ! 641: if (isdigit (**type)) ! 642: { ! 643: const char *p = *type; ! 644: int n = *count; ! 645: do ! 646: { ! 647: n *= 10; ! 648: n += *p - '0'; ! 649: p += 1; ! 650: } ! 651: while (isdigit (*p)); ! 652: if (*p == '_') ! 653: { ! 654: *type = p + 1; ! 655: *count = n; ! 656: } ! 657: } ! 658: return 1; ! 659: } ! 660: ! 661: /* result will be initialised here; it will be freed on failure */ ! 662: ! 663: static int ! 664: do_type (type, result) ! 665: const char **type; ! 666: string *result; ! 667: { ! 668: int n; ! 669: int done; ! 670: int non_empty = 0; ! 671: int success; ! 672: string decl; ! 673: const char *remembered_type; ! 674: ! 675: string_init (&decl); ! 676: string_init (result); ! 677: ! 678: done = 0; ! 679: success = 1; ! 680: while (success && !done) ! 681: { ! 682: int member; ! 683: switch (**type) ! 684: { ! 685: case 'Q': ! 686: n = (*type)[1] - '0'; ! 687: if (n < 0 || n > 9) ! 688: success = 0; ! 689: *type += 2; ! 690: while (n-- > 0) ! 691: do_type (type, result); ! 692: break; ! 693: ! 694: case 'P': ! 695: *type += 1; ! 696: string_prepend (&decl, "*"); ! 697: break; ! 698: ! 699: case 'R': ! 700: *type += 1; ! 701: string_prepend (&decl, "&"); ! 702: break; ! 703: ! 704: case 'T': ! 705: *type += 1; ! 706: if (!get_count (type, &n) || n >= ntypes) ! 707: success = 0; ! 708: else ! 709: { ! 710: remembered_type = typevec[n]; ! 711: type = &remembered_type; ! 712: } ! 713: break; ! 714: ! 715: case 'F': ! 716: *type += 1; ! 717: if (!string_empty (&decl) && decl.b[0] == '*') ! 718: { ! 719: string_prepend (&decl, "("); ! 720: string_append (&decl, ")"); ! 721: } ! 722: if (!do_args (type, &decl) || **type != '_') ! 723: success = 0; ! 724: else ! 725: *type += 1; ! 726: break; ! 727: ! 728: case 'M': ! 729: case 'O': ! 730: { ! 731: int constp = 0; ! 732: int volatilep = 0; ! 733: ! 734: member = **type == 'M'; ! 735: *type += 1; ! 736: if (!isdigit (**type)) ! 737: { ! 738: success = 0; ! 739: break; ! 740: } ! 741: n = 0; ! 742: do ! 743: { ! 744: n *= 10; ! 745: n += **type - '0'; ! 746: *type += 1; ! 747: } ! 748: while (isdigit (**type)); ! 749: if (strlen (*type) < n) ! 750: { ! 751: success = 0; ! 752: break; ! 753: } ! 754: string_append (&decl, ")"); ! 755: string_prepend (&decl, "::"); ! 756: string_prependn (&decl, *type, n); ! 757: string_prepend (&decl, "("); ! 758: *type += n; ! 759: if (member) ! 760: { ! 761: if (**type == 'C') ! 762: { ! 763: *type += 1; ! 764: constp = 1; ! 765: } ! 766: if (**type == 'V') ! 767: { ! 768: *type += 1; ! 769: volatilep = 1; ! 770: } ! 771: if (*(*type)++ != 'F') ! 772: { ! 773: success = 0; ! 774: break; ! 775: } ! 776: } ! 777: if ((member && !do_args (type, &decl)) || **type != '_') ! 778: { ! 779: success = 0; ! 780: break; ! 781: } ! 782: *type += 1; ! 783: if (constp) ! 784: { ! 785: if (non_empty) ! 786: string_append (&decl, " "); ! 787: else ! 788: non_empty = 1; ! 789: string_append (&decl, "const"); ! 790: } ! 791: if (volatilep) ! 792: { ! 793: if (non_empty) ! 794: string_append (&decl, " "); ! 795: else ! 796: non_empty = 1; ! 797: string_append (&decl, "volatile"); ! 798: } ! 799: break; ! 800: } ! 801: ! 802: case 'C': ! 803: if ((*type)[1] == 'P') ! 804: { ! 805: *type += 1; ! 806: if (!string_empty (&decl)) ! 807: string_prepend (&decl, " "); ! 808: string_prepend (&decl, "const"); ! 809: break; ! 810: } ! 811: ! 812: /* fall through */ ! 813: default: ! 814: done = 1; ! 815: break; ! 816: } ! 817: } ! 818: ! 819: non_empty = 0; ! 820: if (success) ! 821: success = do_cuv_prefix (type, result, &non_empty); ! 822: ! 823: if (success) ! 824: success = do_builtin_type(type, result, &non_empty); ! 825: ! 826: if (success) ! 827: { ! 828: if (!string_empty (&decl)) ! 829: { ! 830: string_append (result, " "); ! 831: string_appends (result, &decl); ! 832: } ! 833: string_delete (&decl); ! 834: return 1; ! 835: } ! 836: else ! 837: { ! 838: string_delete (&decl); ! 839: string_delete (result); ! 840: return 0; ! 841: } ! 842: } ! 843: ! 844: int ! 845: do_cuv_prefix (type, result, non_empty) ! 846: char **type; ! 847: string* result; ! 848: int* non_empty; ! 849: { ! 850: int success = 1; ! 851: int done = 0; ! 852: ! 853: while (success && !done) ! 854: { ! 855: switch (**type) ! 856: { ! 857: case 'C': ! 858: *type += 1; ! 859: if (*non_empty) ! 860: string_append (result, " "); ! 861: else ! 862: *non_empty = 1; ! 863: string_append (result, "const"); ! 864: break; ! 865: case 'U': ! 866: *type += 1; ! 867: if (*non_empty) ! 868: string_append (result, " "); ! 869: else ! 870: *non_empty = 1; ! 871: string_append (result, "unsigned"); ! 872: break; ! 873: case 'V': ! 874: *type += 1; ! 875: if (*non_empty) ! 876: string_append (result, " "); ! 877: else ! 878: *non_empty = 1; ! 879: string_append (result, "volatile"); ! 880: break; ! 881: default: ! 882: done = 1; ! 883: break; ! 884: } ! 885: } ! 886: return success; ! 887: } ! 888: ! 889: int ! 890: do_builtin_type (type, result, non_empty) ! 891: char **type; ! 892: string* result; ! 893: int *non_empty; ! 894: { ! 895: int success = 1; ! 896: int n; ! 897: ! 898: switch (**type) ! 899: { ! 900: case '\0': ! 901: case '_': ! 902: break; ! 903: case 'v': ! 904: *type += 1; ! 905: if (*non_empty) ! 906: string_append (result, " "); ! 907: string_append (result, "void"); ! 908: break; ! 909: case 'x': ! 910: *type += 1; ! 911: if (*non_empty) ! 912: string_append (result, " "); ! 913: string_append (result, "long long"); ! 914: break; ! 915: case 'l': ! 916: *type += 1; ! 917: if (*non_empty) ! 918: string_append (result, " "); ! 919: string_append (result, "long"); ! 920: break; ! 921: case 'i': ! 922: *type += 1; ! 923: if (*non_empty) ! 924: string_append (result, " "); ! 925: string_append (result, "int"); ! 926: break; ! 927: case 's': ! 928: *type += 1; ! 929: if (*non_empty) ! 930: string_append (result, " "); ! 931: string_append (result, "short"); ! 932: break; ! 933: case 'c': ! 934: *type += 1; ! 935: if (*non_empty) ! 936: string_append (result, " "); ! 937: string_append (result, "char"); ! 938: break; ! 939: case 'r': ! 940: *type += 1; ! 941: if (*non_empty) ! 942: string_append (result, " "); ! 943: string_append (result, "long double"); ! 944: break; ! 945: case 'd': ! 946: *type += 1; ! 947: if (*non_empty) ! 948: string_append (result, " "); ! 949: string_append (result, "double"); ! 950: break; ! 951: case 'f': ! 952: *type += 1; ! 953: if (*non_empty) ! 954: string_append (result, " "); ! 955: string_append (result, "float"); ! 956: break; ! 957: case 'G': ! 958: *type += 1; ! 959: if (!isdigit (**type)) ! 960: { ! 961: success = 0; ! 962: break; ! 963: } ! 964: /* fall through */ ! 965: case '0': ! 966: case '1': ! 967: case '2': ! 968: case '3': ! 969: case '4': ! 970: case '5': ! 971: case '6': ! 972: case '7': ! 973: case '8': ! 974: case '9': ! 975: n = 0; ! 976: do ! 977: { ! 978: n *= 10; ! 979: n += **type - '0'; ! 980: *type += 1; ! 981: } ! 982: while (isdigit (**type)); ! 983: if (strlen (*type) < n) ! 984: { ! 985: success = 0; ! 986: break; ! 987: } ! 988: if (*non_empty) ! 989: string_append (result, " "); ! 990: string_appendn (result, *type, n); ! 991: *type += n; ! 992: break; ! 993: default: ! 994: success = 0; ! 995: break; ! 996: } ! 997: return success; ! 998: } ! 999: ! 1000: /* `result' will be initialised in do_type; it will be freed on failure */ ! 1001: ! 1002: static int ! 1003: do_arg (type, result) ! 1004: const char **type; ! 1005: string *result; ! 1006: { ! 1007: const char *start = *type; ! 1008: ! 1009: if (!do_type (type, result)) ! 1010: return 0; ! 1011: remember_type (start, *type - start); ! 1012: return 1; ! 1013: } ! 1014: ! 1015: static void ! 1016: remember_type (start, len) ! 1017: const char *start; ! 1018: int len; ! 1019: { ! 1020: char *tem; ! 1021: ! 1022: if (ntypes >= typevec_size) ! 1023: { ! 1024: if (typevec_size == 0) ! 1025: { ! 1026: typevec_size = 3; ! 1027: typevec = (char **) xmalloc (sizeof (char*)*typevec_size); ! 1028: } ! 1029: else ! 1030: { ! 1031: typevec_size *= 2; ! 1032: typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size); ! 1033: } ! 1034: } ! 1035: tem = (char *) xmalloc (len + 1); ! 1036: memcpy (tem, start, len); ! 1037: tem[len] = '\0'; ! 1038: typevec[ntypes++] = tem; ! 1039: } ! 1040: ! 1041: /* `decl' must be already initialised, usually non-empty; ! 1042: it won't be freed on failure */ ! 1043: ! 1044: static int ! 1045: do_args (type, decl) ! 1046: const char **type; ! 1047: string *decl; ! 1048: { ! 1049: string arg; ! 1050: int need_comma = 0; ! 1051: ! 1052: string_append (decl, "("); ! 1053: ! 1054: while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v') ! 1055: { ! 1056: if (**type == 'N') ! 1057: { ! 1058: int r; ! 1059: int t; ! 1060: *type += 1; ! 1061: if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes) ! 1062: return 0; ! 1063: while (--r >= 0) ! 1064: { ! 1065: const char *tem = typevec[t]; ! 1066: if (need_comma) ! 1067: string_append (decl, ", "); ! 1068: if (!do_arg (&tem, &arg)) ! 1069: return 0; ! 1070: string_appends (decl, &arg); ! 1071: string_delete (&arg); ! 1072: need_comma = 1; ! 1073: } ! 1074: } ! 1075: else ! 1076: { ! 1077: if (need_comma) ! 1078: string_append (decl, ", "); ! 1079: if (!do_arg (type, &arg)) ! 1080: return 0; ! 1081: string_appends (decl, &arg); ! 1082: string_delete (&arg); ! 1083: need_comma = 1; ! 1084: } ! 1085: } ! 1086: ! 1087: if (**type == 'v') ! 1088: *type += 1; ! 1089: else if (**type == 'e') ! 1090: { ! 1091: *type += 1; ! 1092: if (need_comma) ! 1093: string_append (decl, ","); ! 1094: string_append (decl, "..."); ! 1095: } ! 1096: ! 1097: string_append (decl, ")"); ! 1098: return 1; ! 1099: } ! 1100: ! 1101: static void ! 1102: munge_function_name (name) ! 1103: string *name; ! 1104: { ! 1105: if (string_empty (name)) ! 1106: return; ! 1107: ! 1108: if (name->p - name->b >= 3 ! 1109: && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER) ! 1110: { ! 1111: int i; ! 1112: /* see if it's an assignment expression */ ! 1113: if (name->p - name->b >= 10 /* op$assign_ */ ! 1114: && memcmp (name->b + 3, "assign_", 7) == 0) ! 1115: { ! 1116: for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) ! 1117: { ! 1118: int len = name->p - name->b - 10; ! 1119: if (strlen (optable[i].in) == len ! 1120: && memcmp (optable[i].in, name->b + 10, len) == 0) ! 1121: { ! 1122: string_clear (name); ! 1123: string_append (name, "operator"); ! 1124: string_append (name, optable[i].out); ! 1125: string_append (name, "="); ! 1126: return; ! 1127: } ! 1128: } ! 1129: } ! 1130: else ! 1131: { ! 1132: for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) ! 1133: { ! 1134: int len = name->p - name->b - 3; ! 1135: if (strlen (optable[i].in) == len ! 1136: && memcmp (optable[i].in, name->b + 3, len) == 0) ! 1137: { ! 1138: string_clear (name); ! 1139: string_append (name, "operator"); ! 1140: string_append (name, optable[i].out); ! 1141: return; ! 1142: } ! 1143: } ! 1144: } ! 1145: return; ! 1146: } ! 1147: else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0) ! 1148: { ! 1149: /* type conversion operator */ ! 1150: string type; ! 1151: const char *tem = name->b + 5; ! 1152: if (do_type (&tem, &type)) ! 1153: { ! 1154: string_clear (name); ! 1155: string_append (name, "operator "); ! 1156: string_appends (name, &type); ! 1157: string_delete (&type); ! 1158: return; ! 1159: } ! 1160: } ! 1161: /* ANSI. */ ! 1162: else if (name->b[2] == 'o' && name->b[3] == 'p') ! 1163: { ! 1164: /* type conversion operator. */ ! 1165: string type; ! 1166: const char *tem = name->b + 4; ! 1167: if (do_type (&tem, &type)) ! 1168: { ! 1169: string_clear (name); ! 1170: string_append (name, "operator "); ! 1171: string_appends (name, &type); ! 1172: string_delete (&type); ! 1173: return; ! 1174: } ! 1175: } ! 1176: else if (name->b[2] >= 'a' && name->b[2] <= 'z' ! 1177: && name->b[3] >= 'a' && name->b[3] <= 'z') ! 1178: { ! 1179: int i; ! 1180: ! 1181: if (name->b[4] == '\0') ! 1182: { ! 1183: /* Operator. */ ! 1184: for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) ! 1185: { ! 1186: if (strlen (optable[i].in) == 2 ! 1187: && memcmp (optable[i].in, name->b + 2, 2) == 0) ! 1188: { ! 1189: string_clear (name); ! 1190: string_append (name, "operator"); ! 1191: string_append (name, optable[i].out); ! 1192: return; ! 1193: } ! 1194: } ! 1195: } ! 1196: else ! 1197: { ! 1198: if (name->b[2] != 'a' || name->b[5] != '\0') ! 1199: return; ! 1200: /* Assignment. */ ! 1201: for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) ! 1202: { ! 1203: if (strlen (optable[i].in) == 3 ! 1204: && memcmp (optable[i].in, name->b + 2, 3) == 0) ! 1205: { ! 1206: string_clear (name); ! 1207: string_append (name, "operator"); ! 1208: string_append (name, optable[i].out); ! 1209: return; ! 1210: } ! 1211: } ! 1212: } ! 1213: } ! 1214: } ! 1215: ! 1216: /* a mini string-handling package */ ! 1217: ! 1218: static void ! 1219: string_need (s, n) ! 1220: string *s; ! 1221: int n; ! 1222: { ! 1223: if (s->b == NULL) ! 1224: { ! 1225: if (n < 32) ! 1226: n = 32; ! 1227: s->p = s->b = (char *) xmalloc (n); ! 1228: s->e = s->b + n; ! 1229: } ! 1230: else if (s->e - s->p < n) ! 1231: { ! 1232: int tem = s->p - s->b; ! 1233: n += tem; ! 1234: n *= 2; ! 1235: s->b = (char *) xrealloc (s->b, n); ! 1236: s->p = s->b + tem; ! 1237: s->e = s->b + n; ! 1238: } ! 1239: } ! 1240: ! 1241: static void ! 1242: string_delete (s) ! 1243: string *s; ! 1244: { ! 1245: if (s->b != NULL) ! 1246: { ! 1247: free (s->b); ! 1248: s->b = s->e = s->p = NULL; ! 1249: } ! 1250: } ! 1251: ! 1252: static void ! 1253: string_init (s) ! 1254: string *s; ! 1255: { ! 1256: s->b = s->p = s->e = NULL; ! 1257: } ! 1258: ! 1259: static void ! 1260: string_clear (s) ! 1261: string *s; ! 1262: { ! 1263: s->p = s->b; ! 1264: } ! 1265: ! 1266: static int ! 1267: string_empty (s) ! 1268: string *s; ! 1269: { ! 1270: return s->b == s->p; ! 1271: } ! 1272: ! 1273: static void ! 1274: string_append (p, s) ! 1275: string *p; ! 1276: const char *s; ! 1277: { ! 1278: int n; ! 1279: if (s == NULL || *s == '\0') ! 1280: return; ! 1281: n = strlen (s); ! 1282: string_need (p, n); ! 1283: memcpy (p->p, s, n); ! 1284: p->p += n; ! 1285: } ! 1286: ! 1287: static void ! 1288: string_appends (p, s) ! 1289: string *p, *s; ! 1290: { ! 1291: int n; ! 1292: if (s->b == s->p) ! 1293: return; ! 1294: n = s->p - s->b; ! 1295: string_need (p, n); ! 1296: memcpy (p->p, s->b, n); ! 1297: p->p += n; ! 1298: } ! 1299: ! 1300: static void ! 1301: string_appendn (p, s, n) ! 1302: string *p; ! 1303: const char *s; ! 1304: int n; ! 1305: { ! 1306: if (n == 0) ! 1307: return; ! 1308: string_need (p, n); ! 1309: memcpy (p->p, s, n); ! 1310: p->p += n; ! 1311: } ! 1312: ! 1313: static void ! 1314: string_prepend (p, s) ! 1315: string *p; ! 1316: const char *s; ! 1317: { ! 1318: if (s == NULL || *s == '\0') ! 1319: return; ! 1320: string_prependn (p, s, strlen (s)); ! 1321: } ! 1322: ! 1323: #if 0 ! 1324: static void ! 1325: string_prepends (p, s) ! 1326: string *p, *s; ! 1327: { ! 1328: if (s->b == s->p) ! 1329: return; ! 1330: string_prependn (p, s->b, s->p - s->b); ! 1331: } ! 1332: #endif ! 1333: ! 1334: static void ! 1335: string_prependn (p, s, n) ! 1336: string *p; ! 1337: const char *s; ! 1338: int n; ! 1339: { ! 1340: char *q; ! 1341: ! 1342: if (n == 0) ! 1343: return; ! 1344: string_need (p, n); ! 1345: for (q = p->p - 1; q >= p->b; q--) ! 1346: q[n] = q[0]; ! 1347: memcpy (p->b, s, n); ! 1348: p->p += n; ! 1349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.