Store all information about the current dll in a structure instead of

using global variables to make it easier to reuse the parsing
routines.
This commit is contained in:
Alexandre Julliard 2004-02-11 06:41:01 +00:00
parent 2ad864dc87
commit 8611e654fc
8 changed files with 441 additions and 367 deletions

View File

@ -94,6 +94,28 @@ typedef struct
} u; } u;
} ORDDEF; } 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) */
SPEC_MODE mode; /* dll mode (dll/exe/etc.) */
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 */
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 */ /* entry point flags */
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */ #define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
#define FLAG_NONAME 0x02 /* don't import function by name */ #define FLAG_NONAME 0x02 /* don't import function by name */
@ -153,54 +175,38 @@ extern int get_alignment(int alignBoundary);
extern void add_import_dll( const char *name, int delay ); extern void add_import_dll( const char *name, int delay );
extern void add_ignore_symbol( const char *name ); extern void add_ignore_symbol( const char *name );
extern void read_undef_symbols( char **argv ); extern void read_undef_symbols( char **argv );
extern int resolve_imports( void ); extern int resolve_imports( DLLSPEC *spec );
extern int output_imports( FILE *outfile ); extern int output_imports( FILE *outfile, DLLSPEC *spec );
extern int load_res32_file( const char *name ); extern int load_res32_file( const char *name, DLLSPEC *spec );
extern int output_resources( FILE *outfile ); extern void output_resources( FILE *outfile, DLLSPEC *spec );
extern void load_res16_file( const char *name ); extern void load_res16_file( const char *name, DLLSPEC *spec );
extern int output_res16_data( FILE *outfile ); extern int output_res16_data( FILE *outfile, DLLSPEC *spec );
extern int output_res16_directory( unsigned char *buffer ); extern int output_res16_directory( unsigned char *buffer, DLLSPEC *spec );
extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor ); 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 int parse_debug_channels( const char *srcdir, const char *filename );
extern void BuildRelays16( FILE *outfile ); extern void BuildRelays16( FILE *outfile );
extern void BuildRelays32( FILE *outfile ); extern void BuildRelays32( FILE *outfile );
extern void BuildSpec16File( FILE *outfile ); extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
extern void BuildSpec32File( FILE *outfile ); extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
extern void BuildDef32File( FILE *outfile ); extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ); extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv );
extern int ParseTopLevel( FILE *file ); extern int ParseTopLevel( FILE *file, DLLSPEC *spec );
/* global variables */ /* global variables */
extern int current_line; 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 UsePIC;
extern int debugging; extern int debugging;
extern int stack_size;
extern int nb_debug_channels; extern int nb_debug_channels;
extern int nb_lib_paths; extern int nb_lib_paths;
extern int nb_errors; extern int nb_errors;
extern int display_warnings; extern int display_warnings;
extern int kill_at; 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 char *input_file_name;
extern const char *output_file_name; extern const char *output_file_name;
extern char **debug_channels; extern char **debug_channels;
extern char **lib_path; 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 */ #endif /* __WINE_BUILD_H */

View File

@ -525,16 +525,16 @@ static int remove_symbol_holes(void)
} }
/* add a symbol to the extra list, but only if needed */ /* 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; int i;
if (!find_symbol( name, undef_symbols, nb_undef_symbols )) if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
{ {
/* check if the symbol is being exported by this dll */ /* 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 || if (odp->type == TYPE_STDCALL ||
odp->type == TYPE_CDECL || odp->type == TYPE_CDECL ||
odp->type == TYPE_VARARGS || odp->type == TYPE_VARARGS ||
@ -550,7 +550,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 */ /* 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]; const char *extras[10];
int i, count = 0, nb_stubs = 0, nb_regs = 0; int i, count = 0, nb_stubs = 0, nb_regs = 0;
@ -558,44 +558,44 @@ static void add_extra_undef_symbols(void)
sort_symbols( undef_symbols, nb_undef_symbols ); 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->type == TYPE_STUB) nb_stubs++;
if (odp->flags & FLAG_REGISTER) nb_regs++; if (odp->flags & FLAG_REGISTER) nb_regs++;
} }
/* add symbols that will be contained in the spec file itself */ /* add symbols that will be contained in the spec file itself */
switch (SpecMode) switch (spec->mode)
{ {
case SPEC_MODE_DLL: case SPEC_MODE_DLL:
break; break;
case SPEC_MODE_GUIEXE: case SPEC_MODE_GUIEXE:
kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" ); kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" ); kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" ); kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
/* fall through */ /* fall through */
case SPEC_MODE_CUIEXE: case SPEC_MODE_CUIEXE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" ); kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
break; break;
case SPEC_MODE_GUIEXE_UNICODE: case SPEC_MODE_GUIEXE_UNICODE:
kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" ); kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" ); kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" ); kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
/* fall through */ /* fall through */
case SPEC_MODE_CUIEXE_UNICODE: case SPEC_MODE_CUIEXE_UNICODE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" ); kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
break; break;
} }
if (nb_delayed) if (nb_delayed)
{ {
kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA" ); kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" ); kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
} }
if (nb_regs) 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) 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 */ /* make sure we import the dlls that contain these functions */
if (kernel_imports) add_import_dll( "kernel32", 0 ); if (kernel_imports) add_import_dll( "kernel32", 0 );
@ -609,16 +609,16 @@ static void add_extra_undef_symbols(void)
} }
/* check if a given imported dll is not needed, taking forwards into account */ /* 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; int i;
size_t len = strlen(imp->dll); size_t len = strlen(imp->dll);
const char *p = strchr( imp->dll, '.' ); const char *p = strchr( imp->dll, '.' );
if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll; if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
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 (!odp || !(odp->flags & FLAG_FORWARD)) continue;
if (!strncasecmp( odp->link_name, imp->dll, len ) && if (!strncasecmp( odp->link_name, imp->dll, len ) &&
odp->link_name[len] == '.') odp->link_name[len] == '.')
@ -708,13 +708,13 @@ static void remove_ignored_symbols(void)
} }
/* resolve the imports for a Win32 module */ /* resolve the imports for a Win32 module */
int resolve_imports( void ) int resolve_imports( DLLSPEC *spec )
{ {
int i, j; int i, j;
if (nb_undef_symbols == -1) return 0; /* no symbol file specified */ if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
add_extra_undef_symbols(); add_extra_undef_symbols( spec );
remove_ignored_symbols(); remove_ignored_symbols();
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
@ -732,7 +732,7 @@ int resolve_imports( void )
} }
} }
/* remove all the holes in the undef symbols list */ /* 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 */ /* 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->dll );
@ -873,7 +873,7 @@ static int output_immediate_imports( FILE *outfile )
} }
/* output the delayed import table of a Win32 module */ /* 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; int i, idx, j, pos;
@ -941,9 +941,9 @@ static int output_delayed_imports( FILE *outfile )
/* check if there's some stub defined. if so, exception struct /* check if there's some stub defined. if so, exception struct
* is already defined, so don't emit it twice * 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, "struct exc_record {\n" );
fprintf( outfile, " unsigned int code, flags;\n" ); fprintf( outfile, " unsigned int code, flags;\n" );
fprintf( outfile, " void *rec, *addr;\n" ); fprintf( outfile, " void *rec, *addr;\n" );
@ -1153,8 +1153,8 @@ static int output_delayed_imports( FILE *outfile )
/* output the import and delayed import tables of a Win32 module /* output the import and delayed import tables of a Win32 module
* returns number of DLLs exported in 'immediate' mode * 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 ); return output_immediate_imports( outfile );
} }

View File

@ -36,20 +36,7 @@
#include "build.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 UsePIC = 0;
int stack_size = 0;
int nb_entry_points = 0;
int nb_names = 0;
int nb_debug_channels = 0; int nb_debug_channels = 0;
int nb_lib_paths = 0; int nb_lib_paths = 0;
int nb_errors = 0; int nb_errors = 0;
@ -63,10 +50,6 @@ int debugging = 1;
int debugging = 0; int debugging = 0;
#endif #endif
char *owner_name = NULL;
char *dll_name = NULL;
char *dll_file_name = NULL;
const char *init_func = NULL;
char **debug_channels = NULL; char **debug_channels = NULL;
char **lib_path = NULL; char **lib_path = NULL;
@ -94,18 +77,18 @@ enum exec_mode_values
static enum exec_mode_values exec_mode = MODE_NONE; static enum exec_mode_values exec_mode = MODE_NONE;
/* set the dll file name from the input file name */ /* 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; 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;
if ((p = strrchr( name, '/' ))) name = p + 1; if ((p = strrchr( name, '/' ))) name = p + 1;
dll_file_name = xmalloc( strlen(name) + 5 ); spec->file_name = xmalloc( strlen(name) + 5 );
strcpy( dll_file_name, name ); strcpy( spec->file_name, name );
if ((p = strrchr( dll_file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0; if ((p = strrchr( spec->file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0;
if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".dll" ); if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
} }
/* cleanup on program exit */ /* cleanup on program exit */
@ -206,7 +189,7 @@ static void set_exec_mode( enum exec_mode_values mode )
} }
/* parse options from the argv array and remove all the recognized ones */ /* 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; char *p;
int optc; int optc;
@ -222,14 +205,14 @@ static char **parse_options( int argc, char **argv )
/* ignored */ /* ignored */
break; break;
case 'F': case 'F':
dll_file_name = xstrdup( optarg ); spec->file_name = xstrdup( optarg );
break; break;
case 'H': case 'H':
if (!isdigit(optarg[0])) if (!isdigit(optarg[0]))
fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg ); fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg );
DLLHeapSize = atoi(optarg); spec->heap_size = atoi(optarg);
if (DLLHeapSize > 65535) if (spec->heap_size > 65535)
fatal_error( "Invalid heap size %d, maximum is 65535\n", DLLHeapSize ); fatal_error( "Invalid heap size %d, maximum is 65535\n", spec->heap_size );
break; break;
case 'I': case 'I':
/* ignored */ /* ignored */
@ -242,18 +225,18 @@ static char **parse_options( int argc, char **argv )
lib_path[nb_lib_paths++] = xstrdup( optarg ); lib_path[nb_lib_paths++] = xstrdup( optarg );
break; break;
case 'M': case 'M':
owner_name = xstrdup( optarg ); spec->owner_name = xstrdup( optarg );
SpecType = SPEC_WIN16; spec->type = SPEC_WIN16;
break; break;
case 'N': case 'N':
dll_name = xstrdup( optarg ); spec->dll_name = xstrdup( optarg );
break; break;
case 'd': case 'd':
add_import_dll( optarg, 1 ); add_import_dll( optarg, 1 );
break; break;
case 'e': case 'e':
init_func = xstrdup( optarg ); spec->init_func = xstrdup( optarg );
if ((p = strchr( init_func, '@' ))) *p = 0; /* kill stdcall decoration */ if ((p = strchr( spec->init_func, '@' ))) *p = 0; /* kill stdcall decoration */
break; break;
case 'f': case 'f':
if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1; if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1;
@ -281,10 +264,10 @@ static char **parse_options( int argc, char **argv )
add_import_dll( optarg, 0 ); add_import_dll( optarg, 0 );
break; break;
case 'm': case 'm':
if (!strcmp( optarg, "gui" )) SpecMode = SPEC_MODE_GUIEXE; if (!strcmp( optarg, "gui" )) spec->mode = SPEC_MODE_GUIEXE;
else if (!strcmp( optarg, "cui" )) SpecMode = SPEC_MODE_CUIEXE; else if (!strcmp( optarg, "cui" )) spec->mode = SPEC_MODE_CUIEXE;
else if (!strcmp( optarg, "guiw" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE; else if (!strcmp( optarg, "guiw" )) spec->mode = SPEC_MODE_GUIEXE_UNICODE;
else if (!strcmp( optarg, "cuiw" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE; else if (!strcmp( optarg, "cuiw" )) spec->mode = SPEC_MODE_CUIEXE_UNICODE;
else usage(1); else usage(1);
break; break;
case 'o': case 'o':
@ -305,21 +288,21 @@ static char **parse_options( int argc, char **argv )
case LONG_OPT_SPEC: case LONG_OPT_SPEC:
set_exec_mode( MODE_SPEC ); set_exec_mode( MODE_SPEC );
input_file = open_input_file( NULL, optarg ); input_file = open_input_file( NULL, optarg );
set_dll_file_name( optarg ); set_dll_file_name( optarg, spec );
break; break;
case LONG_OPT_DEF: case LONG_OPT_DEF:
set_exec_mode( MODE_DEF ); set_exec_mode( MODE_DEF );
input_file = open_input_file( NULL, optarg ); input_file = open_input_file( NULL, optarg );
set_dll_file_name( optarg ); set_dll_file_name( optarg, spec );
break; break;
case LONG_OPT_EXE: case LONG_OPT_EXE:
set_exec_mode( MODE_EXE ); set_exec_mode( MODE_EXE );
if ((p = strrchr( optarg, '/' ))) p++; if ((p = strrchr( optarg, '/' ))) p++;
else p = optarg; else p = optarg;
dll_file_name = xmalloc( strlen(p) + 5 ); spec->file_name = xmalloc( strlen(p) + 5 );
strcpy( dll_file_name, p ); strcpy( spec->file_name, p );
if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".exe" ); if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" );
if (SpecMode == SPEC_MODE_DLL) SpecMode = SPEC_MODE_GUIEXE; if (spec->mode == SPEC_MODE_DLL) spec->mode = SPEC_MODE_GUIEXE;
break; break;
case LONG_OPT_DEBUG: case LONG_OPT_DEBUG:
set_exec_mode( MODE_DEBUG ); set_exec_mode( MODE_DEBUG );
@ -343,28 +326,28 @@ static char **parse_options( int argc, char **argv )
/* load all specified resource files */ /* load all specified resource files */
static void load_resources( char *argv[] ) static void load_resources( char *argv[], DLLSPEC *spec )
{ {
int i; int i;
char **ptr, **last; char **ptr, **last;
switch (SpecType) switch (spec->type)
{ {
case SPEC_WIN16: 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; break;
case SPEC_WIN32: case SPEC_WIN32:
for (i = 0; i < nb_res_files; i++) 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] ); fatal_error( "%s is not a valid Win32 resource file\n", res_files[i] );
} }
/* load any resource file found in the remaining arguments */ /* load any resource file found in the remaining arguments */
for (ptr = last = argv; *ptr; ptr++) 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++ = *ptr; /* not a resource file, keep it in the list */
} }
*last = NULL; *last = NULL;
@ -377,39 +360,60 @@ static void load_resources( char *argv[] )
*/ */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
DLLSPEC spec;
spec.file_name = NULL;
spec.dll_name = NULL;
spec.owner_name = NULL;
spec.init_func = NULL;
spec.type = SPEC_WIN32;
spec.mode = SPEC_MODE_DLL;
spec.base = MAX_ORDINALS;
spec.limit = 0;
spec.stack_size = 0;
spec.heap_size = 0;
spec.nb_entry_points = 0;
spec.alloc_entry_points = 0;
spec.nb_names = 0;
spec.nb_resources = 0;
spec.entry_points = NULL;
spec.names = NULL;
spec.ordinals = NULL;
spec.resources = NULL;
output_file = stdout; output_file = stdout;
argv = parse_options( argc, argv ); argv = parse_options( argc, argv, &spec );
switch(exec_mode) switch(exec_mode)
{ {
case MODE_SPEC: case MODE_SPEC:
load_resources( argv ); load_resources( argv, &spec );
if (!ParseTopLevel( input_file )) break; if (!ParseTopLevel( input_file, &spec )) break;
switch (SpecType) switch (spec.type)
{ {
case SPEC_WIN16: case SPEC_WIN16:
if (argv[0]) if (argv[0])
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildSpec16File( output_file ); BuildSpec16File( output_file, &spec );
break; break;
case SPEC_WIN32: case SPEC_WIN32:
read_undef_symbols( argv ); read_undef_symbols( argv );
BuildSpec32File( output_file ); BuildSpec32File( output_file, &spec );
break; break;
default: assert(0); default: assert(0);
} }
break; break;
case MODE_EXE: case MODE_EXE:
if (SpecType == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); if (spec.type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
load_resources( argv ); load_resources( argv, &spec );
read_undef_symbols( argv ); read_undef_symbols( argv );
BuildSpec32File( output_file ); BuildSpec32File( output_file, &spec );
break; break;
case MODE_DEF: case MODE_DEF:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); 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 (spec.type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!ParseTopLevel( input_file )) break; if (!ParseTopLevel( input_file, &spec )) break;
BuildDef32File( output_file ); BuildDef32File( output_file, &spec );
break; break;
case MODE_DEBUG: case MODE_DEBUG:
BuildDebugFile( output_file, current_src_dir, argv ); BuildDebugFile( output_file, current_src_dir, argv );

View File

@ -134,12 +134,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 * ParseVariable
* *
* Parse a variable definition. * Parse a variable definition.
*/ */
static int ParseVariable( ORDDEF *odp ) static int ParseVariable( ORDDEF *odp, DLLSPEC *spec )
{ {
char *endptr; char *endptr;
int *value_array; int *value_array;
@ -147,7 +158,7 @@ static int ParseVariable( ORDDEF *odp )
int value_array_size; int value_array_size;
const char *token; const char *token;
if (SpecType == SPEC_WIN32) if (spec->type == SPEC_WIN32)
{ {
error( "'variable' not supported in Win32, use 'extern' instead\n" ); error( "'variable' not supported in Win32, use 'extern' instead\n" );
return 0; return 0;
@ -201,12 +212,12 @@ static int ParseVariable( ORDDEF *odp )
* *
* Parse a function definition. * Parse a function definition.
*/ */
static int ParseExportFunction( ORDDEF *odp ) static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec )
{ {
const char *token; const char *token;
unsigned int i; unsigned int i;
switch(SpecType) switch(spec->type)
{ {
case SPEC_WIN16: case SPEC_WIN16:
if (odp->type == TYPE_STDCALL) if (odp->type == TYPE_STDCALL)
@ -269,7 +280,7 @@ static int ParseExportFunction( ORDDEF *odp )
return 0; return 0;
} }
if (SpecType == SPEC_WIN32) if (spec->type == SPEC_WIN32)
{ {
if (strcmp(token, "long") && if (strcmp(token, "long") &&
strcmp(token, "ptr") && strcmp(token, "ptr") &&
@ -306,7 +317,7 @@ static int ParseExportFunction( ORDDEF *odp )
odp->link_name = xstrdup( token ); odp->link_name = xstrdup( token );
if (strchr( odp->link_name, '.' )) if (strchr( odp->link_name, '.' ))
{ {
if (SpecType == SPEC_WIN16) if (spec->type == SPEC_WIN16)
{ {
error( "Forwarded functions not supported for Win16\n" ); error( "Forwarded functions not supported for Win16\n" );
return 0; return 0;
@ -323,13 +334,13 @@ static int ParseExportFunction( ORDDEF *odp )
* *
* Parse an 'equate' definition. * Parse an 'equate' definition.
*/ */
static int ParseEquate( ORDDEF *odp ) static int ParseEquate( ORDDEF *odp, DLLSPEC *spec )
{ {
char *endptr; char *endptr;
int value; int value;
const char *token; const char *token;
if (SpecType == SPEC_WIN32) if (spec->type == SPEC_WIN32)
{ {
error( "'equate' not supported for Win32\n" ); error( "'equate' not supported for Win32\n" );
return 0; return 0;
@ -351,7 +362,7 @@ static int ParseEquate( ORDDEF *odp )
* *
* Parse a 'stub' definition. * Parse a 'stub' definition.
*/ */
static int ParseStub( ORDDEF *odp ) static int ParseStub( ORDDEF *odp, DLLSPEC *spec )
{ {
odp->u.func.arg_types[0] = '\0'; odp->u.func.arg_types[0] = '\0';
odp->link_name = xstrdup(""); odp->link_name = xstrdup("");
@ -364,11 +375,11 @@ static int ParseStub( ORDDEF *odp )
* *
* Parse an 'extern' definition. * Parse an 'extern' definition.
*/ */
static int ParseExtern( ORDDEF *odp ) static int ParseExtern( ORDDEF *odp, DLLSPEC *spec )
{ {
const char *token; const char *token;
if (SpecType == SPEC_WIN16) if (spec->type == SPEC_WIN16)
{ {
error( "'extern' not supported for Win16, use 'variable' instead\n" ); error( "'extern' not supported for Win16, use 'variable' instead\n" );
return 0; return 0;
@ -437,13 +448,12 @@ static void fix_export_name( char *name )
* *
* Parse an ordinal definition. * Parse an ordinal definition.
*/ */
static int ParseOrdinal(int ordinal) static int ParseOrdinal( int ordinal, DLLSPEC *spec )
{ {
const char *token; const char *token;
ORDDEF *odp = xmalloc( sizeof(*odp) ); ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) ); memset( odp, 0, sizeof(*odp) );
EntryPoints[nb_entry_points++] = odp;
if (!(token = GetToken(0))) goto error; if (!(token = GetToken(0))) goto error;
@ -468,22 +478,22 @@ static int ParseOrdinal(int ordinal)
switch(odp->type) switch(odp->type)
{ {
case TYPE_VARIABLE: case TYPE_VARIABLE:
if (!ParseVariable( odp )) goto error; if (!ParseVariable( odp, spec )) goto error;
break; break;
case TYPE_PASCAL: case TYPE_PASCAL:
case TYPE_STDCALL: case TYPE_STDCALL:
case TYPE_VARARGS: case TYPE_VARARGS:
case TYPE_CDECL: case TYPE_CDECL:
if (!ParseExportFunction( odp )) goto error; if (!ParseExportFunction( odp, spec )) goto error;
break; break;
case TYPE_ABS: case TYPE_ABS:
if (!ParseEquate( odp )) goto error; if (!ParseEquate( odp, spec )) goto error;
break; break;
case TYPE_STUB: case TYPE_STUB:
if (!ParseStub( odp )) goto error; if (!ParseStub( odp, spec )) goto error;
break; break;
case TYPE_EXTERN: case TYPE_EXTERN:
if (!ParseExtern( odp )) goto error; if (!ParseExtern( odp, spec )) goto error;
break; break;
default: default:
assert( 0 ); assert( 0 );
@ -493,8 +503,7 @@ static int ParseOrdinal(int ordinal)
if (odp->flags & FLAG_I386) if (odp->flags & FLAG_I386)
{ {
/* ignore this entry point on non-Intel archs */ /* ignore this entry point on non-Intel archs */
EntryPoints[--nb_entry_points] = NULL; spec->nb_entry_points--;
free( odp );
return 1; return 1;
} }
#endif #endif
@ -511,15 +520,9 @@ static int ParseOrdinal(int ordinal)
error( "Ordinal number %d too large\n", ordinal ); error( "Ordinal number %d too large\n", ordinal );
goto error; goto error;
} }
if (ordinal > Limit) Limit = ordinal; if (ordinal > spec->limit) spec->limit = ordinal;
if (ordinal < Base) Base = ordinal; if (ordinal < spec->base) spec->base = ordinal;
odp->ordinal = ordinal; odp->ordinal = ordinal;
if (Ordinals[ordinal])
{
error( "Duplicate ordinal %d\n", ordinal );
goto error;
}
Ordinals[ordinal] = odp;
} }
if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME) if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME)
@ -529,7 +532,7 @@ static int ParseOrdinal(int ordinal)
error( "Nameless function needs an explicit ordinal number\n" ); error( "Nameless function needs an explicit ordinal number\n" );
goto error; goto error;
} }
if (SpecType != SPEC_WIN32) if (spec->type != SPEC_WIN32)
{ {
error( "Nameless functions not supported for Win16\n" ); error( "Nameless functions not supported for Win16\n" );
goto error; goto error;
@ -538,13 +541,11 @@ static int ParseOrdinal(int ordinal)
else odp->export_name = odp->name; else odp->export_name = odp->name;
odp->name = NULL; odp->name = NULL;
} }
else Names[nb_names++] = odp;
return 1; return 1;
error: error:
EntryPoints[--nb_entry_points] = NULL; spec->nb_entry_points--;
free( odp->name ); free( odp->name );
free( odp );
return 0; return 0;
} }
@ -557,39 +558,94 @@ static int name_compare( const void *name1, const void *name2 )
} }
/******************************************************************* /*******************************************************************
* 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 */ /* 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 */ /* 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", error( "'%s' redefined\n%s:%d: First defined here\n",
Names[i]->name, input_file_name, spec->names[i]->name, input_file_name,
min( Names[i]->lineno, Names[i+1]->lineno ) ); 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 * ParseTopLevel
* *
* Parse a spec file. * Parse a spec file.
*/ */
int ParseTopLevel( FILE *file ) int ParseTopLevel( FILE *file, DLLSPEC *spec )
{ {
const char *token; const char *token;
@ -601,16 +657,16 @@ int ParseTopLevel( FILE *file )
if (!(token = GetToken(1))) continue; if (!(token = GetToken(1))) continue;
if (strcmp(token, "@") == 0) if (strcmp(token, "@") == 0)
{ {
if (SpecType != SPEC_WIN32) if (spec->type != SPEC_WIN32)
{ {
error( "'@' ordinals not supported for Win16\n" ); error( "'@' ordinals not supported for Win16\n" );
continue; continue;
} }
if (!ParseOrdinal( -1 )) continue; if (!ParseOrdinal( -1, spec )) continue;
} }
else if (IsNumberString(token)) else if (IsNumberString(token))
{ {
if (!ParseOrdinal( atoi(token) )) continue; if (!ParseOrdinal( atoi(token), spec )) continue;
} }
else else
{ {
@ -621,7 +677,8 @@ int ParseTopLevel( FILE *file )
} }
current_line = 0; /* no longer parsing the input file */ current_line = 0; /* no longer parsing the input file */
sort_names(); assign_names( spec );
assign_ordinals( spec );
return !nb_errors; return !nb_errors;
} }

View File

@ -69,28 +69,29 @@ struct res_type
unsigned int nb_names; /* total number of names */ unsigned int nb_names; /* total number of names */
}; };
static struct resource *resources; /* top level of the resource tree */
static int nb_resources; struct res_tree
{
static struct res_type *res_types; struct res_type *types; /* types array */
static int nb_types; /* total number of types */ unsigned int nb_types; /* total number of types */
};
static const unsigned char *file_pos; /* current position in resource file */ static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */ static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */ 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) ); spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) );
return &resources[nb_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; struct res_type *type;
res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) ); tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
type = &res_types[nb_types++]; type = &tree->types[tree->nb_types++];
type->type = &res->type; type->type = &res->type;
type->res = res; type->res = res;
type->nb_names = 0; type->nb_names = 0;
@ -151,9 +152,9 @@ static void get_string( struct string_id *str )
} }
/* load the next resource from the current file */ /* 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->type );
get_string( &res->name ); get_string( &res->name );
@ -165,7 +166,7 @@ static void load_next_resource(void)
} }
/* load a Win16 .res file */ /* load a Win16 .res file */
void load_res16_file( const char *name ) void load_res16_file( const char *name, DLLSPEC *spec )
{ {
int fd; int fd;
void *base; void *base;
@ -186,7 +187,7 @@ void load_res16_file( const char *name )
file_name = name; file_name = name;
file_pos = base; file_pos = base;
file_end = file_pos + st.st_size; 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 */ /* compare two strings/ids */
@ -214,19 +215,32 @@ static int cmp_res( const void *ptr1, const void *ptr2 )
} }
/* build the 2-level (type,name) resource tree */ /* 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; int i;
struct res_tree *tree;
struct res_type *type = NULL; 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 */ if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
type = add_type( &resources[i] ); type = add_type( tree, &spec->resources[i] );
type->nb_names++; 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 ) inline static void put_byte( unsigned char **buffer, unsigned char val )
@ -254,19 +268,19 @@ static void output_string( unsigned char **buffer, const char *str )
} }
/* output the resource data */ /* output the resource data */
int output_res16_data( FILE *outfile ) int output_res16_data( FILE *outfile, DLLSPEC *spec )
{ {
const struct resource *res; const struct resource *res;
unsigned char *buffer, *p; unsigned char *buffer, *p;
int i, total; 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; total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK;
buffer = p = xmalloc( total ); 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 ); memcpy( p, res->data, res->data_size );
p += res->data_size; p += res->data_size;
@ -278,25 +292,26 @@ int output_res16_data( FILE *outfile )
} }
/* output the resource definitions */ /* 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; int i, offset, res_offset = 0;
unsigned int j; unsigned int j;
struct res_tree *tree;
const struct res_type *type; const struct res_type *type;
const struct resource *res; const struct resource *res;
unsigned char *start = buffer; unsigned char *start = buffer;
build_resource_tree(); tree = build_resource_tree( spec );
offset = 4; /* alignment + terminator */ offset = 4; /* alignment + terminator */
offset += nb_types * 8; /* typeinfo structures */ offset += tree->nb_types * 8; /* typeinfo structures */
offset += nb_resources * 12; /* nameinfo structures */ offset += spec->nb_resources * 12; /* nameinfo structures */
put_word( &buffer, ALIGNMENT ); put_word( &buffer, ALIGNMENT );
/* type and name structures */ /* 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) if (type->type->str)
{ {
@ -331,7 +346,7 @@ int output_res16_directory( unsigned char *buffer )
/* name strings */ /* 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 ); if (type->type->str) output_string( &buffer, type->type->str );
for (j = 0, res = type->res; j < type->nb_names; j++, res++) for (j = 0, res = type->res; j < type->nb_names; j++, res++)
@ -342,5 +357,6 @@ int output_res16_directory( unsigned char *buffer )
put_byte( &buffer, 0 ); /* names terminator */ put_byte( &buffer, 0 ); /* names terminator */
if ((buffer - start) & 1) put_byte( &buffer, 0 ); /* align on word boundary */ if ((buffer - start) & 1) put_byte( &buffer, 0 ); /* align on word boundary */
free_resource_tree( tree );
return buffer - start; return buffer - start;
} }

View File

@ -75,22 +75,22 @@ struct res_type
unsigned int nb_id_names; /* number of names that have a numeric id */ unsigned int nb_id_names; /* number of names that have a numeric id */
}; };
static struct resource *resources; /* top level of the resource tree */
static int nb_resources; struct res_tree
{
static struct res_type *res_types; struct res_type *types; /* types array */
static int nb_types; /* total number of types */ unsigned int nb_types; /* total number of types */
static int nb_id_types; /* number of types that have a numeric id */ };
static const unsigned char *file_pos; /* current position in resource file */ static const unsigned char *file_pos; /* current position in resource file */
static const unsigned char *file_end; /* end of resource file */ static const unsigned char *file_end; /* end of resource file */
static const char *file_name; /* current resource file name */ 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) ); spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) );
return &resources[nb_resources++]; return &spec->resources[spec->nb_resources++];
} }
static inline unsigned int strlenW( const WCHAR *str ) static inline unsigned int strlenW( const WCHAR *str )
@ -118,16 +118,15 @@ static struct res_name *add_name( struct res_type *type, const struct resource *
return name; 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; struct res_type *type;
res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) ); tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
type = &res_types[nb_types++]; type = &tree->types[tree->nb_types++];
type->type = &res->type; type->type = &res->type;
type->names = NULL; type->names = NULL;
type->nb_names = 0; type->nb_names = 0;
type->nb_id_names = 0; type->nb_id_names = 0;
if (!type->type->str) nb_id_types++;
return type; return type;
} }
@ -184,10 +183,10 @@ static int check_header(void)
} }
/* load the next resource from the current file */ /* load the next resource from the current file */
static void load_next_resource(void) static void load_next_resource( DLLSPEC *spec )
{ {
DWORD hdr_size; DWORD hdr_size;
struct resource *res = add_resource(); struct resource *res = add_resource( spec );
res->data_size = (get_dword() + 3) & ~3; res->data_size = (get_dword() + 3) & ~3;
hdr_size = get_dword(); hdr_size = get_dword();
@ -208,7 +207,7 @@ static void load_next_resource(void)
} }
/* load a Win32 .res file */ /* load a Win32 .res file */
int load_res32_file( const char *name ) int load_res32_file( const char *name, DLLSPEC *spec )
{ {
int fd, ret; int fd, ret;
void *base; void *base;
@ -231,7 +230,7 @@ int load_res32_file( const char *name )
file_end = file_pos + st.st_size; file_end = file_pos + st.st_size;
if ((ret = check_header())) if ((ret = check_header()))
{ {
while (file_pos < file_end) load_next_resource(); while (file_pos < file_end) load_next_resource( spec );
} }
close( fd ); close( fd );
return ret; return ret;
@ -263,27 +262,43 @@ static int cmp_res( const void *ptr1, const void *ptr2 )
} }
/* build the 3-level (type,name,language) resource tree */ /* 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; int i;
struct res_tree *tree;
struct res_type *type = NULL; struct res_type *type = NULL;
struct res_name *name = 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] ); type = add_type( tree, &spec->resources[i] );
name = add_name( type, &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++; 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 */ /* output a Unicode string */
@ -298,21 +313,22 @@ static void output_string( FILE *outfile, const WCHAR *name )
} }
/* output the resource definitions */ /* output the resource definitions */
int output_resources( FILE *outfile ) void output_resources( FILE *outfile, DLLSPEC *spec )
{ {
int i, j, k; int i, j, k, nb_id_types;
unsigned int n; unsigned int n;
struct res_tree *tree;
const struct res_type *type; const struct res_type *type;
const struct res_name *name; const struct res_name *name;
const struct resource *res; const struct resource *res;
if (!nb_resources) return 0; if (!spec->nb_resources) return;
build_resource_tree(); tree = build_resource_tree( spec );
/* resource data */ /* 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; const unsigned int *p = res->data;
int size = res->data_size / 4; int size = res->data_size / 4;
@ -347,9 +363,9 @@ int output_resources( FILE *outfile )
fprintf( outfile, "#define OFFSETOF(field) ((char*)&((struct res_struct *)0)->field - (char*)((struct res_struct *) 0))\n" ); 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, "static struct res_struct{\n" );
fprintf( outfile, " struct res_dir type_dir;\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 );
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, " struct res_dir name_%d_dir;\n", i ); 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 ); fprintf( outfile, " struct res_dir_entry name_%d_entries[%d];\n", i, type->nb_names );
@ -361,13 +377,16 @@ int output_resources( FILE *outfile )
} }
} }
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 );
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) if (type->type->str)
fprintf( outfile, " unsigned short type_%d_name[%d];\n", fprintf( outfile, " unsigned short type_%d_name[%d];\n",
i, strlenW(type->type->str)+1 ); i, strlenW(type->type->str)+1 );
else
nb_id_types++;
for (n = 0, name = type->names; n < type->nb_names; n++, name++) for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{ {
if (name->name->str) if (name->name->str)
@ -379,11 +398,11 @@ int output_resources( FILE *outfile )
/* resource directory contents */ /* resource directory contents */
fprintf( outfile, "} resources = {\n" ); 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 */ /* dump the type directory */
fprintf( outfile, " {\n" ); 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) if (!type->type->str)
fprintf( outfile, " { 0x%04x, OFFSETOF(name_%d_dir) | 0x80000000 },\n", fprintf( outfile, " { 0x%04x, OFFSETOF(name_%d_dir) | 0x80000000 },\n",
@ -395,7 +414,7 @@ int output_resources( FILE *outfile )
fprintf( outfile, " },\n" ); fprintf( outfile, " },\n" );
/* dump the names and languages directories */ /* 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", 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 ); type->nb_names - type->nb_id_names, type->nb_id_names, i );
@ -417,7 +436,7 @@ int output_resources( FILE *outfile )
for (k = 0, res = name->res; k < name->nb_languages; k++, res++) for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{ {
fprintf( outfile, " { 0x%04x, OFFSETOF(data_entries[%d]) },\n", fprintf( outfile, " { 0x%04x, OFFSETOF(data_entries[%d]) },\n",
res->lang, res - resources ); res->lang, res - spec->resources );
} }
fprintf( outfile, " },\n" ); fprintf( outfile, " },\n" );
} }
@ -425,13 +444,13 @@ int output_resources( FILE *outfile )
/* dump the resource data entries */ /* dump the resource data entries */
fprintf( outfile, " {\n" ); 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 },\n", i, i );
} }
/* dump the name strings */ /* 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) if (type->type->str)
{ {
@ -448,5 +467,5 @@ int output_resources( FILE *outfile )
} }
} }
fprintf( outfile, " }\n};\n#undef OFFSETOF\n\n" ); fprintf( outfile, " }\n};\n#undef OFFSETOF\n\n" );
return nb_resources; free_resource_tree( tree );
} }

View File

@ -111,7 +111,7 @@ static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp )
* as a byte stream into the assembly code. * as a byte stream into the assembly code.
*/ */
static int BuildModule16( FILE *outfile, int max_code_offset, static int BuildModule16( FILE *outfile, int max_code_offset,
int max_data_offset ) int max_data_offset, DLLSPEC *spec )
{ {
int i; int i;
char *buffer; char *buffer;
@ -142,7 +142,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pModule->next = 0; pModule->next = 0;
pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE; pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
pModule->dgroup = 2; pModule->dgroup = 2;
pModule->heap_size = DLLHeapSize; pModule->heap_size = spec->heap_size;
pModule->stack_size = 0; pModule->stack_size = 0;
pModule->ip = 0; pModule->ip = 0;
pModule->cs = 0; pModule->cs = 0;
@ -172,8 +172,8 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pModule->fileinfo = (int)pFileInfo - (int)pModule; pModule->fileinfo = (int)pFileInfo - (int)pModule;
memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) ); memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
+ strlen(dll_file_name); + strlen(spec->file_name);
strcpy( pFileInfo->szPathName, dll_file_name ); strcpy( pFileInfo->szPathName, spec->file_name );
pstr = (char *)pFileInfo + pFileInfo->cBytes + 1; pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
/* Segment table */ /* Segment table */
@ -201,7 +201,7 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pstr = (char *)pSegment; pstr = (char *)pSegment;
pstr = (char *)(((long)pstr + 3) & ~3); pstr = (char *)(((long)pstr + 3) & ~3);
pModule->res_table = (int)pstr - (int)pModule; pModule->res_table = (int)pstr - (int)pModule;
pstr += output_res16_directory( pstr ); pstr += output_res16_directory( pstr, spec );
/* Imported names table */ /* Imported names table */
@ -215,16 +215,16 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pstr = (char *)(((long)pstr + 3) & ~3); pstr = (char *)(((long)pstr + 3) & ~3);
pModule->name_table = (int)pstr - (int)pModule; pModule->name_table = (int)pstr - (int)pModule;
/* First entry is module name */ /* First entry is module name */
*pstr = strlen( dll_name ); *pstr = strlen( spec->dll_name );
strcpy( pstr + 1, dll_name ); strcpy( pstr + 1, spec->dll_name );
strupper( pstr + 1 ); strupper( pstr + 1 );
pstr += *pstr + 1; pstr += *pstr + 1;
*pstr++ = 0; *pstr++ = 0;
*pstr++ = 0; *pstr++ = 0;
/* Store all ordinals */ /* 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; WORD ord = i;
if (!odp || !odp->name[0]) continue; if (!odp || !odp->name[0]) continue;
*pstr = strlen( odp->name ); *pstr = strlen( odp->name );
@ -240,10 +240,10 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
pstr = (char *)(((long)pstr + 3) & ~3); pstr = (char *)(((long)pstr + 3) & ~3);
pModule->entry_table = (int)pstr - (int)pModule; pModule->entry_table = (int)pstr - (int)pModule;
for (i = 1; i <= Limit; i++) for (i = 1; i <= spec->limit; i++)
{ {
int selector = 0; int selector = 0;
ORDDEF *odp = Ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp) continue; if (!odp) continue;
switch (odp->type) switch (odp->type)
@ -504,14 +504,14 @@ static int Spec16TypeCompare( const void *e1, const void *e2 )
* *
* Output the functions for stub entry points * 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; int i;
char *p; 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; if (!odp || odp->type != TYPE_STUB) continue;
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
@ -528,7 +528,7 @@ static void output_stub_funcs( FILE *outfile )
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE ); fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\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, " rec.info[1] = func;\n" );
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
@ -538,9 +538,9 @@ static void output_stub_funcs( FILE *outfile )
fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" ); fprintf( outfile, " for (;;) RtlRaiseException( &rec );\n}\n\n" );
break; 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; if (!odp || odp->type != TYPE_STUB) continue;
odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 ); odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 );
strcpy( odp->link_name, "__wine_stub_" ); strcpy( odp->link_name, "__wine_stub_" );
@ -557,7 +557,7 @@ static void output_stub_funcs( FILE *outfile )
* *
* Build a Win16 assembly file from a spec file. * Build a Win16 assembly file from a spec file.
*/ */
void BuildSpec16File( FILE *outfile ) void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
{ {
ORDDEF **type, **typelist; ORDDEF **type, **typelist;
int i, nFuncs, nTypes; int i, nFuncs, nTypes;
@ -580,22 +580,22 @@ void BuildSpec16File( FILE *outfile )
memset( data, 0, 16 ); memset( data, 0, 16 );
data_offset = 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; char *p;
dll_name = xstrdup( dll_file_name ); spec->dll_name = xstrdup( spec->file_name );
if ((p = strrchr( dll_name, '.' ))) *p = 0; 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 */ /* 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; if (!odp) continue;
switch (odp->type) switch (odp->type)
{ {
@ -627,15 +627,15 @@ void BuildSpec16File( FILE *outfile )
char profile[101]; char profile[101];
strcpy( profile, get_function_name( typelist[i] )); strcpy( profile, get_function_name( typelist[i] ));
BuildCallFrom16Func( outfile, profile, dll_file_name ); BuildCallFrom16Func( outfile, profile, spec->file_name );
} }
#endif #endif
/* Output the DLL functions prototypes */ /* 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; if (!odp) continue;
switch(odp->type) switch(odp->type)
{ {
@ -724,7 +724,7 @@ void BuildSpec16File( FILE *outfile )
#ifdef __i386__ #ifdef __i386__
fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n", fprintf( outfile, " { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
make_c_identifier(dll_file_name), profile, make_c_identifier(spec->file_name), profile,
(typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) ? "regs": (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) ? "regs":
(typelist[i]->flags & FLAG_RET16) ? "word" : "long" ); (typelist[i]->flags & FLAG_RET16) ? "word" : "long" );
if (argsize) if (argsize)
@ -745,9 +745,9 @@ void BuildSpec16File( FILE *outfile )
} }
fprintf( outfile, " },\n {\n" ); 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; if (!odp) continue;
switch (odp->type) switch (odp->type)
{ {
@ -767,7 +767,7 @@ void BuildSpec16File( FILE *outfile )
type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare ); type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
assert( type ); assert( type );
fprintf( outfile, " /* %s.%d */ ", dll_name, i ); fprintf( outfile, " /* %s.%d */ ", spec->dll_name, i );
#ifdef __i386__ #ifdef __i386__
fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n", fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d /* %s */ },\n",
#else #else
@ -797,8 +797,8 @@ void BuildSpec16File( FILE *outfile )
/* Build the module */ /* Build the module */
module_size = BuildModule16( outfile, code_offset, data_offset ); module_size = BuildModule16( outfile, code_offset, data_offset, spec );
res_size = output_res16_data( outfile ); res_size = output_res16_data( outfile, spec );
/* Output the DLL descriptor */ /* Output the DLL descriptor */
@ -816,14 +816,14 @@ void BuildSpec16File( FILE *outfile )
fprintf( outfile, " sizeof(Module),\n" ); fprintf( outfile, " sizeof(Module),\n" );
fprintf( outfile, " &code_segment,\n" ); fprintf( outfile, " &code_segment,\n" );
fprintf( outfile, " Data_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, " %s\n", res_size ? "resource_data" : "0" );
fprintf( outfile, "};\n" ); fprintf( outfile, "};\n" );
/* Output the DLL constructor */ /* Output the DLL constructor */
sprintf( constructor, "__wine_spec_%s_init", 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(dll_file_name) ); sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
output_dll_init( outfile, constructor, destructor ); output_dll_init( outfile, constructor, destructor );
fprintf( outfile, fprintf( outfile,

View File

@ -55,51 +55,22 @@ static int string_compare( const void *ptr1, const void *ptr2 )
* *
* Generate an internal name for an entry point. Used for stubs etc. * 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]; static char buffer[256];
if (odp->name || odp->export_name) if (odp->name || odp->export_name)
{ {
char *p; 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 ); odp->name ? odp->name : odp->export_name );
/* make sure name is a legal C identifier */ /* make sure name is a legal C identifier */
for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break; for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
if (!*p) return buffer; 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; return buffer;
} }
/*******************************************************************
* AssignOrdinals
*
* Assign ordinals to all entry points.
*/
static void AssignOrdinals(void)
{
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;
}
/******************************************************************* /*******************************************************************
* output_debug * output_debug
* *
@ -134,7 +105,7 @@ static int output_debug( FILE *outfile )
* *
* Output the export table for a Win32 module. * 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; int i, fwd_size = 0, total_size = 0;
@ -150,11 +121,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" ); /* TimeDateStamp */
fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* MajorVersion/MinorVersion */ fprintf( outfile, " \"\\t.long 0\\n\"\n" ); /* MajorVersion/MinorVersion */
fprintf( outfile, " \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */ 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", spec->base ); /* Base */
fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */ 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->nb_names ); /* NumberOfNames */
fprintf( outfile, " \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */ 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_name_ptrs\\n\"\n" ); /* AddressOfNames */
fprintf( outfile, " \"\\t.long __wine_spec_exp_ordinals\\n\"\n" ); /* AddressOfNameOrdinals */ fprintf( outfile, " \"\\t.long __wine_spec_exp_ordinals\\n\"\n" ); /* AddressOfNameOrdinals */
@ -169,9 +140,9 @@ static int output_exports( FILE *outfile, int nr_exports )
/* output the function pointers */ /* output the function pointers */
fprintf( outfile, " \"__wine_spec_exports_funcs:\\n\"\n" ); 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" ); if (!odp) fprintf( outfile, " \"\\t.long 0\\n\"\n" );
else switch(odp->type) else switch(odp->type)
{ {
@ -182,7 +153,8 @@ static int output_exports( FILE *outfile, int nr_exports )
if (!(odp->flags & FLAG_FORWARD)) if (!(odp->flags & FLAG_FORWARD))
{ {
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", 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 else
{ {
@ -191,49 +163,51 @@ static int output_exports( FILE *outfile, int nr_exports )
} }
break; break;
case TYPE_STUB: 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; break;
default: default:
assert(0); 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 */ /* 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" ); 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 ); 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 */ /* output the function names */
fprintf( outfile, " \"\\t.text\\n\"\n" ); fprintf( outfile, " \"\\t.text\\n\"\n" );
fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" ); fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" );
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", dll_file_name ); fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
for (i = 0; i < nb_names; i++) for (i = 0; i < spec->nb_names; i++)
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", Names[i]->name ); fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
fprintf( outfile, " \"\\t.data\\n\"\n" ); fprintf( outfile, " \"\\t.data\\n\"\n" );
if (nb_names) if (spec->nb_names)
{ {
/* output the function ordinals */ /* output the function ordinals */
fprintf( outfile, " \"__wine_spec_exp_ordinals:\\n\"\n" ); 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); total_size += spec->nb_names * sizeof(short);
if (nb_names % 2) if (spec->nb_names % 2)
{ {
fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" ); fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" );
total_size += sizeof(short); total_size += sizeof(short);
@ -245,9 +219,9 @@ static int output_exports( FILE *outfile, int nr_exports )
if (fwd_size) if (fwd_size)
{ {
fprintf( outfile, " \"__wine_spec_forwards:\\n\"\n" ); 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)) if (odp && (odp->flags & FLAG_FORWARD))
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name ); fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
} }
@ -259,9 +233,9 @@ static int output_exports( FILE *outfile, int nr_exports )
if (debugging) 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; unsigned int j, args, mask = 0;
const char *name; const char *name;
@ -281,7 +255,7 @@ static int output_exports( FILE *outfile, int nr_exports )
name = odp->link_name; name = odp->link_name;
args = strlen(odp->u.func.arg_types) * sizeof(int); 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) switch(odp->type)
{ {
@ -319,13 +293,13 @@ static int output_exports( FILE *outfile, int nr_exports )
* *
* Output the functions for stub entry points * 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; 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; if (odp->type != TYPE_STUB) continue;
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" ); fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
@ -343,7 +317,7 @@ static void output_stub_funcs( FILE *outfile )
fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE ); fprintf( outfile, " rec.flags = %d;\n", EH_NONCONTINUABLE );
fprintf( outfile, " rec.rec = 0;\n" ); fprintf( outfile, " rec.rec = 0;\n" );
fprintf( outfile, " rec.params = 2;\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, " rec.info[1] = func;\n" );
fprintf( outfile, "#ifdef __GNUC__\n" ); fprintf( outfile, "#ifdef __GNUC__\n" );
fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" ); fprintf( outfile, " rec.addr = __builtin_return_address(1);\n" );
@ -354,11 +328,11 @@ static void output_stub_funcs( FILE *outfile )
break; 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; 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) if (odp->name)
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name ); fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
else if (odp->export_name) else if (odp->export_name)
@ -374,18 +348,18 @@ static void output_stub_funcs( FILE *outfile )
* *
* Output the functions for register entry points * 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; const char *name;
int i; 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->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
if (!(odp->flags & FLAG_REGISTER)) continue; if (!(odp->flags & FLAG_REGISTER)) continue;
if (odp->flags & FLAG_FORWARD) continue; if (odp->flags & FLAG_FORWARD) continue;
name = make_internal_name( odp, "regs" ); name = make_internal_name( odp, spec, "regs" );
fprintf( outfile, fprintf( outfile,
"asm(\".align %d\\n\\t\"\n" "asm(\".align %d\\n\\t\"\n"
" \"" __ASM_FUNC("%s") "\\n\\t\"\n" " \"" __ASM_FUNC("%s") "\\n\\t\"\n"
@ -485,12 +459,13 @@ void output_dll_init( FILE *outfile, const char *constructor, const char *destru
* *
* Build a Win32 C file from a spec file. * Build a Win32 C file from a spec file.
*/ */
void BuildSpec32File( FILE *outfile ) void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
{ {
int exports_size = 0; int exports_size = 0;
int nr_exports, nr_imports, nr_resources; int nr_exports, nr_imports;
int characteristics, subsystem; int characteristics, subsystem;
DWORD page_size; DWORD page_size;
const char *init_func = spec->init_func;
#ifdef HAVE_GETPAGESIZE #ifdef HAVE_GETPAGESIZE
page_size = getpagesize(); page_size = getpagesize();
@ -506,10 +481,8 @@ void BuildSpec32File( FILE *outfile )
# error Cannot get the page size on this platform # error Cannot get the page size on this platform
#endif #endif
AssignOrdinals(); nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
nr_exports = Base <= Limit ? Limit - Base + 1 : 0; resolve_imports( spec );
resolve_imports();
output_standard_file_header( outfile ); output_standard_file_header( outfile );
/* Reserve some space for the PE header */ /* Reserve some space for the PE header */
@ -541,7 +514,7 @@ void BuildSpec32File( FILE *outfile )
{ {
/* Output the stub functions */ /* Output the stub functions */
output_stub_funcs( outfile ); output_stub_funcs( outfile, spec );
fprintf( outfile, "#ifndef __GNUC__\n" ); fprintf( outfile, "#ifndef __GNUC__\n" );
fprintf( outfile, "static void __asm__dummy(void) {\n" ); fprintf( outfile, "static void __asm__dummy(void) {\n" );
@ -549,11 +522,11 @@ void BuildSpec32File( FILE *outfile )
/* Output code for all register functions */ /* Output code for all register functions */
output_register_funcs( outfile ); output_register_funcs( outfile, spec );
/* Output the exports and relay entry points */ /* 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, "#ifndef __GNUC__\n" );
fprintf( outfile, "}\n" ); fprintf( outfile, "}\n" );
@ -562,11 +535,11 @@ void BuildSpec32File( FILE *outfile )
/* Output the DLL imports */ /* Output the DLL imports */
nr_imports = output_imports( outfile ); nr_imports = output_imports( outfile, spec );
/* Output the resources */ /* Output the resources */
nr_resources = output_resources( outfile ); output_resources( outfile, spec );
/* Output the entry point function */ /* Output the entry point function */
@ -579,7 +552,7 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, "extern void _fini();\n" ); fprintf( outfile, "extern void _fini();\n" );
characteristics = subsystem = 0; characteristics = subsystem = 0;
switch(SpecMode) switch(spec->mode)
{ {
case SPEC_MODE_DLL: case SPEC_MODE_DLL:
if (init_func) if (init_func)
@ -772,9 +745,9 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */ fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */
fprintf( outfile, " 0,\n" ); /* DllCharacteristics */ fprintf( outfile, " 0,\n" ); /* DllCharacteristics */
fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */ 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 */ 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, " 0,\n" ); /* LoaderFlags */
fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */ fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */
fprintf( outfile, " {\n" ); fprintf( outfile, " {\n" );
@ -783,7 +756,8 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */ fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */
nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" ); nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */ 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" ); fprintf( outfile, " }\n }\n};\n\n" );
/* Output the DLL constructor */ /* Output the DLL constructor */
@ -795,7 +769,7 @@ void BuildSpec32File( FILE *outfile )
" __wine_spec_init_state = 1;\n" " __wine_spec_init_state = 1;\n"
" __wine_dll_register( &nt_header, \"%s\" );\n" " __wine_dll_register( &nt_header, \"%s\" );\n"
"}\n\n", "}\n\n",
dll_file_name ); spec->file_name );
output_dll_init( outfile, "__wine_spec_init_ctor", NULL ); output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
fprintf( outfile, fprintf( outfile,
@ -813,25 +787,23 @@ void BuildSpec32File( FILE *outfile )
* *
* Build a Win32 def file from a spec file. * Build a Win32 def file from a spec file.
*/ */
void BuildDef32File(FILE *outfile) void BuildDef32File( FILE *outfile, DLLSPEC *spec )
{ {
const char *name; const char *name;
int i; int i;
AssignOrdinals();
fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n", fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n",
input_file_name ); 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"); fprintf(outfile, "EXPORTS\n");
/* Output the exports and relay entry points */ /* 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; int is_data = 0;
if (!odp) continue; if (!odp) continue;