From 0a185bdb18855ca220ac28edded16855c435bf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Thu, 23 Sep 2004 20:27:30 +0000 Subject: [PATCH] Sync to Wine: Alexandre Julliard - Store all information about the current dll in a structure instead of using global variables to make it easier to reuse the parsing routines. - Added native mode dll support (based on a patch by Marcus Meissner). - Added support for building a dll from a .def file for cases where we don't want to write a full .spec. - Renamed --spec option to --dll for consistency. - Removed the Unicode exe modes, and instead detect automatically which mode to use based on the existence of main or wmain. - Automatically detect whether the entry point is main or WinMain instead of depending on the subsystem type. - Do not strip stdcall decoration in spec files. - Print a warning when DllRegisterServer and similar functions are not marked private. - Fill in the proper offsets in the resource directory instead of relying on the compiler to do it. Jukka Heinonen - Remove support for generating interrupt handlers. - DPMI programs now handle pending events. Robert Shearman - Fix proc name reported in delay load failure. Richard Cohen - Remove . from default library search path. Eric Pouech - added size information about most of the generated thunks (import, 16/32 relay...) - marked the wine thunks by inserting specific symbols (to be managed by wine's dbghelp) - removed the stabs generation: + mostly used by winedbg, and the previous item will replace it for dbghelp + still broken for gdb anyway - enhanced const correctness Pierre d'Herbemont - Detection of .size instruction. - Detection of the assembler name prefix. - Delayed import fix for Darwin and PowerPC Host. - Be more accurate on Darwin stack size. - Delay import fix on PowerPC hosts. Marcus Meissner - Use "LD" instead of "ld" in winebuild to be able to use a different ld or ld options. Dmitry Timoshkov - Add a few missing __ASM_NAME macros. svn path=/trunk/; revision=11014 --- reactos/tools/winebuild/Makefile | 2 +- reactos/tools/winebuild/build.h | 85 ++-- reactos/tools/winebuild/import.c | 516 ++++++++++------------- reactos/tools/winebuild/main.c | 188 +++++---- reactos/tools/winebuild/parser.c | 480 ++++++++++++++++----- reactos/tools/winebuild/relay.c | 143 ++++--- reactos/tools/winebuild/res16.c | 80 ++-- reactos/tools/winebuild/res32.c | 173 +++++--- reactos/tools/winebuild/spec16.c | 96 ++--- reactos/tools/winebuild/spec32.c | 465 ++++++++++---------- reactos/tools/winebuild/utils.c | 81 ++++ reactos/tools/winebuild/winebuild.man.in | 71 ++-- reactos/tools/winebuild/winehq2ros.patch | 86 ++++ reactos/tools/winebuild/winglue.h | 4 + 14 files changed, 1452 insertions(+), 1018 deletions(-) create mode 100644 reactos/tools/winebuild/winehq2ros.patch diff --git a/reactos/tools/winebuild/Makefile b/reactos/tools/winebuild/Makefile index 0c1d8c8b5e3..a9a4bf09ed1 100644 --- a/reactos/tools/winebuild/Makefile +++ b/reactos/tools/winebuild/Makefile @@ -20,7 +20,7 @@ OBJECTS = \ CLEAN_FILES = *.o $(TARGET) -HOST_CFLAGS = -D__USE_W32API -D__REACTOS__ -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine -I$(W32API_PATH)/include +HOST_CFLAGS = -D__USE_W32API -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine -I$(W32API_PATH)/include %.o: %.c $(HOST_CC) $(HOST_CFLAGS) -c $< -o $@ diff --git a/reactos/tools/winebuild/build.h b/reactos/tools/winebuild/build.h index ec350df36c7..281b4fd1864 100644 --- a/reactos/tools/winebuild/build.h +++ b/reactos/tools/winebuild/build.h @@ -50,15 +50,6 @@ typedef enum SPEC_WIN32 } SPEC_TYPE; -typedef enum -{ - SPEC_MODE_DLL, - SPEC_MODE_GUIEXE, - SPEC_MODE_CUIEXE, - SPEC_MODE_GUIEXE_UNICODE, - SPEC_MODE_CUIEXE_UNICODE -} SPEC_MODE; - typedef struct { int n_values; @@ -67,7 +58,6 @@ typedef struct typedef struct { - int n_args; char arg_types[21]; } ORD_FUNCTION; @@ -94,6 +84,31 @@ typedef struct } u; } ORDDEF; +typedef struct +{ + char *file_name; /* file name of the dll */ + char *dll_name; /* internal name of the dll */ + char *owner_name; /* name of the 32-bit dll owning this one */ + char *init_func; /* initialization routine */ + SPEC_TYPE type; /* type of dll (Win16/Win32) */ + int base; /* ordinal base */ + int limit; /* ordinal limit */ + int stack_size; /* exe stack size */ + int heap_size; /* exe heap size */ + int nb_entry_points; /* number of used entry points */ + int alloc_entry_points; /* number of allocated entry points */ + int nb_names; /* number of entry points with names */ + int nb_resources; /* number of resources */ + int characteristics; /* characteristics for the PE header */ + int subsystem; /* subsystem id */ + int subsystem_major; /* subsystem version major number */ + int subsystem_minor; /* subsystem version minor number */ + ORDDEF *entry_points; /* dll entry points */ + ORDDEF **names; /* array of entry point names (points into entry_points) */ + ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */ + struct resource *resources; /* array of dll resources (format differs between Win16/Win32) */ +} DLLSPEC; + /* entry point flags */ #define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */ #define FLAG_NONAME 0x02 /* don't import function by name */ @@ -101,10 +116,9 @@ typedef struct #define FLAG_RET64 0x08 /* function returns a 64-bit value */ #define FLAG_I386 0x10 /* function is i386 only */ #define FLAG_REGISTER 0x20 /* use register calling convention */ -#define FLAG_INTERRUPT 0x40 /* function is an interrupt handler */ -#define FLAG_PRIVATE 0x80 /* function is private (cannot be imported) */ +#define FLAG_PRIVATE 0x40 /* function is private (cannot be imported) */ -#define FLAG_FORWARD 0x100 /* function is a forwarded name */ +#define FLAG_FORWARD 0x80 /* function is a forwarded name */ /* Offset of a structure field relative to the start of the struct */ #define STRUCTOFFSET(type,field) ((int)&((type *)0)->field) @@ -147,60 +161,49 @@ 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); extern void add_import_dll( const char *name, int delay ); extern void add_ignore_symbol( const char *name ); extern void read_undef_symbols( char **argv ); -extern int resolve_imports( void ); -extern int output_imports( FILE *outfile ); -extern int load_res32_file( const char *name ); -extern int output_resources( FILE *outfile ); -extern void load_res16_file( const char *name ); -extern int output_res16_data( FILE *outfile ); -extern int output_res16_directory( unsigned char *buffer ); +extern int resolve_imports( DLLSPEC *spec ); +extern int output_imports( FILE *outfile, DLLSPEC *spec ); +extern int load_res32_file( const char *name, DLLSPEC *spec ); +extern void output_resources( FILE *outfile, DLLSPEC *spec ); +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 ); -extern void BuildSpec16File( FILE *outfile ); -extern void BuildSpec32File( FILE *outfile ); -extern void BuildDef32File( FILE *outfile ); +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 ); + +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 */ extern int current_line; -extern int nb_entry_points; -extern int nb_names; -extern int Base; -extern int Limit; -extern int DLLHeapSize; extern int UsePIC; extern int debugging; -extern int stack_size; extern int nb_debug_channels; extern int nb_lib_paths; extern int nb_errors; extern int display_warnings; extern int kill_at; -extern char *owner_name; -extern char *dll_name; -extern char *dll_file_name; -extern const char *init_func; extern char *input_file_name; extern const char *output_file_name; extern char **debug_channels; extern char **lib_path; -extern ORDDEF *EntryPoints[MAX_ORDINALS]; -extern ORDDEF *Ordinals[MAX_ORDINALS]; -extern ORDDEF *Names[MAX_ORDINALS]; -extern SPEC_MODE SpecMode; -extern SPEC_TYPE SpecType; - #endif /* __WINE_BUILD_H */ diff --git a/reactos/tools/winebuild/import.c b/reactos/tools/winebuild/import.c index 7a9d8c241f2..0abfef2379b 100644 --- a/reactos/tools/winebuild/import.c +++ b/reactos/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 @@ -26,32 +26,22 @@ #include #include #include +#include #ifdef HAVE_UNISTD_H # include #endif -#if defined(WIN32) -#include -#else -#include -#endif - +#include "windef.h" +#include "winbase.h" #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,13 +133,16 @@ static const char * const ppc_reg[32] = { "0", "1", "2", "3", "4", "5", "6", "7" /* compare function names; helper for resolve_imports */ static int name_cmp( const void *name, const void *entry ) { - return strcmp( *(char **)name, *(char **)entry ); + return strcmp( *(const char* const *)name, *(const char* const *)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 * const *)func1; + const ORDDEF *odp2 = *(const ORDDEF * const *)func2; + return strcmp( odp1->name ? odp1->name : odp1->export_name, + odp2->name ? odp2->name : odp2->export_name ); } /* locate a symbol in a (sorted) list */ @@ -165,14 +158,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 */ @@ -182,16 +176,19 @@ inline static void sort_symbols( char **table, int size ) qsort( table, size, sizeof(*table), name_cmp ); } +inline static void output_function_size( FILE *outfile, const char *name ) +{ +#ifdef HAVE_ASM_DOT_SIZE + fprintf( outfile, " \"\\t.size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\\n\"\n", name, name); +#endif +} + /* 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 ); } @@ -208,7 +205,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; } @@ -242,157 +239,44 @@ static char *open_library( const char *name ) { if ((fullname = try_library_path( lib_path[i], name ))) return fullname; } - if (!(fullname = try_library_path( ".", name ))) - fatal_error( "could not open .def file for %s\n", 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; + fatal_error( "could not open .def file for %s\n", name ); + return NULL; } /* 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 */ @@ -413,11 +297,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 )) @@ -495,13 +379,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++; } @@ -531,16 +412,16 @@ static int remove_symbol_holes(void) } /* add a symbol to the extra list, but only if needed */ -static int add_extra_symbol( const char **extras, int *count, const char *name ) +static int add_extra_symbol( const char **extras, int *count, const char *name, const DLLSPEC *spec ) { int i; if (!find_symbol( name, undef_symbols, nb_undef_symbols )) { /* check if the symbol is being exported by this dll */ - for (i = 0; i < nb_entry_points; i++) + for (i = 0; i < spec->nb_entry_points; i++) { - ORDDEF *odp = EntryPoints[i]; + ORDDEF *odp = &spec->entry_points[i]; if (odp->type == TYPE_STDCALL || odp->type == TYPE_CDECL || odp->type == TYPE_VARARGS || @@ -556,7 +437,7 @@ static int add_extra_symbol( const char **extras, int *count, const char *name ) } /* add the extra undefined symbols that will be contained in the generated spec file itself */ -static void add_extra_undef_symbols(void) +static void add_extra_undef_symbols( const DLLSPEC *spec ) { const char *extras[10]; int i, count = 0, nb_stubs = 0, nb_regs = 0; @@ -564,44 +445,36 @@ static void add_extra_undef_symbols(void) sort_symbols( undef_symbols, nb_undef_symbols ); - for (i = 0; i < nb_entry_points; i++) + for (i = 0; i < spec->nb_entry_points; i++) { - ORDDEF *odp = EntryPoints[i]; + ORDDEF *odp = &spec->entry_points[i]; if (odp->type == TYPE_STUB) nb_stubs++; if (odp->flags & FLAG_REGISTER) nb_regs++; } /* add symbols that will be contained in the spec file itself */ - switch (SpecMode) + if (!(spec->characteristics & IMAGE_FILE_DLL)) { - case SPEC_MODE_DLL: - break; - case SPEC_MODE_GUIEXE: - kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" ); - kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" ); - kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" ); - /* fall through */ - case SPEC_MODE_CUIEXE: - kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" ); - break; - case SPEC_MODE_GUIEXE_UNICODE: - kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" ); - kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" ); - kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" ); - /* fall through */ - case SPEC_MODE_CUIEXE_UNICODE: - kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" ); - break; + switch (spec->subsystem) + { + case IMAGE_SUBSYSTEM_WINDOWS_GUI: + case IMAGE_SUBSYSTEM_WINDOWS_CUI: + kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec ); + kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec ); + kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec ); + kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec ); + break; + } } if (nb_delayed) { - kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA" ); - kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" ); + kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec ); + kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec ); } if (nb_regs) - ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs" ); + ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs", spec ); if (nb_delayed || nb_stubs) - ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException" ); + ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec ); /* make sure we import the dlls that contain these functions */ if (kernel_imports) add_import_dll( "kernel32", 0 ); @@ -615,18 +488,19 @@ static void add_extra_undef_symbols(void) } /* check if a given imported dll is not needed, taking forwards into account */ -static int check_unused( const struct import* imp ) +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 = Base; i <= Limit; i++) + for (i = spec->base; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[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 */ } @@ -638,35 +512,26 @@ static int check_unused( const struct import* imp ) static const char *ldcombine_files( char **argv ) { int i, len = 0; - char *cmd; + char *cmd, *ldcmd; int fd, err; -#if defined(WIN32) - char tmppath[MAX_PATH]; - char tmpfile[MAX_PATH]; -#endif -#if defined(WIN32) - if (GetTempPathA(MAX_PATH, tmppath) == 0) return NULL; - if (GetTempFileNameA(tmppath, "WNB", 0, tmpfile) == 0) fatal_error( "could not generate a temp file\n" ); - ld_tmp_file = xstrdup( tmpfile ); - if ((fd = open( ld_tmp_file, O_RDONLY )) == -1) -#else - if (output_file_name && output_file_name[0]) + if (output_file_name && output_file_name[0]) { - ld_tmp_file = xmalloc( PATH_MAX ); + ld_tmp_file = xmalloc( strlen(output_file_name) + 10 ); strcpy( ld_tmp_file, output_file_name ); strcat( ld_tmp_file, ".XXXXXX.o" ); } - else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" ); - if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" ); -#endif + else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" ); + if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" ); close( fd ); atexit( remove_ld_tmp_file ); + ldcmd = getenv("LD"); + if (!ldcmd) ldcmd = "ld"; for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1; - cmd = xmalloc( len + strlen(ld_tmp_file) + 10 ); - sprintf( cmd, "ld -r -o %s", ld_tmp_file ); + cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ldcmd) ); + sprintf( cmd, "%s -r -o %s", ldcmd, ld_tmp_file ); for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] ); err = system( cmd ); if (err) fatal_error( "ld -r failed with status %d\n", err ); @@ -677,6 +542,8 @@ static const char *ldcombine_files( char **argv ) /* read in the list of undefined symbols */ void read_undef_symbols( char **argv ) { + static const char name_prefix[] = __ASM_NAME(""); + static const int prefix_len = sizeof(name_prefix) - 1; FILE *f; char buffer[1024]; int err; @@ -702,6 +569,7 @@ void read_undef_symbols( char **argv ) p = buffer; while (*p == ' ') p++; if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2; + if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len; add_undef_symbol( p ); } if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err ); @@ -725,13 +593,13 @@ static void remove_ignored_symbols(void) } /* resolve the imports for a Win32 module */ -int resolve_imports( void ) +int resolve_imports( DLLSPEC *spec ) { int i, j; if (nb_undef_symbols == -1) return 0; /* no symbol file specified */ - add_extra_undef_symbols(); + add_extra_undef_symbols( spec ); remove_ignored_symbols(); for (i = 0; i < nb_imports; i++) @@ -740,19 +608,19 @@ int resolve_imports( void ) 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; } } /* remove all the holes in the undef symbols list */ - if (!remove_symbol_holes() && check_unused( imp )) + 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--; } @@ -765,6 +633,7 @@ static int output_immediate_imports( FILE *outfile ) { int i, j, pos; int nb_imm = nb_imports - nb_delayed; + static const char import_thunks[] = "__wine_spec_import_thunks"; if (!nb_imm) goto done; @@ -788,7 +657,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; } @@ -800,18 +669,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" ); } @@ -822,18 +691,21 @@ static int output_immediate_imports( FILE *outfile ) fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" ); pos = 20 * (nb_imm + 1); /* offset of imports.data from start of imports */ fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) ); + fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", import_thunks); + for (i = 0; i < nb_imports; i++) { 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 ); @@ -880,19 +752,23 @@ static int output_immediate_imports( FILE *outfile ) #error You need to define import thunks for your architecture! #endif fprintf( outfile, "\"\n" ); + output_function_size( outfile, name ); } pos += 4; } - fprintf( outfile, "\".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" ); + output_function_size( outfile, import_thunks ); + fprintf( outfile, " \".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" ); done: return nb_imm; } /* output the delayed import table of a Win32 module */ -static int output_delayed_imports( FILE *outfile ) +static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) { int i, idx, j, pos; + static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders"; + static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks"; if (!nb_delayed) goto done; @@ -902,8 +778,9 @@ static int output_delayed_imports( FILE *outfile ) 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" ); @@ -926,31 +803,33 @@ static int output_delayed_imports( FILE *outfile ) { 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" ); @@ -958,9 +837,9 @@ static int output_delayed_imports( FILE *outfile ) /* check if there's some stub defined. if so, exception struct * is already defined, so don't emit it twice */ - for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break; + for (i = 0; i < spec->nb_entry_points; i++) if (spec->entry_points[i].type == TYPE_STUB) break; - if (i == nb_entry_points) { + if (i == spec->nb_entry_points) { fprintf( outfile, "struct exc_record {\n" ); fprintf( outfile, " unsigned int code, flags;\n" ); fprintf( outfile, " void *rec, *addr;\n" ); @@ -993,7 +872,7 @@ static int output_delayed_imports( FILE *outfile ) fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.params = 2;\n" ); fprintf( outfile, " rec.info[0] = imd->szName;\n" ); - fprintf( outfile, " rec.info[1] = *pINT + 2;\n" ); + fprintf( outfile, " rec.info[1] = *pINT;\n" ); fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); fprintf( outfile, "#else\n" ); @@ -1008,6 +887,7 @@ static int output_delayed_imports( FILE *outfile ) fprintf( outfile, "#endif\n" ); fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) ); + fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_loaders); fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" ); fprintf( outfile, " \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" ); #if defined(__i386__) @@ -1020,25 +900,31 @@ static int output_delayed_imports( FILE *outfile ) fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" ); fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" ); #elif defined(__powerpc__) +# if defined(__APPLE__) +/* On darwin an extra 56 bytes must be allowed for the linkage area+param area */ +# define extra_stack_storage 56 +# else +# define extra_stack_storage 0 +# endif /* Save all callee saved registers into a stackframe. */ - fprintf( outfile, " \"\\tstwu %s, -48(%s)\\n\"\n", ppc_reg[1], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]); - fprintf( outfile, " \"\\tstw %s, 40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]); + fprintf( outfile, " \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg[1], 48+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]); /* r0 -> r3 (arg1) */ fprintf( outfile, " \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]); /* save return address */ fprintf( outfile, " \"\\tmflr %s\\n\"\n", ppc_reg[0]); - fprintf( outfile, " \"\\tstw %s, 44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]); /* Call the __wine_delay_load function, arg1 is arg1. */ fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n"); @@ -1047,27 +933,28 @@ static int output_delayed_imports( FILE *outfile ) fprintf( outfile, " \"\\tmtctr %s\\n\"\n", ppc_reg[3]); /* restore all saved registers and drop stackframe. */ - fprintf( outfile, " \"\\tlwz %s, 4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]); - fprintf( outfile, " \"\\tlwz %s, 40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[3], 4+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[4], 8+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]); /* Load return value from call into return register */ - fprintf( outfile, " \"\\tlwz %s, 44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]); + fprintf( outfile, " \"\\tlwz %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]); fprintf( outfile, " \"\\tmtlr %s\\n\"\n", ppc_reg[0]); - fprintf( outfile, " \"\\taddi %s, %s, 48\\n\"\n", ppc_reg[1], ppc_reg[1]); + fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[1], ppc_reg[1], 48+extra_stack_storage); /* branch to ctr register. */ - fprintf( outfile, "\"bctr\\n\"\n"); + fprintf( outfile, " \"bctr\\n\"\n"); #else #error You need to defined delayed import thunks for your architecture! #endif + output_function_size( outfile, "__wine_delay_load_asm" ); for (i = idx = 0; i < nb_imports; i++) { @@ -1075,7 +962,10 @@ static int output_delayed_imports( FILE *outfile ) 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__) @@ -1085,31 +975,52 @@ static int output_delayed_imports( FILE *outfile ) fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j ); fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" ); #elif defined(__powerpc__) - /* g0 is a function scratch register or so I understand. */ - /* First load the upper half-word, and then the lower part */ - fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[0], idx); - fprintf( outfile, " \"\\tli %s, %d\\n\"\n", ppc_reg[0], j); +#ifdef __APPLE__ + /* On Darwin we can use r0 and r2 */ + /* Upper part in r2 */ + fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[2], idx); + /* Lower part + r2 -> r0, Note we can't use r0 directly */ + fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[2], j); fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n"); +#else /* __APPLE__ */ + /* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */ + /* Save r13 on the stack */ + fprintf( outfile, " \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]); + fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]); + /* Upper part in r13 */ + fprintf( outfile, " \"\\tlis %s, %d\\n\"\n", ppc_reg[13], idx); + /* Lower part + r13 -> r0, Note we can't use r0 directly */ + fprintf( outfile, " \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[13], j); + /* Restore r13 */ + fprintf( outfile, " \"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[13], ppc_reg[1]); + fprintf( outfile, " \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]); + fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n"); +#endif /* __APPLE__ */ #else #error You need to defined delayed import thunks for your architecture! #endif + output_function_size( outfile, name ); } idx++; } + output_function_size( outfile, delayed_import_loaders ); fprintf( outfile, "\n \".data\\n\\t.align %d\\n\"\n", get_alignment(8) ); + fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_thunks); pos = nb_delayed * 32; for (i = 0; i < nb_imports; i++) { 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 ); @@ -1139,8 +1050,9 @@ static int output_delayed_imports( FILE *outfile ) fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]); fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]); fprintf( outfile, "\t\"\\tstw %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]); - fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos); - fprintf( outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]); + + fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("delay_imports") "+ %d") "\\n\"\n", ppc_reg[9], pos); + fprintf( outfile, "\t\"\\tla %s, " ppc_low (__ASM_NAME("delay_imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]); fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]); fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]); @@ -1155,8 +1067,10 @@ static int output_delayed_imports( FILE *outfile ) #error You need to define delayed import thunks for your architecture! #endif fprintf( outfile, "\n" ); + output_function_size( outfile, name ); } } + output_function_size( outfile, delayed_import_thunks ); fprintf( outfile, "\".text\");\n" ); fprintf( outfile, "#ifndef __GNUC__\n" ); fprintf( outfile, "}\n" ); @@ -1170,8 +1084,8 @@ static int output_delayed_imports( FILE *outfile ) /* output the import and delayed import tables of a Win32 module * returns number of DLLs exported in 'immediate' mode */ -int output_imports( FILE *outfile ) +int output_imports( FILE *outfile, DLLSPEC *spec ) { - output_delayed_imports( outfile ); + output_delayed_imports( outfile, spec ); return output_immediate_imports( outfile ); } diff --git a/reactos/tools/winebuild/main.c b/reactos/tools/winebuild/main.c index 4596d6756dd..98877bdbb3f 100644 --- a/reactos/tools/winebuild/main.c +++ b/reactos/tools/winebuild/main.c @@ -29,27 +29,17 @@ #include #include #include +#include #include #ifdef HAVE_GETOPT_H # include #endif +#include "windef.h" +#include "winbase.h" #include "build.h" -ORDDEF *EntryPoints[MAX_ORDINALS]; -ORDDEF *Ordinals[MAX_ORDINALS]; -ORDDEF *Names[MAX_ORDINALS]; - -SPEC_MODE SpecMode = SPEC_MODE_DLL; -SPEC_TYPE SpecType = SPEC_WIN32; - -int Base = MAX_ORDINALS; -int Limit = 0; -int DLLHeapSize = 0; int UsePIC = 0; -int stack_size = 0; -int nb_entry_points = 0; -int nb_names = 0; int nb_debug_channels = 0; int nb_lib_paths = 0; int nb_errors = 0; @@ -63,27 +53,23 @@ int debugging = 1; int debugging = 0; #endif -char *owner_name = NULL; -char *dll_name = NULL; -char *dll_file_name = NULL; -const char *init_func = NULL; char **debug_channels = NULL; 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, @@ -94,18 +80,43 @@ enum exec_mode_values static enum exec_mode_values exec_mode = MODE_NONE; /* set the dll file name from the input file name */ -static void set_dll_file_name( const char *name ) +static void set_dll_file_name( const char *name, DLLSPEC *spec ) { char *p; - if (dll_file_name) return; + if (spec->file_name) return; if ((p = strrchr( name, '\\' ))) name = p + 1; if ((p = strrchr( name, '/' ))) name = p + 1; - dll_file_name = xmalloc( strlen(name) + 5 ); - strcpy( dll_file_name, name ); - if ((p = strrchr( dll_file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0; - if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".dll" ); + spec->file_name = xmalloc( strlen(name) + 5 ); + strcpy( spec->file_name, name ); + 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" ); +} + +/* set the dll subsystem */ +static void set_subsystem( const char *subsystem, DLLSPEC *spec ) +{ + char *major, *minor, *str = xstrdup( subsystem ); + + if ((major = strchr( str, ':' ))) *major++ = 0; + if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE; + else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; + else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; + else fatal_error( "Invalid subsystem name '%s'\n", subsystem ); + if (major) + { + if ((minor = strchr( major, '.' ))) + { + *minor++ = 0; + spec->subsystem_minor = atoi( minor ); + } + spec->subsystem_major = atoi( major ); + } + free( str ); } /* cleanup on program exit */ @@ -135,15 +146,15 @@ static const char usage_str[] = " -K FLAGS Compiler flags (only -KPIC is supported)\n" " -l --library=LIB Import the specified library\n" " -L --library-path=DIR Look for imports libraries in DIR\n" -" -m --exe-mode=MODE Set the executable mode (cui|gui|cuiw|guiw)\n" " -M --main-module=MODULE Set the name of the main module for a Win16 dll\n" " -N --dll-name=DLLNAME Set the DLL name (default: from input file name)\n" " -o --output=NAME Set the output file name (default: stdout)\n" " -r --res=RSRC.RES Load resources from RSRC.RES\n" +" --subsystem=SUBSYS Set the subsystem (one of native, windows, console)\n" " --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" @@ -153,12 +164,13 @@ 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, LONG_OPT_RELAY16, LONG_OPT_RELAY32, + LONG_OPT_SUBSYSTEM, LONG_OPT_VERSION }; @@ -166,12 +178,13 @@ 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 }, + { "subsystem",1, 0, LONG_OPT_SUBSYSTEM }, { "version", 0, 0, LONG_OPT_VERSION }, /* aliases for short options */ { "source-dir", 1, 0, 'C' }, @@ -184,7 +197,6 @@ static const struct option long_options[] = { "kill-at", 0, 0, 'k' }, { "library", 1, 0, 'l' }, { "library-path", 1, 0, 'L' }, - { "exe-mode", 1, 0, 'm' }, { "main-module", 1, 0, 'M' }, { "dll-name", 1, 0, 'N' }, { "output", 1, 0, 'o' }, @@ -206,7 +218,7 @@ static void set_exec_mode( enum exec_mode_values mode ) } /* parse options from the argv array and remove all the recognized ones */ -static char **parse_options( int argc, char **argv ) +static char **parse_options( int argc, char **argv, DLLSPEC *spec ) { char *p; int optc; @@ -222,14 +234,14 @@ static char **parse_options( int argc, char **argv ) /* ignored */ break; case 'F': - dll_file_name = xstrdup( optarg ); + spec->file_name = xstrdup( optarg ); break; case 'H': if (!isdigit(optarg[0])) fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg ); - DLLHeapSize = atoi(optarg); - if (DLLHeapSize > 65535) - fatal_error( "Invalid heap size %d, maximum is 65535\n", DLLHeapSize ); + spec->heap_size = atoi(optarg); + if (spec->heap_size > 65535) + fatal_error( "Invalid heap size %d, maximum is 65535\n", spec->heap_size ); break; case 'I': /* ignored */ @@ -242,18 +254,18 @@ static char **parse_options( int argc, char **argv ) lib_path[nb_lib_paths++] = xstrdup( optarg ); break; case 'M': - owner_name = xstrdup( optarg ); - SpecType = SPEC_WIN16; + spec->owner_name = xstrdup( optarg ); + spec->type = SPEC_WIN16; break; case 'N': - dll_name = xstrdup( optarg ); + spec->dll_name = xstrdup( optarg ); break; case 'd': add_import_dll( optarg, 1 ); break; case 'e': - init_func = xstrdup( optarg ); - if ((p = strchr( init_func, '@' ))) *p = 0; /* kill stdcall decoration */ + spec->init_func = xstrdup( optarg ); + if ((p = strchr( spec->init_func, '@' ))) *p = 0; /* kill stdcall decoration */ break; case 'f': if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1; @@ -280,13 +292,6 @@ static char **parse_options( int argc, char **argv ) case 'l': add_import_dll( optarg, 0 ); break; - case 'm': - if (!strcmp( optarg, "gui" )) SpecMode = SPEC_MODE_GUIEXE; - else if (!strcmp( optarg, "cui" )) SpecMode = SPEC_MODE_CUIEXE; - else if (!strcmp( optarg, "guiw" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE; - else if (!strcmp( optarg, "cuiw" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE; - else usage(1); - break; case 'o': if (unlink( optarg ) == -1 && errno != ENOENT) fatal_error( "Unable to create output file '%s'\n", optarg ); @@ -302,24 +307,24 @@ static char **parse_options( int argc, char **argv ) case 'w': display_warnings = 1; break; - case LONG_OPT_SPEC: - set_exec_mode( MODE_SPEC ); - input_file = open_input_file( NULL, optarg ); - set_dll_file_name( 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 ); - set_dll_file_name( optarg ); + spec_file_name = xstrdup( optarg ); + set_dll_file_name( optarg, spec ); break; case LONG_OPT_EXE: set_exec_mode( MODE_EXE ); if ((p = strrchr( optarg, '/' ))) p++; else p = optarg; - dll_file_name = xmalloc( strlen(p) + 5 ); - strcpy( dll_file_name, p ); - if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".exe" ); - if (SpecMode == SPEC_MODE_DLL) SpecMode = SPEC_MODE_GUIEXE; + spec->file_name = xmalloc( strlen(p) + 5 ); + strcpy( spec->file_name, p ); + if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" ); + if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; break; case LONG_OPT_DEBUG: set_exec_mode( MODE_DEBUG ); @@ -330,6 +335,9 @@ static char **parse_options( int argc, char **argv ) case LONG_OPT_RELAY32: set_exec_mode( MODE_RELAY32 ); break; + case LONG_OPT_SUBSYSTEM: + set_subsystem( optarg, spec ); + break; case LONG_OPT_VERSION: printf( "winebuild version " PACKAGE_VERSION "\n" ); exit(0); @@ -343,28 +351,28 @@ static char **parse_options( int argc, char **argv ) /* load all specified resource files */ -static void load_resources( char *argv[] ) +static void load_resources( char *argv[], DLLSPEC *spec ) { int i; char **ptr, **last; - switch (SpecType) + switch (spec->type) { case SPEC_WIN16: - for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i] ); + for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i], spec ); break; case SPEC_WIN32: for (i = 0; i < nb_res_files; i++) { - if (!load_res32_file( res_files[i] )) + if (!load_res32_file( res_files[i], spec )) fatal_error( "%s is not a valid Win32 resource file\n", res_files[i] ); } /* load any resource file found in the remaining arguments */ for (ptr = last = argv; *ptr; ptr++) { - if (!load_res32_file( *ptr )) + if (!load_res32_file( *ptr, spec )) *last++ = *ptr; /* not a resource file, keep it in the list */ } *last = NULL; @@ -372,67 +380,67 @@ static void load_resources( char *argv[] ) } } +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 = alloc_dll_spec(); + output_file = stdout; - argv = parse_options( argc, argv ); + argv = parse_options( argc, argv, spec ); switch(exec_mode) { - case MODE_SPEC: - load_resources( argv ); - if (!ParseTopLevel( input_file )) break; - switch (SpecType) + case MODE_DLL: + spec->characteristics |= IMAGE_FILE_DLL; + load_resources( argv, spec ); + if (!parse_input_file( spec )) break; + switch (spec->type) { case SPEC_WIN16: -#if defined(__REACTOS__) fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" ); -#else - if (argv[0]) - fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); - BuildSpec16File( output_file ); -#endif break; case SPEC_WIN32: read_undef_symbols( argv ); - BuildSpec32File( output_file ); + BuildSpec32File( output_file, spec ); break; default: assert(0); } break; case MODE_EXE: - if (SpecType == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); - load_resources( argv ); + 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 ); + 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 (SpecType == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); - if (!ParseTopLevel( input_file )) break; - BuildDef32File( output_file ); + 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 ); break; case MODE_RELAY16: -#if defined(__REACTOS__) fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" ); -#else - if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); - BuildRelays16( output_file ); -#endif break; case MODE_RELAY32: -#if defined(__REACTOS__) fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" ); -#else - if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); - BuildRelays32( output_file ); -#endif break; default: usage(1); diff --git a/reactos/tools/winebuild/parser.c b/reactos/tools/winebuild/parser.c index 63d4bca1fff..ce853433f4d 100644 --- a/reactos/tools/winebuild/parser.c +++ b/reactos/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 * @@ -32,12 +32,8 @@ #include #include -#ifdef WIN32 #include "windef.h" #include "winbase.h" -#else -#include "winglue.h" -#endif #include "build.h" int current_line = 0; @@ -47,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 */ @@ -67,7 +66,6 @@ static const char * const FlagNames[] = "ret64", /* FLAG_RET64 */ "i386", /* FLAG_I386 */ "register", /* FLAG_REGISTER */ - "interrupt", /* FLAG_INTERRUPT */ "private", /* FLAG_PRIVATE */ NULL }; @@ -80,7 +78,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 */ @@ -113,7 +116,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; @@ -138,12 +141,23 @@ static const char * GetToken( int allow_eol ) } +static ORDDEF *add_entry_point( DLLSPEC *spec ) +{ + if (spec->nb_entry_points == spec->alloc_entry_points) + { + spec->alloc_entry_points += 128; + spec->entry_points = xrealloc( spec->entry_points, + spec->alloc_entry_points * sizeof(*spec->entry_points) ); + } + return &spec->entry_points[spec->nb_entry_points++]; +} + /******************************************************************* - * ParseVariable + * parse_spec_variable * - * Parse a variable definition. + * Parse a variable definition in a .spec file. */ -static int ParseVariable( ORDDEF *odp ) +static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec ) { char *endptr; int *value_array; @@ -151,7 +165,7 @@ static int ParseVariable( ORDDEF *odp ) int value_array_size; const char *token; - if (SpecType == SPEC_WIN32) + if (spec->type == SPEC_WIN32) { error( "'variable' not supported in Win32, use 'extern' instead\n" ); return 0; @@ -201,16 +215,16 @@ static int ParseVariable( ORDDEF *odp ) /******************************************************************* - * ParseExportFunction + * parse_spec_export * - * Parse a function definition. + * Parse an exported function definition in a .spec file. */ -static int ParseExportFunction( ORDDEF *odp ) +static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec ) { const char *token; unsigned int i; - switch(SpecType) + switch(spec->type) { case SPEC_WIN16: if (odp->type == TYPE_STDCALL) @@ -225,11 +239,6 @@ static int ParseExportFunction( ORDDEF *odp ) error( "'pascal' not supported for Win32\n" ); return 0; } - if (odp->flags & FLAG_INTERRUPT) - { - error( "'interrupt' not supported for Win32\n" ); - return 0; - } break; default: break; @@ -273,7 +282,7 @@ static int ParseExportFunction( ORDDEF *odp ) return 0; } - if (SpecType == SPEC_WIN32) + if (spec->type == SPEC_WIN32) { if (strcmp(token, "long") && strcmp(token, "ptr") && @@ -310,7 +319,7 @@ static int ParseExportFunction( ORDDEF *odp ) odp->link_name = xstrdup( token ); if (strchr( odp->link_name, '.' )) { - if (SpecType == SPEC_WIN16) + if (spec->type == SPEC_WIN16) { error( "Forwarded functions not supported for Win16\n" ); return 0; @@ -323,17 +332,17 @@ static int ParseExportFunction( ORDDEF *odp ) /******************************************************************* - * ParseEquate + * parse_spec_equate * - * Parse an 'equate' definition. + * Parse an 'equate' definition in a .spec file. */ -static int ParseEquate( ORDDEF *odp ) +static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec ) { char *endptr; int value; const char *token; - if (SpecType == SPEC_WIN32) + if (spec->type == SPEC_WIN32) { error( "'equate' not supported for Win32\n" ); return 0; @@ -351,11 +360,11 @@ static int ParseEquate( ORDDEF *odp ) /******************************************************************* - * ParseStub + * parse_spec_stub * - * Parse a 'stub' definition. + * Parse a 'stub' definition in a .spec file */ -static int ParseStub( ORDDEF *odp ) +static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec ) { odp->u.func.arg_types[0] = '\0'; odp->link_name = xstrdup(""); @@ -364,15 +373,15 @@ static int ParseStub( ORDDEF *odp ) /******************************************************************* - * ParseExtern + * parse_spec_extern * - * Parse an 'extern' definition. + * Parse an 'extern' definition in a .spec file. */ -static int ParseExtern( ORDDEF *odp ) +static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec ) { const char *token; - if (SpecType == SPEC_WIN16) + if (spec->type == SPEC_WIN16) { error( "'extern' not supported for Win16, use 'variable' instead\n" ); return 0; @@ -396,11 +405,11 @@ static int ParseExtern( ORDDEF *odp ) /******************************************************************* - * 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; @@ -422,32 +431,18 @@ 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) +static int parse_spec_ordinal( int ordinal, DLLSPEC *spec ) { const char *token; - ORDDEF *odp = xmalloc( sizeof(*odp) ); + ORDDEF *odp = add_entry_point( spec ); memset( odp, 0, sizeof(*odp) ); - EntryPoints[nb_entry_points++] = odp; if (!(token = GetToken(0))) goto error; @@ -462,32 +457,31 @@ static int ParseOrdinal(int ordinal) } 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 ); odp->lineno = current_line; odp->ordinal = ordinal; switch(odp->type) { case TYPE_VARIABLE: - if (!ParseVariable( odp )) 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 )) goto error; + if (!parse_spec_export( odp, spec )) goto error; break; case TYPE_ABS: - if (!ParseEquate( odp )) goto error; + if (!parse_spec_equate( odp, spec )) goto error; break; case TYPE_STUB: - if (!ParseStub( odp )) goto error; + if (!parse_spec_stub( odp, spec )) goto error; break; case TYPE_EXTERN: - if (!ParseExtern( odp )) goto error; + if (!parse_spec_extern( odp, spec )) goto error; break; default: assert( 0 ); @@ -497,8 +491,7 @@ static int ParseOrdinal(int ordinal) if (odp->flags & FLAG_I386) { /* ignore this entry point on non-Intel archs */ - EntryPoints[--nb_entry_points] = NULL; - free( odp ); + spec->nb_entry_points--; return 1; } #endif @@ -515,15 +508,20 @@ static int ParseOrdinal(int ordinal) error( "Ordinal number %d too large\n", ordinal ); goto error; } - if (ordinal > Limit) Limit = ordinal; - if (ordinal < Base) Base = ordinal; + if (ordinal > spec->limit) spec->limit = ordinal; + if (ordinal < spec->base) spec->base = ordinal; odp->ordinal = ordinal; - if (Ordinals[ordinal]) + } + + if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE)) + { + if (!strcmp( odp->name, "DllRegisterServer" ) || + !strcmp( odp->name, "DllUnregisterServer" ) || + !strcmp( odp->name, "DllGetClassObject" ) || + !strcmp( odp->name, "DllCanUnloadNow" )) { - error( "Duplicate ordinal %d\n", ordinal ); - goto error; + warning( "Function %s should be marked private\n", odp->name ); } - Ordinals[ordinal] = odp; } if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME) @@ -533,7 +531,7 @@ static int ParseOrdinal(int ordinal) error( "Nameless function needs an explicit ordinal number\n" ); goto error; } - if (SpecType != SPEC_WIN32) + if (spec->type != SPEC_WIN32) { error( "Nameless functions not supported for Win16\n" ); goto error; @@ -542,79 +540,135 @@ static int ParseOrdinal(int ordinal) else odp->export_name = odp->name; odp->name = NULL; } - else Names[nb_names++] = odp; return 1; error: - EntryPoints[--nb_entry_points] = NULL; + spec->nb_entry_points--; free( odp->name ); - free( odp ); return 0; } static int name_compare( const void *name1, const void *name2 ) { - ORDDEF *odp1 = *(ORDDEF **)name1; - ORDDEF *odp2 = *(ORDDEF **)name2; + const ORDDEF *odp1 = *(const ORDDEF * const *)name1; + const ORDDEF *odp2 = *(const ORDDEF * const *)name2; return strcmp( odp1->name, odp2->name ); } /******************************************************************* - * sort_names + * assign_names * - * Sort the name array and catch duplicates. + * Build the name array and catch duplicates. */ -static void sort_names(void) +static void assign_names( DLLSPEC *spec ) { - int i; + int i, j; - if (!nb_names) return; + spec->nb_names = 0; + for (i = 0; i < spec->nb_entry_points; i++) + if (spec->entry_points[i].name) spec->nb_names++; + if (!spec->nb_names) return; + + spec->names = xmalloc( spec->nb_names * sizeof(spec->names[0]) ); + for (i = j = 0; i < spec->nb_entry_points; i++) + if (spec->entry_points[i].name) spec->names[j++] = &spec->entry_points[i]; /* sort the list of names */ - qsort( Names, nb_names, sizeof(Names[0]), name_compare ); + qsort( spec->names, spec->nb_names, sizeof(spec->names[0]), name_compare ); /* check for duplicate names */ - for (i = 0; i < nb_names - 1; i++) + for (i = 0; i < spec->nb_names - 1; i++) { - if (!strcmp( Names[i]->name, Names[i+1]->name )) + if (!strcmp( spec->names[i]->name, spec->names[i+1]->name )) { - current_line = max( Names[i]->lineno, Names[i+1]->lineno ); + current_line = max( spec->names[i]->lineno, spec->names[i+1]->lineno ); error( "'%s' redefined\n%s:%d: First defined here\n", - Names[i]->name, input_file_name, - min( Names[i]->lineno, Names[i+1]->lineno ) ); + spec->names[i]->name, input_file_name, + min( spec->names[i]->lineno, spec->names[i+1]->lineno ) ); } } } +/******************************************************************* + * assign_ordinals + * + * Build the ordinal array. + */ +static void assign_ordinals( DLLSPEC *spec ) +{ + int i, count, ordinal; + + /* start assigning from base, or from 1 if no ordinal defined yet */ + if (spec->base == MAX_ORDINALS) spec->base = 1; + if (spec->limit < spec->base) spec->limit = spec->base; + + count = max( spec->limit + 1, spec->base + spec->nb_entry_points ); + spec->ordinals = xmalloc( count * sizeof(spec->ordinals[0]) ); + memset( spec->ordinals, 0, count * sizeof(spec->ordinals[0]) ); + + /* fill in all explicitly specified ordinals */ + for (i = 0; i < spec->nb_entry_points; i++) + { + ordinal = spec->entry_points[i].ordinal; + if (ordinal == -1) continue; + if (spec->ordinals[ordinal]) + { + current_line = max( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ); + error( "ordinal %d redefined\n%s:%d: First defined here\n", + ordinal, input_file_name, + min( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ) ); + } + else spec->ordinals[ordinal] = &spec->entry_points[i]; + } + + /* now assign ordinals to the rest */ + for (i = 0, ordinal = spec->base; i < spec->nb_names; i++) + { + if (spec->names[i]->ordinal != -1) continue; /* already has an ordinal */ + while (spec->ordinals[ordinal]) ordinal++; + if (ordinal >= MAX_ORDINALS) + { + current_line = spec->names[i]->lineno; + fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS ); + } + spec->names[i]->ordinal = ordinal; + spec->ordinals[ordinal] = spec->names[i]; + } + if (ordinal > spec->limit) spec->limit = ordinal; +} + /******************************************************************* - * ParseTopLevel + * parse_spec_file * - * Parse a spec file. + * Parse a .spec file. */ -int ParseTopLevel( FILE *file ) +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; if (strcmp(token, "@") == 0) { - if (SpecType != SPEC_WIN32) + if (spec->type != SPEC_WIN32) { error( "'@' ordinals not supported for Win16\n" ); continue; } - if (!ParseOrdinal( -1 )) continue; + if (!parse_spec_ordinal( -1, spec )) continue; } else if (IsNumberString(token)) { - if (!ParseOrdinal( atoi(token) )) continue; + if (!parse_spec_ordinal( atoi(token), spec )) continue; } else { @@ -625,7 +679,245 @@ int ParseTopLevel( FILE *file ) } current_line = 0; /* no longer parsing the input file */ - sort_names(); + assign_names( spec ); + assign_ordinals( spec ); + return !nb_errors; +} + + +/******************************************************************* + * 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; } diff --git a/reactos/tools/winebuild/relay.c b/reactos/tools/winebuild/relay.c index 87877f3f055..f4a4f5e1023 100644 --- a/reactos/tools/winebuild/relay.c +++ b/reactos/tools/winebuild/relay.c @@ -32,25 +32,22 @@ #include "build.h" -#if defined(__GNUC__) && !defined(__svr4__) -static const int use_stabs = 1; -#else -static const int use_stabs = 0; -#endif - #ifdef __i386__ static void function_header( FILE *outfile, const char *name ) { fprintf( outfile, "\n\t.align %d\n", get_alignment(4) ); - if (use_stabs) - fprintf( outfile, "\t.stabs \"%s:F1\",36,0,0," __ASM_NAME("%s") "\n", name, name); fprintf( outfile, "\t" __ASM_FUNC("%s") "\n", name ); fprintf( outfile, "\t.globl " __ASM_NAME("%s") "\n", name ); fprintf( outfile, __ASM_NAME("%s") ":\n", name ); } +static void function_footer( FILE *outfile, const char *name ) +{ + fprintf( outfile, ".size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\n", name, name ); +} + /******************************************************************* * BuildCallFrom16Core * @@ -444,6 +441,10 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho /* Return to return stub which will return to caller */ fprintf( outfile, "\tlret $12\n" ); } + if (thunk) function_footer( outfile, "__wine_call_from_16_thunk" ); + else if (reg_func) function_footer( outfile, "__wine_call_from_16_regs" ); + else if (short_ret) function_footer( outfile, "__wine_call_from_16_word" ); + else function_footer( outfile, "__wine_call_from_16_long" ); } @@ -605,6 +606,9 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func ) /* Jump to the called routine */ fprintf( outfile, "\t.byte 0x66\n" ); fprintf( outfile, "\tlret\n" ); + + /* Function footer */ + function_footer( outfile, name ); } @@ -648,6 +652,9 @@ static void BuildRet16Func( FILE *outfile ) fprintf( outfile, "\tlret\n" ); + /* Function footer */ + function_footer( outfile, "CallTo16_Ret" ); + /* Declare the return address and data selector variables */ fprintf( outfile, "\n\t.align %d\n", get_alignment(4) ); @@ -756,9 +763,6 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx ) /* Function header */ fprintf( outfile, "\n\t.align %d\n", get_alignment(4) ); - if (use_stabs) - fprintf( outfile, ".stabs \"CALL32_%s:F1\",36,0,0," __ASM_NAME("CALL32_%s") "\n", - name, name ); fprintf( outfile, "\t.globl " __ASM_NAME("CALL32_%s") "\n", name ); fprintf( outfile, __ASM_NAME("CALL32_%s") ":\n", name ); @@ -882,6 +886,7 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx ) fprintf( outfile, "\tpopl %%edi\n" ); fprintf( outfile, "\tpopl %%ebp\n" ); fprintf( outfile, "\tret\n" ); + fprintf( outfile, ".size " __ASM_NAME("CALL32_%s") ", . - " __ASM_NAME("CALL32_%s") "\n", name, name ); } static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx ) @@ -907,6 +912,8 @@ static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx ) } fprintf( outfile, "\tlret\n" ); + fprintf( outfile, ".size " __ASM_NAME("CALL32_%s_Ret") ", . - " __ASM_NAME("CALL32_%s_Ret") "\n", name, name ); + /* Declare the return address variable */ fprintf( outfile, "\n\t.globl " __ASM_NAME("CALL32_%s_RetAddr") "\n", name ); @@ -1036,10 +1043,65 @@ static void BuildCallFrom32Regs( FILE *outfile ) fprintf( outfile, "\tpopl %%ds\n" ); fprintf( outfile, "\tiret\n" ); + function_footer( outfile, "__wine_call_from_32_regs" ); function_header( outfile, "__wine_call_from_32_restore_regs" ); fprintf( outfile, "\tleal 4(%%esp),%%ecx\n" ); fprintf( outfile, "\tjmp 2b\n" ); + function_footer( outfile, "__wine_call_from_32_restore_regs" ); +} + + +/******************************************************************* + * BuildPendingEventCheck + * + * Build a function that checks whether there are any + * pending DPMI events. + * + * Stack layout: + * + * (sp+12) long eflags + * (sp+6) long cs + * (sp+2) long ip + * (sp) word fs + * + * On entry to function, fs register points to a valid TEB. + * On exit from function, stack will be popped. + */ +static void BuildPendingEventCheck( FILE *outfile ) +{ + /* Function header */ + + function_header( outfile, "DPMI_PendingEventCheck" ); + + /* Check for pending events. */ + + fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", + STRUCTOFFSET(TEB,vm86_pending) ); + fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" ); + + fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", + STRUCTOFFSET(TEB,dpmi_vif) ); + + fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" ); + + /* Process pending events. */ + + fprintf( outfile, "\tsti\n" ); + + /* Start cleanup. Restore fs register. */ + + fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" ); + fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Cleanup") ":\n" ); + fprintf( outfile, "\tpopw %%fs\n" ); + + /* Return from function. */ + + fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Return") "\n" ); + fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Return") ":\n" ); + fprintf( outfile, "\tiret\n" ); + + function_footer( outfile, "DPMI_PendingEventCheck" ); } @@ -1050,26 +1112,12 @@ static void BuildCallFrom32Regs( FILE *outfile ) */ void BuildRelays16( FILE *outfile ) { - char buffer[1024]; - /* File header */ fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" ); fprintf( outfile, "\t.text\n" ); - if (output_file_name && use_stabs) - { - getcwd(buffer, sizeof(buffer)); - fprintf( outfile, "\t.file\t\"%s\"\n", output_file_name ); - - /* - * The stabs help the internal debugger as they are an indication that it - * is sensible to step into a thunk/trampoline. - */ - fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer); - fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", output_file_name ); - fprintf( outfile, "Code_Start:\n\n" ); - } + fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_16") ":\n\n" ); fprintf( outfile, __ASM_NAME("Call16_Start") ":\n" ); fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Start") "\n" ); @@ -1101,24 +1149,11 @@ void BuildRelays16( FILE *outfile ) fprintf( outfile, __ASM_NAME("Call16_End") ":\n" ); fprintf( outfile, "\t.globl " __ASM_NAME("Call16_End") "\n" ); - - if (use_stabs) - { - fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n"); - fprintf( outfile, ".Letext:\n"); - - /* Some versions of gdb need to have the filename data for - each section, so output it again for the data section. */ - if (output_file_name) - { - fprintf( outfile, ".stabs \"%s/\",100,0,0,Data_Start\n", buffer); - fprintf( outfile, ".stabs \"%s\",100,0,0,Data_Start\n", output_file_name ); - fprintf( outfile, "Data_Start:\n\n" ); - } - } + fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_16") ",. - " __ASM_NAME("__wine_spec_thunk_text_16") "\n" ); /* The whole Call16_Ret segment must lie within the .data section */ fprintf( outfile, "\n\t.data\n" ); + fprintf( outfile, __ASM_NAME("__wine_spec_thunk_data_16") ":\n\n" ); fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Ret_Start") "\n" ); fprintf( outfile, __ASM_NAME("Call16_Ret_Start") ":\n" ); @@ -1131,9 +1166,13 @@ void BuildRelays16( FILE *outfile ) /* CBClientThunkSLEx return stub */ BuildCallTo32CBClientRet( outfile, TRUE ); + /* Pending DPMI events check stub */ + BuildPendingEventCheck( outfile ); + /* End of Call16_Ret segment */ fprintf( outfile, "\n\t.globl " __ASM_NAME("Call16_Ret_End") "\n" ); fprintf( outfile, __ASM_NAME("Call16_Ret_End") ":\n" ); + fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_data_16") ",. - " __ASM_NAME("__wine_spec_thunk_data_16") "\n" ); } /******************************************************************* @@ -1147,30 +1186,12 @@ void BuildRelays32( FILE *outfile ) fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" ); fprintf( outfile, "\t.text\n" ); - - if (output_file_name && use_stabs) - { - char buffer[1024]; - getcwd(buffer, sizeof(buffer)); - fprintf( outfile, "\t.file\t\"%s\"\n", output_file_name ); - - /* - * The stabs help the internal debugger as they are an indication that it - * is sensible to step into a thunk/trampoline. - */ - fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer); - fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", output_file_name ); - fprintf( outfile, "Code_Start:\n\n" ); - } + fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_32") ":\n\n" ); /* 32-bit register entry point */ BuildCallFrom32Regs( outfile ); - if (use_stabs) - { - fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n"); - fprintf( outfile, ".Letext:\n"); - } + fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_32") ",. - " __ASM_NAME("__wine_spec_thunk_text_32") "\n" ); } #else /* __i386__ */ diff --git a/reactos/tools/winebuild/res16.c b/reactos/tools/winebuild/res16.c index 198e2abd767..17ff05f3410 100644 --- a/reactos/tools/winebuild/res16.c +++ b/reactos/tools/winebuild/res16.c @@ -37,12 +37,8 @@ #include #endif -#ifdef WIN32 #include "windef.h" #include "winbase.h" -#else -#include "winglue.h" -#endif #include "build.h" #define ALIGNMENT 2 /* alignment for resource data */ @@ -73,28 +69,29 @@ struct res_type unsigned int nb_names; /* total number of names */ }; -static struct resource *resources; -static int nb_resources; - -static struct res_type *res_types; -static int nb_types; /* total number of types */ +/* top level of the resource tree */ +struct res_tree +{ + struct res_type *types; /* types array */ + unsigned int nb_types; /* total number of types */ +}; static const unsigned char *file_pos; /* current position in resource file */ static const unsigned char *file_end; /* end of resource file */ static const char *file_name; /* current resource file name */ -inline static struct resource *add_resource(void) +inline static struct resource *add_resource( DLLSPEC *spec ) { - resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) ); - return &resources[nb_resources++]; + spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) ); + return &spec->resources[spec->nb_resources++]; } -static struct res_type *add_type( const struct resource *res ) +static struct res_type *add_type( struct res_tree *tree, const struct resource *res ) { struct res_type *type; - res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) ); - type = &res_types[nb_types++]; + tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) ); + type = &tree->types[tree->nb_types++]; type->type = &res->type; type->res = res; type->nb_names = 0; @@ -155,9 +152,9 @@ static void get_string( struct string_id *str ) } /* load the next resource from the current file */ -static void load_next_resource(void) +static void load_next_resource( DLLSPEC *spec ) { - struct resource *res = add_resource(); + struct resource *res = add_resource( spec ); get_string( &res->type ); get_string( &res->name ); @@ -169,7 +166,7 @@ static void load_next_resource(void) } /* load a Win16 .res file */ -void load_res16_file( const char *name ) +void load_res16_file( const char *name, DLLSPEC *spec ) { int fd; void *base; @@ -190,7 +187,7 @@ void load_res16_file( const char *name ) file_name = name; file_pos = base; file_end = file_pos + st.st_size; - while (file_pos < file_end) load_next_resource(); + while (file_pos < file_end) load_next_resource( spec ); } /* compare two strings/ids */ @@ -218,19 +215,32 @@ static int cmp_res( const void *ptr1, const void *ptr2 ) } /* build the 2-level (type,name) resource tree */ -static void build_resource_tree(void) +static struct res_tree *build_resource_tree( DLLSPEC *spec ) { int i; + struct res_tree *tree; struct res_type *type = NULL; - qsort( resources, nb_resources, sizeof(*resources), cmp_res ); + qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res ); - for (i = 0; i < nb_resources; i++) + tree = xmalloc( sizeof(*tree) ); + tree->types = NULL; + tree->nb_types = 0; + + for (i = 0; i < spec->nb_resources; i++) { - if (!i || cmp_string( &resources[i].type, &resources[i-1].type )) /* new type */ - type = add_type( &resources[i] ); + if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */ + type = add_type( tree, &spec->resources[i] ); type->nb_names++; } + return tree; +} + +/* free the resource tree */ +static void free_resource_tree( struct res_tree *tree ) +{ + free( tree->types ); + free( tree ); } inline static void put_byte( unsigned char **buffer, unsigned char val ) @@ -258,19 +268,19 @@ static void output_string( unsigned char **buffer, const char *str ) } /* output the resource data */ -int output_res16_data( FILE *outfile ) +int output_res16_data( FILE *outfile, DLLSPEC *spec ) { const struct resource *res; unsigned char *buffer, *p; int i, total; - if (!nb_resources) return 0; + if (!spec->nb_resources) return 0; - for (i = total = 0, res = resources; i < nb_resources; i++, res++) + for (i = total = 0, res = spec->resources; i < spec->nb_resources; i++, res++) total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK; buffer = p = xmalloc( total ); - for (i = 0, res = resources; i < nb_resources; i++, res++) + for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) { memcpy( p, res->data, res->data_size ); p += res->data_size; @@ -282,25 +292,26 @@ int output_res16_data( FILE *outfile ) } /* output the resource definitions */ -int output_res16_directory( unsigned char *buffer ) +int output_res16_directory( unsigned char *buffer, DLLSPEC *spec ) { int i, offset, res_offset = 0; unsigned int j; + struct res_tree *tree; const struct res_type *type; const struct resource *res; unsigned char *start = buffer; - build_resource_tree(); + tree = build_resource_tree( spec ); offset = 4; /* alignment + terminator */ - offset += nb_types * 8; /* typeinfo structures */ - offset += nb_resources * 12; /* nameinfo structures */ + offset += tree->nb_types * 8; /* typeinfo structures */ + offset += spec->nb_resources * 12; /* nameinfo structures */ put_word( &buffer, ALIGNMENT ); /* type and name structures */ - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { if (type->type->str) { @@ -335,7 +346,7 @@ int output_res16_directory( unsigned char *buffer ) /* name strings */ - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { if (type->type->str) output_string( &buffer, type->type->str ); for (j = 0, res = type->res; j < type->nb_names; j++, res++) @@ -346,5 +357,6 @@ int output_res16_directory( unsigned char *buffer ) put_byte( &buffer, 0 ); /* names terminator */ if ((buffer - start) & 1) put_byte( &buffer, 0 ); /* align on word boundary */ + free_resource_tree( tree ); return buffer - start; } diff --git a/reactos/tools/winebuild/res32.c b/reactos/tools/winebuild/res32.c index 4454433c848..ca90d7124b2 100644 --- a/reactos/tools/winebuild/res32.c +++ b/reactos/tools/winebuild/res32.c @@ -37,12 +37,8 @@ #include #endif -#ifdef WIN32 #include "windef.h" #include "winbase.h" -#else -#include "winglue.h" -#endif #include "build.h" /* Unicode string or integer id */ @@ -68,6 +64,7 @@ struct res_name const struct string_id *name; /* name */ const struct resource *res; /* resource */ int nb_languages; /* number of languages */ + unsigned int name_offset; /* offset of name in resource dir */ }; /* type level of the resource tree */ @@ -77,24 +74,28 @@ struct res_type struct res_name *names; /* names array */ unsigned int nb_names; /* total number of names */ unsigned int nb_id_names; /* number of names that have a numeric id */ + unsigned int name_offset; /* offset of type name in resource dir */ }; -static struct resource *resources; -static int nb_resources; - -static struct res_type *res_types; -static int nb_types; /* total number of types */ -static int nb_id_types; /* number of types that have a numeric id */ +/* top level of the resource tree */ +struct res_tree +{ + struct res_type *types; /* types array */ + unsigned int nb_types; /* total number of types */ +}; static const unsigned char *file_pos; /* current position in resource file */ static const unsigned char *file_end; /* end of resource file */ static const char *file_name; /* current resource file name */ +/* size of a resource directory with n entries */ +#define RESDIR_SIZE(n) ((4 + 2 * (n)) * sizeof(int)) -inline static struct resource *add_resource(void) + +inline static struct resource *add_resource( DLLSPEC *spec ) { - resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) ); - return &resources[nb_resources++]; + spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) ); + return &spec->resources[spec->nb_resources++]; } static inline unsigned int strlenW( const WCHAR *str ) @@ -122,23 +123,22 @@ static struct res_name *add_name( struct res_type *type, const struct resource * return name; } -static struct res_type *add_type( const struct resource *res ) +static struct res_type *add_type( struct res_tree *tree, const struct resource *res ) { struct res_type *type; - res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) ); - type = &res_types[nb_types++]; + tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) ); + type = &tree->types[tree->nb_types++]; type->type = &res->type; type->names = NULL; type->nb_names = 0; type->nb_id_names = 0; - if (!type->type->str) nb_id_types++; return type; } /* get the next word from the current resource file */ static WORD get_word(void) { - WORD ret = *(WORD *)file_pos; + WORD ret = *(const WORD *)file_pos; file_pos += sizeof(WORD); if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name ); return ret; @@ -147,7 +147,7 @@ static WORD get_word(void) /* get the next dword from the current resource file */ static DWORD get_dword(void) { - DWORD ret = *(DWORD *)file_pos; + DWORD ret = *(const DWORD *)file_pos; file_pos += sizeof(DWORD); if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name ); return ret; @@ -156,7 +156,7 @@ static DWORD get_dword(void) /* get a string from the current resource file */ static void get_string( struct string_id *str ) { - if (*(WCHAR *)file_pos == 0xffff) + if (*(const WCHAR *)file_pos == 0xffff) { get_word(); /* skip the 0xffff */ str->str = NULL; @@ -164,7 +164,7 @@ static void get_string( struct string_id *str ) } else { - WCHAR *p = xmalloc( (strlenW((WCHAR*)file_pos) + 1) * sizeof(WCHAR) ); + WCHAR *p = xmalloc( (strlenW((const WCHAR*)file_pos) + 1) * sizeof(WCHAR) ); str->str = p; str->id = 0; while ((*p++ = get_word())); @@ -188,10 +188,10 @@ static int check_header(void) } /* load the next resource from the current file */ -static void load_next_resource(void) +static void load_next_resource( DLLSPEC *spec ) { DWORD hdr_size; - struct resource *res = add_resource(); + struct resource *res = add_resource( spec ); res->data_size = (get_dword() + 3) & ~3; hdr_size = get_dword(); @@ -207,12 +207,12 @@ static void load_next_resource(void) get_dword(); /* skip version */ get_dword(); /* skip characteristics */ - file_pos = (char *)res->data + res->data_size; + file_pos = (const char *)res->data + res->data_size; if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name ); } /* load a Win32 .res file */ -int load_res32_file( const char *name ) +int load_res32_file( const char *name, DLLSPEC *spec ) { int fd, ret; void *base; @@ -235,7 +235,7 @@ int load_res32_file( const char *name ) file_end = file_pos + st.st_size; if ((ret = check_header())) { - while (file_pos < file_end) load_next_resource(); + while (file_pos < file_end) load_next_resource( spec ); } close( fd ); return ret; @@ -267,27 +267,43 @@ static int cmp_res( const void *ptr1, const void *ptr2 ) } /* build the 3-level (type,name,language) resource tree */ -static void build_resource_tree(void) +static struct res_tree *build_resource_tree( DLLSPEC *spec ) { int i; + struct res_tree *tree; struct res_type *type = NULL; struct res_name *name = NULL; - qsort( resources, nb_resources, sizeof(*resources), cmp_res ); + qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res ); - for (i = 0; i < nb_resources; i++) + tree = xmalloc( sizeof(*tree) ); + tree->types = NULL; + tree->nb_types = 0; + + for (i = 0; i < spec->nb_resources; i++) { - if (!i || cmp_string( &resources[i].type, &resources[i-1].type )) /* new type */ + if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */ { - type = add_type( &resources[i] ); - name = add_name( type, &resources[i] ); + type = add_type( tree, &spec->resources[i] ); + name = add_name( type, &spec->resources[i] ); } - else if (cmp_string( &resources[i].name, &resources[i-1].name )) /* new name */ + else if (cmp_string( &spec->resources[i].name, &spec->resources[i-1].name )) /* new name */ { - name = add_name( type, &resources[i] ); + name = add_name( type, &spec->resources[i] ); } else name->nb_languages++; } + return tree; +} + +/* free the resource tree */ +static void free_resource_tree( struct res_tree *tree ) +{ + int i; + + for (i = 0; i < tree->nb_types; i++) free( tree->types[i].names ); + free( tree->types ); + free( tree ); } /* output a Unicode string */ @@ -302,21 +318,22 @@ static void output_string( FILE *outfile, const WCHAR *name ) } /* output the resource definitions */ -int output_resources( FILE *outfile ) +void output_resources( FILE *outfile, DLLSPEC *spec ) { - int i, j, k; - unsigned int n; - const struct res_type *type; - const struct res_name *name; + int i, j, k, nb_id_types; + unsigned int n, offset, data_offset; + struct res_tree *tree; + struct res_type *type; + struct res_name *name; const struct resource *res; - if (!nb_resources) return 0; + if (!spec->nb_resources) return; - build_resource_tree(); + tree = build_resource_tree( spec ); /* resource data */ - for (i = 0, res = resources; i < nb_resources; i++, res++) + for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) { const unsigned int *p = res->data; int size = res->data_size / 4; @@ -348,69 +365,86 @@ int output_resources( FILE *outfile ) /* resource directory definition */ - fprintf( outfile, "#define OFFSETOF(field) ((char*)&((struct res_struct *)0)->field - (char*)((struct res_struct *) 0))\n" ); fprintf( outfile, "static struct res_struct{\n" ); fprintf( outfile, " struct res_dir type_dir;\n" ); - fprintf( outfile, " struct res_dir_entry type_entries[%d];\n", nb_types ); + fprintf( outfile, " struct res_dir_entry type_entries[%d];\n", tree->nb_types ); + offset = RESDIR_SIZE( tree->nb_types ); - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { + offset += RESDIR_SIZE( type->nb_names ); fprintf( outfile, " struct res_dir name_%d_dir;\n", i ); fprintf( outfile, " struct res_dir_entry name_%d_entries[%d];\n", i, type->nb_names ); for (n = 0, name = type->names; n < type->nb_names; n++, name++) { + offset += RESDIR_SIZE( name->nb_languages ); fprintf( outfile, " struct res_dir lang_%d_%d_dir;\n", i, n ); fprintf( outfile, " struct res_dir_entry lang_%d_%d_entries[%d];\n", i, n, name->nb_languages ); } } - fprintf( outfile, " struct res_data_entry data_entries[%d];\n", nb_resources ); + fprintf( outfile, " struct res_data_entry data_entries[%d];\n", spec->nb_resources ); + offset += spec->nb_resources * 4 * sizeof(int); - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++) { if (type->type->str) + { + type->name_offset = offset | 0x80000000; + offset += (strlenW(type->type->str)+1) * sizeof(unsigned short); fprintf( outfile, " unsigned short type_%d_name[%d];\n", i, strlenW(type->type->str)+1 ); + } + else + { + type->name_offset = type->type->id; + nb_id_types++; + } + for (n = 0, name = type->names; n < type->nb_names; n++, name++) { if (name->name->str) + { + name->name_offset = offset | 0x80000000; + offset += (strlenW(name->name->str)+1) * sizeof(unsigned short); fprintf( outfile, " unsigned short name_%d_%d_name[%d];\n", i, n, strlenW(name->name->str)+1 ); + } + else name->name_offset = name->name->id; } } /* resource directory contents */ fprintf( outfile, "} resources = {\n" ); - fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", nb_types - nb_id_types, nb_id_types ); + fprintf( outfile, " { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types ); /* dump the type directory */ + offset = RESDIR_SIZE( tree->nb_types ); fprintf( outfile, " {\n" ); - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { - if (!type->type->str) - fprintf( outfile, " { 0x%04x, OFFSETOF(name_%d_dir) | 0x80000000 },\n", - type->type->id, i ); - else - fprintf( outfile, " { OFFSETOF(type_%d_name) | 0x80000000, OFFSETOF(name_%d_dir) | 0x80000000 },\n", - i, i ); + fprintf( outfile, " { 0x%08x, 0x%08x },\n", type->name_offset, offset | 0x80000000 ); + offset += RESDIR_SIZE( type->nb_names ); + for (n = 0, name = type->names; n < type->nb_names; n++, name++) + offset += RESDIR_SIZE( name->nb_languages ); } fprintf( outfile, " },\n" ); + data_offset = offset; + offset = RESDIR_SIZE( tree->nb_types ); + /* dump the names and languages directories */ - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { fprintf( outfile, " { 0, 0, 0, 0, %d, %d }, /* name_%d_dir */\n {\n", type->nb_names - type->nb_id_names, type->nb_id_names, i ); + offset += RESDIR_SIZE( type->nb_names ); for (n = 0, name = type->names; n < type->nb_names; n++, name++) { - if (!name->name->str) - fprintf( outfile, " { 0x%04x, OFFSETOF(lang_%d_%d_dir) | 0x80000000 },\n", - name->name->id, i, n ); - else - fprintf( outfile, " { OFFSETOF(name_%d_%d_name) | 0x80000000, OFFSETOF(lang_%d_%d_dir) | 0x80000000 },\n", - i, n, i, n ); + fprintf( outfile, " { 0x%08x, 0x%08x },\n", name->name_offset, offset | 0x80000000 ); + offset += RESDIR_SIZE( name->nb_languages ); } fprintf( outfile, " },\n" ); @@ -420,8 +454,8 @@ int output_resources( FILE *outfile ) name->nb_languages, i, n ); for (k = 0, res = name->res; k < name->nb_languages; k++, res++) { - fprintf( outfile, " { 0x%04x, OFFSETOF(data_entries[%d]) },\n", - res->lang, res - resources ); + fprintf( outfile, " { 0x%04x, 0x%08x },\n", + res->lang, data_offset + (res - spec->resources) * 4 * sizeof(int) ); } fprintf( outfile, " },\n" ); } @@ -429,13 +463,14 @@ int output_resources( FILE *outfile ) /* dump the resource data entries */ fprintf( outfile, " {\n" ); - for (i = 0, res = resources; i < nb_resources; i++, res++) + for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++) { - fprintf( outfile, " { res_%d, sizeof(res_%d), 0, 0 },\n", i, i ); + fprintf( outfile, " { res_%d, sizeof(res_%d), 0, 0 }, /* %08x */\n", i, i, + data_offset + i * 4 * sizeof(int) ); } /* dump the name strings */ - for (i = 0, type = res_types; i < nb_types; i++, type++) + for (i = 0, type = tree->types; i < tree->nb_types; i++, type++) { if (type->type->str) { @@ -451,6 +486,6 @@ int output_resources( FILE *outfile ) } } } - fprintf( outfile, " }\n};\n#undef OFFSETOF\n\n" ); - return nb_resources; + fprintf( outfile, " }\n};\n\n" ); + free_resource_tree( tree ); } diff --git a/reactos/tools/winebuild/spec16.c b/reactos/tools/winebuild/spec16.c index 43188a85bf3..852c65dd7f1 100644 --- a/reactos/tools/winebuild/spec16.c +++ b/reactos/tools/winebuild/spec16.c @@ -111,7 +111,7 @@ static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp ) * as a byte stream into the assembly code. */ static int BuildModule16( FILE *outfile, int max_code_offset, - int max_data_offset ) + int max_data_offset, DLLSPEC *spec ) { int i; char *buffer; @@ -142,7 +142,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset, pModule->next = 0; pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE; pModule->dgroup = 2; - pModule->heap_size = DLLHeapSize; + pModule->heap_size = spec->heap_size; pModule->stack_size = 0; pModule->ip = 0; pModule->cs = 0; @@ -172,8 +172,8 @@ static int BuildModule16( FILE *outfile, int max_code_offset, pModule->fileinfo = (int)pFileInfo - (int)pModule; memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) ); pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) - + strlen(dll_file_name); - strcpy( pFileInfo->szPathName, dll_file_name ); + + strlen(spec->file_name); + strcpy( pFileInfo->szPathName, spec->file_name ); pstr = (char *)pFileInfo + pFileInfo->cBytes + 1; /* Segment table */ @@ -201,7 +201,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset, pstr = (char *)pSegment; pstr = (char *)(((long)pstr + 3) & ~3); pModule->res_table = (int)pstr - (int)pModule; - pstr += output_res16_directory( pstr ); + pstr += output_res16_directory( pstr, spec ); /* Imported names table */ @@ -215,16 +215,16 @@ static int BuildModule16( FILE *outfile, int max_code_offset, pstr = (char *)(((long)pstr + 3) & ~3); pModule->name_table = (int)pstr - (int)pModule; /* First entry is module name */ - *pstr = strlen( dll_name ); - strcpy( pstr + 1, dll_name ); + *pstr = strlen( spec->dll_name ); + strcpy( pstr + 1, spec->dll_name ); strupper( pstr + 1 ); pstr += *pstr + 1; *pstr++ = 0; *pstr++ = 0; /* Store all ordinals */ - for (i = 1; i <= Limit; i++) + for (i = 1; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; WORD ord = i; if (!odp || !odp->name[0]) continue; *pstr = strlen( odp->name ); @@ -240,10 +240,10 @@ static int BuildModule16( FILE *outfile, int max_code_offset, pstr = (char *)(((long)pstr + 3) & ~3); pModule->entry_table = (int)pstr - (int)pModule; - for (i = 1; i <= Limit; i++) + for (i = 1; i <= spec->limit; i++) { int selector = 0; - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp) continue; switch (odp->type) @@ -317,8 +317,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset, * extern LONG WINAPI PREFIX_CallFrom16_C_long_xxx( FARPROC func, LPBYTE args ); * extern void WINAPI PREFIX_CallFrom16_C_regs_xxx( FARPROC func, LPBYTE args, * CONTEXT86 *context ); - * extern void WINAPI PREFIX_CallFrom16_C_intr_xxx( FARPROC func, LPBYTE args, - * CONTEXT86 *context ); * * where 'C' is the calling convention ('p' for pascal or 'c' for cdecl), * and each 'x' is an argument ('w'=word, 's'=signed word, 'l'=long, @@ -333,10 +331,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset, * For register functions, the arguments (if present) are converted just * the same as for normal functions, but in addition the CONTEXT86 pointer * filled with the current register values is passed to the 32-bit routine. - * (An 'intr' interrupt handler routine is treated exactly like a register - * routine, except that upon return, the flags word pushed onto the stack - * by the interrupt is removed by the 16-bit call stub.) - * */ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char *prefix ) { @@ -360,7 +354,6 @@ static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1; else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1; - else if (!strncmp( "intr_", profile + 2, 5 )) reg_func = 2; else if (strncmp( "long_", profile + 2, 5 )) { fprintf( stderr, "Invalid function name '%s', ignored\n", profile ); @@ -467,7 +460,6 @@ static const char *get_function_name( const ORDDEF *odp ) (odp->type == TYPE_PASCAL) ? "p" : (odp->type == TYPE_VARARGS) ? "v" : "c", (odp->flags & FLAG_REGISTER) ? "regs" : - (odp->flags & FLAG_INTERRUPT) ? "intr" : (odp->flags & FLAG_RET16) ? "word" : "long", odp->u.func.arg_types ); return buffer; @@ -479,8 +471,8 @@ static const char *get_function_name( const ORDDEF *odp ) */ static int Spec16TypeCompare( const void *e1, const void *e2 ) { - const ORDDEF *odp1 = *(const ORDDEF **)e1; - const ORDDEF *odp2 = *(const ORDDEF **)e2; + const ORDDEF *odp1 = *(const ORDDEF * const *)e1; + const ORDDEF *odp2 = *(const ORDDEF * const *)e2; int retval; int type1 = odp1->type; int type2 = odp2->type; @@ -490,8 +482,8 @@ static int Spec16TypeCompare( const void *e1, const void *e2 ) if ((retval = type1 - type2) != 0) return retval; - type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT); - type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT); + type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER); + type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER); if ((retval = type1 - type2) != 0) return retval; @@ -504,14 +496,14 @@ static int Spec16TypeCompare( const void *e1, const void *e2 ) * * Output the functions for stub entry points */ -static void output_stub_funcs( FILE *outfile ) +static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec ) { int i; char *p; - for (i = 0; i <= Limit; i++) + for (i = 0; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp || odp->type != TYPE_STUB) continue; fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); @@ -528,7 +520,7 @@ static void output_stub_funcs( FILE *outfile ) fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE ); fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.params = 2;\n" ); - fprintf( outfile, " rec.info[0] = \"%s\";\n", dll_file_name ); + fprintf( outfile, " rec.info[0] = \"%s\";\n", spec->file_name ); fprintf( outfile, " rec.info[1] = func;\n" ); fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); @@ -538,9 +530,9 @@ static void output_stub_funcs( FILE *outfile ) fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" ); break; } - for (i = 0; i <= Limit; i++) + for (i = 0; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp || odp->type != TYPE_STUB) continue; odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 ); strcpy( odp->link_name, "__wine_stub_" ); @@ -557,7 +549,7 @@ static void output_stub_funcs( FILE *outfile ) * * Build a Win16 assembly file from a spec file. */ -void BuildSpec16File( FILE *outfile ) +void BuildSpec16File( FILE *outfile, DLLSPEC *spec ) { ORDDEF **type, **typelist; int i, nFuncs, nTypes; @@ -580,22 +572,22 @@ void BuildSpec16File( FILE *outfile ) memset( data, 0, 16 ); data_offset = 16; - if (!dll_name) /* set default name from file name */ + if (!spec->dll_name) /* set default name from file name */ { char *p; - dll_name = xstrdup( dll_file_name ); - if ((p = strrchr( dll_name, '.' ))) *p = 0; + spec->dll_name = xstrdup( spec->file_name ); + if ((p = strrchr( spec->dll_name, '.' ))) *p = 0; } - output_stub_funcs( outfile ); + output_stub_funcs( outfile, spec ); /* Build sorted list of all argument types, without duplicates */ - typelist = (ORDDEF **)calloc( Limit+1, sizeof(ORDDEF *) ); + typelist = (ORDDEF **)calloc( spec->limit+1, sizeof(ORDDEF *) ); - for (i = nFuncs = 0; i <= Limit; i++) + for (i = nFuncs = 0; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp) continue; switch (odp->type) { @@ -627,15 +619,15 @@ void BuildSpec16File( FILE *outfile ) char profile[101]; strcpy( profile, get_function_name( typelist[i] )); - BuildCallFrom16Func( outfile, profile, dll_file_name ); + BuildCallFrom16Func( outfile, profile, spec->file_name ); } #endif /* Output the DLL functions prototypes */ - for (i = 0; i <= Limit; i++) + for (i = 0; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp) continue; switch(odp->type) { @@ -701,8 +693,6 @@ void BuildSpec16File( FILE *outfile ) break; } - if (typelist[i]->flags & FLAG_INTERRUPT) argsize += 2; - /* build the arg types bit fields */ arg_types[0] = arg_types[1] = 0; for (j = 0; typelist[i]->u.func.arg_types[j]; j++) @@ -719,13 +709,13 @@ void BuildSpec16File( FILE *outfile ) } arg_types[j / 10] |= type << (3 * (j % 10)); } - if (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) arg_types[0] |= ARG_REGISTER; + if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER; if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16; #ifdef __i386__ fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n", - make_c_identifier(dll_file_name), profile, - (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) ? "regs": + make_c_identifier(spec->file_name), profile, + (typelist[i]->flags & FLAG_REGISTER) ? "regs": (typelist[i]->flags & FLAG_RET16) ? "word" : "long" ); if (argsize) fprintf( outfile, " 0x%04x, 0xca66, %d, { 0x%08x, 0x%08x } },\n", @@ -745,9 +735,9 @@ void BuildSpec16File( FILE *outfile ) } fprintf( outfile, " },\n {\n" ); - for (i = 0; i <= Limit; i++) + for (i = 0; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp) continue; switch (odp->type) { @@ -767,7 +757,7 @@ void BuildSpec16File( FILE *outfile ) type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare ); assert( type ); - fprintf( outfile, " /* %s.%d */ ", dll_name, i ); + fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i ); #ifdef __i386__ fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n", #else @@ -797,8 +787,8 @@ void BuildSpec16File( FILE *outfile ) /* Build the module */ - module_size = BuildModule16( outfile, code_offset, data_offset ); - res_size = output_res16_data( outfile ); + module_size = BuildModule16( outfile, code_offset, data_offset, spec ); + res_size = output_res16_data( outfile, spec ); /* Output the DLL descriptor */ @@ -816,14 +806,14 @@ void BuildSpec16File( FILE *outfile ) fprintf( outfile, " sizeof(Module),\n" ); fprintf( outfile, " &code_segment,\n" ); fprintf( outfile, " Data_Segment,\n" ); - fprintf( outfile, " \"%s\",\n", owner_name ); + fprintf( outfile, " \"%s\",\n", spec->owner_name ); fprintf( outfile, " %s\n", res_size ? "resource_data" : "0" ); fprintf( outfile, "};\n" ); /* Output the DLL constructor */ - sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) ); - sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(dll_file_name) ); + sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) ); + sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) ); output_dll_init( outfile, constructor, destructor ); fprintf( outfile, diff --git a/reactos/tools/winebuild/spec32.c b/reactos/tools/winebuild/spec32.c index 855ba3aefc5..331ef915468 100644 --- a/reactos/tools/winebuild/spec32.c +++ b/reactos/tools/winebuild/spec32.c @@ -61,48 +61,42 @@ static int string_compare( const void *ptr1, const void *ptr2 ) * * Generate an internal name for an entry point. Used for stubs etc. */ -static const char *make_internal_name( const ORDDEF *odp, const char *prefix ) +static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const char *prefix ) { static char buffer[256]; if (odp->name || odp->export_name) { char *p; - sprintf( buffer, "__wine_%s_%s_%s", prefix, dll_file_name, + sprintf( buffer, "__wine_%s_%s_%s", prefix, spec->file_name, odp->name ? odp->name : odp->export_name ); /* make sure name is a legal C identifier */ for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break; if (!*p) return buffer; } - sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(dll_file_name), odp->ordinal ); + sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(spec->file_name), odp->ordinal ); return buffer; } /******************************************************************* - * AssignOrdinals + * declare_weak_function * - * Assign ordinals to all entry points. + * Output a prototype for a weak function. */ -static void AssignOrdinals(void) +static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params) { - int i, ordinal; - - if ( !nb_names ) return; - - /* start assigning from Base, or from 1 if no ordinal defined yet */ - if (Base == MAX_ORDINALS) Base = 1; - for (i = 0, ordinal = Base; i < nb_names; i++) - { - if (Names[i]->ordinal != -1) continue; /* already has an ordinal */ - while (Ordinals[ordinal]) ordinal++; - if (ordinal >= MAX_ORDINALS) - { - current_line = Names[i]->lineno; - fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS ); - } - Names[i]->ordinal = ordinal; - Ordinals[ordinal] = Names[i]; - } - if (ordinal > Limit) Limit = ordinal; + fprintf( outfile, "#ifdef __GNUC__\n" ); + fprintf( outfile, "# ifdef __APPLE__\n" ); + fprintf( outfile, "extern %s %s(%s) __attribute__((weak_import));\n", ret_type, name, params ); + fprintf( outfile, "static %s (*__wine_spec_weak_%s)(%s) = %s;\n", ret_type, name, params, name ); + fprintf( outfile, "#define %s __wine_spec_weak_%s\n", name, name ); + fprintf( outfile, "# else\n" ); + fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params ); + fprintf( outfile, "# endif\n" ); + fprintf( outfile, "#else\n" ); + fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params ); + fprintf( outfile, "static void __asm__dummy_%s(void)", name ); + fprintf( outfile, " { asm(\".weak " __ASM_NAME("%s") "\"); }\n", name ); + fprintf( outfile, "#endif\n\n" ); } @@ -140,7 +134,7 @@ static int output_debug( FILE *outfile ) * * Output the export table for a Win32 module. */ -static int output_exports( FILE *outfile, int nr_exports ) +static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec ) { int i, fwd_size = 0, total_size = 0; @@ -156,11 +150,11 @@ static int output_exports( FILE *outfile, int nr_exports ) fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* TimeDateStamp */ fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* MajorVersion/MinorVersion */ fprintf( outfile, " \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */ - fprintf( outfile, " \"\\t.long %d\\n\"\n", Base ); /* Base */ - fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */ - fprintf( outfile, " \"\\t.long %d\\n\"\n", nb_names ); /* NumberOfNames */ + fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->base ); /* Base */ + fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */ + fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->nb_names ); /* NumberOfNames */ fprintf( outfile, " \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */ - if (nb_names) + if (spec->nb_names) { fprintf( outfile, " \"\\t.long __wine_spec_exp_name_ptrs\\n\"\n" ); /* AddressOfNames */ fprintf( outfile, " \"\\t.long __wine_spec_exp_ordinals\\n\"\n" ); /* AddressOfNameOrdinals */ @@ -175,9 +169,9 @@ static int output_exports( FILE *outfile, int nr_exports ) /* output the function pointers */ fprintf( outfile, " \"__wine_spec_exports_funcs:\\n\"\n" ); - for (i = Base; i <= Limit; i++) + for (i = spec->base; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (!odp) fprintf( outfile, " \"\\t.long 0\\n\"\n" ); else switch(odp->type) { @@ -188,7 +182,8 @@ static int output_exports( FILE *outfile, int nr_exports ) if (!(odp->flags & FLAG_FORWARD)) { fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", - (odp->flags & FLAG_REGISTER) ? make_internal_name(odp,"regs") : odp->link_name ); + (odp->flags & FLAG_REGISTER) ? make_internal_name( odp, spec, "regs" ) + : odp->link_name ); } else { @@ -197,49 +192,51 @@ static int output_exports( FILE *outfile, int nr_exports ) } break; case TYPE_STUB: - fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", make_internal_name( odp, "stub" ) ); + fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", + make_internal_name( odp, spec, "stub" ) ); break; default: assert(0); } } - total_size += (Limit - Base + 1) * sizeof(int); + total_size += (spec->limit - spec->base + 1) * sizeof(int); - if (nb_names) + if (spec->nb_names) { /* output the function name pointers */ - int namepos = strlen(dll_file_name) + 1; + int namepos = strlen(spec->file_name) + 1; fprintf( outfile, " \"__wine_spec_exp_name_ptrs:\\n\"\n" ); - for (i = 0; i < nb_names; i++) + for (i = 0; i < spec->nb_names; i++) { fprintf( outfile, " \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos ); - namepos += strlen(Names[i]->name) + 1; + namepos += strlen(spec->names[i]->name) + 1; } - total_size += nb_names * sizeof(int); + total_size += spec->nb_names * sizeof(int); } /* output the function names */ fprintf( outfile, " \"\\t.text\\n\"\n" ); fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" ); - fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", dll_file_name ); - for (i = 0; i < nb_names; i++) - fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", Names[i]->name ); + fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name ); + for (i = 0; i < spec->nb_names; i++) + fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name ); fprintf( outfile, " \"\\t.data\\n\"\n" ); - if (nb_names) + if (spec->nb_names) { /* output the function ordinals */ fprintf( outfile, " \"__wine_spec_exp_ordinals:\\n\"\n" ); - for (i = 0; i < nb_names; i++) + for (i = 0; i < spec->nb_names; i++) { - fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n", Names[i]->ordinal - Base ); + fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n", + spec->names[i]->ordinal - spec->base ); } - total_size += nb_names * sizeof(short); - if (nb_names % 2) + total_size += spec->nb_names * sizeof(short); + if (spec->nb_names % 2) { fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" ); total_size += sizeof(short); @@ -251,9 +248,9 @@ static int output_exports( FILE *outfile, int nr_exports ) if (fwd_size) { fprintf( outfile, " \"__wine_spec_forwards:\\n\"\n" ); - for (i = Base; i <= Limit; i++) + for (i = spec->base; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; if (odp && (odp->flags & FLAG_FORWARD)) fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name ); } @@ -265,9 +262,9 @@ static int output_exports( FILE *outfile, int nr_exports ) if (debugging) { - for (i = Base; i <= Limit; i++) + for (i = spec->base; i <= spec->limit; i++) { - ORDDEF *odp = Ordinals[i]; + ORDDEF *odp = spec->ordinals[i]; unsigned int j, args, mask = 0; const char *name; @@ -287,7 +284,7 @@ static int output_exports( FILE *outfile, int nr_exports ) name = odp->link_name; args = strlen(odp->u.func.arg_types) * sizeof(int); - if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, "regs" ); + if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, spec, "regs" ); switch(odp->type) { @@ -325,13 +322,13 @@ static int output_exports( FILE *outfile, int nr_exports ) * * Output the functions for stub entry points */ -static void output_stub_funcs( FILE *outfile ) +static void output_stub_funcs( FILE *outfile, DLLSPEC *spec ) { int i; - for (i = 0; i < nb_entry_points; i++) + for (i = 0; i < spec->nb_entry_points; i++) { - ORDDEF *odp = EntryPoints[i]; + ORDDEF *odp = &spec->entry_points[i]; if (odp->type != TYPE_STUB) continue; fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); @@ -349,7 +346,7 @@ static void output_stub_funcs( FILE *outfile ) fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE ); fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.params = 2;\n" ); - fprintf( outfile, " rec.info[0] = \"%s\";\n", dll_file_name ); + fprintf( outfile, " rec.info[0] = \"%s\";\n", spec->file_name ); fprintf( outfile, " rec.info[1] = func;\n" ); fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); @@ -360,11 +357,11 @@ static void output_stub_funcs( FILE *outfile ) break; } - for (i = 0; i < nb_entry_points; i++) + for (i = 0; i < spec->nb_entry_points; i++) { - ORDDEF *odp = EntryPoints[i]; + const ORDDEF *odp = &spec->entry_points[i]; if (odp->type != TYPE_STUB) continue; - fprintf( outfile, "void %s(void) ", make_internal_name( odp, "stub" ) ); + fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) ); if (odp->name) fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name ); else if (odp->export_name) @@ -380,18 +377,18 @@ static void output_stub_funcs( FILE *outfile ) * * Output the functions for register entry points */ -static void output_register_funcs( FILE *outfile ) +static void output_register_funcs( FILE *outfile, DLLSPEC *spec ) { const char *name; int i; - for (i = 0; i < nb_entry_points; i++) + for (i = 0; i < spec->nb_entry_points; i++) { - ORDDEF *odp = EntryPoints[i]; + const ORDDEF *odp = &spec->entry_points[i]; if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue; if (!(odp->flags & FLAG_REGISTER)) continue; if (odp->flags & FLAG_FORWARD) continue; - name = make_internal_name( odp, "regs" ); + name = make_internal_name( odp, spec, "regs" ); fprintf( outfile, "asm(\".align %d\\n\\t\"\n" " \"" __ASM_FUNC("%s") "\\n\\t\"\n" @@ -491,13 +488,12 @@ void output_dll_init( FILE *outfile, const char *constructor, const char *destru * * Build a Win32 C file from a spec file. */ -void BuildSpec32File( FILE *outfile ) +void BuildSpec32File( FILE *outfile, DLLSPEC *spec ) { int exports_size = 0; - int nr_exports, nr_imports, nr_resources; - int characteristics, subsystem; + int nr_exports, nr_imports; DWORD page_size; - char constructor[100]; + const char *init_func = spec->init_func; #ifdef HAVE_GETPAGESIZE page_size = getpagesize(); @@ -513,10 +509,8 @@ void BuildSpec32File( FILE *outfile ) # error Cannot get the page size on this platform #endif - AssignOrdinals(); - nr_exports = Base <= Limit ? Limit - Base + 1 : 0; - - resolve_imports(); + nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; + resolve_imports( spec ); output_standard_file_header( outfile ); /* Reserve some space for the PE header */ @@ -535,7 +529,12 @@ void BuildSpec32File( FILE *outfile ) fprintf( outfile, "}\n" ); fprintf( outfile, "#endif\n" ); +#ifdef __APPLE__ + fprintf( outfile, "static char _end[4];\n" ); +#else fprintf( outfile, "extern char _end[];\n" ); +#endif + fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" ); #ifdef __i386__ @@ -548,7 +547,7 @@ void BuildSpec32File( FILE *outfile ) { /* Output the stub functions */ - output_stub_funcs( outfile ); + output_stub_funcs( outfile, spec ); fprintf( outfile, "#ifndef __GNUC__\n" ); fprintf( outfile, "static void __asm__dummy(void) {\n" ); @@ -556,11 +555,11 @@ void BuildSpec32File( FILE *outfile ) /* Output code for all register functions */ - output_register_funcs( outfile ); + output_register_funcs( outfile, spec ); /* Output the exports and relay entry points */ - exports_size = output_exports( outfile, nr_exports ); + exports_size = output_exports( outfile, nr_exports, spec ); fprintf( outfile, "#ifndef __GNUC__\n" ); fprintf( outfile, "}\n" ); @@ -569,37 +568,95 @@ void BuildSpec32File( FILE *outfile ) /* Output the DLL imports */ - nr_imports = output_imports( outfile ); + nr_imports = output_imports( outfile, spec ); /* Output the resources */ - nr_resources = output_resources( outfile ); + output_resources( outfile, spec ); - /* Output LibMain function */ + /* Output the entry point function */ - characteristics = subsystem = 0; - switch(SpecMode) + fprintf( outfile, "static int __wine_spec_init_state;\n" ); + fprintf( outfile, "extern int __wine_main_argc;\n" ); + fprintf( outfile, "extern char **__wine_main_argv;\n" ); + fprintf( outfile, "extern char **__wine_main_environ;\n" ); + fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" ); +#ifdef __APPLE__ + fprintf( outfile, "extern _dyld_func_lookup(char *, void *);" ); + fprintf( outfile, "static void __wine_spec_hidden_init(int argc, char** argv, char** envp)\n" ); + fprintf( outfile, "{\n" ); + fprintf( outfile, " void (*init)(void);\n" ); + fprintf( outfile, " _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" ); + fprintf( outfile, " init();\n" ); + fprintf( outfile, "}\n" ); + fprintf( outfile, "static void __wine_spec_hidden_fini()\n" ); + fprintf( outfile, "{\n" ); + fprintf( outfile, " void (*fini)(void);\n" ); + fprintf( outfile, " _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" ); + fprintf( outfile, " fini();\n" ); + fprintf( outfile, "}\n" ); + fprintf( outfile, "#define _init __wine_spec_hidden_init\n" ); + fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" ); +#else + fprintf( outfile, "extern void _init(int, char**, char**);\n" ); + fprintf( outfile, "extern void _fini();\n" ); +#endif + + if (spec->characteristics & IMAGE_FILE_DLL) { - case SPEC_MODE_DLL: - if (init_func) fprintf( outfile, "extern void %s();\n", init_func ); + if (init_func) + fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func ); else { - fprintf( outfile, "#ifdef __GNUC__\n" ); - fprintf( outfile, "# ifdef __APPLE__\n" ); - fprintf( outfile, "extern void DllMain() __attribute__((weak_import));\n" ); - fprintf( outfile, "# else\n" ); - fprintf( outfile, "extern void DllMain() __attribute__((weak));\n" ); - fprintf( outfile, "# endif\n" ); - fprintf( outfile, "#else\n" ); - fprintf( outfile, "extern void DllMain();\n" ); - fprintf( outfile, "static void __asm__dummy_dllmain(void)" ); - fprintf( outfile, " { asm(\".weak " __ASM_NAME("DllMain") "\"); }\n" ); - fprintf( outfile, "#endif\n" ); + declare_weak_function( outfile, "int __stdcall", "DllMain", "void*, unsigned int, void*" ); + init_func = "DllMain"; } - characteristics = IMAGE_FILE_DLL; + fprintf( outfile, + "static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )\n" + "{\n" + " int ret;\n" + " if (reason == %d && __wine_spec_init_state == 1)\n" + " _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" + " ret = %s ? %s( inst, reason, reserved ) : 1;\n" + " if (reason == %d && __wine_spec_init_state == 1) _fini();\n" + " return ret;\n" + "}\n", + DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH ); + init_func = "__wine_dll_main"; + } + else switch(spec->subsystem) + { + case IMAGE_SUBSYSTEM_NATIVE: + if (init_func) + fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func ); + else + { + declare_weak_function( outfile, "int __stdcall", "DriverEntry", "void*, void*"); + init_func = "DriverEntry"; + } + fprintf( outfile, + "static int __stdcall __wine_driver_entry( void *obj, void *path )\n" + "{\n" + " int ret;\n" + " if (__wine_spec_init_state == 1)\n" + " _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" + " ret = %s ? %s( obj, path ) : 0;\n" + " if (__wine_spec_init_state == 1) _fini();\n" + " return ret;\n" + "}\n", + init_func, init_func ); + init_func = "__wine_driver_entry"; break; - case SPEC_MODE_GUIEXE: - if (!init_func) init_func = "WinMain"; + case IMAGE_SUBSYSTEM_WINDOWS_GUI: + case IMAGE_SUBSYSTEM_WINDOWS_CUI: + if (init_func) + fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func ); + else + { + declare_weak_function( outfile, "int", "main", "int argc, char *argv[]" ); + declare_weak_function( outfile, "int", "wmain", "int argc, unsigned short *argv[]" ); + declare_weak_function( outfile, "int __stdcall", "WinMain", "void *,void *,char *,int" ); + } fprintf( outfile, "\ntypedef struct {\n" " unsigned int cb;\n" @@ -610,123 +667,46 @@ void BuildSpec32File( FILE *outfile ) " char *lpReserved2;\n" " void *hStdInput, *hStdOutput, *hStdError;\n" "} STARTUPINFOA;\n" - "int _ARGC;\n" - "char **_ARGV;\n" - "extern int __stdcall %s(void *,void *,char *,int);\n" "extern char * __stdcall GetCommandLineA(void);\n" "extern void * __stdcall GetModuleHandleA(char *);\n" "extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n" "extern void __stdcall ExitProcess(unsigned int);\n" "static void __wine_exe_main(void)\n" "{\n" - " extern int __wine_main_argc;\n" - " extern char **__wine_main_argv;\n" - " STARTUPINFOA info;\n" - " char *cmdline = GetCommandLineA();\n" - " int bcount=0, in_quotes=0;\n" - " while (*cmdline) {\n" - " if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n" - " else if (*cmdline=='\\\\') bcount++;\n" - " else if (*cmdline=='\\\"') {\n" - " if ((bcount & 1)==0) in_quotes=!in_quotes;\n" - " bcount=0;\n" - " }\n" - " else bcount=0;\n" - " cmdline++;\n" - " }\n" - " while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n" - " GetStartupInfoA( &info );\n" - " if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n" - " _ARGC = __wine_main_argc;\n" - " _ARGV = __wine_main_argv;\n" - " ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n" - "}\n\n", init_func, init_func ); - init_func = "__wine_exe_main"; - subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; - break; - case SPEC_MODE_GUIEXE_UNICODE: - if (!init_func) init_func = "WinMain"; + " int ret;\n" + " if (__wine_spec_init_state == 1)\n" + " _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" ); + if (init_func) + fprintf( outfile, + " ret = %s( __wine_main_argc, __wine_main_argv );\n", init_func ); + else + fprintf( outfile, + " if (WinMain) {\n" + " STARTUPINFOA info;\n" + " char *cmdline = GetCommandLineA();\n" + " int bcount=0, in_quotes=0;\n" + " while (*cmdline) {\n" + " if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n" + " else if (*cmdline=='\\\\') bcount++;\n" + " else if (*cmdline=='\\\"') {\n" + " if ((bcount & 1)==0) in_quotes=!in_quotes;\n" + " bcount=0;\n" + " }\n" + " else bcount=0;\n" + " cmdline++;\n" + " }\n" + " while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n" + " GetStartupInfoA( &info );\n" + " if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n" + " ret = WinMain( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n" + " }\n" + " else if (wmain) ret = wmain( __wine_main_argc, __wine_main_wargv );\n" + " else ret = main( __wine_main_argc, __wine_main_argv );\n" ); fprintf( outfile, - "\ntypedef unsigned short WCHAR;\n" - "typedef struct {\n" - " unsigned int cb;\n" - " char *lpReserved, *lpDesktop, *lpTitle;\n" - " unsigned int dwX, dwY, dwXSize, dwYSize;\n" - " unsigned int dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;\n" - " unsigned short wShowWindow, cbReserved2;\n" - " char *lpReserved2;\n" - " void *hStdInput, *hStdOutput, *hStdError;\n" - "} STARTUPINFOA;\n" - "int _ARGC;\n" - "WCHAR **_ARGV;\n" - "extern int __stdcall %s(void *,void *,char *,int);\n" - "extern char * __stdcall GetCommandLineA(void);\n" - "extern void * __stdcall GetModuleHandleA(char *);\n" - "extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n" - "extern void __stdcall ExitProcess(unsigned int);\n" - "static void __wine_exe_main(void)\n" - "{\n" - " extern int __wine_main_argc;\n" - " extern WCHAR **__wine_main_wargv;\n" - " STARTUPINFOA info;\n" - " char *cmdline = GetCommandLineA();\n" - " int bcount=0, in_quotes=0;\n" - " while (*cmdline) {\n" - " if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n" - " else if (*cmdline=='\\\\') bcount++;\n" - " else if (*cmdline=='\\\"') {\n" - " if ((bcount & 1)==0) in_quotes=!in_quotes;\n" - " bcount=0;\n" - " }\n" - " else bcount=0;\n" - " cmdline++;\n" - " }\n" - " while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n" - " GetStartupInfoA( &info );\n" - " if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n" - " _ARGC = __wine_main_argc;\n" - " _ARGV = __wine_main_wargv;\n" - " ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n" - "}\n\n", init_func, init_func ); + " if (__wine_spec_init_state == 1) _fini();\n" + " ExitProcess( ret );\n" + "}\n\n" ); init_func = "__wine_exe_main"; - subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; - break; - case SPEC_MODE_CUIEXE: - if (!init_func) init_func = "main"; - fprintf( outfile, - "\nint _ARGC;\n" - "char **_ARGV;\n" - "extern void __stdcall ExitProcess(int);\n" - "static void __wine_exe_main(void)\n" - "{\n" - " extern int %s( int argc, char *argv[] );\n" - " extern int __wine_main_argc;\n" - " extern char **__wine_main_argv;\n" - " _ARGC = __wine_main_argc;\n" - " _ARGV = __wine_main_argv;\n" - " ExitProcess( %s( _ARGC, _ARGV ) );\n" - "}\n\n", init_func, init_func ); - init_func = "__wine_exe_main"; - subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; - break; - case SPEC_MODE_CUIEXE_UNICODE: - if (!init_func) init_func = "wmain"; - fprintf( outfile, - "\ntypedef unsigned short WCHAR;\n" - "int _ARGC;\n" - "WCHAR **_ARGV;\n" - "extern void __stdcall ExitProcess(int);\n" - "static void __wine_exe_main(void)\n" - "{\n" - " extern int %s( int argc, WCHAR *argv[] );\n" - " extern int __wine_main_argc;\n" - " extern WCHAR **__wine_main_wargv;\n" - " _ARGC = __wine_main_argc;\n" - " _ARGV = __wine_main_wargv;\n" - " ExitProcess( %s( _ARGC, _ARGV ) );\n" - "}\n\n", init_func, init_func ); - init_func = "__wine_exe_main"; - subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI; break; } @@ -788,29 +768,30 @@ void BuildSpec32File( FILE *outfile ) #endif fprintf( outfile, " 0, 0, 0, 0,\n" ); fprintf( outfile, " sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */ - fprintf( outfile, " 0x%04x },\n", characteristics ); /* Characteristics */ + fprintf( outfile, " 0x%04x },\n", spec->characteristics ); /* Characteristics */ fprintf( outfile, " { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC ); /* Magic */ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorLinkerVersion */ fprintf( outfile, " 0, 0, 0,\n" ); /* SizeOfCode/Data */ - fprintf( outfile, " %s,\n", init_func ? init_func : "DllMain" ); /* AddressOfEntryPoint */ + fprintf( outfile, " %s,\n", init_func ); /* AddressOfEntryPoint */ fprintf( outfile, " 0, __wine_spec_data_start,\n" ); /* BaseOfCode/Data */ fprintf( outfile, " __wine_spec_pe_header,\n" ); /* ImageBase */ fprintf( outfile, " %ld,\n", page_size ); /* SectionAlignment */ fprintf( outfile, " %ld,\n", page_size ); /* FileAlignment */ fprintf( outfile, " 1, 0,\n" ); /* Major/MinorOperatingSystemVersion */ fprintf( outfile, " 0, 0,\n" ); /* Major/MinorImageVersion */ - fprintf( outfile, " 4, 0,\n" ); /* Major/MinorSubsystemVersion */ + fprintf( outfile, " %d,\n", spec->subsystem_major ); /* MajorSubsystemVersion */ + fprintf( outfile, " %d,\n", spec->subsystem_minor ); /* MinorSubsystemVersion */ fprintf( outfile, " 0,\n" ); /* Win32VersionValue */ fprintf( outfile, " _end,\n" ); /* SizeOfImage */ fprintf( outfile, " %ld,\n", page_size ); /* SizeOfHeaders */ fprintf( outfile, " 0,\n" ); /* CheckSum */ - fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */ + fprintf( outfile, " 0x%04x,\n", spec->subsystem );/* Subsystem */ fprintf( outfile, " 0,\n" ); /* DllCharacteristics */ fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */ - (stack_size ? stack_size : 1024) * 1024, page_size ); + (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size ); fprintf( outfile, " %d, %ld,\n", /* SizeOfHeapReserve/Commit */ - (DLLHeapSize ? DLLHeapSize : 1024) * 1024, page_size ); + (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size ); fprintf( outfile, " 0,\n" ); /* LoaderFlags */ fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */ fprintf( outfile, " {\n" ); @@ -819,22 +800,29 @@ void BuildSpec32File( FILE *outfile ) fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */ nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" ); fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */ - nr_resources ? "&resources" : "0", nr_resources ? "sizeof(resources)" : "0" ); + spec->nb_resources ? "&resources" : "0", + spec->nb_resources ? "sizeof(resources)" : "0" ); fprintf( outfile, " }\n }\n};\n\n" ); /* Output the DLL constructor */ - sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) ); - output_dll_init( outfile, constructor, NULL ); - fprintf( outfile, - "void %s(void)\n" + "void __wine_spec_init(void)\n" "{\n" " extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n" - " extern void *__wine_dbg_register( char * const *, int );\n" + " __wine_spec_init_state = 1;\n" " __wine_dll_register( &nt_header, \"%s\" );\n" - "}\n", - constructor, dll_file_name ); + "}\n\n", + spec->file_name ); + + output_dll_init( outfile, "__wine_spec_init_ctor", NULL ); + fprintf( outfile, + "void __wine_spec_init_ctor(void)\n" + "{\n" + " if (__wine_spec_init_state) return;\n" + " __wine_spec_init();\n" + " __wine_spec_init_state = 2;\n" + "}\n" ); } @@ -843,25 +831,23 @@ void BuildSpec32File( FILE *outfile ) * * Build a Win32 def file from a spec file. */ -void BuildDef32File(FILE *outfile) +void BuildDef32File( FILE *outfile, DLLSPEC *spec ) { const char *name; int i; - AssignOrdinals(); - fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n", input_file_name ); - fprintf(outfile, "LIBRARY %s\n\n", dll_file_name); + fprintf(outfile, "LIBRARY %s\n\n", spec->file_name); fprintf(outfile, "EXPORTS\n"); /* Output the exports and relay entry points */ - for(i = 0; i < nb_entry_points; i++) + for(i = 0; i < spec->nb_entry_points; i++) { - ORDDEF *odp = EntryPoints[i]; + const ORDDEF *odp = &spec->entry_points[i]; int is_data = 0; if (!odp) continue; @@ -906,7 +892,7 @@ void BuildDef32File(FILE *outfile) fprintf( outfile, " @%d", odp->ordinal ); if (!odp->name) fprintf( outfile, " NONAME" ); if (is_data) fprintf( outfile, " DATA" ); -#if !defined(__REACTOS__) +#if 0 /* MinGW binutils cannot handle this correctly */ if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" ); #endif @@ -951,8 +937,8 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ) fprintf( outfile, "#ifdef __GNUC__\n" - "static void __wine_dbg_%s_init(void) __attribute__((constructor));\n" - "static void __wine_dbg_%s_fini(void) __attribute__((destructor));\n" + "void __wine_dbg_%s_init(void) __attribute__((constructor));\n" + "void __wine_dbg_%s_fini(void) __attribute__((destructor));\n" "#else\n" "static void __asm__dummy_dll_init(void) {\n", prefix, prefix ); @@ -972,29 +958,34 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ) fprintf( outfile, " \"\\tnop\\n\"\n" ); fprintf( outfile, " \"\\t.section\t\\\".text\\\"\\n\");\n" ); #elif defined(__powerpc__) +# ifdef __APPLE__ + fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" ); + fprintf( outfile, " \"\\t.align 2\\n\"\n" ); + fprintf( outfile, " \"\\t.long " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix ); + fprintf( outfile, " \"\\t.text\\n\");\n" ); + fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" ); + fprintf( outfile, " \"\\t.align 2\\n\"\n" ); + fprintf( outfile, " \"\\t.long " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix ); + fprintf( outfile, " \"\\t.text\\n\");\n" ); +# else fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" ); fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix ); fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" ); fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix ); fprintf( outfile, " \"\\t.text\\n\");\n" ); +# endif #else #error You need to define the DLL constructor for your architecture #endif - fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n" ); + fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" ); fprintf( outfile, - "\n#ifdef __GNUC__\n" - "static\n" - "#endif\n" "void __wine_dbg_%s_init(void)\n" "{\n" " extern void *__wine_dbg_register( char * const *, int );\n" - " debug_registration = __wine_dbg_register( debug_channels, %d );\n" - "}\n", prefix, nr_debug ); + " if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n" + "}\n\n", prefix, nr_debug ); fprintf( outfile, - "\n#ifdef __GNUC__\n" - "static\n" - "#endif\n" "void __wine_dbg_%s_fini(void)\n" "{\n" " extern void __wine_dbg_unregister( void* );\n" diff --git a/reactos/tools/winebuild/utils.c b/reactos/tools/winebuild/utils.c index 4fa4f0f57d6..481c1739a78 100644 --- a/reactos/tools/winebuild/utils.c +++ b/reactos/tools/winebuild/utils.c @@ -86,6 +86,7 @@ void fatal_error( const char *msg, ... ) fprintf( stderr, "%d:", current_line ); fputc( ' ', stderr ); } + else fprintf( stderr, "winebuild: " ); vfprintf( stderr, msg, valist ); va_end( valist ); exit(1); @@ -213,6 +214,86 @@ 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->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->characteristics = 0; + spec->subsystem = 0; + spec->subsystem_major = 4; + spec->subsystem_minor = 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/reactos/tools/winebuild/winebuild.man.in b/reactos/tools/winebuild/winebuild.man.in index ffd80cdc5e4..de9a79255c1 100644 --- a/reactos/tools/winebuild/winebuild.man.in +++ b/reactos/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 @@ -32,16 +33,16 @@ final dll, to allow to get the list of all undefined symbols that need to be imported from other dlls. .TP -.BI \--exe=\ name +.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 as .I input files. .TP -.BI \--def=\ file.spec +.BI \--def= file.spec Build a .def file from a spec file. This is used when building dlls with a PE (Win32) compiler. .TP @@ -75,11 +76,12 @@ Specify the module entry point function; if not specified, the default is .B DllMain for dlls, and -.B main -or .B WinMain -for CUI or GUI executables respectively. This is only valid for Win32 -modules. +for executables (if +.B WinMain +is not defined, the standard C +.B main +is used instead). This is only valid for Win32 modules. .TP .BI \-f\ flags Ignored for compatibility with the C compiler. @@ -130,29 +132,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. -.TP -.BI \-m,\ --exe-mode= mode -Set the executable mode, which can be one of the following: -.br -.B cui -for a command line ASCII executable, -.br -.B gui -for a graphical ASCII executable, -.br -.B cuiw -for a command line Unicode executable, -.br -.B guiw -for a graphical Unicode executable. -.br -A command line executable entry point is a normal C \fBmain\fR -function. A graphical executable has a \fBWinMain\fR entry point -instead. The ASCII/Unicode distinction applies to the strings that are -passed to the entry point. -.br -This option is only meaningful in \fB--exe\fR mode. +meaningful in \fB--dll\fR mode. .TP .BI \-N,\ --dll-name= dllname Set the internal name of the module. It is only used in Win16 @@ -176,6 +156,26 @@ and will automatically be handled correctly (though the .B \-r option will also work for Win32 files). .TP +.BI --subsystem= subsystem[:major[.minor]] +Set the subsystem of the executable, which can be one of the following: +.br +.B console +for a command line executable, +.br +.B windows +for a graphical executable, +.br +.B native +for a native-mode dll. +.br +The entry point of a command line executable is a normal C \fBmain\fR +function. A \fBwmain\fR function can be used instead if you need the +argument array to use Unicode strings. A graphical executable has a +\fBWinMain\fR entry point. +.br +Optionally a major and minor subsystem version can also be specified; +the default subsystem version is 4.0. +.TP .B \--version Display the program version and exit. .TP @@ -237,9 +237,6 @@ The entry point is only available on i386 platforms. .B -register The function uses CPU register to pass arguments. .TP -.B -interrupt -The function is an interrupt handler routine. -.TP .B -private The function cannot be imported from other dlls, it can only be accessed through GetProcAddress. diff --git a/reactos/tools/winebuild/winehq2ros.patch b/reactos/tools/winebuild/winehq2ros.patch new file mode 100644 index 00000000000..d474286cb90 --- /dev/null +++ b/reactos/tools/winebuild/winehq2ros.patch @@ -0,0 +1,86 @@ +Index: main.c +=================================================================== +RCS file: /home/wine/wine/tools/winebuild/main.c,v +retrieving revision 1.55 +diff -u -r1.55 main.c +--- main.c 25 Mar 2004 00:40:52 -0000 1.55 ++++ main.c 23 Sep 2004 20:38:14 -0000 +@@ -412,9 +412,7 @@ + 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 ); ++ fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" ); + break; + case SPEC_WIN32: + read_undef_symbols( argv ); +@@ -439,12 +437,10 @@ + BuildDebugFile( output_file, current_src_dir, argv ); + break; + case MODE_RELAY16: +- if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); +- BuildRelays16( output_file ); ++ fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" ); + break; + case MODE_RELAY32: +- if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); +- BuildRelays32( output_file ); ++ fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" ); + break; + default: + usage(1); +Index: spec32.c +=================================================================== +RCS file: /home/wine/wine/tools/winebuild/spec32.c,v +retrieving revision 1.83 +diff -u -r1.83 spec32.c +--- spec32.c 15 Jul 2004 18:58:42 -0000 1.83 ++++ spec32.c 23 Sep 2004 20:38:15 -0000 +@@ -30,9 +30,15 @@ + #include + #include + ++#ifdef WIN32 + #include "windef.h" + #include "winbase.h" +-#include "wine/exception.h" ++#else ++#include "winglue.h" ++#endif ++#define EXCEPTION_WINE_STUB 0x80000100 /* stub entry point called */ ++#define EH_NONCONTINUABLE 0x01 ++ + #include "build.h" + + +@@ -886,7 +892,10 @@ + fprintf( outfile, " @%d", odp->ordinal ); + if (!odp->name) fprintf( outfile, " NONAME" ); + if (is_data) fprintf( outfile, " DATA" ); ++#if 0 ++ /* MinGW binutils cannot handle this correctly */ + if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" ); ++#endif + fprintf( outfile, "\n" ); + } + } +Index: utils.c +=================================================================== +RCS file: /home/wine/wine/tools/winebuild/utils.c,v +retrieving revision 1.20 +diff -u -r1.20 utils.c +--- utils.c 25 Mar 2004 00:40:52 -0000 1.20 ++++ utils.c 23 Sep 2004 20:38:15 -0000 +@@ -21,6 +21,10 @@ + #include "config.h" + #include "wine/port.h" + ++#if !defined(WIN32) ++#undef strdup ++#endif ++ + #include + #include + #include diff --git a/reactos/tools/winebuild/winglue.h b/reactos/tools/winebuild/winglue.h index 04b3c3fd23b..ecbb4f86588 100644 --- a/reactos/tools/winebuild/winglue.h +++ b/reactos/tools/winebuild/winglue.h @@ -9,7 +9,11 @@ typedef unsigned short WCHAR; #define LOBYTE(w) ((BYTE)(w)) #define HIBYTE(w) ((BYTE)(((WORD)(w)>>8)&0xFF)) +#define DLL_PROCESS_ATTACH 1 +#define DLL_PROCESS_DETACH 0 + #define IMAGE_FILE_DLL 8192 +#define IMAGE_SUBSYSTEM_NATIVE 1 #define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 #define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16