Improve name demangling, add 'demangle symbol' option.
This commit is contained in:
parent
0350d2fd62
commit
0395a4fba4
|
@ -54,10 +54,11 @@ Usage
|
|||
Specmaker is a command line tool. Running it with no arguments or passing
|
||||
it '-h' on the command line lists the available options:
|
||||
|
||||
Usage: specmaker [options] -d dll
|
||||
Usage: specmaker [options] [-d dll | -S sym]
|
||||
|
||||
Options:
|
||||
-d dll Use dll for input file (mandatory)
|
||||
-S sym Demangle C++ symbol 'sym' and exit
|
||||
-h Display this help message
|
||||
-I dir Look for prototypes in 'dir' (implies -c)
|
||||
-o name Set the output dll name (default: dll)
|
||||
|
@ -75,10 +76,26 @@ Options:
|
|||
Basic options
|
||||
-------------
|
||||
|
||||
OPTION: -S sym Demangle C++ symbol 'sym' and exit
|
||||
|
||||
The -S option is used to demangle a C++ symbol as it appears in the exports
|
||||
section of a dll. This is useful for testing the demangler or implementing
|
||||
C++ functions in partially implemented wine DLLS. As an example:
|
||||
|
||||
specmaker -S "??3@YAXPAX@Z"
|
||||
|
||||
Gives:
|
||||
|
||||
void __cdecl _global_operator_delete_1(void * arg0)
|
||||
|
||||
Which is enough information to begin implementing the function.
|
||||
|
||||
|
||||
OPTION: -d dll Use dll for input file (mandatory)
|
||||
|
||||
The -d option tells specmaker which DLL you want to create a .spec file
|
||||
for. You *must* give this option.
|
||||
for. You *must* give this option, unless you are demangling a single symbol
|
||||
using the -S argument.
|
||||
|
||||
16 bit DLL's are not currently supported (Note that Winelib is intended
|
||||
only for Win32 programs).
|
||||
|
|
|
@ -38,6 +38,14 @@ static void do_input (const char *arg)
|
|||
}
|
||||
|
||||
|
||||
static void do_demangle (const char *arg)
|
||||
{
|
||||
globals.do_demangle = 1;
|
||||
globals.do_code = 1;
|
||||
globals.input_name = arg;
|
||||
}
|
||||
|
||||
|
||||
static void do_code (void)
|
||||
{
|
||||
globals.do_code = 1;
|
||||
|
@ -108,6 +116,7 @@ struct option
|
|||
|
||||
static const struct option option_table[] = {
|
||||
{"-d", 1, do_input, "-d dll Use dll for input file (mandatory)"},
|
||||
{"-S", 1, do_demangle, "-S sym Demangle C++ symbol 'sym' and exit"},
|
||||
{"-h", 0, do_usage, "-h Display this help message"},
|
||||
{"-I", 1, do_include, "-I dir Look for prototypes in 'dir' (implies -c)"},
|
||||
{"-o", 1, do_name, "-o name Set the output dll name (default: dll)"},
|
||||
|
@ -127,7 +136,7 @@ static const struct option option_table[] = {
|
|||
void do_usage (void)
|
||||
{
|
||||
const struct option *opt;
|
||||
printf ("Usage: specmaker [options] -d dll\n\nOptions:\n");
|
||||
printf ("Usage: specmaker [options] [-d dll | -S sym]\n\nOptions:\n");
|
||||
for (opt = option_table; opt->name; opt++)
|
||||
printf (" %s\n", opt->usage);
|
||||
puts ("\n");
|
||||
|
@ -180,7 +189,7 @@ static void parse_options (char *argv[])
|
|||
ptr++;
|
||||
}
|
||||
|
||||
if (globals.do_code && !globals.directory)
|
||||
if (!globals.do_demangle && globals.do_code && !globals.directory)
|
||||
fatal ("-I must be used if generating code");
|
||||
|
||||
if (!globals.input_name)
|
||||
|
@ -205,14 +214,25 @@ int main (int argc, char *argv[])
|
|||
|
||||
parse_options (argv);
|
||||
|
||||
memset (&symbol, 0, sizeof (parsed_symbol));
|
||||
|
||||
if (globals.do_demangle)
|
||||
{
|
||||
int result;
|
||||
globals.uc_dll_name = "";
|
||||
symbol.symbol = strdup(globals.input_name);
|
||||
result = symbol_demangle (&symbol);
|
||||
output_prototype (stdout, &symbol);
|
||||
fputc ('\n', stdout);
|
||||
return result ? 1 : 0;
|
||||
}
|
||||
|
||||
dll_open (globals.input_name);
|
||||
|
||||
output_spec_preamble ();
|
||||
output_header_preamble ();
|
||||
output_c_preamble ();
|
||||
|
||||
memset (&symbol, 0, sizeof (parsed_symbol));
|
||||
|
||||
while ((symbol.symbol = dll_next_symbol ()))
|
||||
{
|
||||
count++;
|
||||
|
|
|
@ -76,19 +76,46 @@ int symbol_demangle (parsed_symbol *sym)
|
|||
case '2': function_name = strdup ("operator_new"); break;
|
||||
case '3': function_name = strdup ("operator_delete"); break;
|
||||
case '4': function_name = strdup ("operator_equals"); break;
|
||||
case '5': function_name = strdup ("operator_5"); break;
|
||||
case '6': function_name = strdup ("operator_6"); break;
|
||||
case '7': function_name = strdup ("operator_7"); break;
|
||||
case '8': function_name = strdup ("operator_equals_equals"); break;
|
||||
case '9': function_name = strdup ("operator_not_equals"); break;
|
||||
case 'E': function_name = strdup ("operator_plus_plus"); break;
|
||||
case '5': function_name = strdup ("operator_shiftright"); break;
|
||||
case '6': function_name = strdup ("operator_shiftleft"); break;
|
||||
case '7': function_name = strdup ("operator_not"); break;
|
||||
case '8': function_name = strdup ("operator_equalsequals"); break;
|
||||
case '9': function_name = strdup ("operator_notequals"); break;
|
||||
case 'A': function_name = strdup ("operator_array"); break;
|
||||
case 'C': function_name = strdup ("operator_dereference"); break;
|
||||
case 'D': function_name = strdup ("operator_multiply"); break;
|
||||
case 'E': function_name = strdup ("operator_plusplus"); break;
|
||||
case 'F': function_name = strdup ("operator_minusminus"); break;
|
||||
case 'G': function_name = strdup ("operator_minus"); break;
|
||||
case 'H': function_name = strdup ("operator_plus"); break;
|
||||
case 'I': function_name = strdup ("operator_address"); break;
|
||||
case 'J': function_name = strdup ("operator_dereferencememberptr"); break;
|
||||
case 'K': function_name = strdup ("operator_divide"); break;
|
||||
case 'L': function_name = strdup ("operator_modulo"); break;
|
||||
case 'M': function_name = strdup ("operator_lessthan"); break;
|
||||
case 'N': function_name = strdup ("operator_lessthanequal"); break;
|
||||
case 'O': function_name = strdup ("operator_greaterthan"); break;
|
||||
case 'P': function_name = strdup ("operator_greaterthanequal"); break;
|
||||
case 'R': function_name = strdup ("operator_functioncall"); break;
|
||||
case 'S': function_name = strdup ("operator_compliment"); break;
|
||||
case 'T': function_name = strdup ("operator_xor"); break;
|
||||
case 'U': function_name = strdup ("operator_logicalor"); break;
|
||||
case 'V': function_name = strdup ("operator_logicaland"); break;
|
||||
case 'W': function_name = strdup ("operator_or"); break;
|
||||
case 'X': function_name = strdup ("operator_multiplyequals"); break;
|
||||
case 'Y': function_name = strdup ("operator_plusequals"); break;
|
||||
case 'Z': function_name = strdup ("operator_minusequals"); break;
|
||||
case '_':
|
||||
/* FIXME: Seems to be some kind of escape character - overloads? */
|
||||
switch (*++name)
|
||||
{
|
||||
case '7': /* FIXME: Compiler generated default copy/assignment ctor? */
|
||||
return -1;
|
||||
case '0': function_name = strdup ("operator_divideequals"); break;
|
||||
case '1': function_name = strdup ("operator_moduloequals"); break;
|
||||
case '2': function_name = strdup ("operator_shiftrightequals"); break;
|
||||
case '3': function_name = strdup ("operator_shiftleftequals"); break;
|
||||
case '4': function_name = strdup ("operator_andequals"); break;
|
||||
case '5': function_name = strdup ("operator_orequals"); break;
|
||||
case '6': function_name = strdup ("operator_xorequals"); break;
|
||||
/* FIXME: These look like static vtable/rtti information ? */
|
||||
case 'E': function_name = strdup ("_unknown_E"); break;
|
||||
case 'G': function_name = strdup ("_unknown_G"); break;
|
||||
default:
|
||||
|
@ -287,6 +314,15 @@ static char *demangle_datatype (char **str, compound_type *ct,
|
|||
|
||||
switch (*iter)
|
||||
{
|
||||
case '_':
|
||||
if (*++iter != 'N') /* _N = bool */
|
||||
return NULL;
|
||||
iter++;
|
||||
ct->dest_type = 'I'; /* treat as int */
|
||||
if (!get_constraints_convention_2 (&iter, ct))
|
||||
return NULL;
|
||||
ct->expression = get_type_string (ct->dest_type, ct->flags);
|
||||
break;
|
||||
case 'C': case 'D': case 'E': case 'F': case 'G':
|
||||
case 'H': case 'I': case 'J': case 'K': case 'M':
|
||||
case 'N': case 'O': case 'X': case 'Z':
|
||||
|
|
|
@ -13,7 +13,6 @@ static FILE *cfile = NULL;
|
|||
static void output_spec_postamble (void);
|
||||
static void output_header_postamble (void);
|
||||
static void output_c_postamble (void);
|
||||
static void output_prototype (FILE *file, const parsed_symbol *sym);
|
||||
static void output_c_banner (const parsed_symbol *sym);
|
||||
static const char *get_format_str (int type);
|
||||
static const char *get_in_or_out (const parsed_symbol *sym, size_t arg);
|
||||
|
@ -435,7 +434,7 @@ void output_install_script (void)
|
|||
*
|
||||
* Write a C prototype for a parsed symbol
|
||||
*/
|
||||
static void output_prototype (FILE *file, const parsed_symbol *sym)
|
||||
void output_prototype (FILE *file, const parsed_symbol *sym)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ typedef struct __globals
|
|||
int do_quiet; /* -q */
|
||||
int do_verbose; /* -v */
|
||||
int do_documentation; /* -D */
|
||||
int do_demangle; /* -S */
|
||||
|
||||
/* Option arguments */
|
||||
int start_ordinal; /* -s */
|
||||
|
@ -139,6 +140,8 @@ void output_c_preamble (void);
|
|||
|
||||
void output_c_symbol (const parsed_symbol *sym);
|
||||
|
||||
void output_prototype (FILE *file, const parsed_symbol *sym);
|
||||
|
||||
void output_makefile (void);
|
||||
|
||||
void output_install_script (void);
|
||||
|
|
Loading…
Reference in New Issue