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