diff options
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/demangle.h | 3 | ||||
-rw-r--r-- | libiberty/ChangeLog | 8 | ||||
-rw-r--r-- | libiberty/cplus-dem.c | 277 | ||||
-rw-r--r-- | libiberty/testsuite/demangle-expected | 95 |
5 files changed, 279 insertions, 108 deletions
diff --git a/include/ChangeLog b/include/ChangeLog index 7e242a2dae..9ba0423b67 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2010-01-11 Tristan Gingold <gingold@adacore.com> + + * demangle.h (ada_demangle): Add prototype. + 2010-01-05 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> PR bootstrap/41771 diff --git a/include/demangle.h b/include/demangle.h index 76fab0a458..2ab27602be 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -160,6 +160,9 @@ java_demangle_v3_callback (const char *mangled, extern char* java_demangle_v3 (const char *mangled); +char * +ada_demangle (const char *mangled, int options); + enum gnu_v3_ctor_kinds { gnu_v3_complete_object_ctor = 1, gnu_v3_base_object_ctor, diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index effb327ea2..6d30823569 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,11 @@ +2010-01-11 Tristan Gingold <gingold@adacore.com> + + * cplus-dem.c (ada_demangle): Remove prototype. + (grow_vect): Removed. + (ada_demangle): Rewritten. + (cplus_demangle): Fix indentation. + * testsuite/demangle-expected: Add tests for Ada. + 2010-01-09 Ian Lance Taylor <iant@google.com> PR other/42230 diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 66285141ff..f20a5ef9d8 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -62,8 +62,6 @@ void * realloc (); #include "libiberty.h" -static char *ada_demangle (const char *, int); - #define min(X,Y) (((X) < (Y)) ? (X) : (Y)) /* A value at least one greater than the maximum number of characters @@ -478,8 +476,6 @@ demangle_arm_hp_template (struct work_stuff *, const char **, int, string *); static void recursively_demangle (struct work_stuff *, const char **, string *, int); -static void grow_vect (char **, size_t *, size_t, int); - /* Translate count to integer, consuming tokens in the process. Conversion terminates on the first non-digit character. @@ -872,129 +868,194 @@ cplus_demangle (const char *mangled, int options) } if (GNAT_DEMANGLING) - return ada_demangle(mangled,options); + return ada_demangle (mangled, options); ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); } +/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */ -/* Assuming *OLD_VECT points to an array of *SIZE objects of size - ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, - updating *OLD_VECT and *SIZE as necessary. */ - -static void -grow_vect (char **old_vect, size_t *size, size_t min_size, int element_size) -{ - if (*size < min_size) - { - *size *= 2; - if (*size < min_size) - *size = min_size; - *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size); - } -} - -/* Demangle ada names: - 1. Discard final __{DIGIT}+ or ${DIGIT}+ - 2. Convert other instances of embedded "__" to `.'. - 3. Discard leading _ada_. - 4. Remove everything after first ___ if it is followed by 'X'. - 5. Put symbols that should be suppressed in <...> brackets. - The resulting string is valid until the next call of ada_demangle. */ - -static char * +char * ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) { - int i, j; int len0; const char* p; - char *demangled = NULL; - int changed; - size_t demangled_size = 0; + char *d; + char *demangled; - changed = 0; - + /* Discard leading _ada_, which is used for library level subprograms. */ if (strncmp (mangled, "_ada_", 5) == 0) - { - mangled += 5; - changed = 1; - } - - if (mangled[0] == '_' || mangled[0] == '<') - goto Suppress; + mangled += 5; + + /* All ada unit names are lower-case. */ + if (!ISLOWER (mangled[0])) + goto unknown; + + /* Most of the demangling will trivially remove chars. Operator names + may add one char but because they are always preceeded by '__' which is + replaced by '.', they eventually never expand the size. '___elabs' and + '___elabb' add only 2 chars, but they occur only once. */ + len0 = strlen (mangled) + 2 + 1; + demangled = XNEWVEC (char, len0); - p = strstr (mangled, "___"); - if (p == NULL) - len0 = strlen (mangled); - else + d = demangled; + p = mangled; + while (1) { - if (p[3] == 'X') - { - len0 = p - mangled; - changed = 1; - } + /* Convert name, which is always lower-case. */ + if (ISLOWER (*p)) + { + do + *d++ = *p++; + while (ISLOWER(*p) || ISDIGIT (*p) + || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1])))); + } + else if (p[0] == 'O') + { + static const char * const operators[][2] = + {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"}, + {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"}, + {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="}, + {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"}, + {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"}, + {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"}, + {"Oexpon", "**"}, {NULL, NULL}}; + int k; + + for (k = 0; operators[k][0]; k++) + { + int l = strlen (operators[k][0]); + if (!strncmp (p, operators[k][0], l)) + { + p += l; + l = strlen (operators[k][1]); + *d++ = '"'; + memcpy (d, operators[k][1], l); + d += l; + *d++ = '"'; + break; + } + } + /* Operator not found. */ + if (!operators[k][0]) + goto unknown; + } else - goto Suppress; - } - - /* Make demangled big enough for possible expansion by operator name. */ - grow_vect (&demangled, - &demangled_size, 2 * len0 + 1, - sizeof (char)); - - if (ISDIGIT ((unsigned char) mangled[len0 - 1])) { - for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1) - ; - if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') - { - len0 = i - 1; - changed = 1; - } - else if (mangled[i] == '$') - { - len0 = i; - changed = 1; - } - } - - for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]); - i += 1, j += 1) - demangled[j] = mangled[i]; - - while (i < len0) - { - if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') - { - demangled[j] = '.'; - changed = 1; - i += 2; j += 1; - } + { + /* Not a GNAT encoding. */ + goto unknown; + } + + if (p[0] == '_') + { + /* Separator. */ + if (p[1] == '_') + { + /* Standard separator. Handled first. */ + p += 2; + if (ISDIGIT (*p)) + { + /* Overloading. */ + do + p++; + while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); + } + else if (*p == '_' && !strcmp (p + 1, "elabb")) + { + memcpy (d, "'Elab_Body", 10); + d += 10; + break; + } + else if (*p == '_' && !strcmp (p + 1, "elabs")) + { + memcpy (d, "'Elab_Spec", 10); + d += 10; + break; + } + else + { + *d++ = '.'; + continue; + } + } + else if (p[1] == 'B' || p[1] == 'E') + { + /* Entry Body or barrier Evaluation. */ + p += 2; + while (ISDIGIT (*p)) + p++; + if (p[0] == 's' && p[1] == 0) + break; + else + goto unknown; + } + else + goto unknown; + } + + if (p[0] == 'T' && p[1] == 'K') + { + if (p[2] == 'B' && p[3] == 0) + { + /* Subprogram for task body. */ + break; + } + else if (p[2] == '_' && p[3] == '_') + { + /* Inner declarations in a task. */ + p += 4; + *d++ = '.'; + continue; + } + else + goto unknown; + } + if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) + { + /* Protected type subprogram. */ + break; + } + if (p[0] == 'E' && p[1] == 0) + { + /* Exception name. */ + goto unknown; + } + if (*p == 'N' || *p == 'S') + { + /* Enumerated type name table. */ + goto unknown; + } + if (p[0] == 'X') + { + /* Body nested. */ + if (p[1] == 'n' || p[1] == 'b') + p += 2; + else if (p[1] == 0) + p++; + } + if (p[0] == '.' && ISDIGIT (p[1])) + { + /* Nested subprogram. */ + p += 2; + while (ISDIGIT (*p)) + p++; + } + if (*p == 0) + { + /* End of mangled name. */ + break; + } else - { - demangled[j] = mangled[i]; - i += 1; j += 1; - } + goto unknown; } - demangled[j] = '\000'; - - for (i = 0; demangled[i] != '\0'; i += 1) - if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ') - goto Suppress; + *d = 0; + return demangled; - if (! changed) - { - free (demangled); - return NULL; - } - else - return demangled; - - Suppress: - grow_vect (&demangled, - &demangled_size, strlen (mangled) + 3, - sizeof (char)); + unknown: + len0 = strlen (mangled); + demangled = XNEWVEC (char, len0 + 3); if (mangled[0] == '<') strcpy (demangled, mangled); diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index 6798154d2f..c201a98327 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -3926,3 +3926,98 @@ S<int>::x::{lambda()#3}::operator()() const --format=gnu-v3 _Z1fN1SUt_E f(S::{unnamed type#1}) +# +# Ada (GNAT) tests. +# +# Simple test. +--format=gnat +yz__qrs +yz.qrs +# Operator +--format=gnat +oper__Oadd +oper."+" +# Overloaded subprogram. +--format=gnat +yz__qrs__2 +yz.qrs +# Nested subprogram. +--format=gnat +yz__qrs__tuv.1661 +yz.qrs.tuv +# Nested and overloaded subprograms. +--format=gnat +yz__qrs__tuv__2_1.1667 +yz.qrs.tuv +--format=gnat +yz__qrs__tuv__2_2.1670 +yz.qrs.tuv +--format=gnat +yz__qrs__tuv__2_3.1674 +yz.qrs.tuv +# Elaborated flag (not demangled) +--format=gnat +x_E +<x_E> +# Nested package +--format=gnat +x__m1 +x.m1 +--format=gnat +x__m3 +x.m3 +--format=gnat +x__y__m2X +x.y.m2 +--format=gnat +x__y__z__rXb +x.y.z.r +# Child package +--format=gnat +x__y__j +x.y.j +# Library level +--format=gnat +_ada_x__m3 +x.m3 +# Package body elaborator +--format=gnat +p___elabb +p'Elab_Body +# Package spec elaborator +--format=gnat +p___elabs +p'Elab_Spec +# Task body +--format=gnat +p__taskobjTKB +p.taskobj +# Task subprogram +--format=gnat +p__taskobjTK__f1.2330 +p.taskobj.f1 +# Protected types subprograms +--format=gnat +prot__lock__getN +prot.lock.get +--format=gnat +prot__lock__getP +prot.lock.get +--format=gnat +prot__lock__get__sub.2590 +prot.lock.get.sub +--format=gnat +prot__lock__setN +prot.lock.set +--format=gnat +prot__lock__setP +prot.lock.set +# Protected type entries +--format=gnat +prot__lock__update_B7s +prot.lock.update +--format=gnat +prot__lock__update_E6s +prot.lock.update + + |