Removed trailing whitespace.
[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  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
24
25 #include "config.h"
26 #include "wine/port.h"
27
28 #include <assert.h>
29 #include <stdio.h>
30 #include <errno.h>
31 #include <string.h>
32
33 #include "build.h"
34
35 ORDDEF *EntryPoints[MAX_ORDINALS];
36 ORDDEF *Ordinals[MAX_ORDINALS];
37 ORDDEF *Names[MAX_ORDINALS];
38
39 SPEC_MODE SpecMode = SPEC_MODE_DLL;
40 int Base = MAX_ORDINALS;
41 int Limit = 0;
42 int DLLHeapSize = 0;
43 int UsePIC = 0;
44 int stack_size = 0;
45 int nb_entry_points = 0;
46 int nb_names = 0;
47 int nb_debug_channels = 0;
48 int nb_lib_paths = 0;
49 int display_warnings = 0;
50
51 /* we only support relay debugging on i386 */
52 #if defined(__i386__) && !defined(NO_TRACE_MSGS)
53 int debugging = 1;
54 #else
55 int debugging = 0;
56 #endif
57
58 char DLLName[80];
59 char DLLFileName[80];
60 char owner_name[80];
61 char *init_func = NULL;
62 char **debug_channels = NULL;
63 char **lib_path = NULL;
64
65 const char *input_file_name;
66 const char *output_file_name;
67
68 static FILE *input_file;
69 static FILE *output_file;
70 static const char *current_src_dir;
71
72 /* execution mode */
73 static enum
74 {
75     MODE_NONE,
76     MODE_SPEC,
77     MODE_EXE,
78     MODE_GLUE,
79     MODE_DEF,
80     MODE_DEBUG,
81     MODE_RELAY16,
82     MODE_RELAY32
83 } exec_mode = MODE_NONE;
84
85 /* open the input file */
86 static void open_input( const char *name )
87 {
88     input_file_name = name;
89     if (!(input_file = fopen( name, "r" )))
90     {
91         fprintf( stderr, "Cannot open input file '%s'\n", name );
92         exit(1);
93     }
94 }
95
96 /* cleanup on program exit */
97 static void cleanup(void)
98 {
99     if (output_file_name) unlink( output_file_name );
100 }
101
102
103 /*******************************************************************
104  *         command-line option handling
105  */
106
107 struct option_descr
108 {
109     const char *name;
110     int         has_arg;
111     void      (*func)();
112     const char *usage;
113 };
114
115 static void do_output( const char *arg );
116 static void do_usage(void);
117 static void do_warnings(void);
118 static void do_f_flags( const char *arg );
119 static void do_define( const char *arg );
120 static void do_include( const char *arg );
121 static void do_exe_mode( const char *arg );
122 static void do_spec( const char *arg );
123 static void do_def( const char *arg );
124 static void do_exe( const char *arg );
125 static void do_glue( const char *arg );
126 static void do_relay16(void);
127 static void do_relay32(void);
128 static void do_debug(void);
129 static void do_sym( const char *arg );
130 static void do_chdir( const char *arg );
131 static void do_lib( const char *arg );
132 static void do_import( const char *arg );
133 static void do_dimport( const char *arg );
134 static void do_rsrc( const char *arg );
135
136 static const struct option_descr option_table[] =
137 {
138     { "-h",       0, do_usage,   "-h               Display this help message" },
139     { "-w",       0, do_warnings,"-w               Turn on warnings" },
140     { "-C",       1, do_chdir,   "-C dir           Change directory to <dir> before opening source files" },
141     { "-f",       1, do_f_flags, "-f flags         Compiler flags (only -fPIC is supported)" },
142     { "-D",       1, do_define,  "-D sym           Ignored for C flags compatibility" },
143     { "-I",       1, do_include, "-I dir           Ignored for C flags compatibility" },
144     { "-m",       1, do_exe_mode,"-m mode          Set the executable mode (cui|gui|cuiw|guiw)" },
145     { "-L",       1, do_lib,     "-L directory     Look for imports libraries in 'directory'" },
146     { "-l",       1, do_import,  "-l lib.dll       Import the specified library" },
147     { "-dl",      1, do_dimport, "-dl lib.dll      Delay-import the specified library" },
148     { "-res",     1, do_rsrc,    "-res rsrc.res    Load resources from rsrc.res" },
149     { "-o",       1, do_output,  "-o name          Set the output file name (default: stdout)" },
150     { "-sym",     1, do_sym,     "-sym file.o      Read the list of undefined symbols from 'file.o'\n" },
151     { "-spec",    1, do_spec,    "-spec file.spec  Build a .c file from a spec file" },
152     { "-def",     1, do_def,     "-def file.spec   Build a .def file from a spec file" },
153     { "-exe",     1, do_exe,     "-exe name        Build a .c file from the named executable" },
154     { "-debug",   0, do_debug,   "-debug [files]   Build a .c file containing debug channels declarations" },
155     { "-glue",    1, do_glue,    "-glue file.c     Build the 16-bit glue for a .c file" },
156     { "-relay16", 0, do_relay16, "-relay16         Build the 16-bit relay assembly routines" },
157     { "-relay32", 0, do_relay32, "-relay32         Build the 32-bit relay assembly routines" },
158     { NULL,       0, NULL,      NULL }
159 };
160
161 static void do_output( const char *arg )
162 {
163     if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) )
164     {
165         fprintf ( stderr, "Unable to create output file '%s'\n", arg );
166         exit (1);
167     }
168     if (!(output_file = fopen( arg, "w" )))
169     {
170         fprintf( stderr, "Unable to create output file '%s'\n", arg );
171         exit(1);
172     }
173     output_file_name = arg;
174     atexit( cleanup );  /* make sure we remove the output file on exit */
175 }
176
177 static void do_usage(void)
178 {
179     const struct option_descr *opt;
180     fprintf( stderr, "Usage: winebuild [options]\n\n" );
181     fprintf( stderr, "Options:\n" );
182     for (opt = option_table; opt->name; opt++) fprintf( stderr, "   %s\n", opt->usage );
183     fprintf( stderr, "\nExactly one of -spec, -def, -exe, -debug, -glue, -relay16 or -relay32 must be specified.\n\n" );
184     exit(1);
185 }
186
187 static void do_warnings(void)
188 {
189     display_warnings = 1;
190 }
191
192 static void do_f_flags( const char *arg )
193 {
194     if (!strcmp( arg, "PIC" )) UsePIC = 1;
195     /* ignore all other flags */
196 }
197
198 static void do_define( const char *arg )
199 {
200     /* nothing */
201 }
202
203 static void do_include( const char *arg )
204 {
205     /* nothing */
206 }
207
208 static void do_spec( const char *arg )
209 {
210     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
211     exec_mode = MODE_SPEC;
212     open_input( arg );
213 }
214
215 static void do_def( const char *arg )
216 {
217     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
218     exec_mode = MODE_DEF;
219     open_input( arg );
220 }
221
222 static void do_exe( const char *arg )
223 {
224     const char *p;
225
226     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
227     exec_mode = MODE_EXE;
228     if ((p = strrchr( arg, '/' ))) p++;
229     else p = arg;
230     strcpy( DLLName, p );
231     strcpy( DLLFileName, p );
232     if (!strchr( DLLFileName, '.' )) strcat( DLLFileName, ".exe" );
233     if (SpecMode == SPEC_MODE_DLL) SpecMode = SPEC_MODE_GUIEXE;
234 }
235
236 static void do_exe_mode( const char *arg )
237 {
238     if (!strcmp( arg, "gui" )) SpecMode = SPEC_MODE_GUIEXE;
239     else if (!strcmp( arg, "cui" )) SpecMode = SPEC_MODE_CUIEXE;
240     else if (!strcmp( arg, "guiw" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE;
241     else if (!strcmp( arg, "cuiw" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE;
242     else do_usage();
243 }
244
245 static void do_glue( const char *arg )
246 {
247     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
248     exec_mode = MODE_GLUE;
249     open_input( arg );
250 }
251
252 static void do_debug(void)
253 {
254     if (exec_mode != MODE_NONE) do_usage();
255     exec_mode = MODE_DEBUG;
256 }
257
258 static void do_chdir( const char *arg )
259 {
260     current_src_dir = arg;
261 }
262
263 static void do_relay16(void)
264 {
265     if (exec_mode != MODE_NONE) do_usage();
266     exec_mode = MODE_RELAY16;
267 }
268
269 static void do_relay32(void)
270 {
271     if (exec_mode != MODE_NONE) do_usage();
272     exec_mode = MODE_RELAY32;
273 }
274
275 static void do_sym( const char *arg )
276 {
277     extern void read_undef_symbols( const char *name );
278     read_undef_symbols( arg );
279 }
280
281 static void do_lib( const char *arg )
282 {
283     lib_path = xrealloc( lib_path, (nb_lib_paths+1) * sizeof(*lib_path) );
284     lib_path[nb_lib_paths++] = xstrdup( arg );
285 }
286
287 static void do_import( const char *arg )
288 {
289     add_import_dll( arg, 0 );
290 }
291
292 static void do_dimport( const char *arg )
293 {
294     add_import_dll( arg, 1 );
295 }
296
297 static void do_rsrc( const char *arg )
298 {
299     load_res32_file( arg );
300 }
301
302 /* parse options from the argv array and remove all the recognized ones */
303 static void parse_options( char *argv[] )
304 {
305     const struct option_descr *opt;
306     char * const * ptr;
307     const char* arg=NULL;
308
309     for (ptr = argv + 1; *ptr; ptr++)
310     {
311         for (opt = option_table; opt->name; opt++)
312         {
313             if (opt->has_arg && !strncmp( *ptr, opt->name, strlen(opt->name) ))
314             {
315                 arg=*ptr+strlen(opt->name);
316                 if (*arg=='\0')
317                 {
318                     ptr++;
319                     arg=*ptr;
320                 }
321                 break;
322             }
323             if (!strcmp( *ptr, opt->name ))
324             {
325                 arg=NULL;
326                 break;
327             }
328         }
329
330         if (!opt->name)
331         {
332             if (exec_mode == MODE_DEBUG && **ptr != '-')
333             {
334                 /* this a file name to parse for debug channels */
335                 parse_debug_channels( current_src_dir, *ptr );
336                 continue;
337             }
338             fprintf( stderr, "Unrecognized option '%s'\n", *ptr );
339             do_usage();
340         }
341
342         if (opt->has_arg && arg!=NULL) opt->func( arg );
343         else opt->func( "" );
344     }
345 }
346
347
348 /*******************************************************************
349  *         main
350  */
351 int main(int argc, char **argv)
352 {
353     output_file = stdout;
354     parse_options( argv );
355
356     switch(exec_mode)
357     {
358     case MODE_SPEC:
359         switch (ParseTopLevel( input_file, 0 ))
360         {
361             case SPEC_WIN16:
362                 BuildSpec16File( output_file );
363                 break;
364             case SPEC_WIN32:
365                 BuildSpec32File( output_file );
366                 break;
367             default: assert(0);
368         }
369         break;
370     case MODE_EXE:
371         BuildSpec32File( output_file );
372         break;
373     case MODE_DEF:
374         switch (ParseTopLevel( input_file, 1 ))
375         {
376             case SPEC_WIN16:
377                 fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
378                 break;
379             case SPEC_WIN32:
380                 BuildDef32File( output_file );
381                 break;
382             default: assert(0);
383         }
384         break;
385     case MODE_DEBUG:
386         BuildDebugFile( output_file );
387         break;
388     case MODE_GLUE:
389         BuildGlue( output_file, input_file );
390         break;
391     case MODE_RELAY16:
392         BuildRelays16( output_file );
393         break;
394     case MODE_RELAY32:
395         BuildRelays32( output_file );
396         break;
397     default:
398         do_usage();
399         break;
400     }
401     if (output_file_name)
402     {
403         fclose( output_file );
404         output_file_name = NULL;
405     }
406     return 0;
407 }