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
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/port.h"
36 ORDDEF *EntryPoints[MAX_ORDINALS];
37 ORDDEF *Ordinals[MAX_ORDINALS];
38 ORDDEF *Names[MAX_ORDINALS];
40 SPEC_MODE SpecMode = SPEC_MODE_DLL;
41 SPEC_TYPE SpecType = SPEC_WIN32;
43 int Base = MAX_ORDINALS;
48 int nb_entry_points = 0;
50 int nb_debug_channels = 0;
52 int display_warnings = 0;
55 /* we only support relay debugging on i386 */
56 #if defined(__i386__) && !defined(NO_TRACE_MSGS)
65 char *init_func = NULL;
66 char **debug_channels = NULL;
67 char **lib_path = NULL;
69 char *input_file_name = NULL;
70 const char *output_file_name = NULL;
72 static FILE *input_file;
73 static FILE *output_file;
74 static const char *current_src_dir;
75 static int nb_res_files;
76 static char **res_files;
89 } exec_mode = MODE_NONE;
91 /* set the dll file name from the input file name */
92 static void set_dll_file_name( const char *name )
96 if (*DLLFileName) return;
98 if ((p = strrchr( name, '\\' ))) name = p + 1;
99 if ((p = strrchr( name, '/' ))) name = p + 1;
100 strcpy( DLLFileName, name );
101 if ((p = strrchr( DLLFileName, '.' )) && !strcmp( p, ".spec" )) *p = 0;
102 if (!strchr( DLLFileName, '.' )) strcat( DLLFileName, ".dll" );
105 /* cleanup on program exit */
106 static void cleanup(void)
108 if (output_file_name) unlink( output_file_name );
112 /*******************************************************************
113 * command-line option handling
124 static void do_output( const char *arg );
125 static void do_usage(void);
126 static void do_warnings(void);
127 static void do_f_flags( const char *arg );
128 static void do_define( const char *arg );
129 static void do_include( const char *arg );
130 static void do_k_flags( const char *arg );
131 static void do_ignore( const char *arg );
132 static void do_kill_at(void);
133 static void do_exe_mode( const char *arg );
134 static void do_module( const char *arg );
135 static void do_heap( const char *arg );
136 static void do_name( const char *arg );
137 static void do_file( const char *arg );
138 static void do_entry( const char *arg );
139 static void do_spec( const char *arg );
140 static void do_def( const char *arg );
141 static void do_exe( const char *arg );
142 static void do_glue(void);
143 static void do_relay16(void);
144 static void do_relay32(void);
145 static void do_debug(void);
146 static void do_chdir( const char *arg );
147 static void do_lib( const char *arg );
148 static void do_import( const char *arg );
149 static void do_dimport( const char *arg );
150 static void do_rsrc( const char *arg );
152 static const struct option_descr option_table[] =
154 { "-h", 0, do_usage, "-h Display this help message" },
155 { "-w", 0, do_warnings,"-w Turn on warnings" },
156 { "-C", 1, do_chdir, "-C dir Change directory to <dir> before opening source files" },
157 { "-f", 1, do_f_flags, "-f flags Compiler flags (only -fPIC is supported)" },
158 { "-D", 1, do_define, "-D sym Ignored for C flags compatibility" },
159 { "-I", 1, do_include, "-I dir Ignored for C flags compatibility" },
160 { "-K", 1, do_k_flags, "-K flags Compiler flags (only -KPIC is supported)" },
161 { "-i", 1, do_ignore, "-i sym[,sym] Ignore specified symbols when resolving imports" },
162 { "-k", 0, do_kill_at, "-k Kill stdcall decorations in generated .def files" },
163 { "-m", 1, do_exe_mode,"-m mode Set the executable mode (cui|gui|cuiw|guiw)" },
164 { "-M", 1, do_module, "-M module Set the name of the main (Win32) module for a Win16 dll" },
165 { "-L", 1, do_lib, "-L directory Look for imports libraries in 'directory'" },
166 { "-l", 1, do_import, "-l lib.dll Import the specified library" },
167 { "-d", 1, do_dimport, "-d lib.dll Delay-import the specified library" },
168 { "-H", 1, do_heap, "-H size Set the heap size for a Win16 dll" },
169 { "-N", 1, do_name, "-N dllname Set the DLL name (default: set from input file name)" },
170 { "-F", 1, do_file, "-F dllfile Set the DLL filename (default: set from input file name)" },
171 { "-e", 1, do_entry, "-e function Set the DLL entry point function (default: DllMain)" },
172 { "-r", 1, do_rsrc, "-r rsrc.res Load resources from rsrc.res" },
173 { "-res", 1, do_rsrc, NULL }, /* for backwards compatibility, will disappear */
174 { "-o", 1, do_output, "-o name Set the output file name (default: stdout)\n" },
175 { "--spec", 1, do_spec, "--spec file.spec Build a .c file from a spec file" },
176 { "--def", 1, do_def, "--def file.spec Build a .def file from a spec file" },
177 { "--exe", 1, do_exe, "--exe name Build a .c file for the named executable" },
178 { "--debug", 0, do_debug, "--debug [files] Build a .c file containing debug channels declarations" },
179 { "--glue", 0, do_glue, "--glue [files] Build the 16-bit glue for the source files" },
180 { "--relay16", 0, do_relay16, "--relay16 Build the 16-bit relay assembly routines" },
181 { "--relay32", 0, do_relay32, "--relay32 Build the 32-bit relay assembly routines" },
182 { NULL, 0, NULL, NULL }
185 static void do_output( const char *arg )
187 if ( ( unlink ( arg ) ) == -1 && ( errno != ENOENT ) )
189 fprintf ( stderr, "Unable to create output file '%s'\n", arg );
192 if (!(output_file = fopen( arg, "w" )))
194 fprintf( stderr, "Unable to create output file '%s'\n", arg );
197 output_file_name = arg;
198 atexit( cleanup ); /* make sure we remove the output file on exit */
201 static void do_usage(void)
203 const struct option_descr *opt;
204 fprintf( stderr, "Usage: winebuild [options]\n\n" );
205 fprintf( stderr, "Options:\n" );
206 for (opt = option_table; opt->name; opt++)
207 if (opt->usage) fprintf( stderr, " %s\n", opt->usage );
209 fprintf( stderr, "\nExactly one of --spec, --def, --exe, --debug, --glue, --relay16 or --relay32 must be specified.\n\n" );
213 static void do_warnings(void)
215 display_warnings = 1;
218 static void do_f_flags( const char *arg )
220 if (!strcmp( arg, "PIC" )) UsePIC = 1;
221 /* ignore all other flags */
224 static void do_define( const char *arg )
229 static void do_include( const char *arg )
234 static void do_k_flags( const char *arg )
236 /* Ignored, because cc generates correct code. */
237 /* if (!strcmp( arg, "PIC" )) UsePIC = 1; */
238 /* ignore all other flags */
241 static void do_ignore( const char *arg )
243 char *str = xstrdup( arg );
244 char *token = strtok( str, "," );
247 add_ignore_symbol( token );
248 token = strtok( NULL, "," );
253 static void do_kill_at(void)
258 static void do_heap( const char *arg )
260 if (!isdigit(arg[0]))
261 fatal_error( "Expected number argument with -H option instead of '%s'\n", arg );
262 DLLHeapSize = atoi(arg);
263 if (DLLHeapSize > 65535) fatal_error( "Invalid heap size %d, maximum is 65535\n", DLLHeapSize );
266 static void do_name( const char *arg )
268 strncpy( DLLName, arg, sizeof(DLLName) );
269 DLLName[sizeof(DLLName) - 1] = 0;
272 static void do_file( const char *arg )
274 strncpy( DLLFileName, arg, sizeof(DLLFileName) );
275 DLLFileName[sizeof(DLLFileName) - 1] = 0;
278 static void do_entry( const char *arg )
280 init_func = xstrdup( arg );
283 static void do_spec( const char *arg )
285 if (exec_mode != MODE_NONE || !arg[0]) do_usage();
286 exec_mode = MODE_SPEC;
287 input_file = open_input_file( NULL, arg );
288 set_dll_file_name( arg );
291 static void do_def( const char *arg )
293 if (exec_mode != MODE_NONE || !arg[0]) do_usage();
294 exec_mode = MODE_DEF;
295 input_file = open_input_file( NULL, arg );
296 set_dll_file_name( arg );
299 static void do_exe( const char *arg )
303 if (exec_mode != MODE_NONE || !arg[0]) do_usage();
304 exec_mode = MODE_EXE;
305 if ((p = strrchr( arg, '/' ))) p++;
307 strcpy( DLLFileName, p );
308 if (!strchr( DLLFileName, '.' )) strcat( DLLFileName, ".exe" );
309 if (SpecMode == SPEC_MODE_DLL) SpecMode = SPEC_MODE_GUIEXE;
312 static void do_exe_mode( const char *arg )
314 if (!strcmp( arg, "gui" )) SpecMode = SPEC_MODE_GUIEXE;
315 else if (!strcmp( arg, "cui" )) SpecMode = SPEC_MODE_CUIEXE;
316 else if (!strcmp( arg, "guiw" )) SpecMode = SPEC_MODE_GUIEXE_UNICODE;
317 else if (!strcmp( arg, "cuiw" )) SpecMode = SPEC_MODE_CUIEXE_UNICODE;
321 static void do_module( const char *arg )
323 strcpy( owner_name, arg );
324 SpecType = SPEC_WIN16;
327 static void do_glue(void)
329 if (exec_mode != MODE_NONE) do_usage();
330 exec_mode = MODE_GLUE;
333 static void do_debug(void)
335 if (exec_mode != MODE_NONE) do_usage();
336 exec_mode = MODE_DEBUG;
339 static void do_chdir( const char *arg )
341 current_src_dir = arg;
344 static void do_relay16(void)
346 if (exec_mode != MODE_NONE) do_usage();
347 exec_mode = MODE_RELAY16;
350 static void do_relay32(void)
352 if (exec_mode != MODE_NONE) do_usage();
353 exec_mode = MODE_RELAY32;
356 static void do_lib( const char *arg )
358 lib_path = xrealloc( lib_path, (nb_lib_paths+1) * sizeof(*lib_path) );
359 lib_path[nb_lib_paths++] = xstrdup( arg );
362 static void do_import( const char *arg )
364 add_import_dll( arg, 0 );
367 static void do_dimport( const char *arg )
369 add_import_dll( arg, 1 );
372 static void do_rsrc( const char *arg )
374 res_files = xrealloc( res_files, (nb_res_files+1) * sizeof(*res_files) );
375 res_files[nb_res_files++] = xstrdup( arg );
378 /* parse options from the argv array and remove all the recognized ones */
379 static void parse_options( char *argv[] )
381 const struct option_descr *opt;
383 const char* arg=NULL;
385 for (ptr = last = argv; *ptr; ptr++)
387 /* first check the exact option name */
388 for (opt = option_table; opt->name; opt++)
390 if (!strcmp( *ptr, opt->name ) ||
391 /* for long option check without the first dash too */
392 (opt->name[1] == '-' && !strcmp( *ptr, opt->name+1 )))
394 if (opt->has_arg) arg = *(++ptr);
400 /* now check for option name concatenated with argument */
403 for (opt = option_table; opt->name; opt++)
405 if (opt->has_arg && !strncmp( *ptr, opt->name, strlen(opt->name) ))
407 arg = *ptr + strlen(opt->name);
415 if (opt->has_arg && arg != NULL) opt->func( arg );
416 else opt->func( "" );
418 else /* keep this argument */
420 if (last != ptr) *last = *ptr;
428 /* load all specified resource files */
429 static void load_resources( char *argv[] )
437 for (i = 0; i < nb_res_files; i++) load_res16_file( res_files[i] );
441 for (i = 0; i < nb_res_files; i++)
443 if (!load_res32_file( res_files[i] ))
444 fatal_error( "%s is not a valid Win32 resource file\n", res_files[i] );
447 /* load any resource file found in the remaining arguments */
448 for (ptr = last = argv; *ptr; ptr++)
450 if (!load_res32_file( *ptr ))
451 *last++ = *ptr; /* not a resource file, keep it in the list */
458 /*******************************************************************
461 int main(int argc, char **argv)
463 output_file = stdout;
464 parse_options( argv + 1 );
469 load_resources( argv + 1 );
470 ParseTopLevel( input_file );
475 fatal_error( "file argument '%s' not allowed in this mode\n", argv[1] );
476 BuildSpec16File( output_file );
479 read_undef_symbols( argv + 1 );
480 BuildSpec32File( output_file );
486 if (SpecType == SPEC_WIN16) fatal_error( "Cannot build 16-bit exe files\n" );
487 load_resources( argv + 1 );
488 read_undef_symbols( argv + 1 );
489 BuildSpec32File( output_file );
492 if (argv[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[1] );
493 if (SpecType == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
494 ParseTopLevel( input_file );
495 BuildDef32File( output_file );
498 BuildDebugFile( output_file, current_src_dir, argv + 1 );
501 BuildGlue( output_file, current_src_dir, argv + 1 );
504 if (argv[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[1] );
505 BuildRelays16( output_file );
508 if (argv[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[1] );
509 BuildRelays32( output_file );
515 if (output_file_name)
517 fclose( output_file );
518 output_file_name = NULL;