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

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

View file

@ -94,6 +94,28 @@ typedef struct
} u;
} 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 */

View file

@ -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 );
}

View file

@ -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 );

View file

@ -134,12 +134,23 @@ static const char * GetToken( int allow_eol )
}
static ORDDEF *add_entry_point( DLLSPEC *spec )
{
if (spec->nb_entry_points == spec->alloc_entry_points)
{
spec->alloc_entry_points += 128;
spec->entry_points = xrealloc( spec->entry_points,
spec->alloc_entry_points * sizeof(*spec->entry_points) );
}
return &spec->entry_points[spec->nb_entry_points++];
}
/*******************************************************************
* ParseVariable
*
* 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;
}

View file

@ -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;
}

View file

@ -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 );
}

View file

@ -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,

View file

@ -55,51 +55,22 @@ static int string_compare( const void *ptr1, const void *ptr2 )
*
* Generate an internal name for an entry point. Used for stubs etc.
*/
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;