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