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