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