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