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 );
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 );
......
......@@ -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";
}
......
......@@ -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 );
......
......@@ -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;
......@@ -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 a .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;
......
......@@ -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 );
}
......@@ -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();
}
......
......@@ -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
......
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