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