From 0395a4fba4f7e0e85eb1c920ce99b22da64b396f Mon Sep 17 00:00:00 2001 From: Jon Griffiths Date: Sun, 28 Jan 2001 23:08:52 +0000 Subject: [PATCH] Improve name demangling, add 'demangle symbol' option. --- tools/specmaker/README | 21 +++++++++++++-- tools/specmaker/main.c | 28 ++++++++++++++++--- tools/specmaker/msmangle.c | 54 ++++++++++++++++++++++++++++++------- tools/specmaker/output.c | 3 +-- tools/specmaker/specmaker.h | 3 +++ 5 files changed, 92 insertions(+), 17 deletions(-) diff --git a/tools/specmaker/README b/tools/specmaker/README index e720b7922c9..6eb630134d4 100644 --- a/tools/specmaker/README +++ b/tools/specmaker/README @@ -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). diff --git a/tools/specmaker/main.c b/tools/specmaker/main.c index 2b99e5d25f5..9afe59bc068 100644 --- a/tools/specmaker/main.c +++ b/tools/specmaker/main.c @@ -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++; diff --git a/tools/specmaker/msmangle.c b/tools/specmaker/msmangle.c index b9b68764e98..a418efcd83c 100644 --- a/tools/specmaker/msmangle.c +++ b/tools/specmaker/msmangle.c @@ -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': diff --git a/tools/specmaker/output.c b/tools/specmaker/output.c index 491b74d5189..c4cfb9d6ac6 100644 --- a/tools/specmaker/output.c +++ b/tools/specmaker/output.c @@ -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; diff --git a/tools/specmaker/specmaker.h b/tools/specmaker/specmaker.h index 0fc636771a6..54b2279e586 100644 --- a/tools/specmaker/specmaker.h +++ b/tools/specmaker/specmaker.h @@ -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);