Commit in reactos/tools/winebuild on MAIN
winehq2ros.patch+86added 1.1
Makefile+1-11.4 -> 1.5
build.h+44-411.1 -> 1.2
import.c+212-2981.3 -> 1.4
main.c+98-901.3 -> 1.4
parser.c+386-941.2 -> 1.3
relay.c+82-611.1 -> 1.2
res16.c+46-341.2 -> 1.3
res32.c+104-691.2 -> 1.3
spec16.c+43-531.1 -> 1.2
spec32.c+227-2361.5 -> 1.6
utils.c+811.2 -> 1.3
winebuild.man.in+34-371.1 -> 1.2
winglue.h+41.1 -> 1.2
+1448-1014
1 added + 13 modified, total 14 files
Sync to Wine:
Alexandre Julliard <julliard@winehq.org>
- Store all information about the current dll in a structure instead of
  using global variables to make it easier to reuse the parsing
  routines.
- Added native mode dll support (based on a patch by Marcus Meissner).
- 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.
- Removed the Unicode exe modes, and instead detect automatically which
  mode to use based on the existence of main or wmain.
- Automatically detect whether the entry point is main or WinMain
  instead of depending on the subsystem type.
- Do not strip stdcall decoration in spec files.
- Print a warning when DllRegisterServer and similar functions are not
  marked private.
- Fill in the proper offsets in the resource directory instead of
  relying on the compiler to do it.
Jukka Heinonen <jhei@iki.fi>
- Remove support for generating interrupt handlers.
- DPMI programs now handle pending events.
Robert Shearman <R.J.Shearman@warwick.ac.uk>
- Fix proc name reported in delay load failure.
Richard Cohen <richard@daijobu.co.uk>
- Remove . from default library search path.
Eric Pouech <pouech-eric@wanadoo.fr>
- added size information about most of the generated thunks (import,
  16/32 relay...)
- marked the wine thunks by inserting specific symbols (to be managed
  by wine's dbghelp)
- removed the stabs generation:
  + mostly used by winedbg, and the previous item will replace it for
    dbghelp
  + still broken for gdb anyway
- enhanced const correctness
Pierre d'Herbemont <stegefin@free.fr>
- Detection of .size instruction.
- Detection of the assembler name prefix.
- Delayed import fix for Darwin and PowerPC Host.
- Be more accurate on Darwin stack size.
- Delay import fix on PowerPC hosts.
Marcus Meissner <meissner@suse.de>
- Use "LD" instead of "ld" in winebuild to be able to use a different ld
  or ld options.
Dmitry Timoshkov <dmitry@codeweavers.com>
- Add a few missing __ASM_NAME macros.

reactos/tools/winebuild
winehq2ros.patch added at 1.1
diff -N winehq2ros.patch
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ winehq2ros.patch	23 Sep 2004 20:27:30 -0000	1.1
@@ -0,0 +1,86 @@
+Index: main.c
+===================================================================
+RCS file: /home/wine/wine/tools/winebuild/main.c,v
+retrieving revision 1.55
+diff -u -r1.55 main.c
+--- main.c	25 Mar 2004 00:40:52 -0000	1.55
++++ main.c	23 Sep 2004 20:38:14 -0000
+@@ -412,9 +412,7 @@
+         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 );
++                fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
+                 break;
+             case SPEC_WIN32:
+                 read_undef_symbols( argv );
+@@ -439,12 +437,10 @@
+         BuildDebugFile( output_file, current_src_dir, argv );
+         break;
+     case MODE_RELAY16:
+-        if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
+-        BuildRelays16( output_file );
++        fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
+         break;
+     case MODE_RELAY32:
+-        if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
+-        BuildRelays32( output_file );
++        fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" );
+         break;
+     default:
+         usage(1);
+Index: spec32.c
+===================================================================
+RCS file: /home/wine/wine/tools/winebuild/spec32.c,v
+retrieving revision 1.83
+diff -u -r1.83 spec32.c
+--- spec32.c	15 Jul 2004 18:58:42 -0000	1.83
++++ spec32.c	23 Sep 2004 20:38:15 -0000
+@@ -30,9 +30,15 @@
+ #include <stdarg.h>
+ #include <string.h>
+ 
++#ifdef WIN32
+ #include "windef.h"
+ #include "winbase.h"
+-#include "wine/exception.h"
++#else
++#include "winglue.h"
++#endif
++#define EXCEPTION_WINE_STUB       0x80000100  /* stub entry point called */
++#define EH_NONCONTINUABLE   0x01
++
+ #include "build.h"
+ 
+ 
+@@ -886,7 +892,10 @@
+         fprintf( outfile, " @%d", odp->ordinal );
+         if (!odp->name) fprintf( outfile, " NONAME" );
+         if (is_data) fprintf( outfile, " DATA" );
++#if 0
++        /* MinGW binutils cannot handle this correctly */
+         if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
++#endif
+         fprintf( outfile, "\n" );
+     }
+ }
+Index: utils.c
+===================================================================
+RCS file: /home/wine/wine/tools/winebuild/utils.c,v
+retrieving revision 1.20
+diff -u -r1.20 utils.c
+--- utils.c	25 Mar 2004 00:40:52 -0000	1.20
++++ utils.c	23 Sep 2004 20:38:15 -0000
+@@ -21,6 +21,10 @@
+ #include "config.h"
+ #include "wine/port.h"
+ 
++#if !defined(WIN32)
++#undef strdup
++#endif
++
+ #include <ctype.h>
+ #include <stdarg.h>
+ #include <stdio.h>

reactos/tools/winebuild
Makefile 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- Makefile	21 Feb 2004 09:20:34 -0000	1.4
+++ Makefile	23 Sep 2004 20:27:30 -0000	1.5
@@ -20,7 +20,7 @@
 
 CLEAN_FILES = *.o $(TARGET)
 
-HOST_CFLAGS = -D__USE_W32API -D__REACTOS__ -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine -I$(W32API_PATH)/include
+HOST_CFLAGS = -D__USE_W32API -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/include/wine -I$(W32API_PATH)/include
 
 %.o: %.c
 	$(HOST_CC) $(HOST_CFLAGS) -c $< -o $@

reactos/tools/winebuild
build.h 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- build.h	9 Dec 2003 18:44:25 -0000	1.1
+++ build.h	23 Sep 2004 20:27:30 -0000	1.2
@@ -50,15 +50,6 @@
     SPEC_WIN32
 } SPEC_TYPE;
 
-typedef enum
-{
-    SPEC_MODE_DLL,
-    SPEC_MODE_GUIEXE,
-    SPEC_MODE_CUIEXE,
-    SPEC_MODE_GUIEXE_UNICODE,
-    SPEC_MODE_CUIEXE_UNICODE
-} SPEC_MODE;
-
 typedef struct
 {
     int n_values;
@@ -67,7 +58,6 @@
 
 typedef struct
 {
-    int  n_args;
     char arg_types[21];
 } ORD_FUNCTION;
 
@@ -94,6 +84,31 @@
     } u;
 } ORDDEF;
 
+typedef struct
+{
+    char            *file_name;          /* file name of the dll */
+    char            *dll_name;           /* internal name of the dll */
+    char            *owner_name;         /* name of the 32-bit dll owning this one */
+    char            *init_func;          /* initialization routine */
+    SPEC_TYPE        type;               /* type of dll (Win16/Win32) */
+    int              base;               /* ordinal base */
+    int              limit;              /* ordinal limit */
+    int              stack_size;         /* exe stack size */
+    int              heap_size;          /* exe heap size */
+    int              nb_entry_points;    /* number of used entry points */
+    int              alloc_entry_points; /* number of allocated entry points */
+    int              nb_names;           /* number of entry points with names */
+    int              nb_resources;       /* number of resources */
+    int              characteristics;    /* characteristics for the PE header */
+    int              subsystem;          /* subsystem id */
+    int              subsystem_major;    /* subsystem version major number */
+    int              subsystem_minor;    /* subsystem version minor number */
+    ORDDEF          *entry_points;       /* dll entry points */
+    ORDDEF         **names;              /* array of entry point names (points into entry_points) */
+    ORDDEF         **ordinals;           /* array of dll ordinals (points into entry_points) */
+    struct resource *resources;          /* array of dll resources (format differs between Win16/Win32) */
+} DLLSPEC;
+
 /* entry point flags */
 #define FLAG_NORELAY   0x01  /* don't use relay debugging for this function */
 #define FLAG_NONAME    0x02  /* don't import function by name */
@@ -101,10 +116,9 @@
 #define FLAG_RET64     0x08  /* function returns a 64-bit value */
 #define FLAG_I386      0x10  /* function is i386 only */
 #define FLAG_REGISTER  0x20  /* use register calling convention */
-#define FLAG_INTERRUPT 0x40  /* function is an interrupt handler */
-#define FLAG_PRIVATE   0x80  /* function is private (cannot be imported) */
+#define FLAG_PRIVATE   0x40  /* function is private (cannot be imported) */
 
-#define FLAG_FORWARD   0x100 /* function is a forwarded name */
+#define FLAG_FORWARD   0x80  /* function is a forwarded name */
 
   /* Offset of a structure field relative to the start of the struct */
 #define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
@@ -147,60 +161,49 @@
 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);
 
 extern void add_import_dll( const char *name, int delay );
 extern void add_ignore_symbol( const char *name );
 extern void read_undef_symbols( char **argv );
-extern int resolve_imports( void );
-extern int output_imports( FILE *outfile );
-extern int load_res32_file( const char *name );
-extern int output_resources( FILE *outfile );
-extern void load_res16_file( const char *name );
-extern int output_res16_data( FILE *outfile );
-extern int output_res16_directory( unsigned char *buffer );
+extern int resolve_imports( DLLSPEC *spec );
+extern int output_imports( FILE *outfile, DLLSPEC *spec );
+extern int load_res32_file( const char *name, DLLSPEC *spec );
+extern void output_resources( FILE *outfile, DLLSPEC *spec );
+extern void load_res16_file( const char *name, DLLSPEC *spec );
+extern int output_res16_data( FILE *outfile, DLLSPEC *spec );
+extern int output_res16_directory( unsigned char *buffer, DLLSPEC *spec );
 extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor );
-extern int parse_debug_channels( const char *srcdir, const char *filename );
 
 extern void BuildRelays16( FILE *outfile );
 extern void BuildRelays32( FILE *outfile );
-extern void BuildSpec16File( FILE *outfile );
-extern void BuildSpec32File( FILE *outfile );
-extern void BuildDef32File( FILE *outfile );
+extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
+extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
+extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
 extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv );
-extern int ParseTopLevel( FILE *file );
+
+extern int 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 */
 
 extern int current_line;
-extern int nb_entry_points;
-extern int nb_names;
-extern int Base;
-extern int Limit;
-extern int DLLHeapSize;
 extern int UsePIC;
 extern int debugging;
-extern int stack_size;
 extern int nb_debug_channels;
 extern int nb_lib_paths;
 extern int nb_errors;
 extern int display_warnings;
 extern int kill_at;
 
-extern char *owner_name;
-extern char *dll_name;
-extern char *dll_file_name;
-extern const char *init_func;
 extern char *input_file_name;
 extern const char *output_file_name;
 extern char **debug_channels;
 extern char **lib_path;
 
-extern ORDDEF *EntryPoints[MAX_ORDINALS];
-extern ORDDEF *Ordinals[MAX_ORDINALS];
-extern ORDDEF *Names[MAX_ORDINALS];
-extern SPEC_MODE SpecMode;
-extern SPEC_TYPE SpecType;
-
 #endif  /* __WINE_BUILD_H */

reactos/tools/winebuild
import.c 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- import.c	5 Jan 2004 19:49:59 -0000	1.3
+++ import.c	23 Sep 2004 20:27:30 -0000	1.4
@@ -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
@@ -26,32 +26,22 @@
 #include <fcntl.h>
 #include <stdio.h>
 #include <string.h>
+#include <stdarg.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
 
-#if defined(WIN32)
-#include <windows.h>
-#else
-#include <limits.h>
-#endif
-
+#include "windef.h"
+#include "winbase.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
 {
-    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,13 +133,16 @@
 /* compare function names; helper for resolve_imports */
 static int name_cmp( const void *name, const void *entry )
 {
-    return strcmp( *(char **)name, *(char **)entry );
+    return strcmp( *(const char* const *)name, *(const char* const *)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 * const *)func1;
+    const ORDDEF *odp2 = *(const ORDDEF * const *)func2;
+    return strcmp( odp1->name ? odp1->name : odp1->export_name,
+                   odp2->name ? odp2->name : odp2->export_name );
 }
 
 /* locate a symbol in a (sorted) list */
@@ -165,14 +158,15 @@
 }
 
 /* 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 */
@@ -182,16 +176,19 @@
         qsort( table, size, sizeof(*table), name_cmp );
 }
 
+inline static void output_function_size( FILE *outfile, const char *name )
+{
+#ifdef HAVE_ASM_DOT_SIZE
+    fprintf( outfile, "    \"\\t.size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\\n\"\n", name, name);
+#endif
+}
+
 /* 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 );
 }
 
@@ -208,7 +205,7 @@
 
     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;
 }
@@ -242,157 +239,44 @@
     {
         if ((fullname = try_library_path( lib_path[i], name ))) return fullname;
     }
-    if (!(fullname = try_library_path( ".", name )))
-        fatal_error( "could not open .def file for %s\n", 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;
+    fatal_error( "could not open .def file for %s\n", name );
+    return NULL;
 }
 
 /* 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;
+    ret = parse_def_file( f, spec );
+    close_input_file( f );
+    if (!ret) return 0;
+    if (is_already_imported( spec->file_name )) return 0;
 
-        /* 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;
-        }
+    imp->exports = xmalloc( spec->nb_entry_points * sizeof(*imp->exports) );
 
-        /* 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;
-            }
-        }
+    for (i = 0; i < spec->nb_entry_points; i++)
+    {
+        ORDDEF *odp = &spec->entry_points[i];
 
-        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++;
+        if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
+        if (odp->flags & FLAG_PRIVATE) continue;
+        imp->exports[imp->nb_exports++] = odp;
     }
-    close_input_file( f );
+    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 */
@@ -413,11 +297,11 @@
     }
 
     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 ))
@@ -495,13 +379,10 @@
 }
 
 /* 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++;
 }
@@ -531,16 +412,16 @@
 }
 
 /* add a symbol to the extra list, but only if needed */
-static int add_extra_symbol( const char **extras, int *count, const char *name )
+static int add_extra_symbol( const char **extras, int *count, const char *name, const DLLSPEC *spec )
 {
     int i;
 
     if (!find_symbol( name, undef_symbols, nb_undef_symbols ))
     {
         /* check if the symbol is being exported by this dll */
-        for (i = 0; i < nb_entry_points; i++)
+        for (i = 0; i < spec->nb_entry_points; i++)
         {
-            ORDDEF *odp = EntryPoints[i];
+            ORDDEF *odp = &spec->entry_points[i];
             if (odp->type == TYPE_STDCALL ||
                 odp->type == TYPE_CDECL ||
                 odp->type == TYPE_VARARGS ||
@@ -556,7 +437,7 @@
 }
 
 /* add the extra undefined symbols that will be contained in the generated spec file itself */
-static void add_extra_undef_symbols(void)
+static void add_extra_undef_symbols( const DLLSPEC *spec )
 {
     const char *extras[10];
     int i, count = 0, nb_stubs = 0, nb_regs = 0;
@@ -564,44 +445,36 @@
 
     sort_symbols( undef_symbols, nb_undef_symbols );
 
-    for (i = 0; i < nb_entry_points; i++)
+    for (i = 0; i < spec->nb_entry_points; i++)
     {
-        ORDDEF *odp = EntryPoints[i];
+        ORDDEF *odp = &spec->entry_points[i];
         if (odp->type == TYPE_STUB) nb_stubs++;
         if (odp->flags & FLAG_REGISTER) nb_regs++;
     }
 
     /* add symbols that will be contained in the spec file itself */
-    switch (SpecMode)
+    if (!(spec->characteristics & IMAGE_FILE_DLL))
     {
-    case SPEC_MODE_DLL:
-        break;
-    case SPEC_MODE_GUIEXE:
-        kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
-        kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
-        kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
-        /* fall through */
-    case SPEC_MODE_CUIEXE:
-        kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
-        break;
-    case SPEC_MODE_GUIEXE_UNICODE:
-        kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA" );
-        kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA" );
-        kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA" );
-        /* fall through */
-    case SPEC_MODE_CUIEXE_UNICODE:
-        kernel_imports += add_extra_symbol( extras, &count, "ExitProcess" );
-        break;
+        switch (spec->subsystem)
+        {
+        case IMAGE_SUBSYSTEM_WINDOWS_GUI:
+        case IMAGE_SUBSYSTEM_WINDOWS_CUI:
+            kernel_imports += add_extra_symbol( extras, &count, "GetCommandLineA", spec );
+            kernel_imports += add_extra_symbol( extras, &count, "GetStartupInfoA", spec );
+            kernel_imports += add_extra_symbol( extras, &count, "GetModuleHandleA", spec );
+            kernel_imports += add_extra_symbol( extras, &count, "ExitProcess", spec );
+            break;
+        }
     }
     if (nb_delayed)
     {
-        kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA" );
-        kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress" );
+        kernel_imports += add_extra_symbol( extras, &count, "LoadLibraryA", spec );
+        kernel_imports += add_extra_symbol( extras, &count, "GetProcAddress", spec );
     }
     if (nb_regs)
-        ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs" );
+        ntdll_imports += add_extra_symbol( extras, &count, "__wine_call_from_32_regs", spec );
     if (nb_delayed || nb_stubs)
-        ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException" );
+        ntdll_imports += add_extra_symbol( extras, &count, "RtlRaiseException", spec );
 
     /* make sure we import the dlls that contain these functions */
     if (kernel_imports) add_import_dll( "kernel32", 0 );
@@ -615,18 +488,19 @@
 }
 
 /* check if a given imported dll is not needed, taking forwards into account */
-static int check_unused( const struct import* imp )
+static int check_unused( const struct import* imp, const DLLSPEC *spec )
 {
     int i;
-    size_t len = strlen(imp->dll);
-    const char *p = strchr( imp->dll, '.' );
-    if (p && !strcasecmp( p, ".dll" )) len = p - imp->dll;
+    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 = Base; i <= Limit; i++)
+    for (i = spec->base; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp || !(odp->flags & FLAG_FORWARD)) continue;
-        if (!strncasecmp( odp->link_name, imp->dll, len ) &&
+        if (!strncasecmp( odp->link_name, file_name, len ) &&
             odp->link_name[len] == '.')
             return 0;  /* found a forward, it is used */
     }
@@ -638,35 +512,26 @@
 static const char *ldcombine_files( char **argv )
 {
     int i, len = 0;
-    char *cmd;
+    char *cmd, *ldcmd;
     int fd, err;
-#if defined(WIN32)
-	char tmppath[MAX_PATH];
-	char tmpfile[MAX_PATH];
-#endif
 
-#if defined(WIN32)
-	if (GetTempPathA(MAX_PATH, tmppath) == 0) return NULL;
-	if (GetTempFileNameA(tmppath, "WNB", 0, tmpfile) == 0) fatal_error( "could not generate a temp file\n" );
-	ld_tmp_file = xstrdup( tmpfile );
-	if ((fd = open( ld_tmp_file, O_RDONLY )) == -1)
-#else
-	if (output_file_name && output_file_name[0])
+    if (output_file_name && output_file_name[0])
     {
-        ld_tmp_file = xmalloc( PATH_MAX );
+        ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
         strcpy( ld_tmp_file, output_file_name );
         strcat( ld_tmp_file, ".XXXXXX.o" );
     }
-	else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
-    if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
-#endif
+    else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
 
+    if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
     close( fd );
     atexit( remove_ld_tmp_file );
 
+    ldcmd = getenv("LD");
+    if (!ldcmd) ldcmd = "ld";
     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
-    cmd = xmalloc( len + strlen(ld_tmp_file) + 10 );
-    sprintf( cmd, "ld -r -o %s", ld_tmp_file );
+    cmd = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ldcmd)  );
+    sprintf( cmd, "%s -r -o %s", ldcmd, ld_tmp_file );
     for (i = 0; argv[i]; i++) sprintf( cmd + strlen(cmd), " %s", argv[i] );
     err = system( cmd );
     if (err) fatal_error( "ld -r failed with status %d\n", err );
@@ -677,6 +542,8 @@
 /* read in the list of undefined symbols */
 void read_undef_symbols( char **argv )
 {
+    static const char name_prefix[] = __ASM_NAME("");
+    static const int prefix_len = sizeof(name_prefix) - 1;
     FILE *f;
     char buffer[1024];
     int err;
@@ -702,6 +569,7 @@
         p = buffer;
         while (*p == ' ') p++;
         if (p[0] == 'U' && p[1] == ' ' && p[2]) p += 2;
+        if (prefix_len && !strncmp( p, name_prefix, prefix_len )) p += prefix_len;
         add_undef_symbol( p );
     }
     if ((err = pclose( f ))) warning( "nm -u %s error %d\n", name, err );
@@ -725,13 +593,13 @@
 }
 
 /* resolve the imports for a Win32 module */
-int resolve_imports( void )
+int resolve_imports( DLLSPEC *spec )
 {
     int i, j;
 
     if (nb_undef_symbols == -1) return 0; /* no symbol file specified */
 
-    add_extra_undef_symbols();
+    add_extra_undef_symbols( spec );
     remove_ignored_symbols();
 
     for (i = 0; i < nb_imports; i++)
@@ -740,19 +608,19 @@
 
         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;
             }
         }
         /* remove all the holes in the undef symbols list */
-        if (!remove_symbol_holes() && check_unused( imp ))
+        if (!remove_symbol_holes() && check_unused( imp, spec ))
         {
             /* the dll is not used, get rid of it */
-            warning( "%s imported but no symbols used\n", imp->dll );
+            warning( "%s imported but no symbols used\n", imp->spec->file_name );
             remove_import_dll( i );
             i--;
         }
@@ -765,6 +633,7 @@
 {
     int i, j, pos;
     int nb_imm = nb_imports - nb_delayed;
+    static const char import_thunks[] = "__wine_spec_import_thunks";
 
     if (!nb_imm) goto done;
 
@@ -788,7 +657,7 @@
     {
         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;
     }
 
@@ -800,18 +669,18 @@
     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" );
     }
@@ -822,18 +691,21 @@
     fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
     pos = 20 * (nb_imm + 1);  /* offset of imports.data from start of imports */
     fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
+    fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", import_thunks);
+
     for (i = 0; i < nb_imports; i++)
     {
         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 );
@@ -880,19 +752,23 @@
 #error You need to define import thunks for your architecture!
 #endif
             fprintf( outfile, "\"\n" );
+            output_function_size( outfile, name );
         }
         pos += 4;
     }
-    fprintf( outfile, "\".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
+    output_function_size( outfile, import_thunks );
+    fprintf( outfile, "    \".text\");\n#ifndef __GNUC__\n}\n#endif\n\n" );
 
  done:
     return nb_imm;
 }
 
 /* output the delayed import table of a Win32 module */
-static int output_delayed_imports( FILE *outfile )
+static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
 {
     int i, idx, j, pos;
+    static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
+    static const char delayed_import_thunks[] = "__wine_spec_delayed_import_thunks";
 
     if (!nb_delayed) goto done;
 
@@ -902,8 +778,9 @@
         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" );
@@ -926,31 +803,33 @@
     {
         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" );
@@ -958,9 +837,9 @@
     /* check if there's some stub defined. if so, exception struct
      *  is already defined, so don't emit it twice
      */
-    for (i = 0; i < nb_entry_points; i++) if (EntryPoints[i]->type == TYPE_STUB) break;
+    for (i = 0; i < spec->nb_entry_points; i++) if (spec->entry_points[i].type == TYPE_STUB) break;
 
-    if (i == nb_entry_points) {
+    if (i == spec->nb_entry_points) {
        fprintf( outfile, "struct exc_record {\n" );
        fprintf( outfile, "  unsigned int code, flags;\n" );
        fprintf( outfile, "  void *rec, *addr;\n" );
@@ -993,7 +872,7 @@
     fprintf( outfile, "    rec.rec     = 0;\n" );
     fprintf( outfile, "    rec.params  = 2;\n" );
     fprintf( outfile, "    rec.info[0] = imd->szName;\n" );
-    fprintf( outfile, "    rec.info[1] = *pINT + 2;\n" );
+    fprintf( outfile, "    rec.info[1] = *pINT;\n" );
     fprintf( outfile, "#ifdef __GNUC__\n" );
     fprintf( outfile, "    rec.addr = __builtin_return_address(1);\n" );
     fprintf( outfile, "#else\n" );
@@ -1008,6 +887,7 @@
     fprintf( outfile, "#endif\n" );
 
     fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
+    fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_loaders);
     fprintf( outfile, "    \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
     fprintf( outfile, "    \"" __ASM_NAME("__wine_delay_load_asm") ":\\n\"\n" );
 #if defined(__i386__)
@@ -1020,25 +900,31 @@
     fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
     fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
 #elif defined(__powerpc__)
+# if defined(__APPLE__)
+/* On darwin an extra 56 bytes must be allowed for the linkage area+param area */
+#  define extra_stack_storage    56
+# else
+#  define extra_stack_storage    0
+# endif
     /* Save all callee saved registers into a stackframe. */
-    fprintf( outfile, "    \"\\tstwu %s, -48(%s)\\n\"\n", ppc_reg[1], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,   4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,   8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tstw  %s,  40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg[1], 48+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[3],  4+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[4],  8+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
 
     /* r0 -> r3 (arg1) */
     fprintf( outfile, "    \"\\tmr %s, %s\\n\"\n", ppc_reg[3], ppc_reg[0]);
 
     /* save return address */
     fprintf( outfile, "    \"\\tmflr %s\\n\"\n", ppc_reg[0]);
-    fprintf( outfile, "    \"\\tstw  %s, 44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]);
+    fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
 
     /* Call the __wine_delay_load function, arg1 is arg1. */
     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_delay_load") "\\n\"\n");
@@ -1047,27 +933,28 @@
     fprintf( outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg[3]);
 
     /* restore all saved registers and drop stackframe. */
-    fprintf( outfile, "    \"\\tlwz  %s,   4(%s)\\n\"\n", ppc_reg[3], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,   8(%s)\\n\"\n", ppc_reg[4], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  12(%s)\\n\"\n", ppc_reg[5], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  16(%s)\\n\"\n", ppc_reg[6], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  20(%s)\\n\"\n", ppc_reg[7], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  24(%s)\\n\"\n", ppc_reg[8], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  28(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  32(%s)\\n\"\n", ppc_reg[10], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  36(%s)\\n\"\n", ppc_reg[11], ppc_reg[1]);
-    fprintf( outfile, "    \"\\tlwz  %s,  40(%s)\\n\"\n", ppc_reg[12], ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[3],  4+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[4],  8+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[5], 12+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[6], 16+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[7], 20+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[8], 24+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[9], 28+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[10],32+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[11],36+extra_stack_storage, ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg[12],40+extra_stack_storage, ppc_reg[1]);
 
     /* Load return value from call into return register */
-    fprintf( outfile, "    \"\\tlwz  %s,  44(%s)\\n\"\n", ppc_reg[0], ppc_reg[1]);
+    fprintf( outfile, "    \"\\tlwz  %s,  %d(%s)\\n\"\n", ppc_reg[0], 44+extra_stack_storage, ppc_reg[1]);
     fprintf( outfile, "    \"\\tmtlr %s\\n\"\n", ppc_reg[0]);
-    fprintf( outfile, "    \"\\taddi %s, %s, 48\\n\"\n", ppc_reg[1], ppc_reg[1]);
+    fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[1], ppc_reg[1],  48+extra_stack_storage);
 
     /* branch to ctr register. */
-    fprintf( outfile, "\"bctr\\n\"\n");
+    fprintf( outfile, "    \"bctr\\n\"\n");
 #else
 #error You need to defined delayed import thunks for your architecture!
 #endif
+    output_function_size( outfile, "__wine_delay_load_asm" );
 
     for (i = idx = 0; i < nb_imports; i++)
     {
@@ -1075,7 +962,10 @@
         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__)
@@ -1085,31 +975,52 @@
             fprintf( outfile, "    \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
             fprintf( outfile, "    \"\\tb,a __wine_delay_load_asm\\n\"\n" );
 #elif defined(__powerpc__)
-            /* g0 is a function scratch register or so I understand. */
-            /* First load the upper half-word, and then the lower part */
-            fprintf( outfile, "    \"\\tlis %s, %d\\n\"\n", ppc_reg[0], idx);
-            fprintf( outfile, "    \"\\tli %s, %d\\n\"\n", ppc_reg[0], j);
+#ifdef __APPLE__
+            /* On Darwin we can use r0 and r2 */
+            /* Upper part in r2 */
+            fprintf( outfile, "    \"\\tlis %s, %d\\n\"\n", ppc_reg[2], idx);
+            /* Lower part + r2 -> r0, Note we can't use r0 directly */
+            fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[2], j);
+            fprintf( outfile, "    \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
+#else /* __APPLE__ */
+            /* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
+            /* Save r13 on the stack */
+            fprintf( outfile, "    \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
+            fprintf( outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[13], ppc_reg[1]);
+            /* Upper part in r13 */
+            fprintf( outfile, "    \"\\tlis %s, %d\\n\"\n", ppc_reg[13], idx);
+            /* Lower part + r13 -> r0, Note we can't use r0 directly */
+            fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg[0], ppc_reg[13], j);
+            /* Restore r13 */
+            fprintf( outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[13], ppc_reg[1]);
+            fprintf( outfile, "    \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
             fprintf( outfile, "    \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n");
+#endif /* __APPLE__ */
 #else
 #error You need to defined delayed import thunks for your architecture!
 #endif
+            output_function_size( outfile, name );
         }
         idx++;
     }
+    output_function_size( outfile, delayed_import_loaders );
 
     fprintf( outfile, "\n    \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
+    fprintf( outfile, "    \"" __ASM_NAME("%s") ":\\n\"\n", delayed_import_thunks);
     pos = nb_delayed * 32;
     for (i = 0; i < nb_imports; i++)
     {
         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 );
@@ -1139,8 +1050,9 @@
             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[8], ppc_reg[1]);
             fprintf( outfile, "\t\"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg[1], ppc_reg[1]);
             fprintf( outfile, "\t\"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg[7], ppc_reg[1]);
-            fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
-            fprintf( outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
+
+            fprintf( outfile, "\t\"\\tlis %s, " ppc_high(__ASM_NAME("delay_imports") "+ %d") "\\n\"\n", ppc_reg[9], pos);
+            fprintf( outfile, "\t\"\\tla  %s, " ppc_low (__ASM_NAME("delay_imports") "+ %d") "(%s)\\n\"\n", ppc_reg[8], pos, ppc_reg[9]);
             fprintf( outfile, "\t\"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg[7], ppc_reg[8]);
             fprintf( outfile, "\t\"\\tmtctr %s\\n\"\n", ppc_reg[7]);
 
@@ -1155,8 +1067,10 @@
 #error You need to define delayed import thunks for your architecture!
 #endif
             fprintf( outfile, "\n" );
+            output_function_size( outfile, name );
         }
     }
+    output_function_size( outfile, delayed_import_thunks );
     fprintf( outfile, "\".text\");\n" );
     fprintf( outfile, "#ifndef __GNUC__\n" );
     fprintf( outfile, "}\n" );
@@ -1170,8 +1084,8 @@
 /* output the import and delayed import tables of a Win32 module
  * returns number of DLLs exported in 'immediate' mode
  */
-int output_imports( FILE *outfile )
+int output_imports( FILE *outfile, DLLSPEC *spec )
 {
-   output_delayed_imports( outfile );
+   output_delayed_imports( outfile, spec );
    return output_immediate_imports( outfile );
 }

reactos/tools/winebuild
main.c 1.3 -> 1.4
diff -u -r1.3 -r1.4
--- main.c	5 Jan 2004 19:49:59 -0000	1.3
+++ main.c	23 Sep 2004 20:27:30 -0000	1.4
@@ -29,27 +29,17 @@
 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
+#include <stdarg.h>
 #include <ctype.h>
 #ifdef HAVE_GETOPT_H
 # include <getopt.h>
 #endif
 
+#include "windef.h"
+#include "winbase.h"
 #include "build.h"
 
-ORDDEF *EntryPoints[MAX_ORDINALS];
-ORDDEF *Ordinals[MAX_ORDINALS];
-ORDDEF *Names[MAX_ORDINALS];
-
-SPEC_MODE SpecMode = SPEC_MODE_DLL;
-SPEC_TYPE SpecType = SPEC_WIN32;
-
-int Base = MAX_ORDINALS;
-int Limit = 0;
-int DLLHeapSize = 0;
 int UsePIC = 0;
-int stack_size = 0;
-int nb_entry_points = 0;
-int nb_names = 0;
 int nb_debug_channels = 0;
 int nb_lib_paths = 0;
 int nb_errors = 0;
@@ -63,27 +53,23 @@
 int debugging = 0;
 #endif
 
-char *owner_name = NULL;
-char *dll_name = NULL;
-char *dll_file_name = NULL;
-const char *init_func = NULL;
 char **debug_channels = NULL;
 char **lib_path = NULL;
 
 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,
@@ -94,18 +80,43 @@
 static enum exec_mode_values exec_mode = MODE_NONE;
 
 /* set the dll file name from the input file name */
-static void set_dll_file_name( const char *name )
+static void set_dll_file_name( const char *name, DLLSPEC *spec )
 {
     char *p;
 
-    if (dll_file_name) return;
+    if (spec->file_name) return;
 
     if ((p = strrchr( name, '\\' ))) name = p + 1;
     if ((p = strrchr( name, '/' ))) name = p + 1;
-    dll_file_name = xmalloc( strlen(name) + 5 );
-    strcpy( dll_file_name, name );
-    if ((p = strrchr( dll_file_name, '.' )) && !strcmp( p, ".spec" )) *p = 0;
-    if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".dll" );
+    spec->file_name = xmalloc( strlen(name) + 5 );
+    strcpy( spec->file_name, name );
+    if ((p = strrchr( spec->file_name, '.' )))
+    {
+        if (!strcmp( p, ".spec" ) || !strcmp( p, ".def" )) *p = 0;
+    }
+    if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".dll" );
+}
+
+/* set the dll subsystem */
+static void set_subsystem( const char *subsystem, DLLSPEC *spec )
+{
+    char *major, *minor, *str = xstrdup( subsystem );
+
+    if ((major = strchr( str, ':' ))) *major++ = 0;
+    if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
+    else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
+    else if (!strcmp( str, "console" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
+    else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
+    if (major)
+    {
+        if ((minor = strchr( major, '.' )))
+        {
+            *minor++ = 0;
+            spec->subsystem_minor = atoi( minor );
+        }
+        spec->subsystem_major = atoi( major );
+    }
+    free( str );
 }
 
 /* cleanup on program exit */
@@ -135,15 +146,15 @@
 "    -K FLAGS                Compiler flags (only -KPIC is supported)\n"
 "    -l --library=LIB        Import the specified library\n"
 "    -L --library-path=DIR   Look for imports libraries in DIR\n"
-"    -m --exe-mode=MODE      Set the executable mode (cui|gui|cuiw|guiw)\n"
 "    -M --main-module=MODULE Set the name of the main module for a Win16 dll\n"
 "    -N --dll-name=DLLNAME   Set the DLL name (default: from input file name)\n"
 "    -o --output=NAME        Set the output file name (default: stdout)\n"
 "    -r --res=RSRC.RES       Load resources from RSRC.RES\n"
+"       --subsystem=SUBSYS   Set the subsystem (one of native, windows, console)\n"
 "       --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"
@@ -153,12 +164,13 @@
 
 enum long_options_values
 {
-    LONG_OPT_SPEC = 1,
+    LONG_OPT_DLL = 1,
     LONG_OPT_DEF,
     LONG_OPT_EXE,
     LONG_OPT_DEBUG,
     LONG_OPT_RELAY16,
     LONG_OPT_RELAY32,
+    LONG_OPT_SUBSYSTEM,
     LONG_OPT_VERSION
 };
 
@@ -166,12 +178,13 @@
 
 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 },
+    { "subsystem",1, 0, LONG_OPT_SUBSYSTEM },
     { "version",  0, 0, LONG_OPT_VERSION },
     /* aliases for short options */
     { "source-dir",    1, 0, 'C' },
@@ -184,7 +197,6 @@
     { "kill-at",       0, 0, 'k' },
     { "library",       1, 0, 'l' },
     { "library-path",  1, 0, 'L' },
-    { "exe-mode",      1, 0, 'm' },
     { "main-module",   1, 0, 'M' },
     { "dll-name",      1, 0, 'N' },
     { "output",        1, 0, 'o' },
@@ -206,7 +218,7 @@
 }
 
 /* parse options from the argv array and remove all the recognized ones */
-static char **parse_options( int argc, char **argv )
+static char **parse_options( int argc, char **argv, DLLSPEC *spec )
 {
     char *p;
     int optc;
@@ -222,14 +234,14 @@
             /* ignored */
             break;
         case 'F':
-            dll_file_name = xstrdup( optarg );
+            spec->file_name = xstrdup( optarg );
             break;
         case 'H':
             if (!isdigit(optarg[0]))
                 fatal_error( "Expected number argument with -H option instead of '%s'\n", optarg );
-            DLLHeapSize = atoi(optarg);
-            if (DLLHeapSize > 65535)
-                fatal_error( "Invalid heap size %d, maximum is 65535\n", DLLHeapSize );
+            spec->heap_size = atoi(optarg);
+            if (spec->heap_size > 65535)
+                fatal_error( "Invalid heap size %d, maximum is 65535\n", spec->heap_size );
             break;
         case 'I':
             /* ignored */
@@ -242,18 +254,18 @@
             lib_path[nb_lib_paths++] = xstrdup( optarg );
             break;
         case 'M':
-            owner_name = xstrdup( optarg );
-            SpecType = SPEC_WIN16;
+            spec->owner_name = xstrdup( optarg );
+            spec->type = SPEC_WIN16;
             break;
         case 'N':
-            dll_name = xstrdup( optarg );
+            spec->dll_name = xstrdup( optarg );
             break;
         case 'd':
             add_import_dll( optarg, 1 );
             break;
         case 'e':
-            init_func = xstrdup( optarg );
-            if ((p = strchr( init_func, '@' ))) *p = 0;  /* kill stdcall decoration */
+            spec->init_func = xstrdup( optarg );
+            if ((p = strchr( spec->init_func, '@' ))) *p = 0;  /* kill stdcall decoration */
             break;
         case 'f':
             if (!strcmp( optarg, "PIC") || !strcmp( optarg, "pic")) UsePIC = 1;
@@ -280,13 +292,6 @@
         case 'l':
             add_import_dll( optarg, 0 );
             break;
-        case 'm':
-            if (!strcmp( optarg, "gui" )) SpecMode = SPEC_MODE_GUIEXE;
-            else if (!strcmp( optarg, "cui" )) SpecMode = SPEC_MODE_CUIEXE;
-            else if (!strcmp( optarg, "guiw" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE;
-            else if (!strcmp( optarg, "cuiw" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE;
-            else usage(1);
-            break;
         case 'o':
             if (unlink( optarg ) == -1 && errno != ENOENT)
                 fatal_error( "Unable to create output file '%s'\n", optarg );
@@ -302,24 +307,24 @@
         case 'w':
             display_warnings = 1;
             break;
-        case LONG_OPT_SPEC:
-            set_exec_mode( MODE_SPEC );
-            input_file = open_input_file( NULL, optarg );
-            set_dll_file_name( 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 );
-            set_dll_file_name( optarg );
+            spec_file_name = xstrdup( optarg );
+            set_dll_file_name( optarg, spec );
             break;
         case LONG_OPT_EXE:
             set_exec_mode( MODE_EXE );
             if ((p = strrchr( optarg, '/' ))) p++;
             else p = optarg;
-            dll_file_name = xmalloc( strlen(p) + 5 );
-            strcpy( dll_file_name, p );
-            if (!strchr( dll_file_name, '.' )) strcat( dll_file_name, ".exe" );
-            if (SpecMode == SPEC_MODE_DLL) SpecMode = SPEC_MODE_GUIEXE;
+            spec->file_name = xmalloc( strlen(p) + 5 );
+            strcpy( spec->file_name, p );
+            if (!strchr( spec->file_name, '.' )) strcat( spec->file_name, ".exe" );
+            if (!spec->subsystem) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
             break;
         case LONG_OPT_DEBUG:
             set_exec_mode( MODE_DEBUG );
@@ -330,6 +335,9 @@
         case LONG_OPT_RELAY32:
             set_exec_mode( MODE_RELAY32 );
             break;
+        case LONG_OPT_SUBSYSTEM:
+            set_subsystem( optarg, spec );
+            break;
         case LONG_OPT_VERSION:
             printf( "winebuild version " PACKAGE_VERSION "\n" );
             exit(0);
@@ -343,28 +351,28 @@
 
 
 /* load all specified resource files */
-static void load_resources( char *argv[] )
+static void load_resources( char *argv[], DLLSPEC *spec )
 {
     int i;
     char **ptr, **last;
 
-    switch (SpecType)
+    switch (spec->type)
     {
     case SPEC_WIN16:
-        for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i] );
+        for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i], spec );
         break;
 
     case SPEC_WIN32:
         for (i = 0; i < nb_res_files; i++)
         {
-            if (!load_res32_file( res_files[i] ))
+            if (!load_res32_file( res_files[i], spec ))
                 fatal_error( "%s is not a valid Win32 resource file\n", res_files[i] );
         }
 
         /* load any resource file found in the remaining arguments */
         for (ptr = last = argv; *ptr; ptr++)
         {
-            if (!load_res32_file( *ptr ))
+            if (!load_res32_file( *ptr, spec ))
                 *last++ = *ptr; /* not a resource file, keep it in the list */
         }
         *last = NULL;
@@ -372,67 +380,67 @@
     }
 }
 
+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 = alloc_dll_spec();
+
     output_file = stdout;
-    argv = parse_options( argc, argv );
+    argv = parse_options( argc, argv, spec );
 
     switch(exec_mode)
     {
-    case MODE_SPEC:
-        load_resources( argv );
-        if (!ParseTopLevel( input_file )) break;
-        switch (SpecType)
+    case MODE_DLL:
+        spec->characteristics |= IMAGE_FILE_DLL;
+        load_resources( argv, spec );
+        if (!parse_input_file( spec )) break;
+        switch (spec->type)
         {
             case SPEC_WIN16:
-#if defined(__REACTOS__)
                 fatal_error( "Win16 specs are not supported in ReactOS version of winebuild\n" );
-#else
-                if (argv[0])
-                    fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
-                BuildSpec16File( output_file );
-#endif
                 break;
             case SPEC_WIN32:
                 read_undef_symbols( argv );
-                BuildSpec32File( output_file );
+                BuildSpec32File( output_file, spec );
                 break;
             default: assert(0);
         }
         break;
     case MODE_EXE:
-        if (SpecType == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
-        load_resources( argv );
+        if (spec->type == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
+        load_resources( argv, spec );
         read_undef_symbols( argv );
-        BuildSpec32File( output_file );
+        BuildSpec32File( output_file, spec );
         break;
     case MODE_DEF:
         if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
-        if (SpecType == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
-        if (!ParseTopLevel( input_file )) break;
-        BuildDef32File( output_file );
+        if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
+        if (!parse_input_file( spec )) break;
+        BuildDef32File( output_file, spec );
         break;
     case MODE_DEBUG:
         BuildDebugFile( output_file, current_src_dir, argv );
         break;
     case MODE_RELAY16:
-#if defined(__REACTOS__)
         fatal_error( "Win16 relays are not supported in ReactOS version of winebuild\n" );
-#else
-        if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
-        BuildRelays16( output_file );
-#endif
         break;
     case MODE_RELAY32:
-#if defined(__REACTOS__)
         fatal_error( "Win32 relays are not supported in ReactOS version of winebuild\n" );
-#else
-        if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
-        BuildRelays32( output_file );
-#endif
         break;
     default:
         usage(1);

reactos/tools/winebuild
parser.c 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- parser.c	4 Jan 2004 15:50:41 -0000	1.2
+++ parser.c	23 Sep 2004 20:27:30 -0000	1.3
@@ -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
  *
@@ -32,12 +32,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#ifdef WIN32
 #include "windef.h"
 #include "winbase.h"
-#else
-#include "winglue.h"
-#endif
 #include "build.h"
 
 int current_line = 0;
@@ -47,6 +43,9 @@
 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 */
@@ -67,7 +66,6 @@
     "ret64",       /* FLAG_RET64 */
     "i386",        /* FLAG_I386 */
     "register",    /* FLAG_REGISTER */
-    "interrupt",   /* FLAG_INTERRUPT */
     "private",     /* FLAG_PRIVATE */
     NULL
 };
@@ -80,7 +78,12 @@
 
 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 */
@@ -113,7 +116,7 @@
         else break;
     }
 
-    if ((*p == '\0') || (*p == '#'))
+    if ((*p == '\0') || is_token_comment(*p))
     {
         if (!allow_eol) error( "Declaration not terminated properly\n" );
         return NULL;
@@ -138,12 +141,23 @@
 }
 
 
+static ORDDEF *add_entry_point( DLLSPEC *spec )
+{
+    if (spec->nb_entry_points == spec->alloc_entry_points)
+    {
+        spec->alloc_entry_points += 128;
+        spec->entry_points = xrealloc( spec->entry_points,
+                                       spec->alloc_entry_points * sizeof(*spec->entry_points) );
+    }
+    return &spec->entry_points[spec->nb_entry_points++];
+}
+
 /*******************************************************************
- *         ParseVariable
+ *         parse_spec_variable
  *
- * Parse a variable definition.
+ * Parse a variable definition in a .spec file.
  */
-static int ParseVariable( ORDDEF *odp )
+static int parse_spec_variable( ORDDEF *odp, DLLSPEC *spec )
 {
     char *endptr;
     int *value_array;
@@ -151,7 +165,7 @@
     int value_array_size;
     const char *token;
 
-    if (SpecType == SPEC_WIN32)
+    if (spec->type == SPEC_WIN32)
     {
         error( "'variable' not supported in Win32, use 'extern' instead\n" );
         return 0;
@@ -201,16 +215,16 @@
 
 
 /*******************************************************************
- *         ParseExportFunction
+ *         parse_spec_export
  *
- * Parse a function definition.
+ * Parse an exported function definition in a .spec file.
  */
-static int ParseExportFunction( ORDDEF *odp )
+static int parse_spec_export( ORDDEF *odp, DLLSPEC *spec )
 {
     const char *token;
     unsigned int i;
 
-    switch(SpecType)
+    switch(spec->type)
     {
     case SPEC_WIN16:
         if (odp->type == TYPE_STDCALL)
@@ -225,11 +239,6 @@
             error( "'pascal' not supported for Win32\n" );
             return 0;
         }
-        if (odp->flags & FLAG_INTERRUPT)
-        {
-            error( "'interrupt' not supported for Win32\n" );
-            return 0;
-        }
         break;
     default:
         break;
@@ -273,7 +282,7 @@
             return 0;
         }
 
-        if (SpecType == SPEC_WIN32)
+        if (spec->type == SPEC_WIN32)
         {
             if (strcmp(token, "long") &&
                 strcmp(token, "ptr") &&
@@ -310,7 +319,7 @@
         odp->link_name = xstrdup( token );
         if (strchr( odp->link_name, '.' ))
         {
-            if (SpecType == SPEC_WIN16)
+            if (spec->type == SPEC_WIN16)
             {
                 error( "Forwarded functions not supported for Win16\n" );
                 return 0;
@@ -323,17 +332,17 @@
 
 
 /*******************************************************************
- *         ParseEquate
+ *         parse_spec_equate
  *
- * Parse an 'equate' definition.
+ * Parse an 'equate' definition in a .spec file.
  */
-static int ParseEquate( ORDDEF *odp )
+static int parse_spec_equate( ORDDEF *odp, DLLSPEC *spec )
 {
     char *endptr;
     int value;
     const char *token;
 
-    if (SpecType == SPEC_WIN32)
+    if (spec->type == SPEC_WIN32)
     {
         error( "'equate' not supported for Win32\n" );
         return 0;
@@ -351,11 +360,11 @@
 
 
 /*******************************************************************
- *         ParseStub
+ *         parse_spec_stub
  *
- * Parse a 'stub' definition.
+ * Parse a 'stub' definition in a .spec file
  */
-static int ParseStub( ORDDEF *odp )
+static int parse_spec_stub( ORDDEF *odp, DLLSPEC *spec )
 {
     odp->u.func.arg_types[0] = '\0';
     odp->link_name = xstrdup("");
@@ -364,15 +373,15 @@
 
 
 /*******************************************************************
- *         ParseExtern
+ *         parse_spec_extern
  *
- * Parse an 'extern' definition.
+ * Parse an 'extern' definition in a .spec file.
  */
-static int ParseExtern( ORDDEF *odp )
+static int parse_spec_extern( ORDDEF *odp, DLLSPEC *spec )
 {
     const char *token;
 
-    if (SpecType == SPEC_WIN16)
+    if (spec->type == SPEC_WIN16)
     {
         error( "'extern' not supported for Win16, use 'variable' instead\n" );
         return 0;
@@ -396,11 +405,11 @@
 
 
 /*******************************************************************
- *         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;
@@ -422,32 +431,18 @@
     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)
+static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
 {
     const char *token;
 
-    ORDDEF *odp = xmalloc( sizeof(*odp) );
+    ORDDEF *odp = add_entry_point( spec );
     memset( odp, 0, sizeof(*odp) );
-    EntryPoints[nb_entry_points++] = odp;
 
     if (!(token = GetToken(0))) goto error;
 
@@ -462,32 +457,31 @@
     }
 
     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 );
     odp->lineno = current_line;
     odp->ordinal = ordinal;
 
     switch(odp->type)
     {
     case TYPE_VARIABLE:
-        if (!ParseVariable( odp )) 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 )) goto error;
+        if (!parse_spec_export( odp, spec )) goto error;
         break;
     case TYPE_ABS:
-        if (!ParseEquate( odp )) goto error;
+        if (!parse_spec_equate( odp, spec )) goto error;
         break;
     case TYPE_STUB:
-        if (!ParseStub( odp )) goto error;
+        if (!parse_spec_stub( odp, spec )) goto error;
         break;
     case TYPE_EXTERN:
-        if (!ParseExtern( odp )) goto error;
+        if (!parse_spec_extern( odp, spec )) goto error;
         break;
     default:
         assert( 0 );
@@ -497,8 +491,7 @@
     if (odp->flags & FLAG_I386)
     {
         /* ignore this entry point on non-Intel archs */
-        EntryPoints[--nb_entry_points] = NULL;
-        free( odp );
+        spec->nb_entry_points--;
         return 1;
     }
 #endif
@@ -515,15 +508,20 @@
             error( "Ordinal number %d too large\n", ordinal );
             goto error;
         }
-        if (ordinal > Limit) Limit = ordinal;
-        if (ordinal < Base) Base = ordinal;
+        if (ordinal > spec->limit) spec->limit = ordinal;
+        if (ordinal < spec->base) spec->base = ordinal;
         odp->ordinal = ordinal;
-        if (Ordinals[ordinal])
+    }
+
+    if (odp->type == TYPE_STDCALL && !(odp->flags & FLAG_PRIVATE))
+    {
+        if (!strcmp( odp->name, "DllRegisterServer" ) ||
+            !strcmp( odp->name, "DllUnregisterServer" ) ||
+            !strcmp( odp->name, "DllGetClassObject" ) ||
+            !strcmp( odp->name, "DllCanUnloadNow" ))
         {
-            error( "Duplicate ordinal %d\n", ordinal );
-            goto error;
+            warning( "Function %s should be marked private\n", odp->name );
         }
-        Ordinals[ordinal] = odp;
     }
 
     if (!strcmp( odp->name, "@" ) || odp->flags & FLAG_NONAME)
@@ -533,7 +531,7 @@
             error( "Nameless function needs an explicit ordinal number\n" );
             goto error;
         }
-        if (SpecType != SPEC_WIN32)
+        if (spec->type != SPEC_WIN32)
         {
             error( "Nameless functions not supported for Win16\n" );
             goto error;
@@ -542,79 +540,135 @@
         else odp->export_name = odp->name;
         odp->name = NULL;
     }
-    else Names[nb_names++] = odp;
     return 1;
 
 error:
-    EntryPoints[--nb_entry_points] = NULL;
+    spec->nb_entry_points--;
     free( odp->name );
-    free( odp );
     return 0;
 }
 
 
 static int name_compare( const void *name1, const void *name2 )
 {
-    ORDDEF *odp1 = *(ORDDEF **)name1;
-    ORDDEF *odp2 = *(ORDDEF **)name2;
+    const ORDDEF *odp1 = *(const ORDDEF * const *)name1;
+    const ORDDEF *odp2 = *(const ORDDEF * const *)name2;
     return strcmp( odp1->name, odp2->name );
 }
 
 /*******************************************************************
- *         sort_names
+ *         assign_names
  *
- * Sort the name array and catch duplicates.
+ * Build the name array and catch duplicates.
  */
-static void sort_names(void)
+static void assign_names( DLLSPEC *spec )
 {
-    int i;
+    int i, j;
 
-    if (!nb_names) return;
+    spec->nb_names = 0;
+    for (i = 0; i < spec->nb_entry_points; i++)
+        if (spec->entry_points[i].name) spec->nb_names++;
+    if (!spec->nb_names) return;
+
+    spec->names = xmalloc( spec->nb_names * sizeof(spec->names[0]) );
+    for (i = j = 0; i < spec->nb_entry_points; i++)
+        if (spec->entry_points[i].name) spec->names[j++] = &spec->entry_points[i];
 
     /* sort the list of names */
-    qsort( Names, nb_names, sizeof(Names[0]), name_compare );
+    qsort( spec->names, spec->nb_names, sizeof(spec->names[0]), name_compare );
 
     /* check for duplicate names */
-    for (i = 0; i < nb_names - 1; i++)
+    for (i = 0; i < spec->nb_names - 1; i++)
     {
-        if (!strcmp( Names[i]->name, Names[i+1]->name ))
+        if (!strcmp( spec->names[i]->name, spec->names[i+1]->name ))
         {
-            current_line = max( Names[i]->lineno, Names[i+1]->lineno );
+            current_line = max( spec->names[i]->lineno, spec->names[i+1]->lineno );
             error( "'%s' redefined\n%s:%d: First defined here\n",
-                   Names[i]->name, input_file_name,
-                   min( Names[i]->lineno, Names[i+1]->lineno ) );
+                   spec->names[i]->name, input_file_name,
+                   min( spec->names[i]->lineno, spec->names[i+1]->lineno ) );
+        }
+    }
+}
+
+/*******************************************************************
+ *         assign_ordinals
+ *
+ * Build the ordinal array.
+ */
+static void assign_ordinals( DLLSPEC *spec )
+{
+    int i, count, ordinal;
+
+    /* start assigning from base, or from 1 if no ordinal defined yet */
+    if (spec->base == MAX_ORDINALS) spec->base = 1;
+    if (spec->limit < spec->base) spec->limit = spec->base;
+
+    count = max( spec->limit + 1, spec->base + spec->nb_entry_points );
+    spec->ordinals = xmalloc( count * sizeof(spec->ordinals[0]) );
+    memset( spec->ordinals, 0, count * sizeof(spec->ordinals[0]) );
+
+    /* fill in all explicitly specified ordinals */
+    for (i = 0; i < spec->nb_entry_points; i++)
+    {
+        ordinal = spec->entry_points[i].ordinal;
+        if (ordinal == -1) continue;
+        if (spec->ordinals[ordinal])
+        {
+            current_line = max( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno );
+            error( "ordinal %d redefined\n%s:%d: First defined here\n",
+                   ordinal, input_file_name,
+                   min( spec->entry_points[i].lineno, spec->ordinals[ordinal]->lineno ) );
         }
+        else spec->ordinals[ordinal] = &spec->entry_points[i];
     }
+
+    /* now assign ordinals to the rest */
+    for (i = 0, ordinal = spec->base; i < spec->nb_names; i++)
+    {
+        if (spec->names[i]->ordinal != -1) continue;  /* already has an ordinal */
+        while (spec->ordinals[ordinal]) ordinal++;
+        if (ordinal >= MAX_ORDINALS)
+        {
+            current_line = spec->names[i]->lineno;
+            fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
+        }
+        spec->names[i]->ordinal = ordinal;
+        spec->ordinals[ordinal] = spec->names[i];
+    }
+    if (ordinal > spec->limit) spec->limit = ordinal;
 }
 
 
 /*******************************************************************
- *         ParseTopLevel
+ *         parse_spec_file
  *
- * Parse a spec file.
+ * Parse a .spec file.
  */
-int ParseTopLevel( FILE *file )
+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;
         if (strcmp(token, "@") == 0)
         {
-            if (SpecType != SPEC_WIN32)
+            if (spec->type != SPEC_WIN32)
             {
                 error( "'@' ordinals not supported for Win16\n" );
                 continue;
             }
-            if (!ParseOrdinal( -1 )) continue;
+            if (!parse_spec_ordinal( -1, spec )) continue;
         }
         else if (IsNumberString(token))
         {
-            if (!ParseOrdinal( atoi(token) )) continue;
+            if (!parse_spec_ordinal( atoi(token), spec )) continue;
         }
         else
         {
@@ -625,7 +679,245 @@
     }
 
     current_line = 0;  /* no longer parsing the input file */
-    sort_names();
+    assign_names( spec );
+    assign_ordinals( spec );
+    return !nb_errors;
+}
+
+
+/*******************************************************************
+ *         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;
 }
 

reactos/tools/winebuild
relay.c 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- relay.c	9 Dec 2003 18:44:25 -0000	1.1
+++ relay.c	23 Sep 2004 20:27:30 -0000	1.2
@@ -32,25 +32,22 @@
 
 #include "build.h"
 
-#if defined(__GNUC__) && !defined(__svr4__)
-static const int use_stabs = 1;
-#else
-static const int use_stabs = 0;
-#endif
-
 #ifdef __i386__
 
 static void function_header( FILE *outfile, const char *name )
 {
     fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
-    if (use_stabs)
-        fprintf( outfile, "\t.stabs \"%s:F1\",36,0,0," __ASM_NAME("%s") "\n", name, name);
     fprintf( outfile, "\t" __ASM_FUNC("%s") "\n", name );
     fprintf( outfile, "\t.globl " __ASM_NAME("%s") "\n", name );
     fprintf( outfile, __ASM_NAME("%s") ":\n", name );
 }
 
 
+static void function_footer( FILE *outfile, const char *name )
+{
+    fprintf( outfile, ".size " __ASM_NAME("%s") ", . - " __ASM_NAME("%s") "\n", name, name );
+}
+
 /*******************************************************************
  *         BuildCallFrom16Core
  *
@@ -444,6 +441,10 @@
         /* Return to return stub which will return to caller */
         fprintf( outfile, "\tlret $12\n" );
     }
+    if (thunk) function_footer( outfile, "__wine_call_from_16_thunk" );
+    else if (reg_func) function_footer( outfile, "__wine_call_from_16_regs" );
+    else if (short_ret) function_footer( outfile, "__wine_call_from_16_word" );
+    else function_footer( outfile, "__wine_call_from_16_long" );
 }
 
 
@@ -605,6 +606,9 @@
     /* Jump to the called routine */
     fprintf( outfile, "\t.byte 0x66\n" );
     fprintf( outfile, "\tlret\n" );
+
+    /* Function footer */
+    function_footer( outfile, name );
 }
 
 
@@ -648,6 +652,9 @@
 
     fprintf( outfile, "\tlret\n" );
 
+    /* Function footer */
+    function_footer( outfile, "CallTo16_Ret" );
+
     /* Declare the return address and data selector variables */
 
     fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
@@ -756,9 +763,6 @@
     /* Function header */
 
     fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
-    if (use_stabs)
-        fprintf( outfile, ".stabs \"CALL32_%s:F1\",36,0,0," __ASM_NAME("CALL32_%s") "\n",
-                 name, name );
     fprintf( outfile, "\t.globl " __ASM_NAME("CALL32_%s") "\n", name );
     fprintf( outfile, __ASM_NAME("CALL32_%s") ":\n", name );
 
@@ -882,6 +886,7 @@
     fprintf( outfile, "\tpopl %%edi\n" );
     fprintf( outfile, "\tpopl %%ebp\n" );
     fprintf( outfile, "\tret\n" );
+    fprintf( outfile, ".size " __ASM_NAME("CALL32_%s") ", . - " __ASM_NAME("CALL32_%s") "\n", name, name );
 }
 
 static void BuildCallTo32CBClientRet( FILE *outfile, BOOL isEx )
@@ -907,6 +912,8 @@
     }
     fprintf( outfile, "\tlret\n" );
 
+    fprintf( outfile, ".size " __ASM_NAME("CALL32_%s_Ret") ", . - " __ASM_NAME("CALL32_%s_Ret") "\n", name, name );
+
     /* Declare the return address variable */
 
     fprintf( outfile, "\n\t.globl " __ASM_NAME("CALL32_%s_RetAddr") "\n", name );
@@ -1036,10 +1043,65 @@
 
     fprintf( outfile, "\tpopl %%ds\n" );
     fprintf( outfile, "\tiret\n" );
+    function_footer( outfile, "__wine_call_from_32_regs" );
 
     function_header( outfile, "__wine_call_from_32_restore_regs" );
     fprintf( outfile, "\tleal 4(%%esp),%%ecx\n" );
     fprintf( outfile, "\tjmp 2b\n" );
+    function_footer( outfile, "__wine_call_from_32_restore_regs" );
+}
+
+
+/*******************************************************************
+ *         BuildPendingEventCheck
+ *
+ * Build a function that checks whether there are any
+ * pending DPMI events.
+ *
+ * Stack layout:
+ *   
+ * (sp+12) long   eflags
+ * (sp+6)  long   cs
+ * (sp+2)  long   ip
+ * (sp)    word   fs
+ *
+ * On entry to function, fs register points to a valid TEB.
+ * On exit from function, stack will be popped.
+ */
+static void BuildPendingEventCheck( FILE *outfile )
+{
+    /* Function header */
+
+    function_header( outfile, "DPMI_PendingEventCheck" );
+
+    /* Check for pending events. */
+    
+    fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", 
+             STRUCTOFFSET(TEB,vm86_pending) );
+    fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
+
+    fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", 
+             STRUCTOFFSET(TEB,dpmi_vif) );
+
+    fprintf( outfile, "\tje " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
+
+    /* Process pending events. */
+
+    fprintf( outfile, "\tsti\n" );
+   
+    /* Start cleanup. Restore fs register. */
+
+    fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Cleanup") "\n" );
+    fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Cleanup") ":\n" );
+    fprintf( outfile, "\tpopw %%fs\n" );
+
+    /* Return from function. */
+
+    fprintf( outfile, ".globl " __ASM_NAME("DPMI_PendingEventCheck_Return") "\n" );
+    fprintf( outfile, __ASM_NAME("DPMI_PendingEventCheck_Return") ":\n" );
+    fprintf( outfile, "\tiret\n" );
+
+    function_footer( outfile, "DPMI_PendingEventCheck" );
 }
 
 
@@ -1050,26 +1112,12 @@
  */
 void BuildRelays16( FILE *outfile )
 {
-    char buffer[1024];
-
     /* File header */
 
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
 
-    if (output_file_name && use_stabs)
-    {
-        getcwd(buffer, sizeof(buffer));
-        fprintf( outfile, "\t.file\t\"%s\"\n", output_file_name );
-
-        /*
-         * The stabs help the internal debugger as they are an indication that it
-         * is sensible to step into a thunk/trampoline.
-         */
-        fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
-        fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", output_file_name );
-        fprintf( outfile, "Code_Start:\n\n" );
-    }
+    fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_16") ":\n\n" );
 
     fprintf( outfile, __ASM_NAME("Call16_Start") ":\n" );
     fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Start") "\n" );
@@ -1101,24 +1149,11 @@
 
     fprintf( outfile, __ASM_NAME("Call16_End") ":\n" );
     fprintf( outfile, "\t.globl " __ASM_NAME("Call16_End") "\n" );
-
-    if (use_stabs)
-    {
-        fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
-        fprintf( outfile, ".Letext:\n");
-
-        /* Some versions of gdb need to have the filename data for
-           each section, so output it again for the data section. */
-        if (output_file_name)
-        {
-            fprintf( outfile, ".stabs \"%s/\",100,0,0,Data_Start\n", buffer);
-            fprintf( outfile, ".stabs \"%s\",100,0,0,Data_Start\n", output_file_name );
-            fprintf( outfile, "Data_Start:\n\n" );
-        }
-    }
+    fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_16") ",. - " __ASM_NAME("__wine_spec_thunk_text_16") "\n" );
 
     /* The whole Call16_Ret segment must lie within the .data section */
     fprintf( outfile, "\n\t.data\n" );
+    fprintf( outfile, __ASM_NAME("__wine_spec_thunk_data_16") ":\n\n" );
     fprintf( outfile, "\t.globl " __ASM_NAME("Call16_Ret_Start") "\n" );
     fprintf( outfile, __ASM_NAME("Call16_Ret_Start") ":\n" );
 
@@ -1131,9 +1166,13 @@
     /* CBClientThunkSLEx return stub */
     BuildCallTo32CBClientRet( outfile, TRUE  );
 
+    /* Pending DPMI events check stub */
+    BuildPendingEventCheck( outfile );
+
     /* End of Call16_Ret segment */
     fprintf( outfile, "\n\t.globl " __ASM_NAME("Call16_Ret_End") "\n" );
     fprintf( outfile, __ASM_NAME("Call16_Ret_End") ":\n" );
+    fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_data_16") ",. - " __ASM_NAME("__wine_spec_thunk_data_16") "\n" );
 }
 
 /*******************************************************************
@@ -1147,30 +1186,12 @@
 
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
-
-    if (output_file_name && use_stabs)
-    {
-        char buffer[1024];
-        getcwd(buffer, sizeof(buffer));
-        fprintf( outfile, "\t.file\t\"%s\"\n", output_file_name );
-
-        /*
-         * The stabs help the internal debugger as they are an indication that it
-         * is sensible to step into a thunk/trampoline.
-         */
-        fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
-        fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", output_file_name );
-        fprintf( outfile, "Code_Start:\n\n" );
-    }
+    fprintf( outfile, __ASM_NAME("__wine_spec_thunk_text_32") ":\n\n" );
 
     /* 32-bit register entry point */
     BuildCallFrom32Regs( outfile );
 
-    if (use_stabs)
-    {
-        fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
-        fprintf( outfile, ".Letext:\n");
-    }
+    fprintf( outfile, "\t.size " __ASM_NAME("__wine_spec_thunk_text_32") ",. - " __ASM_NAME("__wine_spec_thunk_text_32") "\n" );
 }
 
 #else /* __i386__ */

reactos/tools/winebuild
res16.c 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- res16.c	4 Jan 2004 15:50:41 -0000	1.2
+++ res16.c	23 Sep 2004 20:27:30 -0000	1.3
@@ -37,12 +37,8 @@
 #include <sys/mman.h>
 #endif
 
-#ifdef WIN32
 #include "windef.h"
 #include "winbase.h"
-#else
-#include "winglue.h"
-#endif
 #include "build.h"
 
 #define ALIGNMENT 2 /* alignment for resource data */
@@ -73,28 +69,29 @@
     unsigned int             nb_names;     /* total number of names */
 };
 
-static struct resource *resources;
-static int nb_resources;
-
-static struct res_type *res_types;
-static int nb_types;     /* total number of types */
+/* top level of the resource tree */
+struct res_tree
+{
+    struct res_type *types;                /* types array */
+    unsigned int     nb_types;             /* total number of types */
+};
 
 static const unsigned char *file_pos;   /* current position in resource file */
 static const unsigned char *file_end;   /* end of resource file */
 static const char *file_name;  /* current resource file name */
 
 
-inline static struct resource *add_resource(void)
+inline static struct resource *add_resource( DLLSPEC *spec )
 {
-    resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) );
-    return &resources[nb_resources++];
+    spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(*spec->resources) );
+    return &spec->resources[spec->nb_resources++];
 }
 
-static struct res_type *add_type( const struct resource *res )
+static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
 {
     struct res_type *type;
-    res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) );
-    type = &res_types[nb_types++];
+    tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
+    type = &tree->types[tree->nb_types++];
     type->type        = &res->type;
     type->res         = res;
     type->nb_names    = 0;
@@ -155,9 +152,9 @@
 }
 
 /* load the next resource from the current file */
-static void load_next_resource(void)
+static void load_next_resource( DLLSPEC *spec )
 {
-    struct resource *res = add_resource();
+    struct resource *res = add_resource( spec );
 
     get_string( &res->type );
     get_string( &res->name );
@@ -169,7 +166,7 @@
 }
 
 /* load a Win16 .res file */
-void load_res16_file( const char *name )
+void load_res16_file( const char *name, DLLSPEC *spec )
 {
     int fd;
     void *base;
@@ -190,7 +187,7 @@
     file_name = name;
     file_pos  = base;
     file_end  = file_pos + st.st_size;
-    while (file_pos < file_end) load_next_resource();
+    while (file_pos < file_end) load_next_resource( spec );
 }
 
 /* compare two strings/ids */
@@ -218,19 +215,32 @@
 }
 
 /* build the 2-level (type,name) resource tree */
-static void build_resource_tree(void)
+static struct res_tree *build_resource_tree( DLLSPEC *spec )
 {
     int i;
+    struct res_tree *tree;
     struct res_type *type = NULL;
 
-    qsort( resources, nb_resources, sizeof(*resources), cmp_res );
+    qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
 
-    for (i = 0; i < nb_resources; i++)
+    tree = xmalloc( sizeof(*tree) );
+    tree->types = NULL;
+    tree->nb_types = 0;
+
+    for (i = 0; i < spec->nb_resources; i++)
     {
-        if (!i || cmp_string( &resources[i].type, &resources[i-1].type ))  /* new type */
-            type = add_type( &resources[i] );
+        if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type ))  /* new type */
+            type = add_type( tree, &spec->resources[i] );
         type->nb_names++;
     }
+    return tree;
+}
+
+/* free the resource tree */
+static void free_resource_tree( struct res_tree *tree )
+{
+    free( tree->types );
+    free( tree );
 }
 
 inline static void put_byte( unsigned char **buffer, unsigned char val )
@@ -258,19 +268,19 @@
 }
 
 /* output the resource data */
-int output_res16_data( FILE *outfile )
+int output_res16_data( FILE *outfile, DLLSPEC *spec )
 {
     const struct resource *res;
     unsigned char *buffer, *p;
     int i, total;
 
-    if (!nb_resources) return 0;
+    if (!spec->nb_resources) return 0;
 
-    for (i = total = 0, res = resources; i < nb_resources; i++, res++)
+    for (i = total = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
         total += (res->data_size + ALIGN_MASK) & ~ALIGN_MASK;
 
     buffer = p = xmalloc( total );
-    for (i = 0, res = resources; i < nb_resources; i++, res++)
+    for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
     {
         memcpy( p, res->data, res->data_size );
         p += res->data_size;
@@ -282,25 +292,26 @@
 }
 
 /* output the resource definitions */
-int output_res16_directory( unsigned char *buffer )
+int output_res16_directory( unsigned char *buffer, DLLSPEC *spec )
 {
     int i, offset, res_offset = 0;
     unsigned int j;
+    struct res_tree *tree;
     const struct res_type *type;
     const struct resource *res;
     unsigned char *start = buffer;
 
-    build_resource_tree();
+    tree = build_resource_tree( spec );
 
     offset = 4;  /* alignment + terminator */
-    offset += nb_types * 8;  /* typeinfo structures */
-    offset += nb_resources * 12;  /* nameinfo structures */
+    offset += tree->nb_types * 8;  /* typeinfo structures */
+    offset += spec->nb_resources * 12;  /* nameinfo structures */
 
     put_word( &buffer, ALIGNMENT );
 
     /* type and name structures */
 
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
         if (type->type->str)
         {
@@ -335,7 +346,7 @@
 
     /* name strings */
 
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
         if (type->type->str) output_string( &buffer, type->type->str );
         for (j = 0, res = type->res; j < type->nb_names; j++, res++)
@@ -346,5 +357,6 @@
     put_byte( &buffer, 0 );  /* names terminator */
     if ((buffer - start) & 1) put_byte( &buffer, 0 );  /* align on word boundary */
 
+    free_resource_tree( tree );
     return buffer - start;
 }

reactos/tools/winebuild
res32.c 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- res32.c	4 Jan 2004 15:50:41 -0000	1.2
+++ res32.c	23 Sep 2004 20:27:30 -0000	1.3
@@ -37,12 +37,8 @@
 #include <sys/mman.h>
 #endif
 
-#ifdef WIN32
 #include "windef.h"
 #include "winbase.h"
-#else
-#include "winglue.h"
-#endif
 #include "build.h"
 
 /* Unicode string or integer id */
@@ -68,6 +64,7 @@
     const struct string_id  *name;         /* name */
     const struct resource   *res;          /* resource */
     int                      nb_languages; /* number of languages */
+    unsigned int             name_offset;  /* offset of name in resource dir */
 };
 
 /* type level of the resource tree */
@@ -77,24 +74,28 @@
     struct res_name         *names;        /* names array */
     unsigned int             nb_names;     /* total number of names */
     unsigned int             nb_id_names;  /* number of names that have a numeric id */
+    unsigned int             name_offset;  /* offset of type name in resource dir */
 };
 
-static struct resource *resources;
-static int nb_resources;
-
-static struct res_type *res_types;
-static int nb_types;     /* total number of types */
-static int nb_id_types;  /* number of types that have a numeric id */
+/* top level of the resource tree */
+struct res_tree
+{
+    struct res_type *types;                /* types array */
+    unsigned int     nb_types;             /* total number of types */
+};
 
 static const unsigned char *file_pos;   /* current position in resource file */
 static const unsigned char *file_end;   /* end of resource file */
 static const char *file_name;  /* current resource file name */
 
+/* size of a resource directory with n entries */
+#define RESDIR_SIZE(n)  ((4 + 2 * (n)) * sizeof(int))
 
-inline static struct resource *add_resource(void)
+
+inline static struct resource *add_resource( DLLSPEC *spec )
 {
-    resources = xrealloc( resources, (nb_resources + 1) * sizeof(*resources) );
-    return &resources[nb_resources++];
+    spec->resources = xrealloc( spec->resources, (spec->nb_resources + 1) * sizeof(spec->resources[0]) );
+    return &spec->resources[spec->nb_resources++];
 }
 
 static inline unsigned int strlenW( const WCHAR *str )
@@ -122,23 +123,22 @@
     return name;
 }
 
-static struct res_type *add_type( const struct resource *res )
+static struct res_type *add_type( struct res_tree *tree, const struct resource *res )
 {
     struct res_type *type;
-    res_types = xrealloc( res_types, (nb_types + 1) * sizeof(*res_types) );
-    type = &res_types[nb_types++];
+    tree->types = xrealloc( tree->types, (tree->nb_types + 1) * sizeof(*tree->types) );
+    type = &tree->types[tree->nb_types++];
     type->type        = &res->type;
     type->names       = NULL;
     type->nb_names    = 0;
     type->nb_id_names = 0;
-    if (!type->type->str) nb_id_types++;
     return type;
 }
 
 /* get the next word from the current resource file */
 static WORD get_word(void)
 {
-    WORD ret = *(WORD *)file_pos;
+    WORD ret = *(const WORD *)file_pos;
     file_pos += sizeof(WORD);
     if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
     return ret;
@@ -147,7 +147,7 @@
 /* get the next dword from the current resource file */
 static DWORD get_dword(void)
 {
-    DWORD ret = *(DWORD *)file_pos;
+    DWORD ret = *(const DWORD *)file_pos;
     file_pos += sizeof(DWORD);
     if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
     return ret;
@@ -156,7 +156,7 @@
 /* get a string from the current resource file */
 static void get_string( struct string_id *str )
 {
-    if (*(WCHAR *)file_pos == 0xffff)
+    if (*(const WCHAR *)file_pos == 0xffff)
     {
         get_word();  /* skip the 0xffff */
         str->str = NULL;
@@ -164,7 +164,7 @@
     }
     else
     {
-        WCHAR *p = xmalloc( (strlenW((WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
+        WCHAR *p = xmalloc( (strlenW((const WCHAR*)file_pos) + 1) * sizeof(WCHAR) );
         str->str = p;
         str->id  = 0;
         while ((*p++ = get_word()));
@@ -188,10 +188,10 @@
 }
 
 /* load the next resource from the current file */
-static void load_next_resource(void)
+static void load_next_resource( DLLSPEC *spec )
 {
     DWORD hdr_size;
-    struct resource *res = add_resource();
+    struct resource *res = add_resource( spec );
 
     res->data_size = (get_dword() + 3) & ~3;
     hdr_size = get_dword();
@@ -207,12 +207,12 @@
     get_dword();                        /* skip version */
     get_dword();                        /* skip characteristics */
 
-    file_pos = (char *)res->data + res->data_size;
+    file_pos = (const char *)res->data + res->data_size;
     if (file_pos > file_end) fatal_error( "%s is a truncated file\n", file_name );
 }
 
 /* load a Win32 .res file */
-int load_res32_file( const char *name )
+int load_res32_file( const char *name, DLLSPEC *spec )
 {
     int fd, ret;
     void *base;
@@ -235,7 +235,7 @@
     file_end  = file_pos + st.st_size;
     if ((ret = check_header()))
     {
-        while (file_pos < file_end) load_next_resource();
+        while (file_pos < file_end) load_next_resource( spec );
     }
     close( fd );
     return ret;
@@ -267,27 +267,43 @@
 }
 
 /* build the 3-level (type,name,language) resource tree */
-static void build_resource_tree(void)
+static struct res_tree *build_resource_tree( DLLSPEC *spec )
 {
     int i;
+    struct res_tree *tree;
     struct res_type *type = NULL;
     struct res_name *name = NULL;
 
-    qsort( resources, nb_resources, sizeof(*resources), cmp_res );
+    qsort( spec->resources, spec->nb_resources, sizeof(*spec->resources), cmp_res );
+
+    tree = xmalloc( sizeof(*tree) );
+    tree->types = NULL;
+    tree->nb_types = 0;
 
-    for (i = 0; i < nb_resources; i++)
+    for (i = 0; i < spec->nb_resources; i++)
     {
-        if (!i || cmp_string( &resources[i].type, &resources[i-1].type ))  /* new type */
+        if (!i || cmp_string( &spec->resources[i].type, &spec->resources[i-1].type ))  /* new type */
         {
-            type = add_type( &resources[i] );
-            name = add_name( type, &resources[i] );
+            type = add_type( tree, &spec->resources[i] );
+            name = add_name( type, &spec->resources[i] );
         }
-        else if (cmp_string( &resources[i].name, &resources[i-1].name )) /* new name */
+        else if (cmp_string( &spec->resources[i].name, &spec->resources[i-1].name )) /* new name */
         {
-            name = add_name( type, &resources[i] );
+            name = add_name( type, &spec->resources[i] );
         }
         else name->nb_languages++;
     }
+    return tree;
+}
+
+/* free the resource tree */
+static void free_resource_tree( struct res_tree *tree )
+{
+    int i;
+
+    for (i = 0; i < tree->nb_types; i++) free( tree->types[i].names );
+    free( tree->types );
+    free( tree );
 }
 
 /* output a Unicode string */
@@ -302,21 +318,22 @@
 }
 
 /* output the resource definitions */
-int output_resources( FILE *outfile )
+void output_resources( FILE *outfile, DLLSPEC *spec )
 {
-    int i, j, k;
-    unsigned int n;
-    const struct res_type *type;
-    const struct res_name *name;
+    int i, j, k, nb_id_types;
+    unsigned int n, offset, data_offset;
+    struct res_tree *tree;
+    struct res_type *type;
+    struct res_name *name;
     const struct resource *res;
 
-    if (!nb_resources) return 0;
+    if (!spec->nb_resources) return;
 
-    build_resource_tree();
+    tree = build_resource_tree( spec );
 
     /* resource data */
 
-    for (i = 0, res = resources; i < nb_resources; i++, res++)
+    for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
     {
         const unsigned int *p = res->data;
         int size = res->data_size / 4;
@@ -348,69 +365,86 @@
 
     /* resource directory definition */
 
-    fprintf( outfile, "#define OFFSETOF(field) ((char*)&((struct res_struct *)0)->field - (char*)((struct res_struct *) 0))\n" );
     fprintf( outfile, "static struct res_struct{\n" );
     fprintf( outfile, "  struct res_dir        type_dir;\n" );
-    fprintf( outfile, "  struct res_dir_entry  type_entries[%d];\n", nb_types );
+    fprintf( outfile, "  struct res_dir_entry  type_entries[%d];\n", tree->nb_types );
+    offset = RESDIR_SIZE( tree->nb_types );
 
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
+        offset += RESDIR_SIZE( type->nb_names );
         fprintf( outfile, "  struct res_dir        name_%d_dir;\n", i );
         fprintf( outfile, "  struct res_dir_entry  name_%d_entries[%d];\n", i, type->nb_names );
         for (n = 0, name = type->names; n < type->nb_names; n++, name++)
         {
+            offset += RESDIR_SIZE( name->nb_languages );
             fprintf( outfile, "  struct res_dir        lang_%d_%d_dir;\n", i, n );
             fprintf( outfile, "  struct res_dir_entry  lang_%d_%d_entries[%d];\n",
                      i, n, name->nb_languages );
         }
     }
 
-    fprintf( outfile, "  struct res_data_entry data_entries[%d];\n", nb_resources );
+    fprintf( outfile, "  struct res_data_entry data_entries[%d];\n", spec->nb_resources );
+    offset += spec->nb_resources * 4 * sizeof(int);
 
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = nb_id_types = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
         if (type->type->str)
+        {
+            type->name_offset = offset | 0x80000000;
+            offset += (strlenW(type->type->str)+1) * sizeof(unsigned short);
             fprintf( outfile, "  unsigned short        type_%d_name[%d];\n",
                      i, strlenW(type->type->str)+1 );
+        }
+        else
+        {
+            type->name_offset = type->type->id;
+            nb_id_types++;
+        }
+
         for (n = 0, name = type->names; n < type->nb_names; n++, name++)
         {
             if (name->name->str)
+            {
+                name->name_offset = offset | 0x80000000;
+                offset += (strlenW(name->name->str)+1) * sizeof(unsigned short);
                 fprintf( outfile, "  unsigned short        name_%d_%d_name[%d];\n",
                          i, n, strlenW(name->name->str)+1 );
+            }
+            else name->name_offset = name->name->id;
         }
     }
 
     /* resource directory contents */
 
     fprintf( outfile, "} resources = {\n" );
-    fprintf( outfile, "  { 0, 0, 0, 0, %d, %d },\n", nb_types - nb_id_types, nb_id_types );
+    fprintf( outfile, "  { 0, 0, 0, 0, %d, %d },\n", tree->nb_types - nb_id_types, nb_id_types );
 
     /* dump the type directory */
+    offset = RESDIR_SIZE( tree->nb_types );
     fprintf( outfile, "  {\n" );
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
-        if (!type->type->str)
-            fprintf( outfile, "    { 0x%04x, OFFSETOF(name_%d_dir) | 0x80000000 },\n",
-                     type->type->id, i );
-        else
-            fprintf( outfile, "    { OFFSETOF(type_%d_name) | 0x80000000, OFFSETOF(name_%d_dir) | 0x80000000 },\n",
-                     i, i );
+        fprintf( outfile, "    { 0x%08x, 0x%08x },\n", type->name_offset, offset | 0x80000000 );
+        offset += RESDIR_SIZE( type->nb_names );
+        for (n = 0, name = type->names; n < type->nb_names; n++, name++)
+            offset += RESDIR_SIZE( name->nb_languages );
     }
     fprintf( outfile, "  },\n" );
 
+    data_offset = offset;
+    offset = RESDIR_SIZE( tree->nb_types );
+
     /* dump the names and languages directories */
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
         fprintf( outfile, "  { 0, 0, 0, 0, %d, %d }, /* name_%d_dir */\n  {\n",
                  type->nb_names - type->nb_id_names, type->nb_id_names, i );
+        offset += RESDIR_SIZE( type->nb_names );
         for (n = 0, name = type->names; n < type->nb_names; n++, name++)
         {
-            if (!name->name->str)
-                fprintf( outfile, "    { 0x%04x, OFFSETOF(lang_%d_%d_dir) | 0x80000000 },\n",
-                         name->name->id, i, n );
-            else
-                fprintf( outfile, "    { OFFSETOF(name_%d_%d_name) | 0x80000000, OFFSETOF(lang_%d_%d_dir) | 0x80000000 },\n",
-                         i, n, i, n );
+            fprintf( outfile, "    { 0x%08x, 0x%08x },\n", name->name_offset, offset | 0x80000000 );
+            offset += RESDIR_SIZE( name->nb_languages );
         }
         fprintf( outfile, "  },\n" );
 
@@ -420,8 +454,8 @@
                      name->nb_languages, i, n );
             for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
             {
-                fprintf( outfile, "    { 0x%04x, OFFSETOF(data_entries[%d]) },\n",
-                         res->lang, res - resources );
+                fprintf( outfile, "    { 0x%04x, 0x%08x },\n",
+                         res->lang, data_offset + (res - spec->resources) * 4 * sizeof(int) );
             }
             fprintf( outfile, "  },\n" );
         }
@@ -429,13 +463,14 @@
 
     /* dump the resource data entries */
     fprintf( outfile, "  {\n" );
-    for (i = 0, res = resources; i < nb_resources; i++, res++)
+    for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
     {
-        fprintf( outfile, "    { res_%d, sizeof(res_%d), 0, 0 },\n", i, i );
+        fprintf( outfile, "    { res_%d, sizeof(res_%d), 0, 0 }, /* %08x */\n", i, i,
+                 data_offset + i * 4 * sizeof(int) );
     }
 
     /* dump the name strings */
-    for (i = 0, type = res_types; i < nb_types; i++, type++)
+    for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
     {
         if (type->type->str)
         {
@@ -451,6 +486,6 @@
             }
         }
     }
-    fprintf( outfile, "  }\n};\n#undef OFFSETOF\n\n" );
-    return nb_resources;
+    fprintf( outfile, "  }\n};\n\n" );
+    free_resource_tree( tree );
 }

reactos/tools/winebuild
spec16.c 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- spec16.c	9 Dec 2003 18:44:25 -0000	1.1
+++ spec16.c	23 Sep 2004 20:27:30 -0000	1.2
@@ -111,7 +111,7 @@
  * as a byte stream into the assembly code.
  */
 static int BuildModule16( FILE *outfile, int max_code_offset,
-                          int max_data_offset )
+                          int max_data_offset, DLLSPEC *spec )
 {
     int i;
     char *buffer;
@@ -142,7 +142,7 @@
     pModule->next = 0;
     pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
     pModule->dgroup = 2;
-    pModule->heap_size = DLLHeapSize;
+    pModule->heap_size = spec->heap_size;
     pModule->stack_size = 0;
     pModule->ip = 0;
     pModule->cs = 0;
@@ -172,8 +172,8 @@
     pModule->fileinfo = (int)pFileInfo - (int)pModule;
     memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
     pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
-                        + strlen(dll_file_name);
-    strcpy( pFileInfo->szPathName, dll_file_name );
+                        + strlen(spec->file_name);
+    strcpy( pFileInfo->szPathName, spec->file_name );
     pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
 
       /* Segment table */
@@ -201,7 +201,7 @@
     pstr = (char *)pSegment;
     pstr = (char *)(((long)pstr + 3) & ~3);
     pModule->res_table = (int)pstr - (int)pModule;
-    pstr += output_res16_directory( pstr );
+    pstr += output_res16_directory( pstr, spec );
 
       /* Imported names table */
 
@@ -215,16 +215,16 @@
     pstr = (char *)(((long)pstr + 3) & ~3);
     pModule->name_table = (int)pstr - (int)pModule;
     /* First entry is module name */
-    *pstr = strlen( dll_name );
-    strcpy( pstr + 1, dll_name );
+    *pstr = strlen( spec->dll_name );
+    strcpy( pstr + 1, spec->dll_name );
     strupper( pstr + 1 );
     pstr += *pstr + 1;
     *pstr++ = 0;
     *pstr++ = 0;
     /* Store all ordinals */
-    for (i = 1; i <= Limit; i++)
+    for (i = 1; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         WORD ord = i;
         if (!odp || !odp->name[0]) continue;
         *pstr = strlen( odp->name );
@@ -240,10 +240,10 @@
 
     pstr = (char *)(((long)pstr + 3) & ~3);
     pModule->entry_table = (int)pstr - (int)pModule;
-    for (i = 1; i <= Limit; i++)
+    for (i = 1; i <= spec->limit; i++)
     {
         int selector = 0;
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp) continue;
 
 	switch (odp->type)
@@ -317,8 +317,6 @@
  *  extern LONG WINAPI PREFIX_CallFrom16_C_long_xxx( FARPROC func, LPBYTE args );
  *  extern void WINAPI PREFIX_CallFrom16_C_regs_xxx( FARPROC func, LPBYTE args,
  *                                                   CONTEXT86 *context );
- *  extern void WINAPI PREFIX_CallFrom16_C_intr_xxx( FARPROC func, LPBYTE args,
- *                                                   CONTEXT86 *context );
  *
  * where 'C' is the calling convention ('p' for pascal or 'c' for cdecl),
  * and each 'x' is an argument  ('w'=word, 's'=signed word, 'l'=long,
@@ -333,10 +331,6 @@
  * For register functions, the arguments (if present) are converted just
  * the same as for normal functions, but in addition the CONTEXT86 pointer
  * filled with the current register values is passed to the 32-bit routine.
- * (An 'intr' interrupt handler routine is treated exactly like a register
- * routine, except that upon return, the flags word pushed onto the stack
- * by the interrupt is removed by the 16-bit call stub.)
- *
  */
 static void BuildCallFrom16Func( FILE *outfile, const char *profile, const char *prefix )
 {
@@ -360,7 +354,6 @@
 
     if (!strncmp( "word_", profile + 2, 5 )) short_ret = 1;
     else if (!strncmp( "regs_", profile + 2, 5 )) reg_func = 1;
-    else if (!strncmp( "intr_", profile + 2, 5 )) reg_func = 2;
     else if (strncmp( "long_", profile + 2, 5 ))
     {
         fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
@@ -467,7 +460,6 @@
              (odp->type == TYPE_PASCAL) ? "p" :
              (odp->type == TYPE_VARARGS) ? "v" : "c",
              (odp->flags & FLAG_REGISTER) ? "regs" :
-             (odp->flags & FLAG_INTERRUPT) ? "intr" :
              (odp->flags & FLAG_RET16) ? "word" : "long",
              odp->u.func.arg_types );
     return buffer;
@@ -479,8 +471,8 @@
  */
 static int Spec16TypeCompare( const void *e1, const void *e2 )
 {
-    const ORDDEF *odp1 = *(const ORDDEF **)e1;
-    const ORDDEF *odp2 = *(const ORDDEF **)e2;
+    const ORDDEF *odp1 = *(const ORDDEF * const *)e1;
+    const ORDDEF *odp2 = *(const ORDDEF * const *)e2;
     int retval;
     int type1 = odp1->type;
     int type2 = odp2->type;
@@ -490,8 +482,8 @@
 
     if ((retval = type1 - type2) != 0) return retval;
 
-    type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT);
-    type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER|FLAG_INTERRUPT);
+    type1 = odp1->flags & (FLAG_RET16|FLAG_REGISTER);
+    type2 = odp2->flags & (FLAG_RET16|FLAG_REGISTER);
 
     if ((retval = type1 - type2) != 0) return retval;
 
@@ -504,14 +496,14 @@
  *
  * Output the functions for stub entry points
 */
-static void output_stub_funcs( FILE *outfile )
+static void output_stub_funcs( FILE *outfile, const DLLSPEC *spec )
 {
     int i;
     char *p;
 
-    for (i = 0; i <= Limit; i++)
+    for (i = 0; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp || odp->type != TYPE_STUB) continue;
         fprintf( outfile, "#ifdef __GNUC__\n" );
         fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
@@ -528,7 +520,7 @@
         fprintf( outfile, "  rec.flags   = %d;\n", EH_NONCONTINUABLE );
         fprintf( outfile, "  rec.rec     = 0;\n" );
         fprintf( outfile, "  rec.params  = 2;\n" );
-        fprintf( outfile, "  rec.info[0] = \"%s\";\n", dll_file_name );
+        fprintf( outfile, "  rec.info[0] = \"%s\";\n", spec->file_name );
         fprintf( outfile, "  rec.info[1] = func;\n" );
         fprintf( outfile, "#ifdef __GNUC__\n" );
         fprintf( outfile, "  rec.addr = __builtin_return_address(1);\n" );
@@ -538,9 +530,9 @@
         fprintf( outfile, "  for (;;) RtlRaiseException( &rec );\n}\n\n" );
         break;
     }
-    for (i = 0; i <= Limit; i++)
+    for (i = 0; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp || odp->type != TYPE_STUB) continue;
         odp->link_name = xrealloc( odp->link_name, strlen(odp->name) + 13 );
         strcpy( odp->link_name, "__wine_stub_" );
@@ -557,7 +549,7 @@
  *
  * Build a Win16 assembly file from a spec file.
  */
-void BuildSpec16File( FILE *outfile )
+void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
 {
     ORDDEF **type, **typelist;
     int i, nFuncs, nTypes;
@@ -580,22 +572,22 @@
     memset( data, 0, 16 );
     data_offset = 16;
 
-    if (!dll_name)  /* set default name from file name */
+    if (!spec->dll_name)  /* set default name from file name */
     {
         char *p;
-        dll_name = xstrdup( dll_file_name );
-        if ((p = strrchr( dll_name, '.' ))) *p = 0;
+        spec->dll_name = xstrdup( spec->file_name );
+        if ((p = strrchr( spec->dll_name, '.' ))) *p = 0;
     }
 
-    output_stub_funcs( outfile );
+    output_stub_funcs( outfile, spec );
 
     /* Build sorted list of all argument types, without duplicates */
 
-    typelist = (ORDDEF **)calloc( Limit+1, sizeof(ORDDEF *) );
+    typelist = (ORDDEF **)calloc( spec->limit+1, sizeof(ORDDEF *) );
 
-    for (i = nFuncs = 0; i <= Limit; i++)
+    for (i = nFuncs = 0; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp) continue;
         switch (odp->type)
         {
@@ -627,15 +619,15 @@
         char profile[101];
 
         strcpy( profile, get_function_name( typelist[i] ));
-        BuildCallFrom16Func( outfile, profile, dll_file_name );
+        BuildCallFrom16Func( outfile, profile, spec->file_name );
     }
 #endif
 
     /* Output the DLL functions prototypes */
 
-    for (i = 0; i <= Limit; i++)
+    for (i = 0; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp) continue;
         switch(odp->type)
         {
@@ -701,8 +693,6 @@
                     break;
                 }
 
-        if (typelist[i]->flags & FLAG_INTERRUPT) argsize += 2;
-
         /* build the arg types bit fields */
         arg_types[0] = arg_types[1] = 0;
         for (j = 0; typelist[i]->u.func.arg_types[j]; j++)
@@ -719,13 +709,13 @@
             }
             arg_types[j / 10] |= type << (3 * (j % 10));
         }
-        if (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) arg_types[0] |= ARG_REGISTER;
+        if (typelist[i]->flags & FLAG_REGISTER) arg_types[0] |= ARG_REGISTER;
         if (typelist[i]->flags & FLAG_RET16) arg_types[0] |= ARG_RET16;
 
 #ifdef __i386__
         fprintf( outfile, "    { 0x68, __wine_%s_CallFrom16_%s, 0x9a, __wine_call_from_16_%s,\n",
-                 make_c_identifier(dll_file_name), profile,
-                 (typelist[i]->flags & (FLAG_REGISTER|FLAG_INTERRUPT)) ? "regs":
+                 make_c_identifier(spec->file_name), profile,
+                 (typelist[i]->flags & FLAG_REGISTER) ? "regs":
                  (typelist[i]->flags & FLAG_RET16) ? "word" : "long" );
         if (argsize)
             fprintf( outfile, "      0x%04x, 0xca66, %d, { 0x%08x, 0x%08x } },\n",
@@ -745,9 +735,9 @@
     }
     fprintf( outfile, "  },\n  {\n" );
 
-    for (i = 0; i <= Limit; i++)
+    for (i = 0; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp) continue;
         switch (odp->type)
         {
@@ -767,7 +757,7 @@
             type = bsearch( &odp, typelist, nTypes, sizeof(ORDDEF *), Spec16TypeCompare );
             assert( type );
 
-            fprintf( outfile, "    /* %s.%d */ ", dll_name, i );
+            fprintf( outfile, "    /* %s.%d */ ", spec->dll_name, i );
 #ifdef __i386__
             fprintf( outfile, "{ 0x5566, 0x68, %s, 0xe866, %d  /* %s */ },\n",
 #else
@@ -797,8 +787,8 @@
 
     /* Build the module */
 
-    module_size = BuildModule16( outfile, code_offset, data_offset );
-    res_size = output_res16_data( outfile );
+    module_size = BuildModule16( outfile, code_offset, data_offset, spec );
+    res_size = output_res16_data( outfile, spec );
 
     /* Output the DLL descriptor */
 
@@ -816,14 +806,14 @@
     fprintf( outfile, "    sizeof(Module),\n" );
     fprintf( outfile, "    &code_segment,\n" );
     fprintf( outfile, "    Data_Segment,\n" );
-    fprintf( outfile, "    \"%s\",\n", owner_name );
+    fprintf( outfile, "    \"%s\",\n", spec->owner_name );
     fprintf( outfile, "    %s\n", res_size ? "resource_data" : "0" );
     fprintf( outfile, "};\n" );
 
     /* Output the DLL constructor */
 
-    sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) );
-    sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(dll_file_name) );
+    sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(spec->file_name) );
+    sprintf( destructor, "__wine_spec_%s_fini", make_c_identifier(spec->file_name) );
     output_dll_init( outfile, constructor, destructor );
 
     fprintf( outfile,

reactos/tools/winebuild
spec32.c 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- spec32.c	18 Jan 2004 13:42:57 -0000	1.5
+++ spec32.c	23 Sep 2004 20:27:30 -0000	1.6
@@ -61,48 +61,42 @@
  *
  * Generate an internal name for an entry point. Used for stubs etc.
  */
-static const char *make_internal_name( const ORDDEF *odp, const char *prefix )
+static const char *make_internal_name( const ORDDEF *odp, DLLSPEC *spec, const char *prefix )
 {
     static char buffer[256];
     if (odp->name || odp->export_name)
     {
         char *p;
-        sprintf( buffer, "__wine_%s_%s_%s", prefix, dll_file_name,
+        sprintf( buffer, "__wine_%s_%s_%s", prefix, spec->file_name,
                  odp->name ? odp->name : odp->export_name );
         /* make sure name is a legal C identifier */
         for (p = buffer; *p; p++) if (!isalnum(*p) && *p != '_') break;
         if (!*p) return buffer;
     }
-    sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(dll_file_name), odp->ordinal );
+    sprintf( buffer, "__wine_%s_%s_%d", prefix, make_c_identifier(spec->file_name), odp->ordinal );
     return buffer;
 }
 
 /*******************************************************************
- *         AssignOrdinals
+ *         declare_weak_function
  *
- * Assign ordinals to all entry points.
+ * Output a prototype for a weak function.
  */
-static void AssignOrdinals(void)
+static void declare_weak_function( FILE *outfile, const char *ret_type, const char *name, const char *params)
 {
-    int i, ordinal;
-
-    if ( !nb_names ) return;
-
-    /* start assigning from Base, or from 1 if no ordinal defined yet */
-    if (Base == MAX_ORDINALS) Base = 1;
-    for (i = 0, ordinal = Base; i < nb_names; i++)
-    {
-        if (Names[i]->ordinal != -1) continue;  /* already has an ordinal */
-        while (Ordinals[ordinal]) ordinal++;
-        if (ordinal >= MAX_ORDINALS)
-        {
-            current_line = Names[i]->lineno;
-            fatal_error( "Too many functions defined (max %d)\n", MAX_ORDINALS );
-        }
-        Names[i]->ordinal = ordinal;
-        Ordinals[ordinal] = Names[i];
-    }
-    if (ordinal > Limit) Limit = ordinal;
+    fprintf( outfile, "#ifdef __GNUC__\n" );
+    fprintf( outfile, "# ifdef __APPLE__\n" );
+    fprintf( outfile, "extern %s %s(%s) __attribute__((weak_import));\n", ret_type, name, params );
+    fprintf( outfile, "static %s (*__wine_spec_weak_%s)(%s) = %s;\n", ret_type, name, params, name );
+    fprintf( outfile, "#define %s __wine_spec_weak_%s\n", name, name );
+    fprintf( outfile, "# else\n" );
+    fprintf( outfile, "extern %s %s(%s) __attribute__((weak));\n", ret_type, name, params );
+    fprintf( outfile, "# endif\n" );
+    fprintf( outfile, "#else\n" );
+    fprintf( outfile, "extern %s %s(%s);\n", ret_type, name, params );
+    fprintf( outfile, "static void __asm__dummy_%s(void)", name );
+    fprintf( outfile, " { asm(\".weak " __ASM_NAME("%s") "\"); }\n", name );
+    fprintf( outfile, "#endif\n\n" );
 }
 
 
@@ -140,7 +134,7 @@
  *
  * Output the export table for a Win32 module.
  */
-static int output_exports( FILE *outfile, int nr_exports )
+static int output_exports( FILE *outfile, int nr_exports, DLLSPEC *spec )
 {
     int i, fwd_size = 0, total_size = 0;
 
@@ -156,11 +150,11 @@
     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* TimeDateStamp */
     fprintf( outfile, "    \"\\t.long 0\\n\"\n" );                 /* MajorVersion/MinorVersion */
     fprintf( outfile, "    \"\\t.long __wine_spec_exp_names\\n\"\n" ); /* Name */
-    fprintf( outfile, "    \"\\t.long %d\\n\"\n", Base );          /* Base */
-    fprintf( outfile, "    \"\\t.long %d\\n\"\n", nr_exports );    /* NumberOfFunctions */
-    fprintf( outfile, "    \"\\t.long %d\\n\"\n", nb_names );      /* NumberOfNames */
+    fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->base );        /* Base */
+    fprintf( outfile, "    \"\\t.long %d\\n\"\n", nr_exports );        /* NumberOfFunctions */
+    fprintf( outfile, "    \"\\t.long %d\\n\"\n", spec->nb_names );    /* NumberOfNames */
     fprintf( outfile, "    \"\\t.long __wine_spec_exports_funcs\\n\"\n" ); /* AddressOfFunctions */
-    if (nb_names)
+    if (spec->nb_names)
     {
         fprintf( outfile, "    \"\\t.long __wine_spec_exp_name_ptrs\\n\"\n" );     /* AddressOfNames */
         fprintf( outfile, "    \"\\t.long __wine_spec_exp_ordinals\\n\"\n" );  /* AddressOfNameOrdinals */
@@ -175,9 +169,9 @@
     /* output the function pointers */
 
     fprintf( outfile, "    \"__wine_spec_exports_funcs:\\n\"\n" );
-    for (i = Base; i <= Limit; i++)
+    for (i = spec->base; i <= spec->limit; i++)
     {
-        ORDDEF *odp = Ordinals[i];
+        ORDDEF *odp = spec->ordinals[i];
         if (!odp) fprintf( outfile, "    \"\\t.long 0\\n\"\n" );
         else switch(odp->type)
         {
@@ -188,7 +182,8 @@
             if (!(odp->flags & FLAG_FORWARD))
             {
                 fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
-                         (odp->flags & FLAG_REGISTER) ? make_internal_name(odp,"regs") : odp->link_name );
+                         (odp->flags & FLAG_REGISTER) ? make_internal_name( odp, spec, "regs" )
+                         : odp->link_name );
             }
             else
             {
@@ -197,49 +192,51 @@
             }
             break;
         case TYPE_STUB:
-            fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n", make_internal_name( odp, "stub" ) );
+            fprintf( outfile, "    \"\\t.long " __ASM_NAME("%s") "\\n\"\n",
+                     make_internal_name( odp, spec, "stub" ) );
             break;
         default:
             assert(0);
         }
     }
-    total_size += (Limit - Base + 1) * sizeof(int);
+    total_size += (spec->limit - spec->base + 1) * sizeof(int);
 
-    if (nb_names)
+    if (spec->nb_names)
     {
         /* output the function name pointers */
 
-        int namepos = strlen(dll_file_name) + 1;
+        int namepos = strlen(spec->file_name) + 1;
 
         fprintf( outfile, "    \"__wine_spec_exp_name_ptrs:\\n\"\n" );
-        for (i = 0; i < nb_names; i++)
+        for (i = 0; i < spec->nb_names; i++)
         {
             fprintf( outfile, "    \"\\t.long __wine_spec_exp_names+%d\\n\"\n", namepos );
-            namepos += strlen(Names[i]->name) + 1;
+            namepos += strlen(spec->names[i]->name) + 1;
         }
-        total_size += nb_names * sizeof(int);
+        total_size += spec->nb_names * sizeof(int);
     }
 
     /* output the function names */
 
     fprintf( outfile, "    \"\\t.text\\n\"\n" );
     fprintf( outfile, "    \"__wine_spec_exp_names:\\n\"\n" );
-    fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", dll_file_name );
-    for (i = 0; i < nb_names; i++)
-        fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", Names[i]->name );
+    fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->file_name );
+    for (i = 0; i < spec->nb_names; i++)
+        fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", spec->names[i]->name );
     fprintf( outfile, "    \"\\t.data\\n\"\n" );
 
-    if (nb_names)
+    if (spec->nb_names)
     {
         /* output the function ordinals */
 
         fprintf( outfile, "    \"__wine_spec_exp_ordinals:\\n\"\n" );
-        for (i = 0; i < nb_names; i++)
+        for (i = 0; i < spec->nb_names; i++)
         {
-            fprintf( outfile, "    \"\\t" __ASM_SHORT " %d\\n\"\n", Names[i]->ordinal - Base );
+            fprintf( outfile, "    \"\\t" __ASM_SHORT " %d\\n\"\n",
+                     spec->names[i]->ordinal - spec->base );
         }
-        total_size += nb_names * sizeof(short);
-        if (nb_names % 2)
+        total_size += spec->nb_names * sizeof(short);
+        if (spec->nb_names % 2)
         {
             fprintf( outfile, "    \"\\t" __ASM_SHORT " 0\\n\"\n" );
             total_size += sizeof(short);
@@ -251,9 +248,9 @@
     if (fwd_size)
     {
         fprintf( outfile, "    \"__wine_spec_forwards:\\n\"\n" );
-        for (i = Base; i <= Limit; i++)
+        for (i = spec->base; i <= spec->limit; i++)
         {
-            ORDDEF *odp = Ordinals[i];
+            ORDDEF *odp = spec->ordinals[i];
             if (odp && (odp->flags & FLAG_FORWARD))
                 fprintf( outfile, "    \"\\t" __ASM_STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
         }
@@ -265,9 +262,9 @@
 
     if (debugging)
     {
-        for (i = Base; i <= Limit; i++)
+        for (i = spec->base; i <= spec->limit; i++)
         {
-            ORDDEF *odp = Ordinals[i];
+            ORDDEF *odp = spec->ordinals[i];
             unsigned int j, args, mask = 0;
             const char *name;
 
@@ -287,7 +284,7 @@
 
             name = odp->link_name;
             args = strlen(odp->u.func.arg_types) * sizeof(int);
-            if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, "regs" );
+            if (odp->flags & FLAG_REGISTER) name = make_internal_name( odp, spec, "regs" );
 
             switch(odp->type)
             {
@@ -325,13 +322,13 @@
  *
  * Output the functions for stub entry points
 */
-static void output_stub_funcs( FILE *outfile )
+static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
 {
     int i;
 
-    for (i = 0; i < nb_entry_points; i++)
+    for (i = 0; i < spec->nb_entry_points; i++)
     {
-        ORDDEF *odp = EntryPoints[i];
+        ORDDEF *odp = &spec->entry_points[i];
         if (odp->type != TYPE_STUB) continue;
         fprintf( outfile, "#ifdef __GNUC__\n" );
         fprintf( outfile, "static void __wine_unimplemented( const char *func ) __attribute__((noreturn));\n" );
@@ -349,7 +346,7 @@
         fprintf( outfile, "  rec.flags   = %d;\n", EH_NONCONTINUABLE );
         fprintf( outfile, "  rec.rec     = 0;\n" );
         fprintf( outfile, "  rec.params  = 2;\n" );
-        fprintf( outfile, "  rec.info[0] = \"%s\";\n", dll_file_name );
+        fprintf( outfile, "  rec.info[0] = \"%s\";\n", spec->file_name );
         fprintf( outfile, "  rec.info[1] = func;\n" );
         fprintf( outfile, "#ifdef __GNUC__\n" );
         fprintf( outfile, "  rec.addr = __builtin_return_address(1);\n" );
@@ -360,11 +357,11 @@
         break;
     }
 
-    for (i = 0; i < nb_entry_points; i++)
+    for (i = 0; i < spec->nb_entry_points; i++)
     {
-        ORDDEF *odp = EntryPoints[i];
+        const ORDDEF *odp = &spec->entry_points[i];
         if (odp->type != TYPE_STUB) continue;
-        fprintf( outfile, "void %s(void) ", make_internal_name( odp, "stub" ) );
+        fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
         if (odp->name)
             fprintf( outfile, "{ __wine_unimplemented(\"%s\"); }\n", odp->name );
         else if (odp->export_name)
@@ -380,18 +377,18 @@
  *
  * Output the functions for register entry points
  */
-static void output_register_funcs( FILE *outfile )
+static void output_register_funcs( FILE *outfile, DLLSPEC *spec )
 {
     const char *name;
     int i;
 
-    for (i = 0; i < nb_entry_points; i++)
+    for (i = 0; i < spec->nb_entry_points; i++)
     {
-        ORDDEF *odp = EntryPoints[i];
+        const ORDDEF *odp = &spec->entry_points[i];
         if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
         if (!(odp->flags & FLAG_REGISTER)) continue;
         if (odp->flags & FLAG_FORWARD) continue;
-        name = make_internal_name( odp, "regs" );
+        name = make_internal_name( odp, spec, "regs" );
         fprintf( outfile,
                  "asm(\".align %d\\n\\t\"\n"
                  "    \"" __ASM_FUNC("%s") "\\n\\t\"\n"
@@ -491,13 +488,12 @@
  *
  * Build a Win32 C file from a spec file.
  */
-void BuildSpec32File( FILE *outfile )
+void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
 {
     int exports_size = 0;
-    int nr_exports, nr_imports, nr_resources;
-    int characteristics, subsystem;
+    int nr_exports, nr_imports;
     DWORD page_size;
-    char constructor[100];
+    const char *init_func = spec->init_func;
 
 #ifdef HAVE_GETPAGESIZE
     page_size = getpagesize();
@@ -513,10 +509,8 @@
 #   error Cannot get the page size on this platform
 #endif
 
-    AssignOrdinals();
-    nr_exports = Base <= Limit ? Limit - Base + 1 : 0;
-
-    resolve_imports();
+    nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
+    resolve_imports( spec );
     output_standard_file_header( outfile );
 
     /* Reserve some space for the PE header */
@@ -535,7 +529,12 @@
     fprintf( outfile, "}\n" );
     fprintf( outfile, "#endif\n" );
 
+#ifdef __APPLE__
+    fprintf( outfile, "static char _end[4];\n" );
+#else
     fprintf( outfile, "extern char _end[];\n" );
+#endif
+    
     fprintf( outfile, "extern int __wine_spec_data_start[], __wine_spec_exports[];\n\n" );
 
 #ifdef __i386__
@@ -548,7 +547,7 @@
     {
         /* Output the stub functions */
 
-        output_stub_funcs( outfile );
+        output_stub_funcs( outfile, spec );
 
         fprintf( outfile, "#ifndef __GNUC__\n" );
         fprintf( outfile, "static void __asm__dummy(void) {\n" );
@@ -556,11 +555,11 @@
 
         /* Output code for all register functions */
 
-        output_register_funcs( outfile );
+        output_register_funcs( outfile, spec );
 
         /* Output the exports and relay entry points */
 
-        exports_size = output_exports( outfile, nr_exports );
+        exports_size = output_exports( outfile, nr_exports, spec );
 
         fprintf( outfile, "#ifndef __GNUC__\n" );
         fprintf( outfile, "}\n" );
@@ -569,86 +568,97 @@
 
     /* Output the DLL imports */
 
-    nr_imports = output_imports( outfile );
+    nr_imports = output_imports( outfile, spec );
 
     /* Output the resources */
 
-    nr_resources = output_resources( outfile );
+    output_resources( outfile, spec );
 
-    /* Output LibMain function */
+    /* Output the entry point function */
+
+    fprintf( outfile, "static int __wine_spec_init_state;\n" );
+    fprintf( outfile, "extern int __wine_main_argc;\n" );
+    fprintf( outfile, "extern char **__wine_main_argv;\n" );
+    fprintf( outfile, "extern char **__wine_main_environ;\n" );
+    fprintf( outfile, "extern unsigned short **__wine_main_wargv;\n" );
+#ifdef __APPLE__
+    fprintf( outfile, "extern _dyld_func_lookup(char *, void *);" );
+    fprintf( outfile, "static void __wine_spec_hidden_init(int argc, char** argv, char** envp)\n" );
+    fprintf( outfile, "{\n" );
+    fprintf( outfile, "    void (*init)(void);\n" );
+    fprintf( outfile, "    _dyld_func_lookup(\"__dyld_make_delayed_module_initializer_calls\", (unsigned long *)&init);\n" );
+    fprintf( outfile, "    init();\n" );
+    fprintf( outfile, "}\n" );
+    fprintf( outfile, "static void __wine_spec_hidden_fini()\n" );
+    fprintf( outfile, "{\n" );
+    fprintf( outfile, "    void (*fini)(void);\n" );
+    fprintf( outfile, "    _dyld_func_lookup(\"__dyld_mod_term_funcs\", (unsigned long *)&fini);\n" );
+    fprintf( outfile, "    fini();\n" );
+    fprintf( outfile, "}\n" );
+    fprintf( outfile, "#define _init __wine_spec_hidden_init\n" );
+    fprintf( outfile, "#define _fini __wine_spec_hidden_fini\n" );
+#else
+    fprintf( outfile, "extern void _init(int, char**, char**);\n" );
+    fprintf( outfile, "extern void _fini();\n" );
+#endif
 
-    characteristics = subsystem = 0;
-    switch(SpecMode)
+    if (spec->characteristics & IMAGE_FILE_DLL)
     {
-    case SPEC_MODE_DLL:
-        if (init_func) fprintf( outfile, "extern void %s();\n", init_func );
+        if (init_func)
+            fprintf( outfile, "extern int __stdcall %s( void*, unsigned int, void* );\n\n", init_func );
         else
         {
-            fprintf( outfile, "#ifdef __GNUC__\n" );
-            fprintf( outfile, "# ifdef __APPLE__\n" );
-            fprintf( outfile, "extern void DllMain() __attribute__((weak_import));\n" );
-            fprintf( outfile, "# else\n" );
-            fprintf( outfile, "extern void DllMain() __attribute__((weak));\n" );
-            fprintf( outfile, "# endif\n" );
-            fprintf( outfile, "#else\n" );
-            fprintf( outfile, "extern void DllMain();\n" );
-            fprintf( outfile, "static void __asm__dummy_dllmain(void)" );
-            fprintf( outfile, " { asm(\".weak " __ASM_NAME("DllMain") "\"); }\n" );
-            fprintf( outfile, "#endif\n" );
+            declare_weak_function( outfile, "int __stdcall", "DllMain", "void*, unsigned int, void*" );
+            init_func = "DllMain";
         }
-        characteristics = IMAGE_FILE_DLL;
-        break;
-    case SPEC_MODE_GUIEXE:
-        if (!init_func) init_func = "WinMain";
         fprintf( outfile,
-                 "\ntypedef struct {\n"
-                 "    unsigned int cb;\n"
-                 "    char *lpReserved, *lpDesktop, *lpTitle;\n"
-                 "    unsigned int dwX, dwY, dwXSize, dwYSize;\n"
-                 "    unsigned int dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags;\n"
-                 "    unsigned short wShowWindow, cbReserved2;\n"
-                 "    char *lpReserved2;\n"
-                 "    void *hStdInput, *hStdOutput, *hStdError;\n"
-                 "} STARTUPINFOA;\n"
-                 "int _ARGC;\n"
-                 "char **_ARGV;\n"
-                 "extern int __stdcall %s(void *,void *,char *,int);\n"
-                 "extern char * __stdcall GetCommandLineA(void);\n"
-                 "extern void * __stdcall GetModuleHandleA(char *);\n"
-                 "extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n"
-                 "extern void __stdcall ExitProcess(unsigned int);\n"
-                 "static void __wine_exe_main(void)\n"
+                 "static int __stdcall __wine_dll_main( void *inst, unsigned int reason, void *reserved )\n"
                  "{\n"
-                 "    extern int __wine_main_argc;\n"
-                 "    extern char **__wine_main_argv;\n"
-                 "    STARTUPINFOA info;\n"
-                 "    char *cmdline = GetCommandLineA();\n"
-                 "    int bcount=0, in_quotes=0;\n"
-                 "    while (*cmdline) {\n"
-                 "        if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
-                 "        else if (*cmdline=='\\\\') bcount++;\n"
-                 "        else if (*cmdline=='\\\"') {\n"
-                 "            if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
-                 "            bcount=0;\n"
-                 "        }\n"
-                 "        else bcount=0;\n"
-                 "        cmdline++;\n"
-                 "    }\n"
-                 "    while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
-                 "    GetStartupInfoA( &info );\n"
-                 "    if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
-                 "    _ARGC = __wine_main_argc;\n"
-                 "    _ARGV = __wine_main_argv;\n"
-                 "    ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
-                 "}\n\n", init_func, init_func );
-        init_func = "__wine_exe_main";
-        subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
+                 "    int ret;\n"
+                 "    if (reason == %d && __wine_spec_init_state == 1)\n"
+                 "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
+                 "    ret = %s ? %s( inst, reason, reserved ) : 1;\n"
+                 "    if (reason == %d && __wine_spec_init_state == 1) _fini();\n"
+                 "    return ret;\n"
+                 "}\n",
+                 DLL_PROCESS_ATTACH, init_func, init_func, DLL_PROCESS_DETACH );
+        init_func = "__wine_dll_main";
+    }
+    else switch(spec->subsystem)
+    {
+    case IMAGE_SUBSYSTEM_NATIVE:
+        if (init_func)
+            fprintf( outfile, "extern int __stdcall %s( void*, void* );\n\n", init_func );
+        else
+        {
+            declare_weak_function( outfile, "int __stdcall", "DriverEntry", "void*, void*");
+            init_func = "DriverEntry";
+        }
+        fprintf( outfile,
+                 "static int __stdcall __wine_driver_entry( void *obj, void *path )\n"
+                 "{\n"
+                 "    int ret;\n"
+                 "    if (__wine_spec_init_state == 1)\n"
+                 "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n"
+                 "    ret = %s ? %s( obj, path ) : 0;\n"
+                 "    if (__wine_spec_init_state == 1) _fini();\n"
+                 "    return ret;\n"
+                 "}\n",
+                 init_func, init_func );
+        init_func = "__wine_driver_entry";
         break;
-    case SPEC_MODE_GUIEXE_UNICODE:
-        if (!init_func) init_func = "WinMain";
+    case IMAGE_SUBSYSTEM_WINDOWS_GUI:
+    case IMAGE_SUBSYSTEM_WINDOWS_CUI:
+        if (init_func)
+            fprintf( outfile, "extern int %s( int argc, char *argv[] );\n", init_func );
+        else
+        {
+            declare_weak_function( outfile, "int", "main", "int argc, char *argv[]" );
+            declare_weak_function( outfile, "int", "wmain", "int argc, unsigned short *argv[]" );
+            declare_weak_function( outfile, "int __stdcall", "WinMain", "void *,void *,char *,int" );
+        }
         fprintf( outfile,
-                 "\ntypedef unsigned short WCHAR;\n"
-                 "typedef struct {\n"
+                 "\ntypedef struct {\n"
                  "    unsigned int cb;\n"
                  "    char *lpReserved, *lpDesktop, *lpTitle;\n"
                  "    unsigned int dwX, dwY, dwXSize, dwYSize;\n"
@@ -657,76 +667,46 @@
                  "    char *lpReserved2;\n"
                  "    void *hStdInput, *hStdOutput, *hStdError;\n"
                  "} STARTUPINFOA;\n"
-                 "int _ARGC;\n"
-                 "WCHAR **_ARGV;\n"
-                 "extern int __stdcall %s(void *,void *,char *,int);\n"
                  "extern char * __stdcall GetCommandLineA(void);\n"
                  "extern void * __stdcall GetModuleHandleA(char *);\n"
                  "extern void __stdcall GetStartupInfoA(STARTUPINFOA *);\n"
                  "extern void __stdcall ExitProcess(unsigned int);\n"
                  "static void __wine_exe_main(void)\n"
                  "{\n"
-                 "    extern int __wine_main_argc;\n"
-                 "    extern WCHAR **__wine_main_wargv;\n"
-                 "    STARTUPINFOA info;\n"
-                 "    char *cmdline = GetCommandLineA();\n"
-                 "    int bcount=0, in_quotes=0;\n"
-                 "    while (*cmdline) {\n"
-                 "        if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
-                 "        else if (*cmdline=='\\\\') bcount++;\n"
-                 "        else if (*cmdline=='\\\"') {\n"
-                 "            if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
-                 "            bcount=0;\n"
-                 "        }\n"
-                 "        else bcount=0;\n"
-                 "        cmdline++;\n"
-                 "    }\n"
-                 "    while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
-                 "    GetStartupInfoA( &info );\n"
-                 "    if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
-                 "    _ARGC = __wine_main_argc;\n"
-                 "    _ARGV = __wine_main_wargv;\n"
-                 "    ExitProcess( %s( GetModuleHandleA(0), 0, cmdline, info.wShowWindow ) );\n"
-                 "}\n\n", init_func, init_func );
-        init_func = "__wine_exe_main";
-        subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI;
-        break;
-    case SPEC_MODE_CUIEXE:
-        if (!init_func) init_func = "main";
-        fprintf( outfile,
-                 "\nint _ARGC;\n"
-                 "char **_ARGV;\n"
-                 "extern void __stdcall ExitProcess(int);\n"
-                 "static void __wine_exe_main(void)\n"
-                 "{\n"
-                 "    extern int %s( int argc, char *argv[] );\n"
-                 "    extern int __wine_main_argc;\n"
-                 "    extern char **__wine_main_argv;\n"
-                 "    _ARGC = __wine_main_argc;\n"
-                 "    _ARGV = __wine_main_argv;\n"
-                 "    ExitProcess( %s( _ARGC, _ARGV ) );\n"
-                 "}\n\n", init_func, init_func );
-        init_func = "__wine_exe_main";
-        subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
-        break;
-    case SPEC_MODE_CUIEXE_UNICODE:
-        if (!init_func) init_func = "wmain";
+                 "    int ret;\n"
+                 "    if (__wine_spec_init_state == 1)\n"
+                 "        _init( __wine_main_argc, __wine_main_argv, __wine_main_environ );\n" );
+        if (init_func)
+            fprintf( outfile,
+                     "    ret = %s( __wine_main_argc, __wine_main_argv );\n", init_func );
+        else
+            fprintf( outfile,
+                     "    if (WinMain) {\n"
+                     "        STARTUPINFOA info;\n"
+                     "        char *cmdline = GetCommandLineA();\n"
+                     "        int bcount=0, in_quotes=0;\n"
+                     "        while (*cmdline) {\n"
+                     "            if ((*cmdline=='\\t' || *cmdline==' ') && !in_quotes) break;\n"
+                     "            else if (*cmdline=='\\\\') bcount++;\n"
+                     "            else if (*cmdline=='\\\"') {\n"
+                     "                if ((bcount & 1)==0) in_quotes=!in_quotes;\n"
+                     "                bcount=0;\n"
+                     "            }\n"
+                     "            else bcount=0;\n"
+                     "            cmdline++;\n"
+                     "        }\n"
+                     "        while (*cmdline=='\\t' || *cmdline==' ') cmdline++;\n"
+                     "        GetStartupInfoA( &info );\n"
+                     "        if (!(info.dwFlags & 1)) info.wShowWindow = 1;\n"
+                     "        ret = WinMain( GetModuleHandleA(0), 0, cmdline, info.wShowWindow );\n"
+                     "    }\n"
+                     "    else if (wmain) ret = wmain( __wine_main_argc, __wine_main_wargv );\n"
+                     "    else ret = main( __wine_main_argc, __wine_main_argv );\n" );
         fprintf( outfile,
-                 "\ntypedef unsigned short WCHAR;\n"
-                 "int _ARGC;\n"
-                 "WCHAR **_ARGV;\n"
-                 "extern void __stdcall ExitProcess(int);\n"
-                 "static void __wine_exe_main(void)\n"
-                 "{\n"
-                 "    extern int %s( int argc, WCHAR *argv[] );\n"
-                 "    extern int __wine_main_argc;\n"
-                 "    extern WCHAR **__wine_main_wargv;\n"
-                 "    _ARGC = __wine_main_argc;\n"
-                 "    _ARGV = __wine_main_wargv;\n"
-                 "    ExitProcess( %s( _ARGC, _ARGV ) );\n"
-                 "}\n\n", init_func, init_func );
+                 "    if (__wine_spec_init_state == 1) _fini();\n"
+                 "    ExitProcess( ret );\n"
+                 "}\n\n" );
         init_func = "__wine_exe_main";
-        subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
         break;
     }
 
@@ -788,29 +768,30 @@
 #endif
     fprintf( outfile, "    0, 0, 0, 0,\n" );
     fprintf( outfile, "    sizeof(nt_header.OptionalHeader),\n" ); /* SizeOfOptionalHeader */
-    fprintf( outfile, "    0x%04x },\n", characteristics );        /* Characteristics */
+    fprintf( outfile, "    0x%04x },\n", spec->characteristics );  /* Characteristics */
 
     fprintf( outfile, "  { 0x%04x,\n", IMAGE_NT_OPTIONAL_HDR_MAGIC );  /* Magic */
     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorLinkerVersion */
     fprintf( outfile, "    0, 0, 0,\n" );                /* SizeOfCode/Data */
-    fprintf( outfile, "    %s,\n", init_func ? init_func : "DllMain" );  /* AddressOfEntryPoint */
+    fprintf( outfile, "    %s,\n", init_func );          /* AddressOfEntryPoint */
     fprintf( outfile, "    0, __wine_spec_data_start,\n" );              /* BaseOfCode/Data */
     fprintf( outfile, "    __wine_spec_pe_header,\n" );  /* ImageBase */
     fprintf( outfile, "    %ld,\n", page_size );         /* SectionAlignment */
     fprintf( outfile, "    %ld,\n", page_size );         /* FileAlignment */
     fprintf( outfile, "    1, 0,\n" );                   /* Major/MinorOperatingSystemVersion */
     fprintf( outfile, "    0, 0,\n" );                   /* Major/MinorImageVersion */
-    fprintf( outfile, "    4, 0,\n" );                   /* Major/MinorSubsystemVersion */
+    fprintf( outfile, "    %d,\n", spec->subsystem_major );             /* MajorSubsystemVersion */
+    fprintf( outfile, "    %d,\n", spec->subsystem_minor );             /* MinorSubsystemVersion */
     fprintf( outfile, "    0,\n" );                      /* Win32VersionValue */
     fprintf( outfile, "    _end,\n" );                   /* SizeOfImage */
     fprintf( outfile, "    %ld,\n", page_size );         /* SizeOfHeaders */
     fprintf( outfile, "    0,\n" );                      /* CheckSum */
-    fprintf( outfile, "    0x%04x,\n", subsystem );      /* Subsystem */
+    fprintf( outfile, "    0x%04x,\n", spec->subsystem );/* Subsystem */
     fprintf( outfile, "    0,\n" );                      /* DllCharacteristics */
     fprintf( outfile, "    %d, %ld,\n",                  /* SizeOfStackReserve/Commit */
-             (stack_size ? stack_size : 1024) * 1024, page_size );
+             (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
     fprintf( outfile, "    %d, %ld,\n",                  /* SizeOfHeapReserve/Commit */
-             (DLLHeapSize ? DLLHeapSize : 1024) * 1024, page_size );
+             (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
     fprintf( outfile, "    0,\n" );                      /* LoaderFlags */
     fprintf( outfile, "    %d,\n", IMAGE_NUMBEROF_DIRECTORY_ENTRIES );  /* NumberOfRvaAndSizes */
     fprintf( outfile, "    {\n" );
@@ -819,22 +800,29 @@
     fprintf( outfile, "      { %s, %s },\n",  /* IMAGE_DIRECTORY_ENTRY_IMPORT */
              nr_imports ? "&imports" : "0", nr_imports ? "sizeof(imports)" : "0" );
     fprintf( outfile, "      { %s, %s },\n",   /* IMAGE_DIRECTORY_ENTRY_RESOURCE */
-             nr_resources ? "&resources" : "0", nr_resources ? "sizeof(resources)" : "0" );
+             spec->nb_resources ? "&resources" : "0",
+             spec->nb_resources ? "sizeof(resources)" : "0" );
     fprintf( outfile, "    }\n  }\n};\n\n" );
 
     /* Output the DLL constructor */
 
-    sprintf( constructor, "__wine_spec_%s_init", make_c_identifier(dll_file_name) );
-    output_dll_init( outfile, constructor, NULL );
-
     fprintf( outfile,
-             "void %s(void)\n"
+             "void __wine_spec_init(void)\n"
              "{\n"
              "    extern void __wine_dll_register( const struct image_nt_headers *, const char * );\n"
-             "    extern void *__wine_dbg_register( char * const *, int );\n"
+             "    __wine_spec_init_state = 1;\n"
              "    __wine_dll_register( &nt_header, \"%s\" );\n"
-             "}\n",
-             constructor, dll_file_name );
+             "}\n\n",
+             spec->file_name );
+
+    output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
+    fprintf( outfile,
+             "void __wine_spec_init_ctor(void)\n"
+             "{\n"
+             "    if (__wine_spec_init_state) return;\n"
+             "    __wine_spec_init();\n"
+             "    __wine_spec_init_state = 2;\n"
+             "}\n" );
 }
 
 
@@ -843,25 +831,23 @@
  *
  * Build a Win32 def file from a spec file.
  */
-void BuildDef32File(FILE *outfile)
+void BuildDef32File( FILE *outfile, DLLSPEC *spec )
 {
     const char *name;
     int i;
 
-    AssignOrdinals();
-
     fprintf(outfile, "; File generated automatically from %s; do not edit!\n\n",
             input_file_name );
 
-    fprintf(outfile, "LIBRARY %s\n\n", dll_file_name);
+    fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
 
     fprintf(outfile, "EXPORTS\n");
 
     /* Output the exports and relay entry points */
 
-    for(i = 0; i < nb_entry_points; i++)
+    for(i = 0; i < spec->nb_entry_points; i++)
     {
-        ORDDEF *odp = EntryPoints[i];
+        const ORDDEF *odp = &spec->entry_points[i];
         int is_data = 0;
 
         if (!odp) continue;
@@ -906,7 +892,7 @@
         fprintf( outfile, " @%d", odp->ordinal );
         if (!odp->name) fprintf( outfile, " NONAME" );
         if (is_data) fprintf( outfile, " DATA" );
-#if !defined(__REACTOS__)
+#if 0
         /* MinGW binutils cannot handle this correctly */
         if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
 #endif
@@ -951,8 +937,8 @@
 
     fprintf( outfile,
              "#ifdef __GNUC__\n"
-             "static void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
-             "static void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
+             "void __wine_dbg_%s_init(void) __attribute__((constructor));\n"
+             "void __wine_dbg_%s_fini(void) __attribute__((destructor));\n"
              "#else\n"
              "static void __asm__dummy_dll_init(void) {\n",
              prefix, prefix );
@@ -972,29 +958,34 @@
     fprintf( outfile, "    \"\\tnop\\n\"\n" );
     fprintf( outfile, "    \"\\t.section\t\\\".text\\\"\\n\");\n" );
 #elif defined(__powerpc__)
+# ifdef __APPLE__
+	fprintf( outfile, "asm(\"\\t.mod_init_func\\n\"\n" );
+	fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
+	fprintf( outfile, "    \"\\t.long " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
+	fprintf( outfile, "    \"\\t.text\\n\");\n" );
+	fprintf( outfile, "asm(\"\\t.mod_term_func\\n\"\n" );
+	fprintf( outfile, "    \"\\t.align 2\\n\"\n" );
+	fprintf( outfile, "    \"\\t.long " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
+	fprintf( outfile, "    \"\\t.text\\n\");\n" );
+# else
     fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" );
     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix );
     fprintf( outfile, "    \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" );
     fprintf( outfile, "    \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix );
     fprintf( outfile, "    \"\\t.text\\n\");\n" );
+# endif
 #else
 #error You need to define the DLL constructor for your architecture
 #endif
-    fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n" );
+    fprintf( outfile, "}\n#endif /* defined(__GNUC__) */\n\n" );
 
     fprintf( outfile,
-             "\n#ifdef __GNUC__\n"
-             "static\n"
-             "#endif\n"
              "void __wine_dbg_%s_init(void)\n"
              "{\n"
              "    extern void *__wine_dbg_register( char * const *, int );\n"
-             "    debug_registration = __wine_dbg_register( debug_channels, %d );\n"
-             "}\n", prefix, nr_debug );
+             "    if (!debug_registration) debug_registration = __wine_dbg_register( debug_channels, %d );\n"
+             "}\n\n", prefix, nr_debug );
     fprintf( outfile,
-             "\n#ifdef __GNUC__\n"
-             "static\n"
-             "#endif\n"
              "void __wine_dbg_%s_fini(void)\n"
              "{\n"
              "    extern void __wine_dbg_unregister( void* );\n"

reactos/tools/winebuild
utils.c 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- utils.c	5 Jan 2004 19:49:59 -0000	1.2
+++ utils.c	23 Sep 2004 20:27:30 -0000	1.3
@@ -86,6 +86,7 @@
             fprintf( stderr, "%d:", current_line );
         fputc( ' ', stderr );
     }
+    else fprintf( stderr, "winebuild: " );
     vfprintf( stderr, msg, valist );
     va_end( valist );
     exit(1);
@@ -214,6 +215,86 @@
 
 
 /*******************************************************************
+ *         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->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->characteristics    = 0;
+    spec->subsystem          = 0;
+    spec->subsystem_major    = 4;
+    spec->subsystem_minor    = 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
  *
  * Map a string to a valid C identifier.

reactos/tools/winebuild
winebuild.man.in 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- winebuild.man.in	9 Dec 2003 18:44:25 -0000	1.1
+++ winebuild.man.in	23 Sep 2004 20:27:30 -0000	1.2
@@ -19,10 +19,11 @@
 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
@@ -32,16 +33,16 @@
 to get the list of all undefined symbols that need to be imported from
 other dlls.
 .TP
-.BI \--exe= name
+.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
 as
 .I input files.
 .TP
-.BI \--def= file.spec
+.BI \--def= file.spec
 Build a .def file from a spec file. This is used when building dlls
 with a PE (Win32) compiler.
 .TP
@@ -75,11 +76,12 @@
 is
 .B DllMain
 for dlls, and
-.B main
-or
 .B WinMain
-for CUI or GUI executables respectively. This is only valid for Win32
-modules.
+for executables (if
+.B WinMain
+is not defined, the standard C
+.B main
+is used instead). This is only valid for Win32 modules.
 .TP
 .BI \-f\  flags
 Ignored for compatibility with the C compiler.
@@ -130,29 +132,7 @@
 .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.
-.TP
-.BI \-m,\ --exe-mode= mode
-Set the executable mode, which can be one of the following:
-.br
-.B cui
-for a command line ASCII executable,
-.br
-.B gui
-for a graphical ASCII executable,
-.br
-.B cuiw
-for a command line Unicode executable,
-.br
-.B guiw
-for a graphical Unicode executable.
-.br
-A command line executable entry point is a normal C \fBmain\fR
-function. A graphical executable has a \fBWinMain\fR entry point
-instead. The ASCII/Unicode distinction applies to the strings that are
-passed to the entry point.
-.br
-This option is only meaningful in \fB--exe\fR mode.
+meaningful in \fB--dll\fR mode.
 .TP
 .BI \-N,\ --dll-name= dllname
 Set the internal name of the module. It is only used in Win16
@@ -176,6 +156,26 @@
 .B \-r
 option will also work for Win32 files).
 .TP
+.BI --subsystem= subsystem[:major[.minor]]
+Set the subsystem of the executable, which can be one of the following:
+.br
+.B console
+for a command line executable,
+.br
+.B windows
+for a graphical executable,
+.br
+.B native
+for a native-mode dll.
+.br
+The entry point of a command line executable is a normal C \fBmain\fR
+function. A \fBwmain\fR function can be used instead if you need the
+argument array to use Unicode strings. A graphical executable has a
+\fBWinMain\fR entry point.
+.br
+Optionally a major and minor subsystem version can also be specified;
+the default subsystem version is 4.0.
+.TP
 .B \--version
 Display the program version and exit.
 .TP
@@ -237,9 +237,6 @@
 .B -register
 The function uses CPU register to pass arguments.
 .TP
-.B -interrupt
-The function is an interrupt handler routine.
-.TP
 .B -private
 The function cannot be imported from other dlls, it can only be
 accessed through GetProcAddress.

reactos/tools/winebuild
winglue.h 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- winglue.h	4 Jan 2004 15:50:41 -0000	1.1
+++ winglue.h	23 Sep 2004 20:27:30 -0000	1.2
@@ -9,7 +9,11 @@
 #define LOBYTE(w)	((BYTE)(w))
 #define HIBYTE(w)	((BYTE)(((WORD)(w)>>8)&0xFF))
 
+#define DLL_PROCESS_ATTACH 1
+#define DLL_PROCESS_DETACH 0
+
 #define IMAGE_FILE_DLL	8192
+#define IMAGE_SUBSYSTEM_NATIVE		1
 #define IMAGE_SUBSYSTEM_WINDOWS_GUI	2
 #define IMAGE_SUBSYSTEM_WINDOWS_CUI	3
 #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
CVSspam 0.2.8