Commit 5599ac22 authored by Alexandre Julliard's avatar Alexandre Julliard

winebuild: Add support for generating stand-alone 16-bit modules.

This is done by wrapping them inside an empty 32-bit module.
parent ddc8941d
...@@ -207,13 +207,16 @@ extern int resolve_imports( DLLSPEC *spec ); ...@@ -207,13 +207,16 @@ extern int resolve_imports( DLLSPEC *spec );
extern int has_imports(void); extern int has_imports(void);
extern int has_relays( DLLSPEC *spec ); extern int has_relays( DLLSPEC *spec );
extern void output_get_pc_thunk(void); extern void output_get_pc_thunk(void);
extern void output_module( DLLSPEC *spec );
extern void output_stubs( DLLSPEC *spec ); extern void output_stubs( DLLSPEC *spec );
extern void output_imports( 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 int load_res32_file( const char *name, DLLSPEC *spec );
extern void output_resources( DLLSPEC *spec ); extern void output_resources( DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec ); extern void load_res16_file( const char *name, DLLSPEC *spec );
extern void output_res16_data( DLLSPEC *spec ); extern void output_res16_data( DLLSPEC *spec );
extern void output_res16_directory( DLLSPEC *spec ); extern void output_res16_directory( DLLSPEC *spec );
extern void output_spec16_file( DLLSPEC *spec );
extern void BuildRelays16(void); extern void BuildRelays16(void);
extern void BuildRelays32(void); extern void BuildRelays32(void);
...@@ -221,6 +224,7 @@ extern void BuildSpec16File( DLLSPEC *spec ); ...@@ -221,6 +224,7 @@ extern void BuildSpec16File( DLLSPEC *spec );
extern void BuildSpec32File( DLLSPEC *spec ); extern void BuildSpec32File( DLLSPEC *spec );
extern void BuildDef32File( 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_spec_file( FILE *file, DLLSPEC *spec );
extern int parse_def_file( FILE *file, DLLSPEC *spec ); extern int parse_def_file( FILE *file, DLLSPEC *spec );
......
...@@ -379,6 +379,7 @@ static const char *get_default_entry_point( const DLLSPEC *spec ) ...@@ -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->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "__wine_spec_drv_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"; return "__wine_spec_exe_entry";
} }
......
...@@ -82,6 +82,7 @@ char *spec_file_name = NULL; ...@@ -82,6 +82,7 @@ char *spec_file_name = NULL;
FILE *output_file = NULL; FILE *output_file = NULL;
const char *output_file_name = NULL; const char *output_file_name = NULL;
static const char *output_file_source_name; static const char *output_file_source_name;
static char *main_module; /* FIXME: to be removed */
char *as_command = NULL; char *as_command = NULL;
char *ld_command = NULL; char *ld_command = NULL;
...@@ -142,6 +143,7 @@ static void set_subsystem( const char *subsystem, DLLSPEC *spec ) ...@@ -142,6 +143,7 @@ static void set_subsystem( const char *subsystem, DLLSPEC *spec )
if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE; if (!strcmp( str, "native" )) spec->subsystem = IMAGE_SUBSYSTEM_NATIVE;
else if (!strcmp( str, "windows" )) spec->subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI; 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, "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 ); else fatal_error( "Invalid subsystem name '%s'\n", subsystem );
if (major) if (major)
{ {
...@@ -359,6 +361,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) ...@@ -359,6 +361,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
break; break;
case 'M': case 'M':
spec->type = SPEC_WIN16; spec->type = SPEC_WIN16;
main_module = xstrdup( optarg );
break; break;
case 'N': case 'N':
spec->dll_name = xstrdup( optarg ); spec->dll_name = xstrdup( optarg );
...@@ -591,9 +594,13 @@ int main(int argc, char **argv) ...@@ -591,9 +594,13 @@ int main(int argc, char **argv)
switch (spec->type) switch (spec->type)
{ {
case SPEC_WIN16: case SPEC_WIN16:
if (argv[0]) if (!main_module)
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] ); {
BuildSpec16File( spec ); read_undef_symbols( spec, argv );
output_spec16_file( spec );
}
else
BuildSpec16File( spec );
break; break;
case SPEC_WIN32: case SPEC_WIN32:
read_undef_symbols( spec, argv ); read_undef_symbols( spec, argv );
......
...@@ -146,13 +146,17 @@ static const char * GetToken( int allow_eol ) ...@@ -146,13 +146,17 @@ static const char * GetToken( int allow_eol )
static ORDDEF *add_entry_point( DLLSPEC *spec ) static ORDDEF *add_entry_point( DLLSPEC *spec )
{ {
ORDDEF *ret;
if (spec->nb_entry_points == spec->alloc_entry_points) if (spec->nb_entry_points == spec->alloc_entry_points)
{ {
spec->alloc_entry_points += 128; spec->alloc_entry_points += 128;
spec->entry_points = xrealloc( spec->entry_points, spec->entry_points = xrealloc( spec->entry_points,
spec->alloc_entry_points * sizeof(*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 ) ...@@ -475,9 +479,7 @@ static int parse_spec_ordinal( int ordinal, DLLSPEC *spec )
{ {
const char *token; const char *token;
size_t len; size_t len;
ORDDEF *odp = add_entry_point( spec ); ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) );
if (!(token = GetToken(0))) goto error; if (!(token = GetToken(0))) goto error;
...@@ -724,6 +726,29 @@ static void assign_ordinals( DLLSPEC *spec ) ...@@ -724,6 +726,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 * parse_spec_file
* *
* Parse a .spec file. * Parse a .spec file.
...@@ -844,9 +869,7 @@ static int parse_def_export( char *name, DLLSPEC *spec ) ...@@ -844,9 +869,7 @@ static int parse_def_export( char *name, DLLSPEC *spec )
{ {
int i, args; int i, args;
const char *token = GetToken(1); const char *token = GetToken(1);
ORDDEF *odp = add_entry_point( spec ); ORDDEF *odp = add_entry_point( spec );
memset( odp, 0, sizeof(*odp) );
odp->lineno = current_line; odp->lineno = current_line;
odp->ordinal = -1; odp->ordinal = -1;
......
...@@ -522,20 +522,16 @@ static void output_init_code( const DLLSPEC *spec ) ...@@ -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 **typelist;
ORDDEF *entry_point = NULL; ORDDEF *entry_point = NULL;
int i, j, nb_funcs; int i, j, nb_funcs;
/* File header */
output_standard_file_header();
if (!spec->file_name) if (!spec->file_name)
{ {
char *p; char *p;
...@@ -827,14 +823,58 @@ void BuildSpec16File( DLLSPEC *spec ) ...@@ -827,14 +823,58 @@ void BuildSpec16File( DLLSPEC *spec )
output( "\t.long %s\n", asm_name("wine_ldt_copy") ); 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( "\n\t%s\n", get_asm_string_section() );
output( ".L__wine_spec_file_name:\n" ); output( ".L__wine_spec_file_name:\n" );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name ); output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output_stubs( spec ); output_stubs( spec );
output_get_pc_thunk(); output_get_pc_thunk();
output_init_code( spec );
output_gnu_stack_note(); 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 );
} }
...@@ -186,7 +186,7 @@ static void output_relay_debug( DLLSPEC *spec ) ...@@ -186,7 +186,7 @@ static void output_relay_debug( DLLSPEC *spec )
* *
* Output the export table for a Win32 module. * 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 i, fwd_size = 0;
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 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 ) ...@@ -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; int machine = 0;
unsigned int page_size = get_page_size(); unsigned int page_size = get_page_size();
resolve_imports( spec );
output_standard_file_header();
/* Reserve some space for the PE header */ /* Reserve some space for the PE header */
switch (target_platform) switch (target_platform)
...@@ -522,11 +519,24 @@ void BuildSpec32File( DLLSPEC *spec ) ...@@ -522,11 +519,24 @@ void BuildSpec32File( DLLSPEC *spec )
if (target_platform == PLATFORM_APPLE) if (target_platform == PLATFORM_APPLE)
output( "\t.lcomm %s,4\n", asm_name("_end") ); 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_stubs( spec );
output_exports( spec ); output_exports( spec );
output_imports( spec ); output_imports( spec );
output_resources( spec ); output_resources( spec );
output_asm_constructor( "__wine_spec_init_ctor" );
output_gnu_stack_note(); output_gnu_stack_note();
} }
......
...@@ -197,7 +197,10 @@ for a command line executable, ...@@ -197,7 +197,10 @@ for a command line executable,
for a graphical executable, for a graphical executable,
.br .br
.B native .B native
for a native-mode dll. for a native-mode dll,
.br
.B win16
for a 16-bit module.
.br .br
The entry point of a command line executable is a normal C \fBmain\fR 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 function. A \fBwmain\fR function can be used instead if you need the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment