Commit 8611e654 authored by Alexandre Julliard's avatar Alexandre Julliard

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

using global variables to make it easier to reuse the parsing routines.
parent 2ad864dc
......@@ -94,6 +94,28 @@ 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) */
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 */
#define FLAG_NORELAY 0x01 /* don't use relay debugging for this function */
#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_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 ParseTopLevel( FILE *file, DLLSPEC *spec );
/* 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 */
......@@ -525,16 +525,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 ||
......@@ -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 */
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;
......@@ -558,44 +558,44 @@ 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)
switch (spec->mode)
{
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" );
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 );
/* fall through */
case SPEC_MODE_CUIEXE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
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" );
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 );
/* fall through */
case SPEC_MODE_CUIEXE_UNICODE:
kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
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 );
......@@ -609,16 +609,16 @@ 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;
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 ) &&
odp->link_name[len] == '.')
......@@ -708,13 +708,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++)
......@@ -732,7 +732,7 @@ int resolve_imports( void )
}
}
/* 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 );
......@@ -873,7 +873,7 @@ static int output_immediate_imports( FILE *outfile )
}
/* 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;
......@@ -941,9 +941,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" );
......@@ -1153,8 +1153,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 );
}
......@@ -36,20 +36,7 @@
#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,10 +50,6 @@ 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;
......@@ -94,18 +77,18 @@ 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, '.' )) && !strcmp( p, ".spec" )) *p = 0;
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
}
/* 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 */
static char **parse_options( int argc, char **argv )
static char **parse_options( int argc, char **argv, DLLSPEC *spec )
{
char *p;
int optc;
......@@ -222,14 +205,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 +225,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;
......@@ -281,10 +264,10 @@ static char **parse_options( int argc, char **argv )
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;
if (!strcmp( optarg, "gui" )) spec->mode = SPEC_MODE_GUIEXE;
else if (!strcmp( optarg, "cui" )) spec->mode = SPEC_MODE_CUIEXE;
else if (!strcmp( optarg, "guiw" )) spec->mode = SPEC_MODE_GUIEXE_UNICODE;
else if (!strcmp( optarg, "cuiw" )) spec->mode = SPEC_MODE_CUIEXE_UNICODE;
else usage(1);
break;
case 'o':
......@@ -305,21 +288,21 @@ static char **parse_options( int argc, char **argv )
case LONG_OPT_SPEC:
set_exec_mode( MODE_SPEC );
input_file = open_input_file( NULL, optarg );
set_dll_file_name( 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 );
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->mode == SPEC_MODE_DLL) spec->mode = SPEC_MODE_GUIEXE;
break;
case LONG_OPT_DEBUG:
set_exec_mode( MODE_DEBUG );
......@@ -343,28 +326,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;
......@@ -377,39 +360,60 @@ static void load_resources( 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;
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)
load_resources( argv, &spec );
if (!ParseTopLevel( input_file, &spec )) break;
switch (spec.type)
{
case SPEC_WIN16:
if (argv[0])
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildSpec16File( output_file );
BuildSpec16File( output_file, &spec );
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 (!ParseTopLevel( input_file, &spec )) break;
BuildDef32File( output_file, &spec );
break;
case MODE_DEBUG:
BuildDebugFile( output_file, current_src_dir, argv );
......
......@@ -69,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;
......@@ -151,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 );
......@@ -165,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;
......@@ -186,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 */
......@@ -214,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 );
tree = xmalloc( sizeof(*tree) );
tree->types = NULL;
tree->nb_types = 0;
for (i = 0; i < nb_resources; i++)
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 )
......@@ -254,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;
......@@ -278,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)
{
......@@ -331,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++)
......@@ -342,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;
}
......@@ -75,22 +75,22 @@ struct res_type
unsigned int nb_id_names; /* number of names that have a numeric id */
};
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 */
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 )
......@@ -118,16 +118,15 @@ 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;
}
......@@ -184,10 +183,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();
......@@ -208,7 +207,7 @@ static void load_next_resource(void)
}
/* 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;
......@@ -231,7 +230,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;
......@@ -263,27 +262,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 */
......@@ -298,21 +313,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;
int i, j, k, nb_id_types;
unsigned int n;
struct res_tree *tree;
const struct res_type *type;
const 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;
......@@ -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, "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 );
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_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)
fprintf( outfile, " unsigned short type_%d_name[%d];\n",
i, strlenW(type->type->str)+1 );
else
nb_id_types++;
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
if (name->name->str)
......@@ -379,11 +398,11 @@ int output_resources( FILE *outfile )
/* 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 */
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",
......@@ -395,7 +414,7 @@ int output_resources( FILE *outfile )
fprintf( outfile, " },\n" );
/* 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 );
......@@ -417,7 +436,7 @@ int output_resources( FILE *outfile )
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 );
res->lang, res - spec->resources );
}
fprintf( outfile, " },\n" );
}
......@@ -425,13 +444,13 @@ 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 );
}
/* 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)
{
......@@ -448,5 +467,5 @@ int output_resources( FILE *outfile )
}
}
fprintf( outfile, " }\n};\n#undef OFFSETOF\n\n" );
return nb_resources;
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)
......@@ -504,14 +504,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 +528,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 +538,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 +557,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 +580,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 +627,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)
{
......@@ -724,7 +724,7 @@ void BuildSpec16File( FILE *outfile )
#ifdef __i386__
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_RET16) ? "word" : "long" );
if (argsize)
......@@ -745,9 +745,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 +767,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 +797,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 +816,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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment