Generate Win32 dll descriptor structure in the .spec.c file so that we
[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 char owner_name[80];
50
51 const char *input_file_name;
52 const char *output_file_name;
53
54 unsigned short code_selector;
55 unsigned short data_selector;
56
57 static FILE *input_file;
58 static FILE *output_file;
59
60 /* execution mode */
61 static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE;
62
63 /* open the input file */
64 static void open_input( const char *name )
65 {
66     input_file_name = name;
67     if (!(input_file = fopen( name, "r" )))
68     {
69         fprintf( stderr, "Cannot open input file '%s'\n", name );
70         exit(1);
71     }
72 }
73
74 /* cleanup on program exit */
75 static void cleanup(void)
76 {
77     if (output_file_name) unlink( output_file_name );
78 }
79
80
81 /*******************************************************************
82  *         command-line option handling
83  */
84
85 struct option
86 {
87     const char *name;
88     int         has_arg;
89     void      (*func)();
90     const char *usage;
91 };
92
93 static void do_pic(void);
94 static void do_output( const char *arg );
95 static void do_usage(void);
96 static void do_spec( const char *arg );
97 static void do_glue( const char *arg );
98 static void do_relay(void);
99
100 static const struct option option_table[] =
101 {
102     { "-fPIC",  0, do_pic,    "-fPIC            Generate PIC code" },
103     { "-h",     0, do_usage,  "-h               Display this help message" },
104     { "-o",     1, do_output, "-o name          Set the output file name (default: stdout)" },
105     { "-spec",  1, do_spec,   "-spec file.spec  Build a .c file from a spec file" },
106     { "-glue",  1, do_glue,   "-glue file.c     Build the 16-bit glue for a .c file" },
107     { "-relay", 0, do_relay,  "-relay           Build the relay assembly routines" },
108     { NULL }
109 };
110
111 static void do_pic(void)
112 {
113     UsePIC = 1;
114 }
115
116 static void do_output( const char *arg )
117 {
118     if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) ) 
119     {
120         fprintf ( stderr, "Unable to create output file '%s'\n", arg );
121         exit (1);
122     }
123     if (!(output_file = fopen( arg, "w" )))
124     {
125         fprintf( stderr, "Unable to create output file '%s'\n", arg );
126         exit(1);
127     }
128     output_file_name = arg;
129     atexit( cleanup );  /* make sure we remove the output file on exit */
130 }
131
132 static void do_usage(void)
133 {
134     const struct option *opt;
135     fprintf( stderr, "Usage: winebuild [options]\n\n" );
136     fprintf( stderr, "Options:\n" );
137     for (opt = option_table; opt->name; opt++) fprintf( stderr, "   %s\n", opt->usage );
138     fprintf( stderr, "\nExactly one of -spec, -glue or -relay must be specified.\n\n" );
139     exit(1);
140 }
141
142 static void do_spec( const char *arg )
143 {
144     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
145     exec_mode = MODE_SPEC;
146     open_input( arg );
147 }
148
149 static void do_glue( const char *arg )
150 {
151     if (exec_mode != MODE_NONE || !arg[0]) do_usage();
152     exec_mode = MODE_GLUE;
153     open_input( arg );
154 }
155
156 static void do_relay(void)
157 {
158     if (exec_mode != MODE_NONE) do_usage();
159     exec_mode = MODE_RELAY;
160 }
161
162
163 /* parse options from the argv array and remove all the recognized ones */
164 static void parse_options( char *argv[] )
165 {
166     const struct option *opt;
167     int i;
168
169     for (i = 1; argv[i]; i++)
170     {
171         for (opt = option_table; opt->name; opt++)
172             if (!strcmp( argv[i], opt->name )) break;
173
174         if (!opt->name)
175         {
176             fprintf( stderr, "Unrecognized option '%s'\n", argv[i] );
177             do_usage();
178         }
179
180         if (opt->has_arg && argv[i+1]) opt->func( argv[++i] );
181         else opt->func( "" );
182     }
183 }
184
185
186 /*******************************************************************
187  *         main
188  */
189 int main(int argc, char **argv)
190 {
191     output_file = stdout;
192     parse_options( argv );
193
194     /* Retrieve the selector values; this assumes that we are building
195      * the asm files on the platform that will also run them. Probably
196      * a safe assumption to make.
197      */
198     code_selector = __get_cs();
199     data_selector = __get_ds();
200
201     switch(exec_mode)
202     {
203     case MODE_SPEC:
204         switch (ParseTopLevel( input_file ))
205         {
206             case SPEC_WIN16:
207                 BuildSpec16File( output_file );
208                 break;
209             case SPEC_WIN32:
210                 BuildSpec32File( output_file );
211                 break;
212             default: assert(0);
213         }
214         break;
215     case MODE_GLUE:
216         BuildGlue( output_file, input_file );
217         break;
218     case MODE_RELAY:
219         BuildRelays( output_file );
220         break;
221     default:
222         do_usage();
223         break;
224     }
225     fclose( output_file );
226     output_file_name = NULL;
227     return 0;
228 }