This is the third and final batch of makefile changes this round.
[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
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.
9
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.
14
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. */
18
19 /* This is for g++ 1.95.03 (November 13 verison). */
20
21 /* This file exports one function
22
23 char *cplus_demangle (const char *name, int mode)
24
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
52 /* GDB-specific, FIXME. */
53 #include "defs.h"
54
55 #include <ctype.h>
56
57 #ifdef USG
58 #include <memory.h>
59 #include <string.h>
60 #else
61 #include <strings.h>
62 #endif
63
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
71 #ifndef __STDC__
72 #define const
73 #endif
74
75 #ifdef __STDC__
76 extern char *cplus_demangle (const char *type, int mode);
77 #else
78 extern char *cplus_demangle ();
79 #endif
80
81 #ifdef __STDC__
82 /* GDB prototypes these as void* in defs.h, so we better too, at least
83 as long as we're including defs.h. */
84 /* FIXME extern void *xmalloc (int);
85 extern void *xrealloc (char *, int); */
86 extern void free (void *);
87 #else
88 extern char *xmalloc ();
89 extern char *xrealloc ();
90 extern void free ();
91 #endif
92
93 static char **typevec = 0;
94 static int ntypes = 0;
95 static int typevec_size = 0;
96
97 const static struct optable {
98 const char *in;
99 const char *out;
100 int ansi;
101 } optable[] = {
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=) */
175 };
176
177 /* Beware: these aren't '\0' terminated. */
178
179 typedef struct string {
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
185 static void
186 string_need PARAMS ((string *, int));
187
188 static void
189 string_delete PARAMS ((string *));
190
191 static void
192 string_init PARAMS ((string *));
193
194 static void
195 string_clear PARAMS ((string *));
196
197 static int
198 string_empty PARAMS ((string *));
199
200 static void
201 string_append PARAMS ((string *, const char *));
202
203 static void
204 string_appends PARAMS ((string *, string *));
205
206 static void
207 string_appendn PARAMS ((string *, const char *, int));
208
209 static void
210 string_prepend PARAMS ((string *, const char *));
211
212 static void
213 string_prependn PARAMS ((string *, const char *, int));
214
215 static int
216 get_count PARAMS ((const char **, int *));
217
218 static int
219 do_args PARAMS ((const char **, string *, int));
220
221 static int
222 do_type PARAMS ((const char **, string *, int));
223
224 static int
225 do_arg PARAMS ((const char **, string *, int));
226
227 static void
228 munge_function_name PARAMS ((string *, int));
229
230 static void
231 remember_type PARAMS ((const char *, int));
232
233 #if 0
234 static void
235 string_prepends PARAMS ((string *, string *));
236 #endif
237
238
239 /* Takes operator name as e.g. "++" and returns mangled
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. */
244 char *
245 cplus_mangle_opname (opname, arg_mode)
246 char *opname;
247 int arg_mode;
248 {
249 int i, len = strlen (opname);
250
251 if (arg_mode != 0 && arg_mode != 1)
252 error ("invalid arg_mode");
253
254 for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
255 {
256 if (strlen (optable[i].out) == len
257 && arg_mode == optable[i].ansi
258 && memcmp (optable[i].out, opname, len) == 0)
259 return (char *)optable[i].in;
260 }
261 return 0;
262 }
263
264 char *
265 cplus_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;
273 int destructor = 0;
274 int static_type = 0;
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 */
297 if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_')
298 {
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);
311 strcat (tem, "::~");
312 strcat (tem, type);
313 if (print_arg_types)
314 strcat (tem, "()");
315 return tem;
316 }
317 /* static data member */
318 if (*type != '_' && (p = strchr (type, CPLUS_MARKER)) != NULL)
319 {
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;
326 }
327 /* virtual table "_vt$" */
328 if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER)
329 {
330 int n = strlen (type + 4) + 14 + 1;
331 char *tem = (char *) xmalloc (n);
332 strcpy (tem, type + 4);
333 strcat (tem, " virtual table");
334 return tem;
335 }
336 return NULL;
337 }
338
339 string_init (&decl);
340
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)
350 {
351 if (!isdigit (p[2]) && ('t' != p[2]))
352 {
353 p += 1;
354 while (*p != '\0' && !(*p == '_' && p[1] == '_'))
355 p++;
356 string_appendn (&decl, type, p - type);
357 string_need (&decl, 1);
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;
372 }
373 }
374 else
375 {
376 string_appendn (&decl, type, p - type);
377 string_need (&decl, 1);
378 *(decl.p) = '\0';
379 munge_function_name (&decl, arg_mode);
380 p += 2;
381 }
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 }
421 if (constructor || destructor)
422 {
423 string_appendn (&decl, p, n);
424 string_append (&decl, "::");
425 if (destructor)
426 string_append(&decl, "~");
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
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);
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;
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 }
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
663 static int
664 get_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
695 static int
696 do_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 {
718 case 'Q':
719 n = (*type)[1] - '0';
720 if (n < 0 || n > 9)
721 success = 0;
722 *type += 2;
723 while (n-- > 0)
724 do_type (type, result, arg_mode);
725 break;
726
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
1020 static int
1021 do_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
1034 static void
1035 remember_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
1063 static int
1064 do_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
1128 static void
1129 munge_function_name (name, arg_mode)
1130 string *name;
1131 int arg_mode;
1132 {
1133 if (string_empty (name))
1134 return;
1135
1136 if (name->p - name->b >= 3
1137 && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER)
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 }
1175 else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0)
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 }
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;
1195 if (do_type (&tem, &type, arg_mode))
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 }
1243 }
1244
1245 /* a mini string-handling package */
1246
1247 static void
1248 string_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
1270 static void
1271 string_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
1281 static void
1282 string_init (s)
1283 string *s;
1284 {
1285 s->b = s->p = s->e = NULL;
1286 }
1287
1288 static void
1289 string_clear (s)
1290 string *s;
1291 {
1292 s->p = s->b;
1293 }
1294
1295 static int
1296 string_empty (s)
1297 string *s;
1298 {
1299 return s->b == s->p;
1300 }
1301
1302 static void
1303 string_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
1316 static void
1317 string_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
1329 static void
1330 string_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
1342 static void
1343 string_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
1353 static void
1354 string_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
1363 static void
1364 string_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.057652 seconds and 4 git commands to generate.