- Minor API files fixes.
[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 "winnt.h"
17 #include "build.h"
18
19 #ifdef __i386__
20 extern WORD __get_cs(void);
21 extern WORD __get_ds(void);
22 __ASM_GLOBAL_FUNC( __get_cs, "movw %cs,%ax\n\tret" );
23 __ASM_GLOBAL_FUNC( __get_ds, "movw %ds,%ax\n\tret" );
24 #else
25 static inline WORD __get_cs(void) { return 0; }
26 static inline WORD __get_ds(void) { return 0; }
27 #endif
28
29
30 ORDDEF EntryPoints[MAX_ORDINALS];
31 ORDDEF *Ordinals[MAX_ORDINALS];
32 ORDDEF *Names[MAX_ORDINALS];
33
34 SPEC_MODE SpecMode = SPEC_MODE_DLL;
35 int Base = MAX_ORDINALS;
36 int Limit = 0;
37 int DLLHeapSize = 0;
38 int UsePIC = 0;
39 int nb_entry_points = 0;
40 int nb_names = 0;
41 int nb_imports = 0;
42 int debugging = 1;
43
44 char DLLName[80];
45 char DLLFileName[80];
46 char DLLInitFunc[80];
47 char *DLLImports[MAX_IMPORTS];
48 char rsrc_name[80];
49
50 const char *input_file_name;
51 const char *output_file_name;
52
53 unsigned short code_selector;
54 unsigned short data_selector;
55
56 static FILE *input_file;
57 static FILE *output_file;
58
59 /* execution mode */
60 static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE;
61
62 /* open the input file */
63 static void open_input( const char *name )
64 {
65     input_file_name = name;
66     if (!(input_file = fopen( name, "r" )))
67     {
68         fprintf( stderr, "Cannot open input file '%s'\n", name );
69         exit(1);
70     }
71 }
72
73 /* cleanup on program exit */
74 static void cleanup(void)
75 {
76     if (output_file_name) unlink( output_file_name );
77 }
78
79
80 /*******************************************************************
81  *         command-line option handling
82  */
83
84 struct option
85 {
86     const char *name;
87     int         has_arg;
88     void      (*func)();
89     const char *usage;
90 };
91
92 static void do_pic(void);
93 static void do_output( const char *arg );
94 static void do_usage(void);
95 static void do_spec( const char *arg );
96 static void do_glue( const char *arg );
97 static void do_relay(void);
98
99 static const struct option option_table[] =
100 {
101     { "-fPIC",  0, do_pic,    "-fPIC            Generate PIC code" },
102     { "-h",     0, do_usage,  "-h               Display this help message" },
103     { "-o",     1, do_output, "-o name          Set the output file name (default: stdout)" },
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 }
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 *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
162 /* parse options from the argv array and remove all the recognized ones */
163 static void parse_options( char *argv[] )
164 {
165     const struct option *opt;
166     int i;
167
168     for (i = 1; argv[i]; i++)
169     {
170         for (opt = option_table; opt->name; opt++)
171             if (!strcmp( argv[i], opt->name )) break;
172
173         if (!opt->name)
174         {
175             fprintf( stderr, "Unrecognized option '%s'\n", argv[i] );
176             do_usage();
177         }
178
179         if (opt->has_arg && argv[i+1]) opt->func( argv[++i] );
180         else opt->func( "" );
181     }
182 }
183
184
185 /*******************************************************************
186  *         main
187  */
188 int main(int argc, char **argv)
189 {
190     output_file = stdout;
191     parse_options( argv );
192
193     /* Retrieve the selector values; this assumes that we are building
194      * the asm files on the platform that will also run them. Probably
195      * a safe assumption to make.
196      */
197     code_selector = __get_cs();
198     data_selector = __get_ds();
199
200     switch(exec_mode)
201     {
202     case MODE_SPEC:
203         switch (ParseTopLevel( input_file ))
204         {
205             case SPEC_WIN16:
206                 BuildSpec16File( output_file );
207                 break;
208             case SPEC_WIN32:
209                 BuildSpec32File( output_file );
210                 break;
211             default: assert(0);
212         }
213         break;
214     case MODE_GLUE:
215         BuildGlue( output_file, input_file );
216         break;
217     case MODE_RELAY:
218         BuildRelays( output_file );
219         break;
220     default:
221         do_usage();
222         break;
223     }
224     fclose( output_file );
225     output_file_name = NULL;
226     return 0;
227 }