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