diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index 1be0fc8a37..572f4652cd 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -207,13 +207,16 @@ extern int resolve_imports( DLLSPEC *spec ); extern int has_imports(void); extern int has_relays( DLLSPEC *spec ); extern void output_get_pc_thunk(void); +extern void output_module( DLLSPEC *spec ); extern void output_stubs( DLLSPEC *spec ); extern void output_imports( DLLSPEC *spec ); +extern void output_exports( DLLSPEC *spec ); extern int load_res32_file( const char *name, DLLSPEC *spec ); extern void output_resources( DLLSPEC *spec ); extern void load_res16_file( const char *name, DLLSPEC *spec ); extern void output_res16_data( DLLSPEC *spec ); extern void output_res16_directory( DLLSPEC *spec ); +extern void output_spec16_file( DLLSPEC *spec ); extern void BuildRelays16(void); extern void BuildRelays32(void); @@ -221,6 +224,7 @@ extern void BuildSpec16File( DLLSPEC *spec ); extern void BuildSpec32File( DLLSPEC *spec ); extern void BuildDef32File( DLLSPEC *spec ); +extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 ); extern int parse_spec_file( FILE *file, DLLSPEC *spec ); extern int parse_def_file( FILE *file, DLLSPEC *spec ); diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index bd56a00bdd..fcd958d24a 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -379,6 +379,7 @@ static const char *get_default_entry_point( const DLLSPEC *spec ) { if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry"; if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "__wine_spec_drv_entry"; + if (spec->type == SPEC_WIN16) return "__wine_spec_exe16_entry"; return "__wine_spec_exe_entry"; } diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 47cb266d90..cab5243c7e 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -82,6 +82,7 @@ char *spec_file_name = NULL; FILE *output_file = NULL; const char *output_file_name = NULL; static const char *output_file_source_name; +static char *main_module; /* FIXME: to be removed */ char *as_command = NULL; char *ld_command = NULL; @@ -142,6 +143,7 @@ static void set_subsystem( const char *subsystem, DLLSPEC *spec ) 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 if (!strcmp( str, "win16" )) spec->type = SPEC_WIN16; else fatal_error( "Invalid subsystem name '%s'\n", subsystem ); if (major) { @@ -359,6 +361,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) break; case 'M': spec->type = SPEC_WIN16; + main_module = xstrdup( optarg ); break; case 'N': spec->dll_name = xstrdup( optarg ); @@ -591,9 +594,13 @@ int main(int argc, char **argv) switch (spec->type) { case SPEC_WIN16: - if (argv[0]) - fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); - BuildSpec16File( spec ); + if (!main_module) + { + read_undef_symbols( spec, argv ); + output_spec16_file( spec ); + } + else + BuildSpec16File( spec ); break; case SPEC_WIN32: read_undef_symbols( spec, argv ); diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index ee39dcff71..dd79a1cd15 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -146,13 +146,17 @@ static const char * GetToken( int allow_eol ) static ORDDEF *add_entry_point( DLLSPEC *spec ) { + ORDDEF *ret; + 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++]; + ret = &spec->entry_points[spec->nb_entry_points++]; + memset( ret, 0, sizeof(*ret) ); + return ret; } /******************************************************************* @@ -475,9 +479,7 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec ) { const char *token; size_t len; - ORDDEF *odp = add_entry_point( spec ); - memset( odp, 0, sizeof(*odp) ); if (!(token = GetToken(0))) goto error; @@ -723,6 +725,29 @@ static void assign_ordinals( DLLSPEC *spec ) } +/******************************************************************* + * add_16bit_exports + * + * Add the necessary exports to the 32-bit counterpart of a 16-bit module. + */ +void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 ) +{ + ORDDEF *odp; + + /* add an export for the NE module */ + + odp = add_entry_point( spec32 ); + odp->type = TYPE_EXTERN; + odp->name = xstrdup( "__wine_spec_dos_header" ); + odp->lineno = 0; + odp->ordinal = 1; + odp->link_name = xstrdup( ".L__wine_spec_dos_header" ); + + assign_names( spec32 ); + assign_ordinals( spec32 ); +} + + /******************************************************************* * parse_spec_file * @@ -844,9 +869,7 @@ 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; diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 82b5065052..1465d2c440 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -522,20 +522,16 @@ static void output_init_code( const DLLSPEC *spec ) /******************************************************************* - * BuildSpec16File + * output_module16 * - * Build a Win16 assembly file from a spec file. + * Output code for a 16-bit module. */ -void BuildSpec16File( DLLSPEC *spec ) +static void output_module16( DLLSPEC *spec ) { ORDDEF **typelist; ORDDEF *entry_point = NULL; int i, j, nb_funcs; - /* File header */ - - output_standard_file_header(); - if (!spec->file_name) { char *p; @@ -827,14 +823,58 @@ void BuildSpec16File( DLLSPEC *spec ) output( "\t.long %s\n", asm_name("wine_ldt_copy") ); } + free( typelist ); +} + + +/******************************************************************* + * BuildSpec16File + * + * Build a Win16 assembly file from a spec file. + */ +void BuildSpec16File( DLLSPEC *spec ) +{ + output_standard_file_header(); + output_module16( spec ); + output_init_code( spec ); + output( "\n\t%s\n", get_asm_string_section() ); output( ".L__wine_spec_file_name:\n" ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name ); output_stubs( spec ); output_get_pc_thunk(); - output_init_code( spec ); output_gnu_stack_note(); - - free( typelist ); +} + + +/******************************************************************* + * output_spec16_file + * + * Output the complete data for a spec 16-bit file. + */ +void output_spec16_file( DLLSPEC *spec16 ) +{ + DLLSPEC *spec32 = alloc_dll_spec(); + + spec32->file_name = xstrdup( spec16->file_name ); + + if (spec16->characteristics & IMAGE_FILE_DLL) + { + spec32->characteristics = IMAGE_FILE_DLL; + spec32->init_func = xstrdup( "__wine_spec_dll_entry" ); + } + + resolve_imports( spec16 ); + add_16bit_exports( spec32, spec16 ); + + output_standard_file_header(); + output_module( spec32 ); + output_module16( spec16 ); + output_stubs( spec16 ); + output_exports( spec32 ); + output_imports( spec16 ); + output_resources( spec16 ); + output_gnu_stack_note(); + free_dll_spec( spec32 ); } diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 54891259e1..24580d4cfb 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -186,7 +186,7 @@ static void output_relay_debug( DLLSPEC *spec ) * * Output the export table for a Win32 module. */ -static void output_exports( DLLSPEC *spec ) +void output_exports( DLLSPEC *spec ) { int i, fwd_size = 0; int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0; @@ -366,18 +366,15 @@ static void output_asm_constructor( const char *constructor ) /******************************************************************* - * BuildSpec32File + * output_module * - * Build a Win32 C file from a spec file. + * Output the module data. */ -void BuildSpec32File( DLLSPEC *spec ) +void output_module( DLLSPEC *spec ) { int machine = 0; unsigned int page_size = get_page_size(); - resolve_imports( spec ); - output_standard_file_header(); - /* Reserve some space for the PE header */ switch (target_platform) @@ -522,11 +519,24 @@ void BuildSpec32File( DLLSPEC *spec ) if (target_platform == PLATFORM_APPLE) output( "\t.lcomm %s,4\n", asm_name("_end") ); + output_asm_constructor( "__wine_spec_init_ctor" ); +} + + +/******************************************************************* + * BuildSpec32File + * + * Build a Win32 C file from a spec file. + */ +void BuildSpec32File( DLLSPEC *spec ) +{ + resolve_imports( spec ); + output_standard_file_header(); + output_module( spec ); output_stubs( spec ); output_exports( spec ); output_imports( spec ); output_resources( spec ); - output_asm_constructor( "__wine_spec_init_ctor" ); output_gnu_stack_note(); } diff --git a/tools/winebuild/winebuild.man.in b/tools/winebuild/winebuild.man.in index d8bc569e26..da0728e98e 100644 --- a/tools/winebuild/winebuild.man.in +++ b/tools/winebuild/winebuild.man.in @@ -197,7 +197,10 @@ for a command line executable, for a graphical executable, .br .B native -for a native-mode dll. +for a native-mode dll, +.br +.B win16 +for a 16-bit module. .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