Commit 492ac292 authored by Alexandre Julliard's avatar Alexandre Julliard

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.
parent 14743a0f
...@@ -129,7 +129,7 @@ LINTS = $(C_SRCS:.c=.ln) ...@@ -129,7 +129,7 @@ LINTS = $(C_SRCS:.c=.ln)
$(WINDRES) -i $< -o $@ $(WINDRES) -i $< -o $@
.spec.spec.c: .spec.spec.c:
$(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --spec $< $(WINEBUILD) $(DEFS) -o $@ --main-module $(MODULE) --dll $<
.spec.spec.def: .spec.spec.def:
$(WINEBUILD) $(DEFS) -o $@ --def $< $(WINEBUILD) $(DEFS) -o $@ --def $<
......
...@@ -27,7 +27,7 @@ all: $(MODULE)$(DLLEXT) $(SUBDIRS) ...@@ -27,7 +27,7 @@ all: $(MODULE)$(DLLEXT) $(SUBDIRS)
# Rules for .so files # Rules for .so files
$(MAINSPEC).c: $(MAINSPEC) $(RC_SRCS:.rc=.res) $(ALL_OBJS) $(IMPORTLIBS) $(WINEBUILD) $(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 $(MODULE).so: $(MAINSPEC).o $(ALL_OBJS) Makefile.in
$(LDDLL) $(MAINSPEC).o $(ALL_OBJS) -o $@ -L$(DLLDIR) $(ALL_LIBS) -lc $(LDDLL) $(MAINSPEC).o $(ALL_OBJS) -o $@ -L$(DLLDIR) $(ALL_LIBS) -lc
......
...@@ -76,7 +76,7 @@ EXTRASUBDIRS = \ ...@@ -76,7 +76,7 @@ EXTRASUBDIRS = \
# Special rules for 16-bit resource and spec files # Special rules for 16-bit resource and spec files
gdi.exe.spec.c: gdi.exe.spec version16.res 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 version16.res: version16.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
......
...@@ -113,7 +113,7 @@ relay16asm.s: $(WINEBUILD) ...@@ -113,7 +113,7 @@ relay16asm.s: $(WINEBUILD)
# Special rules for 16-bit resource and spec files # Special rules for 16-bit resource and spec files
krnl386.exe.spec.c: krnl386.exe.spec version16.res 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 version16.res: version16.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
......
...@@ -72,10 +72,10 @@ version16.res: version16.rc ...@@ -72,10 +72,10 @@ version16.res: version16.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/version16.rc
shell.spec.c: shell.spec version16.res 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 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 && \ sed -e '1,2d' -e 's/\(.*\)/ \"\1\",/' $(TOPSRCDIR)/AUTHORS && \
echo ' 0 };') >$@ || ($(RM) $@ && false) echo ' 0 };') >$@ || ($(RM) $@ && false)
......
...@@ -168,13 +168,13 @@ EXTRASUBDIRS = \ ...@@ -168,13 +168,13 @@ EXTRASUBDIRS = \
# Special rules for 16-bit resource and spec files # Special rules for 16-bit resource and spec files
user.exe.spec.c: user.exe.spec resources/version16.res 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 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 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 resources/display.res: resources/display.rc
$(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/resources/display.rc $(LDPATH) $(RC16) $(RC16FLAGS) -fo$@ $(SRCDIR)/resources/display.rc
......
...@@ -68,7 +68,6 @@ typedef struct ...@@ -68,7 +68,6 @@ typedef struct
typedef struct typedef struct
{ {
int n_args;
char arg_types[21]; char arg_types[21];
} ORD_FUNCTION; } ORD_FUNCTION;
...@@ -170,6 +169,9 @@ extern FILE *open_input_file( const char *srcdir, const char *name ); ...@@ -170,6 +169,9 @@ extern FILE *open_input_file( const char *srcdir, const char *name );
extern void close_input_file( FILE *file ); extern void close_input_file( FILE *file );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len, extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
const char *label, int constant ); 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 const char *make_c_identifier( const char *str );
extern int get_alignment(int alignBoundary); extern int get_alignment(int alignBoundary);
...@@ -184,7 +186,6 @@ extern void load_res16_file( const char *name, DLLSPEC *spec ); ...@@ -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_data( FILE *outfile, DLLSPEC *spec );
extern int output_res16_directory( unsigned char *buffer, 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 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 BuildRelays16( FILE *outfile );
extern void BuildRelays32( FILE *outfile ); extern void BuildRelays32( FILE *outfile );
...@@ -192,7 +193,10 @@ extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec ); ...@@ -192,7 +193,10 @@ extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec ); extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
extern void BuildDef32File( FILE *outfile, DLLSPEC *spec ); extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ); extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv );
extern int ParseTopLevel( FILE *file, 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 */ /* global variables */
......
/* /*
* DLL imports support * DLL imports support
* *
* Copyright 2000 Alexandre Julliard * Copyright 2000, 2004 Alexandre Julliard
* 2000 Eric Pouech * Copyright 2000 Eric Pouech
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -32,20 +32,13 @@ ...@@ -32,20 +32,13 @@
#include "build.h" #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 struct import
{ {
char *dll; /* dll name */ DLLSPEC *spec; /* description of the imported dll */
int delay; /* delay or not dll loading ? */ 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 */ 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 */ int nb_imports; /* number of imported functions */
}; };
...@@ -143,7 +136,10 @@ static int name_cmp( const void *name, const void *entry ) ...@@ -143,7 +136,10 @@ static int name_cmp( const void *name, const void *entry )
/* compare function names; helper for resolve_imports */ /* compare function names; helper for resolve_imports */
static int func_cmp( const void *func1, const void *func2 ) 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 */ /* locate a symbol in a (sorted) list */
...@@ -159,14 +155,15 @@ inline static const char *find_symbol( const char *name, char **table, int size ...@@ -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 */ /* 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.name = (char *)name;
func.ordinal = -1; func.ordinal = -1;
if (table) res = bsearch( &func, table, size, sizeof(*table), func_cmp ); odp = &func;
return res; if (table) res = bsearch( &odp, table, size, sizeof(*table), func_cmp );
return res ? *res : NULL;
} }
/* sort a symbol table */ /* sort a symbol table */
...@@ -179,13 +176,9 @@ inline static void sort_symbols( char **table, int size ) ...@@ -179,13 +176,9 @@ inline static void sort_symbols( char **table, int size )
/* free an import structure */ /* free an import structure */
static void free_imports( struct import *imp ) 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->exports );
free( imp->imports ); free( imp->imports );
free( imp->dll ); free_dll_spec( imp->spec );
free( imp ); free( imp );
} }
...@@ -202,7 +195,7 @@ static int is_already_imported( const char *name ) ...@@ -202,7 +195,7 @@ static int is_already_imported( const char *name )
for (i = 0; i < nb_imports; i++) 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; return 0;
} }
...@@ -241,152 +234,40 @@ static char *open_library( const char *name ) ...@@ -241,152 +234,40 @@ static char *open_library( const char *name )
return fullname; 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 */ /* read in the list of exported symbols of an import library */
static int read_import_lib( const char *name, struct import *imp ) static int read_import_lib( const char *name, struct import *imp )
{ {
FILE *f; FILE *f;
char buffer[1024];
char *fullname; char *fullname;
int size; int i, ret;
DLLSPEC *spec = imp->spec;
imp->exports = NULL; imp->exports = NULL;
imp->nb_exports = size = 0; imp->nb_exports = 0;
fullname = open_library( name ); fullname = open_library( name );
f = open_input_file( NULL, fullname ); f = open_input_file( NULL, fullname );
free( fullname ); free( fullname );
while (fgets( buffer, sizeof(buffer), f )) ret = parse_def_file( f, spec );
{
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 ); close_input_file( f );
return 0; /* ignore this dll */ if (!ret) return 0;
} if (is_already_imported( spec->file_name )) return 0;
free( imp->dll );
imp->dll = xstrdup( name );
goto next;
}
if (!strcmp( name, "EXPORTS" )) goto next;
/* check for ordinal */ imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
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 */ for (i = 0; i < spec->nb_entry_points; i++)
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" ); ORDDEF *odp = &spec->entry_points[i];
goto next;
}
}
if (imp->nb_exports == size) if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
{ if (odp->flags & FLAG_PRIVATE) continue;
size += 128; imp->exports[imp->nb_exports++] = odp;
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++;
} }
close_input_file( f ); imp->exports = xrealloc( imp->exports, imp->nb_exports * sizeof(*imp->exports) );
if (imp->nb_exports) if (imp->nb_exports)
qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp ); qsort( imp->exports, imp->nb_exports, sizeof(*imp->exports), func_cmp );
return !nb_errors; return 1;
} }
/* add a dll to the list of imports */ /* add a dll to the list of imports */
...@@ -407,11 +288,11 @@ void add_import_dll( const char *name, int delay ) ...@@ -407,11 +288,11 @@ void add_import_dll( const char *name, int delay )
} }
imp = xmalloc( sizeof(*imp) ); imp = xmalloc( sizeof(*imp) );
imp->dll = fullname; imp->spec = alloc_dll_spec();
imp->spec->file_name = fullname;
imp->delay = delay; imp->delay = delay;
imp->imports = NULL; imp->imports = NULL;
imp->nb_imports = 0; imp->nb_imports = 0;
if (delay) nb_delayed++; if (delay) nb_delayed++;
if (read_import_lib( name, imp )) if (read_import_lib( name, imp ))
...@@ -489,13 +370,10 @@ void add_ignore_symbol( const char *name ) ...@@ -489,13 +370,10 @@ void add_ignore_symbol( const char *name )
} }
/* add a function to the list of imports from a given dll */ /* 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 = xrealloc( imp->imports, (imp->nb_imports+1) * sizeof(*imp->imports) );
imp->imports[imp->nb_imports].name = xstrdup( func->name ); imp->imports[imp->nb_imports++] = func;
imp->imports[imp->nb_imports].ordinal = func->ordinal;
imp->imports[imp->nb_imports].ord_only = func->ord_only;
imp->nb_imports++;
total_imports++; total_imports++;
if (imp->delay) total_delayed++; if (imp->delay) total_delayed++;
} }
...@@ -613,15 +491,16 @@ static void add_extra_undef_symbols( const DLLSPEC *spec ) ...@@ -613,15 +491,16 @@ static void add_extra_undef_symbols( const DLLSPEC *spec )
static int check_unused( const struct import* imp, const DLLSPEC *spec ) static int check_unused( const struct import* imp, const DLLSPEC *spec )
{ {
int i; int i;
size_t len = strlen(imp->dll); const char *file_name = imp->spec->file_name;
const char *p = strchr( imp->dll, '.' ); size_t len = strlen( file_name );
if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll; const char *p = strchr( file_name, '.' );
if (p && !strcasecmp( p, ".dll" )) len = p - file_name;
for (i = spec->base; i <= spec->limit; i++) for (i = spec->base; i <= spec->limit; i++)
{ {
ORDDEF *odp = spec->ordinals[i]; ORDDEF *odp = spec->ordinals[i];
if (!odp || !(odp->flags & FLAG_FORWARD)) continue; if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
if (!strncasecmp( odp->link_name, imp->dll, len ) && if (!strncasecmp( odp->link_name, file_name, len ) &&
odp->link_name[len] == '.') odp->link_name[len] == '.')
return 0; /* found a forward, it is used */ return 0; /* found a forward, it is used */
} }
...@@ -724,10 +603,10 @@ int resolve_imports( DLLSPEC *spec ) ...@@ -724,10 +603,10 @@ int resolve_imports( DLLSPEC *spec )
for (j = 0; j < nb_undef_symbols; j++) for (j = 0; j < nb_undef_symbols; j++)
{ {
struct func *func = find_export( undef_symbols[j], imp->exports, imp->nb_exports ); ORDDEF *odp = find_export( undef_symbols[j], imp->exports, imp->nb_exports );
if (func) if (odp)
{ {
add_import_func( imp, func ); add_import_func( imp, odp );
free( undef_symbols[j] ); free( undef_symbols[j] );
undef_symbols[j] = NULL; undef_symbols[j] = NULL;
} }
...@@ -736,7 +615,7 @@ int resolve_imports( DLLSPEC *spec ) ...@@ -736,7 +615,7 @@ int resolve_imports( DLLSPEC *spec )
if (!remove_symbol_holes() && check_unused( imp, spec )) if (!remove_symbol_holes() && check_unused( imp, spec ))
{ {
/* the dll is not used, get rid of it */ /* the dll is not used, get rid of it */
warning( "%s imported but no symbols used\n", imp->dll ); warning( "%s imported but no symbols used\n", imp->spec->file_name );
remove_import_dll( i ); remove_import_dll( i );
i--; i--;
} }
...@@ -772,7 +651,7 @@ static int output_immediate_imports( FILE *outfile ) ...@@ -772,7 +651,7 @@ static int output_immediate_imports( FILE *outfile )
{ {
if (dll_imports[i]->delay) continue; if (dll_imports[i]->delay) continue;
fprintf( outfile, " { 0, 0, 0, \"%s\", &imports.data[%d] },\n", 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; j += dll_imports[i]->nb_imports + 1;
} }
...@@ -784,18 +663,18 @@ static int output_immediate_imports( FILE *outfile ) ...@@ -784,18 +663,18 @@ static int output_immediate_imports( FILE *outfile )
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
{ {
if (dll_imports[i]->delay) continue; 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++) for (j = 0; j < dll_imports[i]->nb_imports; j++)
{ {
struct func *import = &dll_imports[i]->imports[j]; ORDDEF *odp = dll_imports[i]->imports[j];
if (!import->ord_only) if (!(odp->flags & FLAG_NONAME))
{ {
unsigned short ord = import->ordinal; unsigned short ord = odp->ordinal;
fprintf( outfile, " \"\\%03o\\%03o%s\",\n", 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 else
fprintf( outfile, " (char *)%d,\n", import->ordinal ); fprintf( outfile, " (char *)%d,\n", odp->ordinal );
} }
fprintf( outfile, " 0,\n" ); fprintf( outfile, " 0,\n" );
} }
...@@ -811,13 +690,14 @@ static int output_immediate_imports( FILE *outfile ) ...@@ -811,13 +690,14 @@ static int output_immediate_imports( FILE *outfile )
if (dll_imports[i]->delay) continue; if (dll_imports[i]->delay) continue;
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4) for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
{ {
struct func *import = &dll_imports[i]->imports[j]; ORDDEF *odp = dll_imports[i]->imports[j];
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name ); const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name ); fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", import->name); fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t", name);
#if defined(__i386__) #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 ); fprintf( outfile, ".byte 0x2e\\n\\tjmp *(imports+%d)\\n\\tnop\\n", pos );
else else
fprintf( outfile, "jmp *(imports+%d)\\n\\tmovl %%esi,%%esi\\n", pos ); 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 ) ...@@ -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); fprintf( outfile, "static void *__wine_delay_imp_%d_hmod;\n", i);
for (j = 0; j < dll_imports[i]->nb_imports; j++) for (j = 0; j < dll_imports[i]->nb_imports; j++)
{ {
fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", ORDDEF *odp = dll_imports[i]->imports[j];
i, dll_imports[i]->imports[j].name ); const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
} }
} }
fprintf( outfile, "\n" ); fprintf( outfile, "\n" );
...@@ -910,31 +791,33 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) ...@@ -910,31 +791,33 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
{ {
if (!dll_imports[i]->delay) continue; 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", 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; j += dll_imports[i]->nb_imports;
} }
fprintf( outfile, " },\n {\n" ); fprintf( outfile, " },\n {\n" );
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
{ {
if (!dll_imports[i]->delay) continue; 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++) 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" ); fprintf( outfile, " },\n {\n" );
for (i = 0; i < nb_imports; i++) for (i = 0; i < nb_imports; i++)
{ {
if (!dll_imports[i]->delay) continue; 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++) for (j = 0; j < dll_imports[i]->nb_imports; j++)
{ {
struct func *import = &dll_imports[i]->imports[j]; ORDDEF *odp = dll_imports[i]->imports[j];
if (import->ord_only) if (!odp->name)
fprintf( outfile, " (char *)%d,\n", import->ordinal ); fprintf( outfile, " (char *)%d,\n", odp->ordinal );
else else
fprintf( outfile, " \"%s\",\n", import->name ); fprintf( outfile, " \"%s\",\n", odp->name );
} }
} }
fprintf( outfile, " }\n};\n\n" ); fprintf( outfile, " }\n};\n\n" );
...@@ -1059,7 +942,10 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) ...@@ -1059,7 +942,10 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
for (j = 0; j < dll_imports[i]->nb_imports; j++) for (j = 0; j < dll_imports[i]->nb_imports; j++)
{ {
char buffer[128]; 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, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", buffer );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer ); fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\"\n", buffer );
#if defined(__i386__) #if defined(__i386__)
...@@ -1088,12 +974,14 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) ...@@ -1088,12 +974,14 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
if (!dll_imports[i]->delay) continue; if (!dll_imports[i]->delay) continue;
for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4) for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += 4)
{ {
struct func *import = &dll_imports[i]->imports[j]; ORDDEF *odp = dll_imports[i]->imports[j];
fprintf( outfile, " \"\\t" __ASM_FUNC("%s") "\\n\"\n", import->name ); const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, " \"\\t.globl " __ASM_NAME("%s") "\\n\"\n", import->name );
fprintf( outfile, " \"" __ASM_NAME("%s") ":\\n\\t\"", import->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 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 ); fprintf( outfile, "\".byte 0x2e\\n\\tjmp *(delay_imports+%d)\\n\\tnop\\n\"", pos );
else else
fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos ); fprintf( outfile, "\"jmp *(delay_imports+%d)\\n\\tmovl %%esi,%%esi\\n\"", pos );
......
...@@ -56,17 +56,17 @@ char **lib_path = NULL; ...@@ -56,17 +56,17 @@ char **lib_path = NULL;
char *input_file_name = NULL; char *input_file_name = NULL;
const char *output_file_name = NULL; const char *output_file_name = NULL;
static FILE *input_file;
static FILE *output_file; static FILE *output_file;
static const char *current_src_dir; static const char *current_src_dir;
static int nb_res_files; static int nb_res_files;
static char **res_files; static char **res_files;
static char *spec_file_name;
/* execution mode */ /* execution mode */
enum exec_mode_values enum exec_mode_values
{ {
MODE_NONE, MODE_NONE,
MODE_SPEC, MODE_DLL,
MODE_EXE, MODE_EXE,
MODE_DEF, MODE_DEF,
MODE_DEBUG, MODE_DEBUG,
...@@ -87,7 +87,10 @@ static void set_dll_file_name( const char *name, DLLSPEC *spec ) ...@@ -87,7 +87,10 @@ static void set_dll_file_name( const char *name, DLLSPEC *spec )
if ((p = strrchr( name, '/' ))) name = p + 1; if ((p = strrchr( name, '/' ))) name = p + 1;
spec->file_name = xmalloc( strlen(name) + 5 ); spec->file_name = xmalloc( strlen(name) + 5 );
strcpy( spec->file_name, name ); 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" ); if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
} }
...@@ -126,7 +129,7 @@ static const char usage_str[] = ...@@ -126,7 +129,7 @@ static const char usage_str[] =
" --version Print the version and exit\n" " --version Print the version and exit\n"
" -w --warnings Turn on warnings\n" " -w --warnings Turn on warnings\n"
"\nMode options:\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" " --def=FILE.SPEC Build a .def file from a spec file\n"
" --exe=NAME Build a .c file for the named executable\n" " --exe=NAME Build a .c file for the named executable\n"
" --debug [FILES] Build a .c file with the debug channels declarations\n" " --debug [FILES] Build a .c file with the debug channels declarations\n"
...@@ -136,7 +139,7 @@ static const char usage_str[] = ...@@ -136,7 +139,7 @@ static const char usage_str[] =
enum long_options_values enum long_options_values
{ {
LONG_OPT_SPEC = 1, LONG_OPT_DLL = 1,
LONG_OPT_DEF, LONG_OPT_DEF,
LONG_OPT_EXE, LONG_OPT_EXE,
LONG_OPT_DEBUG, 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"; ...@@ -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[] = static const struct option long_options[] =
{ {
{ "spec", 1, 0, LONG_OPT_SPEC }, { "dll", 1, 0, LONG_OPT_DLL },
{ "def", 1, 0, LONG_OPT_DEF }, { "def", 1, 0, LONG_OPT_DEF },
{ "exe", 1, 0, LONG_OPT_EXE }, { "exe", 1, 0, LONG_OPT_EXE },
{ "debug", 0, 0, LONG_OPT_DEBUG }, { "debug", 0, 0, LONG_OPT_DEBUG },
{ "relay16", 0, 0, LONG_OPT_RELAY16 }, { "relay16", 0, 0, LONG_OPT_RELAY16 },
{ "relay32", 0, 0, LONG_OPT_RELAY32 }, { "relay32", 0, 0, LONG_OPT_RELAY32 },
{ "version", 0, 0, LONG_OPT_VERSION }, { "version", 0, 0, LONG_OPT_VERSION },
{ "spec", 1, 0, LONG_OPT_DLL }, /* for backwards compatibility */
/* aliases for short options */ /* aliases for short options */
{ "source-dir", 1, 0, 'C' }, { "source-dir", 1, 0, 'C' },
{ "delay-lib", 1, 0, 'd' }, { "delay-lib", 1, 0, 'd' },
...@@ -287,14 +291,14 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) ...@@ -287,14 +291,14 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case 'w': case 'w':
display_warnings = 1; display_warnings = 1;
break; break;
case LONG_OPT_SPEC: case LONG_OPT_DLL:
set_exec_mode( MODE_SPEC ); set_exec_mode( MODE_DLL );
input_file = open_input_file( NULL, optarg ); spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec ); set_dll_file_name( optarg, spec );
break; break;
case LONG_OPT_DEF: case LONG_OPT_DEF:
set_exec_mode( MODE_DEF ); set_exec_mode( MODE_DEF );
input_file = open_input_file( NULL, optarg ); spec_file_name = xstrdup( optarg );
set_dll_file_name( optarg, spec ); set_dll_file_name( optarg, spec );
break; break;
case LONG_OPT_EXE: case LONG_OPT_EXE:
...@@ -357,65 +361,59 @@ static void load_resources( char *argv[], DLLSPEC *spec ) ...@@ -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 * main
*/ */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
DLLSPEC spec; DLLSPEC *spec = alloc_dll_spec();
spec.file_name = NULL;
spec.dll_name = NULL;
spec.owner_name = NULL;
spec.init_func = NULL;
spec.type = SPEC_WIN32;
spec.mode = SPEC_MODE_DLL;
spec.base = MAX_ORDINALS;
spec.limit = 0;
spec.stack_size = 0;
spec.heap_size = 0;
spec.nb_entry_points = 0;
spec.alloc_entry_points = 0;
spec.nb_names = 0;
spec.nb_resources = 0;
spec.entry_points = NULL;
spec.names = NULL;
spec.ordinals = NULL;
spec.resources = NULL;
output_file = stdout; output_file = stdout;
argv = parse_options( argc, argv, &spec ); argv = parse_options( argc, argv, spec );
switch(exec_mode) switch(exec_mode)
{ {
case MODE_SPEC: case MODE_DLL:
load_resources( argv, &spec ); load_resources( argv, spec );
if (!ParseTopLevel( input_file, &spec )) break; if (!parse_input_file( spec )) break;
switch (spec.type) switch (spec->type)
{ {
case SPEC_WIN16: case SPEC_WIN16:
if (argv[0]) if (argv[0])
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildSpec16File( output_file, &spec ); BuildSpec16File( output_file, spec );
break; break;
case SPEC_WIN32: case SPEC_WIN32:
read_undef_symbols( argv ); read_undef_symbols( argv );
BuildSpec32File( output_file, &spec ); BuildSpec32File( output_file, spec );
break; break;
default: assert(0); default: assert(0);
} }
break; break;
case MODE_EXE: case MODE_EXE:
if (spec.type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" ); if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
load_resources( argv, &spec ); load_resources( argv, spec );
read_undef_symbols( argv ); read_undef_symbols( argv );
BuildSpec32File( output_file, &spec ); BuildSpec32File( output_file, spec );
break; break;
case MODE_DEF: case MODE_DEF:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (spec.type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" ); if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!ParseTopLevel( input_file, &spec )) break; if (!parse_input_file( spec )) break;
BuildDef32File( output_file, &spec ); BuildDef32File( output_file, spec );
break; break;
case MODE_DEBUG: case MODE_DEBUG:
BuildDebugFile( output_file, current_src_dir, argv ); BuildDebugFile( output_file, current_src_dir, argv );
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright 1993 Robert J. Amstadt * Copyright 1993 Robert J. Amstadt
* Copyright 1995 Martin von Loewis * Copyright 1995 Martin von Loewis
* Copyright 1995, 1996, 1997 Alexandre Julliard * Copyright 1995, 1996, 1997, 2004 Alexandre Julliard
* Copyright 1997 Eric Youngdale * Copyright 1997 Eric Youngdale
* Copyright 1999 Ulrich Weigand * Copyright 1999 Ulrich Weigand
* *
...@@ -43,6 +43,9 @@ static char TokenBuffer[512]; ...@@ -43,6 +43,9 @@ static char TokenBuffer[512];
static char *ParseNext = ParseBuffer; static char *ParseNext = ParseBuffer;
static FILE *input_file; static FILE *input_file;
static const char *separator_chars;
static const char *comment_chars;
static const char * const TypeNames[TYPE_NBTYPES] = static const char * const TypeNames[TYPE_NBTYPES] =
{ {
"variable", /* TYPE_VARIABLE */ "variable", /* TYPE_VARIABLE */
...@@ -76,7 +79,12 @@ static int IsNumberString(const char *s) ...@@ -76,7 +79,12 @@ static int IsNumberString(const char *s)
inline static int is_token_separator( char ch ) 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 */ /* 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 ) ...@@ -109,7 +117,7 @@ static const char * GetToken( int allow_eol )
else break; else break;
} }
if ((*p == '\0') || (*p == '#')) if ((*p == '\0') || is_token_comment(*p))
{ {
if (!allow_eol) error( "Declaration not terminated properly\n" ); if (!allow_eol) error( "Declaration not terminated properly\n" );
return NULL; return NULL;
...@@ -146,11 +154,11 @@ static ORDDEF *add_entry_point( DLLSPEC *spec ) ...@@ -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; char *endptr;
int *value_array; int *value_array;
...@@ -208,11 +216,11 @@ static int ParseVariable( ORDDEF *odp, DLLSPEC *spec ) ...@@ -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; const char *token;
unsigned int i; unsigned int i;
...@@ -330,11 +338,11 @@ static int ParseExportFunction( ORDDEF *odp, DLLSPEC *spec ) ...@@ -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; char *endptr;
int value; int value;
...@@ -358,11 +366,11 @@ static int ParseEquate( ORDDEF *odp, DLLSPEC *spec ) ...@@ -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->u.func.arg_types[0] = '\0';
odp->link_name = xstrdup(""); odp->link_name = xstrdup("");
...@@ -371,11 +379,11 @@ static int ParseStub( ORDDEF *odp, DLLSPEC *spec ) ...@@ -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; const char *token;
...@@ -403,11 +411,11 @@ static int ParseExtern( ORDDEF *odp, DLLSPEC *spec ) ...@@ -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; unsigned int i;
const char *token; const char *token;
...@@ -429,26 +437,13 @@ static const char *ParseFlags( ORDDEF *odp ) ...@@ -429,26 +437,13 @@ static const char *ParseFlags( ORDDEF *odp )
return token; 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; const char *token;
...@@ -468,32 +463,32 @@ static int ParseOrdinal( int ordinal, DLLSPEC *spec ) ...@@ -468,32 +463,32 @@ static int ParseOrdinal( int ordinal, DLLSPEC *spec )
} }
if (!(token = GetToken(0))) goto error; 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 ); odp->name = xstrdup( token );
fix_export_name( odp->name ); remove_stdcall_decoration( odp->name );
odp->lineno = current_line; odp->lineno = current_line;
odp->ordinal = ordinal; odp->ordinal = ordinal;
switch(odp->type) switch(odp->type)
{ {
case TYPE_VARIABLE: case TYPE_VARIABLE:
if (!ParseVariable( odp, spec )) goto error; if (!parse_spec_variable( odp, spec )) goto error;
break; break;
case TYPE_PASCAL: case TYPE_PASCAL:
case TYPE_STDCALL: case TYPE_STDCALL:
case TYPE_VARARGS: case TYPE_VARARGS:
case TYPE_CDECL: case TYPE_CDECL:
if (!ParseExportFunction( odp, spec )) goto error; if (!parse_spec_export( odp, spec )) goto error;
break; break;
case TYPE_ABS: case TYPE_ABS:
if (!ParseEquate( odp, spec )) goto error; if (!parse_spec_equate( odp, spec )) goto error;
break; break;
case TYPE_STUB: case TYPE_STUB:
if (!ParseStub( odp, spec )) goto error; if (!parse_spec_stub( odp, spec )) goto error;
break; break;
case TYPE_EXTERN: case TYPE_EXTERN:
if (!ParseExtern( odp, spec )) goto error; if (!parse_spec_extern( odp, spec )) goto error;
break; break;
default: default:
assert( 0 ); assert( 0 );
...@@ -641,17 +636,20 @@ static void assign_ordinals( DLLSPEC *spec ) ...@@ -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; const char *token;
input_file = file; input_file = file;
current_line = 0; current_line = 0;
comment_chars = "#;";
separator_chars = "()-";
while (get_next_line()) while (get_next_line())
{ {
if (!(token = GetToken(1))) continue; if (!(token = GetToken(1))) continue;
...@@ -662,11 +660,11 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec ) ...@@ -662,11 +660,11 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec )
error( "'@' ordinals not supported for Win16\n" ); error( "'@' ordinals not supported for Win16\n" );
continue; continue;
} }
if (!ParseOrdinal( -1, spec )) continue; if (!parse_spec_ordinal( -1, spec )) continue;
} }
else if (IsNumberString(token)) else if (IsNumberString(token))
{ {
if (!ParseOrdinal( atoi(token), spec )) continue; if (!parse_spec_ordinal( atoi(token), spec )) continue;
} }
else else
{ {
...@@ -684,6 +682,243 @@ int ParseTopLevel( FILE *file, DLLSPEC *spec ) ...@@ -684,6 +682,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 * add_debug_channel
*/ */
static void add_debug_channel( const char *name ) static void add_debug_channel( const char *name )
......
...@@ -210,6 +210,83 @@ void close_input_file( FILE *file ) ...@@ -210,6 +210,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 * make_c_identifier
* *
* Map a string to a valid C identifier. * Map a string to a valid C identifier.
......
...@@ -19,10 +19,11 @@ option can be specified, as described in the \fBOPTIONS\fR section. ...@@ -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 You have to specify exactly one of the following options, depending on
what you want winebuild to generate. what you want winebuild to generate.
.TP .TP
.BI \--spec=\ file.spec .BI \--dll=\ filename
Build a C file from a spec file (see \fBSPEC FILE SYNTAX\fR for 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 details), or from a standard Windows .def file. The resulting C file
other object files to build a working Wine dll. must be compiled and linked to the other object files to build a
working Wine dll.
.br .br
In that mode, the In that mode, the
.I input files .I input files
...@@ -34,7 +35,7 @@ other dlls. ...@@ -34,7 +35,7 @@ other dlls.
.TP .TP
.BI \--exe=\ name .BI \--exe=\ name
Build a C file for the named executable. This is basically the same as 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 since an executable doesn't export functions. The resulting C file
must be compiled and linked to the other object files to build a 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 working Wine executable, and all the other object files must be listed
...@@ -130,7 +131,7 @@ imported from it is actually called). ...@@ -130,7 +131,7 @@ imported from it is actually called).
.BI \-M,\ --main-module= module .BI \-M,\ --main-module= module
Specify that we are building a 16-bit dll, that will ultimately be 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 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 .TP
.BI \-m,\ --mode= mode .BI \-m,\ --mode= mode
Set the executable or dll mode, which can be one of the following: Set the executable or dll mode, which can be one of the following:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment