mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-31 12:23:31 +00:00
Sync to Wine:
Alexandre Julliard <[email protected]> - 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 <[email protected]> - Remove support for generating interrupt handlers. - DPMI programs now handle pending events. Robert Shearman <[email protected]> - Fix proc name reported in delay load failure. Richard Cohen <[email protected]> - Remove . from default library search path. Eric Pouech <[email protected]> - 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 <[email protected]> - 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 <[email protected]> - Use "LD" instead of "ld" in winebuild to be able to use a different ld or ld options. Dmitry Timoshkov <[email protected]> - Add a few missing __ASM_NAME macros. svn path=/trunk/; revision=11014
This commit is contained in:
@@ -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 $@
|
||||
|
||||
@@ -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 */
|
||||
|
||||
+215
-301
@@ -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 <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#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 );
|
||||
}
|
||||
|
||||
@@ -29,27 +29,17 @@
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
# include <getopt.h>
|
||||
#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);
|
||||
|
||||
@@ -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 <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
@@ -37,12 +37,8 @@
|
||||
#include <sys/mman.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
+104
-69
@@ -37,12 +37,8 @@
|
||||
#include <sys/mman.h>
|
||||
#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 );
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+228
-237
@@ -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"
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
+#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 <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.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
|
||||
|
||||
Reference in New Issue
Block a user