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