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