| /* |
| * Main function |
| * |
| * Copyright 1993 Robert J. Amstadt |
| * Copyright 1995 Martin von Loewis |
| * Copyright 1995, 1996, 1997 Alexandre Julliard |
| * Copyright 1997 Eric Youngdale |
| * Copyright 1999 Ulrich Weigand |
| */ |
| |
| #include <assert.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| #include <errno.h> |
| |
| #include "config.h" |
| #include "winnt.h" |
| #include "build.h" |
| |
| ORDDEF *EntryPoints[MAX_ORDINALS]; |
| ORDDEF *Ordinals[MAX_ORDINALS]; |
| ORDDEF *Names[MAX_ORDINALS]; |
| |
| SPEC_MODE SpecMode = SPEC_MODE_DLL; |
| int Base = MAX_ORDINALS; |
| int Limit = 0; |
| int DLLHeapSize = 0; |
| int UsePIC = 0; |
| int nb_entry_points = 0; |
| int nb_names = 0; |
| int nb_debug_channels = 0; |
| int nb_lib_paths = 0; |
| |
| /* we only support relay debugging on i386 */ |
| #if defined(__i386__) && !defined(NO_TRACE_MSGS) |
| int debugging = 1; |
| #else |
| int debugging = 0; |
| #endif |
| |
| char DLLName[80]; |
| char DLLFileName[80]; |
| char owner_name[80]; |
| char *init_func = NULL; |
| char **debug_channels = NULL; |
| char **lib_path = NULL; |
| |
| const char *input_file_name; |
| const char *output_file_name; |
| |
| static FILE *input_file; |
| static FILE *output_file; |
| |
| /* execution mode */ |
| static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE; |
| |
| /* open the input file */ |
| static void open_input( const char *name ) |
| { |
| input_file_name = name; |
| if (!(input_file = fopen( name, "r" ))) |
| { |
| fprintf( stderr, "Cannot open input file '%s'\n", name ); |
| exit(1); |
| } |
| } |
| |
| /* cleanup on program exit */ |
| static void cleanup(void) |
| { |
| if (output_file_name) unlink( output_file_name ); |
| } |
| |
| |
| /******************************************************************* |
| * command-line option handling |
| */ |
| |
| struct option |
| { |
| const char *name; |
| int has_arg; |
| void (*func)(); |
| const char *usage; |
| }; |
| |
| static void do_pic(void); |
| static void do_output( const char *arg ); |
| static void do_usage(void); |
| static void do_spec( const char *arg ); |
| static void do_glue( const char *arg ); |
| static void do_relay(void); |
| static void do_sym( const char *arg ); |
| static void do_lib( const char *arg ); |
| |
| static const struct option option_table[] = |
| { |
| { "-fPIC", 0, do_pic, "-fPIC Generate PIC code" }, |
| { "-h", 0, do_usage, "-h Display this help message" }, |
| { "-L", 1, do_lib, "-L directory Look for imports libraries in 'directory'" }, |
| { "-o", 1, do_output, "-o name Set the output file name (default: stdout)" }, |
| { "-sym", 1, do_sym, "-sym file.o Read the list of undefined symbols from 'file.o'" }, |
| { "-spec", 1, do_spec, "-spec file.spec Build a .c file from a spec file" }, |
| { "-glue", 1, do_glue, "-glue file.c Build the 16-bit glue for a .c file" }, |
| { "-relay", 0, do_relay, "-relay Build the relay assembly routines" }, |
| { NULL, 0, NULL, NULL } |
| }; |
| |
| static void do_pic(void) |
| { |
| UsePIC = 1; |
| } |
| |
| static void do_output( const char *arg ) |
| { |
| if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) ) |
| { |
| fprintf ( stderr, "Unable to create output file '%s'\n", arg ); |
| exit (1); |
| } |
| if (!(output_file = fopen( arg, "w" ))) |
| { |
| fprintf( stderr, "Unable to create output file '%s'\n", arg ); |
| exit(1); |
| } |
| output_file_name = arg; |
| atexit( cleanup ); /* make sure we remove the output file on exit */ |
| } |
| |
| static void do_usage(void) |
| { |
| const struct option *opt; |
| fprintf( stderr, "Usage: winebuild [options]\n\n" ); |
| fprintf( stderr, "Options:\n" ); |
| for (opt = option_table; opt->name; opt++) fprintf( stderr, " %s\n", opt->usage ); |
| fprintf( stderr, "\nExactly one of -spec, -glue or -relay must be specified.\n\n" ); |
| exit(1); |
| } |
| |
| static void do_spec( const char *arg ) |
| { |
| if (exec_mode != MODE_NONE || !arg[0]) do_usage(); |
| exec_mode = MODE_SPEC; |
| open_input( arg ); |
| } |
| |
| static void do_glue( const char *arg ) |
| { |
| if (exec_mode != MODE_NONE || !arg[0]) do_usage(); |
| exec_mode = MODE_GLUE; |
| open_input( arg ); |
| } |
| |
| static void do_relay(void) |
| { |
| if (exec_mode != MODE_NONE) do_usage(); |
| exec_mode = MODE_RELAY; |
| } |
| |
| static void do_sym( const char *arg ) |
| { |
| extern void read_undef_symbols( const char *name ); |
| read_undef_symbols( arg ); |
| } |
| |
| static void do_lib( const char *arg ) |
| { |
| lib_path = xrealloc( lib_path, (nb_lib_paths+1) * sizeof(*lib_path) ); |
| lib_path[nb_lib_paths++] = xstrdup( arg ); |
| } |
| |
| /* parse options from the argv array and remove all the recognized ones */ |
| static void parse_options( char *argv[] ) |
| { |
| const struct option *opt; |
| char * const * ptr; |
| const char* arg=NULL; |
| |
| ptr=argv+1; |
| while (*ptr != NULL) |
| { |
| for (opt = option_table; opt->name; opt++) |
| { |
| if (opt->has_arg && !strncmp( *ptr, opt->name, strlen(opt->name) )) |
| { |
| arg=*ptr+strlen(opt->name); |
| if (*arg=='\0') |
| { |
| ptr++; |
| arg=*ptr; |
| } |
| break; |
| } |
| if (!strcmp( *ptr, opt->name )) |
| { |
| arg=NULL; |
| break; |
| } |
| } |
| |
| if (!opt->name) |
| { |
| fprintf( stderr, "Unrecognized option '%s'\n", *ptr ); |
| do_usage(); |
| } |
| |
| if (opt->has_arg && arg!=NULL) opt->func( arg ); |
| else opt->func( "" ); |
| ptr++; |
| } |
| } |
| |
| |
| /******************************************************************* |
| * main |
| */ |
| int main(int argc, char **argv) |
| { |
| output_file = stdout; |
| parse_options( argv ); |
| |
| switch(exec_mode) |
| { |
| case MODE_SPEC: |
| switch (ParseTopLevel( input_file )) |
| { |
| case SPEC_WIN16: |
| BuildSpec16File( output_file ); |
| break; |
| case SPEC_WIN32: |
| BuildSpec32File( output_file ); |
| break; |
| default: assert(0); |
| } |
| break; |
| case MODE_GLUE: |
| BuildGlue( output_file, input_file ); |
| break; |
| case MODE_RELAY: |
| BuildRelays( output_file ); |
| break; |
| default: |
| do_usage(); |
| break; |
| } |
| fclose( output_file ); |
| output_file_name = NULL; |
| return 0; |
| } |