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