Added LDFLAGS to linking of wine-related binaries.
[wine] / tools / winebuild / main.c
1 /*
2  * Main function
3  *
4  * Copyright 1993 Robert J. Amstadt
5  * Copyright 1995 Martin von Loewis
6  * Copyright 1995, 1996, 1997 Alexandre Julliard
7  * Copyright 1997 Eric Youngdale
8  * Copyright 1999 Ulrich Weigand
9  */
10
11 #include <assert.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <errno.h>
15
16 #include "winnt.h"
17 #include "build.h"
18
19 #ifdef __i386__
20 extern WORD __get_cs(void);
21 extern WORD __get_ds(void);
22 __ASM_GLOBAL_FUNC( __get_cs, "movw %cs,%ax\n\tret" );
23 __ASM_GLOBAL_FUNC( __get_ds, "movw %ds,%ax\n\tret" );
24 #else
25 static inline WORD __get_cs(void) { return 0; }
26 static inline WORD __get_ds(void) { return 0; }
27 #endif
28
29
30 ORDDEF EntryPoints[MAX_ORDINALS];
31 ORDDEF *Ordinals[MAX_ORDINALS];
32 ORDDEF *Names[MAX_ORDINALS];
33
34 SPEC_MODE SpecMode = SPEC_MODE_DLL;
35 int Base = MAX_ORDINALS;
36 int Limit = 0;
37 int DLLHeapSize = 0;
38 int UsePIC = 0;
39 int nb_entry_points = 0;
40 int nb_names = 0;
41 int debugging = 1;
42
43 char DLLName[80];
44 char DLLFileName[80];
45 char DLLInitFunc[80];
46 char owner_name[80];
47
48 const char *input_file_name;
49 const char *output_file_name;
50
51 unsigned short code_selector;
52 unsigned short data_selector;
53
54 static FILE *input_file;
55 static FILE *output_file;
56
57 /* execution mode */
58 static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE;
59
60 /* open the input file */
61 static void open_input( const char *name )
62 {
63     input_file_name = name;
64     if (!(input_file = fopen( name, "r" )))
65     {
66         fprintf( stderr, "Cannot open input file '%s'\n", name );
67         exit(1);
68     }
69 }
70
71 /* cleanup on program exit */
72 static void cleanup(void)
73 {
74     if (output_file_name) unlink( output_file_name );
75 }
76
77
78 /*******************************************************************
79  *         command-line option handling
80  */
81
82 struct option
83 {
84     const char *name;
85     int         has_arg;
86     void      (*func)();
87     const char *usage;
88 };
89
90 static void do_pic(void);
91 static void do_output( const char *arg );
92 static void do_usage(void);
93 static void do_spec( const char *arg );
94 static void do_glue( const char *arg );
95 static void do_relay(void);
96
97 static const struct option option_table[] =
98 {
99     { "-fPIC",  0, do_pic,    "-fPIC            Generate PIC code" },
100     { "-h",     0, do_usage,  "-h               Display this help message" },
101     { "-o",     1, do_output, "-o name          Set the output file name (default: stdout)" },
102     { "-spec",  1, do_spec,   "-spec file.spec  Build a .c file from a spec file" },
103     { "-glue",  1, do_glue,   "-glue file.c     Build the 16-bit glue for a .c file" },
104     { "-relay", 0, do_relay,  "-relay           Build the relay assembly routines" },
105     { NULL,     0, NULL,      NULL }
106 };
107
108 static void do_pic(void)
109 {
110     UsePIC = 1;
111 }
112
113 static void do_output( const char *arg )
114 {
115     if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) ) 
116     {
117         fprintf ( stderr, "Unable to create output file '%s'\n", arg );
118         exit (1);
119     }
120     if (!(output_file = fopen( arg, "w" )))
121     {
122         fprintf( stderr, "Unable to create output file '%s'\n", arg );
123         exit(1);
124     }
125     output_file_name = arg;
126     atexit( cleanup );  /* make sure we remove the output file on exit */
127 }
128
129 static void do_usage(void)
130 {
131     const struct option *opt;
132     fprintf( stderr, "Usage: winebuild [options]\n\n" );
133     fprintf( stderr, "Options:\n" );
134     for (opt = option_table; opt->name; opt++) fprintf( stderr, "   %s\n", opt->usage );
135     fprintf( stderr, "\nExactly one of -spec, -glue or -relay must be specified.\n\n" );
136     exit(1);
137 }
138
139 static void do_spec( const char *arg )
140 {
141     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
142     exec_mode = MODE_SPEC;
143     open_input( arg );
144 }
145
146 static void do_glue( const char *arg )
147 {
148     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
149     exec_mode = MODE_GLUE;
150     open_input( arg );
151 }
152
153 static void do_relay(void)
154 {
155     if (exec_mode != MODE_NONE) do_usage();
156     exec_mode = MODE_RELAY;
157 }
158
159
160 /* parse options from the argv array and remove all the recognized ones */
161 static void parse_options( char *argv[] )
162 {
163     const struct option *opt;
164     int i;
165
166     for (i = 1; argv[i]; i++)
167     {
168         for (opt = option_table; opt->name; opt++)
169             if (!strcmp( argv[i], opt->name )) break;
170
171         if (!opt->name)
172         {
173             fprintf( stderr, "Unrecognized option '%s'\n", argv[i] );
174             do_usage();
175         }
176
177         if (opt->has_arg && argv[i+1]) opt->func( argv[++i] );
178         else opt->func( "" );
179     }
180 }
181
182
183 /*******************************************************************
184  *         main
185  */
186 int main(int argc, char **argv)
187 {
188     output_file = stdout;
189     parse_options( argv );
190
191     /* Retrieve the selector values; this assumes that we are building
192      * the asm files on the platform that will also run them. Probably
193      * a safe assumption to make.
194      */
195     code_selector = __get_cs();
196     data_selector = __get_ds();
197
198     switch(exec_mode)
199     {
200     case MODE_SPEC:
201         switch (ParseTopLevel( input_file ))
202         {
203             case SPEC_WIN16:
204                 BuildSpec16File( output_file );
205                 break;
206             case SPEC_WIN32:
207                 BuildSpec32File( output_file );
208                 break;
209             default: assert(0);
210         }
211         break;
212     case MODE_GLUE:
213         BuildGlue( output_file, input_file );
214         break;
215     case MODE_RELAY:
216         BuildRelays( output_file );
217         break;
218     default:
219         do_usage();
220         break;
221     }
222     fclose( output_file );
223     output_file_name = NULL;
224     return 0;
225 }