Added support for building a dll from a .def file for cases where we
don't want to write a full .spec. Renamed --spec option to --dll for consistency.
This commit is contained in:
parent
14743a0f3b
commit
492ac292b9
|
@ -129,7 +129,7 @@ LINTS = $(C_SRCS:.c=.ln)
|
|||
$(WINDRES) -i $< -o $@
|
||||
|
||||
.spec.spec.c:
|
||||
$(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --spec $<
|
||||
$(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $<
|
||||
|
||||
.spec.spec.def:
|
||||
$(WINEBUILD) $(DEFS) -o $@ --def $<
|
||||
|
|
|
@ -27,7 +27,7 @@ all: $(MODULE)$(DLLEXT) $(SUBDIRS)
|
|||
# Rules for .so files
|
||||
|
||||
$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD)
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --spec $(SRCDIR)/$(MAINSPEC) $(DLLMODE:%=--mode %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%)
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll $(SRCDIR)/$(MAINSPEC) $(DLLMODE:%=--mode %) $(RC_SRCS:.rc=.res) $(ALL_OBJS) -L$(DLLDIR) $(DELAYIMPORTS:%=-d%) $(IMPORTS:%=-l%)
|
||||
|
||||
$(MODULE).so: $(MAINSPEC).o $(ALL_OBJS) Makefile.in
|
||||
$(LDDLL) $(MAINSPEC).o $(ALL_OBJS) -o $@ -L$(DLLDIR) $(ALL_LIBS) -lc
|
||||
|
|
|
@ -76,7 +76,7 @@ EXTRASUBDIRS = \
|
|||
# Special rules for 16-bit resource and spec files
|
||||
|
||||
gdi.exe.spec.c: gdi.exe.spec version16.res
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --spec $(SRCDIR)/gdi.exe.spec
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/gdi.exe.spec
|
||||
|
||||
version16.res: version16.rc
|
||||
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
|
||||
|
|
|
@ -113,7 +113,7 @@ relay16asm.s: $(WINEBUILD)
|
|||
# Special rules for 16-bit resource and spec files
|
||||
|
||||
krnl386.exe.spec.c: krnl386.exe.spec version16.res
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --spec $(SRCDIR)/krnl386.exe.spec
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --dll-name kernel --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/krnl386.exe.spec
|
||||
|
||||
version16.res: version16.rc
|
||||
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
|
||||
|
|
|
@ -72,10 +72,10 @@ version16.res: version16.rc
|
|||
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
|
||||
|
||||
shell.spec.c: shell.spec version16.res
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --spec $(SRCDIR)/shell.spec
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res version16.res --dll $(SRCDIR)/shell.spec
|
||||
|
||||
authors.c: $(TOPSRCDIR)/AUTHORS
|
||||
(LANG=C; echo 'const char * const SHELL_Authors[] = {' && \
|
||||
(LC_ALL=C; echo 'const char * const SHELL_Authors[] = {' && \
|
||||
sed -e '1,2d' -e 's/\(.*\)/ \"\1\",/' $(TOPSRCDIR)/AUTHORS && \
|
||||
echo ' 0 };') >$@ || ($(RM) $@ && false)
|
||||
|
||||
|
|
|
@ -168,13 +168,13 @@ EXTRASUBDIRS = \
|
|||
# Special rules for 16-bit resource and spec files
|
||||
|
||||
user.exe.spec.c: user.exe.spec resources/version16.res
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res resources/version16.res --spec $(SRCDIR)/user.exe.spec
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --heap 65520 --main-module $(MODULE) --res resources/version16.res --dll $(SRCDIR)/user.exe.spec
|
||||
|
||||
display.drv.spec.c: display.drv.spec resources/display.res
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/display.res --spec $(SRCDIR)/display.drv.spec
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/display.res --dll $(SRCDIR)/display.drv.spec
|
||||
|
||||
mouse.drv.spec.c: mouse.drv.spec resources/mouse.res
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/mouse.res --spec $(SRCDIR)/mouse.drv.spec
|
||||
$(WINEBUILD) $(DEFS) $(DLLFLAGS) -o $@ --main-module $(MODULE) --res resources/mouse.res --dll $(SRCDIR)/mouse.drv.spec
|
||||
|
||||
resources/display.res: resources/display.rc
|
||||
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/resources/display.rc
|
||||
|
|
|
@ -68,7 +68,6 @@ typedef struct
|
|||
|
||||
typedef struct
|
||||
{
|
||||
int n_args;
|
||||
char arg_types[21];
|
||||
} ORD_FUNCTION;
|
||||
|
||||
|
@ -170,6 +169,9 @@ extern FILE *open_input_file( const char *srcdir, const char *name );
|
|||
extern void close_input_file( FILE *file );
|
||||
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
|
||||
const char *label, int constant );
|
||||
extern int remove_stdcall_decoration( char *name );
|
||||
extern DLLSPEC *alloc_dll_spec(void);
|
||||
extern void free_dll_spec( DLLSPEC *spec );
|
||||
extern const char *make_c_identifier( const char *str );
|
||||
extern int get_alignment(int alignBoundary);
|
||||
|
||||
|
@ -184,7 +186,6 @@ 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 );
|
||||
|
@ -192,7 +193,10 @@ 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, DLLSPEC *spec );
|
||||
|
||||
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
|
||||
extern int parse_def_file( FILE *file, DLLSPEC *spec );
|
||||
extern int parse_debug_channels( const char *srcdir, const char *filename );
|
||||
|
||||
/* global variables */
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*
|
||||
* DLL imports support
|
||||
*
|
||||
* Copyright 2000 Alexandre Julliard
|
||||
* 2000 Eric Pouech
|
||||
* Copyright 2000, 2004 Alexandre Julliard
|
||||
* Copyright 2000 Eric Pouech
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -32,20 +32,13 @@
|
|||
|
||||
#include "build.h"
|
||||
|
||||
struct func
|
||||
{
|
||||
char *name; /* function name */
|
||||
int ordinal; /* function ordinal */
|
||||
int ord_only; /* non-zero if function is imported by ordinal */
|
||||
};
|
||||
|
||||
struct import
|
||||
{
|
||||
char *dll; /* dll name */
|
||||
DLLSPEC *spec; /* description of the imported dll */
|
||||
int delay; /* delay or not dll loading ? */
|
||||
struct func *exports; /* functions exported from this dll */
|
||||
ORDDEF **exports; /* functions exported from this dll */
|
||||
int nb_exports; /* number of exported functions */
|
||||
struct func *imports; /* functions we want to import from this dll */
|
||||
ORDDEF **imports; /* functions we want to import from this dll */
|
||||
int nb_imports; /* number of imported functions */
|
||||
};
|
||||
|
||||
|
@ -143,7 +136,10 @@ static int name_cmp( const void *name, const void *entry )
|
|||
/* compare function names; helper for resolve_imports */
|
||||
static int func_cmp( const void *func1, const void *func2 )
|
||||
{
|
||||
return strcmp( ((struct func *)func1)->name, ((struct func *)func2)->name );
|
||||
const ORDDEF *odp1 = *(const ORDDEF **)func1;
|
||||
const ORDDEF *odp2 = *(const ORDDEF **)func2;
|
||||
return strcmp( odp1->name ? odp1->name : odp1->export_name,
|
||||
odp2->name ? odp2->name : odp2->export_name );
|
||||
}
|
||||
|
||||
/* locate a symbol in a (sorted) list */
|
||||
|
@ -159,14 +155,15 @@ inline static const char *find_symbol( const char *name, char **table, int size
|
|||
}
|
||||
|
||||
/* locate an export in a (sorted) export list */
|
||||
inline static struct func *find_export( const char *name, struct func *table, int size )
|
||||
inline static ORDDEF *find_export( const char *name, ORDDEF **table, int size )
|
||||
{
|
||||
struct func func, *res = NULL;
|
||||
ORDDEF func, *odp, **res = NULL;
|
||||
|
||||
func.name = (char *)name;
|
||||
func.ordinal = -1;
|
||||
if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp );
|
||||
return res;
|
||||
odp = &func;
|
||||
if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
|
||||
return res ? *res : NULL;
|
||||
}
|
||||
|
||||
/* sort a symbol table */
|
||||
|
@ -179,13 +176,9 @@ inline static void sort_symbols( char **table, int size )
|
|||
/* free an import structure */
|
||||
static void free_imports( struct import *imp )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < imp->nb_exports; i++) free( imp->exports[i].name );
|
||||
for (i = 0; i < imp->nb_imports; i++) free( imp->imports[i].name );
|
||||
free( imp->exports );
|
||||
free( imp->imports );
|
||||
free( imp->dll );
|
||||
free_dll_spec( imp->spec );
|
||||
free( imp );
|
||||
}
|
||||
|
||||
|
@ -202,7 +195,7 @@ static int is_already_imported( const char *name )
|
|||
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!strcmp( dll_imports[i]->dll, name )) return 1;
|
||||
if (!strcmp( dll_imports[i]->spec->file_name, name )) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -241,152 +234,40 @@ static char *open_library( const char *name )
|
|||
return fullname;
|
||||
}
|
||||
|
||||
/* skip whitespace until the next token */
|
||||
static char *skip_whitespace( char *p )
|
||||
{
|
||||
while (*p && isspace(*p)) p++;
|
||||
if (!*p || *p == ';') p = NULL;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* skip to the start of the next token, null terminating the current one */
|
||||
static char *next_token( char *p )
|
||||
{
|
||||
while (*p && !isspace(*p)) p++;
|
||||
if (*p) *p++ = 0;
|
||||
return skip_whitespace( p );
|
||||
}
|
||||
|
||||
/* remove the @nn suffix from stdcall names */
|
||||
static char *remove_stdcall_decoration( char *buffer )
|
||||
{
|
||||
char *p = buffer + strlen(buffer) - 1;
|
||||
while (p > buffer && isdigit(*p)) p--;
|
||||
if (p > buffer && *p == '@') *p = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* read in the list of exported symbols of an import library */
|
||||
static int read_import_lib( const char *name, struct import *imp )
|
||||
{
|
||||
FILE *f;
|
||||
char buffer[1024];
|
||||
char *fullname;
|
||||
int size;
|
||||
int i, ret;
|
||||
DLLSPEC *spec = imp->spec;
|
||||
|
||||
imp->exports = NULL;
|
||||
imp->nb_exports = size = 0;
|
||||
imp->nb_exports = 0;
|
||||
|
||||
fullname = open_library( name );
|
||||
f = open_input_file( NULL, fullname );
|
||||
free( fullname );
|
||||
|
||||
while (fgets( buffer, sizeof(buffer), f ))
|
||||
{
|
||||
char *name, *flags;
|
||||
int ordinal = 0, ord_only = 0;
|
||||
|
||||
char *p = buffer + strlen(buffer) - 1;
|
||||
if (p < buffer) goto next;
|
||||
if (*p == '\n') *p-- = 0;
|
||||
|
||||
p = buffer;
|
||||
if (!(p = skip_whitespace(p))) goto next;
|
||||
name = p;
|
||||
p = next_token( name );
|
||||
|
||||
if (!strcmp( name, "LIBRARY" ))
|
||||
{
|
||||
if (!p)
|
||||
{
|
||||
error( "Expected name after LIBRARY\n" );
|
||||
goto next;
|
||||
}
|
||||
name = p;
|
||||
p = next_token( name );
|
||||
if (p)
|
||||
{
|
||||
error( "Garbage after LIBRARY statement\n" );
|
||||
goto next;
|
||||
}
|
||||
if (is_already_imported( name ))
|
||||
{
|
||||
close_input_file( f );
|
||||
return 0; /* ignore this dll */
|
||||
}
|
||||
free( imp->dll );
|
||||
imp->dll = xstrdup( name );
|
||||
goto next;
|
||||
}
|
||||
if (!strcmp( name, "EXPORTS" )) goto next;
|
||||
|
||||
/* check for ordinal */
|
||||
if (!p)
|
||||
{
|
||||
error( "Expected ordinal after function name\n" );
|
||||
goto next;
|
||||
}
|
||||
if (*p != '@' || !isdigit(p[1]))
|
||||
{
|
||||
error( "Expected ordinal after function name '%s'\n", name );
|
||||
goto next;
|
||||
}
|
||||
ordinal = strtol( p+1, &p, 10 );
|
||||
if (ordinal >= MAX_ORDINALS)
|
||||
{
|
||||
error( "Invalid ordinal number %d\n", ordinal );
|
||||
goto next;
|
||||
}
|
||||
|
||||
/* check for optional flags */
|
||||
while (p && (p = skip_whitespace(p)))
|
||||
{
|
||||
flags = p;
|
||||
p = next_token( flags );
|
||||
if (!strcmp( flags, "NONAME" ))
|
||||
{
|
||||
ord_only = 1;
|
||||
if (!ordinal)
|
||||
{
|
||||
error( "Invalid ordinal number %d\n", ordinal );
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
else if (!strcmp( flags, "CONSTANT" ) || !strcmp( flags, "DATA" ))
|
||||
{
|
||||
/* we don't support importing non-function entry points */
|
||||
goto next;
|
||||
}
|
||||
else if (!strcmp( flags, "PRIVATE" ))
|
||||
{
|
||||
/* function must not be imported */
|
||||
goto next;
|
||||
}
|
||||
else
|
||||
{
|
||||
error( "Garbage after ordinal declaration\n" );
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
if (imp->nb_exports == size)
|
||||
{
|
||||
size += 128;
|
||||
imp->exports = xrealloc( imp->exports, size * sizeof(*imp->exports) );
|
||||
}
|
||||
if ((p = strchr( name, '=' ))) *p = 0;
|
||||
remove_stdcall_decoration( name );
|
||||
imp->exports[imp->nb_exports].name = xstrdup( name );
|
||||
imp->exports[imp->nb_exports].ordinal = ordinal;
|
||||
imp->exports[imp->nb_exports].ord_only = ord_only;
|
||||
imp->nb_exports++;
|
||||
next:
|
||||
current_line++;
|
||||
}
|
||||
ret = parse_def_file( f, spec );
|
||||
close_input_file( f );
|
||||
if (!ret) return 0;
|
||||
if (is_already_imported( spec->file_name )) return 0;
|
||||
|
||||
imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
|
||||
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
|
||||
if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
|
||||
if (odp->flags & FLAG_PRIVATE) continue;
|
||||
imp->exports[imp->nb_exports++] = odp;
|
||||
}
|
||||
imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) );
|
||||
if (imp->nb_exports)
|
||||
qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
|
||||
return !nb_errors;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* add a dll to the list of imports */
|
||||
|
@ -407,11 +288,11 @@ void add_import_dll( const char *name, int delay )
|
|||
}
|
||||
|
||||
imp = xmalloc( sizeof(*imp) );
|
||||
imp->dll = fullname;
|
||||
imp->delay = delay;
|
||||
imp->imports = NULL;
|
||||
imp->nb_imports = 0;
|
||||
|
||||
imp->spec = alloc_dll_spec();
|
||||
imp->spec->file_name = fullname;
|
||||
imp->delay = delay;
|
||||
imp->imports = NULL;
|
||||
imp->nb_imports = 0;
|
||||
if (delay) nb_delayed++;
|
||||
|
||||
if (read_import_lib( name, imp ))
|
||||
|
@ -489,13 +370,10 @@ void add_ignore_symbol( const char *name )
|
|||
}
|
||||
|
||||
/* add a function to the list of imports from a given dll */
|
||||
static void add_import_func( struct import *imp, const struct func *func )
|
||||
static void add_import_func( struct import *imp, ORDDEF *func )
|
||||
{
|
||||
imp->imports = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
|
||||
imp->imports[imp->nb_imports].name = xstrdup( func->name );
|
||||
imp->imports[imp->nb_imports].ordinal = func->ordinal;
|
||||
imp->imports[imp->nb_imports].ord_only = func->ord_only;
|
||||
imp->nb_imports++;
|
||||
imp->imports[imp->nb_imports++] = func;
|
||||
total_imports++;
|
||||
if (imp->delay) total_delayed++;
|
||||
}
|
||||
|
@ -613,15 +491,16 @@ static void add_extra_undef_symbols( const DLLSPEC *spec )
|
|||
static int check_unused( const struct import* imp, const DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
size_t len = strlen(imp->dll);
|
||||
const char *p = strchr( imp->dll, '.' );
|
||||
if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
|
||||
const char *file_name = imp->spec->file_name;
|
||||
size_t len = strlen( file_name );
|
||||
const char *p = strchr( file_name, '.' );
|
||||
if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
|
||||
|
||||
for (i = spec->base; i <= spec->limit; i++)
|
||||
{
|
||||
ORDDEF *odp = spec->ordinals[i];
|
||||
if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
|
||||
if (!strncasecmp( odp->link_name, imp->dll, len ) &&
|
||||
if (!strncasecmp( odp->link_name, file_name, len ) &&
|
||||
odp->link_name[len] == '.')
|
||||
return 0; /* found a forward, it is used */
|
||||
}
|
||||
|
@ -724,10 +603,10 @@ int resolve_imports( DLLSPEC *spec )
|
|||
|
||||
for (j = 0; j < nb_undef_symbols; j++)
|
||||
{
|
||||
struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
|
||||
if (func)
|
||||
ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
|
||||
if (odp)
|
||||
{
|
||||
add_import_func( imp, func );
|
||||
add_import_func( imp, odp );
|
||||
free( undef_symbols[j] );
|
||||
undef_symbols[j] = NULL;
|
||||
}
|
||||
|
@ -736,7 +615,7 @@ int resolve_imports( DLLSPEC *spec )
|
|||
if (!remove_symbol_holes() && check_unused( imp, spec ))
|
||||
{
|
||||
/* the dll is not used, get rid of it */
|
||||
warning( "%s imported but no symbols used\n", imp->dll );
|
||||
warning( "%s imported but no symbols used\n", imp->spec->file_name );
|
||||
remove_import_dll( i );
|
||||
i--;
|
||||
}
|
||||
|
@ -772,7 +651,7 @@ static int output_immediate_imports( FILE *outfile )
|
|||
{
|
||||
if (dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
|
||||
dll_imports[i]->dll, j );
|
||||
dll_imports[i]->spec->file_name, j );
|
||||
j += dll_imports[i]->nb_imports + 1;
|
||||
}
|
||||
|
||||
|
@ -784,18 +663,18 @@ static int output_immediate_imports( FILE *outfile )
|
|||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
|
||||
fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++)
|
||||
{
|
||||
struct func *import = &dll_imports[i]->imports[j];
|
||||
if (!import->ord_only)
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!(odp->flags & FLAG_NONAME))
|
||||
{
|
||||
unsigned short ord = import->ordinal;
|
||||
unsigned short ord = odp->ordinal;
|
||||
fprintf( outfile, " \"\\%03o\\%03o%s\",\n",
|
||||
*(unsigned char *)&ord, *((unsigned char *)&ord + 1), import->name );
|
||||
*(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
|
||||
}
|
||||
else
|
||||
fprintf( outfile, " (char *)%d,\n", import->ordinal );
|
||||
fprintf( outfile, " (char *)%d,\n", odp->ordinal );
|
||||
}
|
||||
fprintf( outfile, " 0,\n" );
|
||||
}
|
||||
|
@ -811,13 +690,14 @@ static int output_immediate_imports( FILE *outfile )
|
|||
if (dll_imports[i]->delay) continue;
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
|
||||
{
|
||||
struct func *import = &dll_imports[i]->imports[j];
|
||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
|
||||
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
|
||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", import->name);
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
|
||||
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
|
||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", name);
|
||||
|
||||
#if defined(__i386__)
|
||||
if (strstr( import->name, "__wine_call_from_16" ))
|
||||
if (strstr( name, "__wine_call_from_16" ))
|
||||
fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
|
||||
else
|
||||
fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos );
|
||||
|
@ -886,8 +766,9 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++)
|
||||
{
|
||||
fprintf( outfile, "void __wine_delay_imp_%d_%s();\n",
|
||||
i, dll_imports[i]->imports[j].name );
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, "\n" );
|
||||
|
@ -910,31 +791,33 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, " { 0, \"%s\", &__wine_delay_imp_%d_hmod, &delay_imports.IAT[%d], &delay_imports.INT[%d], 0, 0, 0 },\n",
|
||||
dll_imports[i]->dll, i, j, j );
|
||||
dll_imports[i]->spec->file_name, i, j, j );
|
||||
j += dll_imports[i]->nb_imports;
|
||||
}
|
||||
fprintf( outfile, " },\n {\n" );
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
|
||||
fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++)
|
||||
{
|
||||
fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, dll_imports[i]->imports[j].name);
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
fprintf( outfile, " &__wine_delay_imp_%d_%s,\n", i, name );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, " },\n {\n" );
|
||||
for (i = 0; i < nb_imports; i++)
|
||||
{
|
||||
if (!dll_imports[i]->delay) continue;
|
||||
fprintf( outfile, " /* %s */\n", dll_imports[i]->dll );
|
||||
fprintf( outfile, " /* %s */\n", dll_imports[i]->spec->file_name );
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++)
|
||||
{
|
||||
struct func *import = &dll_imports[i]->imports[j];
|
||||
if (import->ord_only)
|
||||
fprintf( outfile, " (char *)%d,\n", import->ordinal );
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
if (!odp->name)
|
||||
fprintf( outfile, " (char *)%d,\n", odp->ordinal );
|
||||
else
|
||||
fprintf( outfile, " \"%s\",\n", import->name );
|
||||
fprintf( outfile, " \"%s\",\n", odp->name );
|
||||
}
|
||||
}
|
||||
fprintf( outfile, " }\n};\n\n" );
|
||||
|
@ -1059,7 +942,10 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
for (j = 0; j < dll_imports[i]->nb_imports; j++)
|
||||
{
|
||||
char buffer[128];
|
||||
sprintf( buffer, "__wine_delay_imp_%d_%s", i, dll_imports[i]->imports[j].name );
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
|
||||
sprintf( buffer, "__wine_delay_imp_%d_%s", i, name );
|
||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
|
||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
|
||||
#if defined(__i386__)
|
||||
|
@ -1088,12 +974,14 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
|
|||
if (!dll_imports[i]->delay) continue;
|
||||
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
|
||||
{
|
||||
struct func *import = &dll_imports[i]->imports[j];
|
||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name );
|
||||
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
|
||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", import->name);
|
||||
ORDDEF *odp = dll_imports[i]->imports[j];
|
||||
const char *name = odp->name ? odp->name : odp->export_name;
|
||||
|
||||
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
|
||||
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
|
||||
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", name );
|
||||
#if defined(__i386__)
|
||||
if (strstr( import->name, "__wine_call_from_16" ))
|
||||
if (strstr( name, "__wine_call_from_16" ))
|
||||
fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
|
||||
else
|
||||
fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
|
||||
|
|
|
@ -56,17 +56,17 @@ char **lib_path = NULL;
|
|||
char *input_file_name = NULL;
|
||||
const char *output_file_name = NULL;
|
||||
|
||||
static FILE *input_file;
|
||||
static FILE *output_file;
|
||||
static const char *current_src_dir;
|
||||
static int nb_res_files;
|
||||
static char **res_files;
|
||||
static char *spec_file_name;
|
||||
|
||||
/* execution mode */
|
||||
enum exec_mode_values
|
||||
{
|
||||
MODE_NONE,
|
||||
MODE_SPEC,
|
||||
MODE_DLL,
|
||||
MODE_EXE,
|
||||
MODE_DEF,
|
||||
MODE_DEBUG,
|
||||
|
@ -87,7 +87,10 @@ static void set_dll_file_name( const char *name, DLLSPEC *spec )
|
|||
if ((p = strrchr( name, '/' ))) name = p + 1;
|
||||
spec->file_name = xmalloc( strlen(name) + 5 );
|
||||
strcpy( spec->file_name, name );
|
||||
if ((p = strrchr( spec->file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0;
|
||||
if ((p = strrchr( spec->file_name, '.' )))
|
||||
{
|
||||
if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0;
|
||||
}
|
||||
if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
|
||||
}
|
||||
|
||||
|
@ -126,7 +129,7 @@ static const char usage_str[] =
|
|||
" --version Print the version and exit\n"
|
||||
" -w --warnings Turn on warnings\n"
|
||||
"\nMode options:\n"
|
||||
" --spec=FILE.SPEC Build a .c file from a spec file\n"
|
||||
" --dll=FILE Build a .c file from a .spec or .def file\n"
|
||||
" --def=FILE.SPEC Build a .def file from a spec file\n"
|
||||
" --exe=NAME Build a .c file for the named executable\n"
|
||||
" --debug [FILES] Build a .c file with the debug channels declarations\n"
|
||||
|
@ -136,7 +139,7 @@ static const char usage_str[] =
|
|||
|
||||
enum long_options_values
|
||||
{
|
||||
LONG_OPT_SPEC = 1,
|
||||
LONG_OPT_DLL = 1,
|
||||
LONG_OPT_DEF,
|
||||
LONG_OPT_EXE,
|
||||
LONG_OPT_DEBUG,
|
||||
|
@ -149,13 +152,14 @@ static const char short_options[] = "C:D:F:H:I:K:L:M:N:d:e:f:hi:kl:m:o:r:w";
|
|||
|
||||
static const struct option long_options[] =
|
||||
{
|
||||
{ "spec", 1, 0, LONG_OPT_SPEC },
|
||||
{ "dll", 1, 0, LONG_OPT_DLL },
|
||||
{ "def", 1, 0, LONG_OPT_DEF },
|
||||
{ "exe", 1, 0, LONG_OPT_EXE },
|
||||
{ "debug", 0, 0, LONG_OPT_DEBUG },
|
||||
{ "relay16", 0, 0, LONG_OPT_RELAY16 },
|
||||
{ "relay32", 0, 0, LONG_OPT_RELAY32 },
|
||||
{ "version", 0, 0, LONG_OPT_VERSION },
|
||||
{ "spec", 1, 0, LONG_OPT_DLL }, /* for backwards compatibility */
|
||||
/* aliases for short options */
|
||||
{ "source-dir", 1, 0, 'C' },
|
||||
{ "delay-lib", 1, 0, 'd' },
|
||||
|
@ -287,14 +291,14 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
|
|||
case 'w':
|
||||
display_warnings = 1;
|
||||
break;
|
||||
case LONG_OPT_SPEC:
|
||||
set_exec_mode( MODE_SPEC );
|
||||
input_file = open_input_file( NULL, optarg );
|
||||
case LONG_OPT_DLL:
|
||||
set_exec_mode( MODE_DLL );
|
||||
spec_file_name = xstrdup( optarg );
|
||||
set_dll_file_name( optarg, spec );
|
||||
break;
|
||||
case LONG_OPT_DEF:
|
||||
set_exec_mode( MODE_DEF );
|
||||
input_file = open_input_file( NULL, optarg );
|
||||
spec_file_name = xstrdup( optarg );
|
||||
set_dll_file_name( optarg, spec );
|
||||
break;
|
||||
case LONG_OPT_EXE:
|
||||
|
@ -357,65 +361,59 @@ static void load_resources( char *argv[], DLLSPEC *spec )
|
|||
}
|
||||
}
|
||||
|
||||
static int parse_input_file( DLLSPEC *spec )
|
||||
{
|
||||
FILE *input_file = open_input_file( NULL, spec_file_name );
|
||||
char *extension = strrchr( spec_file_name, '.' );
|
||||
|
||||
if (extension && !strcmp( extension, ".def" ))
|
||||
return parse_def_file( input_file, spec );
|
||||
else
|
||||
return parse_spec_file( input_file, spec );
|
||||
close_input_file( input_file );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* main
|
||||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
DLLSPEC spec;
|
||||
|
||||
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;
|
||||
DLLSPEC *spec = alloc_dll_spec();
|
||||
|
||||
output_file = stdout;
|
||||
argv = parse_options( argc, argv, &spec );
|
||||
argv = parse_options( argc, argv, spec );
|
||||
|
||||
switch(exec_mode)
|
||||
{
|
||||
case MODE_SPEC:
|
||||
load_resources( argv, &spec );
|
||||
if (!ParseTopLevel( input_file, &spec )) break;
|
||||
switch (spec.type)
|
||||
case MODE_DLL:
|
||||
load_resources( argv, spec );
|
||||
if (!parse_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, &spec );
|
||||
BuildSpec16File( output_file, spec );
|
||||
break;
|
||||
case SPEC_WIN32:
|
||||
read_undef_symbols( argv );
|
||||
BuildSpec32File( output_file, &spec );
|
||||
BuildSpec32File( output_file, spec );
|
||||
break;
|
||||
default: assert(0);
|
||||
}
|
||||
break;
|
||||
case MODE_EXE:
|
||||
if (spec.type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
|
||||
load_resources( argv, &spec );
|
||||
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, &spec );
|
||||
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 (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 );
|
||||
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
|
||||
if (!parse_input_file( spec )) break;
|
||||
BuildDef32File( output_file, spec );
|
||||
break;
|
||||
case MODE_DEBUG:
|
||||
BuildDebugFile( output_file, current_src_dir, argv );
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Copyright 1993 Robert J. Amstadt
|
||||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1995, 1996, 1997 Alexandre Julliard
|
||||
* Copyright 1995, 1996, 1997, 2004 Alexandre Julliard
|
||||
* Copyright 1997 Eric Youngdale
|
||||
* Copyright 1999 Ulrich Weigand
|
||||
*
|
||||
|
@ -43,6 +43,9 @@ static char TokenBuffer[512];
|
|||
static char *ParseNext = ParseBuffer;
|
||||
static FILE *input_file;
|
||||
|
||||
static const char *separator_chars;
|
||||
static const char *comment_chars;
|
||||
|
||||
static const char * const TypeNames[TYPE_NBTYPES] =
|
||||
{
|
||||
"variable", /* TYPE_VARIABLE */
|
||||
|
@ -76,7 +79,12 @@ static int IsNumberString(const char *s)
|
|||
|
||||
inline static int is_token_separator( char ch )
|
||||
{
|
||||
return (ch == '(' || ch == ')' || ch == '-');
|
||||
return strchr( separator_chars, ch ) != NULL;
|
||||
}
|
||||
|
||||
inline static int is_token_comment( char ch )
|
||||
{
|
||||
return strchr( comment_chars, ch ) != NULL;
|
||||
}
|
||||
|
||||
/* get the next line from the input file, or return 0 if at eof */
|
||||
|
@ -109,7 +117,7 @@ static const char * GetToken( int allow_eol )
|
|||
else break;
|
||||
}
|
||||
|
||||
if ((*p == '\0') || (*p == '#'))
|
||||
if ((*p == '\0') || is_token_comment(*p))
|
||||
{
|
||||
if (!allow_eol) error( "Declaration not terminated properly\n" );
|
||||
return NULL;
|
||||
|
@ -146,11 +154,11 @@ static ORDDEF *add_entry_point( DLLSPEC *spec )
|
|||
}
|
||||
|
||||
/*******************************************************************
|
||||
* ParseVariable
|
||||
* parse_spec_variable
|
||||
*
|
||||
* Parse a variable definition.
|
||||
* Parse a variable definition in a .spec file.
|
||||
*/
|
||||
static int ParseVariable( ORDDEF *odp, DLLSPEC *spec )
|
||||
static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
char *endptr;
|
||||
int *value_array;
|
||||
|
@ -208,11 +216,11 @@ static int ParseVariable( ORDDEF *odp, DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseExportFunction
|
||||
* parse_spec_export
|
||||
*
|
||||
* Parse a function definition.
|
||||
* Parse an exported function definition in a .spec file.
|
||||
*/
|
||||
static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec )
|
||||
static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
unsigned int i;
|
||||
|
@ -330,11 +338,11 @@ static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseEquate
|
||||
* parse_spec_equate
|
||||
*
|
||||
* Parse an 'equate' definition.
|
||||
* Parse an 'equate' definition in a .spec file.
|
||||
*/
|
||||
static int ParseEquate( ORDDEF *odp, DLLSPEC *spec )
|
||||
static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
char *endptr;
|
||||
int value;
|
||||
|
@ -358,11 +366,11 @@ static int ParseEquate( ORDDEF *odp, DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseStub
|
||||
* parse_spec_stub
|
||||
*
|
||||
* Parse a 'stub' definition.
|
||||
* Parse a 'stub' definition in a .spec file
|
||||
*/
|
||||
static int ParseStub( ORDDEF *odp, DLLSPEC *spec )
|
||||
static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
odp->u.func.arg_types[0] = '\0';
|
||||
odp->link_name = xstrdup("");
|
||||
|
@ -371,11 +379,11 @@ static int ParseStub( ORDDEF *odp, DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseExtern
|
||||
* parse_spec_extern
|
||||
*
|
||||
* Parse an 'extern' definition.
|
||||
* Parse an 'extern' definition in a .spec file.
|
||||
*/
|
||||
static int ParseExtern( ORDDEF *odp, DLLSPEC *spec )
|
||||
static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
|
||||
|
@ -403,11 +411,11 @@ static int ParseExtern( ORDDEF *odp, DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseFlags
|
||||
* parse_spec_flags
|
||||
*
|
||||
* Parse the optional flags for an entry point
|
||||
* Parse the optional flags for an entry point in a .spec file.
|
||||
*/
|
||||
static const char *ParseFlags( ORDDEF *odp )
|
||||
static const char *parse_spec_flags( ORDDEF *odp )
|
||||
{
|
||||
unsigned int i;
|
||||
const char *token;
|
||||
|
@ -429,26 +437,13 @@ static const char *ParseFlags( ORDDEF *odp )
|
|||
return token;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* fix_export_name
|
||||
*
|
||||
* Fix an exported function name by removing a possible @xx suffix
|
||||
*/
|
||||
static void fix_export_name( char *name )
|
||||
{
|
||||
char *p, *end = strrchr( name, '@' );
|
||||
if (!end || !end[1] || end == name) return;
|
||||
/* make sure all the rest is digits */
|
||||
for (p = end + 1; *p; p++) if (!isdigit(*p)) return;
|
||||
*end = 0;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* ParseOrdinal
|
||||
* parse_spec_ordinal
|
||||
*
|
||||
* Parse an ordinal definition.
|
||||
* Parse an ordinal definition in a .spec file.
|
||||
*/
|
||||
static int ParseOrdinal( int ordinal, DLLSPEC *spec )
|
||||
static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
|
||||
|
@ -468,32 +463,32 @@ static int ParseOrdinal( int ordinal, DLLSPEC *spec )
|
|||
}
|
||||
|
||||
if (!(token = GetToken(0))) goto error;
|
||||
if (*token == '-' && !(token = ParseFlags( odp ))) goto error;
|
||||
if (*token == '-' && !(token = parse_spec_flags( odp ))) goto error;
|
||||
|
||||
odp->name = xstrdup( token );
|
||||
fix_export_name( odp->name );
|
||||
remove_stdcall_decoration( odp->name );
|
||||
odp->lineno = current_line;
|
||||
odp->ordinal = ordinal;
|
||||
|
||||
switch(odp->type)
|
||||
{
|
||||
case TYPE_VARIABLE:
|
||||
if (!ParseVariable( odp, spec )) goto error;
|
||||
if (!parse_spec_variable( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_PASCAL:
|
||||
case TYPE_STDCALL:
|
||||
case TYPE_VARARGS:
|
||||
case TYPE_CDECL:
|
||||
if (!ParseExportFunction( odp, spec )) goto error;
|
||||
if (!parse_spec_export( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_ABS:
|
||||
if (!ParseEquate( odp, spec )) goto error;
|
||||
if (!parse_spec_equate( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_STUB:
|
||||
if (!ParseStub( odp, spec )) goto error;
|
||||
if (!parse_spec_stub( odp, spec )) goto error;
|
||||
break;
|
||||
case TYPE_EXTERN:
|
||||
if (!ParseExtern( odp, spec )) goto error;
|
||||
if (!parse_spec_extern( odp, spec )) goto error;
|
||||
break;
|
||||
default:
|
||||
assert( 0 );
|
||||
|
@ -641,17 +636,20 @@ static void assign_ordinals( DLLSPEC *spec )
|
|||
|
||||
|
||||
/*******************************************************************
|
||||
* ParseTopLevel
|
||||
* parse_spec_file
|
||||
*
|
||||
* Parse a spec file.
|
||||
* Parse a .spec file.
|
||||
*/
|
||||
int ParseTopLevel( FILE *file, DLLSPEC *spec )
|
||||
int parse_spec_file( FILE *file, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
|
||||
input_file = file;
|
||||
current_line = 0;
|
||||
|
||||
comment_chars = "#;";
|
||||
separator_chars = "()-";
|
||||
|
||||
while (get_next_line())
|
||||
{
|
||||
if (!(token = GetToken(1))) continue;
|
||||
|
@ -662,11 +660,11 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec )
|
|||
error( "'@' ordinals not supported for Win16\n" );
|
||||
continue;
|
||||
}
|
||||
if (!ParseOrdinal( -1, spec )) continue;
|
||||
if (!parse_spec_ordinal( -1, spec )) continue;
|
||||
}
|
||||
else if (IsNumberString(token))
|
||||
{
|
||||
if (!ParseOrdinal( atoi(token), spec )) continue;
|
||||
if (!parse_spec_ordinal( atoi(token), spec )) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -683,6 +681,243 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec )
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* parse_def_library
|
||||
*
|
||||
* Parse a LIBRARY declaration in a .def file.
|
||||
*/
|
||||
static int parse_def_library( DLLSPEC *spec )
|
||||
{
|
||||
const char *token = GetToken(1);
|
||||
|
||||
if (!token) return 1;
|
||||
if (strcmp( token, "BASE" ))
|
||||
{
|
||||
free( spec->file_name );
|
||||
spec->file_name = xstrdup( token );
|
||||
if (!(token = GetToken(1))) return 1;
|
||||
}
|
||||
if (strcmp( token, "BASE" ))
|
||||
{
|
||||
error( "Expected library name or BASE= declaration, got '%s'\n", token );
|
||||
return 0;
|
||||
}
|
||||
if (!(token = GetToken(0))) return 0;
|
||||
if (strcmp( token, "=" ))
|
||||
{
|
||||
error( "Expected '=' after BASE, got '%s'\n", token );
|
||||
return 0;
|
||||
}
|
||||
if (!(token = GetToken(0))) return 0;
|
||||
/* FIXME: do something with base address */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* parse_def_stack_heap_size
|
||||
*
|
||||
* Parse a STACKSIZE or HEAPSIZE declaration in a .def file.
|
||||
*/
|
||||
static int parse_def_stack_heap_size( int is_stack, DLLSPEC *spec )
|
||||
{
|
||||
const char *token = GetToken(0);
|
||||
char *end;
|
||||
unsigned long size;
|
||||
|
||||
if (!token) return 0;
|
||||
size = strtoul( token, &end, 0 );
|
||||
if (*end)
|
||||
{
|
||||
error( "Invalid number '%s'\n", token );
|
||||
return 0;
|
||||
}
|
||||
if (is_stack) spec->stack_size = size / 1024;
|
||||
else spec->heap_size = size / 1024;
|
||||
if (!(token = GetToken(1))) return 1;
|
||||
if (strcmp( token, "," ))
|
||||
{
|
||||
error( "Expected ',' after size, got '%s'\n", token );
|
||||
return 0;
|
||||
}
|
||||
if (!(token = GetToken(0))) return 0;
|
||||
/* FIXME: do something with reserve size */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* parse_def_export
|
||||
*
|
||||
* Parse an export declaration in a .def file.
|
||||
*/
|
||||
static int parse_def_export( char *name, DLLSPEC *spec )
|
||||
{
|
||||
int i, args;
|
||||
const char *token = GetToken(1);
|
||||
|
||||
ORDDEF *odp = add_entry_point( spec );
|
||||
memset( odp, 0, sizeof(*odp) );
|
||||
|
||||
odp->lineno = current_line;
|
||||
odp->ordinal = -1;
|
||||
odp->name = name;
|
||||
args = remove_stdcall_decoration( odp->name );
|
||||
if (args == -1) odp->type = TYPE_CDECL;
|
||||
else
|
||||
{
|
||||
odp->type = TYPE_STDCALL;
|
||||
args /= sizeof(int);
|
||||
if (args >= sizeof(odp->u.func.arg_types))
|
||||
{
|
||||
error( "Too many arguments in stdcall function '%s'\n", odp->name );
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < args; i++) odp->u.func.arg_types[i] = 'l';
|
||||
}
|
||||
|
||||
/* check for optional internal name */
|
||||
|
||||
if (token && !strcmp( token, "=" ))
|
||||
{
|
||||
if (!(token = GetToken(0))) goto error;
|
||||
odp->link_name = xstrdup( token );
|
||||
remove_stdcall_decoration( odp->link_name );
|
||||
token = GetToken(1);
|
||||
}
|
||||
|
||||
/* check for optional ordinal */
|
||||
|
||||
if (token && token[0] == '@')
|
||||
{
|
||||
int ordinal;
|
||||
|
||||
if (!IsNumberString( token+1 ))
|
||||
{
|
||||
error( "Expected number after '@', got '%s'\n", token+1 );
|
||||
goto error;
|
||||
}
|
||||
ordinal = atoi( token+1 );
|
||||
if (!ordinal)
|
||||
{
|
||||
error( "Ordinal 0 is not valid\n" );
|
||||
goto error;
|
||||
}
|
||||
if (ordinal >= MAX_ORDINALS)
|
||||
{
|
||||
error( "Ordinal number %d too large\n", ordinal );
|
||||
goto error;
|
||||
}
|
||||
if (ordinal > spec->limit) spec->limit = ordinal;
|
||||
if (ordinal < spec->base) spec->base = ordinal;
|
||||
odp->ordinal = ordinal;
|
||||
token = GetToken(1);
|
||||
}
|
||||
|
||||
/* check for other optional keywords */
|
||||
|
||||
if (token && !strcmp( token, "NONAME" ))
|
||||
{
|
||||
if (odp->ordinal == -1)
|
||||
{
|
||||
error( "NONAME requires an ordinal\n" );
|
||||
goto error;
|
||||
}
|
||||
odp->export_name = odp->name;
|
||||
odp->name = NULL;
|
||||
odp->flags |= FLAG_NONAME;
|
||||
token = GetToken(1);
|
||||
}
|
||||
if (token && !strcmp( token, "PRIVATE" ))
|
||||
{
|
||||
odp->flags |= FLAG_PRIVATE;
|
||||
token = GetToken(1);
|
||||
}
|
||||
if (token && !strcmp( token, "DATA" ))
|
||||
{
|
||||
odp->type = TYPE_EXTERN;
|
||||
token = GetToken(1);
|
||||
}
|
||||
if (token)
|
||||
{
|
||||
error( "Garbage text '%s' found at end of export declaration\n", token );
|
||||
goto error;
|
||||
}
|
||||
return 1;
|
||||
|
||||
error:
|
||||
spec->nb_entry_points--;
|
||||
free( odp->name );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* parse_def_file
|
||||
*
|
||||
* Parse a .def file.
|
||||
*/
|
||||
int parse_def_file( FILE *file, DLLSPEC *spec )
|
||||
{
|
||||
const char *token;
|
||||
int in_exports = 0;
|
||||
|
||||
input_file = file;
|
||||
current_line = 0;
|
||||
|
||||
comment_chars = ";";
|
||||
separator_chars = ",=";
|
||||
|
||||
while (get_next_line())
|
||||
{
|
||||
if (!(token = GetToken(1))) continue;
|
||||
|
||||
if (!strcmp( token, "LIBRARY" ) || !strcmp( token, "NAME" ))
|
||||
{
|
||||
if (!parse_def_library( spec )) continue;
|
||||
goto end_of_line;
|
||||
}
|
||||
else if (!strcmp( token, "STACKSIZE" ))
|
||||
{
|
||||
if (!parse_def_stack_heap_size( 1, spec )) continue;
|
||||
goto end_of_line;
|
||||
}
|
||||
else if (!strcmp( token, "HEAPSIZE" ))
|
||||
{
|
||||
if (!parse_def_stack_heap_size( 0, spec )) continue;
|
||||
goto end_of_line;
|
||||
}
|
||||
else if (!strcmp( token, "EXPORTS" ))
|
||||
{
|
||||
in_exports = 1;
|
||||
if (!(token = GetToken(1))) continue;
|
||||
}
|
||||
else if (!strcmp( token, "IMPORTS" ))
|
||||
{
|
||||
in_exports = 0;
|
||||
if (!(token = GetToken(1))) continue;
|
||||
}
|
||||
else if (!strcmp( token, "SECTIONS" ))
|
||||
{
|
||||
in_exports = 0;
|
||||
if (!(token = GetToken(1))) continue;
|
||||
}
|
||||
|
||||
if (!in_exports) continue; /* ignore this line */
|
||||
if (!parse_def_export( xstrdup(token), spec )) continue;
|
||||
|
||||
end_of_line:
|
||||
if ((token = GetToken(1))) error( "Syntax error near '%s'\n", token );
|
||||
}
|
||||
|
||||
current_line = 0; /* no longer parsing the input file */
|
||||
assign_names( spec );
|
||||
assign_ordinals( spec );
|
||||
return !nb_errors;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* add_debug_channel
|
||||
*/
|
||||
|
|
|
@ -209,6 +209,83 @@ void close_input_file( FILE *file )
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* remove_stdcall_decoration
|
||||
*
|
||||
* Remove a possible @xx suffix from a function name.
|
||||
* Return the numerical value of the suffix, or -1 if none.
|
||||
*/
|
||||
int remove_stdcall_decoration( char *name )
|
||||
{
|
||||
char *p, *end = strrchr( name, '@' );
|
||||
if (!end || !end[1] || end == name) return -1;
|
||||
/* make sure all the rest is digits */
|
||||
for (p = end + 1; *p; p++) if (!isdigit(*p)) return -1;
|
||||
*end = 0;
|
||||
return atoi( end + 1 );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* alloc_dll_spec
|
||||
*
|
||||
* Create a new dll spec file descriptor
|
||||
*/
|
||||
DLLSPEC *alloc_dll_spec(void)
|
||||
{
|
||||
DLLSPEC *spec;
|
||||
|
||||
spec = xmalloc( sizeof(*spec) );
|
||||
spec->file_name = NULL;
|
||||
spec->dll_name = NULL;
|
||||
spec->owner_name = NULL;
|
||||
spec->init_func = NULL;
|
||||
spec->type = SPEC_WIN32;
|
||||
spec->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;
|
||||
return spec;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* free_dll_spec
|
||||
*
|
||||
* Free dll spec file descriptor
|
||||
*/
|
||||
void free_dll_spec( DLLSPEC *spec )
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < spec->nb_entry_points; i++)
|
||||
{
|
||||
ORDDEF *odp = &spec->entry_points[i];
|
||||
free( odp->name );
|
||||
free( odp->export_name );
|
||||
free( odp->link_name );
|
||||
}
|
||||
free( spec->file_name );
|
||||
free( spec->dll_name );
|
||||
free( spec->owner_name );
|
||||
free( spec->init_func );
|
||||
free( spec->entry_points );
|
||||
free( spec->names );
|
||||
free( spec->ordinals );
|
||||
free( spec->resources );
|
||||
free( spec );
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* make_c_identifier
|
||||
*
|
||||
|
|
|
@ -19,10 +19,11 @@ option can be specified, as described in the \fBOPTIONS\fR section.
|
|||
You have to specify exactly one of the following options, depending on
|
||||
what you want winebuild to generate.
|
||||
.TP
|
||||
.BI \--spec=\ file.spec
|
||||
Build a C file from a spec file (see \fBSPEC FILE SYNTAX\fR for
|
||||
details). The resulting C file must be compiled and linked to the
|
||||
other object files to build a working Wine dll.
|
||||
.BI \--dll=\ filename
|
||||
Build a C file from a .spec file (see \fBSPEC FILE SYNTAX\fR for
|
||||
details), or from a standard Windows .def file. The resulting C file
|
||||
must be compiled and linked to the other object files to build a
|
||||
working Wine dll.
|
||||
.br
|
||||
In that mode, the
|
||||
.I input files
|
||||
|
@ -34,7 +35,7 @@ other dlls.
|
|||
.TP
|
||||
.BI \--exe=\ name
|
||||
Build a C file for the named executable. This is basically the same as
|
||||
the --spec mode except that it doesn't require a .spec file as input,
|
||||
the --dll mode except that it doesn't require a .spec file as input,
|
||||
since an executable doesn't export functions. The resulting C file
|
||||
must be compiled and linked to the other object files to build a
|
||||
working Wine executable, and all the other object files must be listed
|
||||
|
@ -130,7 +131,7 @@ imported from it is actually called).
|
|||
.BI \-M,\ --main-module= module
|
||||
Specify that we are building a 16-bit dll, that will ultimately be
|
||||
linked together with the 32-bit dll specified in \fImodule\fR. Only
|
||||
meaningful in \fB--spec\fR mode.
|
||||
meaningful in \fB--dll\fR mode.
|
||||
.TP
|
||||
.BI \-m,\ --mode= mode
|
||||
Set the executable or dll mode, which can be one of the following:
|
||||
|
|
Loading…
Reference in New Issue