diff --git a/Make.rules.in b/Make.rules.in index 29c101940e7..b6d36def23f 100644 --- a/Make.rules.in +++ b/Make.rules.in @@ -129,7 +129,7 @@ LINTS = $(C_SRCS:.c=.ln) $(WINDRES) -i $< -o $@ .spec.spec.c: - $(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --spec $< + $(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $< .spec.spec.def: $(WINEBUILD) $(DEFS) -o $@ --def $< diff --git a/dlls/Makedll.rules.in b/dlls/Makedll.rules.in index db71d4d9bfe..f6cd62ab8bd 100644 --- a/dlls/Makedll.rules.in +++ b/dlls/Makedll.rules.in @@ -27,7 +27,7 @@ all: $(MODULE)$(DLLEXT) $(SUBDIRS) # Rules for .so files $(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD) - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --spec $(SRCDIR)/$(MAINSPEC) $(DLLMODE:%=--mode %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%) + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(DLLMODE:%=--mode %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%) $(MODULE).so: $(MAINSPEC).o $(ALL_OBJS) Makefile.in $(LDDLL) $(MAINSPEC).o $(ALL_OBJS) -o $@ -L$(DLLDIR) $(ALL_LIBS) -lc diff --git a/dlls/gdi/Makefile.in b/dlls/gdi/Makefile.in index 6dcf81f3793..81e64c68685 100644 --- a/dlls/gdi/Makefile.in +++ b/dlls/gdi/Makefile.in @@ -76,7 +76,7 @@ EXTRASUBDIRS = \ # Special rules for 16-bit resource and spec files gdi.exe.spec.c: gdi.exe.spec version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --spec $(SRCDIR)/gdi.exe.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/gdi.exe.spec version16.res: version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc diff --git a/dlls/kernel/Makefile.in b/dlls/kernel/Makefile.in index b6fec8a4358..8192fc17d60 100644 --- a/dlls/kernel/Makefile.in +++ b/dlls/kernel/Makefile.in @@ -113,7 +113,7 @@ relay16asm.s: $(WINEBUILD) # Special rules for 16-bit resource and spec files krnl386.exe.spec.c: krnl386.exe.spec version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --spec $(SRCDIR)/krnl386.exe.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/krnl386.exe.spec version16.res: version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in index f4218444a82..c8471d35359 100644 --- a/dlls/shell32/Makefile.in +++ b/dlls/shell32/Makefile.in @@ -72,10 +72,10 @@ version16.res: version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc shell.spec.c: shell.spec version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --spec $(SRCDIR)/shell.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/shell.spec authors.c: $(TOPSRCDIR)/AUTHORS - (LANG=C; echo 'const char * const SHELL_Authors[] = {' && \ + (LC_ALL=C; echo 'const char * const SHELL_Authors[] = {' && \ sed -e '1,2d' -e 's/\(.*\)/ \"\1\",/' $(TOPSRCDIR)/AUTHORS && \ echo ' 0 };') >$@ || ($(RM) $@ && false) diff --git a/dlls/user/Makefile.in b/dlls/user/Makefile.in index 8f0bb0cbc9a..562b54ad5b2 100644 --- a/dlls/user/Makefile.in +++ b/dlls/user/Makefile.in @@ -168,13 +168,13 @@ EXTRASUBDIRS = \ # Special rules for 16-bit resource and spec files user.exe.spec.c: user.exe.spec resources/version16.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res resources/version16.res --spec $(SRCDIR)/user.exe.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res resources/version16.res --dll $(SRCDIR)/user.exe.spec display.drv.spec.c: display.drv.spec resources/display.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/display.res --spec $(SRCDIR)/display.drv.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/display.res --dll $(SRCDIR)/display.drv.spec mouse.drv.spec.c: mouse.drv.spec resources/mouse.res - $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/mouse.res --spec $(SRCDIR)/mouse.drv.spec + $(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/mouse.res --dll $(SRCDIR)/mouse.drv.spec resources/display.res: resources/display.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/resources/display.rc diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index c7da34df17f..9e6d38711db 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -68,7 +68,6 @@ typedef struct typedef struct { - int n_args; char arg_types[21]; } ORD_FUNCTION; @@ -170,6 +169,9 @@ extern FILE *open_input_file( const char *srcdir, const char *name ); extern void close_input_file( FILE *file ); extern void dump_bytes( FILE *outfile, const unsigned char *data, int len, const char *label, int constant ); +extern int remove_stdcall_decoration( char *name ); +extern DLLSPEC *alloc_dll_spec(void); +extern void free_dll_spec( DLLSPEC *spec ); extern const char *make_c_identifier( const char *str ); extern int get_alignment(int alignBoundary); @@ -184,7 +186,6 @@ extern void load_res16_file( const char *name, DLLSPEC *spec ); extern int output_res16_data( FILE *outfile, DLLSPEC *spec ); extern int output_res16_directory( unsigned char *buffer, DLLSPEC *spec ); extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor ); -extern int parse_debug_channels( const char *srcdir, const char *filename ); extern void BuildRelays16( FILE *outfile ); extern void BuildRelays32( FILE *outfile ); @@ -192,7 +193,10 @@ extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec ); extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec ); extern void BuildDef32File( FILE *outfile, DLLSPEC *spec ); extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ); -extern int ParseTopLevel( FILE *file, DLLSPEC *spec ); + +extern int parse_spec_file( FILE *file, DLLSPEC *spec ); +extern int parse_def_file( FILE *file, DLLSPEC *spec ); +extern int parse_debug_channels( const char *srcdir, const char *filename ); /* global variables */ diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index a8f367ced65..996e0b19abb 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1,8 +1,8 @@ /* * DLL imports support * - * Copyright 2000 Alexandre Julliard - * 2000 Eric Pouech + * Copyright 2000, 2004 Alexandre Julliard + * Copyright 2000 Eric Pouech * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -32,20 +32,13 @@ #include "build.h" -struct func -{ - char *name; /* function name */ - int ordinal; /* function ordinal */ - int ord_only; /* non-zero if function is imported by ordinal */ -}; - struct import { - char *dll; /* dll name */ + DLLSPEC *spec; /* description of the imported dll */ int delay; /* delay or not dll loading ? */ - struct func *exports; /* functions exported from this dll */ + ORDDEF **exports; /* functions exported from this dll */ int nb_exports; /* number of exported functions */ - struct func *imports; /* functions we want to import from this dll */ + ORDDEF **imports; /* functions we want to import from this dll */ int nb_imports; /* number of imported functions */ }; @@ -143,7 +136,10 @@ static int name_cmp( const void *name, const void *entry ) /* compare function names; helper for resolve_imports */ static int func_cmp( const void *func1, const void *func2 ) { - return strcmp( ((struct func *)func1)->name, ((struct func *)func2)->name ); + const ORDDEF *odp1 = *(const ORDDEF **)func1; + const ORDDEF *odp2 = *(const ORDDEF **)func2; + return strcmp( odp1->name ? odp1->name : odp1->export_name, + odp2->name ? odp2->name : odp2->export_name ); } /* locate a symbol in a (sorted) list */ @@ -159,14 +155,15 @@ inline static const char *find_symbol( const char *name, char **table, int size } /* locate an export in a (sorted) export list */ -inline static struct func *find_export( const char *name, struct func *table, int size ) +inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size ) { - struct func func, *res = NULL; + ORDDEF func, *odp, **res = NULL; func.name = (char *)name; func.ordinal = -1; - if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp ); - return res; + odp = &func; + if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp ); + return res ? *res : NULL; } /* sort a symbol table */ @@ -179,13 +176,9 @@ inline static void sort_symbols( char **table, int size ) /* free an import structure */ static void free_imports( struct import *imp ) { - int i; - - for (i = 0; i < imp->nb_exports; i++) free( imp->exports[i].name ); - for (i = 0; i < imp->nb_imports; i++) free( imp->imports[i].name ); free( imp->exports ); free( imp->imports ); - free( imp->dll ); + free_dll_spec( imp->spec ); free( imp ); } @@ -202,7 +195,7 @@ static int is_already_imported( const char *name ) for (i = 0; i < nb_imports; i++) { - if (!strcmp( dll_imports[i]->dll, name )) return 1; + if (!strcmp( dll_imports[i]->spec->file_name, name )) return 1; } return 0; } @@ -241,152 +234,40 @@ static char *open_library( const char *name ) return fullname; } -/* skip whitespace until the next token */ -static char *skip_whitespace( char *p ) -{ - while (*p && isspace(*p)) p++; - if (!*p || *p == ';') p = NULL; - return p; -} - -/* skip to the start of the next token, null terminating the current one */ -static char *next_token( char *p ) -{ - while (*p && !isspace(*p)) p++; - if (*p) *p++ = 0; - return skip_whitespace( p ); -} - -/* remove the @nn suffix from stdcall names */ -static char *remove_stdcall_decoration( char *buffer ) -{ - char *p = buffer + strlen(buffer) - 1; - while (p > buffer && isdigit(*p)) p--; - if (p > buffer && *p == '@') *p = 0; - return buffer; -} - /* read in the list of exported symbols of an import library */ static int read_import_lib( const char *name, struct import *imp ) { FILE *f; - char buffer[1024]; char *fullname; - int size; + int i, ret; + DLLSPEC *spec = imp->spec; imp->exports = NULL; - imp->nb_exports = size = 0; + imp->nb_exports = 0; fullname = open_library( name ); f = open_input_file( NULL, fullname ); free( fullname ); - while (fgets( buffer, sizeof(buffer), f )) - { - char *name, *flags; - int ordinal = 0, ord_only = 0; - - char *p = buffer + strlen(buffer) - 1; - if (p < buffer) goto next; - if (*p == '\n') *p-- = 0; - - p = buffer; - if (!(p = skip_whitespace(p))) goto next; - name = p; - p = next_token( name ); - - if (!strcmp( name, "LIBRARY" )) - { - if (!p) - { - error( "Expected name after LIBRARY\n" ); - goto next; - } - name = p; - p = next_token( name ); - if (p) - { - error( "Garbage after LIBRARY statement\n" ); - goto next; - } - if (is_already_imported( name )) - { - close_input_file( f ); - return 0; /* ignore this dll */ - } - free( imp->dll ); - imp->dll = xstrdup( name ); - goto next; - } - if (!strcmp( name, "EXPORTS" )) goto next; - - /* check for ordinal */ - if (!p) - { - error( "Expected ordinal after function name\n" ); - goto next; - } - if (*p != '@' || !isdigit(p[1])) - { - error( "Expected ordinal after function name '%s'\n", name ); - goto next; - } - ordinal = strtol( p+1, &p, 10 ); - if (ordinal >= MAX_ORDINALS) - { - error( "Invalid ordinal number %d\n", ordinal ); - goto next; - } - - /* check for optional flags */ - while (p && (p = skip_whitespace(p))) - { - flags = p; - p = next_token( flags ); - if (!strcmp( flags, "NONAME" )) - { - ord_only = 1; - if (!ordinal) - { - error( "Invalid ordinal number %d\n", ordinal ); - goto next; - } - } - else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" )) - { - /* we don't support importing non-function entry points */ - goto next; - } - else if (!strcmp( flags, "PRIVATE" )) - { - /* function must not be imported */ - goto next; - } - else - { - error( "Garbage after ordinal declaration\n" ); - goto next; - } - } - - if (imp->nb_exports == size) - { - size += 128; - imp->exports = xrealloc( imp->exports, size * sizeof(*imp->exports) ); - } - if ((p = strchr( name, '=' ))) *p = 0; - remove_stdcall_decoration( name ); - imp->exports[imp->nb_exports].name = xstrdup( name ); - imp->exports[imp->nb_exports].ordinal = ordinal; - imp->exports[imp->nb_exports].ord_only = ord_only; - imp->nb_exports++; - next: - current_line++; - } + ret = parse_def_file( f, spec ); close_input_file( f ); + if (!ret) return 0; + if (is_already_imported( spec->file_name )) return 0; + + imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) ); + + for (i = 0; i < spec->nb_entry_points; i++) + { + ORDDEF *odp = &spec->entry_points[i]; + + if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue; + if (odp->flags & FLAG_PRIVATE) continue; + imp->exports[imp->nb_exports++] = odp; + } + imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) ); if (imp->nb_exports) qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp ); - return !nb_errors; + return 1; } /* add a dll to the list of imports */ @@ -407,11 +288,11 @@ void add_import_dll( const char *name, int delay ) } imp = xmalloc( sizeof(*imp) ); - imp->dll = fullname; - imp->delay = delay; - imp->imports = NULL; - imp->nb_imports = 0; - + imp->spec = alloc_dll_spec(); + imp->spec->file_name = fullname; + imp->delay = delay; + imp->imports = NULL; + imp->nb_imports = 0; if (delay) nb_delayed++; if (read_import_lib( name, imp )) @@ -489,13 +370,10 @@ void add_ignore_symbol( const char *name ) } /* add a function to the list of imports from a given dll */ -static void add_import_func( struct import *imp, const struct func *func ) +static void add_import_func( struct import *imp, ORDDEF *func ) { imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) ); - imp->imports[imp->nb_imports].name = xstrdup( func->name ); - imp->imports[imp->nb_imports].ordinal = func->ordinal; - imp->imports[imp->nb_imports].ord_only = func->ord_only; - imp->nb_imports++; + imp->imports[imp->nb_imports++] = func; total_imports++; if (imp->delay) total_delayed++; } @@ -613,15 +491,16 @@ static void add_extra_undef_symbols( const DLLSPEC *spec ) static int check_unused( const struct import* imp, const DLLSPEC *spec ) { int i; - size_t len = strlen(imp->dll); - const char *p = strchr( imp->dll, '.' ); - if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll; + const char *file_name = imp->spec->file_name; + size_t len = strlen( file_name ); + const char *p = strchr( file_name, '.' ); + if (p && !strcasecmp( p, ".dll" )) len = p - file_name; for (i = spec->base; i <= spec->limit; i++) { ORDDEF *odp = spec->ordinals[i]; if (!odp || !(odp->flags & FLAG_FORWARD)) continue; - if (!strncasecmp( odp->link_name, imp->dll, len ) && + if (!strncasecmp( odp->link_name, file_name, len ) && odp->link_name[len] == '.') return 0; /* found a forward, it is used */ } @@ -724,10 +603,10 @@ int resolve_imports( DLLSPEC *spec ) for (j = 0; j < nb_undef_symbols; j++) { - struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports ); - if (func) + ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports ); + if (odp) { - add_import_func( imp, func ); + add_import_func( imp, odp ); free( undef_symbols[j] ); undef_symbols[j] = NULL; } @@ -736,7 +615,7 @@ int resolve_imports( DLLSPEC *spec ) if (!remove_symbol_holes() && check_unused( imp, spec )) { /* the dll is not used, get rid of it */ - warning( "%s imported but no symbols used\n", imp->dll ); + warning( "%s imported but no symbols used\n", imp->spec->file_name ); remove_import_dll( i ); i--; } @@ -772,7 +651,7 @@ static int output_immediate_imports( FILE *outfile ) { if (dll_imports[i]->delay) continue; fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n", - dll_imports[i]->dll, j ); + dll_imports[i]->spec->file_name, j ); j += dll_imports[i]->nb_imports + 1; } @@ -784,18 +663,18 @@ static int output_immediate_imports( FILE *outfile ) for (i = 0; i < nb_imports; i++) { if (dll_imports[i]->delay) continue; - fprintf( outfile, " /* %s */\n", dll_imports[i]->dll ); + fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name ); for (j = 0; j < dll_imports[i]->nb_imports; j++) { - struct func *import = &dll_imports[i]->imports[j]; - if (!import->ord_only) + ORDDEF *odp = dll_imports[i]->imports[j]; + if (!(odp->flags & FLAG_NONAME)) { - unsigned short ord = import->ordinal; + unsigned short ord = odp->ordinal; fprintf( outfile, " \"\\%03o\\%03o%s\",\n", - *(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name ); + *(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name ); } else - fprintf( outfile, " (char *)%d,\n", import->ordinal ); + fprintf( outfile, " (char *)%d,\n", odp->ordinal ); } fprintf( outfile, " 0,\n" ); } @@ -811,13 +690,14 @@ static int output_immediate_imports( FILE *outfile ) if (dll_imports[i]->delay) continue; for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4) { - struct func *import = &dll_imports[i]->imports[j]; - fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name ); - fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name ); - fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", import->name); + ORDDEF *odp = dll_imports[i]->imports[j]; + const char *name = odp->name ? odp->name : odp->export_name; + fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name ); + fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name ); + fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", name); #if defined(__i386__) - if (strstr( import->name, "__wine_call_from_16" )) + if (strstr( name, "__wine_call_from_16" )) fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos ); else fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos ); @@ -886,8 +766,9 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i); for (j = 0; j < dll_imports[i]->nb_imports; j++) { - fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", - i, dll_imports[i]->imports[j].name ); + ORDDEF *odp = dll_imports[i]->imports[j]; + const char *name = odp->name ? odp->name : odp->export_name; + fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name ); } } fprintf( outfile, "\n" ); @@ -910,31 +791,33 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) { if (!dll_imports[i]->delay) continue; fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n", - dll_imports[i]->dll, i, j, j ); + dll_imports[i]->spec->file_name, i, j, j ); j += dll_imports[i]->nb_imports; } fprintf( outfile, " },\n {\n" ); for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; - fprintf( outfile, " /* %s */\n", dll_imports[i]->dll ); + fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name ); for (j = 0; j < dll_imports[i]->nb_imports; j++) { - fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j].name); + ORDDEF *odp = dll_imports[i]->imports[j]; + const char *name = odp->name ? odp->name : odp->export_name; + fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, name ); } } fprintf( outfile, " },\n {\n" ); for (i = 0; i < nb_imports; i++) { if (!dll_imports[i]->delay) continue; - fprintf( outfile, " /* %s */\n", dll_imports[i]->dll ); + fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name ); for (j = 0; j < dll_imports[i]->nb_imports; j++) { - struct func *import = &dll_imports[i]->imports[j]; - if (import->ord_only) - fprintf( outfile, " (char *)%d,\n", import->ordinal ); + ORDDEF *odp = dll_imports[i]->imports[j]; + if (!odp->name) + fprintf( outfile, " (char *)%d,\n", odp->ordinal ); else - fprintf( outfile, " \"%s\",\n", import->name ); + fprintf( outfile, " \"%s\",\n", odp->name ); } } fprintf( outfile, " }\n};\n\n" ); @@ -1059,7 +942,10 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) for (j = 0; j < dll_imports[i]->nb_imports; j++) { char buffer[128]; - sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j].name ); + ORDDEF *odp = dll_imports[i]->imports[j]; + const char *name = odp->name ? odp->name : odp->export_name; + + sprintf( buffer, "__wine_delay_imp_%d_%s", i, name ); fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer ); fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer ); #if defined(__i386__) @@ -1088,12 +974,14 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) if (!dll_imports[i]->delay) continue; for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4) { - struct func *import = &dll_imports[i]->imports[j]; - fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name ); - fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name ); - fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", import->name); + ORDDEF *odp = dll_imports[i]->imports[j]; + const char *name = odp->name ? odp->name : odp->export_name; + + fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name ); + fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name ); + fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", name ); #if defined(__i386__) - if (strstr( import->name, "__wine_call_from_16" )) + if (strstr( name, "__wine_call_from_16" )) fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos ); else fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos ); diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index edddd7c5bb1..20509791130 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -56,17 +56,17 @@ char **lib_path = NULL; char *input_file_name = NULL; const char *output_file_name = NULL; -static FILE *input_file; static FILE *output_file; static const char *current_src_dir; static int nb_res_files; static char **res_files; +static char *spec_file_name; /* execution mode */ enum exec_mode_values { MODE_NONE, - MODE_SPEC, + MODE_DLL, MODE_EXE, MODE_DEF, MODE_DEBUG, @@ -87,7 +87,10 @@ static void set_dll_file_name( const char *name, DLLSPEC *spec ) if ((p = strrchr( name, '/' ))) name = p + 1; spec->file_name = xmalloc( strlen(name) + 5 ); strcpy( spec->file_name, name ); - if ((p = strrchr( spec->file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0; + if ((p = strrchr( spec->file_name, '.' ))) + { + if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0; + } if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" ); } @@ -126,7 +129,7 @@ static const char usage_str[] = " --version Print the version and exit\n" " -w --warnings Turn on warnings\n" "\nMode options:\n" -" --spec=FILE.SPEC Build a .c file from a spec file\n" +" --dll=FILE Build a .c file from a .spec or .def file\n" " --def=FILE.SPEC Build a .def file from a spec file\n" " --exe=NAME Build a .c file for the named executable\n" " --debug [FILES] Build a .c file with the debug channels declarations\n" @@ -136,7 +139,7 @@ static const char usage_str[] = enum long_options_values { - LONG_OPT_SPEC = 1, + LONG_OPT_DLL = 1, LONG_OPT_DEF, LONG_OPT_EXE, LONG_OPT_DEBUG, @@ -149,13 +152,14 @@ static const char short_options[] = "C:D:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w"; static const struct option long_options[] = { - { "spec", 1, 0, LONG_OPT_SPEC }, + { "dll", 1, 0, LONG_OPT_DLL }, { "def", 1, 0, LONG_OPT_DEF }, { "exe", 1, 0, LONG_OPT_EXE }, { "debug", 0, 0, LONG_OPT_DEBUG }, { "relay16", 0, 0, LONG_OPT_RELAY16 }, { "relay32", 0, 0, LONG_OPT_RELAY32 }, { "version", 0, 0, LONG_OPT_VERSION }, + { "spec", 1, 0, LONG_OPT_DLL }, /* for backwards compatibility */ /* aliases for short options */ { "source-dir", 1, 0, 'C' }, { "delay-lib", 1, 0, 'd' }, @@ -287,14 +291,14 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) case 'w': display_warnings = 1; break; - case LONG_OPT_SPEC: - set_exec_mode( MODE_SPEC ); - input_file = open_input_file( NULL, optarg ); + case LONG_OPT_DLL: + set_exec_mode( MODE_DLL ); + spec_file_name = xstrdup( optarg ); set_dll_file_name( optarg, spec ); break; case LONG_OPT_DEF: set_exec_mode( MODE_DEF ); - input_file = open_input_file( NULL, optarg ); + spec_file_name = xstrdup( optarg ); set_dll_file_name( optarg, spec ); break; case LONG_OPT_EXE: @@ -357,65 +361,59 @@ static void load_resources( char *argv[], DLLSPEC *spec ) } } +static int parse_input_file( DLLSPEC *spec ) +{ + FILE *input_file = open_input_file( NULL, spec_file_name ); + char *extension = strrchr( spec_file_name, '.' ); + + if (extension && !strcmp( extension, ".def" )) + return parse_def_file( input_file, spec ); + else + return parse_spec_file( input_file, spec ); + close_input_file( input_file ); +} + + /******************************************************************* * main */ int main(int argc, char **argv) { - DLLSPEC spec; - - spec.file_name = NULL; - spec.dll_name = NULL; - spec.owner_name = NULL; - spec.init_func = NULL; - spec.type = SPEC_WIN32; - spec.mode = SPEC_MODE_DLL; - spec.base = MAX_ORDINALS; - spec.limit = 0; - spec.stack_size = 0; - spec.heap_size = 0; - spec.nb_entry_points = 0; - spec.alloc_entry_points = 0; - spec.nb_names = 0; - spec.nb_resources = 0; - spec.entry_points = NULL; - spec.names = NULL; - spec.ordinals = NULL; - spec.resources = NULL; + DLLSPEC *spec = alloc_dll_spec(); output_file = stdout; - argv = parse_options( argc, argv, &spec ); + argv = parse_options( argc, argv, spec ); switch(exec_mode) { - case MODE_SPEC: - load_resources( argv, &spec ); - if (!ParseTopLevel( input_file, &spec )) break; - switch (spec.type) + case MODE_DLL: + load_resources( argv, spec ); + if (!parse_input_file( spec )) break; + switch (spec->type) { case SPEC_WIN16: if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); - BuildSpec16File( output_file, &spec ); + BuildSpec16File( output_file, spec ); break; case SPEC_WIN32: read_undef_symbols( argv ); - BuildSpec32File( output_file, &spec ); + BuildSpec32File( output_file, spec ); break; default: assert(0); } break; case MODE_EXE: - if (spec.type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); - load_resources( argv, &spec ); + if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); + load_resources( argv, spec ); read_undef_symbols( argv ); - BuildSpec32File( output_file, &spec ); + BuildSpec32File( output_file, spec ); break; case MODE_DEF: if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); - if (spec.type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); - if (!ParseTopLevel( input_file, &spec )) break; - BuildDef32File( output_file, &spec ); + if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); + if (!parse_input_file( spec )) break; + BuildDef32File( output_file, spec ); break; case MODE_DEBUG: BuildDebugFile( output_file, current_src_dir, argv ); diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 49b42a9d67f..652826fdd5f 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -3,7 +3,7 @@ * * Copyright 1993 Robert J. Amstadt * Copyright 1995 Martin von Loewis - * Copyright 1995, 1996, 1997 Alexandre Julliard + * Copyright 1995, 1996, 1997, 2004 Alexandre Julliard * Copyright 1997 Eric Youngdale * Copyright 1999 Ulrich Weigand * @@ -43,6 +43,9 @@ static char TokenBuffer[512]; static char *ParseNext = ParseBuffer; static FILE *input_file; +static const char *separator_chars; +static const char *comment_chars; + static const char * const TypeNames[TYPE_NBTYPES] = { "variable", /* TYPE_VARIABLE */ @@ -76,7 +79,12 @@ static int IsNumberString(const char *s) inline static int is_token_separator( char ch ) { - return (ch == '(' || ch == ')' || ch == '-'); + return strchr( separator_chars, ch ) != NULL; +} + +inline static int is_token_comment( char ch ) +{ + return strchr( comment_chars, ch ) != NULL; } /* get the next line from the input file, or return 0 if at eof */ @@ -109,7 +117,7 @@ static const char * GetToken( int allow_eol ) else break; } - if ((*p == '\0') || (*p == '#')) + if ((*p == '\0') || is_token_comment(*p)) { if (!allow_eol) error( "Declaration not terminated properly\n" ); return NULL; @@ -146,11 +154,11 @@ static ORDDEF *add_entry_point( DLLSPEC *spec ) } /******************************************************************* - * ParseVariable + * parse_spec_variable * - * Parse a variable definition. + * Parse a variable definition in a .spec file. */ -static int ParseVariable( ORDDEF *odp, DLLSPEC *spec ) +static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec ) { char *endptr; int *value_array; @@ -208,11 +216,11 @@ static int ParseVariable( ORDDEF *odp, DLLSPEC *spec ) /******************************************************************* - * ParseExportFunction + * parse_spec_export * - * Parse a function definition. + * Parse an exported function definition in a .spec file. */ -static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec ) +static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec ) { const char *token; unsigned int i; @@ -330,11 +338,11 @@ static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec ) /******************************************************************* - * ParseEquate + * parse_spec_equate * - * Parse an 'equate' definition. + * Parse an 'equate' definition in a .spec file. */ -static int ParseEquate( ORDDEF *odp, DLLSPEC *spec ) +static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec ) { char *endptr; int value; @@ -358,11 +366,11 @@ static int ParseEquate( ORDDEF *odp, DLLSPEC *spec ) /******************************************************************* - * ParseStub + * parse_spec_stub * - * Parse a 'stub' definition. + * Parse a 'stub' definition in a .spec file */ -static int ParseStub( ORDDEF *odp, DLLSPEC *spec ) +static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec ) { odp->u.func.arg_types[0] = '\0'; odp->link_name = xstrdup(""); @@ -371,11 +379,11 @@ static int ParseStub( ORDDEF *odp, DLLSPEC *spec ) /******************************************************************* - * ParseExtern + * parse_spec_extern * - * Parse an 'extern' definition. + * Parse an 'extern' definition in a .spec file. */ -static int ParseExtern( ORDDEF *odp, DLLSPEC *spec ) +static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec ) { const char *token; @@ -403,11 +411,11 @@ static int ParseExtern( ORDDEF *odp, DLLSPEC *spec ) /******************************************************************* - * ParseFlags + * parse_spec_flags * - * Parse the optional flags for an entry point + * Parse the optional flags for an entry point in a .spec file. */ -static const char *ParseFlags( ORDDEF *odp ) +static const char *parse_spec_flags( ORDDEF *odp ) { unsigned int i; const char *token; @@ -429,26 +437,13 @@ static const char *ParseFlags( ORDDEF *odp ) return token; } -/******************************************************************* - * fix_export_name - * - * Fix an exported function name by removing a possible @xx suffix - */ -static void fix_export_name( char *name ) -{ - char *p, *end = strrchr( name, '@' ); - if (!end || !end[1] || end == name) return; - /* make sure all the rest is digits */ - for (p = end + 1; *p; p++) if (!isdigit(*p)) return; - *end = 0; -} /******************************************************************* - * ParseOrdinal + * parse_spec_ordinal * - * Parse an ordinal definition. + * Parse an ordinal definition in a .spec file. */ -static int ParseOrdinal( int ordinal, DLLSPEC *spec ) +static int parse_spec_ordinal( int ordinal, DLLSPEC *spec ) { const char *token; @@ -468,32 +463,32 @@ static int ParseOrdinal( int ordinal, DLLSPEC *spec ) } if (!(token = GetToken(0))) goto error; - if (*token == '-' && !(token = ParseFlags( odp ))) goto error; + if (*token == '-' && !(token = parse_spec_flags( odp ))) goto error; odp->name = xstrdup( token ); - fix_export_name( odp->name ); + remove_stdcall_decoration( odp->name ); odp->lineno = current_line; odp->ordinal = ordinal; switch(odp->type) { case TYPE_VARIABLE: - if (!ParseVariable( odp, spec )) goto error; + if (!parse_spec_variable( odp, spec )) goto error; break; case TYPE_PASCAL: case TYPE_STDCALL: case TYPE_VARARGS: case TYPE_CDECL: - if (!ParseExportFunction( odp, spec )) goto error; + if (!parse_spec_export( odp, spec )) goto error; break; case TYPE_ABS: - if (!ParseEquate( odp, spec )) goto error; + if (!parse_spec_equate( odp, spec )) goto error; break; case TYPE_STUB: - if (!ParseStub( odp, spec )) goto error; + if (!parse_spec_stub( odp, spec )) goto error; break; case TYPE_EXTERN: - if (!ParseExtern( odp, spec )) goto error; + if (!parse_spec_extern( odp, spec )) goto error; break; default: assert( 0 ); @@ -641,17 +636,20 @@ static void assign_ordinals( DLLSPEC *spec ) /******************************************************************* - * ParseTopLevel + * parse_spec_file * - * Parse a spec file. + * Parse a .spec file. */ -int ParseTopLevel( FILE *file, DLLSPEC *spec ) +int parse_spec_file( FILE *file, DLLSPEC *spec ) { const char *token; input_file = file; current_line = 0; + comment_chars = "#;"; + separator_chars = "()-"; + while (get_next_line()) { if (!(token = GetToken(1))) continue; @@ -662,11 +660,11 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec ) error( "'@' ordinals not supported for Win16\n" ); continue; } - if (!ParseOrdinal( -1, spec )) continue; + if (!parse_spec_ordinal( -1, spec )) continue; } else if (IsNumberString(token)) { - if (!ParseOrdinal( atoi(token), spec )) continue; + if (!parse_spec_ordinal( atoi(token), spec )) continue; } else { @@ -683,6 +681,243 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec ) } +/******************************************************************* + * parse_def_library + * + * Parse a LIBRARY declaration in a .def file. + */ +static int parse_def_library( DLLSPEC *spec ) +{ + const char *token = GetToken(1); + + if (!token) return 1; + if (strcmp( token, "BASE" )) + { + free( spec->file_name ); + spec->file_name = xstrdup( token ); + if (!(token = GetToken(1))) return 1; + } + if (strcmp( token, "BASE" )) + { + error( "Expected library name or BASE= declaration, got '%s'\n", token ); + return 0; + } + if (!(token = GetToken(0))) return 0; + if (strcmp( token, "=" )) + { + error( "Expected '=' after BASE, got '%s'\n", token ); + return 0; + } + if (!(token = GetToken(0))) return 0; + /* FIXME: do something with base address */ + + return 1; +} + + +/******************************************************************* + * parse_def_stack_heap_size + * + * Parse a STACKSIZE or HEAPSIZE declaration in a .def file. + */ +static int parse_def_stack_heap_size( int is_stack, DLLSPEC *spec ) +{ + const char *token = GetToken(0); + char *end; + unsigned long size; + + if (!token) return 0; + size = strtoul( token, &end, 0 ); + if (*end) + { + error( "Invalid number '%s'\n", token ); + return 0; + } + if (is_stack) spec->stack_size = size / 1024; + else spec->heap_size = size / 1024; + if (!(token = GetToken(1))) return 1; + if (strcmp( token, "," )) + { + error( "Expected ',' after size, got '%s'\n", token ); + return 0; + } + if (!(token = GetToken(0))) return 0; + /* FIXME: do something with reserve size */ + return 1; +} + + +/******************************************************************* + * parse_def_export + * + * Parse an export declaration in a .def file. + */ +static int parse_def_export( char *name, DLLSPEC *spec ) +{ + int i, args; + const char *token = GetToken(1); + + ORDDEF *odp = add_entry_point( spec ); + memset( odp, 0, sizeof(*odp) ); + + odp->lineno = current_line; + odp->ordinal = -1; + odp->name = name; + args = remove_stdcall_decoration( odp->name ); + if (args == -1) odp->type = TYPE_CDECL; + else + { + odp->type = TYPE_STDCALL; + args /= sizeof(int); + if (args >= sizeof(odp->u.func.arg_types)) + { + error( "Too many arguments in stdcall function '%s'\n", odp->name ); + return 0; + } + for (i = 0; i < args; i++) odp->u.func.arg_types[i] = 'l'; + } + + /* check for optional internal name */ + + if (token && !strcmp( token, "=" )) + { + if (!(token = GetToken(0))) goto error; + odp->link_name = xstrdup( token ); + remove_stdcall_decoration( odp->link_name ); + token = GetToken(1); + } + + /* check for optional ordinal */ + + if (token && token[0] == '@') + { + int ordinal; + + if (!IsNumberString( token+1 )) + { + error( "Expected number after '@', got '%s'\n", token+1 ); + goto error; + } + ordinal = atoi( token+1 ); + if (!ordinal) + { + error( "Ordinal 0 is not valid\n" ); + goto error; + } + if (ordinal >= MAX_ORDINALS) + { + error( "Ordinal number %d too large\n", ordinal ); + goto error; + } + if (ordinal > spec->limit) spec->limit = ordinal; + if (ordinal < spec->base) spec->base = ordinal; + odp->ordinal = ordinal; + token = GetToken(1); + } + + /* check for other optional keywords */ + + if (token && !strcmp( token, "NONAME" )) + { + if (odp->ordinal == -1) + { + error( "NONAME requires an ordinal\n" ); + goto error; + } + odp->export_name = odp->name; + odp->name = NULL; + odp->flags |= FLAG_NONAME; + token = GetToken(1); + } + if (token && !strcmp( token, "PRIVATE" )) + { + odp->flags |= FLAG_PRIVATE; + token = GetToken(1); + } + if (token && !strcmp( token, "DATA" )) + { + odp->type = TYPE_EXTERN; + token = GetToken(1); + } + if (token) + { + error( "Garbage text '%s' found at end of export declaration\n", token ); + goto error; + } + return 1; + +error: + spec->nb_entry_points--; + free( odp->name ); + return 0; +} + + +/******************************************************************* + * parse_def_file + * + * Parse a .def file. + */ +int parse_def_file( FILE *file, DLLSPEC *spec ) +{ + const char *token; + int in_exports = 0; + + input_file = file; + current_line = 0; + + comment_chars = ";"; + separator_chars = ",="; + + while (get_next_line()) + { + if (!(token = GetToken(1))) continue; + + if (!strcmp( token, "LIBRARY" ) || !strcmp( token, "NAME" )) + { + if (!parse_def_library( spec )) continue; + goto end_of_line; + } + else if (!strcmp( token, "STACKSIZE" )) + { + if (!parse_def_stack_heap_size( 1, spec )) continue; + goto end_of_line; + } + else if (!strcmp( token, "HEAPSIZE" )) + { + if (!parse_def_stack_heap_size( 0, spec )) continue; + goto end_of_line; + } + else if (!strcmp( token, "EXPORTS" )) + { + in_exports = 1; + if (!(token = GetToken(1))) continue; + } + else if (!strcmp( token, "IMPORTS" )) + { + in_exports = 0; + if (!(token = GetToken(1))) continue; + } + else if (!strcmp( token, "SECTIONS" )) + { + in_exports = 0; + if (!(token = GetToken(1))) continue; + } + + if (!in_exports) continue; /* ignore this line */ + if (!parse_def_export( xstrdup(token), spec )) continue; + + end_of_line: + if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token ); + } + + current_line = 0; /* no longer parsing the input file */ + assign_names( spec ); + assign_ordinals( spec ); + return !nb_errors; +} + + /******************************************************************* * add_debug_channel */ diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 2736ba0d6cc..cd7d56ae4b3 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -209,6 +209,83 @@ void close_input_file( FILE *file ) } +/******************************************************************* + * remove_stdcall_decoration + * + * Remove a possible @xx suffix from a function name. + * Return the numerical value of the suffix, or -1 if none. + */ +int remove_stdcall_decoration( char *name ) +{ + char *p, *end = strrchr( name, '@' ); + if (!end || !end[1] || end == name) return -1; + /* make sure all the rest is digits */ + for (p = end + 1; *p; p++) if (!isdigit(*p)) return -1; + *end = 0; + return atoi( end + 1 ); +} + + +/******************************************************************* + * alloc_dll_spec + * + * Create a new dll spec file descriptor + */ +DLLSPEC *alloc_dll_spec(void) +{ + DLLSPEC *spec; + + spec = xmalloc( sizeof(*spec) ); + spec->file_name = NULL; + spec->dll_name = NULL; + spec->owner_name = NULL; + spec->init_func = NULL; + spec->type = SPEC_WIN32; + spec->mode = SPEC_MODE_DLL; + spec->base = MAX_ORDINALS; + spec->limit = 0; + spec->stack_size = 0; + spec->heap_size = 0; + spec->nb_entry_points = 0; + spec->alloc_entry_points = 0; + spec->nb_names = 0; + spec->nb_resources = 0; + spec->entry_points = NULL; + spec->names = NULL; + spec->ordinals = NULL; + spec->resources = NULL; + return spec; +} + + +/******************************************************************* + * free_dll_spec + * + * Free dll spec file descriptor + */ +void free_dll_spec( DLLSPEC *spec ) +{ + int i; + + for (i = 0; i < spec->nb_entry_points; i++) + { + ORDDEF *odp = &spec->entry_points[i]; + free( odp->name ); + free( odp->export_name ); + free( odp->link_name ); + } + free( spec->file_name ); + free( spec->dll_name ); + free( spec->owner_name ); + free( spec->init_func ); + free( spec->entry_points ); + free( spec->names ); + free( spec->ordinals ); + free( spec->resources ); + free( spec ); +} + + /******************************************************************* * make_c_identifier * diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index d7cb76a932c..9e684740940 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -19,10 +19,11 @@ option can be specified, as described in the \fBOPTIONS\fR section. You have to specify exactly one of the following options, depending on what you want winebuild to generate. .TP -.BI \--spec=\ file.spec -Build a C file from a spec file (see \fBSPEC FILE SYNTAX\fR for -details). The resulting C file must be compiled and linked to the -other object files to build a working Wine dll. +.BI \--dll=\ filename +Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for +details), or from a standard Windows .def file. The resulting C file +must be compiled and linked to the other object files to build a +working Wine dll. .br In that mode, the .I input files @@ -34,7 +35,7 @@ other dlls. .TP .BI \--exe=\ name Build a C file for the named executable. This is basically the same as -the --spec mode except that it doesn't require a .spec file as input, +the --dll mode except that it doesn't require a .spec file as input, since an executable doesn't export functions. The resulting C file must be compiled and linked to the other object files to build a working Wine executable, and all the other object files must be listed @@ -130,7 +131,7 @@ imported from it is actually called). .BI \-M,\ --main-module= module Specify that we are building a 16-bit dll, that will ultimately be linked together with the 32-bit dll specified in \fImodule\fR. Only -meaningful in \fB--spec\fR mode. +meaningful in \fB--dll\fR mode. .TP .BI \-m,\ --mode= mode Set the executable or dll mode, which can be one of the following: