Commit 0395a4fb authored by Jon Griffiths's avatar Jon Griffiths Committed by Alexandre Julliard

Improve name demangling, add 'demangle symbol' option.

parent 0350d2fd
...@@ -54,10 +54,11 @@ Usage ...@@ -54,10 +54,11 @@ Usage
Specmaker is a command line tool. Running it with no arguments or passing Specmaker is a command line tool. Running it with no arguments or passing
it '-h' on the command line lists the available options: it '-h' on the command line lists the available options:
Usage: specmaker [options] -d dll Usage: specmaker [options] [-d dll | -S sym]
Options: Options:
-d dll Use dll for input file (mandatory) -d dll Use dll for input file (mandatory)
-S sym Demangle C++ symbol 'sym' and exit
-h Display this help message -h Display this help message
-I dir Look for prototypes in 'dir' (implies -c) -I dir Look for prototypes in 'dir' (implies -c)
-o name Set the output dll name (default: dll) -o name Set the output dll name (default: dll)
...@@ -75,10 +76,26 @@ Options: ...@@ -75,10 +76,26 @@ Options:
Basic 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) OPTION: -d dll Use dll for input file (mandatory)
The -d option tells specmaker which DLL you want to create a .spec file 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 16 bit DLL's are not currently supported (Note that Winelib is intended
only for Win32 programs). only for Win32 programs).
......
...@@ -38,6 +38,14 @@ static void do_input (const char *arg) ...@@ -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) static void do_code (void)
{ {
globals.do_code = 1; globals.do_code = 1;
...@@ -108,6 +116,7 @@ struct option ...@@ -108,6 +116,7 @@ struct option
static const struct option option_table[] = { static const struct option option_table[] = {
{"-d", 1, do_input, "-d dll Use dll for input file (mandatory)"}, {"-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"}, {"-h", 0, do_usage, "-h Display this help message"},
{"-I", 1, do_include, "-I dir Look for prototypes in 'dir' (implies -c)"}, {"-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)"}, {"-o", 1, do_name, "-o name Set the output dll name (default: dll)"},
...@@ -127,7 +136,7 @@ static const struct option option_table[] = { ...@@ -127,7 +136,7 @@ static const struct option option_table[] = {
void do_usage (void) void do_usage (void)
{ {
const struct option *opt; 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++) for (opt = option_table; opt->name; opt++)
printf (" %s\n", opt->usage); printf (" %s\n", opt->usage);
puts ("\n"); puts ("\n");
...@@ -180,7 +189,7 @@ static void parse_options (char *argv[]) ...@@ -180,7 +189,7 @@ static void parse_options (char *argv[])
ptr++; ptr++;
} }
if (globals.do_code && !globals.directory) if (!globals.do_demangle && globals.do_code && !globals.directory)
fatal ("-I must be used if generating code"); fatal ("-I must be used if generating code");
if (!globals.input_name) if (!globals.input_name)
...@@ -205,14 +214,25 @@ int main (int argc, char *argv[]) ...@@ -205,14 +214,25 @@ int main (int argc, char *argv[])
parse_options (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); dll_open (globals.input_name);
output_spec_preamble (); output_spec_preamble ();
output_header_preamble (); output_header_preamble ();
output_c_preamble (); output_c_preamble ();
memset (&symbol, 0, sizeof (parsed_symbol));
while ((symbol.symbol = dll_next_symbol ())) while ((symbol.symbol = dll_next_symbol ()))
{ {
count++; count++;
......
...@@ -76,19 +76,46 @@ int symbol_demangle (parsed_symbol *sym) ...@@ -76,19 +76,46 @@ int symbol_demangle (parsed_symbol *sym)
case '2': function_name = strdup ("operator_new"); break; case '2': function_name = strdup ("operator_new"); break;
case '3': function_name = strdup ("operator_delete"); break; case '3': function_name = strdup ("operator_delete"); break;
case '4': function_name = strdup ("operator_equals"); break; case '4': function_name = strdup ("operator_equals"); break;
case '5': function_name = strdup ("operator_5"); break; case '5': function_name = strdup ("operator_shiftright"); break;
case '6': function_name = strdup ("operator_6"); break; case '6': function_name = strdup ("operator_shiftleft"); break;
case '7': function_name = strdup ("operator_7"); break; case '7': function_name = strdup ("operator_not"); break;
case '8': function_name = strdup ("operator_equals_equals"); break; case '8': function_name = strdup ("operator_equalsequals"); break;
case '9': function_name = strdup ("operator_not_equals"); break; case '9': function_name = strdup ("operator_notequals"); break;
case 'E': function_name = strdup ("operator_plus_plus"); 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 '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 '_': case '_':
/* FIXME: Seems to be some kind of escape character - overloads? */
switch (*++name) switch (*++name)
{ {
case '7': /* FIXME: Compiler generated default copy/assignment ctor? */ case '0': function_name = strdup ("operator_divideequals"); break;
return -1; 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 'E': function_name = strdup ("_unknown_E"); break;
case 'G': function_name = strdup ("_unknown_G"); break; case 'G': function_name = strdup ("_unknown_G"); break;
default: default:
...@@ -287,6 +314,15 @@ static char *demangle_datatype (char **str, compound_type *ct, ...@@ -287,6 +314,15 @@ static char *demangle_datatype (char **str, compound_type *ct,
switch (*iter) 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 'C': case 'D': case 'E': case 'F': case 'G':
case 'H': case 'I': case 'J': case 'K': case 'M': case 'H': case 'I': case 'J': case 'K': case 'M':
case 'N': case 'O': case 'X': case 'Z': case 'N': case 'O': case 'X': case 'Z':
......
...@@ -13,7 +13,6 @@ static FILE *cfile = NULL; ...@@ -13,7 +13,6 @@ static FILE *cfile = NULL;
static void output_spec_postamble (void); static void output_spec_postamble (void);
static void output_header_postamble (void); static void output_header_postamble (void);
static void output_c_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 void output_c_banner (const parsed_symbol *sym);
static const char *get_format_str (int type); static const char *get_format_str (int type);
static const char *get_in_or_out (const parsed_symbol *sym, size_t arg); static const char *get_in_or_out (const parsed_symbol *sym, size_t arg);
...@@ -435,7 +434,7 @@ void output_install_script (void) ...@@ -435,7 +434,7 @@ void output_install_script (void)
* *
* Write a C prototype for a parsed symbol * 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; unsigned int i;
......
...@@ -77,6 +77,7 @@ typedef struct __globals ...@@ -77,6 +77,7 @@ typedef struct __globals
int do_quiet; /* -q */ int do_quiet; /* -q */
int do_verbose; /* -v */ int do_verbose; /* -v */
int do_documentation; /* -D */ int do_documentation; /* -D */
int do_demangle; /* -S */
/* Option arguments */ /* Option arguments */
int start_ordinal; /* -s */ int start_ordinal; /* -s */
...@@ -139,6 +140,8 @@ void output_c_preamble (void); ...@@ -139,6 +140,8 @@ void output_c_preamble (void);
void output_c_symbol (const parsed_symbol *sym); void output_c_symbol (const parsed_symbol *sym);
void output_prototype (FILE *file, const parsed_symbol *sym);
void output_makefile (void); void output_makefile (void);
void output_install_script (void); void output_install_script (void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment