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