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