148862Sbostic /*-
248862Sbostic * This code is derived from software copyrighted by the Free Software
348862Sbostic * Foundation.
448862Sbostic */
548862Sbostic
648861Sbostic #ifndef lint
7*62051Sbostic static char sccsid[] = "@(#)cplus-dem.c 8.1 (Berkeley) 06/06/93";
848861Sbostic #endif /* not lint */
948861Sbostic
1048853Sbostic /* Demangler for GNU C++
1148853Sbostic Copyright (C) 1989 Free Software Foundation, Inc.
1248853Sbostic written by James Clark (jjc@jclark.uucp)
1348853Sbostic
1448853Sbostic This program is free software; you can redistribute it and/or modify
1548853Sbostic it under the terms of the GNU General Public License as published by
1648853Sbostic the Free Software Foundation; either version 1, or (at your option)
1748853Sbostic any later version.
1848853Sbostic
1948853Sbostic This program is distributed in the hope that it will be useful,
2048853Sbostic but WITHOUT ANY WARRANTY; without even the implied warranty of
2148853Sbostic MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2248853Sbostic GNU General Public License for more details.
2348853Sbostic
2448853Sbostic You should have received a copy of the GNU General Public License
2548853Sbostic along with this program; if not, write to the Free Software
2648853Sbostic Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
2748853Sbostic
2848853Sbostic /* This is for g++ 1.36.1 (November 6 version). It will probably
2948853Sbostic require changes for any other version.
3048853Sbostic
3148853Sbostic Modified for g++ 1.36.2 (November 18 version). */
3248853Sbostic
3348853Sbostic /* This file exports one function
3448853Sbostic
3548853Sbostic char *cplus_demangle (const char *name)
3648853Sbostic
3748853Sbostic If `name' is a mangled function name produced by g++, then
3848853Sbostic a pointer to a malloced string giving a C++ representation
3948853Sbostic of the name will be returned; otherwise NULL will be returned.
4048853Sbostic It is the caller's responsibility to free the string which
4148853Sbostic is returned.
4248853Sbostic
4348853Sbostic For example,
4448853Sbostic
4548853Sbostic cplus_demangle ("_foo__1Ai")
4648853Sbostic
4748853Sbostic returns
4848853Sbostic
4948853Sbostic "A::foo(int)"
5048853Sbostic
5148853Sbostic This file imports xmalloc and xrealloc, which are like malloc and
5248853Sbostic realloc except that they generate a fatal error if there is no
5348853Sbostic available memory. */
5448853Sbostic
5548853Sbostic /* #define nounderscore 1 /* define this is names don't start with _ */
5648853Sbostic
5748853Sbostic #include <stdio.h>
5848853Sbostic #include <ctype.h>
5948853Sbostic
6048853Sbostic #ifdef USG
6148853Sbostic #include <memory.h>
6248853Sbostic #include <string.h>
6348853Sbostic #else
6448853Sbostic #include <strings.h>
6548853Sbostic #define memcpy(s1, s2, n) bcopy ((s2), (s1), (n))
6648853Sbostic #define memcmp(s1, s2, n) bcmp ((s2), (s1), (n))
6748853Sbostic #define strchr index
6848853Sbostic #define strrchr rindex
6948853Sbostic #endif
7048853Sbostic
7148853Sbostic #ifdef __STDC__
7248853Sbostic extern char *cplus_demangle (const char *type);
7348853Sbostic #else
7448853Sbostic extern char *cplus_demangle ();
7548853Sbostic #endif
7648853Sbostic
7748853Sbostic #ifdef __STDC__
7848853Sbostic extern char *xmalloc (int);
7948853Sbostic extern char *xrealloc (char *, int);
8048853Sbostic #else
8148853Sbostic extern char *xmalloc ();
8248853Sbostic extern char *xrealloc ();
8348853Sbostic #endif
8448853Sbostic
8548853Sbostic static char **typevec = 0;
8648853Sbostic static int ntypes = 0;
8748853Sbostic static int typevec_size = 0;
8848853Sbostic
8948853Sbostic static struct {
9048853Sbostic const char *in;
9148853Sbostic const char *out;
9248853Sbostic } optable[] = {
9348853Sbostic "new", " new",
9448853Sbostic "delete", " delete",
9548853Sbostic "ne", "!=",
9648853Sbostic "eq", "==",
9748853Sbostic "ge", ">=",
9848853Sbostic "gt", ">",
9948853Sbostic "le", "<=",
10048853Sbostic "lt", "<",
10148853Sbostic "plus", "+",
10248853Sbostic "minus", "-",
10348853Sbostic "mult", "*",
10448853Sbostic "convert", "+", /* unary + */
10548853Sbostic "negate", "-", /* unary - */
10648853Sbostic "trunc_mod", "%",
10748853Sbostic "trunc_div", "/",
10848853Sbostic "truth_andif", "&&",
10948853Sbostic "truth_orif", "||",
11048853Sbostic "truth_not", "!",
11148853Sbostic "postincrement", "++",
11248853Sbostic "postdecrement", "--",
11348853Sbostic "bit_ior", "|",
11448853Sbostic "bit_xor", "^",
11548853Sbostic "bit_and", "&",
11648853Sbostic "bit_not", "~",
11748853Sbostic "call", "()",
11848853Sbostic "cond", "?:",
11948853Sbostic "alshift", "<<",
12048853Sbostic "arshift", ">>",
12148853Sbostic "component", "->",
12248853Sbostic "indirect", "*",
12348853Sbostic "method_call", "->()",
12448853Sbostic "addr", "&", /* unary & */
12548853Sbostic "array", "[]",
12648853Sbostic "nop", "", /* for operator= */
12748853Sbostic };
12848853Sbostic
12948853Sbostic /* Beware: these aren't '\0' terminated. */
13048853Sbostic
13148853Sbostic typedef struct {
13248853Sbostic char *b; /* pointer to start of string */
13348853Sbostic char *p; /* pointer after last character */
13448853Sbostic char *e; /* pointer after end of allocated space */
13548853Sbostic } string;
13648853Sbostic
13748853Sbostic #ifdef __STDC__
13848853Sbostic static void string_need (string *s, int n);
13948853Sbostic static void string_delete (string *s);
14048853Sbostic static void string_init (string *s);
14148853Sbostic static void string_clear (string *s);
14248853Sbostic static int string_empty (string *s);
14348853Sbostic static void string_append (string *p, const char *s);
14448853Sbostic static void string_appends (string *p, string *s);
14548853Sbostic static void string_appendn (string *p, const char *s, int n);
14648853Sbostic static void string_prepend (string *p, const char *s);
14748853Sbostic #if 0
14848853Sbostic static void string_prepends (string *p, string *s);
14948853Sbostic #endif
15048853Sbostic static void string_prependn (string *p, const char *s, int n);
15148853Sbostic static int get_count (const char **type, int *count);
15248853Sbostic static int do_args (const char **type, string *decl);
15348853Sbostic static int do_type (const char **type, string *result);
15448853Sbostic static int do_arg (const char **type, string *result);
15548853Sbostic static int do_args (const char **type, string *decl);
15648853Sbostic static void munge_function_name (string *name);
15748853Sbostic static void remember_type (const char *type, int len);
15848853Sbostic #else
15948853Sbostic static void string_need ();
16048853Sbostic static void string_delete ();
16148853Sbostic static void string_init ();
16248853Sbostic static void string_clear ();
16348853Sbostic static int string_empty ();
16448853Sbostic static void string_append ();
16548853Sbostic static void string_appends ();
16648853Sbostic static void string_appendn ();
16748853Sbostic static void string_prepend ();
16848853Sbostic static void string_prepends ();
16948853Sbostic static void string_prependn ();
17048853Sbostic static int get_count ();
17148853Sbostic static int do_args ();
17248853Sbostic static int do_type ();
17348853Sbostic static int do_arg ();
17448853Sbostic static int do_args ();
17548853Sbostic static void munge_function_name ();
17648853Sbostic static void remember_type ();
17748853Sbostic #endif
17848853Sbostic
17948853Sbostic char *
cplus_demangle(type)18048853Sbostic cplus_demangle (type)
18148853Sbostic const char *type;
18248853Sbostic {
18348853Sbostic string decl;
18448853Sbostic int n;
18548853Sbostic int success = 0;
18648853Sbostic int constructor = 0;
18748853Sbostic int const_flag = 0;
18848853Sbostic int i;
18948853Sbostic const char *p;
19048853Sbostic #ifndef LONGERNAMES
19148853Sbostic const char *premangle;
19248853Sbostic #endif
19348853Sbostic
19448853Sbostic if (type == NULL || *type == '\0')
19548853Sbostic return NULL;
19648853Sbostic #ifndef nounderscore
19748853Sbostic if (*type++ != '_')
19848853Sbostic return NULL;
19948853Sbostic #endif
20048853Sbostic p = type;
20148853Sbostic while (*p != '\0' && !(*p == '_' && p[1] == '_'))
20248853Sbostic p++;
20348853Sbostic if (*p == '\0')
20448853Sbostic {
20548853Sbostic /* destructor */
20648853Sbostic if (type[0] == '_' && type[1] == '$' && type[2] == '_')
20748853Sbostic {
20848853Sbostic int n = (strlen (type) - 3)*2 + 3 + 2 + 1;
20948853Sbostic char *tem = (char *) xmalloc (n);
21048853Sbostic strcpy (tem, type + 3);
21148853Sbostic strcat (tem, "::~");
21248853Sbostic strcat (tem, type + 3);
21348853Sbostic strcat (tem, "()");
21448853Sbostic return tem;
21548853Sbostic }
21648853Sbostic /* static data member */
21748853Sbostic if (*type != '_' && (p = strchr (type, '$')) != NULL)
21848853Sbostic {
21948853Sbostic int n = strlen (type) + 2;
22048853Sbostic char *tem = (char *) xmalloc (n);
22148853Sbostic memcpy (tem, type, p - type);
22248853Sbostic strcpy (tem + (p - type), "::");
22348853Sbostic strcpy (tem + (p - type) + 2, p + 1);
22448853Sbostic return tem;
22548853Sbostic }
22648853Sbostic /* virtual table */
22748853Sbostic if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
22848853Sbostic {
22948853Sbostic int n = strlen (type + 4) + 14 + 1;
23048853Sbostic char *tem = (char *) xmalloc (n);
23148853Sbostic strcpy (tem, type + 4);
23248853Sbostic strcat (tem, " virtual table");
23348853Sbostic return tem;
23448853Sbostic }
23548853Sbostic return NULL;
23648853Sbostic }
23748853Sbostic
23848853Sbostic string_init (&decl);
23948853Sbostic
24048853Sbostic if (p == type)
24148853Sbostic {
24248853Sbostic if (!isdigit (p[2]))
24348853Sbostic {
24448853Sbostic string_delete (&decl);
24548853Sbostic return NULL;
24648853Sbostic }
24748853Sbostic constructor = 1;
24848853Sbostic }
24948853Sbostic else
25048853Sbostic {
25148853Sbostic string_appendn (&decl, type, p - type);
25248853Sbostic munge_function_name (&decl);
25348853Sbostic }
25448853Sbostic p += 2;
25548853Sbostic
25648853Sbostic #ifndef LONGERNAMES
25748853Sbostic premangle = p;
25848853Sbostic #endif
25948853Sbostic switch (*p)
26048853Sbostic {
26148853Sbostic case 'C':
26248853Sbostic /* a const member function */
26348853Sbostic if (!isdigit (p[1]))
26448853Sbostic {
26548853Sbostic string_delete (&decl);
26648853Sbostic return NULL;
26748853Sbostic }
26848853Sbostic p += 1;
26948853Sbostic const_flag = 1;
27048853Sbostic /* fall through */
27148853Sbostic case '0':
27248853Sbostic case '1':
27348853Sbostic case '2':
27448853Sbostic case '3':
27548853Sbostic case '4':
27648853Sbostic case '5':
27748853Sbostic case '6':
27848853Sbostic case '7':
27948853Sbostic case '8':
28048853Sbostic case '9':
28148853Sbostic n = 0;
28248853Sbostic do
28348853Sbostic {
28448853Sbostic n *= 10;
28548853Sbostic n += *p - '0';
28648853Sbostic p += 1;
28748853Sbostic }
28848853Sbostic while (isdigit (*p));
28948853Sbostic if (strlen (p) < n)
29048853Sbostic {
29148853Sbostic string_delete (&decl);
29248853Sbostic return NULL;
29348853Sbostic }
29448853Sbostic if (constructor)
29548853Sbostic {
29648853Sbostic string_appendn (&decl, p, n);
29748853Sbostic string_append (&decl, "::");
29848853Sbostic string_appendn (&decl, p, n);
29948853Sbostic }
30048853Sbostic else
30148853Sbostic {
30248853Sbostic string_prepend (&decl, "::");
30348853Sbostic string_prependn (&decl, p, n);
30448853Sbostic }
30548853Sbostic p += n;
30648853Sbostic #ifndef LONGERNAMES
30748853Sbostic remember_type (premangle, p - premangle);
30848853Sbostic #endif
30948853Sbostic success = do_args (&p, &decl);
31048853Sbostic if (const_flag)
31148853Sbostic string_append (&decl, " const");
31248853Sbostic break;
31348853Sbostic case 'F':
31448853Sbostic p += 1;
31548853Sbostic success = do_args (&p, &decl);
31648853Sbostic break;
31748853Sbostic }
31848853Sbostic
31948853Sbostic for (i = 0; i < ntypes; i++)
32048853Sbostic if (typevec[i] != NULL)
32148853Sbostic free (typevec[i]);
32248853Sbostic ntypes = 0;
32348853Sbostic if (typevec != NULL)
32448853Sbostic {
32548853Sbostic free ((char *)typevec);
32648853Sbostic typevec = NULL;
32748853Sbostic typevec_size = 0;
32848853Sbostic }
32948853Sbostic
33048853Sbostic if (success)
33148853Sbostic {
33248853Sbostic string_appendn (&decl, "", 1);
33348853Sbostic return decl.b;
33448853Sbostic }
33548853Sbostic else
33648853Sbostic {
33748853Sbostic string_delete (&decl);
33848853Sbostic return NULL;
33948853Sbostic }
34048853Sbostic }
34148853Sbostic
34248853Sbostic static int
get_count(type,count)34348853Sbostic get_count (type, count)
34448853Sbostic const char **type;
34548853Sbostic int *count;
34648853Sbostic {
34748853Sbostic if (!isdigit (**type))
34848853Sbostic return 0;
34948853Sbostic *count = **type - '0';
35048853Sbostic *type += 1;
35148853Sbostic /* see flush_repeats in cplus-method.c */
35248853Sbostic if (isdigit (**type))
35348853Sbostic {
35448853Sbostic const char *p = *type;
35548853Sbostic int n = *count;
35648853Sbostic do
35748853Sbostic {
35848853Sbostic n *= 10;
35948853Sbostic n += *p - '0';
36048853Sbostic p += 1;
36148853Sbostic }
36248853Sbostic while (isdigit (*p));
36348853Sbostic if (*p == '_')
36448853Sbostic {
36548853Sbostic *type = p + 1;
36648853Sbostic *count = n;
36748853Sbostic }
36848853Sbostic }
36948853Sbostic return 1;
37048853Sbostic }
37148853Sbostic
37248853Sbostic /* result will be initialised here; it will be freed on failure */
37348853Sbostic
37448853Sbostic static int
do_type(type,result)37548853Sbostic do_type (type, result)
37648853Sbostic const char **type;
37748853Sbostic string *result;
37848853Sbostic {
37948853Sbostic int n;
38048853Sbostic int done;
38148853Sbostic int non_empty = 0;
38248853Sbostic int success;
38348853Sbostic string decl;
38448853Sbostic const char *remembered_type;
38548853Sbostic
38648853Sbostic string_init (&decl);
38748853Sbostic string_init (result);
38848853Sbostic
38948853Sbostic done = 0;
39048853Sbostic success = 1;
39148853Sbostic while (success && !done)
39248853Sbostic {
39348853Sbostic int member;
39448853Sbostic switch (**type)
39548853Sbostic {
39648853Sbostic case 'P':
39748853Sbostic *type += 1;
39848853Sbostic string_prepend (&decl, "*");
39948853Sbostic break;
40048853Sbostic
40148853Sbostic case 'R':
40248853Sbostic *type += 1;
40348853Sbostic string_prepend (&decl, "&");
40448853Sbostic break;
40548853Sbostic
40648853Sbostic case 'T':
40748853Sbostic *type += 1;
40848853Sbostic if (!get_count (type, &n) || n >= ntypes)
40948853Sbostic success = 0;
41048853Sbostic else
41148853Sbostic {
41248853Sbostic remembered_type = typevec[n];
41348853Sbostic type = &remembered_type;
41448853Sbostic }
41548853Sbostic break;
41648853Sbostic
41748853Sbostic case 'F':
41848853Sbostic *type += 1;
41948853Sbostic if (!string_empty (&decl) && decl.b[0] == '*')
42048853Sbostic {
42148853Sbostic string_prepend (&decl, "(");
42248853Sbostic string_append (&decl, ")");
42348853Sbostic }
42448853Sbostic if (!do_args (type, &decl) || **type != '_')
42548853Sbostic success = 0;
42648853Sbostic else
42748853Sbostic *type += 1;
42848853Sbostic break;
42948853Sbostic
43048853Sbostic case 'M':
43148853Sbostic case 'O':
43248853Sbostic {
43348853Sbostic int constp = 0;
43448853Sbostic int volatilep = 0;
43548853Sbostic
43648853Sbostic member = **type == 'M';
43748853Sbostic *type += 1;
43848853Sbostic if (!isdigit (**type))
43948853Sbostic {
44048853Sbostic success = 0;
44148853Sbostic break;
44248853Sbostic }
44348853Sbostic n = 0;
44448853Sbostic do
44548853Sbostic {
44648853Sbostic n *= 10;
44748853Sbostic n += **type - '0';
44848853Sbostic *type += 1;
44948853Sbostic }
45048853Sbostic while (isdigit (**type));
45148853Sbostic if (strlen (*type) < n)
45248853Sbostic {
45348853Sbostic success = 0;
45448853Sbostic break;
45548853Sbostic }
45648853Sbostic string_append (&decl, ")");
45748853Sbostic string_prepend (&decl, "::");
45848853Sbostic string_prependn (&decl, *type, n);
45948853Sbostic string_prepend (&decl, "(");
46048853Sbostic *type += n;
46148853Sbostic if (member)
46248853Sbostic {
46348853Sbostic if (**type == 'C')
46448853Sbostic {
46548853Sbostic *type += 1;
46648853Sbostic constp = 1;
46748853Sbostic }
46848853Sbostic if (**type == 'V')
46948853Sbostic {
47048853Sbostic *type += 1;
47148853Sbostic volatilep = 1;
47248853Sbostic }
47348853Sbostic if (*(*type)++ != 'F')
47448853Sbostic {
47548853Sbostic success = 0;
47648853Sbostic break;
47748853Sbostic }
47848853Sbostic }
47948853Sbostic if ((member && !do_args (type, &decl)) || **type != '_')
48048853Sbostic {
48148853Sbostic success = 0;
48248853Sbostic break;
48348853Sbostic }
48448853Sbostic *type += 1;
48548853Sbostic if (constp)
48648853Sbostic {
48748853Sbostic if (non_empty)
48848853Sbostic string_append (&decl, " ");
48948853Sbostic else
49048853Sbostic non_empty = 1;
49148853Sbostic string_append (&decl, "const");
49248853Sbostic }
49348853Sbostic if (volatilep)
49448853Sbostic {
49548853Sbostic if (non_empty)
49648853Sbostic string_append (&decl, " ");
49748853Sbostic else
49848853Sbostic non_empty = 1;
49948853Sbostic string_append (&decl, "volatilep");
50048853Sbostic }
50148853Sbostic break;
50248853Sbostic }
50348853Sbostic
50448853Sbostic case 'C':
50548853Sbostic if ((*type)[1] == 'P')
50648853Sbostic {
50748853Sbostic *type += 1;
50848853Sbostic if (!string_empty (&decl))
50948853Sbostic string_prepend (&decl, " ");
51048853Sbostic string_prepend (&decl, "const");
51148853Sbostic break;
51248853Sbostic }
51348853Sbostic
51448853Sbostic /* fall through */
51548853Sbostic default:
51648853Sbostic done = 1;
51748853Sbostic break;
51848853Sbostic }
51948853Sbostic }
52048853Sbostic
52148853Sbostic done = 0;
52248853Sbostic non_empty = 0;
52348853Sbostic while (success && !done)
52448853Sbostic {
52548853Sbostic switch (**type)
52648853Sbostic {
52748853Sbostic case 'C':
52848853Sbostic *type += 1;
52948853Sbostic if (non_empty)
53048853Sbostic string_append (result, " ");
53148853Sbostic else
53248853Sbostic non_empty = 1;
53348853Sbostic string_append (result, "const");
53448853Sbostic break;
53548853Sbostic case 'U':
53648853Sbostic *type += 1;
53748853Sbostic if (non_empty)
53848853Sbostic string_append (result, " ");
53948853Sbostic else
54048853Sbostic non_empty = 1;
54148853Sbostic string_append (result, "unsigned");
54248853Sbostic break;
54348853Sbostic case 'V':
54448853Sbostic *type += 1;
54548853Sbostic if (non_empty)
54648853Sbostic string_append (result, " ");
54748853Sbostic else
54848853Sbostic non_empty = 1;
54948853Sbostic string_append (result, "volatile");
55048853Sbostic break;
55148853Sbostic default:
55248853Sbostic done = 1;
55348853Sbostic break;
55448853Sbostic }
55548853Sbostic }
55648853Sbostic
55748853Sbostic if (success)
55848853Sbostic switch (**type)
55948853Sbostic {
56048853Sbostic case '\0':
56148853Sbostic case '_':
56248853Sbostic break;
56348853Sbostic case 'v':
56448853Sbostic *type += 1;
56548853Sbostic if (non_empty)
56648853Sbostic string_append (result, " ");
56748853Sbostic string_append (result, "void");
56848853Sbostic break;
56948853Sbostic case 'x':
57048853Sbostic *type += 1;
57148853Sbostic if (non_empty)
57248853Sbostic string_append (result, " ");
57348853Sbostic string_append (result, "long long");
57448853Sbostic break;
57548853Sbostic case 'l':
57648853Sbostic *type += 1;
57748853Sbostic if (non_empty)
57848853Sbostic string_append (result, " ");
57948853Sbostic string_append (result, "long");
58048853Sbostic break;
58148853Sbostic case 'i':
58248853Sbostic *type += 1;
58348853Sbostic if (non_empty)
58448853Sbostic string_append (result, " ");
58548853Sbostic string_append (result, "int");
58648853Sbostic break;
58748853Sbostic case 's':
58848853Sbostic *type += 1;
58948853Sbostic if (non_empty)
59048853Sbostic string_append (result, " ");
59148853Sbostic string_append (result, "short");
59248853Sbostic break;
59348853Sbostic case 'c':
59448853Sbostic *type += 1;
59548853Sbostic if (non_empty)
59648853Sbostic string_append (result, " ");
59748853Sbostic string_append (result, "char");
59848853Sbostic break;
59948853Sbostic case 'r':
60048853Sbostic *type += 1;
60148853Sbostic if (non_empty)
60248853Sbostic string_append (result, " ");
60348853Sbostic string_append (result, "long double");
60448853Sbostic break;
60548853Sbostic case 'd':
60648853Sbostic *type += 1;
60748853Sbostic if (non_empty)
60848853Sbostic string_append (result, " ");
60948853Sbostic string_append (result, "double");
61048853Sbostic break;
61148853Sbostic case 'f':
61248853Sbostic *type += 1;
61348853Sbostic if (non_empty)
61448853Sbostic string_append (result, " ");
61548853Sbostic string_append (result, "float");
61648853Sbostic break;
61748853Sbostic case 'G':
61848853Sbostic *type += 1;
61948853Sbostic if (!isdigit (**type))
62048853Sbostic {
62148853Sbostic success = 0;
62248853Sbostic break;
62348853Sbostic }
62448853Sbostic /* fall through */
62548853Sbostic case '0':
62648853Sbostic case '1':
62748853Sbostic case '2':
62848853Sbostic case '3':
62948853Sbostic case '4':
63048853Sbostic case '5':
63148853Sbostic case '6':
63248853Sbostic case '7':
63348853Sbostic case '8':
63448853Sbostic case '9':
63548853Sbostic n = 0;
63648853Sbostic do
63748853Sbostic {
63848853Sbostic n *= 10;
63948853Sbostic n += **type - '0';
64048853Sbostic *type += 1;
64148853Sbostic }
64248853Sbostic while (isdigit (**type));
64348853Sbostic if (strlen (*type) < n)
64448853Sbostic {
64548853Sbostic success = 0;
64648853Sbostic break;
64748853Sbostic }
64848853Sbostic if (non_empty)
64948853Sbostic string_append (result, " ");
65048853Sbostic string_appendn (result, *type, n);
65148853Sbostic *type += n;
65248853Sbostic break;
65348853Sbostic default:
65448853Sbostic success = 0;
65548853Sbostic break;
65648853Sbostic }
65748853Sbostic
65848853Sbostic if (success)
65948853Sbostic {
66048853Sbostic if (!string_empty (&decl))
66148853Sbostic {
66248853Sbostic string_append (result, " ");
66348853Sbostic string_appends (result, &decl);
66448853Sbostic }
66548853Sbostic string_delete (&decl);
66648853Sbostic return 1;
66748853Sbostic }
66848853Sbostic else
66948853Sbostic {
67048853Sbostic string_delete (&decl);
67148853Sbostic string_delete (result);
67248853Sbostic return 0;
67348853Sbostic }
67448853Sbostic }
67548853Sbostic
67648853Sbostic /* `result' will be initialised in do_type; it will be freed on failure */
67748853Sbostic
67848853Sbostic static int
do_arg(type,result)67948853Sbostic do_arg (type, result)
68048853Sbostic const char **type;
68148853Sbostic string *result;
68248853Sbostic {
68348853Sbostic const char *start = *type;
68448853Sbostic
68548853Sbostic if (!do_type (type, result))
68648853Sbostic return 0;
68748853Sbostic remember_type (start, *type - start);
68848853Sbostic return 1;
68948853Sbostic }
69048853Sbostic
69148853Sbostic static void
remember_type(start,len)69248853Sbostic remember_type (start, len)
69348853Sbostic const char *start;
69448853Sbostic int len;
69548853Sbostic {
69648853Sbostic char *tem;
69748853Sbostic
69848853Sbostic if (ntypes >= typevec_size)
69948853Sbostic {
70048853Sbostic if (typevec_size == 0)
70148853Sbostic {
70248853Sbostic typevec_size = 3;
70348853Sbostic typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
70448853Sbostic }
70548853Sbostic else
70648853Sbostic {
70748853Sbostic typevec_size *= 2;
70848853Sbostic typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
70948853Sbostic }
71048853Sbostic }
71148853Sbostic tem = (char *) xmalloc (len + 1);
71248853Sbostic memcpy (tem, start, len);
71348853Sbostic tem[len] = '\0';
71448853Sbostic typevec[ntypes++] = tem;
71548853Sbostic }
71648853Sbostic
71748853Sbostic /* `decl' must be already initialised, usually non-empty;
71848853Sbostic it won't be freed on failure */
71948853Sbostic
72048853Sbostic static int
do_args(type,decl)72148853Sbostic do_args (type, decl)
72248853Sbostic const char **type;
72348853Sbostic string *decl;
72448853Sbostic {
72548853Sbostic string arg;
72648853Sbostic int need_comma = 0;
72748853Sbostic
72848853Sbostic string_append (decl, "(");
72948853Sbostic
73048853Sbostic while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
73148853Sbostic {
73248853Sbostic if (**type == 'N')
73348853Sbostic {
73448853Sbostic int r;
73548853Sbostic int t;
73648853Sbostic *type += 1;
73748853Sbostic if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
73848853Sbostic return 0;
73948853Sbostic while (--r >= 0)
74048853Sbostic {
74148853Sbostic const char *tem = typevec[t];
74248853Sbostic if (need_comma)
74348853Sbostic string_append (decl, ", ");
74448853Sbostic if (!do_arg (&tem, &arg))
74548853Sbostic return 0;
74648853Sbostic string_appends (decl, &arg);
74748853Sbostic string_delete (&arg);
74848853Sbostic need_comma = 1;
74948853Sbostic }
75048853Sbostic }
75148853Sbostic else
75248853Sbostic {
75348853Sbostic if (need_comma)
75448853Sbostic string_append (decl, ", ");
75548853Sbostic if (!do_arg (type, &arg))
75648853Sbostic return 0;
75748853Sbostic string_appends (decl, &arg);
75848853Sbostic string_delete (&arg);
75948853Sbostic need_comma = 1;
76048853Sbostic }
76148853Sbostic }
76248853Sbostic
76348853Sbostic if (**type == 'v')
76448853Sbostic *type += 1;
76548853Sbostic else if (**type == 'e')
76648853Sbostic {
76748853Sbostic *type += 1;
76848853Sbostic if (need_comma)
76948853Sbostic string_append (decl, ",");
77048853Sbostic string_append (decl, "...");
77148853Sbostic }
77248853Sbostic
77348853Sbostic string_append (decl, ")");
77448853Sbostic return 1;
77548853Sbostic }
77648853Sbostic
77748853Sbostic static void
munge_function_name(name)77848853Sbostic munge_function_name (name)
77948853Sbostic string *name;
78048853Sbostic {
78148853Sbostic if (!string_empty (name) && name->p - name->b >= 3
78248853Sbostic && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
78348853Sbostic {
78448853Sbostic int i;
78548853Sbostic /* see if it's an assignment expression */
78648853Sbostic if (name->p - name->b >= 10 /* op$assign_ */
78748853Sbostic && memcmp (name->b + 3, "assign_", 7) == 0)
78848853Sbostic {
78948853Sbostic for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
79048853Sbostic {
79148853Sbostic int len = name->p - name->b - 10;
79248853Sbostic if (strlen (optable[i].in) == len
79348853Sbostic && memcmp (optable[i].in, name->b + 10, len) == 0)
79448853Sbostic {
79548853Sbostic string_clear (name);
79648853Sbostic string_append (name, "operator");
79748853Sbostic string_append (name, optable[i].out);
79848853Sbostic string_append (name, "=");
79948853Sbostic return;
80048853Sbostic }
80148853Sbostic }
80248853Sbostic }
80348853Sbostic else
80448853Sbostic {
80548853Sbostic for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
80648853Sbostic {
80748853Sbostic int len = name->p - name->b - 3;
80848853Sbostic if (strlen (optable[i].in) == len
80948853Sbostic && memcmp (optable[i].in, name->b + 3, len) == 0)
81048853Sbostic {
81148853Sbostic string_clear (name);
81248853Sbostic string_append (name, "operator");
81348853Sbostic string_append (name, optable[i].out);
81448853Sbostic return;
81548853Sbostic }
81648853Sbostic }
81748853Sbostic }
81848853Sbostic return;
81948853Sbostic }
82048853Sbostic else if (!string_empty (name) && name->p - name->b >= 5
82148853Sbostic && memcmp (name->b, "type$", 5) == 0)
82248853Sbostic {
82348853Sbostic /* type conversion operator */
82448853Sbostic string type;
82548853Sbostic const char *tem = name->b + 5;
82648853Sbostic if (do_type (&tem, &type))
82748853Sbostic {
82848853Sbostic string_clear (name);
82948853Sbostic string_append (name, "operator ");
83048853Sbostic string_appends (name, &type);
83148853Sbostic string_delete (&type);
83248853Sbostic return;
83348853Sbostic }
83448853Sbostic }
83548853Sbostic }
83648853Sbostic
83748853Sbostic /* a mini string-handling package */
83848853Sbostic
83948853Sbostic static void
string_need(s,n)84048853Sbostic string_need (s, n)
84148853Sbostic string *s;
84248853Sbostic int n;
84348853Sbostic {
84448853Sbostic if (s->b == NULL)
84548853Sbostic {
84648853Sbostic if (n < 32)
84748853Sbostic n = 32;
84848853Sbostic s->p = s->b = (char *) xmalloc (n);
84948853Sbostic s->e = s->b + n;
85048853Sbostic }
85148853Sbostic else if (s->e - s->p < n)
85248853Sbostic {
85348853Sbostic int tem = s->p - s->b;
85448853Sbostic n += tem;
85548853Sbostic n *= 2;
85648853Sbostic s->b = (char *) xrealloc (s->b, n);
85748853Sbostic s->p = s->b + tem;
85848853Sbostic s->e = s->b + n;
85948853Sbostic }
86048853Sbostic }
86148853Sbostic
86248853Sbostic static void
string_delete(s)86348853Sbostic string_delete (s)
86448853Sbostic string *s;
86548853Sbostic {
86648853Sbostic if (s->b != NULL)
86748853Sbostic {
86848853Sbostic free (s->b);
86948853Sbostic s->b = s->e = s->p = NULL;
87048853Sbostic }
87148853Sbostic }
87248853Sbostic
87348853Sbostic static void
string_init(s)87448853Sbostic string_init (s)
87548853Sbostic string *s;
87648853Sbostic {
87748853Sbostic s->b = s->p = s->e = NULL;
87848853Sbostic }
87948853Sbostic
88048853Sbostic static void
string_clear(s)88148853Sbostic string_clear (s)
88248853Sbostic string *s;
88348853Sbostic {
88448853Sbostic s->p = s->b;
88548853Sbostic }
88648853Sbostic
88748853Sbostic static int
string_empty(s)88848853Sbostic string_empty (s)
88948853Sbostic string *s;
89048853Sbostic {
89148853Sbostic return s->b == s->p;
89248853Sbostic }
89348853Sbostic
89448853Sbostic static void
string_append(p,s)89548853Sbostic string_append (p, s)
89648853Sbostic string *p;
89748853Sbostic const char *s;
89848853Sbostic {
89948853Sbostic int n;
90048853Sbostic if (s == NULL || *s == '\0')
90148853Sbostic return;
90248853Sbostic n = strlen (s);
90348853Sbostic string_need (p, n);
90448853Sbostic memcpy (p->p, s, n);
90548853Sbostic p->p += n;
90648853Sbostic }
90748853Sbostic
90848853Sbostic static void
string_appends(p,s)90948853Sbostic string_appends (p, s)
91048853Sbostic string *p, *s;
91148853Sbostic {
91248853Sbostic int n;
91348853Sbostic if (s->b == s->p)
91448853Sbostic return;
91548853Sbostic n = s->p - s->b;
91648853Sbostic string_need (p, n);
91748853Sbostic memcpy (p->p, s->b, n);
91848853Sbostic p->p += n;
91948853Sbostic }
92048853Sbostic
92148853Sbostic static void
string_appendn(p,s,n)92248853Sbostic string_appendn (p, s, n)
92348853Sbostic string *p;
92448853Sbostic const char *s;
92548853Sbostic int n;
92648853Sbostic {
92748853Sbostic if (n == 0)
92848853Sbostic return;
92948853Sbostic string_need (p, n);
93048853Sbostic memcpy (p->p, s, n);
93148853Sbostic p->p += n;
93248853Sbostic }
93348853Sbostic
93448853Sbostic static void
string_prepend(p,s)93548853Sbostic string_prepend (p, s)
93648853Sbostic string *p;
93748853Sbostic const char *s;
93848853Sbostic {
93948853Sbostic if (s == NULL || *s == '\0')
94048853Sbostic return;
94148853Sbostic string_prependn (p, s, strlen (s));
94248853Sbostic }
94348853Sbostic
94448853Sbostic #if 0
94548853Sbostic static void
94648853Sbostic string_prepends (p, s)
94748853Sbostic string *p, *s;
94848853Sbostic {
94948853Sbostic if (s->b == s->p)
95048853Sbostic return;
95148853Sbostic string_prependn (p, s->b, s->p - s->b);
95248853Sbostic }
95348853Sbostic #endif
95448853Sbostic
95548853Sbostic static void
string_prependn(p,s,n)95648853Sbostic string_prependn (p, s, n)
95748853Sbostic string *p;
95848853Sbostic const char *s;
95948853Sbostic int n;
96048853Sbostic {
96148853Sbostic char *q;
96248853Sbostic
96348853Sbostic if (n == 0)
96448853Sbostic return;
96548853Sbostic string_need (p, n);
96648853Sbostic for (q = p->p - 1; q >= p->b; q--)
96748853Sbostic q[n] = q[0];
96848853Sbostic memcpy (p->b, s, n);
96948853Sbostic p->p += n;
97048853Sbostic }
971