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
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);
......
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