Changed the GDI driver interface to pass an opaque PHYSDEV pointer
[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
27 #include <assert.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <string.h>
31
32 #include "build.h"
33
34 ORDDEF *EntryPoints[MAX_ORDINALS];
35 ORDDEF *Ordinals[MAX_ORDINALS];
36 ORDDEF *Names[MAX_ORDINALS];
37
38 SPEC_MODE SpecMode = SPEC_MODE_DLL;
39 int Base = MAX_ORDINALS;
40 int Limit = 0;
41 int DLLHeapSize = 0;
42 int UsePIC = 0;
43 int stack_size = 0;
44 int nb_entry_points = 0;
45 int nb_names = 0;
46 int nb_debug_channels = 0;
47 int nb_lib_paths = 0;
48 int display_warnings = 0;
49
50 /* we only support relay debugging on i386 */
51 #if defined(__i386__) && !defined(NO_TRACE_MSGS)
52 int debugging = 1;
53 #else
54 int debugging = 0;
55 #endif
56
57 char DLLName[80];
58 char DLLFileName[80];
59 char owner_name[80];
60 char *init_func = NULL;
61 char **debug_channels = NULL;
62 char **lib_path = NULL;
63
64 const char *input_file_name;
65 const char *output_file_name;
66
67 static FILE *input_file;
68 static FILE *output_file;
69
70 /* execution mode */
71 static enum
72 {
73     MODE_NONE,
74     MODE_SPEC,
75     MODE_GLUE,
76     MODE_DEF,
77     MODE_RELAY16,
78     MODE_RELAY32
79 } exec_mode = MODE_NONE;
80
81 /* open the input file */
82 static void open_input( const char *name )
83 {
84     input_file_name = name;
85     if (!(input_file = fopen( name, "r" )))
86     {
87         fprintf( stderr, "Cannot open input file '%s'\n", name );
88         exit(1);
89     }
90 }
91
92 /* cleanup on program exit */
93 static void cleanup(void)
94 {
95     if (output_file_name) unlink( output_file_name );
96 }
97
98
99 /*******************************************************************
100  *         command-line option handling
101  */
102
103 struct option_descr
104 {
105     const char *name;
106     int         has_arg;
107     void      (*func)();
108     const char *usage;
109 };
110
111 static void do_pic(void);
112 static void do_output( const char *arg );
113 static void do_usage(void);
114 static void do_warnings(void);
115 static void do_spec( const char *arg );
116 static void do_def( const char *arg );
117 static void do_glue( const char *arg );
118 static void do_relay16(void);
119 static void do_relay32(void);
120 static void do_sym( const char *arg );
121 static void do_lib( const char *arg );
122
123 static const struct option_descr option_table[] =
124 {
125     { "-fPIC",    0, do_pic,     "-fPIC            Generate PIC code" },
126     { "-h",       0, do_usage,   "-h               Display this help message" },
127     { "-w",       0, do_warnings,"-w               Turn on warnings" },
128     { "-L",       1, do_lib,     "-L directory     Look for imports libraries in 'directory'" },
129     { "-o",       1, do_output,  "-o name          Set the output file name (default: stdout)" },
130     { "-sym",     1, do_sym,     "-sym file.o      Read the list of undefined symbols from 'file.o'" },
131     { "-spec",    1, do_spec,    "-spec file.spec  Build a .c file from a spec file" },
132     { "-def",     1, do_def,     "-def file.spec   Build a .def file from a spec file" },
133     { "-glue",    1, do_glue,    "-glue file.c     Build the 16-bit glue for a .c file" },
134     { "-relay16", 0, do_relay16, "-relay16         Build the 16-bit relay assembly routines" },
135     { "-relay32", 0, do_relay32, "-relay32         Build the 32-bit relay assembly routines" },
136     { NULL,       0, NULL,      NULL }
137 };
138
139 static void do_pic(void)
140 {
141     UsePIC = 1;
142 }
143
144 static void do_output( const char *arg )
145 {
146     if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) ) 
147     {
148         fprintf ( stderr, "Unable to create output file '%s'\n", arg );
149         exit (1);
150     }
151     if (!(output_file = fopen( arg, "w" )))
152     {
153         fprintf( stderr, "Unable to create output file '%s'\n", arg );
154         exit(1);
155     }
156     output_file_name = arg;
157     atexit( cleanup );  /* make sure we remove the output file on exit */
158 }
159
160 static void do_usage(void)
161 {
162     const struct option_descr *opt;
163     fprintf( stderr, "Usage: winebuild [options]\n\n" );
164     fprintf( stderr, "Options:\n" );
165     for (opt = option_table; opt->name; opt++) fprintf( stderr, "   %s\n", opt->usage );
166     fprintf( stderr, "\nExactly one of -spec, -glue or -relay must be specified.\n\n" );
167     exit(1);
168 }
169
170 static void do_warnings(void)
171 {
172     display_warnings = 1;
173 }
174
175 static void do_spec( const char *arg )
176 {
177     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
178     exec_mode = MODE_SPEC;
179     open_input( arg );
180 }
181
182 static void do_def( const char *arg )
183 {
184     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
185     exec_mode = MODE_DEF;
186     open_input( arg );
187 }
188
189 static void do_glue( const char *arg )
190 {
191     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
192     exec_mode = MODE_GLUE;
193     open_input( arg );
194 }
195
196 static void do_relay16(void)
197 {
198     if (exec_mode != MODE_NONE) do_usage();
199     exec_mode = MODE_RELAY16;
200 }
201
202 static void do_relay32(void)
203 {
204     if (exec_mode != MODE_NONE) do_usage();
205     exec_mode = MODE_RELAY32;
206 }
207
208 static void do_sym( const char *arg )
209 {
210     extern void read_undef_symbols( const char *name );
211     read_undef_symbols( arg );
212 }
213
214 static void do_lib( const char *arg )
215 {
216     lib_path = xrealloc( lib_path, (nb_lib_paths+1) * sizeof(*lib_path) );
217     lib_path[nb_lib_paths++] = xstrdup( arg );
218 }
219
220 /* parse options from the argv array and remove all the recognized ones */
221 static void parse_options( char *argv[] )
222 {
223     const struct option_descr *opt;
224     char * const * ptr;
225     const char* arg=NULL;
226
227     ptr=argv+1;
228     while (*ptr != NULL)
229     {
230         for (opt = option_table; opt->name; opt++)
231         {
232             if (opt->has_arg && !strncmp( *ptr, opt->name, strlen(opt->name) ))
233             {
234                 arg=*ptr+strlen(opt->name);
235                 if (*arg=='\0')
236                 {
237                     ptr++;
238                     arg=*ptr;
239                 }
240                 break;
241             }
242             if (!strcmp( *ptr, opt->name ))
243             {
244                 arg=NULL;
245                 break;
246             }
247         }
248
249         if (!opt->name)
250         {
251             fprintf( stderr, "Unrecognized option '%s'\n", *ptr );
252             do_usage();
253         }
254
255         if (opt->has_arg && arg!=NULL) opt->func( arg );
256         else opt->func( "" );
257         ptr++;
258     }
259 }
260
261
262 /*******************************************************************
263  *         main
264  */
265 int main(int argc, char **argv)
266 {
267     output_file = stdout;
268     parse_options( argv );
269
270     switch(exec_mode)
271     {
272     case MODE_SPEC:
273         switch (ParseTopLevel( input_file, 0 ))
274         {
275             case SPEC_WIN16:
276                 BuildSpec16File( output_file );
277                 break;
278             case SPEC_WIN32:
279                 BuildSpec32File( output_file );
280                 break;
281             default: assert(0);
282         }
283         break;
284     case MODE_DEF:
285         switch (ParseTopLevel( input_file, 1 ))
286         {
287             case SPEC_WIN16:
288                 fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
289                 break;
290             case SPEC_WIN32:
291                 BuildDef32File( output_file );
292                 break;
293             default: assert(0);
294         }
295         break;
296     case MODE_GLUE:
297         BuildGlue( output_file, input_file );
298         break;
299     case MODE_RELAY16:
300         BuildRelays16( output_file );
301         break;
302     case MODE_RELAY32:
303         BuildRelays32( output_file );
304         break;
305     default:
306         do_usage();
307         break;
308     }
309     if (output_file_name)
310     {
311         fclose( output_file );
312         output_file_name = NULL;
313     }
314     return 0;
315 }