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(ParseContext
*c
, 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
, 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
= (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
;
702 int sub
, subEntry
, prefixLen
;
705 int decodeStart
= c
->fP
.fNumI
;
707 // Scan through the incom
708 iP
= &c
->fInEntries
[entry
];
709 endSP
= &c
->fInEntries
[MAX_ENTRIES
];
710 sP
= &c
->fInEntries
[decodeStart
];
712 prefixLen
= iP
->fLen
;
713 typeID
= cp
= iP
->fFundTypeID
;
714 for (q_count
= 0; sP
< endSP
&& (cp
-typeID
) < prefixLen
; q_count
++, sP
++) {
717 count
= strtoul(cp
, (char **) &cp
, 10);
720 sP
->fType
= kNTClass
;
721 sP
->fFundTypeID
= typeID
;
722 sP
->fLen
= cp
- typeID
;
727 // Search backwards until I find the first substitution
729 for (subEntry
= q_count
, sP
--; subEntry
> 0; subEntry
--, sP
--) {
730 sub
= searchDictClass(c
, sP
->fFundTypeID
, sP
->fLen
);
735 // Now drop the symbol into the output buffer
741 *oP
= *iP
; // No sub copy original
743 // Substitution found
744 prefixLen
= sP
->fLen
; // Length of substitution
746 oP
->fType
= kNTSubstitute
; // Assume complete substitution
750 // We have a partial substitution so tag on the unmatched bit
751 if (prefixLen
!= iP
->fLen
) {
752 oP
->fType
= kNTSubQualClass
; // Re-characterise as 2 part sub
758 *oP
= *iP
; // Duplicate the original
759 oP
->fType
= kNTSubQualClass
;
760 oP
->fFundTypeID
+= prefixLen
; // Skip leading substituted text
761 oP
->fLen
-= prefixLen
;
765 // Finally insert the qualified class names into the dictionary
766 for (subEntry
++, sP
++; subEntry
< q_count
; subEntry
++, decodeStart
++) {
767 c
->fInEntries
[decodeStart
] = *sP
++;
768 if (!newSub(c
, decodeStart
, 1))
771 c
->fP
.fNumI
= decodeStart
;
773 if (!newSub(c
, entry
, 1))
780 appendType(ParseContext
*c
, int type
)
782 BaseTypeData
*iP
, *oP
;
785 int entry
, numE
, lastEntry
;
788 if (type
>= c
->fP
.fNumT
)
791 tP
= &c
->fTypeList
[type
++];
792 entry
= tP
->fStartEntry
;
793 numE
= tP
->fNumEntries
;
794 lastEntry
= entry
+ numE
;
796 for (i
= 0, found
= false, sub
= -1; i
< numE
; i
++) {
797 iP
= &c
->fInEntries
[entry
+ i
];
800 // Function & Builtin can't be compressed alone
803 i
++; // Copy the current entry
809 sub
= searchDict(c
, entry
+ i
, numE
- i
);
810 if (sub
< 0 && !iP
->fQualified
)
817 sub
= searchDict(c
, entry
+ i
, numE
- i
);
821 // Internal error's should never occur
824 case kNTSubQualClass
:
834 return -1; // Internal error: no terminal symbol?
836 // Copy the already input buffer to the output
837 oP
= &c
->fOutEntries
[c
->fP
.fNumO
];
839 if (c
->fP
.fNumO
+ i
>= MAX_ENTRIES
)
842 bcopy(&c
->fInEntries
[entry
], oP
, i
* sizeof(*oP
));
848 // We found a substitution
849 oP
->fType
= kNTSubstitute
;
851 c
->fP
.fNumO
++; // Increment output for the substitution
853 // Walk over types that have been substituted
854 while (type
< c
->fP
.fNumT
855 && c
->fTypeList
[type
].fStartEntry
< lastEntry
)
858 else switch (iP
->fType
)
861 type
= appendType(c
, type
); // Class Name
864 type
= appendType(c
, type
); // Pointer to function
870 type
= appendType(c
, type
); // Return type
874 // process the argument list
876 tP
= &c
->fTypeList
[type
];
877 if (tP
->fStartEntry
< lastEntry
) {
878 type
= appendType(c
, type
);
884 } while (type
< c
->fP
.fNumT
);
888 oP
->fType
= kNTFuncEnd
;
892 i
--; // Do not store the buildit in the dictionary
895 case kNTClass
: // Nothing more to do
898 else if (appendQualifiedClass(c
, entry
+ i
))
904 // No further substititions to be had update the dictionary
905 for (i
+= entry
; --i
>= entry
; ) {
906 if (!newSub(c
, i
, lastEntry
- i
))
913 static Boolean
appendArgumentList(ParseContext
*c
)
917 c
->fRetCode
= kR3InternalNotRemangled
;
918 // Setup the output entry array
920 for (i
= 0; i
< num
; ) {
921 i
= appendType(c
, i
);
926 // First pass output uncompressed types
927 for (i
= 0, num
= c
->fP
.fNumO
; i
< num
; i
++) {
930 bP
= &c
->fOutEntries
[i
];
933 continue; // Pseudo entry do not output;
937 case kNTSubstitute
: appendSub(c
, bP
->fLen
); break;
939 case kNTSubQualClass
:
941 appendSub(c
, bP
->fLen
);
942 i
++; bP
= &c
->fOutEntries
[i
];
943 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
948 if (bP
->fQualified
) {
950 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
954 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
958 char numbuf
[16]; // Bigger than MAX_LONG + 3
960 len
= snprintf(numbuf
, sizeof(numbuf
),
961 "A%lu_", (unsigned long) bP
->fFundTypeID
);
962 appendNStr(c
, numbuf
, len
);
967 case kNTDeclarator
: appendChar(c
, (int) bP
->fFundTypeID
); break;
968 case kNTMethod
: appendChar(c
, 'M'); break;
969 case kNTFunction
: appendChar(c
, 'F'); break;
970 case kNTFuncEnd
: appendChar(c
, 'E'); break;
975 return false; // Fatal errors
979 // Successful remangle
980 c
->fRetCode
= kR3Remangled
;
988 // <count> ::= <digit> <digit>*
989 static Boolean
parse_count(ParseContext
*c
, int *countP
)
995 if (ch
< '1' || ch
> '9')
998 count
= strtol(c
->fP
.fInChar
, (char **) &c
->fP
.fInChar
, 10);
1006 // "n" <index> can cause the following type to be ambiguous as
1008 // "n" <digit> <counted_class_name> ...
1009 // | "n" <digit> <digit> '_' <declarator> <fund_type_id> ...
1010 // However as the class '_Pc' is probably going to be unlikely a quick
1011 // check to see if the next field is a valid type would probably clear
1012 // up the abiguity for the majority of cases.
1014 // <index> ::= <digit> | <digit> <digit> <digit>* "_"
1015 static Boolean
parse_index(ParseContext
*c
, int *indexP
)
1017 CheckPoint chk
= *checkPoint(c
);
1024 if ( !('0' <= ch0
&& ch0
<= '9') )
1026 if ('0' <= ch1
&& ch1
<= '9') {
1027 if (!parse_count(c
, &index
))
1029 if (isNext(c
, '_')) {
1030 // @@@ gvdl: Ambiguity check one day
1036 resetTo(c
, &chk
); // Must be the one digit case
1052 // <qualifier> ::= "C" ; const
1054 // | "u" ; restrict (C99) unsupported
1055 // | "G" ; struct/union/enum ; unused in gcc3
1056 static Boolean
parse_qualifiers(ParseContext
*c
)
1058 BaseTypeData
*bP
= c
->fCurBaseP
;
1062 bP
->fConst
= true; // "C" ; const
1063 else if (isNext(c
, 'V'))
1064 bP
->fVolatile
= true; // "V" ; volatile
1065 else if (isNext(c
, 'u'))
1066 return false; // "u" ; restrict (C99)
1067 else if (isNext(c
, 'G'))
1068 continue; // "G" ; struct/union/enum ; unused
1076 // Assumes we have an open fInEntry in fCurBaseP
1077 static Boolean
duplicateEntries(ParseContext
*c
, int start
, int numE
)
1079 BaseTypeData
*bIP
= &c
->fInEntries
[start
]; // First duplicate entry
1080 BaseTypeData
*bP
= c
->fCurBaseP
;
1083 // Duplicating a method
1084 if (kNTMethod
== bIP
->fType
) {
1085 bP
--; // Strip leading 'P' declarator
1091 // do we have room available for duplication
1092 if (c
->fP
.fNumI
+ numE
>= MAX_ENTRIES
)
1095 // Copy the parse entries over
1096 bcopy(bIP
, bP
, (numE
+ 1) * sizeof(*bP
));
1098 // Now we have to duplicate the types for the new entry
1099 for (i
= 0; i
< c
->fP
.fNumT
; i
++) {
1100 TypeData
*tP
= &c
->fTypeList
[i
];
1101 if (tP
->fStartEntry
< start
)
1103 else if (tP
->fStartEntry
<= start
+ numE
)
1104 dupType(c
, tP
, bP
- bIP
);
1109 c
->fP
.fNumI
+= numE
;
1116 // Must have a valid c->fCurBaseP pointer on entry
1117 // <class_name> ::= <counted_class_name> ; plain class name
1118 // | "Q" <qualified_name> ; qualified name
1119 // | "B" <index> ; compressed name
1120 // | "K" <qualified_name> ; ignored and illegal
1121 // <qualified_name> ::= <q_count> <counted_class_name>+
1122 // <q_count> ::= <digit> | "_" <digit> <digit>* "_"
1123 // <counted_class_name> ::= <count> <name>
1124 // <name> ::= <char> <char>*
1126 parse_class_name(ParseContext
*c
)
1128 BaseTypeData
*bP
= c
->fCurBaseP
;
1129 const char *typeId
= c
->fP
.fInChar
;
1133 if (parse_count(c
, &count
)) {
1135 // <counted_class_name> ::= <count> <name>
1136 if (!hasRemain(c
, count
))
1139 bP
->fType
= kNTClass
;
1142 bP
->fFundTypeID
= typeId
;
1143 bP
->fLen
= c
->fP
.fInChar
- typeId
;
1146 switch (peekNext(c
)) {
1153 // | "Q" <qualified_name> ; qualified name
1154 // <qualified_name> ::= <q_count> <counted_class_name>+
1155 // <q_count> ::= <digit> | "_" <digit> <digit>* "_"
1156 if ('_' == (ch
= getNext(c
))) {
1158 if (!parse_count(c
, &q_count
) || !isNext(c
, '_'))
1161 else if ('1' <= ch
&& ch
<= '9')
1167 typeId
= c
->fP
.fInChar
;
1168 bP
->fType
= kNTClass
;
1169 bP
->fQualified
= true;
1171 for (i
= 0; i
< q_count
; i
++) {
1172 if (parse_count(c
, &count
))
1177 bP
->fLen
= c
->fP
.fInChar
- typeId
;
1178 bP
->fFundTypeID
= typeId
;
1186 if (!parse_index(c
, &count
) || count
>= c
->fP
.fNumB
)
1189 if (!duplicateEntries(c
, c
->fBDict
[count
].fStartEntry
,
1190 c
->fBDict
[count
].fNumEntries
))
1199 if (newBDict(c
, bP
- c
->fInEntries
, 1))
1206 // <fund_type_id> ::= <class_name>
1214 // | "r" ; long double
1218 // | "x" ; long long
1219 // | "G" <count> ; ???
1220 static Boolean
parse_fund_type_id(ParseContext
*c
)
1222 BaseTypeData
*bP
= c
->fCurBaseP
;
1224 if (!parse_class_name(c
)) {
1225 // Use the TypeID pointer as a 4 character buffer
1226 char ch
= peekNext(c
);
1228 if (bP
->fSigned
&& 'c' != ch
)
1229 goto abandonParse
; // illegal only chars can be signed
1233 case 'b': case 'd': case 'f': case 'v': case 'w': // No map types
1236 case 'c': // character
1237 if (bP
->fSigned
) ch
= 'a';
1238 else if (bP
->fUnsigned
) ch
= 'h';
1240 case 'e': // ellipsis
1244 if (bP
->fUnsigned
) ch
= 'j';
1247 if (bP
->fUnsigned
) ch
= 'm';
1249 case 'r': // long double
1253 if (bP
->fUnsigned
) ch
= 't';
1255 case 'x': // long long
1256 if (bP
->fUnsigned
) ch
= 'y';
1259 case 'G': // Don't understand "G"
1264 advance(c
, 1); // Consume the input character
1265 bP
->fFundTypeID
= (void *) (int) ch
;
1267 bP
->fType
= kNTBuiltIn
;
1276 // <arg_type> ::= <type> [ "n" <index> ]
1277 // | "N" <count> <pos> ; Not implemented
1278 // | "T" <index> ; Not implemented
1279 static Boolean
parse_arg_type(ParseContext
*c
)
1281 // Don't bother to check point as parse_argument_types does it for us
1286 typeP
= &c
->fTypeList
[c
->fP
.fNumT
]; // Cache type for later repeat
1290 // Now check for a repeat count on this type
1291 if (isNext(c
, 'n')) {
1292 if (!parse_index(c
, &repeat
))
1296 c
->fCurBaseP
= newIn(c
); // Duplicate requires a fresh type
1299 if (!duplicateEntries(c
, typeP
->fStartEntry
, typeP
->fNumEntries
))
1307 // <argument_types> ::= # Empty
1309 static Boolean
parse_argument_types(ParseContext
*c
)
1314 if (!parse_arg_type(c
))
1317 while (!atEnd(c
) && parse_arg_type(c
))
1322 // Not a counted class name so reset to checkPoint
1327 // leaf function so the copy aside buffer isn't on the primary
1330 rotateFunction(ParseContext
*c
, int argStart
, int retStart
)
1332 char returnTypeBuffer
[MAX_RETURN_BUFFER
];
1335 char *sArgP
, *sRetP
;
1338 TypeData
*argTP
= &c
->fTypeList
[argStart
];
1339 TypeData
*retTP
= &c
->fTypeList
[retStart
];
1341 // Rotate around the entries first
1342 numArg
= retTP
->fStartEntry
- argTP
->fStartEntry
;
1343 numRet
= retTP
->fNumEntries
;
1344 lenArg
= numArg
* sizeof(BaseTypeData
);
1345 lenRet
= numRet
* sizeof(BaseTypeData
);
1347 // Copy the return type into a buffer
1348 if (lenRet
> sizeof(returnTypeBuffer
))
1351 sArgP
= (char *) (&c
->fInEntries
[argTP
->fStartEntry
]);
1352 sRetP
= (char *) (&c
->fInEntries
[retTP
->fStartEntry
]);
1354 bcopy(sRetP
, returnTypeBuffer
, lenRet
);
1355 bcopy(sArgP
, sArgP
+ lenRet
, lenArg
);
1356 bcopy(returnTypeBuffer
, sArgP
, lenRet
);
1358 // Retarget the argument and return types for the new entry positions
1361 numArg
= retStart
- argStart
;
1362 numRet
= c
->fP
.fNumT
- retStart
;
1363 for (i
= 0; i
< numArg
; i
++)
1364 c
->fTypeList
[argStart
+i
].fStartEntry
+= lenRet
;
1365 for (i
= 0; i
< numRet
; i
++)
1366 c
->fTypeList
[retStart
+i
].fStartEntry
-= lenArg
;
1368 // Rotate the BDictionary
1369 for (i
= 0; i
< c
->fP
.fNumB
; i
++) {
1370 TypeData
*bDP
= &c
->fBDict
[i
];
1371 int start
= bDP
->fStartEntry
;
1373 if (start
>= argTP
->fStartEntry
)
1374 bDP
->fStartEntry
= start
+ lenRet
;
1375 else if (start
>= retTP
->fStartEntry
)
1376 bDP
->fStartEntry
= start
- lenArg
;
1379 // Finally rotate the retargeted type structures.
1380 lenArg
= numArg
* sizeof(TypeData
);
1381 lenRet
= numRet
* sizeof(TypeData
);
1383 sArgP
= (char *) (&c
->fTypeList
[argStart
]);
1384 sRetP
= (char *) (&c
->fTypeList
[retStart
]);
1386 bcopy(sRetP
, returnTypeBuffer
, lenRet
);
1387 bcopy(sArgP
, sArgP
+ lenRet
, lenArg
);
1388 bcopy(returnTypeBuffer
, sArgP
, lenRet
);
1393 // <function_type> ::= "F" <argument_types> "_" <type>
1394 static Boolean
parse_function_type(ParseContext
*c
, Boolean forMethod
)
1396 TypeData
*bDictP
= 0;
1397 BaseTypeData
*bP
= c
->fCurBaseP
;
1399 int argTypeStart
, retTypeStart
;
1402 bDictP
= newBDict(c
, c
->fP
.fNumI
-1, 0);
1407 if (!isNext(c
, 'F'))
1410 bP
->fType
= kNTFunction
;
1412 // Note that the argument types will advance the Entry list
1413 argTypeStart
= c
->fP
.fNumT
;
1414 if (!parse_argument_types(c
))
1417 if (!isNext(c
, '_'))
1420 // Parse the return type
1421 retTypeStart
= c
->fP
.fNumT
;
1425 // gcc3 puts the return code just after the 'F' declaration
1426 // as this impacts the order of the compression I need to rotate
1427 // the return type and the argument types.
1428 if (!rotateFunction(c
, argTypeStart
, retTypeStart
))
1432 bDictP
->fNumEntries
= c
->fP
.fNumI
- bDictP
->fStartEntry
;
1440 // To convert 2.95 method to a 3.0 method I need to prune the
1441 // first argument of the function type out of the parse tree.
1442 static Boolean
cleanMethodFunction(ParseContext
*c
, int type
)
1444 TypeData
*typeP
, *startTP
, *endTP
;
1446 int i
, thisStart
, thisEnd
, thisLen
, funcRemain
;
1448 // Get pointer for the return value's type.
1449 startTP
= &c
->fTypeList
[type
+1];
1450 endTP
= &c
->fTypeList
[c
->fP
.fNumT
];
1452 // Now look for the first type that starts after the return type
1453 thisEnd
= startTP
->fStartEntry
+ startTP
->fNumEntries
;
1454 for (startTP
++; startTP
< endTP
; startTP
++)
1455 if (startTP
->fStartEntry
>= thisEnd
)
1458 if (startTP
>= endTP
) {
1459 c
->fRetCode
= kR3InternalNotRemangled
;
1460 return false; // Internal error: should never happen
1463 // We now have a pointer to the 1st argument in the input list
1464 // we will need to excise the entries from the input list and don't forget
1465 // to remove the associated types from the type list.
1467 thisLen
= startTP
->fNumEntries
;
1468 thisStart
= startTP
->fStartEntry
;
1469 thisEnd
= thisStart
+ thisLen
;
1470 funcRemain
= c
->fP
.fNumI
- thisEnd
;
1471 bP
= &c
->fInEntries
[thisStart
];
1473 // If we have no arguments then replace the pointer with a void
1475 c
->fP
.fNumI
-= (thisLen
- 1);
1477 bP
->fFundTypeID
= (void *) (int) 'v'; // Void arg list
1479 bP
->fType
= kNTBuiltIn
;
1481 // Update the type entry for the void argument list
1482 startTP
->fNumEntries
= 1;
1486 // Move the argument list down to replace the 'this' pointer
1487 bcopy(bP
+ thisLen
, bP
, funcRemain
* sizeof(*bP
));
1488 c
->fP
.fNumI
-= thisLen
;
1490 // And remove the 'this' pointers type
1492 // First walk over all of the types that have to be removed
1493 for (typeP
= startTP
+ 1; typeP
< endTP
; typeP
++)
1494 if (typeP
->fStartEntry
>= thisEnd
)
1497 if (typeP
>= endTP
) {
1498 c
->fRetCode
= kR3InternalNotRemangled
;
1499 return false; // Internal error Can't be a void argument list.
1502 bcopy(typeP
, startTP
, (char *) endTP
- (char *) typeP
);
1504 c
->fP
.fNumT
-= typeP
- startTP
;
1505 endTP
= &c
->fTypeList
[c
->fP
.fNumT
];
1506 for (typeP
= startTP
; typeP
< endTP
; typeP
++)
1507 typeP
->fStartEntry
-= thisLen
;
1509 // Finally we can retarget the BDictionary lists
1510 for (i
= 0; i
< c
->fP
.fNumB
; i
++) {
1511 TypeData
*bDP
= &c
->fBDict
[i
];
1512 int start
= bDP
->fStartEntry
;
1514 if (start
< thisStart
)
1516 if (start
>= thisEnd
)
1519 bDP
->fStartEntry
= start
- thisLen
;
1525 // <method_type> ::= "M" <class_name> <function_type>
1527 // Note this is a very bad function. Gcc3 doesn't doesn't use pointer that
1528 // is immediately before this entry. We will have to delete the 'P' declarator
1529 // that is before the method declaration.
1530 // We will also have to prune the first type in the argument list as Gcc3
1531 // doesn't register the 'this' pointer within the function list.
1532 static Boolean
parse_method_type(ParseContext
*c
)
1538 bDictP
= newBDict(c
, c
->fP
.fNumI
-2, 0);
1542 // Replace 'P' declarator
1544 bP
= c
->fCurBaseP
- 1;
1546 if (!isNext(c
, 'M'))
1549 if (bP
->fFundTypeID
!= (void *) (int) 'P')
1552 // Replace the previous 'Pointer' declarator
1553 bP
->fType
= kNTMethod
;
1554 bP
->fFundTypeID
= NULL
;
1557 // Grab the method's 'this' type specification
1558 typeP
= newType(c
, c
->fP
.fNumI
);
1559 if (!newIn(c
) || !typeP
)
1562 if (!parse_class_name(c
))
1564 typeP
->fNumEntries
= c
->fP
.fNumI
- typeP
->fStartEntry
;
1566 // Grab the <function_type> specifier
1567 typeP
= newType(c
, c
->fP
.fNumI
);
1568 if (!newIn(c
) || !typeP
)
1571 if (!parse_function_type(c
, /* forMethod */ true))
1574 if (!cleanMethodFunction(c
, typeP
- c
->fTypeList
))
1576 typeP
->fNumEntries
= c
->fP
.fNumI
- typeP
->fStartEntry
;
1578 // Finally update the dictionary with the M & 'this'
1579 bDictP
->fNumEntries
= c
->fP
.fNumI
- bDictP
->fStartEntry
;
1587 static Boolean
emitQualifiers(ParseContext
*c
)
1589 BaseTypeData
*bP
= c
->fCurBaseP
;
1591 if (bP
->fVolatile
|| bP
->fConst
) {
1592 Boolean isConst
, isVolatile
, isSigned
, isUnsigned
;
1594 isVolatile
= bP
->fVolatile
;
1595 isConst
= bP
->fConst
;
1596 isSigned
= bP
->fSigned
;
1597 isUnsigned
= bP
->fUnsigned
;
1598 bP
->fConst
= bP
->fVolatile
= bP
->fSigned
= bP
->fUnsigned
= 0;
1601 bP
->fType
= kNTDeclarator
;
1602 bP
->fFundTypeID
= (void *) (int) 'V';
1609 bP
->fType
= kNTDeclarator
;
1610 bP
->fFundTypeID
= (void *) (int) 'K';
1616 bP
->fSigned
= isSigned
;
1617 bP
->fUnsigned
= isUnsigned
;
1624 // <base_type> ::= <function_type> ; function
1625 // | <method_type> ; method
1626 // | <type_qualifier>* <fund_type_id>
1627 // <type_qualifier> ::= "S" ; signed (chars only)
1628 // | "U" ; unsigned (any integral type)
1629 // | "J" ; __complex
1631 static Boolean
parse_base_type(ParseContext
*c
)
1633 if ('F' == peekNext(c
)) {
1634 if (!parse_function_type(c
, /* forMethod */ false))
1637 else if ('M' == peekNext(c
)) {
1638 if (!parse_method_type(c
))
1642 // | <type_qualifier>* <fund_type_id>
1643 BaseTypeData
*bP
= c
->fCurBaseP
;
1646 // <type_qualifier> ::= "S" ; signed (chars only)
1647 { bP
->fSigned
= true; continue; }
1648 else if (isNext(c
, 'U'))
1649 // | "U" ; unsigned (any integral type)
1650 { bP
->fUnsigned
= true; continue; }
1651 else if (isNext(c
, 'C'))
1653 // <qualifier> ::= "C" ; const
1654 { bP
->fConst
= true; continue; }
1655 else if (isNext(c
, 'V'))
1657 { bP
->fVolatile
= true; continue; }
1658 else if (charNext(c
, "Ju"))
1659 goto abandonParse
; // Don't support these qualifiers
1660 // | "J" ; __complex
1661 // | "u" ; restrict (C99)
1666 if (!emitQualifiers(c
))
1669 if (!parse_fund_type_id(c
))
1678 // Use the top SDict as a stack of declarators.
1679 // parses <declarator>*
1680 // <declarator> ::= "P" ; pointer
1681 // | "p" ; pointer (but never occurs?)
1682 // | "R" ; reference (&)
1683 // | "A" <count> ; array
1688 // As a side-effect the fCurBaseP is setup with any qualifiers on exit
1689 static Boolean
parse_declarators(ParseContext
*c
)
1694 // Note we MUST go through the for loop at least once
1695 for (count
= 0; ; count
++) {
1696 const char *curDecl
;
1702 // <declarator> ::= <qualifier> production
1703 if (!parse_qualifiers(c
) || !emitQualifiers(c
))
1706 dP
= c
->fCurBaseP
; // Find the current base type pointer
1708 curDecl
= c
->fP
.fInChar
;
1710 switch (peekNext(c
)) {
1712 case 'P': case 'p': case 'R':
1713 // <declarator> ::= "P" ; pointer
1714 // | "p" ; pointer (but never occurs?)
1715 // | "R" ; reference (&)
1717 dP
->fType
= kNTDeclarator
;
1721 if ('p' == ch
) ch
= 'P';
1722 dP
->fFundTypeID
= (void *) (int) ch
;
1724 continue; // Go around again
1727 // | "A" <count> ; array
1728 dP
->fType
= kNTArray
;
1730 advance(c
, 1); curDecl
++;
1732 strtoul(curDecl
, (char **) &c
->fP
.fInChar
, 10);
1735 dP
->fFundTypeID
= curDecl
;
1737 continue; // Go around again
1740 // | "T" <index> Unsupported
1741 // | "O" <count> Unsupported
1758 // <type> ::= <declarator>* <base_type>
1759 static Boolean
parse_type(ParseContext
*c
)
1761 CheckPoint chk
= *checkPoint(c
);
1762 TypeData
*typeP
= newType(c
, c
->fP
.fNumI
);
1766 // As a side-effect the fCurBaseP is setup with any qualifiers on exit
1767 if (!parse_declarators(c
))
1770 // Merge the last qualifiers into the base type
1771 if (!parse_base_type(c
) || kNTUndefined
== c
->fCurBaseP
->fType
)
1774 typeP
->fNumEntries
= c
->fP
.fNumI
- typeP
->fStartEntry
;
1782 // <function_name> ::= <char> <char>*
1783 // No need to check point as an invalid function name is fatal
1784 // Consumes trailing "__".
1786 parse_function_name(ParseContext
*c
)
1790 while ( (ch
= peekNext(c
)) )
1793 if ('_' == ch
&& '_' == peekNext(c
)) {
1796 } while ('_' == peekNext(c
));
1804 // <opinfo> ::= "type" <type>
1806 // | <opname> "__" ; Implies null function name
1808 // <opname> ::= "aa" # && ==> "aa"
1809 // | "aad" # &= ==> "aN"
1810 // | "ad" # & ==> "ad"
1811 // | "adv" # /= ==> "dV"
1812 // | "aer" # ^= ==> "eO"
1813 // | "als" # <<= ==> "lS"
1814 // | "amd" # %= ==> "rM"
1815 // | "ami" # -= ==> "mI"
1816 // | "aml" # *= ==> "mL
1817 // | "aor" # |= ==> "oR
1818 // | "apl" # += ==> "pL
1819 // | "ars" # >>= ==> "rS
1820 // | "as" # = ==> "aS
1821 // | "cl" # () ==> "cl
1822 // | "cm" # , ==> "cm
1823 // | "cn" # ?: ==> "qu
1824 // | "co" # ~ ==> "co
1825 // | "dl" # delete ==> "dl
1826 // | "dv" # / ==> "dv
1827 // | "eq" # == ==> "eq
1828 // | "er" # ^ ==> "eo
1829 // | "ge" # >= ==> "ge
1830 // | "gt" # > ==> "gt
1831 // | "le" # <= ==> "le
1832 // | "ls" # << ==> "ls
1833 // | "lt" # < ==> "lt
1834 // | "md" # % ==> "rm
1835 // | "mi" # - ==> "mi
1836 // | "ml" # * ==> "ml
1837 // | "mm" # -- ==> "mm
1838 // | "mn" # <? ==> "????????????????
1839 // | "mx" # >? ==> "????????????????
1840 // | "ne" # != ==> "ne
1841 // | "nt" # ! ==> "nt
1842 // | "nw" # new ==> "nw
1843 // | "oo" # || ==> "oo"
1844 // | "or" # | ==> "or
1845 // | "pl" # + ==> "pl
1846 // | "pp" # ++ ==> "pp
1847 // | "rf" # -> ==> "pt
1848 // | "rm" # ->* ==> "pm
1849 // | "rs" # >> ==> "rs
1850 // | "sz" # sizeof ==> "sz
1851 // | "vc" # [] ==> "ix
1852 // | "vd" # delete[] ==> "da
1853 // | "vn" # new[] ==> "na
1854 static struct opMap
{
1855 const char *op295
, *op3
;
1857 {"aad", "aN" }, {"adv", "dV" }, {"aer", "eO" }, {"als", "lS" },
1858 {"amd", "rM" }, {"ami", "mI" }, {"aml", "mL" }, {"aor", "oR" },
1859 {"apl", "pL" }, {"ars", "rS" }, {"aa", "aa" }, {"ad", "ad" },
1860 {"as", "aS" }, {"cl", "cl" }, {"cm", "cm" }, {"cn", "qu" },
1861 {"co", "co" }, {"dl", "dl" }, {"dv", "dv" }, {"eq", "eq" },
1862 {"er", "eo" }, {"ge", "ge" }, {"gt", "gt" }, {"le", "le" },
1863 {"ls", "ls" }, {"lt", "lt" }, {"md", "rm" }, {"mi", "mi" },
1864 {"ml", "ml" }, {"mm", "mm" }, {"mn", NULL
}, {"mx", NULL
},
1865 {"ne", "ne" }, {"nt", "nt" }, {"nw", "nw" }, {"oo", "oo" },
1866 {"or", "or" }, {"pl", "pl" }, {"pp", "pp" }, {"rf", "pt" },
1867 {"rm", "pm" }, {"rs", "rs" }, {"sz", "sz" }, {"vc", "ix" },
1868 {"vd", "da" }, {"vn", "na" },
1871 static Boolean
parse_opinfo(ParseContext
*c
, const char **opInfoP
)
1873 CheckPoint chk
= *checkPoint(c
);
1878 if ('a' == (ch
= peekNext(c
))) {
1881 else if (strNext(c
, "type")) {
1884 else if (retard(c
, 4) && strNext(c
, "____op")) {
1885 // @@@ gvdl: check this out it may change
1886 // <opinfo> ::= "__op" <type>
1890 // Failed till now so reset and see if we have an operator
1893 // quick check to see if we may have an operator
1894 if (!strrchr("acdeglmnoprsv", peekNext(c
)))
1898 for (i
= 0; i
< sizeof(opMapTable
)/sizeof(opMapTable
[0]); i
++) {
1899 if (strNext(c
, opMapTable
[i
].op295
)) {
1900 op
= opMapTable
[i
].op3
;
1907 if (!strNext(c
, "__")) // Trailing underbars
1918 // <signature> ::= <qualifier>* <s_element> <argument_types>
1919 // <s_element> ::= <class_name>
1920 // | "K" <qualified_name>
1922 // | "F" <argument_types> [ "_" <return_type> ]
1923 // <return_type> ::= <type>
1924 // Treat the prefix's s_element as a full type
1926 parse_signature(ParseContext
*c
,
1927 const char *func
, int funcLen
, const char *op
)
1932 Boolean isFunction
= false;
1934 if (isNext(c
, 'F')) {
1935 // | "F" <argument_types> [ "_" <return_type> ]
1937 char numbuf
[16]; // Bigger than MAX_INT + 4
1943 len
= snprintf(numbuf
, sizeof(numbuf
), "__Z%d", funcLen
);
1945 appendNStr(c
, numbuf
, len
);
1946 appendNStr(c
, func
, funcLen
);
1948 else if (isNext(c
, 'S')) {
1956 // See if we can find a qualified class reference
1957 tP
= newType(c
, c
->fP
.fNumI
);
1965 // Parse any qualifiers, store results in *fCurBaseP
1967 if (!parse_qualifiers(c
))
1970 if (!parse_class_name(c
))
1973 bP
= c
->fCurBaseP
; // class name may have redifined current
1974 tP
->fNumEntries
= c
->fP
.fNumI
- tP
->fStartEntry
;
1976 APPENDSTR(c
, "__ZN");
1977 decodeQual(bP
, &qualLen
, &qual
);
1979 appendNStr(c
, qual
, qualLen
);
1980 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
1983 char numbuf
[16]; // Bigger than MAX_INT + 1
1986 len
= snprintf(numbuf
, sizeof(numbuf
), "%d", funcLen
);
1987 appendNStr(c
, numbuf
, len
);
1988 appendNStr(c
, func
, funcLen
);
1993 // No function & no op means constructor choose one of C1 & C2
2000 appendChar(c
, 'v'); // void argument list
2001 c
->fRetCode
= kR3Remangled
;
2005 c
->fCurBaseP
= NULL
;
2006 if (!parse_argument_types(c
))
2010 if (isNext(c
, '_')) {
2011 // && !parse_type(c) @@@ gvdl: Unsupported return
2012 c
->fRetCode
= kR3InternalNotRemangled
;
2020 // OK we have a complete and successful parse now output the
2022 return appendArgumentList(c
);
2028 // <mangled_name> ::= <prefix> [ <signature> ]
2029 // <prefix> ::= [ "_GLOBAL_" [ID] "__" ] <function_name> "__" [ <opinfo> ]
2030 static Boolean
parse_mangled_name(ParseContext
*c
)
2033 CheckPoint dubBarChk
;
2037 if (strNext(c
, "_GLOBAL_")) { // Is this GLOBAL static constructor?
2038 // gvdl: can't deal with _GLOBAL_
2039 c
->fRetCode
= kR3InternalNotRemangled
;
2040 return false; // Can't deal with these
2043 func
= c
->fP
.fInChar
;
2044 for (chk
= *checkPoint(c
); ; resetTo(c
, &dubBarChk
)) {
2046 const char *op
= NULL
;
2048 if (!parse_function_name(c
))
2050 dubBarChk
= *checkPoint(c
);
2052 // Note that the opInfo may be earlier than the curDoubleBar
2053 // in which case the function name may need to be shrunk later on.
2054 (void) parse_opinfo(c
, &op
);
2057 goto abandonParse
; // No Signature?
2059 funcLen
= inCharFromCheck(c
, &dubBarChk
) - func
- 2;
2060 if (parse_signature(c
, func
, funcLen
, op
))
2063 if (kR3NotRemangled
!= c
->fRetCode
)
2066 // If no error then try again maybe another '__' exists
2074 // <gnu_special> ::= ("_._" | "_$_" ) <class_name> ; destructor
2075 // | "__vt_" <class_name> ; virtual table
2076 // | "_" <class_name> ("."|"$") <varname>
2077 static Boolean
parse_gnu_special(ParseContext
*c
)
2079 CheckPoint chk
= *checkPoint(c
);
2080 BaseTypeData
*bP
= newIn(c
);
2085 // What do the intel desctructors look like
2086 if (strNext(c
, "_._") || strNext(c
, "_$_") ) // Is this a destructor
2088 if (!parse_class_name(c
) || !atEnd(c
))
2090 APPENDSTR(c
, "__ZN");
2091 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2092 APPENDSTR(c
, "D2Ev");
2093 c
->fRetCode
= kR3Remangled
;
2096 else if (strNext(c
, "__vt_")) // Is it's a vtable?
2098 if (!parse_class_name(c
) || !atEnd(c
))
2101 APPENDSTR(c
, "__ZTV");
2102 if (kNTClass
!= bP
->fType
)
2104 else if (bP
->fQualified
) {
2106 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2110 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2112 c
->fRetCode
= kR3Remangled
;
2115 else if (isNext(c
, '_')) // Maybe it's a variable
2117 const char *varname
;
2119 char numbuf
[16]; // Bigger than MAX_INT + 1
2121 if (!parse_class_name(c
)) // Loads up the bP structure
2124 if (!isNext(c
, '.') && !isNext(c
, '$'))
2127 // Parse the variable name now.
2128 varname
= c
->fP
.fInChar
;
2129 if (atEnd(c
) || !isValidFirstChar(getNext(c
)))
2133 if (!isValidChar(getNext(c
)))
2136 varlen
= c
->fP
.fInChar
- varname
;
2137 len
= snprintf(numbuf
, sizeof(numbuf
), "%d", varlen
);
2139 APPENDSTR(c
, "__ZN");
2140 appendNStr(c
, bP
->fFundTypeID
, bP
->fLen
);
2142 appendNStr(c
, numbuf
, len
);
2143 appendNStr(c
, varname
, varlen
);
2146 c
->fRetCode
= kR3Remangled
;
2150 // Oh well it is none of those so give up but reset scan
2156 // <special_or_name> ::= <gnu_special>
2158 static Boolean
parse_special_or_name(ParseContext
*c
)
2163 res
= (parse_gnu_special(c
) || parse_mangled_name(c
));
2164 appendChar(c
, '\0');
2169 Rem3Return
rem3_remangle_name(char *gcc3
, int *gcc3size
, const char *gcc295
)
2175 if (!gcc295
|| !gcc3
|| !gcc3size
)
2176 return kR3BadArgument
;
2178 size
= strlen(gcc295
);
2180 return kR3NotRemangled
; // Not a valid C++ symbol
2181 else if (*gcc295
!= '_')
2182 return kR3NotRemangled
; // no leading '_', not valid
2184 c
= (ParseContext
*) malloc(sizeof(*c
));
2186 return kR3InternalNotRemangled
;
2187 bzero(c
, sizeof(*c
));
2190 c
->fInStr
= gcc295
+ 1; // Strip leading '_'
2191 c
->fP
.fInChar
= c
->fInStr
;
2193 c
->fOutStrEnd
= gcc3
+ *gcc3size
;
2196 c
->fRetCode
= kR3NotRemangled
;
2197 (void) parse_special_or_name(c
);
2199 result
= c
->fRetCode
;
2200 if (kR3Remangled
== result
) {
2201 if (c
->fOutChar
> c
->fOutStrEnd
)
2202 result
= kR3BufferTooSmallRemangled
;
2203 *gcc3size
= c
->fOutChar
- gcc3
- 1; // Remove nul from len