1 // 45678901234567890123456789012345678901234567890123456789012345678901234567890
5 Stan Shebs of Apple Computer, Inc 2002
7 Parse and remangle implemented by
8 Godfrey van der Linden of Apple Computer, Inc 2002
10 Rules for demangling IOKit symbols
12 In Darwin versions 1.0 through at least 5.2, IOKit is compiled using
13 GCC version 2. GCC 2's C++ symbol mangling algorithm ultimately
14 derives from the basic scheme described in the Annotated C++ Reference
15 Manual (ARM), section 7.2.1c, with a number of changes, mostly due to
16 the expansion of the language since the ARM was published in 1990.
18 This description is not complete. It omits RTTI, thunks, and
19 templates, since they are not allowed in IOKit. The description also
20 mentions mangled name constructs that are not disallowed in IOKit, but
21 that as of Jan 2002, did actually appear in any symbol in the base
24 A mangled name basically consists of a function name followed
25 by two underscores, optionally followed by a signature computed
26 from the function's argument types. (Note that in Darwin, the
27 compiler adds an additional underscore to all C and C++ symbols.
28 The description assumes this has been removed.)
30 <special_or_name> ::= <gnu_special>
33 <mangled_name> ::= <prefix> [ <signature> ]
35 <prefix> ::= [ "_GLOBAL_" [ID] "__" ] <function_name> "__" [ <opinfo> ]
37 <function_name> ::= <char> <char>*
40 Questions for Stan (@@@Stan@@@)
41 1> A valid <opinfo> implies a null function name.
42 2> I wonder if an <opinfo> is mutually exclusive with a <function_name> perhaps something like :-
43 <prefix> ::= [ "_GLOBAL_" ("I"|"D") "__" ] ((<function_name> "__") | <opinfo>)
44 3> Do constructors turn up as an opinfo or a NULL function name?
46 The optional "_GLOBAL_"("I"|"D")"__" sequence indicates global constructors
47 and destructors, but in practice these do not appear with the mach-o Apple 2.95
49 A Null <function_name> indicates a constructor or an operator.
51 Since <function_name> may include trailing underscores, the demangler
52 should scan forward until a non-underscore is seen, and then take the
53 last two as the separator between name and signature.
55 <function_name> may also include any number of leading underscores, so
56 the demangler needs to add those to <function_name> and look for the
57 "__" following the name.
59 <gnu_special> ::= ("_._"|"_$_" ) <class_name> ; destructor
60 | "__vt_" <class_name> ; virtual table
61 | "_" <class_name> ("."|"$") <varname> ; Variable
63 <class_name> ::= <counted_class_name>
64 | "Q" <qualified_name>
65 | "K" <qualified_name> ; ignored and illegal
67 <counted_class_name> ::= <count> <name>
69 <qualified_name> ::= <q_count> <counted_class_name> <counted_class_name>*
71 <opinfo> ::= "type" <type>
76 <opname> ::= "aa" # &&
123 Questions for Stan (@@@Stan@@@)
124 1> What the hell is The "type" & "__op" stuff?
126 IOKit has so far only been observed to use operations new ("nw") and
129 The signature is a concatenated list of elements, which are usually
130 argument types, but may include other sorts of things.
132 <signature> ::= <qualifier>* <s_element> <argument_types>
134 <s_element> ::= <class_name>
136 | "F" <argument_types> [ "_" <return_type> ]
138 Questions for Stan (@@@Stan@@@)
139 1> I think the 'B' phrase should probably read '| "B" <index>'?
140 2> Ambiguous productions for signature
141 OSObject::func(struct timeval fred) => _func__8OSObject7timeval
142 signature could be parsed as
143 <s_element> <s_element> or <s_element> <argument_types>
144 I believe the second one must be the valid production.
146 <count> ::= <digit> <digit>*
150 <name> ::= <char> <char>*
152 The <count> is the number of characters in <name>.
154 Argument types are a concatenated sequence of types.
156 <argument_types> ::= # Empty
158 <arg_type> ::= <type> [ "n" <index> ]
162 The "N" repeats and "T" references to already-seen typescan only
163 appear if -fno-squangle (no squashed mangling), and in practice aren't
164 seen in IOKit symbols.
166 <index> ::= <digit> | <digit> <digit> <digit>* "_"
168 Return types are just like any other sort of type.
170 <return_type> ::= <type>
172 Types consist of a variable number of declarators in front of a basic
175 <type> ::= <declarator>* <base_type>
177 <declarator> ::= "P" ; pointer
178 | "p" ; pointer (but never occurs?)
179 | "R" ; reference (&)
180 | "A" <count> ; array
185 The "A" <count> production can produce an ambigous output if it is followed by a counted class name or structure name.
187 The "T" reference to a type does not appear in IOKit symbols, nor do
188 the "M" and "O" declarators.
190 <base_type> ::= <function_type> ; function
191 | <method_type> ; method
192 | <type_qualifier>* <fund_type_id>
194 <function_type> ::= "F" <argument_types> "_" <type>
196 <method_type> ::= "M" <class_name> <function_type>
198 A qualified name consists of a count of types, followed by all the
199 types concatenated together. For instance, Namespace::Class is
200 Q29Namespace5Class. For more than 9 types (which has not yet occurred
201 in IOKit), the multi-digit count is surrounded by underscores.
203 Questions for Stan (@@@Stan@@@)
204 1> Can the types in a qualified name really be generic types or can the set be restricted to just counted class names?
206 <q_count> ::= <digit> | "_" <digit> <digit>* "_"
208 Fundamental types are single letters representing standard built-in
209 types, optionally preceded by type qualifiers for properties like
210 signedness and constness. For instance, CUi is a const unsigned int.
212 <type_qualifier> ::= "S" ; signed (chars only)
213 | "U" ; unsigned (any integral type)
217 <fund_type_id> ::= <class_name>
229 | "G" <count> ; ?????
232 "G" does not appear in IOKit symbols in this context.
234 <qualifier> ::= "C" ; const
236 | "u" ; restrict (C99)
237 | "G" ; struct/union/enum unused by gcc3
239 The restrict qualifier has not appeared in IOKit symbols.
247 #include <sys/systm.h>
249 #include <libkern/OSTypes.h>
251 #include <libsa/stdlib.h>
253 enum { false = 0, true = 1 };
263 #include <CoreFoundation/CoreFoundation.h>
269 #define STRLEN(s) (sizeof(s)-1)
270 #define APPENDSTR(c, str) do { appendNStr(c, str, STRLEN(str)); } while (0)
272 #define MAX_COMPOUND_TYPES 128
273 #define MAX_ENTRIES 256
274 #define MAX_SDICT_ENTRIES 256
275 #define MAX_BDICT_ENTRIES 64
276 #define MAX_RETURN_BUFFER 256
278 // Can't be bigger that 16 entries
279 typedef enum NameTypes
{
280 kNTUndefined
, kNTClass
, kNTFunction
, kNTFuncEnd
,
281 kNTMethod
, kNTBuiltIn
, kNTDeclarator
, kNTArray
,
282 kNTKName
, kNTSubstitute
, kNTSubQualClass
285 typedef struct TypeData
{
286 short fStartEntry
, fNumEntries
;
289 typedef struct BaseTypeData
{
290 const char *fFundTypeID
; // May contain the type itself for kNTBuiltIt
291 unsigned int fLen
:16;
292 unsigned int fType
:4; // Must fit a NameType
293 unsigned int fVolatile
:1;
294 unsigned int fConst
:1;
295 unsigned int fSigned
:1;
296 unsigned int fUnsigned
:1;
297 unsigned int fPseudo
:1;
298 unsigned int fQualified
:1;
301 typedef struct CheckPoint
{
303 unsigned char fNumI
, fNumO
, fNumT
, fNumB
, fNumS
;
306 typedef struct ParseContext
{
308 BaseTypeData fInEntries
[MAX_ENTRIES
]; // Input parsed elements
309 BaseTypeData fOutEntries
[MAX_ENTRIES
]; // Output parsed elements
310 TypeData fTypeList
[MAX_COMPOUND_TYPES
]; // Table of types
311 TypeData fSubDict
[MAX_SDICT_ENTRIES
];
312 TypeData fBDict
[MAX_BDICT_ENTRIES
]; // B dictionary types
313 BaseTypeData
*fCurBaseP
;
322 // The only forward declaration necessary
324 static Boolean
parse_type(ParseContext
*c
);
326 // Helper functions for walking through the string
327 static __inline__
char getNext(ParseContext
*c
)
329 return *c
->fP
.fInChar
++;
332 static __inline__ CheckPoint
*checkPoint(ParseContext
*c
)
337 static __inline__
void resetTo(ParseContext
*c
, CheckPoint
*chk
)
342 static __inline__
const char *inCharFromCheck(CheckPoint
*chk
)
347 static __inline__
void advance(ParseContext
*c
, int len
)
349 c
->fP
.fInChar
+= len
;
352 static __inline__ Boolean
retard(ParseContext
*c
, int len
)
354 const char *cp
= c
->fP
.fInChar
- len
;
362 static __inline__
char peekAt(ParseContext
*c
, int index
)
364 return c
->fP
.fInChar
[index
];
367 static __inline__
char peekNext(ParseContext
*c
)
372 static __inline__ Boolean
atEnd(ParseContext
*c
)
374 return '\0' == peekNext(c
);
377 static __inline__ Boolean
hasRemain(ParseContext
*c
, int len
)
379 return (c
->fP
.fInChar
- c
->fInStr
+ len
<= c
->fInSize
);
383 // Routines for allocating entries in the various
385 static __inline__ BaseTypeData
*newIn(ParseContext
*c
)
389 if (c
->fP
.fNumI
< MAX_ENTRIES
) {
390 iP
= &c
->fInEntries
[c
->fP
.fNumI
++];
391 bzero(iP
, sizeof(*iP
));
396 c
->fRetCode
= kR3InternalNotRemangled
;
401 static __inline__ BaseTypeData
*newOut(ParseContext
*c
)
405 if (c
->fP
.fNumO
< MAX_ENTRIES
) {
406 oP
= &c
->fOutEntries
[c
->fP
.fNumO
++];
410 c
->fRetCode
= kR3InternalNotRemangled
;
415 static __inline__ TypeData
*
416 newSub(ParseContext
*c
, int start
, int num
)
420 if (c
->fP
.fNumS
< MAX_SDICT_ENTRIES
) {
421 sP
= &c
->fSubDict
[c
->fP
.fNumS
++];
422 sP
->fStartEntry
= start
;
423 sP
->fNumEntries
= num
;
427 c
->fRetCode
= kR3InternalNotRemangled
;
432 static __inline__ TypeData
*
433 newBDict(ParseContext
*c
, int start
, int num
)
437 if (c
->fP
.fNumB
< MAX_BDICT_ENTRIES
) {
438 bP
= &c
->fBDict
[c
->fP
.fNumB
++];
439 bP
->fStartEntry
= start
;
440 bP
->fNumEntries
= num
;
444 c
->fRetCode
= kR3InternalNotRemangled
;
449 static __inline__ TypeData
*
450 newType(ParseContext
*c
, int start
)
454 if (c
->fP
.fNumT
< MAX_COMPOUND_TYPES
) {
455 tP
= &c
->fTypeList
[c
->fP
.fNumT
++];
456 tP
->fStartEntry
= start
;
463 static __inline__ TypeData
*
464 dupType(ParseContext
*c
, TypeData
*iTP
, int offset
)
466 TypeData
*tP
= newType(c
, iTP
->fStartEntry
+ offset
);
468 tP
->fNumEntries
= iTP
->fNumEntries
;
474 // Identifier character recognition helpers, can be optimised
476 static __inline__ Boolean
isValidFirstAlphabetic(char c
)
478 if ('a' <= c
&& c
<= 'z')
480 else if ('A' <= c
&& c
<= 'Z')
486 static __inline__ Boolean
isValidFirstChar(char c
)
488 if (isValidFirstAlphabetic(c
))
496 static __inline__ Boolean
isValidChar(char c
)
498 if (isValidFirstChar(c
))
500 else if ('0' <= c
&& c
<= '9')
507 // Helper function for recognising characters and strings
510 // Check the current input is the given character
511 static __inline__ Boolean
isNext(ParseContext
*c
, char ch
)
513 if (peekNext(c
) == ch
) {
521 // Check the current input is ONE of the characters in str
522 static Boolean
charNext(ParseContext
*c
, const char *str
)
524 if (hasRemain(c
, 1)) {
525 char ch
= peekNext(c
);
528 while ( (next
= *str
++) )
538 // Check the current input for 'str'
539 static Boolean
strNext(ParseContext
*c
, const char *str
)
541 const char *cp
= c
->fP
.fInChar
;
545 c
->fP
.fInChar
= (const char *) cp
;
551 } while (*cp
++ == *str
++);
557 // Qualifier re-encoding
560 decodeQual(BaseTypeData
*typeP
, int *qualLenP
, const char **qualP
)
565 if (typeP
->fConst
&& typeP
->fVolatile
)
566 { qual
= "VK"; qualLen
= 2; }
567 else if (typeP
->fConst
)
568 { qual
= "K"; qualLen
= 1; }
569 else if (typeP
->fVolatile
)
570 { qual
= "V"; qualLen
= 1; }
572 { qual
= NULL
; qualLen
= 0; }
583 static void appendChar(ParseContext
*c
, char ch
)
585 char *outAddr
= c
->fOutChar
++;
586 if (outAddr
< c
->fOutStrEnd
)
590 static void appendNStr(ParseContext
*c
, const char *str
, int len
)
592 char *outAddr
= c
->fOutChar
;
595 if (c
->fOutChar
< c
->fOutStrEnd
)
596 bcopy(str
, outAddr
, len
);
599 static __inline__
void appendStr(ParseContext
*c
, const char *str
)
601 appendNStr(c
, str
, strlen(str
));
604 static void appendSub(ParseContext
*c
, int ls
)
612 appendChar(c
, (ms
< 10)? '0' + ms
: 'A' + ms
- 10);
615 appendChar(c
, (ls
< 10)? '0' + ls
: 'A' + ls
- 10);
620 static Boolean
compareTypes(ParseContext
*c
, int sub
, int entry
, int numEntries
)
622 TypeData
*subP
= &c
->fSubDict
[sub
];
623 BaseTypeData
*bSP
, *bIP
;
626 if (subP
->fNumEntries
!= numEntries
)
629 bSP
= &c
->fInEntries
[subP
->fStartEntry
];
630 bIP
= &c
->fInEntries
[entry
];
632 for (i
= 0; i
< numEntries
; i
++, bSP
++, bIP
++) {
633 if (bSP
->fType
!= bIP
->fType
)
636 switch (bSP
->fType
) {
638 if (bSP
->fLen
!= bIP
->fLen
)
640 else if (strncmp(bSP
->fFundTypeID
, bIP
->fFundTypeID
, bSP
->fLen
))
647 if (bSP
->fFundTypeID
!= bIP
->fFundTypeID
)
658 return false; // Fatal errors
665 static int searchDict(ParseContext
*c
, int entry
, int numE
)
667 int sub
, numSubs
= c
->fP
.fNumS
;
669 // don't try to substitute the last builtin
670 if (numE
== 1 && kNTBuiltIn
== c
->fInEntries
[entry
].fType
)
673 for (sub
= 0; sub
< numSubs
; sub
++)
674 if (compareTypes(c
, sub
, entry
, numE
))
680 static int searchDictClass(ParseContext
*c
, const char *qname
, int len
)
683 int sub
, numSubs
= c
->fP
.fNumS
;
685 for (sub
= 0, subP
= c
->fSubDict
; sub
< numSubs
; sub
++, subP
++) {
686 BaseTypeData
*iP
= &c
->fInEntries
[subP
->fStartEntry
];
688 if (kNTClass
!= iP
->fType
|| iP
->fLen
!= len
)
690 if (!strncmp(iP
->fFundTypeID
, qname
, len
))
698 appendQualifiedClass(ParseContext
*c
, int entry
)
700 BaseTypeData
*iP
, *oP
, *sP
, *endSP
;
701 const char *cp
, *typeID
;
703 int sub
, subEntry
, prefixLen
;
706 int decodeStart
= c
->fP
.fNumI
;
708 // Scan through the incom
709 iP
= &c
->fInEntries
[entry
];
710 endSP
= &c
->fInEntries
[MAX_ENTRIES
];
711 sP
= &c
->fInEntries
[decodeStart
];
713 prefixLen
= iP
->fLen
;
714 typeID
= cp
= iP
->fFundTypeID
;
715 for (q_count
= 0; sP
< endSP
&& (cp
-typeID
) < prefixLen
; q_count
++, sP
++) {
718 count
= strtoul(cp
, &cp_new
, 10);
721 sP
->fType
= kNTClass
;
722 sP
->fFundTypeID
= typeID
;
723 sP
->fLen
= cp
- typeID
;
728 // Search backwards until I find the first substitution
730 for (subEntry
= q_count
, sP
--; subEntry
> 0; subEntry
--, sP
--) {
731 sub
= searchDictClass(c
, sP
->fFundTypeID
, sP
->fLen
);
736 // Now drop the symbol into the output buffer
742 *oP
= *iP
; // No sub copy original
744 // Substitution found
745 prefixLen
= sP
->fLen
; // Length of substitution
747 oP
->fType
= kNTSubstitute
; // Assume complete substitution
749 oP
->fFundTypeID
= NULL
;
751 // We have a partial substitution so tag on the unmatched bit
752 if (prefixLen
!= iP
->fLen
) {
753 oP
->fType
= kNTSubQualClass
; // Re-characterise as 2 part sub
759 *oP
= *iP
; // Duplicate the original
760 oP
->fType
= kNTSubQualClass
;
761 oP
->fFundTypeID
+= prefixLen
; // Skip leading substituted text
762 oP
->fLen
-= prefixLen
;
766 // Finally insert the qualified class names into the dictionary
767 for (subEntry
++, sP
++; subEntry
< q_count
; subEntry
++, decodeStart
++) {
768 c
->fInEntries
[decodeStart
] = *sP
++;
769 if (!newSub(c
, decodeStart
, 1))
772 c
->fP
.fNumI
= decodeStart
;
774 if (!newSub(c
, entry
, 1))
781 appendType(ParseContext
*c
, int type
)
783 BaseTypeData
*iP
, *oP
;
786 int entry
, numE
, lastEntry
;
789 if (type
>= c
->fP
.fNumT
)
792 tP
= &c
->fTypeList
[type
++];
793 entry
= tP
->fStartEntry
;
794 numE
= tP
->fNumEntries
;
795 lastEntry
= entry
+ numE
;
797 for (i
= 0, found
= false, sub
= -1; i
< numE
; i
++) {
798 iP
= &c
->fInEntries
[entry
+ i
];
801 // Function & Builtin can't be compressed alone
804 i
++; // Copy the current entry
810 sub
= searchDict(c
, entry
+ i
, numE
- i
);
811 if (sub
< 0 && !iP
->fQualified
)
818 sub
= searchDict(c
, entry
+ i
, numE
- i
);
822 // Internal error's should never occur
825 case kNTSubQualClass
:
835 return -1; // Internal error: no terminal symbol?
837 // Copy the already input buffer to the output
838 oP
= &c
->fOutEntries
[c
->fP
.fNumO
];
840 if (c
->fP
.fNumO
+ i
>= MAX_ENTRIES
)
843 bcopy(&c
->fInEntries
[entry
], oP
, i
* sizeof(*oP
));
849 // We found a substitution
850 oP
->fType
= kNTSubstitute
;
852 c
->fP
.fNumO
++; // Increment output for the substitution
854 // Walk over types that have been substituted
855 while (type
< c
->fP
.fNumT
856 && c
->fTypeList
[type
].fStartEntry
< lastEntry
)
859 else switch (iP
->fType
)
862 type
= appendType(c
, type
); // Class Name
865 type
= appendType(c
, type
); // Pointer to function
871 type
= appendType(c
, type
); // Return type
875 // process the argument list
877 tP
= &c
->fTypeList
[type
];
878 if (tP
->fStartEntry
< lastEntry
) {
879 type
= appendType(c
, type
);
885 } while (type
< c
->fP
.fNumT
);
889 oP
->fType
= kNTFuncEnd
;
893 i
--; // Do not store the buildit in the dictionary
896 case kNTClass
: // Nothing more to do
899 else if (appendQualifiedClass(c
, entry
+ i
))
905 // No further substititions to be had update the dictionary
906 for (i
+= entry
; --i
>= entry
; ) {
907 if (!newSub(c
, i
, lastEntry
- i
))
914 static Boolean
appendArgumentList(ParseContext
*c
)
918 c
->fRetCode
= kR3InternalNotRemangled
;
919 // Setup the output entry array
921 for (i
= 0; i
< num
; ) {
922 i
= appendType(c
, i
);
927 // First pass output uncompressed types
928 for (i
= 0, num
= c
->fP
.fNumO
; i
< num
; i
++) {
931 bP
= &c
->fOutEntries
[i
];
934 continue; // Pseudo entry do not output;
938 case kNTSubstitute
: appendSub(c
, bP
->fLen
); break;
940 case kNTSubQualClass
:
942 appendSub(c
, bP
->fLen
);
943 i
++; bP
= &c
->fOutEntries
[i
];
944 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
949 if (bP
->fQualified
) {
951 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
955 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
959 char numbuf
[16]; // Bigger than MAX_LONG + 3
961 len
= snprintf(numbuf
, sizeof(numbuf
),
962 "A%lu_", (unsigned long) bP
->fFundTypeID
);
963 appendNStr(c
, numbuf
, len
);
968 case kNTDeclarator
: appendChar(c
, (int) bP
->fFundTypeID
); break;
969 case kNTMethod
: appendChar(c
, 'M'); break;
970 case kNTFunction
: appendChar(c
, 'F'); break;
971 case kNTFuncEnd
: appendChar(c
, 'E'); break;
976 return false; // Fatal errors
980 // Successful remangle
981 c
->fRetCode
= kR3Remangled
;
989 // <count> ::= <digit> <digit>*
990 static Boolean
parse_count(ParseContext
*c
, int *countP
)
997 if (ch
< '1' || ch
> '9')
1000 count
= strtol(c
->fP
.fInChar
, &newp
, 10);
1001 c
->fP
.fInChar
= newp
;
1009 // "n" <index> can cause the following type to be ambiguous as
1011 // "n" <digit> <counted_class_name> ...
1012 // | "n" <digit> <digit> '_' <declarator> <fund_type_id> ...
1013 // However as the class '_Pc' is probably going to be unlikely a quick
1014 // check to see if the next field is a valid type would probably clear
1015 // up the abiguity for the majority of cases.
1017 // <index> ::= <digit> | <digit> <digit> <digit>* "_"
1018 static Boolean
parse_index(ParseContext
*c
, int *indexP
)
1020 CheckPoint chk
= *checkPoint(c
);
1027 if ( !('0' <= ch0
&& ch0
<= '9') )
1029 if ('0' <= ch1
&& ch1
<= '9') {
1030 if (!parse_count(c
, &index
))
1032 if (isNext(c
, '_')) {
1033 // @@@ gvdl: Ambiguity check one day
1039 resetTo(c
, &chk
); // Must be the one digit case
1055 // <qualifier> ::= "C" ; const
1057 // | "u" ; restrict (C99) unsupported
1058 // | "G" ; struct/union/enum ; unused in gcc3
1059 static Boolean
parse_qualifiers(ParseContext
*c
)
1061 BaseTypeData
*bP
= c
->fCurBaseP
;
1065 bP
->fConst
= true; // "C" ; const
1066 else if (isNext(c
, 'V'))
1067 bP
->fVolatile
= true; // "V" ; volatile
1068 else if (isNext(c
, 'u'))
1069 return false; // "u" ; restrict (C99)
1070 else if (isNext(c
, 'G'))
1071 continue; // "G" ; struct/union/enum ; unused
1079 // Assumes we have an open fInEntry in fCurBaseP
1080 static Boolean
duplicateEntries(ParseContext
*c
, int start
, int numE
)
1082 BaseTypeData
*bIP
= &c
->fInEntries
[start
]; // First duplicate entry
1083 BaseTypeData
*bP
= c
->fCurBaseP
;
1086 // Duplicating a method
1087 if (kNTMethod
== bIP
->fType
) {
1088 bP
--; // Strip leading 'P' declarator
1094 // do we have room available for duplication
1095 if (c
->fP
.fNumI
+ numE
>= MAX_ENTRIES
)
1098 // Copy the parse entries over
1099 bcopy(bIP
, bP
, (numE
+ 1) * sizeof(*bP
));
1101 // Now we have to duplicate the types for the new entry
1102 for (i
= 0; i
< c
->fP
.fNumT
; i
++) {
1103 TypeData
*tP
= &c
->fTypeList
[i
];
1104 if (tP
->fStartEntry
< start
)
1106 else if (tP
->fStartEntry
<= start
+ numE
)
1107 dupType(c
, tP
, bP
- bIP
);
1112 c
->fP
.fNumI
+= numE
;
1119 // Must have a valid c->fCurBaseP pointer on entry
1120 // <class_name> ::= <counted_class_name> ; plain class name
1121 // | "Q" <qualified_name> ; qualified name
1122 // | "B" <index> ; compressed name
1123 // | "K" <qualified_name> ; ignored and illegal
1124 // <qualified_name> ::= <q_count> <counted_class_name>+
1125 // <q_count> ::= <digit> | "_" <digit> <digit>* "_"
1126 // <counted_class_name> ::= <count> <name>
1127 // <name> ::= <char> <char>*
1129 parse_class_name(ParseContext
*c
)
1131 BaseTypeData
*bP
= c
->fCurBaseP
;
1132 const char *typeId
= c
->fP
.fInChar
;
1136 if (parse_count(c
, &count
)) {
1138 // <counted_class_name> ::= <count> <name>
1139 if (!hasRemain(c
, count
))
1142 bP
->fType
= kNTClass
;
1145 bP
->fFundTypeID
= typeId
;
1146 bP
->fLen
= c
->fP
.fInChar
- typeId
;
1149 switch (peekNext(c
)) {
1156 // | "Q" <qualified_name> ; qualified name
1157 // <qualified_name> ::= <q_count> <counted_class_name>+
1158 // <q_count> ::= <digit> | "_" <digit> <digit>* "_"
1159 if ('_' == (ch
= getNext(c
))) {
1161 if (!parse_count(c
, &q_count
) || !isNext(c
, '_'))
1164 else if ('1' <= ch
&& ch
<= '9')
1170 typeId
= c
->fP
.fInChar
;
1171 bP
->fType
= kNTClass
;
1172 bP
->fQualified
= true;
1174 for (i
= 0; i
< q_count
; i
++) {
1175 if (parse_count(c
, &count
))
1180 bP
->fLen
= c
->fP
.fInChar
- typeId
;
1181 bP
->fFundTypeID
= typeId
;
1189 if (!parse_index(c
, &count
) || count
>= c
->fP
.fNumB
)
1192 if (!duplicateEntries(c
, c
->fBDict
[count
].fStartEntry
,
1193 c
->fBDict
[count
].fNumEntries
))
1202 if (newBDict(c
, bP
- c
->fInEntries
, 1))
1209 // <fund_type_id> ::= <class_name>
1217 // | "r" ; long double
1221 // | "x" ; long long
1222 // | "G" <count> ; ???
1223 static Boolean
parse_fund_type_id(ParseContext
*c
)
1225 BaseTypeData
*bP
= c
->fCurBaseP
;
1227 if (!parse_class_name(c
)) {
1228 // Use the TypeID pointer as a 4 character buffer
1229 char ch
= peekNext(c
);
1231 if (bP
->fSigned
&& 'c' != ch
)
1232 goto abandonParse
; // illegal only chars can be signed
1236 case 'b': case 'd': case 'f': case 'v': case 'w': // No map types
1239 case 'c': // character
1240 if (bP
->fSigned
) ch
= 'a';
1241 else if (bP
->fUnsigned
) ch
= 'h';
1243 case 'e': // ellipsis
1247 if (bP
->fUnsigned
) ch
= 'j';
1250 if (bP
->fUnsigned
) ch
= 'm';
1252 case 'r': // long double
1256 if (bP
->fUnsigned
) ch
= 't';
1258 case 'x': // long long
1259 if (bP
->fUnsigned
) ch
= 'y';
1262 case 'G': // Don't understand "G"
1267 advance(c
, 1); // Consume the input character
1268 bP
->fFundTypeID
= (void *) (int) ch
;
1270 bP
->fType
= kNTBuiltIn
;
1279 // <arg_type> ::= <type> [ "n" <index> ]
1280 // | "N" <count> <pos> ; Not implemented
1281 // | "T" <index> ; Not implemented
1282 static Boolean
parse_arg_type(ParseContext
*c
)
1284 // Don't bother to check point as parse_argument_types does it for us
1289 typeP
= &c
->fTypeList
[c
->fP
.fNumT
]; // Cache type for later repeat
1293 // Now check for a repeat count on this type
1294 if (isNext(c
, 'n')) {
1295 if (!parse_index(c
, &repeat
))
1299 c
->fCurBaseP
= newIn(c
); // Duplicate requires a fresh type
1302 if (!duplicateEntries(c
, typeP
->fStartEntry
, typeP
->fNumEntries
))
1310 // <argument_types> ::= # Empty
1312 static Boolean
parse_argument_types(ParseContext
*c
)
1317 if (!parse_arg_type(c
))
1320 while (!atEnd(c
) && parse_arg_type(c
))
1325 // Not a counted class name so reset to checkPoint
1330 // leaf function so the copy aside buffer isn't on the primary
1333 rotateFunction(ParseContext
*c
, int argStart
, int retStart
)
1335 char returnTypeBuffer
[MAX_RETURN_BUFFER
];
1336 unsigned int numArg
, numRet
;
1337 unsigned int lenArg
, lenRet
;
1338 char *sArgP
, *sRetP
;
1341 TypeData
*argTP
= &c
->fTypeList
[argStart
];
1342 TypeData
*retTP
= &c
->fTypeList
[retStart
];
1344 // Rotate around the entries first
1345 numArg
= retTP
->fStartEntry
- argTP
->fStartEntry
;
1346 numRet
= retTP
->fNumEntries
;
1347 lenArg
= numArg
* sizeof(BaseTypeData
);
1348 lenRet
= numRet
* sizeof(BaseTypeData
);
1350 // Copy the return type into a buffer
1351 if (lenRet
> sizeof(returnTypeBuffer
))
1354 sArgP
= (char *) (&c
->fInEntries
[argTP
->fStartEntry
]);
1355 sRetP
= (char *) (&c
->fInEntries
[retTP
->fStartEntry
]);
1357 bcopy(sRetP
, returnTypeBuffer
, lenRet
);
1358 bcopy(sArgP
, sArgP
+ lenRet
, lenArg
);
1359 bcopy(returnTypeBuffer
, sArgP
, lenRet
);
1361 // Retarget the argument and return types for the new entry positions
1364 numArg
= retStart
- argStart
;
1365 numRet
= c
->fP
.fNumT
- retStart
;
1366 for (i
= 0; i
< numArg
; i
++)
1367 c
->fTypeList
[argStart
+i
].fStartEntry
+= lenRet
;
1368 for (i
= 0; i
< numRet
; i
++)
1369 c
->fTypeList
[retStart
+i
].fStartEntry
-= lenArg
;
1371 // Rotate the BDictionary
1372 for (i
= 0; i
< c
->fP
.fNumB
; i
++) {
1373 TypeData
*bDP
= &c
->fBDict
[i
];
1374 int start
= bDP
->fStartEntry
;
1376 if (start
>= argTP
->fStartEntry
)
1377 bDP
->fStartEntry
= start
+ lenRet
;
1378 else if (start
>= retTP
->fStartEntry
)
1379 bDP
->fStartEntry
= start
- lenArg
;
1382 // Finally rotate the retargeted type structures.
1383 lenArg
= numArg
* sizeof(TypeData
);
1384 lenRet
= numRet
* sizeof(TypeData
);
1386 sArgP
= (char *) (&c
->fTypeList
[argStart
]);
1387 sRetP
= (char *) (&c
->fTypeList
[retStart
]);
1389 bcopy(sRetP
, returnTypeBuffer
, lenRet
);
1390 bcopy(sArgP
, sArgP
+ lenRet
, lenArg
);
1391 bcopy(returnTypeBuffer
, sArgP
, lenRet
);
1396 // <function_type> ::= "F" <argument_types> "_" <type>
1397 static Boolean
parse_function_type(ParseContext
*c
, Boolean forMethod
)
1399 TypeData
*bDictP
= NULL
;
1400 BaseTypeData
*bP
= c
->fCurBaseP
;
1402 int argTypeStart
, retTypeStart
;
1405 bDictP
= newBDict(c
, c
->fP
.fNumI
-1, 0);
1410 if (!isNext(c
, 'F'))
1413 bP
->fType
= kNTFunction
;
1415 // Note that the argument types will advance the Entry list
1416 argTypeStart
= c
->fP
.fNumT
;
1417 if (!parse_argument_types(c
))
1420 if (!isNext(c
, '_'))
1423 // Parse the return type
1424 retTypeStart
= c
->fP
.fNumT
;
1428 // gcc3 puts the return code just after the 'F' declaration
1429 // as this impacts the order of the compression I need to rotate
1430 // the return type and the argument types.
1431 if (!rotateFunction(c
, argTypeStart
, retTypeStart
))
1435 bDictP
->fNumEntries
= c
->fP
.fNumI
- bDictP
->fStartEntry
;
1443 // To convert 2.95 method to a 3.0 method I need to prune the
1444 // first argument of the function type out of the parse tree.
1445 static Boolean
cleanMethodFunction(ParseContext
*c
, int type
)
1447 TypeData
*typeP
, *startTP
, *endTP
;
1449 int i
, thisStart
, thisEnd
, thisLen
, funcRemain
;
1451 // Get pointer for the return value's type.
1452 startTP
= &c
->fTypeList
[type
+1];
1453 endTP
= &c
->fTypeList
[c
->fP
.fNumT
];
1455 // Now look for the first type that starts after the return type
1456 thisEnd
= startTP
->fStartEntry
+ startTP
->fNumEntries
;
1457 for (startTP
++; startTP
< endTP
; startTP
++)
1458 if (startTP
->fStartEntry
>= thisEnd
)
1461 if (startTP
>= endTP
) {
1462 c
->fRetCode
= kR3InternalNotRemangled
;
1463 return false; // Internal error: should never happen
1466 // We now have a pointer to the 1st argument in the input list
1467 // we will need to excise the entries from the input list and don't forget
1468 // to remove the associated types from the type list.
1470 thisLen
= startTP
->fNumEntries
;
1471 thisStart
= startTP
->fStartEntry
;
1472 thisEnd
= thisStart
+ thisLen
;
1473 funcRemain
= c
->fP
.fNumI
- thisEnd
;
1474 bP
= &c
->fInEntries
[thisStart
];
1476 // If we have no arguments then replace the pointer with a void
1478 c
->fP
.fNumI
-= (thisLen
- 1);
1480 bP
->fFundTypeID
= (void *) (int) 'v'; // Void arg list
1482 bP
->fType
= kNTBuiltIn
;
1484 // Update the type entry for the void argument list
1485 startTP
->fNumEntries
= 1;
1489 // Move the argument list down to replace the 'this' pointer
1490 bcopy(bP
+ thisLen
, bP
, funcRemain
* sizeof(*bP
));
1491 c
->fP
.fNumI
-= thisLen
;
1493 // And remove the 'this' pointers type
1495 // First walk over all of the types that have to be removed
1496 for (typeP
= startTP
+ 1; typeP
< endTP
; typeP
++)
1497 if (typeP
->fStartEntry
>= thisEnd
)
1500 if (typeP
>= endTP
) {
1501 c
->fRetCode
= kR3InternalNotRemangled
;
1502 return false; // Internal error Can't be a void argument list.
1505 bcopy(typeP
, startTP
, (char *) endTP
- (char *) typeP
);
1507 c
->fP
.fNumT
-= typeP
- startTP
;
1508 endTP
= &c
->fTypeList
[c
->fP
.fNumT
];
1509 for (typeP
= startTP
; typeP
< endTP
; typeP
++)
1510 typeP
->fStartEntry
-= thisLen
;
1512 // Finally we can retarget the BDictionary lists
1513 for (i
= 0; i
< c
->fP
.fNumB
; i
++) {
1514 TypeData
*bDP
= &c
->fBDict
[i
];
1515 int start
= bDP
->fStartEntry
;
1517 if (start
< thisStart
)
1519 if (start
>= thisEnd
)
1522 bDP
->fStartEntry
= start
- thisLen
;
1528 // <method_type> ::= "M" <class_name> <function_type>
1530 // Note this is a very bad function. Gcc3 doesn't doesn't use pointer that
1531 // is immediately before this entry. We will have to delete the 'P' declarator
1532 // that is before the method declaration.
1533 // We will also have to prune the first type in the argument list as Gcc3
1534 // doesn't register the 'this' pointer within the function list.
1535 static Boolean
parse_method_type(ParseContext
*c
)
1541 bDictP
= newBDict(c
, c
->fP
.fNumI
-2, 0);
1545 // Replace 'P' declarator
1547 bP
= c
->fCurBaseP
- 1;
1549 if (!isNext(c
, 'M'))
1552 if (bP
->fFundTypeID
!= (void *) (int) 'P')
1555 // Replace the previous 'Pointer' declarator
1556 bP
->fType
= kNTMethod
;
1557 bP
->fFundTypeID
= NULL
;
1560 // Grab the method's 'this' type specification
1561 typeP
= newType(c
, c
->fP
.fNumI
);
1562 if (!newIn(c
) || !typeP
)
1565 if (!parse_class_name(c
))
1567 typeP
->fNumEntries
= c
->fP
.fNumI
- typeP
->fStartEntry
;
1569 // Grab the <function_type> specifier
1570 typeP
= newType(c
, c
->fP
.fNumI
);
1571 if (!newIn(c
) || !typeP
)
1574 if (!parse_function_type(c
, /* forMethod */ true))
1577 if (!cleanMethodFunction(c
, typeP
- c
->fTypeList
))
1579 typeP
->fNumEntries
= c
->fP
.fNumI
- typeP
->fStartEntry
;
1581 // Finally update the dictionary with the M & 'this'
1582 bDictP
->fNumEntries
= c
->fP
.fNumI
- bDictP
->fStartEntry
;
1590 static Boolean
emitQualifiers(ParseContext
*c
)
1592 BaseTypeData
*bP
= c
->fCurBaseP
;
1594 if (bP
->fVolatile
|| bP
->fConst
) {
1595 Boolean isConst
, isVolatile
, isSigned
, isUnsigned
;
1597 isVolatile
= bP
->fVolatile
;
1598 isConst
= bP
->fConst
;
1599 isSigned
= bP
->fSigned
;
1600 isUnsigned
= bP
->fUnsigned
;
1601 bP
->fConst
= bP
->fVolatile
= bP
->fSigned
= bP
->fUnsigned
= 0;
1604 bP
->fType
= kNTDeclarator
;
1605 bP
->fFundTypeID
= (void *) (int) 'V';
1612 bP
->fType
= kNTDeclarator
;
1613 bP
->fFundTypeID
= (void *) (int) 'K';
1619 bP
->fSigned
= isSigned
;
1620 bP
->fUnsigned
= isUnsigned
;
1627 // <base_type> ::= <function_type> ; function
1628 // | <method_type> ; method
1629 // | <type_qualifier>* <fund_type_id>
1630 // <type_qualifier> ::= "S" ; signed (chars only)
1631 // | "U" ; unsigned (any integral type)
1632 // | "J" ; __complex
1634 static Boolean
parse_base_type(ParseContext
*c
)
1636 if ('F' == peekNext(c
)) {
1637 if (!parse_function_type(c
, /* forMethod */ false))
1640 else if ('M' == peekNext(c
)) {
1641 if (!parse_method_type(c
))
1645 // | <type_qualifier>* <fund_type_id>
1646 BaseTypeData
*bP
= c
->fCurBaseP
;
1649 // <type_qualifier> ::= "S" ; signed (chars only)
1650 { bP
->fSigned
= true; continue; }
1651 else if (isNext(c
, 'U'))
1652 // | "U" ; unsigned (any integral type)
1653 { bP
->fUnsigned
= true; continue; }
1654 else if (isNext(c
, 'C'))
1656 // <qualifier> ::= "C" ; const
1657 { bP
->fConst
= true; continue; }
1658 else if (isNext(c
, 'V'))
1660 { bP
->fVolatile
= true; continue; }
1661 else if (charNext(c
, "Ju"))
1662 goto abandonParse
; // Don't support these qualifiers
1663 // | "J" ; __complex
1664 // | "u" ; restrict (C99)
1669 if (!emitQualifiers(c
))
1672 if (!parse_fund_type_id(c
))
1681 // Use the top SDict as a stack of declarators.
1682 // parses <declarator>*
1683 // <declarator> ::= "P" ; pointer
1684 // | "p" ; pointer (but never occurs?)
1685 // | "R" ; reference (&)
1686 // | "A" <count> ; array
1691 // As a side-effect the fCurBaseP is setup with any qualifiers on exit
1692 static Boolean
parse_declarators(ParseContext
*c
)
1699 // Note we MUST go through the for loop at least once
1700 for (count
= 0; ; count
++) {
1701 const char *curDecl
;
1707 // <declarator> ::= <qualifier> production
1708 if (!parse_qualifiers(c
) || !emitQualifiers(c
))
1711 dP
= c
->fCurBaseP
; // Find the current base type pointer
1713 curDecl
= c
->fP
.fInChar
;
1715 switch (peekNext(c
)) {
1717 case 'P': case 'p': case 'R':
1718 // <declarator> ::= "P" ; pointer
1719 // | "p" ; pointer (but never occurs?)
1720 // | "R" ; reference (&)
1722 dP
->fType
= kNTDeclarator
;
1726 if ('p' == ch
) ch
= 'P';
1727 dP
->fFundTypeID
= (void *) (int) ch
;
1729 continue; // Go around again
1732 // | "A" <count> ; array
1733 dP
->fType
= kNTArray
;
1735 advance(c
, 1); curDecl
++;
1736 l
= strtoul(curDecl
, &newp
, 10);
1737 c
->fP
.fInChar
= newp
;
1738 curDecl
= (const char *)l
;
1741 dP
->fFundTypeID
= curDecl
;
1743 continue; // Go around again
1746 // | "T" <index> Unsupported
1747 // | "O" <count> Unsupported
1764 // <type> ::= <declarator>* <base_type>
1765 static Boolean
parse_type(ParseContext
*c
)
1767 CheckPoint chk
= *checkPoint(c
);
1768 TypeData
*typeP
= newType(c
, c
->fP
.fNumI
);
1772 // As a side-effect the fCurBaseP is setup with any qualifiers on exit
1773 if (!parse_declarators(c
))
1776 // Merge the last qualifiers into the base type
1777 if (!parse_base_type(c
) || kNTUndefined
== c
->fCurBaseP
->fType
)
1780 typeP
->fNumEntries
= c
->fP
.fNumI
- typeP
->fStartEntry
;
1788 // <function_name> ::= <char> <char>*
1789 // No need to check point as an invalid function name is fatal
1790 // Consumes trailing "__".
1792 parse_function_name(ParseContext
*c
)
1796 while ( (ch
= peekNext(c
)) )
1799 if ('_' == ch
&& '_' == peekNext(c
)) {
1802 } while ('_' == peekNext(c
));
1810 // <opinfo> ::= "type" <type>
1812 // | <opname> "__" ; Implies null function name
1814 // <opname> ::= "aa" # && ==> "aa"
1815 // | "aad" # &= ==> "aN"
1816 // | "ad" # & ==> "ad"
1817 // | "adv" # /= ==> "dV"
1818 // | "aer" # ^= ==> "eO"
1819 // | "als" # <<= ==> "lS"
1820 // | "amd" # %= ==> "rM"
1821 // | "ami" # -= ==> "mI"
1822 // | "aml" # *= ==> "mL
1823 // | "aor" # |= ==> "oR
1824 // | "apl" # += ==> "pL
1825 // | "ars" # >>= ==> "rS
1826 // | "as" # = ==> "aS
1827 // | "cl" # () ==> "cl
1828 // | "cm" # , ==> "cm
1829 // | "cn" # ?: ==> "qu
1830 // | "co" # ~ ==> "co
1831 // | "dl" # delete ==> "dl
1832 // | "dv" # / ==> "dv
1833 // | "eq" # == ==> "eq
1834 // | "er" # ^ ==> "eo
1835 // | "ge" # >= ==> "ge
1836 // | "gt" # > ==> "gt
1837 // | "le" # <= ==> "le
1838 // | "ls" # << ==> "ls
1839 // | "lt" # < ==> "lt
1840 // | "md" # % ==> "rm
1841 // | "mi" # - ==> "mi
1842 // | "ml" # * ==> "ml
1843 // | "mm" # -- ==> "mm
1844 // | "mn" # <? ==> "????????????????
1845 // | "mx" # >? ==> "????????????????
1846 // | "ne" # != ==> "ne
1847 // | "nt" # ! ==> "nt
1848 // | "nw" # new ==> "nw
1849 // | "oo" # || ==> "oo"
1850 // | "or" # | ==> "or
1851 // | "pl" # + ==> "pl
1852 // | "pp" # ++ ==> "pp
1853 // | "rf" # -> ==> "pt
1854 // | "rm" # ->* ==> "pm
1855 // | "rs" # >> ==> "rs
1856 // | "sz" # sizeof ==> "sz
1857 // | "vc" # [] ==> "ix
1858 // | "vd" # delete[] ==> "da
1859 // | "vn" # new[] ==> "na
1860 static struct opMap
{
1861 const char *op295
, *op3
;
1863 {"aad", "aN" }, {"adv", "dV" }, {"aer", "eO" }, {"als", "lS" },
1864 {"amd", "rM" }, {"ami", "mI" }, {"aml", "mL" }, {"aor", "oR" },
1865 {"apl", "pL" }, {"ars", "rS" }, {"aa", "aa" }, {"ad", "ad" },
1866 {"as", "aS" }, {"cl", "cl" }, {"cm", "cm" }, {"cn", "qu" },
1867 {"co", "co" }, {"dl", "dl" }, {"dv", "dv" }, {"eq", "eq" },
1868 {"er", "eo" }, {"ge", "ge" }, {"gt", "gt" }, {"le", "le" },
1869 {"ls", "ls" }, {"lt", "lt" }, {"md", "rm" }, {"mi", "mi" },
1870 {"ml", "ml" }, {"mm", "mm" }, {"mn", NULL
}, {"mx", NULL
},
1871 {"ne", "ne" }, {"nt", "nt" }, {"nw", "nw" }, {"oo", "oo" },
1872 {"or", "or" }, {"pl", "pl" }, {"pp", "pp" }, {"rf", "pt" },
1873 {"rm", "pm" }, {"rs", "rs" }, {"sz", "sz" }, {"vc", "ix" },
1874 {"vd", "da" }, {"vn", "na" },
1877 static Boolean
parse_opinfo(ParseContext
*c
, const char **opInfoP
)
1879 CheckPoint chk
= *checkPoint(c
);
1884 if ('a' == (ch
= peekNext(c
))) {
1887 else if (strNext(c
, "type")) {
1890 else if (retard(c
, 4) && strNext(c
, "____op")) {
1891 // @@@ gvdl: check this out it may change
1892 // <opinfo> ::= "__op" <type>
1896 // Failed till now so reset and see if we have an operator
1899 // quick check to see if we may have an operator
1900 if (!strrchr("acdeglmnoprsv", peekNext(c
)))
1904 for (i
= 0; i
< sizeof(opMapTable
)/sizeof(opMapTable
[0]); i
++) {
1905 if (strNext(c
, opMapTable
[i
].op295
)) {
1906 op
= opMapTable
[i
].op3
;
1913 if (!strNext(c
, "__")) // Trailing underbars
1924 // <signature> ::= <qualifier>* <s_element> <argument_types>
1925 // <s_element> ::= <class_name>
1926 // | "K" <qualified_name>
1928 // | "F" <argument_types> [ "_" <return_type> ]
1929 // <return_type> ::= <type>
1930 // Treat the prefix's s_element as a full type
1932 parse_signature(ParseContext
*c
,
1933 const char *func
, int funcLen
, const char *op
)
1938 Boolean isFunction
= false;
1940 if (isNext(c
, 'F')) {
1941 // | "F" <argument_types> [ "_" <return_type> ]
1943 char numbuf
[16]; // Bigger than MAX_INT + 4
1949 len
= snprintf(numbuf
, sizeof(numbuf
), "__Z%d", funcLen
);
1951 appendNStr(c
, numbuf
, len
);
1952 appendNStr(c
, func
, funcLen
);
1954 else if (isNext(c
, 'S')) {
1962 // See if we can find a qualified class reference
1963 tP
= newType(c
, c
->fP
.fNumI
);
1971 // Parse any qualifiers, store results in *fCurBaseP
1973 if (!parse_qualifiers(c
))
1976 if (!parse_class_name(c
))
1979 bP
= c
->fCurBaseP
; // class name may have redifined current
1980 tP
->fNumEntries
= c
->fP
.fNumI
- tP
->fStartEntry
;
1982 APPENDSTR(c
, "__ZN");
1983 decodeQual(bP
, &qualLen
, &qual
);
1985 appendNStr(c
, qual
, qualLen
);
1986 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
1989 char numbuf
[16]; // Bigger than MAX_INT + 1
1992 len
= snprintf(numbuf
, sizeof(numbuf
), "%d", funcLen
);
1993 appendNStr(c
, numbuf
, len
);
1994 appendNStr(c
, func
, funcLen
);
1999 // No function & no op means constructor choose one of C1 & C2
2006 appendChar(c
, 'v'); // void argument list
2007 c
->fRetCode
= kR3Remangled
;
2011 c
->fCurBaseP
= NULL
;
2012 if (!parse_argument_types(c
))
2016 if (isNext(c
, '_')) {
2017 // && !parse_type(c) @@@ gvdl: Unsupported return
2018 c
->fRetCode
= kR3InternalNotRemangled
;
2026 // OK we have a complete and successful parse now output the
2028 return appendArgumentList(c
);
2034 // <mangled_name> ::= <prefix> [ <signature> ]
2035 // <prefix> ::= [ "_GLOBAL_" [ID] "__" ] <function_name> "__" [ <opinfo> ]
2036 static Boolean
parse_mangled_name(ParseContext
*c
)
2039 CheckPoint dubBarChk
;
2043 if (strNext(c
, "_GLOBAL_")) { // Is this GLOBAL static constructor?
2044 // gvdl: can't deal with _GLOBAL_
2045 c
->fRetCode
= kR3InternalNotRemangled
;
2046 return false; // Can't deal with these
2049 func
= c
->fP
.fInChar
;
2050 for (chk
= *checkPoint(c
); ; resetTo(c
, &dubBarChk
)) {
2052 const char *op
= NULL
;
2054 if (!parse_function_name(c
))
2056 dubBarChk
= *checkPoint(c
);
2058 // Note that the opInfo may be earlier than the curDoubleBar
2059 // in which case the function name may need to be shrunk later on.
2060 (void) parse_opinfo(c
, &op
);
2063 goto abandonParse
; // No Signature?
2065 funcLen
= inCharFromCheck(&dubBarChk
) - func
- 2;
2066 if (parse_signature(c
, func
, funcLen
, op
))
2069 if (kR3NotRemangled
!= c
->fRetCode
)
2072 // If no error then try again maybe another '__' exists
2080 // <gnu_special> ::= ("_._" | "_$_" ) <class_name> ; destructor
2081 // | "__vt_" <class_name> ; virtual table
2082 // | "_" <class_name> ("."|"$") <varname>
2083 static Boolean
parse_gnu_special(ParseContext
*c
)
2085 CheckPoint chk
= *checkPoint(c
);
2086 BaseTypeData
*bP
= newIn(c
);
2091 // What do the intel desctructors look like
2092 if (strNext(c
, "_._") || strNext(c
, "_$_") ) // Is this a destructor
2094 if (!parse_class_name(c
) || !atEnd(c
))
2096 APPENDSTR(c
, "__ZN");
2097 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2098 APPENDSTR(c
, "D2Ev");
2099 c
->fRetCode
= kR3Remangled
;
2102 else if (strNext(c
, "__vt_")) // Is it's a vtable?
2104 if (!parse_class_name(c
) || !atEnd(c
))
2107 APPENDSTR(c
, "__ZTV");
2108 if (kNTClass
!= bP
->fType
)
2110 else if (bP
->fQualified
) {
2112 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2116 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2118 c
->fRetCode
= kR3Remangled
;
2121 else if (isNext(c
, '_')) // Maybe it's a variable
2123 const char *varname
;
2125 char numbuf
[16]; // Bigger than MAX_INT + 1
2127 if (!parse_class_name(c
)) // Loads up the bP structure
2130 if (!isNext(c
, '.') && !isNext(c
, '$'))
2133 // Parse the variable name now.
2134 varname
= c
->fP
.fInChar
;
2135 if (atEnd(c
) || !isValidFirstChar(getNext(c
)))
2139 if (!isValidChar(getNext(c
)))
2142 varlen
= c
->fP
.fInChar
- varname
;
2143 len
= snprintf(numbuf
, sizeof(numbuf
), "%d", varlen
);
2145 APPENDSTR(c
, "__ZN");
2146 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2148 appendNStr(c
, numbuf
, len
);
2149 appendNStr(c
, varname
, varlen
);
2152 c
->fRetCode
= kR3Remangled
;
2156 // Oh well it is none of those so give up but reset scan
2162 // <special_or_name> ::= <gnu_special>
2164 static Boolean
parse_special_or_name(ParseContext
*c
)
2169 res
= (parse_gnu_special(c
) || parse_mangled_name(c
));
2170 appendChar(c
, '\0');
2175 Rem3Return
rem3_remangle_name(char *gcc3
, int *gcc3size
, const char *gcc295
)
2181 if (!gcc295
|| !gcc3
|| !gcc3size
)
2182 return kR3BadArgument
;
2184 size
= strlen(gcc295
);
2186 return kR3NotRemangled
; // Not a valid C++ symbol
2187 else if (*gcc295
!= '_')
2188 return kR3NotRemangled
; // no leading '_', not valid
2190 c
= (ParseContext
*) malloc(sizeof(*c
));
2192 return kR3InternalNotRemangled
;
2193 bzero(c
, sizeof(*c
));
2196 c
->fInStr
= gcc295
+ 1; // Strip leading '_'
2197 c
->fP
.fInChar
= c
->fInStr
;
2199 c
->fOutStrEnd
= gcc3
+ *gcc3size
;
2202 c
->fRetCode
= kR3NotRemangled
;
2203 (void) parse_special_or_name(c
);
2205 result
= c
->fRetCode
;
2206 if (kR3Remangled
== result
) {
2207 if (c
->fOutChar
> c
->fOutStrEnd
)
2208 result
= kR3BufferTooSmallRemangled
;
2209 *gcc3size
= c
->fOutChar
- gcc3
- 1; // Remove nul from len