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:
parent
2ad864dc87
commit
8611e654fc
|
@ -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 );
|
||||
|
|
|
@ -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
|
||||
*
|
||||
* Parse a variable definition.
|
||||
*/
|
||||
static int ParseVariable( ORDDEF *odp )
|
||||
static int ParseVariable( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
char *endptr;
|
||||
int *value_array;
|
||||
|
@ -147,7 +158,7 @@ static int ParseVariable( ORDDEF *odp )
|
|||
int value_array_size;
|
||||
const char *token;
|
||||
|
||||
if (SpecType == SPEC_WIN32)
|
||||
if (spec->type == SPEC_WIN32)
|
||||
{
|
||||
error( "'variable' not supported in Win32, use 'extern' instead\n" );
|
||||
return 0;
|
||||
|
@ -201,12 +212,12 @@ static int ParseVariable( ORDDEF *odp )
|
|||
*
|
||||
* Parse a function definition.
|
||||
*/
|
||||
static int ParseExportFunction( ORDDEF *odp )
|
||||
static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
unsigned int i;
|
||||
|
||||
switch(SpecType)
|
||||
switch(spec->type)
|
||||
{
|
||||
case SPEC_WIN16:
|
||||
if (odp->type == TYPE_STDCALL)
|
||||
|
@ -269,7 +280,7 @@ static int ParseExportFunction( ORDDEF *odp )
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (SpecType == SPEC_WIN32)
|
||||
if (spec->type == SPEC_WIN32)
|
||||
{
|
||||
if (strcmp(token, "long") &&
|
||||
strcmp(token, "ptr") &&
|
||||
|
@ -306,7 +317,7 @@ static int ParseExportFunction( ORDDEF *odp )
|
|||
odp->link_name = xstrdup( token );
|
||||
if (strchr( odp->link_name, '.' ))
|
||||
{
|
||||
if (SpecType == SPEC_WIN16)
|
||||
if (spec->type == SPEC_WIN16)
|
||||
{
|
||||
error( "Forwarded functions not supported for Win16\n" );
|
||||
return 0;
|
||||
|
@ -323,13 +334,13 @@ static int ParseExportFunction( ORDDEF *odp )
|
|||
*
|
||||
* Parse an 'equate' definition.
|
||||
*/
|
||||
static int ParseEquate( ORDDEF *odp )
|
||||
static int ParseEquate( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
char *endptr;
|
||||
int value;
|
||||
const char *token;
|
||||
|
||||
if (SpecType == SPEC_WIN32)
|
||||
if (spec->type == SPEC_WIN32)
|
||||
{
|
||||
error( "'equate' not supported for Win32\n" );
|
||||
return 0;
|
||||
|
@ -351,7 +362,7 @@ static int ParseEquate( ORDDEF *odp )
|
|||
*
|
||||
* Parse a 'stub' definition.
|
||||
*/
|
||||
static int ParseStub( ORDDEF *odp )
|
||||
static int ParseStub( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
odp->u.func.arg_types[0] = '\0';
|
||||
odp->link_name = xstrdup("");
|
||||
|
@ -364,11 +375,11 @@ static int ParseStub( ORDDEF *odp )
|
|||
*
|
||||
* Parse an 'extern' definition.
|
||||
*/
|
||||
static int ParseExtern( ORDDEF *odp )
|
||||
static int ParseExtern( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
|
||||
if (SpecType == SPEC_WIN16)
|
||||
if (spec->type == SPEC_WIN16)
|
||||
{
|
||||
error( "'extern' not supported for Win16, use 'variable' instead\n" );
|
||||
return 0;
|
||||
|
@ -437,13 +448,12 @@ static void fix_export_name( char *name )
|
|||
*
|
||||
* Parse an ordinal definition.
|
||||
*/
|
||||
static int ParseOrdinal(int ordinal)
|
||||
static int ParseOrdinal( int ordinal, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
|
||||
ORDDEF *odp = xmalloc( sizeof(*odp) );
|
||||
ORDDEF *odp = add_entry_point( spec );
|
||||
memset( odp, 0, sizeof(*odp) );
|
||||
EntryPoints[nb_entry_points++] = odp;
|
||||
|
||||
if (!(token = GetToken(0))) goto error;
|
||||
|
||||
|
@ -468,22 +478,22 @@ static int ParseOrdinal(int ordinal)
|
|||
switch(odp->type)
|
||||
{
|
||||
case TYPE_VARIABLE:
|
||||
if (!ParseVariable( odp )) goto error;
|
||||
if (!ParseVariable( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_PASCAL:
|
||||
case TYPE_STDCALL:
|
||||
case TYPE_VARARGS:
|
||||
case TYPE_CDECL:
|
||||
if (!ParseExportFunction( odp )) goto error;
|
||||
if (!ParseExportFunction( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_ABS:
|
||||
if (!ParseEquate( odp )) goto error;
|
||||
if (!ParseEquate( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
if (!ParseStub( odp )) goto error;
|
||||
if (!ParseStub( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_EXTERN:
|
||||
if (!ParseExtern( odp )) goto error;
|
||||
if (!ParseExtern( odp, spec )) goto error;
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
|
@ -493,8 +503,7 @@ static int ParseOrdinal(int ordinal)
|
|||
if (odp->flags & FLAG_I386)
|
||||
{
|
||||
/* ignore this entry point on non-Intel archs */
|
||||
EntryPoints[--nb_entry_points] = NULL;
|
||||
free( odp );
|
||||
spec->nb_entry_points--;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
@ -511,15 +520,9 @@ static int ParseOrdinal(int ordinal)
|
|||
error( "Ordinal number %d too large\n", ordinal );
|
||||
goto error;
|
||||
}
|
||||
if (ordinal > Limit) Limit = ordinal;
|
||||
if (ordinal < Base) Base = ordinal;
|
||||
if (ordinal > spec->limit) spec->limit = ordinal;
|
||||
if (ordinal < spec->base) spec->base = ordinal;
|
||||
odp->ordinal = ordinal;
|
||||
if (Ordinals[ordinal])
|
||||
{
|
||||
error( "Duplicate ordinal %d\n", ordinal );
|
||||
goto error;
|
||||
}
|
||||
Ordinals[ordinal] = odp;
|
||||
}
|
||||
|
||||
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" );
|
||||
goto error;
|
||||
}
|
||||
if (SpecType != SPEC_WIN32)
|
||||
if (spec->type != SPEC_WIN32)
|
||||
{
|
||||
error( "Nameless functions not supported for Win16\n" );
|
||||
goto error;
|
||||
|
@ -538,13 +541,11 @@ static int ParseOrdinal(int ordinal)
|
|||
else odp->export_name = odp->name;
|
||||
odp->name = NULL;
|
||||
}
|
||||
else Names[nb_names++] = odp;
|
||||
return 1;
|
||||
|
||||
error:
|
||||
EntryPoints[--nb_entry_points] = NULL;
|
||||
spec->nb_entry_points--;
|
||||
free( odp->name );
|
||||
free( odp );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
qsort( Names, nb_names, sizeof(Names[0]), name_compare );
|
||||
qsort( spec->names, spec->nb_names, sizeof(spec->names[0]), name_compare );
|
||||
|
||||
/* check for duplicate names */
|
||||
for (i = 0; i < nb_names - 1; i++)
|
||||
for (i = 0; i < spec->nb_names - 1; i++)
|
||||
{
|
||||
if (!strcmp( Names[i]->name, Names[i+1]->name ))
|
||||
if (!strcmp( spec->names[i]->name, spec->names[i+1]->name ))
|
||||
{
|
||||
current_line = max( Names[i]->lineno, Names[i+1]->lineno );
|
||||
current_line = max( spec->names[i]->lineno, spec->names[i+1]->lineno );
|
||||
error( "'%s' redefined\n%s:%d: First defined here\n",
|
||||
Names[i]->name, input_file_name,
|
||||
min( Names[i]->lineno, Names[i+1]->lineno ) );
|
||||
spec->names[i]->name, input_file_name,
|
||||
min( spec->names[i]->lineno, spec->names[i+1]->lineno ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* assign_ordinals
|
||||
*
|
||||
* Build the ordinal array.
|
||||
*/
|
||||
static void assign_ordinals( DLLSPEC *spec )
|
||||
{
|
||||
int i, count, ordinal;
|
||||
|
||||
/* start assigning from base, or from 1 if no ordinal defined yet */
|
||||
if (spec->base == MAX_ORDINALS) spec->base = 1;
|
||||
if (spec->limit < spec->base) spec->limit = spec->base;
|
||||
|
||||
count = max( spec->limit + 1, spec->base + spec->nb_entry_points );
|
||||
spec->ordinals = xmalloc( count * sizeof(spec->ordinals[0]) );
|
||||
memset( spec->ordinals, 0, count * sizeof(spec->ordinals[0]) );
|
||||
|
||||
/* fill in all explicitly specified ordinals */
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ordinal = spec->entry_points[i].ordinal;
|
||||
if (ordinal == -1) continue;
|
||||
if (spec->ordinals[ordinal])
|
||||
{
|
||||
current_line = max( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno );
|
||||
error( "ordinal %d redefined\n%s:%d: First defined here\n",
|
||||
ordinal, input_file_name,
|
||||
min( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ) );
|
||||
}
|
||||
else spec->ordinals[ordinal] = &spec->entry_points[i];
|
||||
}
|
||||
|
||||
/* now assign ordinals to the rest */
|
||||
for (i = 0, ordinal = spec->base; i < spec->nb_names; i++)
|
||||
{
|
||||
if (spec->names[i]->ordinal != -1) continue; /* already has an ordinal */
|
||||
while (spec->ordinals[ordinal]) ordinal++;
|
||||
if (ordinal >= MAX_ORDINALS)
|
||||
{
|
||||
current_line = spec->names[i]->lineno;
|
||||
fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
|
||||
}
|
||||
spec->names[i]->ordinal = ordinal;
|
||||
spec->ordinals[ordinal] = spec->names[i];
|
||||
}
|
||||
if (ordinal > spec->limit) spec->limit = ordinal;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseTopLevel
|
||||
*
|
||||
* Parse a spec file.
|
||||
*/
|
||||
int ParseTopLevel( FILE *file )
|
||||
int ParseTopLevel( FILE *file, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
|
||||
|
@ -601,16 +657,16 @@ int ParseTopLevel( FILE *file )
|
|||
if (!(token = GetToken(1))) continue;
|
||||
if (strcmp(token, "@") == 0)
|
||||
{
|
||||
if (SpecType != SPEC_WIN32)
|
||||
if (spec->type != SPEC_WIN32)
|
||||
{
|
||||
error( "'@' ordinals not supported for Win16\n" );
|
||||
continue;
|
||||
}
|
||||
if (!ParseOrdinal( -1 )) continue;
|
||||
if (!ParseOrdinal( -1, spec )) continue;
|
||||
}
|
||||
else if (IsNumberString(token))
|
||||
{
|
||||
if (!ParseOrdinal( atoi(token) )) continue;
|
||||
if (!ParseOrdinal( atoi(token), spec )) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -621,7 +677,8 @@ int ParseTopLevel( FILE *file )
|
|||
}
|
||||
|
||||
current_line = 0; /* no longer parsing the input file */
|
||||
sort_names();
|
||||
assign_names( spec );
|
||||
assign_ordinals( spec );
|
||||
return !nb_errors;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
for (i = 0; i < nb_resources; i++)
|
||||
tree = xmalloc( sizeof(*tree) );
|
||||
tree->types = NULL;
|
||||
tree->nb_types = 0;
|
||||
|
||||
for (i = 0; i < spec->nb_resources; i++)
|
||||
{
|
||||
if (!i || cmp_string( &resources[i].type, &resources[i-1].type )) /* new type */
|
||||
type = add_type( &resources[i] );
|
||||
if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type )) /* new type */
|
||||
type = add_type( tree, &spec->resources[i] );
|
||||
type->nb_names++;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
/* free the resource tree */
|
||||
static void free_resource_tree( struct res_tree *tree )
|
||||
{
|
||||
free( tree->types );
|
||||
free( tree );
|
||||
}
|
||||
|
||||
inline static void put_byte( unsigned char **buffer, unsigned char val )
|
||||
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
static const char *make_internal_name( const ORDDEF *odp, const char *prefix )
|
||||
static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const char *prefix )
|
||||
{
|
||||
static char buffer[256];
|
||||
if (odp->name || odp->export_name)
|
||||
{
|
||||
char *p;
|
||||
sprintf( buffer, "__wine_%s_%s_%s", prefix, dll_file_name,
|
||||
sprintf( buffer, "__wine_%s_%s_%s", prefix, spec->file_name,
|
||||
odp->name ? odp->name : odp->export_name );
|
||||
/* make sure name is a legal C identifier */
|
||||
for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
|
||||
if (!*p) return buffer;
|
||||
}
|
||||
sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(dll_file_name), odp->ordinal );
|
||||
sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(spec->file_name), odp->ordinal );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* AssignOrdinals
|
||||
*
|
||||
* 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
|
||||
*
|
||||
|
@ -134,7 +105,7 @@ static int output_debug( FILE *outfile )
|
|||
*
|
||||
* Output the export table for a Win32 module.
|
||||
*/
|
||||
static int output_exports( FILE *outfile, int nr_exports )
|
||||
static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
|
||||
{
|
||||
int i, fwd_size = 0, total_size = 0;
|
||||
|
||||
|
@ -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" ); /* MajorVersion/MinorVersion */
|
||||
fprintf( outfile, " \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
|
||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", Base ); /* Base */
|
||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */
|
||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", nb_names ); /* NumberOfNames */
|
||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->base ); /* Base */
|
||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", nr_exports ); /* NumberOfFunctions */
|
||||
fprintf( outfile, " \"\\t.long %d\\n\"\n", spec->nb_names ); /* NumberOfNames */
|
||||
fprintf( outfile, " \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */
|
||||
if (nb_names)
|
||||
if (spec->nb_names)
|
||||
{
|
||||
fprintf( outfile, " \"\\t.long __wine_spec_exp_name_ptrs\\n\"\n" ); /* AddressOfNames */
|
||||
fprintf( outfile, " \"\\t.long __wine_spec_exp_ordinals\\n\"\n" ); /* AddressOfNameOrdinals */
|
||||
|
@ -169,9 +140,9 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
/* output the function pointers */
|
||||
|
||||
fprintf( outfile, " \"__wine_spec_exports_funcs:\\n\"\n" );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp) fprintf( outfile, " \"\\t.long 0\\n\"\n" );
|
||||
else switch(odp->type)
|
||||
{
|
||||
|
@ -182,7 +153,8 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
if (!(odp->flags & FLAG_FORWARD))
|
||||
{
|
||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
|
||||
(odp->flags & FLAG_REGISTER) ? make_internal_name(odp,"regs") : odp->link_name );
|
||||
(odp->flags & FLAG_REGISTER) ? make_internal_name( odp, spec, "regs" )
|
||||
: odp->link_name );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -191,49 +163,51 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
}
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n", make_internal_name( odp, "stub" ) );
|
||||
fprintf( outfile, " \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
|
||||
make_internal_name( odp, spec, "stub" ) );
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
total_size += (Limit - Base + 1) * sizeof(int);
|
||||
total_size += (spec->limit - spec->base + 1) * sizeof(int);
|
||||
|
||||
if (nb_names)
|
||||
if (spec->nb_names)
|
||||
{
|
||||
/* output the function name pointers */
|
||||
|
||||
int namepos = strlen(dll_file_name) + 1;
|
||||
int namepos = strlen(spec->file_name) + 1;
|
||||
|
||||
fprintf( outfile, " \"__wine_spec_exp_name_ptrs:\\n\"\n" );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
{
|
||||
fprintf( outfile, " \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
|
||||
namepos += strlen(Names[i]->name) + 1;
|
||||
namepos += strlen(spec->names[i]->name) + 1;
|
||||
}
|
||||
total_size += nb_names * sizeof(int);
|
||||
total_size += spec->nb_names * sizeof(int);
|
||||
}
|
||||
|
||||
/* output the function names */
|
||||
|
||||
fprintf( outfile, " \"\\t.text\\n\"\n" );
|
||||
fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" );
|
||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", dll_file_name );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", Names[i]->name );
|
||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
|
||||
fprintf( outfile, " \"\\t.data\\n\"\n" );
|
||||
|
||||
if (nb_names)
|
||||
if (spec->nb_names)
|
||||
{
|
||||
/* output the function ordinals */
|
||||
|
||||
fprintf( outfile, " \"__wine_spec_exp_ordinals:\\n\"\n" );
|
||||
for (i = 0; i < nb_names; i++)
|
||||
for (i = 0; i < spec->nb_names; i++)
|
||||
{
|
||||
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n", Names[i]->ordinal - Base );
|
||||
fprintf( outfile, " \"\\t" __ASM_SHORT " %d\\n\"\n",
|
||||
spec->names[i]->ordinal - spec->base );
|
||||
}
|
||||
total_size += nb_names * sizeof(short);
|
||||
if (nb_names % 2)
|
||||
total_size += spec->nb_names * sizeof(short);
|
||||
if (spec->nb_names % 2)
|
||||
{
|
||||
fprintf( outfile, " \"\\t" __ASM_SHORT " 0\\n\"\n" );
|
||||
total_size += sizeof(short);
|
||||
|
@ -245,9 +219,9 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
if (fwd_size)
|
||||
{
|
||||
fprintf( outfile, " \"__wine_spec_forwards:\\n\"\n" );
|
||||
for (i = Base; i <= Limit; i++)
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (odp && (odp->flags & FLAG_FORWARD))
|
||||
fprintf( outfile, " \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
|
||||
}
|
||||
|
@ -259,9 +233,9 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
|
||||
if (debugging)
|
||||
{
|
||||
for (i = Base; i <= Limit; i++)
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = Ordinals[i];
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
unsigned int j, args, mask = 0;
|
||||
const char *name;
|
||||
|
||||
|
@ -281,7 +255,7 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
|
||||
name = odp->link_name;
|
||||
args = strlen(odp->u.func.arg_types) * sizeof(int);
|
||||
if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, "regs" );
|
||||
if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, spec, "regs" );
|
||||
|
||||
switch(odp->type)
|
||||
{
|
||||
|
@ -319,13 +293,13 @@ static int output_exports( FILE *outfile, int nr_exports )
|
|||
*
|
||||
* Output the functions for stub entry points
|
||||
*/
|
||||
static void output_stub_funcs( FILE *outfile )
|
||||
static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nb_entry_points; i++)
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = EntryPoints[i];
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "#ifdef __GNUC__\n" );
|
||||
fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
|
||||
|
@ -343,7 +317,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" );
|
||||
|
@ -354,11 +328,11 @@ static void output_stub_funcs( FILE *outfile )
|
|||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < nb_entry_points; i++)
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = EntryPoints[i];
|
||||
const ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STUB) continue;
|
||||
fprintf( outfile, "void %s(void) ", make_internal_name( odp, "stub" ) );
|
||||
fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
|
||||
if (odp->name)
|
||||
fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
|
||||
else if (odp->export_name)
|
||||
|
@ -374,18 +348,18 @@ static void output_stub_funcs( FILE *outfile )
|
|||
*
|
||||
* Output the functions for register entry points
|
||||
*/
|
||||
static void output_register_funcs( FILE *outfile )
|
||||
static void output_register_funcs( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
const char *name;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nb_entry_points; i++)
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = EntryPoints[i];
|
||||
const ORDDEF *odp = &spec->entry_points[i];
|
||||
if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
|
||||
if (!(odp->flags & FLAG_REGISTER)) continue;
|
||||
if (odp->flags & FLAG_FORWARD) continue;
|
||||
name = make_internal_name( odp, "regs" );
|
||||
name = make_internal_name( odp, spec, "regs" );
|
||||
fprintf( outfile,
|
||||
"asm(\".align %d\\n\\t\"\n"
|
||||
" \"" __ASM_FUNC("%s") "\\n\\t\"\n"
|
||||
|
@ -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.
|
||||
*/
|
||||
void BuildSpec32File( FILE *outfile )
|
||||
void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
int exports_size = 0;
|
||||
int nr_exports, nr_imports, nr_resources;
|
||||
int nr_exports, nr_imports;
|
||||
int characteristics, subsystem;
|
||||
DWORD page_size;
|
||||
const char *init_func = spec->init_func;
|
||||
|
||||
#ifdef HAVE_GETPAGESIZE
|
||||
page_size = getpagesize();
|
||||
|
@ -506,10 +481,8 @@ void BuildSpec32File( FILE *outfile )
|
|||
# error Cannot get the page size on this platform
|
||||
#endif
|
||||
|
||||
AssignOrdinals();
|
||||
nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
|
||||
|
||||
resolve_imports();
|
||||
nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
|
||||
resolve_imports( spec );
|
||||
output_standard_file_header( outfile );
|
||||
|
||||
/* Reserve some space for the PE header */
|
||||
|
@ -541,7 +514,7 @@ void BuildSpec32File( FILE *outfile )
|
|||
{
|
||||
/* Output the stub functions */
|
||||
|
||||
output_stub_funcs( outfile );
|
||||
output_stub_funcs( outfile, spec );
|
||||
|
||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||
fprintf( outfile, "static void __asm__dummy(void) {\n" );
|
||||
|
@ -549,11 +522,11 @@ void BuildSpec32File( FILE *outfile )
|
|||
|
||||
/* Output code for all register functions */
|
||||
|
||||
output_register_funcs( outfile );
|
||||
output_register_funcs( outfile, spec );
|
||||
|
||||
/* Output the exports and relay entry points */
|
||||
|
||||
exports_size = output_exports( outfile, nr_exports );
|
||||
exports_size = output_exports( outfile, nr_exports, spec );
|
||||
|
||||
fprintf( outfile, "#ifndef __GNUC__\n" );
|
||||
fprintf( outfile, "}\n" );
|
||||
|
@ -562,11 +535,11 @@ void BuildSpec32File( FILE *outfile )
|
|||
|
||||
/* Output the DLL imports */
|
||||
|
||||
nr_imports = output_imports( outfile );
|
||||
nr_imports = output_imports( outfile, spec );
|
||||
|
||||
/* Output the resources */
|
||||
|
||||
nr_resources = output_resources( outfile );
|
||||
output_resources( outfile, spec );
|
||||
|
||||
/* Output the entry point function */
|
||||
|
||||
|
@ -579,7 +552,7 @@ void BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, "extern void _fini();\n" );
|
||||
|
||||
characteristics = subsystem = 0;
|
||||
switch(SpecMode)
|
||||
switch(spec->mode)
|
||||
{
|
||||
case SPEC_MODE_DLL:
|
||||
if (init_func)
|
||||
|
@ -772,9 +745,9 @@ void BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, " 0x%04x,\n", subsystem ); /* Subsystem */
|
||||
fprintf( outfile, " 0,\n" ); /* DllCharacteristics */
|
||||
fprintf( outfile, " %d, %ld,\n", /* SizeOfStackReserve/Commit */
|
||||
(stack_size ? stack_size : 1024) * 1024, page_size );
|
||||
(spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
|
||||
fprintf( outfile, " %d, %ld,\n", /* SizeOfHeapReserve/Commit */
|
||||
(DLLHeapSize ? DLLHeapSize : 1024) * 1024, page_size );
|
||||
(spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
|
||||
fprintf( outfile, " 0,\n" ); /* LoaderFlags */
|
||||
fprintf( outfile, " %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES ); /* NumberOfRvaAndSizes */
|
||||
fprintf( outfile, " {\n" );
|
||||
|
@ -783,7 +756,8 @@ void BuildSpec32File( FILE *outfile )
|
|||
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_IMPORT */
|
||||
nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
|
||||
fprintf( outfile, " { %s, %s },\n", /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
|
||||
nr_resources ? "&resources" : "0", nr_resources ? "sizeof(resources)" : "0" );
|
||||
spec->nb_resources ? "&resources" : "0",
|
||||
spec->nb_resources ? "sizeof(resources)" : "0" );
|
||||
fprintf( outfile, " }\n }\n};\n\n" );
|
||||
|
||||
/* Output the DLL constructor */
|
||||
|
@ -795,7 +769,7 @@ void BuildSpec32File( FILE *outfile )
|
|||
" __wine_spec_init_state = 1;\n"
|
||||
" __wine_dll_register( &nt_header, \"%s\" );\n"
|
||||
"}\n\n",
|
||||
dll_file_name );
|
||||
spec->file_name );
|
||||
|
||||
output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
|
||||
fprintf( outfile,
|
||||
|
@ -813,25 +787,23 @@ void BuildSpec32File( FILE *outfile )
|
|||
*
|
||||
* Build a Win32 def file from a spec file.
|
||||
*/
|
||||
void BuildDef32File(FILE *outfile)
|
||||
void BuildDef32File( FILE *outfile, DLLSPEC *spec )
|
||||
{
|
||||
const char *name;
|
||||
int i;
|
||||
|
||||
AssignOrdinals();
|
||||
|
||||
fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n",
|
||||
input_file_name );
|
||||
|
||||
fprintf(outfile, "LIBRARY %s\n\n", dll_file_name);
|
||||
fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
|
||||
|
||||
fprintf(outfile, "EXPORTS\n");
|
||||
|
||||
/* Output the exports and relay entry points */
|
||||
|
||||
for(i = 0; i < nb_entry_points; i++)
|
||||
for(i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = EntryPoints[i];
|
||||
const ORDDEF *odp = &spec->entry_points[i];
|
||||
int is_data = 0;
|
||||
|
||||
if (!odp) continue;
|
||||
|
|
Loading…
Reference in New Issue