diff options
author | Steve Chamberlain <sac@cygnus> | 1992-02-27 17:24:13 +0000 |
---|---|---|
committer | Steve Chamberlain <sac@cygnus> | 1992-02-27 17:24:13 +0000 |
commit | d2861901404dccfda821ebe019cdf9439ab7dcf4 (patch) | |
tree | 0be113582724f46f3d9b38c8ef843868c59c83fd /ld/cplus-dem.c | |
parent | cba0d141fb4c565ae5e04b339a95d57123aa46fb (diff) | |
download | gdb-d2861901404dccfda821ebe019cdf9439ab7dcf4.zip gdb-d2861901404dccfda821ebe019cdf9439ab7dcf4.tar.gz gdb-d2861901404dccfda821ebe019cdf9439ab7dcf4.tar.bz2 |
Why didn't it start emacs
Diffstat (limited to 'ld/cplus-dem.c')
-rw-r--r-- | ld/cplus-dem.c | 1363 |
1 files changed, 1363 insertions, 0 deletions
diff --git a/ld/cplus-dem.c b/ld/cplus-dem.c new file mode 100644 index 0000000..7495a63 --- /dev/null +++ b/ld/cplus-dem.c @@ -0,0 +1,1363 @@ +/* Demangler for GNU C++ + Copyright 1989, 1991 Free Software Foundation, Inc. + written by James Clark (jjc@@jclark.uucp) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* This is for g++ 1.95.03 (November 13 verison). */ + +/* This file exports one function + + char *cplus_demangle (const char *name, int mode) + + If NAME is a mangled function name produced by GNU C++, then + a pointer to a malloced string giving a C++ representation + of the name will be returned; otherwise NULL will be returned. + It is the caller's responsibility to free the string which + is returned. + + If MODE > 0, then ANSI qualifiers such as `const' and `void' are output. + Otherwise they are not. + If MODE >= 0, parameters are emitted; otherwise not. + + For example, + + cplus_demangle ("foo__1Ai", 0) => "A::foo(int)" + cplus_demangle ("foo__1Ai", 1) => "A::foo(int)" + cplus_demangle ("foo__1Ai", -1) => "A::foo" + + cplus_demangle ("foo__1Afe", 0) => "A::foo(float,...)" + cplus_demangle ("foo__1Afe", 1) => "A::foo(float,...)" + cplus_demangle ("foo__1Afe", -1) => "A::foo" + + This file imports xmalloc and xrealloc, which are like malloc and + realloc except that they generate a fatal error if there is no + available memory. */ + +/* define this if names don't start with _ */ +#define nounderscore 1 +#include <bfd.h> +#include <sysdep.h> +#define xmalloc ldmalloc +#define xrealloc realloc + +/* This is '$' on systems where the assembler can deal with that. + Where the assembler can't, it's '.' (but on many systems '.' is + used for other things). */ +#if !defined (CPLUS_MARKER) +#define CPLUS_MARKER '$' +#endif + +#ifndef __STDC__ +#define const +#endif + +#ifdef __STDC__ +extern char *cplus_demangle (const char *type, int mode); +#else +extern char *cplus_demangle (); +#endif + + +static char **typevec = 0; +static int ntypes = 0; +static int typevec_size = 0; + +const static struct optable { + const char *in; + const char *out; + int ansi; +} optable[] = { + "nw", " new", 1, /* new (1.92, ansi) */ + "dl", " delete", 1, /* new (1.92, ansi) */ + "new", " new", 0, /* old (1.91, and 1.x) */ + "delete", " delete", 0, /* old (1.91, and 1.x) */ + "as", "=", 1, /* ansi */ + "ne", "!=", 1, /* old, ansi */ + "eq", "==", 1, /* old, ansi */ + "ge", ">=", 1, /* old, ansi */ + "gt", ">", 1, /* old, ansi */ + "le", "<=", 1, /* old, ansi */ + "lt", "<", 1, /* old, ansi */ + "plus", "+", 0, /* old */ + "pl", "+", 1, /* ansi */ + "apl", "+=", 1, /* ansi */ + "minus", "-", 0, /* old */ + "mi", "-", 1, /* ansi */ + "ami", "-=", 1, /* ansi */ + "mult", "*", 0, /* old */ + "ml", "*", 1, /* ansi */ + "aml", "*=", 1, /* ansi */ + "convert", "+", 0, /* old (unary +) */ + "negate", "-", 0, /* old (unary -) */ + "trunc_mod", "%", 0, /* old */ + "md", "%", 1, /* ansi */ + "amd", "%=", 1, /* ansi */ + "trunc_div", "/", 0, /* old */ + "dv", "/", 1, /* ansi */ + "adv", "/=", 1, /* ansi */ + "truth_andif", "&&", 0, /* old */ + "aa", "&&", 1, /* ansi */ + "truth_orif", "||", 0, /* old */ + "oo", "||", 1, /* ansi */ + "truth_not", "!", 0, /* old */ + "nt", "!", 1, /* ansi */ + "postincrement", "++", 0, /* old */ + "pp", "++", 1, /* ansi */ + "postdecrement", "--", 0, /* old */ + "mm", "--", 1, /* ansi */ + "bit_ior", "|", 0, /* old */ + "or", "|", 1, /* ansi */ + "aor", "|=", 1, /* ansi */ + "bit_xor", "^", 0, /* old */ + "er", "^", 1, /* ansi */ + "aer", "^=", 1, /* ansi */ + "bit_and", "&", 0, /* old */ + "ad", "&", 1, /* ansi */ + "aad", "&=", 1, /* ansi */ + "bit_not", "~", 0, /* old */ + "co", "~", 1, /* ansi */ + "call", "()", 0, /* old */ + "cl", "()", 1, /* ansi */ + "alshift", "<<", 0, /* old */ + "ls", "<<", 1, /* ansi */ + "als", "<<=", 1, /* ansi */ + "arshift", ">>", 0, /* old */ + "rs", ">>", 1, /* ansi */ + "ars", ">>=", 1, /* ansi */ + "component", "->", 0, /* old */ + "rf", "->", 1, /* ansi */ + "indirect", "*", 0, /* old */ + "method_call", "->()", 0, /* old */ + "addr", "&", 0, /* old (unary &) */ + "array", "[]", 0, /* old */ + "vc", "[]", 1, /* ansi */ + "compound", ",", 0, /* old */ + "cm", ",", 1, /* ansi */ + "cond", "?:", 0, /* old */ + "cn", "?:", 1, /* psuedo-ansi */ + "max", ">?", 0, /* old */ + "mx", ">?", 1, /* psuedo-ansi */ + "min", "<?", 0, /* old */ + "mn", "<?", 1, /* psuedo-ansi */ + "nop", "", 0, /* old (for operator=) */ +}; + +/* Beware: these aren't '\0' terminated. */ + +typedef struct string { + char *b; /* pointer to start of string */ + char *p; /* pointer after last character */ + char *e; /* pointer after end of allocated space */ +} string; + +#if _STDC_ == 1 +#define PARAMS(x) x +#else +#define PARAMS(x) () +#endif + +static void +string_need PARAMS ((string *, int)); + +static void +string_delete PARAMS ((string *)); + +static void +string_init PARAMS ((string *)); + +static void +string_clear PARAMS ((string *)); + +static int +string_empty PARAMS ((string *)); + +static void +string_append PARAMS ((string *, const char *)); + +static void +string_appends PARAMS ((string *, string *)); + +static void +string_appendn PARAMS ((string *, const char *, int)); + +static void +string_prepend PARAMS ((string *, const char *)); + +static void +string_prependn PARAMS ((string *, const char *, int)); + +static int +get_count PARAMS ((const char **, int *)); + +static int +do_args PARAMS ((const char **, string *, int)); + +static int +do_type PARAMS ((const char **, string *, int)); + +static int +do_arg PARAMS ((const char **, string *, int)); + +static void +munge_function_name PARAMS ((string *, int)); + +static void +remember_type PARAMS ((const char *, int)); + +#if 0 +static void +string_prepends PARAMS ((string *, string *)); +#endif + + +/* Takes operator name as e.g. "++" and returns mangled + operator name (e.g. "postincrement_expr"), or NULL if not found. + + If ARG_MODE == 1, return the ANSI name; + if ARG_MODE == 0 return the old GNU name. */ +char * +cplus_mangle_opname (opname, arg_mode) + char *opname; + int arg_mode; +{ + int i, len = strlen (opname); + + + for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) + { + if (strlen (optable[i].out) == len + && arg_mode == optable[i].ansi + && memcmp (optable[i].out, opname, len) == 0) + return (char *)optable[i].in; + } + return 0; +} + +char * +cplus_demangle (type, arg_mode) + const char *type; + int arg_mode; +{ + string decl; + int n; + int success = 0; + int constructor = 0; + int destructor = 0; + int static_type = 0; + int const_flag = 0; + int i; + const char *p; +#ifndef LONGERNAMES + const char *premangle; +#endif + +# define print_ansi_qualifiers (arg_mode > 0) +# define print_arg_types (arg_mode >= 0) + + if (type == NULL || *type == '\0') + return NULL; +#ifndef nounderscore + if (*type++ != '_') + return NULL; +#endif + p = type; + while (*p != '\0' && !(*p == '_' && p[1] == '_')) + p++; + if (*p == '\0') + { + /* destructor */ + if (type[0] == '_' && type[1] == CPLUS_MARKER && type[2] == '_') + { + int n; + char *tem; + + type += 3; /* Get past _$_ at front. */ + while (isdigit (*type)) + /* If there are digits at the front, it's because + of new 2.0 name mangling. Just skip them. */ + type++; + + n = strlen (type)*2 + 3 + 2 + 1; + tem = (char *) xmalloc (n); + strcpy (tem, type); + strcat (tem, "::~"); + strcat (tem, type); + if (print_arg_types) + strcat (tem, "()"); + return tem; + } + /* static data member */ + if (*type != '_' && (p = strchr (type, CPLUS_MARKER)) != NULL) + { + int n = strlen (type) + 2; + char *tem = (char *) xmalloc (n); + memcpy (tem, type, p - type); + strcpy (tem + (p - type), "::"); + strcpy (tem + (p - type) + 2, p + 1); + return tem; + } + /* virtual table "_vt$" */ + if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == CPLUS_MARKER) + { + int n = strlen (type + 4) + 14 + 1; + char *tem = (char *) xmalloc (n); + strcpy (tem, type + 4); + strcat (tem, " virtual table"); + return tem; + } + return NULL; + } + + string_init (&decl); + + if (static_type) + { + if (!isdigit (p[0]) && ('t' != p[0])) + { + string_delete (&decl); + return NULL; + } + } + else if (p == type) + { + if (!isdigit (p[2]) && ('t' != p[2])) + { + p += 1; + while (*p != '\0' && !(*p == '_' && p[1] == '_')) + p++; + string_appendn (&decl, type, p - type); + string_need (&decl, 1); + *(decl.p) = '\0'; + munge_function_name (&decl, 1); + if (decl.b[0] == '_') + { + string_delete (&decl); + return NULL; + } + else + p += 2; + } + else + { + constructor = 1; + p += 2; + } + } + else + { + string_appendn (&decl, type, p - type); + string_need (&decl, 1); + *(decl.p) = '\0'; + munge_function_name (&decl, arg_mode); + p += 2; + } + +#ifndef LONGERNAMES + premangle = p; +#endif + switch (*p) + { + case 'C': + /* a const member function */ + if (!isdigit (p[1])) + { + string_delete (&decl); + return NULL; + } + p += 1; + const_flag = 1; + /* fall through */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = 0; + do + { + n *= 10; + n += *p - '0'; + p += 1; + } + while (isdigit (*p)); + if (strlen (p) < n) + { + string_delete (&decl); + return NULL; + } + if (constructor || destructor) + { + string_appendn (&decl, p, n); + string_append (&decl, "::"); + if (destructor) + string_append(&decl, "~"); + string_appendn (&decl, p, n); + } + else + { + string_prepend (&decl, "::"); + string_prependn (&decl, p, n); + } + p += n; +#ifndef LONGERNAMES + remember_type (premangle, p - premangle); +#endif + if (static_type) + { + string_append(&decl, p+1); + p += strlen(p); + success = 1; + } + else + success = do_args (&p, &decl, arg_mode); + if (const_flag && print_arg_types) + string_append (&decl, " const"); + break; + case 'F': + p += 1; + success = do_args (&p, &decl, arg_mode); + break; + /* template additions */ + case 't': + p += 1; + { + int r, i; + int non_empty = 0; + string tname; + string trawname; + + string temp; + int need_comma = 0; + + string_init(&tname); + string_init(&trawname); + + /* get template name */ + if (!get_count (&p, &r)) + return 0; + string_appendn (&tname, p, r); + string_appendn (&trawname, p, r); + string_appendn (&trawname, "", 1); + p += r; + string_append (&tname, "<"); + /* get size of template parameter list */ + if (!get_count (&p, &r)) + return 0; + for (i = 0; i < r; i++) + { + if (need_comma) + string_append (&tname, ", "); + /* Z for type parameters */ + if (*p == 'Z') + { + p += 1; + + success = do_type (&p, &temp, arg_mode); + string_appendn (&temp, "", 1); + if (success) + string_append (&tname, temp.b); + string_delete(&temp); + if (!success) + break; + } + /* otherwise, value parameter */ + else + { + const char *old_p = p; + int is_pointer = 0; + int is_real = 0; + int is_integral = 0; + int done = 0; + + success = do_type (&p, &temp, arg_mode); + string_appendn (&temp, "", 1); + if (success) + string_append (&tname, temp.b); + string_delete(&temp); + if (!success) + break; + string_append (&tname, "="); + while (*old_p && !done) + { + switch (*old_p) + { + case 'P': + case 'R': + done = is_pointer = 1; + break; + case 'C': /* const */ + case 'U': /* unsigned */ + case 'V': /* volatile */ + case 'F': /* function */ + case 'M': /* member function */ + case 'O': /* ??? */ + old_p++; + continue; + case 'Q': /* repetition of following */ + case 'T': /* remembered type */ + abort(); + break; + case 'v': /* void */ + abort(); + break; + case 'x': /* long long */ + case 'l': /* long */ + case 'i': /* int */ + case 's': /* short */ + case 'c': /* char */ + done = is_integral = 1; + break; + case 'r': /* long double */ + case 'd': /* double */ + case 'f': /* float */ + done = is_real = 1; + break; + default: + abort(); + } + } + if (is_integral) + { + if (*p == 'm') + { + string_appendn (&tname, "-", 1); + p++; + } + while (isdigit (*p)) + { + string_appendn (&tname, p, 1); + p++; + } + } + else if (is_real) + { + if (*p == 'm') + { + string_appendn (&tname, "-", 1); + p++; + } + while (isdigit (*p)) + { + string_appendn (&tname, p, 1); + p++; + } + if (*p == '.') /* fraction */ + { + string_appendn (&tname, ".", 1); + p++; + while (isdigit (*p)) + { + string_appendn (&tname, p, 1); + p++; + } + } + if (*p == 'e') /* exponent */ + { + string_appendn (&tname, "e", 1); + p++; + while (isdigit (*p)) + { + string_appendn (&tname, p, 1); + p++; + } + } + } + else if (is_pointer) + { + int symbol_len; + + if (!get_count (&p, &symbol_len)) + { + success = 0; + break; + } + string_appendn (&tname, p, symbol_len); + p += symbol_len; + } + } + need_comma = 1; + } + string_append (&tname, ">::"); + if (destructor) + string_append(&tname, "~"); + if (constructor || destructor) { + string_append (&tname, trawname.b); + } + string_delete(&trawname); + + if (!success) { + string_delete(&tname); + return 0; + } + string_prepend (&decl, tname.b); + string_delete(&tname); + + if (static_type) + { + string_append(&decl, p+1); + p += strlen(p); + success = 1; + } + else + success = do_args (&p, &decl, arg_mode); + break; + } + } + + for (i = 0; i < ntypes; i++) + if (typevec[i] != NULL) + free (typevec[i]); + ntypes = 0; + if (typevec != NULL) + { + free ((char *)typevec); + typevec = NULL; + typevec_size = 0; + } + + if (success) + { + string_appendn (&decl, "", 1); + return decl.b; + } + else + { + string_delete (&decl); + return NULL; + } +} + +static int +get_count (type, count) + const char **type; + int *count; +{ + if (!isdigit (**type)) + return 0; + *count = **type - '0'; + *type += 1; + /* see flush_repeats in cplus-method.c */ + if (isdigit (**type)) + { + const char *p = *type; + int n = *count; + do + { + n *= 10; + n += *p - '0'; + p += 1; + } + while (isdigit (*p)); + if (*p == '_') + { + *type = p + 1; + *count = n; + } + } + return 1; +} + +/* result will be initialised here; it will be freed on failure */ + +static int +do_type (type, result, arg_mode) + const char **type; + string *result; + int arg_mode; +{ + int n; + int done; + int non_empty = 0; + int success; + string decl; + const char *remembered_type; + + string_init (&decl); + string_init (result); + + done = 0; + success = 1; + while (success && !done) + { + int member; + switch (**type) + { + case 'Q': + n = (*type)[1] - '0'; + if (n < 0 || n > 9) + success = 0; + *type += 2; + while (n-- > 0) + do_type (type, result, arg_mode); + break; + + case 'P': + *type += 1; + string_prepend (&decl, "*"); + break; + + case 'R': + *type += 1; + string_prepend (&decl, "&"); + break; + + case 'T': + *type += 1; + if (!get_count (type, &n) || n >= ntypes) + success = 0; + else + { + remembered_type = typevec[n]; + type = &remembered_type; + } + break; + + case 'F': + *type += 1; + if (!string_empty (&decl) && decl.b[0] == '*') + { + string_prepend (&decl, "("); + string_append (&decl, ")"); + } + if (!do_args (type, &decl, arg_mode) || **type != '_') + success = 0; + else + *type += 1; + break; + + case 'M': + case 'O': + { + int constp = 0; + int volatilep = 0; + + member = **type == 'M'; + *type += 1; + if (!isdigit (**type)) + { + success = 0; + break; + } + n = 0; + do + { + n *= 10; + n += **type - '0'; + *type += 1; + } + while (isdigit (**type)); + if (strlen (*type) < n) + { + success = 0; + break; + } + string_append (&decl, ")"); + string_prepend (&decl, "::"); + string_prependn (&decl, *type, n); + string_prepend (&decl, "("); + *type += n; + if (member) + { + if (**type == 'C') + { + *type += 1; + constp = 1; + } + if (**type == 'V') + { + *type += 1; + volatilep = 1; + } + if (*(*type)++ != 'F') + { + success = 0; + break; + } + } + if ((member && !do_args (type, &decl, arg_mode)) || **type != '_') + { + success = 0; + break; + } + *type += 1; + if (! print_ansi_qualifiers) + break; + if (constp) + { + if (non_empty) + string_append (&decl, " "); + else + non_empty = 1; + string_append (&decl, "const"); + } + if (volatilep) + { + if (non_empty) + string_append (&decl, " "); + else + non_empty = 1; + string_append (&decl, "volatile"); + } + break; + } + + case 'C': + if ((*type)[1] == 'P') + { + *type += 1; + if (print_ansi_qualifiers) + { + if (!string_empty (&decl)) + string_prepend (&decl, " "); + string_prepend (&decl, "const"); + } + break; + } + + /* fall through */ + default: + done = 1; + break; + } + } + + done = 0; + non_empty = 0; + while (success && !done) + { + switch (**type) + { + case 'C': + *type += 1; + if (print_ansi_qualifiers) + { + if (non_empty) + string_append (result, " "); + else + non_empty = 1; + string_append (result, "const"); + } + break; + case 'U': + *type += 1; + if (non_empty) + string_append (result, " "); + else + non_empty = 1; + string_append (result, "unsigned"); + break; + case 'V': + *type += 1; + if (print_ansi_qualifiers) + { + if (non_empty) + string_append (result, " "); + else + non_empty = 1; + string_append (result, "volatile"); + } + break; + default: + done = 1; + break; + } + } + + if (success) + switch (**type) + { + case '\0': + case '_': + break; + case 'v': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "void"); + break; + case 'x': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "long long"); + break; + case 'l': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "long"); + break; + case 'i': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "int"); + break; + case 's': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "short"); + break; + case 'c': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "char"); + break; + case 'r': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "long double"); + break; + case 'd': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "double"); + break; + case 'f': + *type += 1; + if (non_empty) + string_append (result, " "); + string_append (result, "float"); + break; + case 'G': + *type += 1; + if (!isdigit (**type)) + { + success = 0; + break; + } + /* fall through */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + n = 0; + do + { + n *= 10; + n += **type - '0'; + *type += 1; + } + while (isdigit (**type)); + if (strlen (*type) < n) + { + success = 0; + break; + } + if (non_empty) + string_append (result, " "); + string_appendn (result, *type, n); + *type += n; + break; + default: + success = 0; + break; + } + + if (success) + { + if (!string_empty (&decl)) + { + string_append (result, " "); + string_appends (result, &decl); + } + string_delete (&decl); + return 1; + } + else + { + string_delete (&decl); + string_delete (result); + return 0; + } +} + +/* `result' will be initialised in do_type; it will be freed on failure */ + +static int +do_arg (type, result, arg_mode) + const char **type; + string *result; + int arg_mode; +{ + const char *start = *type; + + if (!do_type (type, result, arg_mode)) + return 0; + remember_type (start, *type - start); + return 1; +} + +static void +remember_type (start, len) + const char *start; + int len; +{ + char *tem; + + if (ntypes >= typevec_size) + { + if (typevec_size == 0) + { + typevec_size = 3; + typevec = (char **) xmalloc (sizeof (char*)*typevec_size); + } + else + { + typevec_size *= 2; + typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size); + } + } + tem = (char *) xmalloc (len + 1); + memcpy (tem, start, len); + tem[len] = '\0'; + typevec[ntypes++] = tem; +} + +/* `decl' must be already initialised, usually non-empty; + it won't be freed on failure */ + +static int +do_args (type, decl, arg_mode) + const char **type; + string *decl; + int arg_mode; +{ + string arg; + int need_comma = 0; + + if (print_arg_types) + string_append (decl, "("); + + while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v') + { + if (**type == 'N') + { + int r; + int t; + *type += 1; + if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes) + return 0; + while (--r >= 0) + { + const char *tem = typevec[t]; + if (need_comma && print_arg_types) + string_append (decl, ", "); + if (!do_arg (&tem, &arg, arg_mode)) + return 0; + if (print_arg_types) + string_appends (decl, &arg); + string_delete (&arg); + need_comma = 1; + } + } + else + { + if (need_comma & print_arg_types) + string_append (decl, ", "); + if (!do_arg (type, &arg, arg_mode)) + return 0; + if (print_arg_types) + string_appends (decl, &arg); + string_delete (&arg); + need_comma = 1; + } + } + + if (**type == 'v') + *type += 1; + else if (**type == 'e') + { + *type += 1; + if (print_arg_types) + { + if (need_comma) + string_append (decl, ","); + string_append (decl, "..."); + } + } + + if (print_arg_types) + string_append (decl, ")"); + return 1; +} + +static void +munge_function_name (name, arg_mode) + string *name; + int arg_mode; +{ + if (string_empty (name)) + return; + + if (name->p - name->b >= 3 + && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == CPLUS_MARKER) + { + int i; + /* see if it's an assignment expression */ + if (name->p - name->b >= 10 /* op$assign_ */ + && memcmp (name->b + 3, "assign_", 7) == 0) + { + for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) + { + int len = name->p - name->b - 10; + if (strlen (optable[i].in) == len + && memcmp (optable[i].in, name->b + 10, len) == 0) + { + string_clear (name); + string_append (name, "operator"); + string_append (name, optable[i].out); + string_append (name, "="); + return; + } + } + } + else + { + for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) + { + int len = name->p - name->b - 3; + if (strlen (optable[i].in) == len + && memcmp (optable[i].in, name->b + 3, len) == 0) + { + string_clear (name); + string_append (name, "operator"); + string_append (name, optable[i].out); + return; + } + } + } + return; + } + else if (name->p - name->b >= 5 && memcmp (name->b, "type$", 5) == 0) + { + /* type conversion operator */ + string type; + const char *tem = name->b + 5; + if (do_type (&tem, &type, arg_mode)) + { + string_clear (name); + string_append (name, "operator "); + string_appends (name, &type); + string_delete (&type); + return; + } + } + /* ANSI. */ + else if (name->b[2] == 'o' && name->b[3] == 'p') + { + /* type conversion operator. */ + string type; + const char *tem = name->b + 4; + if (do_type (&tem, &type, arg_mode)) + { + string_clear (name); + string_append (name, "operator "); + string_appends (name, &type); + string_delete (&type); + return; + } + } + else if (name->b[0] == '_' && name->b[1] == '_' + && name->b[2] >= 'a' && name->b[2] <= 'z' + && name->b[3] >= 'a' && name->b[3] <= 'z') + { + int i; + + if (name->b[4] == '\0') + { + /* Operator. */ + for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) + { + if (strlen (optable[i].in) == 2 + && memcmp (optable[i].in, name->b + 2, 2) == 0) + { + string_clear (name); + string_append (name, "operator"); + string_append (name, optable[i].out); + return; + } + } + } + else + { + if (name->b[2] != 'a' || name->b[5] != '\0') + return; + /* Assignment. */ + for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++) + { + if (strlen (optable[i].in) == 3 + && memcmp (optable[i].in, name->b + 2, 3) == 0) + { + string_clear (name); + string_append (name, "operator"); + string_append (name, optable[i].out); + return; + } + } + } + } +} + +/* a mini string-handling package */ + +static void +string_need (s, n) + string *s; + int n; +{ + if (s->b == NULL) + { + if (n < 32) + n = 32; + s->p = s->b = (char *) xmalloc (n); + s->e = s->b + n; + } + else if (s->e - s->p < n) + { + int tem = s->p - s->b; + n += tem; + n *= 2; + s->b = (char *) xrealloc (s->b, n); + s->p = s->b + tem; + s->e = s->b + n; + } +} + +static void +string_delete (s) + string *s; +{ + if (s->b != NULL) + { + free (s->b); + s->b = s->e = s->p = NULL; + } +} + +static void +string_init (s) + string *s; +{ + s->b = s->p = s->e = NULL; +} + +static void +string_clear (s) + string *s; +{ + s->p = s->b; +} + +static int +string_empty (s) + string *s; +{ + return s->b == s->p; +} + +static void +string_append (p, s) + string *p; + const char *s; +{ + int n; + if (s == NULL || *s == '\0') + return; + n = strlen (s); + string_need (p, n); + memcpy (p->p, s, n); + p->p += n; +} + +static void +string_appends (p, s) + string *p, *s; +{ + int n; + if (s->b == s->p) + return; + n = s->p - s->b; + string_need (p, n); + memcpy (p->p, s->b, n); + p->p += n; +} + +static void +string_appendn (p, s, n) + string *p; + const char *s; + int n; +{ + if (n == 0) + return; + string_need (p, n); + memcpy (p->p, s, n); + p->p += n; +} + +static void +string_prepend (p, s) + string *p; + const char *s; +{ + if (s == NULL || *s == '\0') + return; + string_prependn (p, s, strlen (s)); +} + +#if 0 +static void +string_prepends (p, s) + string *p, *s; +{ + if (s->b == s->p) + return; + string_prependn (p, s->b, s->p - s->b); +} +#endif + +static void +string_prependn (p, s, n) + string *p; + const char *s; + int n; +{ + char *q; + + if (n == 0) + return; + string_need (p, n); + for (q = p->p - 1; q >= p->b; q--) + q[n] = q[0]; + memcpy (p->b, s, n); + p->p += n; +} |