]> git.saurik.com Git - apple/xnu.git/blobdiff - libsa/c++rem3.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / libsa / c++rem3.c
diff --git a/libsa/c++rem3.c b/libsa/c++rem3.c
deleted file mode 100644 (file)
index 44d76d6..0000000
+++ /dev/null
@@ -1,2215 +0,0 @@
-// 45678901234567890123456789012345678901234567890123456789012345678901234567890
-/*
-
-Rules specification by
-Stan Shebs of Apple Computer, Inc 2002
-
-Parse and remangle implemented by
-Godfrey van der Linden of Apple Computer, Inc 2002
-
-Rules for demangling IOKit symbols
-
-In Darwin versions 1.0 through at least 5.2, IOKit is compiled using
-GCC version 2.  GCC 2's C++ symbol mangling algorithm ultimately
-derives from the basic scheme described in the Annotated C++ Reference
-Manual (ARM), section 7.2.1c, with a number of changes, mostly due to
-the expansion of the language since the ARM was published in 1990.
-
-This description is not complete.  It omits RTTI, thunks, and
-templates, since they are not allowed in IOKit.  The description also
-mentions mangled name constructs that are not disallowed in IOKit, but
-that as of Jan 2002, did actually appear in any symbol in the base
-system.
-
-A mangled name basically consists of a function name followed
-by two underscores, optionally followed by a signature computed
-from the function's argument types.  (Note that in Darwin, the
-compiler adds an additional underscore to all C and C++ symbols.
-The description assumes this has been removed.)
-
-<special_or_name> ::= <gnu_special>
-                    | <mangled_name>
-
-<mangled_name> ::= <prefix> [ <signature> ]
-
-<prefix> ::= [ "_GLOBAL_" [ID] "__" ] <function_name> "__" [ <opinfo> ]
-
-<function_name> ::= <char> <char>*
-                  | NULL
-
-Questions for Stan (@@@Stan@@@)
-1> A valid <opinfo> implies a null function name.
-2> I wonder if an <opinfo> is mutually exclusive with a <function_name> perhaps something like :-
-<prefix> ::= [ "_GLOBAL_" ("I"|"D") "__" ] ((<function_name> "__") | <opinfo>)
-3> Do constructors turn up as an opinfo or a NULL function name?
-
-The optional "_GLOBAL_"("I"|"D")"__" sequence indicates global constructors
-and destructors, but in practice these do not appear with the mach-o Apple 2.95
-
-A Null <function_name> indicates a constructor or an operator.
-
-Since <function_name> may include trailing underscores, the demangler
-should scan forward until a non-underscore is seen, and then take the
-last two as the separator between name and signature.
-
-<function_name> may also include any number of leading underscores, so
-the demangler needs to add those to <function_name> and look for the
-"__" following the name.
-
-<gnu_special> ::= ("_._"|"_$_" ) <class_name>  ; destructor
-                | "__vt_" <class_name>         ; virtual table
-                | "_" <class_name> ("."|"$") <varname> ; Variable
-
-<class_name> ::= <counted_class_name>
-               | "Q" <qualified_name>
-               | "K" <qualified_name>  ; ignored and illegal
-
-<counted_class_name> ::= <count> <name>
-
-<qualified_name> ::= <q_count> <counted_class_name> <counted_class_name>*
-
-<opinfo> ::= "type" <type>
-           | "__op" <type>
-           | <opname> "__"
-           | "a"
-
-<opname> ::= "aa"      # &&
-           | "aad"     # &=
-           | "ad"      # &
-           | "adv"     # /=
-           | "aer"     # ^=
-           | "als"     # <<=
-           | "amd"     # %=
-           | "ami"     # -=
-           | "aml"     # *=
-           | "aor"     # |=
-           | "apl"     # +=
-           | "ars"     # >>=
-           | "as"      # =
-           | "cl"      # ()
-           | "cm"      # ,
-           | "cn"      # ?:
-           | "co"      # ~
-           | "dl"      # delete
-           | "dv"      # /
-           | "eq"      # ==
-           | "er"      # ^
-           | "ge"      # >=
-           | "gt"      # >
-           | "le"      # <=
-           | "ls"      # <<
-           | "lt"      # <
-           | "md"      # %
-           | "mi"      # -
-           | "ml"      # *
-           | "mm"      # --
-           | "mn"      # <?
-           | "mx"      # >?
-           | "ne"      # !=
-           | "nt"      # !
-           | "nw"      # new
-           | "oo"      # ||
-           | "or"      # |
-           | "pl"      # +
-           | "pp"      # ++
-           | "rf"      # ->
-           | "rm"      # ->*
-           | "rs"      # >>
-           | "sz"      # sizeof
-           | "vc"      # []
-           | "vd"      # delete[]
-           | "vn"      # new[]
-
-Questions for Stan (@@@Stan@@@)
-1> What the hell is The "type" & "__op" stuff?
-
-IOKit has so far only been observed to use operations new ("nw") and
-delete ("dl").
-
-The signature is a concatenated list of elements, which are usually
-argument types, but may include other sorts of things.
-
-<signature> ::= <qualifier>* <s_element> <argument_types>
-
-<s_element> ::= <class_name>
-              | "S"
-              | "F" <argument_types> [ "_" <return_type> ] 
-
-Questions for Stan (@@@Stan@@@)
-1> I think the 'B' phrase should probably read '| "B" <index>'?
-2> Ambiguous productions for signature
-   OSObject::func(struct timeval fred) => _func__8OSObject7timeval
-   signature could be parsed as
-        <s_element> <s_element> or <s_element> <argument_types>
-    I believe the second one must be the valid production.
-
-<count> ::= <digit> <digit>*
-
-<varname> :: <name>
-
-<name> ::= <char> <char>*
-
-The <count> is the number of characters in <name>.
-
-Argument types are a concatenated sequence of types.
-
-<argument_types> ::= # Empty
-                   | <arg_type>+
-<arg_type> ::= <type>  [ "n" <index> ]
-            | "N" <count> <pos>
-             | "T" <index>
-
-The "N" repeats and "T" references to already-seen typescan only
-appear if -fno-squangle (no squashed mangling), and in practice aren't
-seen in IOKit symbols.
-
-<index> ::= <digit> | <digit> <digit> <digit>* "_"
-
-Return types are just like any other sort of type.
-
-<return_type> ::= <type>
-
-Types consist of a variable number of declarators in front of a basic
-type.
-
-<type> ::= <declarator>* <base_type>
-
-<declarator> ::= "P"            ; pointer
-               | "p"            ; pointer (but never occurs?)
-               | "R"            ; reference (&)
-               | "A" <count>    ; array
-               | "T" <index>
-               | "O" <count>
-               | <qualifier>
-
-The "A" <count> production can produce an ambigous output if it is followed by a counted class name or structure name.
-
-The "T" reference to a type does not appear in IOKit symbols, nor do
-the "M" and "O" declarators.
-
-<base_type> ::= <function_type>        ; function
-              | <method_type>  ; method
-              | <type_qualifier>* <fund_type_id>
-
-<function_type> ::= "F" <argument_types> "_" <type>
-
-<method_type> ::= "M" <class_name> <function_type>
-
-A qualified name consists of a count of types, followed by all the
-types concatenated together.  For instance, Namespace::Class is
-Q29Namespace5Class.  For more than 9 types (which has not yet occurred
-in IOKit), the multi-digit count is surrounded by underscores.
-
-Questions for Stan (@@@Stan@@@)
-1> Can the types in a qualified name really be generic types or can the set be restricted to just counted class names?
-
-<q_count> ::= <digit> | "_" <digit> <digit>* "_"
-
-Fundamental types are single letters representing standard built-in
-types, optionally preceded by type qualifiers for properties like
-signedness and constness.  For instance, CUi is a const unsigned int.
-
-<type_qualifier> ::= "S"        ; signed (chars only)
-                   | "U"        ; unsigned (any integral type)
-                   | "J"        ; __complex
-                   | <qualifier>
-
-<fund_type_id> ::= <class_name>
-                 | "b"          ; bool
-                 | "c"          ; char
-                 | "d"          ; double
-                 | "f"          ; float
-                 | "i"          ; int
-                 | "l"          ; long
-                 | "r"          ; long double
-                 | "s"          ; short
-                 | "v"          ; void
-                 | "w"          ; wchar_t
-                 | "x"          ; long long
-                 | "G" <count>  ; ?????
-                 | "e"         ; ellipsis
-
-"G" does not appear in IOKit symbols in this context.
-
-<qualifier> ::= "C"             ; const
-              | "V"             ; volatile
-              | "u"             ; restrict (C99)
-              | "G"             ; struct/union/enum unused by gcc3
-
-The restrict qualifier has not appeared in IOKit symbols.
-
-*/
-#if KERNEL
-
-#include <stdarg.h>
-#include <string.h>
-
-#include <sys/systm.h>
-
-#include <libkern/OSTypes.h>
-
-#include <libsa/stdlib.h>
-
-enum { false = 0, true = 1 };
-
-#else /* !KERNEL */
-
-#include <unistd.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#endif /* KERNEL */
-
-#include "c++rem3.h"
-
-#define STRLEN(s) (sizeof(s)-1)
-#define APPENDSTR(c, str) do { appendNStr(c, str, STRLEN(str)); } while (0)
-
-#define MAX_COMPOUND_TYPES     128
-#define MAX_ENTRIES            256
-#define MAX_SDICT_ENTRIES      256
-#define MAX_BDICT_ENTRIES       64
-#define MAX_RETURN_BUFFER      256
-
-// Can't be bigger that 16 entries
-typedef enum NameTypes {
-    kNTUndefined,      kNTClass,       kNTFunction,    kNTFuncEnd,
-    kNTMethod,         kNTBuiltIn,     kNTDeclarator,  kNTArray,
-    kNTKName,          kNTSubstitute,  kNTSubQualClass
-} NameTypes;
-
-typedef struct TypeData {
-    short fStartEntry, fNumEntries;
-} TypeData;
-
-typedef struct BaseTypeData {
-    const char *fFundTypeID;   // May contain the type itself for kNTBuiltIt
-    unsigned int fLen:16;
-    unsigned int fType:4;      // Must fit a NameType
-    unsigned int fVolatile:1;
-    unsigned int fConst:1;
-    unsigned int fSigned:1;
-    unsigned int fUnsigned:1;
-    unsigned int fPseudo:1;
-    unsigned int fQualified:1;
-} BaseTypeData;
-
-typedef struct CheckPoint {
-    const char *fInChar;
-    unsigned char fNumI, fNumO, fNumT, fNumB, fNumS;
-} CheckPoint;
-
-typedef struct ParseContext {
-    CheckPoint fP;
-    BaseTypeData fInEntries[MAX_ENTRIES];      // Input parsed elements
-    BaseTypeData fOutEntries[MAX_ENTRIES];     // Output parsed elements
-    TypeData fTypeList[MAX_COMPOUND_TYPES];    // Table of types
-    TypeData fSubDict[MAX_SDICT_ENTRIES];
-    TypeData fBDict[MAX_BDICT_ENTRIES];                // B dictionary types
-    BaseTypeData *fCurBaseP;
-    const char *fInStr;
-    char *fOutStrEnd;
-    char *fOutChar;
-    int fInSize;
-    Rem3Return fRetCode;
-} ParseContext;
-
-//
-// The only forward declaration necessary
-//
-static Boolean parse_type(ParseContext *c);
-
-// Helper functions for walking through the string
-static __inline__ char getNext(ParseContext *c)
-{
-    return *c->fP.fInChar++;
-}
-
-static __inline__ CheckPoint *checkPoint(ParseContext *c)
-{
-    return &c->fP;
-}
-
-static __inline__ void resetTo(ParseContext *c, CheckPoint *chk)
-{
-    c->fP = *chk;
-}
-
-static __inline__ const char *inCharFromCheck(CheckPoint *chk)
-{
-    return chk->fInChar;
-}
-
-static __inline__ void advance(ParseContext *c, int len)
-{
-    c->fP.fInChar += len;
-}
-
-static __inline__ Boolean retard(ParseContext *c, int len)
-{
-    const char *cp = c->fP.fInChar - len;
-    if (cp < c->fInStr)
-        return false;
-
-    c->fP.fInChar = cp;
-    return true;
-}
-
-static __inline__ char peekAt(ParseContext *c, int index)
-{
-    return c->fP.fInChar[index];
-}
-
-static __inline__ char peekNext(ParseContext *c)
-{
-    return peekAt(c, 0);
-}
-
-static __inline__ Boolean atEnd(ParseContext *c)
-{
-    return '\0' == peekNext(c);
-}
-
-static __inline__ Boolean hasRemain(ParseContext *c, int len)
-{
-    return (c->fP.fInChar - c->fInStr + len <= c->fInSize);
-}
-
-//
-// Routines for allocating entries in the various
-//
-static __inline__ BaseTypeData *newIn(ParseContext *c)
-{
-    BaseTypeData *iP;
-
-    if (c->fP.fNumI < MAX_ENTRIES) {
-        iP = &c->fInEntries[c->fP.fNumI++];
-        bzero(iP, sizeof(*iP));
-        c->fCurBaseP = iP;
-        return iP;
-    }
-    else {
-        c->fRetCode = kR3InternalNotRemangled;
-        return NULL;
-    }
-}
-
-static __inline__ BaseTypeData *newOut(ParseContext *c)
-{
-    BaseTypeData *oP;
-
-    if (c->fP.fNumO < MAX_ENTRIES) {
-        oP = &c->fOutEntries[c->fP.fNumO++];
-        return oP;
-    }
-    else {
-        c->fRetCode = kR3InternalNotRemangled;
-        return NULL;
-    }
-}
-
-static __inline__ TypeData *
-newSub(ParseContext *c, int start, int num)
-{
-    TypeData *sP;
-
-    if (c->fP.fNumS < MAX_SDICT_ENTRIES) {
-        sP = &c->fSubDict[c->fP.fNumS++];
-        sP->fStartEntry = start;
-        sP->fNumEntries = num;
-        return sP;
-    }
-    else {
-        c->fRetCode = kR3InternalNotRemangled;
-        return NULL;
-    }
-}
-
-static __inline__ TypeData *
-newBDict(ParseContext *c, int start, int num)
-{
-    TypeData *bP;
-
-    if (c->fP.fNumB < MAX_BDICT_ENTRIES) {
-        bP = &c->fBDict[c->fP.fNumB++];
-        bP->fStartEntry = start;
-        bP->fNumEntries = num;
-        return bP;
-    }
-    else {
-        c->fRetCode = kR3InternalNotRemangled;
-        return NULL;
-    }
-}
-
-static __inline__ TypeData *
-newType(ParseContext *c, int start)
-{
-    TypeData *tP;
-
-    if (c->fP.fNumT < MAX_COMPOUND_TYPES) {
-        tP = &c->fTypeList[c->fP.fNumT++];
-        tP->fStartEntry = start;
-        return tP;
-    }
-    else
-        return NULL;
-}
-
-static __inline__ TypeData *
-dupType(ParseContext *c, TypeData *iTP, int offset)
-{
-    TypeData *tP = newType(c, iTP->fStartEntry + offset);
-    if (tP)
-        tP->fNumEntries = iTP->fNumEntries;
-
-    return tP;
-}
-
-//
-// Identifier character recognition helpers, can be optimised
-//
-static __inline__ Boolean isValidFirstAlphabetic(char c)
-{
-    if ('a' <= c && c <= 'z')
-        return true;
-    else if ('A' <= c && c <= 'Z')
-        return true;
-    else
-        return false;
-}
-
-static __inline__ Boolean isValidFirstChar(char c)
-{
-    if (isValidFirstAlphabetic(c))
-        return true;
-    else if (c == '_')
-        return true;
-    else
-        return false;
-}
-
-static __inline__ Boolean isValidChar(char c)
-{
-    if (isValidFirstChar(c))
-        return true;
-    else if ('0' <= c && c <= '9')
-        return true;
-    else
-        return false;
-}
-
-//
-// Helper function for recognising characters and strings
-//
-
-// Check the current input is the given character
-static __inline__ Boolean isNext(ParseContext *c, char ch)
-{
-    if (peekNext(c) == ch) {
-        advance(c, 1);
-        return true;
-    }
-    else
-        return false;
-}
-
-// Check the current input is ONE of the characters in str
-static Boolean charNext(ParseContext *c, const char *str)
-{
-    if (hasRemain(c, 1)) {
-        char ch = peekNext(c);
-        char next;
-
-        while ( (next = *str++) )
-            if (next == ch) {
-                advance(c, 1);
-                return true;
-            }
-    }
-
-    return false;
-}
-
-// Check the current input for 'str'
-static Boolean strNext(ParseContext *c, const char *str)
-{
-    const char *cp = c->fP.fInChar;
-
-    do {
-        if (!*str) {
-            c->fP.fInChar = (const char *) cp;
-            return true;
-        }
-        else if (!*cp)
-            return false;
-
-    } while (*cp++ == *str++);
-
-    return false;
-}
-
-//
-// Qualifier re-encoding
-//
-static void
-decodeQual(BaseTypeData *typeP, int *qualLenP, const char **qualP)
-{
-    const char *qual;
-    int qualLen;
-
-    if (typeP->fConst && typeP->fVolatile)
-        { qual = "VK"; qualLen = 2; }
-    else if (typeP->fConst)
-        { qual = "K";  qualLen = 1; }
-    else if (typeP->fVolatile)
-        { qual = "V";  qualLen = 1; }
-    else
-        { qual = NULL; qualLen = 0; }
-
-    *qualLenP = qualLen;
-    *qualP = qual;
-}
-
-
-//
-// Output functions
-//
-
-static void appendChar(ParseContext *c, char ch)
-{
-    char *outAddr = c->fOutChar++;
-    if (outAddr < c->fOutStrEnd)
-        *outAddr = ch;
-}
-
-static void appendNStr(ParseContext *c, const char *str, int len)
-{
-    char *outAddr = c->fOutChar;
-
-    c->fOutChar += len;
-    if (c->fOutChar < c->fOutStrEnd)
-        bcopy(str, outAddr, len);
-}
-
-static __inline__ void appendStr(ParseContext *c, const char *str)
-{
-    appendNStr(c, str, strlen(str));
-}
-
-static void appendSub(ParseContext *c, int ls)
-{
-    appendChar(c, 'S');
-    if (ls) {
-        if (--ls >= 36) {
-            int ms;
-    
-            ms = ls / 36;
-            appendChar(c, (ms < 10)? '0' + ms : 'A' + ms - 10);
-            ls -= (ms * 36);
-        }
-        appendChar(c, (ls < 10)? '0' + ls : 'A' + ls - 10);
-    }
-    appendChar(c, '_');
-}
-
-static Boolean compareTypes(ParseContext *c, int sub, int entry, int numEntries)
-{
-    TypeData *subP = &c->fSubDict[sub];
-    BaseTypeData *bSP, *bIP;
-    int i;
-
-    if (subP->fNumEntries != numEntries)
-        return false;
-
-    bSP = &c->fInEntries[subP->fStartEntry];
-    bIP = &c->fInEntries[entry];
-
-    for (i = 0; i < numEntries; i++, bSP++, bIP++) {
-        if (bSP->fType != bIP->fType)
-            return false;
-
-        switch (bSP->fType) {
-        case kNTClass:
-            if (bSP->fLen != bIP->fLen)
-                return false;
-            else if (strncmp(bSP->fFundTypeID, bIP->fFundTypeID, bSP->fLen))
-                return false;
-            break;
-
-        case kNTArray:
-        case kNTBuiltIn:
-        case kNTDeclarator:
-            if (bSP->fFundTypeID != bIP->fFundTypeID)
-                return false;
-            break;
-
-        case kNTMethod:
-        case kNTFunction:
-        case kNTUndefined:
-        case kNTKName:
-            break;             // OK so far
-
-        default:
-            return false;      // Fatal errors 
-        }
-    }
-
-    return true;
-}
-
-static int searchDict(ParseContext *c, int entry, int numE)
-{
-    int sub, numSubs = c->fP.fNumS;
-
-        // don't try to substitute the last builtin 
-    if (numE == 1 && kNTBuiltIn == c->fInEntries[entry].fType)
-        return -1;
-        
-    for (sub = 0; sub < numSubs; sub++)
-        if (compareTypes(c, sub, entry, numE))
-            return sub;
-
-    return -1;
-}
-
-static int searchDictClass(ParseContext *c, const char *qname, int len)
-{
-    TypeData *subP;
-    int sub, numSubs = c->fP.fNumS;
-
-    for (sub = 0, subP = c->fSubDict; sub < numSubs; sub++, subP++) {
-        BaseTypeData *iP = &c->fInEntries[subP->fStartEntry];
-
-        if (kNTClass != iP->fType || iP->fLen != len)
-            continue;
-        if (!strncmp(iP->fFundTypeID, qname, len))
-            return sub;
-    }
-
-    return -1;
-}
-
-static Boolean
-appendQualifiedClass(ParseContext *c, int entry)
-{
-    BaseTypeData *iP, *oP, *sP, *endSP;
-    const char *cp, *typeID;
-    char *cp_new;
-    int sub, subEntry, prefixLen;
-    int q_count;
-
-    int decodeStart = c->fP.fNumI;
-
-    // Scan through the incom
-    iP = &c->fInEntries[entry];
-    endSP = &c->fInEntries[MAX_ENTRIES];
-    sP = &c->fInEntries[decodeStart];
-
-    prefixLen = iP->fLen;
-    typeID = cp = iP->fFundTypeID;
-    for (q_count = 0; sP < endSP && (cp-typeID) < prefixLen; q_count++, sP++) {
-        int count;
-
-        count = strtoul(cp, &cp_new, 10);
-       cp = cp_new + count;
-
-        sP->fType = kNTClass;
-        sP->fFundTypeID = typeID;
-        sP->fLen = cp - typeID;
-    }
-    if (sP >= endSP)
-        return false;
-    
-    // Search backwards until I find the first substitution
-    sub = -1;
-    for (subEntry = q_count, sP--; subEntry > 0; subEntry--, sP--) {
-        sub = searchDictClass(c, sP->fFundTypeID, sP->fLen);
-        if (-1 != sub)
-            break;
-    }
-
-    // Now drop the symbol into the output buffer
-    oP = newOut(c);
-    if (!oP)
-        return false;
-
-    if (sub < 0)
-        *oP = *iP;     // No sub copy original
-    else {
-        // Substitution found
-        prefixLen = sP->fLen;          // Length of substitution
-
-        oP->fType = kNTSubstitute;     // Assume complete substitution
-        oP->fLen = sub;
-        oP->fFundTypeID = NULL;
-
-        // We have a partial substitution so tag on the unmatched bit
-        if (prefixLen != iP->fLen) {
-            oP->fType = kNTSubQualClass; // Re-characterise as 2 part sub
-    
-            oP = newOut(c);
-            if (!oP)
-                return false;
-
-            *oP = *iP;                 // Duplicate the original
-            oP->fType = kNTSubQualClass;
-            oP->fFundTypeID += prefixLen; // Skip leading substituted text
-            oP->fLen -= prefixLen;
-        }
-    }
-
-    // Finally insert the qualified class names into the dictionary
-    for (subEntry++, sP++; subEntry < q_count; subEntry++, decodeStart++) {
-        c->fInEntries[decodeStart] = *sP++;
-        if (!newSub(c, decodeStart, 1))
-            return false;
-    }
-    c->fP.fNumI = decodeStart;
-
-    if (!newSub(c, entry, 1))
-        return false;
-    
-    return true;
-}
-
-static int
-appendType(ParseContext *c, int type)
-{
-    BaseTypeData *iP, *oP;
-    TypeData *tP;
-    int i, sub;
-    int entry, numE, lastEntry;
-    Boolean found;
-
-    if (type >= c->fP.fNumT)
-        return -1;
-
-    tP = &c->fTypeList[type++];
-    entry = tP->fStartEntry;
-    numE  = tP->fNumEntries;
-    lastEntry = entry + numE;
-    iP = NULL;
-    for (i = 0, found = false, sub = -1; i < numE; i++) {
-        iP = &c->fInEntries[entry + i];
-        switch (iP->fType) {
-
-       // Function & Builtin can't be compressed alone
-        case kNTFunction:
-        case kNTBuiltIn:
-            i++;               // Copy the current entry
-            found = true;
-            break;
-
-        case kNTClass:
-        case kNTMethod:
-            sub = searchDict(c, entry + i, numE - i);
-            if (sub < 0 && !iP->fQualified)
-                i++;
-            found = true;
-            break;
-
-        case kNTDeclarator:
-        case kNTArray:
-            sub = searchDict(c, entry + i, numE - i);
-            found = (sub >= 0);
-            break;
-
-        // Internal error's should never occur
-        case kNTKName:
-        case kNTSubstitute:
-        case kNTSubQualClass:
-        case kNTUndefined:
-        default:
-            return -1;
-        }
-        if (found)
-            break;
-    }
-
-    if (!found)
-        return -1;     // Internal error: no terminal symbol?
-
-    // Copy the already input buffer to the output
-    oP = &c->fOutEntries[c->fP.fNumO];
-    if (i) {  
-        if (c->fP.fNumO + i >= MAX_ENTRIES)
-            return -1;
-
-        bcopy(&c->fInEntries[entry], oP, i * sizeof(*oP));
-        c->fP.fNumO += i;
-        oP += i;
-    }
-
-    if (sub >= 0) {
-        // We found a substitution
-        oP->fType = kNTSubstitute;
-        oP->fLen = sub;
-        c->fP.fNumO++;         // Increment output for the substitution
-
-        // Walk over types that have been substituted
-        while (type < c->fP.fNumT 
-           &&  c->fTypeList[type].fStartEntry < lastEntry)
-                type++;
-    }
-    else switch (iP->fType)
-    {
-    case kNTMethod:
-        type = appendType(c, type);    // Class Name
-        if (type < 0)
-            return type;
-        type = appendType(c, type);    // Pointer to function
-        if (type < 0)
-            return type;
-        break;
-
-    case kNTFunction:
-        type = appendType(c, type);    // Return type
-        if (type < 0)
-            return type;
-
-        // process the argument list
-        do {
-            tP = &c->fTypeList[type];
-            if (tP->fStartEntry < lastEntry) {
-                type = appendType(c, type);
-                if (type < 0)
-                    return type;
-            }
-            else
-                break;
-        } while (type < c->fP.fNumT);
-        oP = newOut(c);
-        if (!oP)
-            return -1;
-        oP->fType = kNTFuncEnd;
-        break;
-
-    case kNTBuiltIn:
-        i--;           // Do not store the buildit in the dictionary
-        break;
-
-    case kNTClass:     // Nothing more to do
-        if (!iP->fQualified)
-            break;
-        else if (appendQualifiedClass(c, entry + i))
-            break;
-        else
-            return -1;
-    }
-    
-    // No further substititions to be had update the dictionary
-    for (i += entry; --i >= entry; ) {
-        if (!newSub(c, i, lastEntry - i))
-            return -1;
-    }
-    
-    return type;
-}
-
-static Boolean appendArgumentList(ParseContext *c)
-{
-    int i, num;
-
-    c->fRetCode = kR3InternalNotRemangled;
-    // Setup the output entry array
-    num = c->fP.fNumT;
-    for (i = 0; i < num; ) {
-        i = appendType(c, i);
-        if (i < 0)
-            return false;
-    }
-
-    // First pass output uncompressed types
-    for (i = 0, num = c->fP.fNumO; i < num; i++) {
-        BaseTypeData *bP;
-
-        bP = &c->fOutEntries[i];
-
-        if (bP->fPseudo)
-            continue;  // Pseudo entry do not output;
-
-        switch (bP->fType) {
-
-        case kNTSubstitute: appendSub(c, bP->fLen); break;
-
-        case kNTSubQualClass:
-            appendChar(c, 'N');
-            appendSub(c, bP->fLen);
-            i++; bP = &c->fOutEntries[i];
-            appendNStr(c, bP->fFundTypeID, bP->fLen);
-            appendChar(c, 'E');
-            break;
-
-        case kNTClass:
-            if (bP->fQualified) {
-                appendChar(c, 'N');
-                appendNStr(c, bP->fFundTypeID, bP->fLen);
-                appendChar(c, 'E');
-            }
-            else
-                appendNStr(c, bP->fFundTypeID, bP->fLen);
-            break;
-
-        case kNTArray: {
-            char numbuf[16];   // Bigger than MAX_LONG + 3
-            int len;
-            len = snprintf(numbuf, sizeof(numbuf),
-                           "A%lu_", (unsigned long) bP->fFundTypeID);
-            appendNStr(c, numbuf, len);
-            break;
-        }
-
-        case kNTBuiltIn:
-        case kNTDeclarator:    appendChar(c, (int) bP->fFundTypeID); break;
-        case kNTMethod:                appendChar(c, 'M'); break;
-        case kNTFunction:      appendChar(c, 'F'); break;
-        case kNTFuncEnd:       appendChar(c, 'E'); break;
-
-        case kNTUndefined:
-        case kNTKName:
-        default:
-            return false;      // Fatal errors 
-        }
-    }
-
-    // Successful remangle
-    c->fRetCode = kR3Remangled;
-    return true;
-}
-
-//
-// Parse routines
-//
-
-// <count> ::= <digit> <digit>*
-static Boolean parse_count(ParseContext *c, int *countP)
-{
-    int count = 0;
-    char ch;
-    char *newp;
-
-    ch = peekNext(c);
-    if (ch < '1' || ch > '9')
-        return false;
-
-    count = strtol(c->fP.fInChar, &newp, 10);
-    c->fP.fInChar = newp;
-    if (countP)
-        *countP = count;
-
-    return true;
-}
-
-
-// "n" <index> can cause the following type to be ambiguous as
-// n23_Pc... can be
-//       "n" <digit> <counted_class_name> ...
-//     | "n" <digit> <digit> '_' <declarator> <fund_type_id> ...
-// However as the class '_Pc' is probably going to be unlikely a quick
-// check to see if the next field is a valid type would probably clear
-// up the abiguity for the majority of cases.
-// 
-// <index> ::= <digit> | <digit> <digit> <digit>* "_"
-static Boolean parse_index(ParseContext *c, int *indexP)
-{
-    CheckPoint chk = *checkPoint(c);
-    char ch0, ch1;
-    int index;
-
-    ch0 = peekAt(c, 0);
-    ch1 = peekAt(c, 1);
-
-    if ( !('0' <= ch0 && ch0 <= '9') )
-        goto abandonParse;
-    if ('0' <= ch1 && ch1 <= '9') {
-        if (!parse_count(c, &index))
-            goto abandonParse;
-        if (isNext(c, '_')) {
-            // @@@ gvdl: Ambiguity check one day
-            if (indexP)
-                *indexP = index;
-            return true;
-        }
-        else
-            resetTo(c, &chk);  // Must be the one digit case
-    }
-
-    // One digit case
-    advance(c, 1);
-    index = ch0 - '0';
-
-    if (indexP)
-        *indexP = index;
-    return true;
-
-abandonParse:
-    return false;
-}
-
-
-// <qualifier> ::= "C" ; const
-//               | "V" ; volatile
-//               | "u" ; restrict (C99) unsupported
-//               | "G" ; struct/union/enum ; unused in gcc3
-static Boolean parse_qualifiers(ParseContext *c)
-{
-    BaseTypeData *bP = c->fCurBaseP;
-
-    for (;;) {
-        if (isNext(c, 'C'))
-            bP->fConst = true;         // "C"  ; const
-        else if (isNext(c, 'V'))
-            bP->fVolatile = true;      // "V"  ; volatile
-        else if (isNext(c, 'u'))
-            return false;              // "u"  ; restrict (C99)
-        else if (isNext(c, 'G'))
-            continue;                  // "G"  ; struct/union/enum ; unused
-        else
-            break;
-    }
-
-    return true;
-}
-
-// Assumes we have an open fInEntry in fCurBaseP
-static Boolean duplicateEntries(ParseContext *c, int start, int numE)
-{
-    BaseTypeData *bIP = &c->fInEntries[start]; // First duplicate entry
-    BaseTypeData *bP = c->fCurBaseP;
-    int i;
-
-    // Duplicating a method
-    if (kNTMethod == bIP->fType) {
-        bP--;                  // Strip leading 'P' declarator
-        c->fP.fNumI--;
-    }
-
-    numE--;
-
-    // do we have room available for duplication
-    if (c->fP.fNumI + numE >= MAX_ENTRIES)
-        return false;
-
-    // Copy the parse entries over
-    bcopy(bIP, bP, (numE + 1) * sizeof(*bP));
-
-    // Now we have to duplicate the types for the new entry
-    for (i = 0; i < c->fP.fNumT; i++) {
-        TypeData *tP = &c->fTypeList[i];
-        if (tP->fStartEntry < start)
-            continue;
-        else if (tP->fStartEntry <= start + numE)
-            dupType(c, tP, bP - bIP);
-        else
-            break;
-    } 
-
-    c->fP.fNumI += numE;
-    bP += numE;
-    c->fCurBaseP = bP;
-
-    return true;
-}
-
-// Must have a valid c->fCurBaseP pointer on entry
-// <class_name> ::= <counted_class_name>       ; plain class name
-//                | "Q" <qualified_name>       ; qualified name
-//                | "B" <index>                        ; compressed name
-//                | "K" <qualified_name>       ; ignored and illegal
-// <qualified_name> ::= <q_count> <counted_class_name>+
-// <q_count> ::= <digit> | "_" <digit> <digit>* "_"
-// <counted_class_name> ::= <count> <name>
-// <name> ::= <char> <char>*
-static Boolean
-parse_class_name(ParseContext *c)
-{
-    BaseTypeData *bP = c->fCurBaseP;
-    const char *typeId = c->fP.fInChar;
-    char ch;
-    int count;
-
-    if (parse_count(c, &count)) {
-
-        // <counted_class_name> ::= <count> <name>
-        if (!hasRemain(c, count))
-            goto abandonParse;
-
-        bP->fType = kNTClass;
-        advance(c, count);
-
-        bP->fFundTypeID = typeId;
-        bP->fLen = c->fP.fInChar - typeId;
-    }
-    else {
-        switch (peekNext(c)) {
-
-        case 'Q': {
-            int i, q_count;
-
-            advance(c, 1);
-
-            //                | "Q" <qualified_name>   ; qualified name
-            // <qualified_name> ::= <q_count> <counted_class_name>+
-            // <q_count> ::= <digit> | "_" <digit> <digit>* "_"
-            if ('_' == (ch = getNext(c))) {
-                advance(c, 1);
-                if (!parse_count(c, &q_count) || !isNext(c, '_'))
-                    goto abandonParse;
-            }
-            else if ('1' <= ch && ch <= '9')
-                q_count = ch - '0';
-
-            if (!q_count)
-                goto abandonParse;
-
-            typeId = c->fP.fInChar;
-            bP->fType = kNTClass;
-            bP->fQualified = true;
-            i = 0;
-            for (i = 0; i < q_count; i++) {
-                if (parse_count(c, &count))
-                    advance(c, count);
-                else
-                    goto abandonParse;
-            }
-            bP->fLen = c->fP.fInChar - typeId;
-            bP->fFundTypeID = typeId;
-            break;
-        }
-
-        case 'B':
-            //               | "B" <index>
-            advance(c, 1);
-
-            if (!parse_index(c, &count) || count >= c->fP.fNumB)
-                goto abandonParse;
-
-            if (!duplicateEntries(c, c->fBDict[count].fStartEntry,
-                                     c->fBDict[count].fNumEntries))
-                goto abandonParse;
-            return true;
-
-        case 'K': default:
-            goto abandonParse;
-        }
-    }
-
-    if (newBDict(c, bP - c->fInEntries, 1))
-        return true;
-
-abandonParse:
-    return false;
-}
-
-// <fund_type_id> ::= <class_name>
-//                  | "b"          ; bool
-//                  | "c"          ; char
-//                  | "d"          ; double
-//                  | "e"          ; ellipsis
-//                  | "f"          ; float
-//                  | "i"          ; int
-//                  | "l"          ; long
-//                  | "r"          ; long double
-//                  | "s"          ; short
-//                  | "v"          ; void
-//                  | "w"          ; wchar_t
-//                  | "x"          ; long long
-//                  | "G" <count>  ; ???
-static Boolean parse_fund_type_id(ParseContext *c)
-{
-    BaseTypeData *bP = c->fCurBaseP;
-
-    if (!parse_class_name(c)) {
-        // Use the TypeID pointer as a 4 character buffer
-        char ch = peekNext(c);
-
-        if (bP->fSigned && 'c' != ch)
-            goto abandonParse; // illegal only chars can be signed
-
-        switch (ch) {
-
-        case 'b': case 'd': case 'f': case 'v': case 'w':      // No map types
-            break;
-
-        case 'c':                      // character
-            if (bP->fSigned)           ch = 'a';
-            else if (bP->fUnsigned)    ch = 'h';
-            break;
-        case 'e':                      // ellipsis
-                                        ch = 'z';
-            break;
-        case 'i':                      // int
-            if (bP->fUnsigned)         ch = 'j';
-            break;
-        case 'l':                      // long
-            if (bP->fUnsigned)         ch = 'm';
-            break;
-        case 'r':                      // long double
-                                        ch = 'e';
-            break;
-        case 's':                      // short
-            if (bP->fUnsigned)         ch = 't';
-            break;
-        case 'x':                      // long long
-            if (bP->fUnsigned)         ch = 'y';
-            break;
-
-        case 'G':                      // Don't understand "G"
-        default:
-            goto abandonParse;
-        }
-
-        advance(c, 1); // Consume the input character
-        bP->fFundTypeID = (void *) (int) ch;
-        bP->fLen = 0;
-        bP->fType = kNTBuiltIn;
-    }
-
-    return true;
-
-abandonParse:
-    return false;
-}
-
-// <arg_type> ::= <type>  [ "n" <index> ]
-//            | "N" <count> <pos>      ; Not implemented
-//             | "T" <index>           ; Not implemented
-static Boolean parse_arg_type(ParseContext *c)
-{
-    // Don't bother to check point as parse_argument_types does it for us
-
-    TypeData *typeP;
-    int repeat = 0;
-
-    typeP = &c->fTypeList[c->fP.fNumT];        // Cache type for later repeat
-    if (!parse_type(c))
-        return false;
-
-    // Now check for a repeat count on this type
-    if (isNext(c, 'n')) {
-        if (!parse_index(c, &repeat))
-            return false;
-
-        do {
-            c->fCurBaseP = newIn(c);   // Duplicate requires a fresh type
-            if (!c->fCurBaseP)
-                return false;
-            if (!duplicateEntries(c, typeP->fStartEntry, typeP->fNumEntries))
-                return false;
-        } while (--repeat);
-    }
-
-    return true;
-}
-
-// <argument_types> ::= # Empty
-//                    | <arg_type>+
-static Boolean parse_argument_types(ParseContext *c)
-{
-    if (atEnd(c))
-        return true;
-
-    if (!parse_arg_type(c))
-        goto abandonParse;
-
-    while (!atEnd(c) && parse_arg_type(c))
-        ;
-
-    return true;
-
-    // Not a counted class name so reset to checkPoint
-abandonParse:
-    return false;
-}
-
-// leaf function so the copy aside buffer isn't on the primary
-// recursion stack.
-static Boolean
-rotateFunction(ParseContext *c, int argStart, int retStart)
-{
-    char returnTypeBuffer[MAX_RETURN_BUFFER];
-    unsigned int numArg, numRet;
-    unsigned int lenArg, lenRet;
-    char *sArgP, *sRetP;
-    unsigned int i;
-
-    TypeData *argTP = &c->fTypeList[argStart];
-    TypeData *retTP = &c->fTypeList[retStart];
-
-    // Rotate around the entries first
-    numArg = retTP->fStartEntry - argTP->fStartEntry;
-    numRet = retTP->fNumEntries;
-    lenArg = numArg * sizeof(BaseTypeData);
-    lenRet = numRet * sizeof(BaseTypeData);
-
-    // Copy the return type into a buffer
-    if (lenRet > sizeof(returnTypeBuffer))
-        return false;
-
-    sArgP = (char *) (&c->fInEntries[argTP->fStartEntry]);
-    sRetP = (char *) (&c->fInEntries[retTP->fStartEntry]);
-    
-    bcopy(sRetP, returnTypeBuffer, lenRet);
-    bcopy(sArgP, sArgP + lenRet, lenArg);
-    bcopy(returnTypeBuffer, sArgP, lenRet);
-
-    // Retarget the argument and return types for the new entry positions
-    lenArg = numArg;
-    lenRet = numRet;
-    numArg = retStart - argStart;
-    numRet = c->fP.fNumT - retStart;
-    for (i = 0; i < numArg; i++)
-        c->fTypeList[argStart+i].fStartEntry += lenRet;
-    for (i = 0; i < numRet; i++)
-        c->fTypeList[retStart+i].fStartEntry -= lenArg;
-
-    // Rotate the BDictionary
-    for (i = 0; i < c->fP.fNumB; i++) {
-        TypeData *bDP = &c->fBDict[i];
-        int start = bDP->fStartEntry;
-
-        if (start >= argTP->fStartEntry)
-            bDP->fStartEntry = start + lenRet;
-        else if (start >= retTP->fStartEntry)
-            bDP->fStartEntry = start - lenArg;
-    }
-
-    // Finally rotate the retargeted type structures.
-    lenArg = numArg * sizeof(TypeData);
-    lenRet = numRet * sizeof(TypeData);
-
-    sArgP = (char *) (&c->fTypeList[argStart]);
-    sRetP = (char *) (&c->fTypeList[retStart]);
-
-    bcopy(sRetP, returnTypeBuffer, lenRet);
-    bcopy(sArgP, sArgP + lenRet, lenArg);
-    bcopy(returnTypeBuffer, sArgP, lenRet);
-
-    return true;
-}
-
-// <function_type> ::= "F" <argument_types> "_" <type>
-static Boolean parse_function_type(ParseContext *c, Boolean forMethod)
-{
-    TypeData *bDictP = NULL;
-    BaseTypeData *bP = c->fCurBaseP;
-
-    int argTypeStart, retTypeStart;
-
-    if (!forMethod) {
-        bDictP = newBDict(c, c->fP.fNumI-1, 0);
-        if (!bDictP)
-            goto abandonParse;
-    }
-
-    if (!isNext(c, 'F'))
-        goto abandonParse;
-
-    bP->fType = kNTFunction;
-
-    // Note that the argument types will advance the Entry list
-    argTypeStart = c->fP.fNumT;
-    if (!parse_argument_types(c))
-        goto abandonParse;
-
-    if (!isNext(c, '_'))
-        goto abandonParse;
-
-    // Parse the return type
-    retTypeStart = c->fP.fNumT;
-    if (!parse_type(c))
-        goto abandonParse;
-
-    // gcc3 puts the return code just after the 'F' declaration
-    // as this impacts the order of the compression I need to rotate
-    // the return type and the argument types.
-    if (!rotateFunction(c, argTypeStart, retTypeStart))
-        goto abandonParse;
-
-    if (!forMethod)
-        bDictP->fNumEntries = c->fP.fNumI - bDictP->fStartEntry;
-
-    return true;
-
-abandonParse:
-    return false;
-}
-
-// To convert 2.95 method to a 3.0 method I need to prune the
-// first argument of the function type out of the parse tree.
-static Boolean cleanMethodFunction(ParseContext *c, int type)
-{
-    TypeData *typeP, *startTP, *endTP;            
-    BaseTypeData *bP;
-    int i, thisStart, thisEnd, thisLen, funcRemain;
-
-    // Get pointer for the return value's type.
-    startTP = &c->fTypeList[type+1];
-    endTP = &c->fTypeList[c->fP.fNumT];
-
-    // Now look for the first type that starts after the return type
-    thisEnd = startTP->fStartEntry + startTP->fNumEntries;
-    for (startTP++; startTP < endTP; startTP++)
-        if (startTP->fStartEntry >= thisEnd)
-            break;
-
-    if (startTP >= endTP) {
-        c->fRetCode = kR3InternalNotRemangled;
-        return false;  // Internal error: should never happen
-    }
-
-    // We now have a pointer to the 1st argument in the input list
-    // we will need to excise the entries from the input list and don't forget
-    // to remove the associated types from the type list.
-
-    thisLen = startTP->fNumEntries;
-    thisStart = startTP->fStartEntry;
-    thisEnd = thisStart + thisLen;
-    funcRemain = c->fP.fNumI - thisEnd;
-    bP = &c->fInEntries[thisStart];
-
-    // If we have no arguments then replace the pointer with a void
-    if (!funcRemain) {
-        c->fP.fNumI -= (thisLen - 1);
-
-        bP->fFundTypeID = (void *) (int) 'v';  // Void arg list
-        bP->fLen = 0;
-        bP->fType = kNTBuiltIn;
-
-        // Update the type entry for the void argument list
-        startTP->fNumEntries = 1;
-        return true;
-    }
-
-    // Move the argument list down to replace the 'this' pointer
-    bcopy(bP + thisLen, bP, funcRemain * sizeof(*bP));
-    c->fP.fNumI -= thisLen;
-
-    // And remove the 'this' pointers type
-    
-    // First walk over all of the types that have to be removed
-    for (typeP = startTP + 1; typeP < endTP; typeP++)
-        if (typeP->fStartEntry >= thisEnd)
-            break;
-
-    if (typeP >= endTP) {
-        c->fRetCode = kR3InternalNotRemangled;
-        return false;  // Internal error Can't be a void argument list.
-    }
-
-    bcopy(typeP, startTP, (char *) endTP - (char *) typeP);
-    
-    c->fP.fNumT -= typeP - startTP;
-    endTP = &c->fTypeList[c->fP.fNumT];
-    for (typeP = startTP ; typeP < endTP; typeP++)
-        typeP->fStartEntry -= thisLen;
-
-    // Finally we can retarget the BDictionary lists
-    for (i = 0; i < c->fP.fNumB; i++) {
-        TypeData *bDP = &c->fBDict[i];
-        int start = bDP->fStartEntry;
-
-        if (start < thisStart)
-            continue;
-        if (start >= thisEnd)
-            break;
-
-        bDP->fStartEntry = start - thisLen;
-    }
-
-    return true;
-}
-
-// <method_type> ::= "M" <class_name> <function_type>
-//
-// Note this is a very bad function.  Gcc3 doesn't doesn't use pointer that
-// is immediately before this entry.  We will have to delete the 'P' declarator
-// that is before the method declaration.
-// We will also have to prune the first type in the argument list as Gcc3
-// doesn't register the 'this' pointer within the function list.
-static Boolean parse_method_type(ParseContext *c)
-{
-    TypeData *bDictP;
-    TypeData *typeP;            
-    BaseTypeData *bP;
-
-    bDictP = newBDict(c, c->fP.fNumI-2, 0);
-    if (!bDictP)
-        goto abandonParse;
-
-    // Replace 'P' declarator
-    c->fP.fNumI--;
-    bP = c->fCurBaseP - 1;
-
-    if (!isNext(c, 'M'))
-        goto abandonParse;
-
-    if (bP->fFundTypeID != (void *) (int) 'P')
-        goto abandonParse;
-
-    // Replace the previous 'Pointer' declarator
-    bP->fType = kNTMethod;
-    bP->fFundTypeID = NULL;
-    bP->fLen = 0;
-
-    // Grab the method's 'this' type specification
-    typeP = newType(c, c->fP.fNumI);
-    if (!newIn(c) || !typeP)
-        goto abandonParse;
-
-    if (!parse_class_name(c))
-        goto abandonParse;
-    typeP->fNumEntries = c->fP.fNumI - typeP->fStartEntry;
-
-    // Grab the <function_type> specifier
-    typeP = newType(c, c->fP.fNumI);
-    if (!newIn(c) || !typeP)
-        goto abandonParse;
-
-    if (!parse_function_type(c, /* forMethod */ true))
-        goto abandonParse;
-
-    if (!cleanMethodFunction(c, typeP - c->fTypeList))
-        goto abandonParse;
-    typeP->fNumEntries = c->fP.fNumI - typeP->fStartEntry;
-
-    // Finally update the dictionary with the M & 'this'
-    bDictP->fNumEntries = c->fP.fNumI - bDictP->fStartEntry;
-
-    return true;
-
-abandonParse:
-    return false;
-}
-
-static Boolean emitQualifiers(ParseContext *c)
-{
-    BaseTypeData *bP = c->fCurBaseP;
-
-    if (bP->fVolatile || bP->fConst) {
-        Boolean isConst, isVolatile, isSigned, isUnsigned;
-    
-        isVolatile = bP->fVolatile;
-        isConst = bP->fConst;
-        isSigned = bP->fSigned;
-        isUnsigned = bP->fUnsigned;
-        bP->fConst = bP->fVolatile = bP->fSigned = bP->fUnsigned = 0;
-    
-        if (isVolatile) {
-            bP->fType = kNTDeclarator;
-            bP->fFundTypeID = (void *) (int) 'V';
-            bP->fLen = 0;
-            bP = newIn(c);
-            if (!bP)
-                return false;
-        }
-        if (isConst) {
-            bP->fType = kNTDeclarator;
-            bP->fFundTypeID = (void *) (int) 'K';
-            bP->fLen = 0;
-            bP = newIn(c);
-            if (!bP)
-                return false;
-        }
-        bP->fSigned = isSigned;
-        bP->fUnsigned = isUnsigned;
-    }
-
-    return true;
-}
-
-
-// <base_type> ::= <function_type>     ; function
-//               | <method_type>       ; method
-//               | <type_qualifier>* <fund_type_id>
-// <type_qualifier> ::= "S"        ; signed (chars only)
-//                    | "U"        ; unsigned (any integral type)
-//                    | "J"        ; __complex
-//                    | <qualifier>
-static Boolean parse_base_type(ParseContext *c)
-{
-    if ('F' == peekNext(c)) {
-        if (!parse_function_type(c, /* forMethod */ false))
-            goto abandonParse;
-    }
-    else if ('M' == peekNext(c)) {
-        if (!parse_method_type(c))
-            goto abandonParse;
-    }
-    else {
-        //               | <type_qualifier>* <fund_type_id>
-        BaseTypeData *bP = c->fCurBaseP;
-        for (;;) {
-            if (isNext(c, 'S'))
-                // <type_qualifier> ::= "S"    ; signed (chars only)
-                { bP->fSigned = true; continue; }
-            else if (isNext(c, 'U'))
-                //                    | "U"    ; unsigned (any integral type)
-                { bP->fUnsigned = true; continue; }
-            else if (isNext(c, 'C'))
-                //                    | <qualifier>
-                // <qualifier> ::= "C"         ; const
-                { bP->fConst = true; continue; }
-            else if (isNext(c, 'V'))
-                //               | "V"         ; volatile
-                { bP->fVolatile = true; continue; }
-            else if (charNext(c, "Ju"))
-                goto abandonParse;     // Don't support these qualifiers
-                //                    | "J"    ; __complex
-                //               | "u"         ; restrict (C99)
-            else
-                break;
-        }
-
-        if (!emitQualifiers(c))
-            goto abandonParse;
-
-        if (!parse_fund_type_id(c))
-            goto abandonParse;
-    }
-    return true;
-
-abandonParse:
-    return false;
-}
-
-// Use the top SDict as a stack of declarators.
-// parses <declarator>*
-// <declarator> ::= "P"            ; pointer
-//                | "p"            ; pointer (but never occurs?)
-//                | "R"            ; reference (&)
-//                | "A" <count>    ; array
-//                | "T" <index>
-//                | "O" <count>
-//                | <qualifier>
-//
-// As a side-effect the fCurBaseP is setup with any qualifiers on exit
-static Boolean parse_declarators(ParseContext *c)
-{
-    int count;
-    unsigned long l;
-    BaseTypeData *dP;
-    char *newp;
-
-    // Note we MUST go through the for loop at least once
-    for (count = 0; ; count++) {
-        const char *curDecl;
-        char ch;
-
-        if (!newIn(c))
-            goto abandonParse;
-
-        // <declarator> ::= <qualifier> production
-        if (!parse_qualifiers(c) || !emitQualifiers(c))
-            goto abandonParse;
-
-        dP = c->fCurBaseP;     // Find the current base type pointer
-
-        curDecl = c->fP.fInChar;
-
-        switch (peekNext(c)) {
-
-        case 'P': case 'p': case 'R':
-            // <declarator> ::= "P"            ; pointer
-            //                | "p"            ; pointer (but never occurs?)
-            //                | "R"            ; reference (&)
-
-            dP->fType = kNTDeclarator;
-            advance(c, 1);
-
-            ch = *curDecl;
-            if ('p' == ch) ch = 'P';
-            dP->fFundTypeID = (void *) (int) ch;
-            dP->fLen = 0;
-            continue;  // Go around again
-
-        case 'A':
-            //                | "A" <count>    ; array
-            dP->fType = kNTArray;
-
-            advance(c, 1); curDecl++;
-            l = strtoul(curDecl, &newp, 10);
-            c->fP.fInChar = newp;
-            curDecl = (const char *)l;
-            if (!curDecl)
-                goto abandonParse;
-            dP->fFundTypeID = curDecl;
-            dP->fLen = 0;
-            continue;  // Go around again
-
-        case 'T': case 'O':
-            //                | "T" <index>    Unsupported
-            //                | "O" <count>    Unsupported
-            goto abandonParse;
-
-        default:
-            break;
-        }
-
-        break;
-    }
-
-    dP->fLen = 0;
-    return true;
-
-abandonParse:
-    return false;
-}
-
-// <type> ::= <declarator>* <base_type>
-static Boolean parse_type(ParseContext *c)
-{
-    CheckPoint chk = *checkPoint(c);
-    TypeData *typeP = newType(c, c->fP.fNumI);
-    if (!typeP)
-        goto abandonParse;
-
-    // As a side-effect the fCurBaseP is setup with any qualifiers on exit
-    if (!parse_declarators(c))
-        goto abandonParse;
-
-    // Merge the last qualifiers into the base type
-    if (!parse_base_type(c) || kNTUndefined == c->fCurBaseP->fType)
-        goto abandonParse;
-
-    typeP->fNumEntries = c->fP.fNumI - typeP->fStartEntry;
-    return true;
-
-abandonParse:
-    resetTo(c, &chk);
-    return false;
-}
-
-// <function_name> ::= <char> <char>*
-// No need to check point as an invalid function name is fatal
-// Consumes trailing "__".
-static Boolean
-parse_function_name(ParseContext *c)
-{
-    char ch;
-
-    while ( (ch = peekNext(c)) )
-    {
-        advance(c, 1);
-        if ('_' == ch && '_' == peekNext(c)) {
-            do {
-                advance(c, 1);
-            } while ('_' == peekNext(c));
-            return true;
-        }
-    }
-
-    return false;
-}
-
-// <opinfo> ::= "type" <type>
-//            | "__op" <type>
-//            | <opname> "__"  ; Implies null function name
-//            | "a"
-// <opname> ::= "aa"   # &&    ==> "aa"
-//            | "aad"  # &=    ==> "aN"
-//            | "ad"   # &     ==> "ad"
-//            | "adv"  # /=    ==> "dV"
-//            | "aer"  # ^=    ==> "eO"
-//            | "als"  # <<=   ==> "lS"
-//            | "amd"  # %=    ==> "rM"
-//            | "ami"  # -=    ==> "mI"
-//            | "aml"  # *=    ==> "mL
-//            | "aor"  # |=    ==> "oR
-//            | "apl"  # +=    ==> "pL
-//            | "ars"  # >>=   ==> "rS
-//            | "as"   # =     ==> "aS
-//            | "cl"   # ()    ==> "cl
-//            | "cm"   # ,     ==> "cm
-//            | "cn"   # ?:    ==> "qu
-//            | "co"   # ~     ==> "co
-//            | "dl"   # delete ==> "dl
-//            | "dv"   # /     ==> "dv
-//            | "eq"   # ==    ==> "eq
-//            | "er"   # ^     ==> "eo
-//            | "ge"   # >=    ==> "ge
-//            | "gt"   # >     ==> "gt
-//            | "le"   # <=    ==> "le
-//            | "ls"   # <<    ==> "ls
-//            | "lt"   # <     ==> "lt
-//            | "md"   # %     ==> "rm
-//            | "mi"   # -     ==> "mi
-//            | "ml"   # *     ==> "ml
-//            | "mm"   # --    ==> "mm
-//            | "mn"   # <?    ==> "????????????????
-//            | "mx"   # >?    ==> "????????????????
-//            | "ne"   # !=    ==> "ne
-//            | "nt"   # !     ==> "nt
-//            | "nw"   # new   ==> "nw
-//            | "oo"   # ||    ==> "oo"
-//            | "or"   # |     ==> "or
-//            | "pl"   # +     ==> "pl
-//            | "pp"   # ++    ==> "pp
-//            | "rf"   # ->    ==> "pt
-//            | "rm"   # ->*   ==> "pm
-//            | "rs"   # >>    ==> "rs
-//            | "sz"   # sizeof ==> "sz
-//            | "vc"   # []    ==> "ix
-//            | "vd"   # delete[] ==> "da
-//            | "vn"   # new[] ==> "na
-static struct opMap { 
-    const char *op295, *op3;
-} opMapTable[] = {  
-    {"aad", "aN" }, {"adv", "dV" }, {"aer", "eO" }, {"als", "lS" },
-    {"amd", "rM" }, {"ami", "mI" }, {"aml", "mL" }, {"aor", "oR" },
-    {"apl", "pL" }, {"ars", "rS" }, {"aa",  "aa" }, {"ad",  "ad" },
-    {"as",  "aS" }, {"cl",  "cl" }, {"cm",  "cm" }, {"cn",  "qu" },
-    {"co",  "co" }, {"dl",  "dl" }, {"dv",  "dv" }, {"eq",  "eq" },
-    {"er",  "eo" }, {"ge",  "ge" }, {"gt",  "gt" }, {"le",  "le" },
-    {"ls",  "ls" }, {"lt",  "lt" }, {"md",  "rm" }, {"mi",  "mi" },
-    {"ml",  "ml" }, {"mm",  "mm" }, {"mn",  NULL }, {"mx",  NULL },
-    {"ne",  "ne" }, {"nt",  "nt" }, {"nw",  "nw" }, {"oo",  "oo" },
-    {"or",  "or" }, {"pl",  "pl" }, {"pp",  "pp" }, {"rf",  "pt" },
-    {"rm",  "pm" }, {"rs",  "rs" }, {"sz",  "sz" }, {"vc",  "ix" },
-    {"vd",  "da" }, {"vn",  "na" },
-};
-
-static Boolean parse_opinfo(ParseContext *c, const char **opInfoP)
-{
-    CheckPoint chk = *checkPoint(c);
-    const char *op;
-    char ch;
-    unsigned int i;
-
-    if ('a' == (ch = peekNext(c))) {
-        goto abandonParse;
-    }
-    else if (strNext(c, "type")) {
-        goto abandonParse;
-    }
-    else if (retard(c, 4) && strNext(c, "____op")) {
-        // @@@ gvdl: check this out it may change
-        // <opinfo> ::= "__op" <type>
-        goto abandonParse;
-    }
-
-    // Failed till now so reset and see if we have an operator
-    resetTo(c, &chk);
-
-    // quick check to see if we may have an operator
-    if (!strrchr("acdeglmnoprsv", peekNext(c)))
-        goto abandonParse;
-
-    op = NULL;
-    for (i = 0; i < sizeof(opMapTable)/sizeof(opMapTable[0]); i++) {
-        if (strNext(c, opMapTable[i].op295)) {
-            op = opMapTable[i].op3;
-            break;
-        }
-    }
-    if (!op)
-        goto abandonParse;
-
-    if (!strNext(c, "__"))             // Trailing underbars
-        goto abandonParse;
-
-    if (opInfoP)
-        *opInfoP = op;
-    return true;
-
-abandonParse:
-    return false;
-}
-
-// <signature> ::= <qualifier>* <s_element> <argument_types>
-// <s_element> ::= <class_name>
-//               | "K" <qualified_name>
-//               | "S"
-//               | "F" <argument_types> [ "_" <return_type> ] 
-// <return_type> ::= <type>
-// Treat the prefix's s_element as a full type
-static Boolean
-parse_signature(ParseContext *c,
-                const char *func, int funcLen, const char *op)
-{
-    BaseTypeData *bP;
-    TypeData *tP;
-
-    Boolean isFunction = false;
-
-    if (isNext(c, 'F')) {
-        //               | "F" <argument_types> [ "_" <return_type> ] 
-
-        char numbuf[16];       // Bigger than MAX_INT + 4
-        int len;
-        isFunction = true;
-        if (!funcLen)
-            goto abandonParse;
-
-        len = snprintf(numbuf, sizeof(numbuf), "__Z%d", funcLen);
-
-        appendNStr(c, numbuf, len);
-        appendNStr(c, func, funcLen);
-    }
-    else if (isNext(c, 'S')) {
-        //         | "S"       ; Ignored
-        goto abandonParse;
-    }
-    else {
-        const char *qual;
-        int qualLen;
-
-        // See if we can find a qualified class reference
-        tP = newType(c, c->fP.fNumI);
-        if (!tP)
-            goto abandonParse;
-    
-        bP = newIn(c);
-        if (!bP)
-            goto abandonParse;
-    
-        // Parse any qualifiers, store results in *fCurBaseP
-        bP->fPseudo = true;
-        if (!parse_qualifiers(c))
-            goto abandonParse;
-    
-        if (!parse_class_name(c))
-            goto abandonParse;
-
-        bP = c->fCurBaseP;     // class name may have redifined current
-        tP->fNumEntries = c->fP.fNumI - tP->fStartEntry;
-
-        APPENDSTR(c, "__ZN");
-        decodeQual(bP, &qualLen, &qual);
-        if (qualLen)
-            appendNStr(c, qual, qualLen);
-        appendNStr(c, bP->fFundTypeID, bP->fLen);
-
-        if (funcLen) {
-            char numbuf[16];   // Bigger than MAX_INT + 1
-            int len;
-
-            len = snprintf(numbuf, sizeof(numbuf), "%d", funcLen);
-            appendNStr(c, numbuf, len);
-            appendNStr(c, func, funcLen);
-        }
-        else if (op)
-            appendStr(c, op);
-        else {
-            // No function & no op means constructor choose one of C1 & C2
-            APPENDSTR(c, "C2");
-        }
-        appendChar(c, 'E');
-    }
-
-    if (atEnd(c)) {
-        appendChar(c, 'v');    // void argument list
-        c->fRetCode = kR3Remangled;
-        return true;
-    }
-
-    c->fCurBaseP = NULL;
-    if (!parse_argument_types(c))
-        goto abandonParse;
-
-    if (isFunction) {
-        if (isNext(c, '_')) {
-            // && !parse_type(c)       @@@ gvdl: Unsupported return
-            c->fRetCode = kR3InternalNotRemangled;
-            goto abandonParse;
-        }
-    }
-
-    if (!atEnd(c))
-        goto abandonParse;
-
-    // OK we have a complete and successful parse now output the
-    // argument list
-    return appendArgumentList(c);
-
-abandonParse:
-    return false;
-}
-
-// <mangled_name> ::= <prefix> [ <signature> ]
-// <prefix> ::= [ "_GLOBAL_" [ID] "__" ] <function_name> "__" [ <opinfo> ]
-static Boolean parse_mangled_name(ParseContext *c)
-{
-    CheckPoint chk;
-    CheckPoint dubBarChk;
-    const char *func;
-
-    // <prefix> parse
-    if (strNext(c, "_GLOBAL_")) {      // Is this GLOBAL static constructor?
-        // gvdl: can't deal with _GLOBAL_
-        c->fRetCode = kR3InternalNotRemangled;
-        return false;  // Can't deal with these
-    }
-
-    func = c->fP.fInChar;
-    for (chk = *checkPoint(c); ; resetTo(c, &dubBarChk)) {
-        int funcLen;
-        const char *op = NULL;
-
-        if (!parse_function_name(c))
-            goto abandonParse;
-        dubBarChk = *checkPoint(c);
-
-        // Note that the opInfo may be earlier than the curDoubleBar
-        // in which case the function name may need to be shrunk later on.
-        (void) parse_opinfo(c, &op);
-
-        if (atEnd(c))
-            goto abandonParse; // No Signature?
-
-        funcLen = inCharFromCheck(&dubBarChk) - func - 2;
-        if (parse_signature(c, func, funcLen, op))
-            return true;
-
-        if (kR3NotRemangled != c->fRetCode)
-            goto abandonParse;
-
-        // If no error then try again maybe another '__' exists
-    }
-
-abandonParse:
-    resetTo(c, &chk);
-    return false;
-}
-
-// <gnu_special> ::= ("_._" | "_$_" ) <class_name>     ; destructor
-//                 | "__vt_" <class_name>              ; virtual table
-//                 | "_" <class_name> ("."|"$") <varname>
-static Boolean parse_gnu_special(ParseContext *c)
-{
-    CheckPoint chk = *checkPoint(c);
-    BaseTypeData *bP = newIn(c);
-
-    if (!bP)
-        return false;
-
-    // What do the intel desctructors look like
-    if (strNext(c, "_._") || strNext(c, "_$_") )       // Is this a destructor
-    {
-        if (!parse_class_name(c) || !atEnd(c))
-            goto abandonParse;
-        APPENDSTR(c, "__ZN");
-        appendNStr(c, bP->fFundTypeID, bP->fLen);
-        APPENDSTR(c, "D2Ev");
-        c->fRetCode = kR3Remangled;
-        return true;
-    }
-    else if (strNext(c, "__vt_"))      // Is it's a vtable?
-    {
-        if (!parse_class_name(c) || !atEnd(c))
-            goto abandonParse;
-
-        APPENDSTR(c, "__ZTV");
-        if (kNTClass != bP->fType)
-            goto abandonParse;
-        else if (bP->fQualified) {
-            appendChar(c, 'N');
-            appendNStr(c, bP->fFundTypeID, bP->fLen);
-            appendChar(c, 'E');
-        }
-        else
-            appendNStr(c, bP->fFundTypeID, bP->fLen);
-
-        c->fRetCode = kR3Remangled;
-        return true;
-    }
-    else if (isNext(c, '_'))           // Maybe it's a variable
-    {
-        const char *varname;
-        int varlen, len;
-        char numbuf[16];       // Bigger than MAX_INT + 1
-
-        if (!parse_class_name(c))      // Loads up the bP structure
-            goto abandonParse;
-
-        if (!isNext(c, '.') && !isNext(c, '$'))
-            goto abandonParse;
-
-        // Parse the variable name now.
-        varname = c->fP.fInChar;
-        if (atEnd(c) || !isValidFirstChar(getNext(c)))
-            goto abandonParse;
-
-        while ( !atEnd(c) )
-            if (!isValidChar(getNext(c)))
-                goto abandonParse;
-
-        varlen = c->fP.fInChar - varname;
-        len = snprintf(numbuf, sizeof(numbuf), "%d", varlen);
-
-        APPENDSTR(c, "__ZN");
-        appendNStr(c, bP->fFundTypeID, bP->fLen);
-
-        appendNStr(c, numbuf, len);
-        appendNStr(c, varname, varlen);
-        appendChar(c, 'E');
-
-        c->fRetCode = kR3Remangled;
-        return true;
-    }
-
-    // Oh well it is none of those so give up but reset scan
-abandonParse:
-    resetTo(c, &chk);
-    return false;
-}
-
-// <special_or_name> ::= <gnu_special>
-//                     | <mangled_name>
-static Boolean parse_special_or_name(ParseContext *c)
-{
-    Boolean res;
-
-    
-    res = (parse_gnu_special(c) || parse_mangled_name(c));
-    appendChar(c, '\0');
-
-    return res;
-}
-
-Rem3Return rem3_remangle_name(char *gcc3, int *gcc3size, const char *gcc295)
-{
-    ParseContext *c;
-    Rem3Return result;
-    int size;
-
-    if (!gcc295 || !gcc3 || !gcc3size)
-        return kR3BadArgument;
-
-    size = strlen(gcc295);
-    if (size < 2)
-        return kR3NotRemangled;        // Not a valid C++ symbol
-    else if (*gcc295 != '_')
-        return kR3NotRemangled;        // no leading '_', not valid
-
-    c = (ParseContext *) malloc(sizeof(*c));
-    if (!c)
-        return kR3InternalNotRemangled;
-    bzero(c, sizeof(*c));
-
-    c->fInSize = size;
-    c->fInStr = gcc295 + 1;    // Strip leading '_'
-    c->fP.fInChar = c->fInStr;
-
-    c->fOutStrEnd = gcc3 + *gcc3size;
-    c->fOutChar = gcc3;
-
-    c->fRetCode = kR3NotRemangled;
-    (void) parse_special_or_name(c);
-
-    result = c->fRetCode;
-    if (kR3Remangled == result) {
-        if (c->fOutChar > c->fOutStrEnd)
-            result = kR3BufferTooSmallRemangled;
-        *gcc3size = c->fOutChar - gcc3 - 1;    // Remove nul from len
-    }
-
-    free(c);
-
-    return result;
-}