Renamed struct option to avoid conflicts with getopt.h.
[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 "config.h"
17 #include "winnt.h"
18 #include "build.h"
19
20 ORDDEF *EntryPoints[MAX_ORDINALS];
21 ORDDEF *Ordinals[MAX_ORDINALS];
22 ORDDEF *Names[MAX_ORDINALS];
23
24 SPEC_MODE SpecMode = SPEC_MODE_DLL;
25 int Base = MAX_ORDINALS;
26 int Limit = 0;
27 int DLLHeapSize = 0;
28 int UsePIC = 0;
29 int nb_entry_points = 0;
30 int nb_names = 0;
31 int nb_debug_channels = 0;
32 int nb_lib_paths = 0;
33
34 /* we only support relay debugging on i386 */
35 #if defined(__i386__) && !defined(NO_TRACE_MSGS)
36 int debugging = 1;
37 #else
38 int debugging = 0;
39 #endif
40
41 char DLLName[80];
42 char DLLFileName[80];
43 char owner_name[80];
44 char *init_func = NULL;
45 char **debug_channels = NULL;
46 char **lib_path = NULL;
47
48 const char *input_file_name;
49 const char *output_file_name;
50
51 static FILE *input_file;
52 static FILE *output_file;
53
54 /* execution mode */
55 static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE;
56
57 /* open the input file */
58 static void open_input( const char *name )
59 {
60     input_file_name = name;
61     if (!(input_file = fopen( name, "r" )))
62     {
63         fprintf( stderr, "Cannot open input file '%s'\n", name );
64         exit(1);
65     }
66 }
67
68 /* cleanup on program exit */
69 static void cleanup(void)
70 {
71     if (output_file_name) unlink( output_file_name );
72 }
73
74
75 /*******************************************************************
76  *         command-line option handling
77  */
78
79 struct option_descr
80 {
81     const char *name;
82     int         has_arg;
83     void      (*func)();
84     const char *usage;
85 };
86
87 static void do_pic(void);
88 static void do_output( const char *arg );
89 static void do_usage(void);
90 static void do_spec( const char *arg );
91 static void do_glue( const char *arg );
92 static void do_relay(void);
93 static void do_sym( const char *arg );
94 static void do_lib( const char *arg );
95
96 static const struct option_descr option_table[] =
97 {
98     { "-fPIC",  0, do_pic,    "-fPIC            Generate PIC code" },
99     { "-h",     0, do_usage,  "-h               Display this help message" },
100     { "-L",     1, do_lib,    "-L directory     Look for imports libraries in 'directory'" },
101     { "-o",     1, do_output, "-o name          Set the output file name (default: stdout)" },
102     { "-sym",   1, do_sym,    "-sym file.o      Read the list of undefined symbols from 'file.o'" },
103     { "-spec",  1, do_spec,   "-spec file.spec  Build a .c file from a spec file" },
104     { "-glue",  1, do_glue,   "-glue file.c     Build the 16-bit glue for a .c file" },
105     { "-relay", 0, do_relay,  "-relay           Build the relay assembly routines" },
106     { NULL,     0, NULL,      NULL }
107 };
108
109 static void do_pic(void)
110 {
111     UsePIC = 1;
112 }
113
114 static void do_output( const char *arg )
115 {
116     if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) ) 
117     {
118         fprintf ( stderr, "Unable to create output file '%s'\n", arg );
119         exit (1);
120     }
121     if (!(output_file = fopen( arg, "w" )))
122     {
123         fprintf( stderr, "Unable to create output file '%s'\n", arg );
124         exit(1);
125     }
126     output_file_name = arg;
127     atexit( cleanup );  /* make sure we remove the output file on exit */
128 }
129
130 static void do_usage(void)
131 {
132     const struct option_descr *opt;
133     fprintf( stderr, "Usage: winebuild [options]\n\n" );
134     fprintf( stderr, "Options:\n" );
135     for (opt = option_table; opt->name; opt++) fprintf( stderr, "   %s\n", opt->usage );
136     fprintf( stderr, "\nExactly one of -spec, -glue or -relay must be specified.\n\n" );
137     exit(1);
138 }
139
140 static void do_spec( const char *arg )
141 {
142     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
143     exec_mode = MODE_SPEC;
144     open_input( arg );
145 }
146
147 static void do_glue( const char *arg )
148 {
149     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
150     exec_mode = MODE_GLUE;
151     open_input( arg );
152 }
153
154 static void do_relay(void)
155 {
156     if (exec_mode != MODE_NONE) do_usage();
157     exec_mode = MODE_RELAY;
158 }
159
160 static void do_sym( const char *arg )
161 {
162     extern void read_undef_symbols( const char *name );
163     read_undef_symbols( arg );
164 }
165
166 static void do_lib( const char *arg )
167 {
168     lib_path = xrealloc( lib_path, (nb_lib_paths+1) * sizeof(*lib_path) );
169     lib_path[nb_lib_paths++] = xstrdup( arg );
170 }
171
172 /* parse options from the argv array and remove all the recognized ones */
173 static void parse_options( char *argv[] )
174 {
175     const struct option_descr *opt;
176     char * const * ptr;
177     const char* arg=NULL;
178
179     ptr=argv+1;
180     while (*ptr != NULL)
181     {
182         for (opt = option_table; opt->name; opt++)
183         {
184             if (opt->has_arg && !strncmp( *ptr, opt->name, strlen(opt->name) ))
185             {
186                 arg=*ptr+strlen(opt->name);
187                 if (*arg=='\0')
188                 {
189                     ptr++;
190                     arg=*ptr;
191                 }
192                 break;
193             }
194             if (!strcmp( *ptr, opt->name ))
195             {
196                 arg=NULL;
197                 break;
198             }
199         }
200
201         if (!opt->name)
202         {
203             fprintf( stderr, "Unrecognized option '%s'\n", *ptr );
204             do_usage();
205         }
206
207         if (opt->has_arg && arg!=NULL) opt->func( arg );
208         else opt->func( "" );
209         ptr++;
210     }
211 }
212
213
214 /*******************************************************************
215  *         main
216  */
217 int main(int argc, char **argv)
218 {
219     output_file = stdout;
220     parse_options( argv );
221
222     switch(exec_mode)
223     {
224     case MODE_SPEC:
225         switch (ParseTopLevel( input_file ))
226         {
227             case SPEC_WIN16:
228                 BuildSpec16File( output_file );
229                 break;
230             case SPEC_WIN32:
231                 BuildSpec32File( output_file );
232                 break;
233             default: assert(0);
234         }
235         break;
236     case MODE_GLUE:
237         BuildGlue( output_file, input_file );
238         break;
239     case MODE_RELAY:
240         BuildRelays( output_file );
241         break;
242     default:
243         do_usage();
244         break;
245     }
246     fclose( output_file );
247     output_file_name = NULL;
248     return 0;
249 }