Tue Mar 3 15:11:52 1992 Michael Tiemann (tiemann@cygnus.com)
[deliverable/binutils-gdb.git] / gdb / cplus-dem.c
CommitLineData
dd3b648e 1/* Demangler for GNU C++
7d9884b9 2 Copyright 1989, 1991 Free Software Foundation, Inc.
dd3b648e
RP
3 written by James Clark (jjc@jclark.uucp)
4
572acbbe
MT
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
99a7de40 9
572acbbe
MT
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
99a7de40 14
572acbbe
MT
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
dd3b648e 18
7d9884b9 19/* This is for g++ 1.95.03 (November 13 verison). */
dd3b648e
RP
20
21/* This file exports one function
22
23 char *cplus_demangle (const char *name, int mode)
572acbbe 24
dd3b648e
RP
25 If NAME is a mangled function name produced by GNU C++, then
26 a pointer to a malloced string giving a C++ representation
27 of the name will be returned; otherwise NULL will be returned.
28 It is the caller's responsibility to free the string which
29 is returned.
30
31 If MODE > 0, then ANSI qualifiers such as `const' and `void' are output.
32 Otherwise they are not.
33 If MODE >= 0, parameters are emitted; otherwise not.
34
35 For example,
36
37 cplus_demangle ("foo__1Ai", 0) => "A::foo(int)"
38 cplus_demangle ("foo__1Ai", 1) => "A::foo(int)"
39 cplus_demangle ("foo__1Ai", -1) => "A::foo"
40
41 cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)"
42 cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)"
43 cplus_demangle ("foo__1Afe", -1) => "A::foo"
44
45 This file imports xmalloc and xrealloc, which are like malloc and
46 realloc except that they generate a fatal error if there is no
47 available memory. */
48
49/* define this if names don't start with _ */
50/* #define nounderscore 1 */
51
e1ce8aa5
JK
52/* GDB-specific, FIXME. */
53#include "defs.h"
e1ce8aa5 54
d747e0af
MT
55#include <ctype.h>
56
dd3b648e
RP
57#ifdef USG
58#include <memory.h>
59#include <string.h>
60#else
61#include <strings.h>
dd3b648e
RP
62#endif
63
8ffd75c8
JG
64/* This is '$' on systems where the assembler can deal with that.
65 Where the assembler can't, it's '.' (but on many systems '.' is
66 used for other things). */
67#if !defined (CPLUS_MARKER)
68#define CPLUS_MARKER '$'
69#endif
70
dd3b648e
RP
71#ifndef __STDC__
72#define const
73#endif
74
75#ifdef __STDC__
76extern char *cplus_demangle (const char *type, int mode);
77#else
78extern char *cplus_demangle ();
79#endif
80
81#ifdef __STDC__
2cb3be2c
JK
82/* GDB prototypes these as void* in defs.h, so we better too, at least
83 as long as we're including defs.h. */
088c3a0b
JG
84/* FIXME extern void *xmalloc (int);
85 extern void *xrealloc (char *, int); */
d11c44f1 86extern void free (void *);
dd3b648e
RP
87#else
88extern char *xmalloc ();
89extern char *xrealloc ();
90extern void free ();
91#endif
92
93static char **typevec = 0;
94static int ntypes = 0;
95static int typevec_size = 0;
96
ef98d5ac 97const static struct optable {
dd3b648e
RP
98 const char *in;
99 const char *out;
572acbbe 100 int ansi;
dd3b648e 101} optable[] = {
572acbbe
MT
102 "nw", " new", 1, /* new (1.92, ansi) */
103 "dl", " delete", 1, /* new (1.92, ansi) */
104 "new", " new", 0, /* old (1.91, and 1.x) */
105 "delete", " delete", 0, /* old (1.91, and 1.x) */
106 "as", "=", 1, /* ansi */
107 "ne", "!=", 1, /* old, ansi */
108 "eq", "==", 1, /* old, ansi */
109 "ge", ">=", 1, /* old, ansi */
110 "gt", ">", 1, /* old, ansi */
111 "le", "<=", 1, /* old, ansi */
112 "lt", "<", 1, /* old, ansi */
113 "plus", "+", 0, /* old */
114 "pl", "+", 1, /* ansi */
115 "apl", "+=", 1, /* ansi */
116 "minus", "-", 0, /* old */
117 "mi", "-", 1, /* ansi */
118 "ami", "-=", 1, /* ansi */
119 "mult", "*", 0, /* old */
120 "ml", "*", 1, /* ansi */
121 "aml", "*=", 1, /* ansi */
122 "convert", "+", 0, /* old (unary +) */
123 "negate", "-", 0, /* old (unary -) */
124 "trunc_mod", "%", 0, /* old */
125 "md", "%", 1, /* ansi */
126 "amd", "%=", 1, /* ansi */
127 "trunc_div", "/", 0, /* old */
128 "dv", "/", 1, /* ansi */
129 "adv", "/=", 1, /* ansi */
130 "truth_andif", "&&", 0, /* old */
131 "aa", "&&", 1, /* ansi */
132 "truth_orif", "||", 0, /* old */
133 "oo", "||", 1, /* ansi */
134 "truth_not", "!", 0, /* old */
135 "nt", "!", 1, /* ansi */
136 "postincrement", "++", 0, /* old */
137 "pp", "++", 1, /* ansi */
138 "postdecrement", "--", 0, /* old */
139 "mm", "--", 1, /* ansi */
140 "bit_ior", "|", 0, /* old */
141 "or", "|", 1, /* ansi */
142 "aor", "|=", 1, /* ansi */
143 "bit_xor", "^", 0, /* old */
144 "er", "^", 1, /* ansi */
145 "aer", "^=", 1, /* ansi */
146 "bit_and", "&", 0, /* old */
147 "ad", "&", 1, /* ansi */
148 "aad", "&=", 1, /* ansi */
149 "bit_not", "~", 0, /* old */
150 "co", "~", 1, /* ansi */
151 "call", "()", 0, /* old */
152 "cl", "()", 1, /* ansi */
153 "alshift", "<<", 0, /* old */
154 "ls", "<<", 1, /* ansi */
155 "als", "<<=", 1, /* ansi */
156 "arshift", ">>", 0, /* old */
157 "rs", ">>", 1, /* ansi */
158 "ars", ">>=", 1, /* ansi */
159 "component", "->", 0, /* old */
160 "rf", "->", 1, /* ansi */
161 "indirect", "*", 0, /* old */
162 "method_call", "->()", 0, /* old */
163 "addr", "&", 0, /* old (unary &) */
164 "array", "[]", 0, /* old */
165 "vc", "[]", 1, /* ansi */
166 "compound", ",", 0, /* old */
167 "cm", ",", 1, /* ansi */
168 "cond", "?:", 0, /* old */
169 "cn", "?:", 1, /* psuedo-ansi */
170 "max", ">?", 0, /* old */
171 "mx", ">?", 1, /* psuedo-ansi */
172 "min", "<?", 0, /* old */
173 "mn", "<?", 1, /* psuedo-ansi */
174 "nop", "", 0, /* old (for operator=) */
dd3b648e
RP
175};
176
177/* Beware: these aren't '\0' terminated. */
178
ef98d5ac 179typedef struct string {
dd3b648e
RP
180 char *b; /* pointer to start of string */
181 char *p; /* pointer after last character */
182 char *e; /* pointer after end of allocated space */
183} string;
184
1ab3bf1b
JG
185static void
186string_need PARAMS ((string *, int));
187
188static void
189string_delete PARAMS ((string *));
190
191static void
192string_init PARAMS ((string *));
193
194static void
195string_clear PARAMS ((string *));
196
197static int
198string_empty PARAMS ((string *));
199
200static void
201string_append PARAMS ((string *, const char *));
202
203static void
204string_appends PARAMS ((string *, string *));
205
206static void
207string_appendn PARAMS ((string *, const char *, int));
208
209static void
210string_prepend PARAMS ((string *, const char *));
211
212static void
213string_prependn PARAMS ((string *, const char *, int));
214
215static int
216get_count PARAMS ((const char **, int *));
217
218static int
219do_args PARAMS ((const char **, string *, int));
220
221static int
222do_type PARAMS ((const char **, string *, int));
223
224static int
225do_arg PARAMS ((const char **, string *, int));
226
227static void
228munge_function_name PARAMS ((string *, int));
229
230static void
231remember_type PARAMS ((const char *, int));
232
dd3b648e 233#if 0
1ab3bf1b
JG
234static void
235string_prepends PARAMS ((string *, string *));
dd3b648e
RP
236#endif
237
1ab3bf1b 238
55838914 239/* Takes operator name as e.g. "++" and returns mangled
572acbbe
MT
240 operator name (e.g. "postincrement_expr"), or NULL if not found.
241
242 If ARG_MODE == 1, return the ANSI name;
243 if ARG_MODE == 0 return the old GNU name. */
55838914 244char *
572acbbe 245cplus_mangle_opname (opname, arg_mode)
55838914 246 char *opname;
572acbbe 247 int arg_mode;
55838914
JK
248{
249 int i, len = strlen (opname);
55838914 250
572acbbe
MT
251 if (arg_mode != 0 && arg_mode != 1)
252 error ("invalid arg_mode");
253
55838914
JK
254 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
255 {
256 if (strlen (optable[i].out) == len
572acbbe 257 && arg_mode == optable[i].ansi
55838914 258 && memcmp (optable[i].out, opname, len) == 0)
e1ce8aa5 259 return (char *)optable[i].in;
55838914 260 }
55838914
JK
261 return 0;
262}
263
dd3b648e
RP
264char *
265cplus_demangle (type, arg_mode)
266 const char *type;
267 int arg_mode;
268{
269 string decl;
270 int n;
271 int success = 0;
272 int constructor = 0;
4c53d9ca
DHW
273 int destructor = 0;
274 int static_type = 0;
dd3b648e
RP
275 int const_flag = 0;
276 int i;
277 const char *p;
278#ifndef LONGERNAMES
279 const char *premangle;
280#endif
281
282# define print_ansi_qualifiers (arg_mode > 0)
283# define print_arg_types (arg_mode >= 0)
284
285 if (type == NULL || *type == '\0')
286 return NULL;
287#ifndef nounderscore
288 if (*type++ != '_')
289 return NULL;
290#endif
291 p = type;
292 while (*p != '\0' && !(*p == '_' && p[1] == '_'))
293 p++;
294 if (*p == '\0')
295 {
296 /* destructor */
f88e7af8 297 if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
dd3b648e 298 {
0eb0a820
MT
299 int n;
300 char *tem;
301
302 type += 3; /* Get past _$_ at front. */
303 while (isdigit (*type))
304 /* If there are digits at the front, it's because
305 of new 2.0 name mangling. Just skip them. */
306 type++;
307
308 n = strlen (type)*2 + 3 + 2 + 1;
309 tem = (char *) xmalloc (n);
310 strcpy (tem, type);
572acbbe 311 strcat (tem, "::~");
0eb0a820 312 strcat (tem, type);
572acbbe
MT
313 if (print_arg_types)
314 strcat (tem, "()");
315 return tem;
dd3b648e
RP
316 }
317 /* static data member */
572acbbe 318 if (*type != '_' && (p = strchr (type, CPLUS_MARKER)) != NULL)
dd3b648e 319 {
572acbbe
MT
320 int n = strlen (type) + 2;
321 char *tem = (char *) xmalloc (n);
322 memcpy (tem, type, p - type);
323 strcpy (tem + (p - type), "::");
324 strcpy (tem + (p - type) + 2, p + 1);
325 return tem;
dd3b648e 326 }
572acbbe 327 /* virtual table "_vt$" */
f88e7af8 328 if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
dd3b648e 329 {
572acbbe
MT
330 int n = strlen (type + 4) + 14 + 1;
331 char *tem = (char *) xmalloc (n);
dd3b648e
RP
332 strcpy (tem, type + 4);
333 strcat (tem, " virtual table");
334 return tem;
335 }
336 return NULL;
337 }
338
339 string_init (&decl);
340
4c53d9ca
DHW
341 if (static_type)
342 {
343 if (!isdigit (p[0]) && ('t' != p[0]))
344 {
345 string_delete (&decl);
346 return NULL;
347 }
348 }
349 else if (p == type)
dd3b648e 350 {
572acbbe 351 if (!isdigit (p[2]) && ('t' != p[2]))
dd3b648e 352 {
572acbbe
MT
353 p += 1;
354 while (*p != '\0' && !(*p == '_' && p[1] == '_'))
355 p++;
1cca1729
MT
356 string_appendn (&decl, type, p - type);
357 string_need (&decl, 1);
572acbbe
MT
358 *(decl.p) = '\0';
359 munge_function_name (&decl, 1);
360 if (decl.b[0] == '_')
361 {
362 string_delete (&decl);
363 return NULL;
364 }
365 else
366 p += 2;
367 }
368 else
369 {
370 constructor = 1;
371 p += 2;
dd3b648e 372 }
dd3b648e
RP
373 }
374 else
375 {
376 string_appendn (&decl, type, p - type);
1cca1729 377 string_need (&decl, 1);
572acbbe 378 *(decl.p) = '\0';
dd3b648e 379 munge_function_name (&decl, arg_mode);
4c53d9ca 380 p += 2;
dd3b648e 381 }
dd3b648e
RP
382
383#ifndef LONGERNAMES
384 premangle = p;
385#endif
386 switch (*p)
387 {
388 case 'C':
389 /* a const member function */
390 if (!isdigit (p[1]))
391 {
392 string_delete (&decl);
393 return NULL;
394 }
395 p += 1;
396 const_flag = 1;
397 /* fall through */
398 case '0':
399 case '1':
400 case '2':
401 case '3':
402 case '4':
403 case '5':
404 case '6':
405 case '7':
406 case '8':
407 case '9':
408 n = 0;
409 do
410 {
411 n *= 10;
412 n += *p - '0';
413 p += 1;
414 }
415 while (isdigit (*p));
416 if (strlen (p) < n)
417 {
418 string_delete (&decl);
419 return NULL;
420 }
4c53d9ca 421 if (constructor || destructor)
dd3b648e
RP
422 {
423 string_appendn (&decl, p, n);
424 string_append (&decl, "::");
4c53d9ca
DHW
425 if (destructor)
426 string_append(&decl, "~");
dd3b648e
RP
427 string_appendn (&decl, p, n);
428 }
429 else
430 {
431 string_prepend (&decl, "::");
432 string_prependn (&decl, p, n);
433 }
434 p += n;
435#ifndef LONGERNAMES
436 remember_type (premangle, p - premangle);
437#endif
4c53d9ca
DHW
438 if (static_type)
439 {
440 string_append(&decl, p+1);
441 p += strlen(p);
442 success = 1;
443 }
444 else
445 success = do_args (&p, &decl, arg_mode);
dd3b648e
RP
446 if (const_flag && print_arg_types)
447 string_append (&decl, " const");
448 break;
449 case 'F':
450 p += 1;
451 success = do_args (&p, &decl, arg_mode);
452 break;
4c53d9ca
DHW
453 /* template additions */
454 case 't':
455 p += 1;
456 {
457 int r, i;
458 int non_empty = 0;
459 string tname;
460 string trawname;
461
462 string temp;
463 int need_comma = 0;
464
465 string_init(&tname);
466 string_init(&trawname);
467
468 /* get template name */
469 if (!get_count (&p, &r))
470 return 0;
471 string_appendn (&tname, p, r);
472 string_appendn (&trawname, p, r);
473 string_appendn (&trawname, "", 1);
474 p += r;
475 string_append (&tname, "<");
476 /* get size of template parameter list */
477 if (!get_count (&p, &r))
478 return 0;
479 for (i = 0; i < r; i++)
480 {
481 if (need_comma)
482 string_append (&tname, ", ");
483 /* Z for type parameters */
484 if (*p == 'Z')
485 {
486 p += 1;
487
488 success = do_type (&p, &temp, arg_mode);
489 string_appendn (&temp, "", 1);
490 if (success)
491 string_append (&tname, temp.b);
492 string_delete(&temp);
493 if (!success)
494 break;
495 }
496 /* otherwise, value parameter */
497 else
498 {
499 const char *old_p = p;
500 int is_pointer = 0;
501 int is_real = 0;
502 int is_integral = 0;
503 int done = 0;
504
505 success = do_type (&p, &temp, arg_mode);
506 string_appendn (&temp, "", 1);
507 if (success)
508 string_append (&tname, temp.b);
509 string_delete(&temp);
510 if (!success)
511 break;
512 string_append (&tname, "=");
513 while (*old_p && !done)
514 {
515 switch (*old_p)
516 {
517 case 'P':
518 case 'R':
519 done = is_pointer = 1;
520 break;
521 case 'C': /* const */
522 case 'U': /* unsigned */
523 case 'V': /* volatile */
524 case 'F': /* function */
525 case 'M': /* member function */
526 case 'O': /* ??? */
527 old_p++;
528 continue;
529 case 'Q': /* repetition of following */
530 case 'T': /* remembered type */
531 abort();
532 break;
533 case 'v': /* void */
534 abort();
535 break;
536 case 'x': /* long long */
537 case 'l': /* long */
538 case 'i': /* int */
539 case 's': /* short */
540 case 'c': /* char */
541 done = is_integral = 1;
542 break;
543 case 'r': /* long double */
544 case 'd': /* double */
545 case 'f': /* float */
546 done = is_real = 1;
547 break;
548 default:
549 abort();
550 }
551 }
552 if (is_integral)
553 {
554 if (*p == 'm')
555 {
556 string_appendn (&tname, "-", 1);
557 p++;
558 }
559 while (isdigit (*p))
560 {
561 string_appendn (&tname, p, 1);
562 p++;
563 }
564 }
565 else if (is_real)
566 {
567 if (*p == 'm')
568 {
569 string_appendn (&tname, "-", 1);
570 p++;
571 }
572 while (isdigit (*p))
573 {
574 string_appendn (&tname, p, 1);
575 p++;
576 }
577 if (*p == '.') /* fraction */
578 {
579 string_appendn (&tname, ".", 1);
580 p++;
581 while (isdigit (*p))
582 {
583 string_appendn (&tname, p, 1);
584 p++;
585 }
586 }
587 if (*p == 'e') /* exponent */
588 {
589 string_appendn (&tname, "e", 1);
590 p++;
591 while (isdigit (*p))
592 {
593 string_appendn (&tname, p, 1);
594 p++;
595 }
596 }
597 }
598 else if (is_pointer)
599 {
600 int symbol_len;
601
602 if (!get_count (&p, &symbol_len))
603 {
604 success = 0;
605 break;
606 }
607 string_appendn (&tname, p, symbol_len);
608 p += symbol_len;
609 }
610 }
611 need_comma = 1;
612 }
613 string_append (&tname, ">::");
614 if (destructor)
615 string_append(&tname, "~");
616 if (constructor || destructor) {
617 string_append (&tname, trawname.b);
618 }
619 string_delete(&trawname);
620
621 if (!success) {
622 string_delete(&tname);
623 return 0;
624 }
625 string_prepend (&decl, tname.b);
626 string_delete(&tname);
627
628 if (static_type)
629 {
630 string_append(&decl, p+1);
631 p += strlen(p);
632 success = 1;
633 }
634 else
635 success = do_args (&p, &decl, arg_mode);
636 break;
637 }
dd3b648e
RP
638 }
639
640 for (i = 0; i < ntypes; i++)
641 if (typevec[i] != NULL)
642 free (typevec[i]);
643 ntypes = 0;
644 if (typevec != NULL)
645 {
646 free ((char *)typevec);
647 typevec = NULL;
648 typevec_size = 0;
649 }
650
651 if (success)
652 {
653 string_appendn (&decl, "", 1);
654 return decl.b;
655 }
656 else
657 {
658 string_delete (&decl);
659 return NULL;
660 }
661}
662
663static int
664get_count (type, count)
665 const char **type;
666 int *count;
667{
668 if (!isdigit (**type))
669 return 0;
670 *count = **type - '0';
671 *type += 1;
672 /* see flush_repeats in cplus-method.c */
673 if (isdigit (**type))
674 {
675 const char *p = *type;
676 int n = *count;
677 do
678 {
679 n *= 10;
680 n += *p - '0';
681 p += 1;
682 }
683 while (isdigit (*p));
684 if (*p == '_')
685 {
686 *type = p + 1;
687 *count = n;
688 }
689 }
690 return 1;
691}
692
693/* result will be initialised here; it will be freed on failure */
694
695static int
696do_type (type, result, arg_mode)
697 const char **type;
698 string *result;
699 int arg_mode;
700{
701 int n;
702 int done;
703 int non_empty = 0;
704 int success;
705 string decl;
706 const char *remembered_type;
707
708 string_init (&decl);
709 string_init (result);
710
711 done = 0;
712 success = 1;
713 while (success && !done)
714 {
715 int member;
716 switch (**type)
717 {
55838914
JK
718 case 'Q':
719 n = (*type)[1] - '0';
720 if (n < 0 || n > 9)
721 success = 0;
722 *type += 2;
723 while (n-- > 0)
e1ce8aa5 724 do_type (type, result, arg_mode);
55838914
JK
725 break;
726
dd3b648e
RP
727 case 'P':
728 *type += 1;
729 string_prepend (&decl, "*");
730 break;
731
732 case 'R':
733 *type += 1;
734 string_prepend (&decl, "&");
735 break;
736
737 case 'T':
738 *type += 1;
739 if (!get_count (type, &n) || n >= ntypes)
740 success = 0;
741 else
742 {
743 remembered_type = typevec[n];
744 type = &remembered_type;
745 }
746 break;
747
748 case 'F':
749 *type += 1;
750 if (!string_empty (&decl) && decl.b[0] == '*')
751 {
752 string_prepend (&decl, "(");
753 string_append (&decl, ")");
754 }
755 if (!do_args (type, &decl, arg_mode) || **type != '_')
756 success = 0;
757 else
758 *type += 1;
759 break;
760
761 case 'M':
762 case 'O':
763 {
764 int constp = 0;
765 int volatilep = 0;
766
767 member = **type == 'M';
768 *type += 1;
769 if (!isdigit (**type))
770 {
771 success = 0;
772 break;
773 }
774 n = 0;
775 do
776 {
777 n *= 10;
778 n += **type - '0';
779 *type += 1;
780 }
781 while (isdigit (**type));
782 if (strlen (*type) < n)
783 {
784 success = 0;
785 break;
786 }
787 string_append (&decl, ")");
788 string_prepend (&decl, "::");
789 string_prependn (&decl, *type, n);
790 string_prepend (&decl, "(");
791 *type += n;
792 if (member)
793 {
794 if (**type == 'C')
795 {
796 *type += 1;
797 constp = 1;
798 }
799 if (**type == 'V')
800 {
801 *type += 1;
802 volatilep = 1;
803 }
804 if (*(*type)++ != 'F')
805 {
806 success = 0;
807 break;
808 }
809 }
810 if ((member && !do_args (type, &decl, arg_mode)) || **type != '_')
811 {
812 success = 0;
813 break;
814 }
815 *type += 1;
816 if (! print_ansi_qualifiers)
817 break;
818 if (constp)
819 {
820 if (non_empty)
821 string_append (&decl, " ");
822 else
823 non_empty = 1;
824 string_append (&decl, "const");
825 }
826 if (volatilep)
827 {
828 if (non_empty)
829 string_append (&decl, " ");
830 else
831 non_empty = 1;
832 string_append (&decl, "volatile");
833 }
834 break;
835 }
836
837 case 'C':
838 if ((*type)[1] == 'P')
839 {
840 *type += 1;
841 if (print_ansi_qualifiers)
842 {
843 if (!string_empty (&decl))
844 string_prepend (&decl, " ");
845 string_prepend (&decl, "const");
846 }
847 break;
848 }
849
850 /* fall through */
851 default:
852 done = 1;
853 break;
854 }
855 }
856
857 done = 0;
858 non_empty = 0;
859 while (success && !done)
860 {
861 switch (**type)
862 {
863 case 'C':
864 *type += 1;
865 if (print_ansi_qualifiers)
866 {
867 if (non_empty)
868 string_append (result, " ");
869 else
870 non_empty = 1;
871 string_append (result, "const");
872 }
873 break;
874 case 'U':
875 *type += 1;
876 if (non_empty)
877 string_append (result, " ");
878 else
879 non_empty = 1;
880 string_append (result, "unsigned");
881 break;
882 case 'V':
883 *type += 1;
884 if (print_ansi_qualifiers)
885 {
886 if (non_empty)
887 string_append (result, " ");
888 else
889 non_empty = 1;
890 string_append (result, "volatile");
891 }
892 break;
893 default:
894 done = 1;
895 break;
896 }
897 }
898
899 if (success)
900 switch (**type)
901 {
902 case '\0':
903 case '_':
904 break;
905 case 'v':
906 *type += 1;
907 if (non_empty)
908 string_append (result, " ");
909 string_append (result, "void");
910 break;
911 case 'x':
912 *type += 1;
913 if (non_empty)
914 string_append (result, " ");
915 string_append (result, "long long");
916 break;
917 case 'l':
918 *type += 1;
919 if (non_empty)
920 string_append (result, " ");
921 string_append (result, "long");
922 break;
923 case 'i':
924 *type += 1;
925 if (non_empty)
926 string_append (result, " ");
927 string_append (result, "int");
928 break;
929 case 's':
930 *type += 1;
931 if (non_empty)
932 string_append (result, " ");
933 string_append (result, "short");
934 break;
935 case 'c':
936 *type += 1;
937 if (non_empty)
938 string_append (result, " ");
939 string_append (result, "char");
940 break;
941 case 'r':
942 *type += 1;
943 if (non_empty)
944 string_append (result, " ");
945 string_append (result, "long double");
946 break;
947 case 'd':
948 *type += 1;
949 if (non_empty)
950 string_append (result, " ");
951 string_append (result, "double");
952 break;
953 case 'f':
954 *type += 1;
955 if (non_empty)
956 string_append (result, " ");
957 string_append (result, "float");
958 break;
959 case 'G':
960 *type += 1;
961 if (!isdigit (**type))
962 {
963 success = 0;
964 break;
965 }
966 /* fall through */
967 case '0':
968 case '1':
969 case '2':
970 case '3':
971 case '4':
972 case '5':
973 case '6':
974 case '7':
975 case '8':
976 case '9':
977 n = 0;
978 do
979 {
980 n *= 10;
981 n += **type - '0';
982 *type += 1;
983 }
984 while (isdigit (**type));
985 if (strlen (*type) < n)
986 {
987 success = 0;
988 break;
989 }
990 if (non_empty)
991 string_append (result, " ");
992 string_appendn (result, *type, n);
993 *type += n;
994 break;
995 default:
996 success = 0;
997 break;
998 }
999
1000 if (success)
1001 {
1002 if (!string_empty (&decl))
1003 {
1004 string_append (result, " ");
1005 string_appends (result, &decl);
1006 }
1007 string_delete (&decl);
1008 return 1;
1009 }
1010 else
1011 {
1012 string_delete (&decl);
1013 string_delete (result);
1014 return 0;
1015 }
1016}
1017
1018/* `result' will be initialised in do_type; it will be freed on failure */
1019
1020static int
1021do_arg (type, result, arg_mode)
1022 const char **type;
1023 string *result;
1024 int arg_mode;
1025{
1026 const char *start = *type;
1027
1028 if (!do_type (type, result, arg_mode))
1029 return 0;
1030 remember_type (start, *type - start);
1031 return 1;
1032}
1033
1034static void
1035remember_type (start, len)
1036 const char *start;
1037 int len;
1038{
1039 char *tem;
1040
1041 if (ntypes >= typevec_size)
1042 {
1043 if (typevec_size == 0)
1044 {
1045 typevec_size = 3;
1046 typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
1047 }
1048 else
1049 {
1050 typevec_size *= 2;
1051 typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
1052 }
1053 }
1054 tem = (char *) xmalloc (len + 1);
1055 memcpy (tem, start, len);
1056 tem[len] = '\0';
1057 typevec[ntypes++] = tem;
1058}
1059
1060/* `decl' must be already initialised, usually non-empty;
1061 it won't be freed on failure */
1062
1063static int
1064do_args (type, decl, arg_mode)
1065 const char **type;
1066 string *decl;
1067 int arg_mode;
1068{
1069 string arg;
1070 int need_comma = 0;
1071
1072 if (print_arg_types)
1073 string_append (decl, "(");
1074
1075 while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
1076 {
1077 if (**type == 'N')
1078 {
1079 int r;
1080 int t;
1081 *type += 1;
1082 if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
1083 return 0;
1084 while (--r >= 0)
1085 {
1086 const char *tem = typevec[t];
1087 if (need_comma && print_arg_types)
1088 string_append (decl, ", ");
1089 if (!do_arg (&tem, &arg, arg_mode))
1090 return 0;
1091 if (print_arg_types)
1092 string_appends (decl, &arg);
1093 string_delete (&arg);
1094 need_comma = 1;
1095 }
1096 }
1097 else
1098 {
1099 if (need_comma & print_arg_types)
1100 string_append (decl, ", ");
1101 if (!do_arg (type, &arg, arg_mode))
1102 return 0;
1103 if (print_arg_types)
1104 string_appends (decl, &arg);
1105 string_delete (&arg);
1106 need_comma = 1;
1107 }
1108 }
1109
1110 if (**type == 'v')
1111 *type += 1;
1112 else if (**type == 'e')
1113 {
1114 *type += 1;
1115 if (print_arg_types)
1116 {
1117 if (need_comma)
1118 string_append (decl, ",");
1119 string_append (decl, "...");
1120 }
1121 }
1122
1123 if (print_arg_types)
1124 string_append (decl, ")");
1125 return 1;
1126}
1127
1128static void
1129munge_function_name (name, arg_mode)
1130 string *name;
1131 int arg_mode;
1132{
572acbbe
MT
1133 if (string_empty (name))
1134 return;
1135
1136 if (name->p - name->b >= 3
f88e7af8 1137 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
dd3b648e
RP
1138 {
1139 int i;
1140 /* see if it's an assignment expression */
1141 if (name->p - name->b >= 10 /* op$assign_ */
1142 && memcmp (name->b + 3, "assign_", 7) == 0)
1143 {
1144 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
1145 {
1146 int len = name->p - name->b - 10;
1147 if (strlen (optable[i].in) == len
1148 && memcmp (optable[i].in, name->b + 10, len) == 0)
1149 {
1150 string_clear (name);
1151 string_append (name, "operator");
1152 string_append (name, optable[i].out);
1153 string_append (name, "=");
1154 return;
1155 }
1156 }
1157 }
1158 else
1159 {
1160 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
1161 {
1162 int len = name->p - name->b - 3;
1163 if (strlen (optable[i].in) == len
1164 && memcmp (optable[i].in, name->b + 3, len) == 0)
1165 {
1166 string_clear (name);
1167 string_append (name, "operator");
1168 string_append (name, optable[i].out);
1169 return;
1170 }
1171 }
1172 }
1173 return;
1174 }
572acbbe 1175 else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0)
dd3b648e
RP
1176 {
1177 /* type conversion operator */
1178 string type;
1179 const char *tem = name->b + 5;
1180 if (do_type (&tem, &type, arg_mode))
1181 {
1182 string_clear (name);
1183 string_append (name, "operator ");
1184 string_appends (name, &type);
1185 string_delete (&type);
1186 return;
1187 }
1188 }
572acbbe
MT
1189 /* ANSI. */
1190 else if (name->b[2] == 'o' && name->b[3] == 'p')
1191 {
1192 /* type conversion operator. */
1193 string type;
1194 const char *tem = name->b + 4;
1a18a185 1195 if (do_type (&tem, &type, arg_mode))
572acbbe
MT
1196 {
1197 string_clear (name);
1198 string_append (name, "operator ");
1199 string_appends (name, &type);
1200 string_delete (&type);
1201 return;
1202 }
1203 }
1204 else if (name->b[0] == '_' && name->b[1] == '_'
1205 && name->b[2] >= 'a' && name->b[2] <= 'z'
1206 && name->b[3] >= 'a' && name->b[3] <= 'z')
1207 {
1208 int i;
1209
1210 if (name->b[4] == '\0')
1211 {
1212 /* Operator. */
1213 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
1214 {
1215 if (strlen (optable[i].in) == 2
1216 && memcmp (optable[i].in, name->b + 2, 2) == 0)
1217 {
1218 string_clear (name);
1219 string_append (name, "operator");
1220 string_append (name, optable[i].out);
1221 return;
1222 }
1223 }
1224 }
1225 else
1226 {
1227 if (name->b[2] != 'a' || name->b[5] != '\0')
1228 return;
1229 /* Assignment. */
1230 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
1231 {
1232 if (strlen (optable[i].in) == 3
1233 && memcmp (optable[i].in, name->b + 2, 3) == 0)
1234 {
1235 string_clear (name);
1236 string_append (name, "operator");
1237 string_append (name, optable[i].out);
1238 return;
1239 }
1240 }
1241 }
1242 }
dd3b648e
RP
1243}
1244
1245/* a mini string-handling package */
1246
1247static void
1248string_need (s, n)
1249 string *s;
1250 int n;
1251{
1252 if (s->b == NULL)
1253 {
1254 if (n < 32)
1255 n = 32;
1256 s->p = s->b = (char *) xmalloc (n);
1257 s->e = s->b + n;
1258 }
1259 else if (s->e - s->p < n)
1260 {
1261 int tem = s->p - s->b;
1262 n += tem;
1263 n *= 2;
1264 s->b = (char *) xrealloc (s->b, n);
1265 s->p = s->b + tem;
1266 s->e = s->b + n;
1267 }
1268}
1269
1270static void
1271string_delete (s)
1272 string *s;
1273{
1274 if (s->b != NULL)
1275 {
1276 free (s->b);
1277 s->b = s->e = s->p = NULL;
1278 }
1279}
1280
1281static void
1282string_init (s)
1283 string *s;
1284{
1285 s->b = s->p = s->e = NULL;
1286}
1287
1288static void
1289string_clear (s)
1290 string *s;
1291{
1292 s->p = s->b;
1293}
1294
1295static int
1296string_empty (s)
1297 string *s;
1298{
1299 return s->b == s->p;
1300}
1301
1302static void
1303string_append (p, s)
1304 string *p;
1305 const char *s;
1306{
1307 int n;
1308 if (s == NULL || *s == '\0')
1309 return;
1310 n = strlen (s);
1311 string_need (p, n);
1312 memcpy (p->p, s, n);
1313 p->p += n;
1314}
1315
1316static void
1317string_appends (p, s)
1318 string *p, *s;
1319{
1320 int n;
1321 if (s->b == s->p)
1322 return;
1323 n = s->p - s->b;
1324 string_need (p, n);
1325 memcpy (p->p, s->b, n);
1326 p->p += n;
1327}
1328
1329static void
1330string_appendn (p, s, n)
1331 string *p;
1332 const char *s;
1333 int n;
1334{
1335 if (n == 0)
1336 return;
1337 string_need (p, n);
1338 memcpy (p->p, s, n);
1339 p->p += n;
1340}
1341
1342static void
1343string_prepend (p, s)
1344 string *p;
1345 const char *s;
1346{
1347 if (s == NULL || *s == '\0')
1348 return;
1349 string_prependn (p, s, strlen (s));
1350}
1351
1352#if 0
1353static void
1354string_prepends (p, s)
1355 string *p, *s;
1356{
1357 if (s->b == s->p)
1358 return;
1359 string_prependn (p, s->b, s->p - s->b);
1360}
1361#endif
1362
1363static void
1364string_prependn (p, s, n)
1365 string *p;
1366 const char *s;
1367 int n;
1368{
1369 char *q;
1370
1371 if (n == 0)
1372 return;
1373 string_need (p, n);
1374 for (q = p->p - 1; q >= p->b; q--)
1375 q[n] = q[0];
1376 memcpy (p->b, s, n);
1377 p->p += n;
1378}
This page took 0.101062 seconds and 4 git commands to generate.