Added stdcall64 entry point type to allow correct relay debugging
[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 debugging = 1;
42
43 char DLLName[80];
44 char DLLFileName[80];
45 char DLLInitFunc[80];
46 char rsrc_name[80];
47 char owner_name[80];
48
49 const char *input_file_name;
50 const char *output_file_name;
51
52 unsigned short code_selector;
53 unsigned short data_selector;
54
55 static FILE *input_file;
56 static FILE *output_file;
57
58 /* execution mode */
59 static enum { MODE_NONE, MODE_SPEC, MODE_GLUE, MODE_RELAY } exec_mode = MODE_NONE;
60
61 /* open the input file */
62 static void open_input( const char *name )
63 {
64     input_file_name = name;
65     if (!(input_file = fopen( name, "r" )))
66     {
67         fprintf( stderr, "Cannot open input file '%s'\n", name );
68         exit(1);
69     }
70 }
71
72 /* cleanup on program exit */
73 static void cleanup(void)
74 {
75     if (output_file_name) unlink( output_file_name );
76 }
77
78
79 /*******************************************************************
80  *         command-line option handling
81  */
82
83 struct option
84 {
85     const char *name;
86     int         has_arg;
87     void      (*func)();
88     const char *usage;
89 };
90
91 static void do_pic(void);
92 static void do_output( const char *arg );
93 static void do_usage(void);
94 static void do_spec( const char *arg );
95 static void do_glue( const char *arg );
96 static void do_relay(void);
97
98 static const struct option option_table[] =
99 {
100     { "-fPIC",  0, do_pic,    "-fPIC            Generate PIC code" },
101     { "-h",     0, do_usage,  "-h               Display this help message" },
102     { "-o",     1, do_output, "-o name          Set the output file name (default: stdout)" },
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 }
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 *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
161 /* parse options from the argv array and remove all the recognized ones */
162 static void parse_options( char *argv[] )
163 {
164     const struct option *opt;
165     int i;
166
167     for (i = 1; argv[i]; i++)
168     {
169         for (opt = option_table; opt->name; opt++)
170             if (!strcmp( argv[i], opt->name )) break;
171
172         if (!opt->name)
173         {
174             fprintf( stderr, "Unrecognized option '%s'\n", argv[i] );
175             do_usage();
176         }
177
178         if (opt->has_arg && argv[i+1]) opt->func( argv[++i] );
179         else opt->func( "" );
180     }
181 }
182
183
184 /*******************************************************************
185  *         main
186  */
187 int main(int argc, char **argv)
188 {
189     output_file = stdout;
190     parse_options( argv );
191
192     /* Retrieve the selector values; this assumes that we are building
193      * the asm files on the platform that will also run them. Probably
194      * a safe assumption to make.
195      */
196     code_selector = __get_cs();
197     data_selector = __get_ds();
198
199     switch(exec_mode)
200     {
201     case MODE_SPEC:
202         switch (ParseTopLevel( input_file ))
203         {
204             case SPEC_WIN16:
205                 BuildSpec16File( output_file );
206                 break;
207             case SPEC_WIN32:
208                 BuildSpec32File( output_file );
209                 break;
210             default: assert(0);
211         }
212         break;
213     case MODE_GLUE:
214         BuildGlue( output_file, input_file );
215         break;
216     case MODE_RELAY:
217         BuildRelays( output_file );
218         break;
219     default:
220         do_usage();
221         break;
222     }
223     fclose( output_file );
224     output_file_name = NULL;
225     return 0;
226 }