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;
54 /* we only support relay debugging on i386 */
55 #if defined(__i386__) && !defined(NO_TRACE_MSGS)
64 char *init_func
= NULL
;
65 char **debug_channels
= NULL
;
66 char **lib_path
= NULL
;
68 char *input_file_name
= NULL
;
69 const char *output_file_name
= NULL
;
71 static FILE *input_file
;
72 static FILE *output_file
;
73 static const char *current_src_dir
;
74 static int nb_res_files
;
75 static char **res_files
;
88 } exec_mode
= MODE_NONE
;
90 /* set the dll file name from the input file name */
91 static void set_dll_file_name( const char *name
)
95 if ((p
= strrchr( name
, '\\' ))) name
= p
+ 1;
96 if ((p
= strrchr( name
, '/' ))) name
= p
+ 1;
97 strcpy( DLLFileName
, name
);
98 if ((p
= strrchr( DLLFileName
, '.' )) && !strcmp( p
, ".spec" )) *p
= 0;
99 if (!strchr( DLLFileName
, '.' )) strcat( DLLFileName
, ".dll" );
102 /* cleanup on program exit */
103 static void cleanup(void)
105 if (output_file_name
) unlink( output_file_name
);
109 /*******************************************************************
110 * command-line option handling
121 static void do_output( const char *arg
);
122 static void do_usage(void);
123 static void do_warnings(void);
124 static void do_f_flags( const char *arg
);
125 static void do_define( const char *arg
);
126 static void do_include( const char *arg
);
127 static void do_k_flags( const char *arg
);
128 static void do_exe_mode( const char *arg
);
129 static void do_module( const char *arg
);
130 static void do_heap( const char *arg
);
131 static void do_name( const char *arg
);
132 static void do_entry( const char *arg
);
133 static void do_spec( const char *arg
);
134 static void do_def( const char *arg
);
135 static void do_exe( const char *arg
);
136 static void do_glue(void);
137 static void do_relay16(void);
138 static void do_relay32(void);
139 static void do_debug(void);
140 static void do_chdir( const char *arg
);
141 static void do_lib( const char *arg
);
142 static void do_import( const char *arg
);
143 static void do_dimport( const char *arg
);
144 static void do_rsrc( const char *arg
);
146 static const struct option_descr option_table
[] =
148 { "-h", 0, do_usage
, "-h Display this help message" },
149 { "-w", 0, do_warnings
,"-w Turn on warnings" },
150 { "-C", 1, do_chdir
, "-C dir Change directory to <dir> before opening source files" },
151 { "-f", 1, do_f_flags
, "-f flags Compiler flags (only -fPIC is supported)" },
152 { "-D", 1, do_define
, "-D sym Ignored for C flags compatibility" },
153 { "-I", 1, do_include
, "-I dir Ignored for C flags compatibility" },
154 { "-K", 1, do_k_flags
, "-K flags Compiler flags (only -KPIC is supported)" },
155 { "-m", 1, do_exe_mode
,"-m mode Set the executable mode (cui|gui|cuiw|guiw)" },
156 { "-M", 1, do_module
, "-M module Set the name of the main (Win32) module for a Win16 dll" },
157 { "-L", 1, do_lib
, "-L directory Look for imports libraries in 'directory'" },
158 { "-l", 1, do_import
, "-l lib.dll Import the specified library" },
159 { "-d", 1, do_dimport
, "-d lib.dll Delay-import the specified library" },
160 { "-H", 1, do_heap
, "-H size Set the heap size for a Win16 dll" },
161 { "-N", 1, do_name
, "-N dllname Set the DLL name (default: set from input file name)" },
162 { "-e", 1, do_entry
, "-e function Set the DLL entry point function (default: DllMain)" },
163 { "-r", 1, do_rsrc
, "-r rsrc.res Load resources from rsrc.res" },
164 { "-res", 1, do_rsrc
, NULL
}, /* for backwards compatibility, will disappear */
165 { "-o", 1, do_output
, "-o name Set the output file name (default: stdout)\n" },
166 { "--spec", 1, do_spec
, "--spec file.spec Build a .c file from a spec file" },
167 { "--def", 1, do_def
, "--def file.spec Build a .def file from a spec file" },
168 { "--exe", 1, do_exe
, "--exe name Build a .c file for the named executable" },
169 { "--debug", 0, do_debug
, "--debug [files] Build a .c file containing debug channels declarations" },
170 { "--glue", 0, do_glue
, "--glue [files] Build the 16-bit glue for the source files" },
171 { "--relay16", 0, do_relay16
, "--relay16 Build the 16-bit relay assembly routines" },
172 { "--relay32", 0, do_relay32
, "--relay32 Build the 32-bit relay assembly routines" },
173 { NULL
, 0, NULL
, NULL
}
176 static void do_output( const char *arg
)
178 if ( ( unlink ( arg
) ) == -1 && ( errno
!= ENOENT
) )
180 fprintf ( stderr
, "Unable to create output file '%s'\n", arg
);
183 if (!(output_file
= fopen( arg
, "w" )))
185 fprintf( stderr
, "Unable to create output file '%s'\n", arg
);
188 output_file_name
= arg
;
189 atexit( cleanup
); /* make sure we remove the output file on exit */
192 static void do_usage(void)
194 const struct option_descr
*opt
;
195 fprintf( stderr
, "Usage: winebuild [options]\n\n" );
196 fprintf( stderr
, "Options:\n" );
197 for (opt
= option_table
; opt
->name
; opt
++)
198 if (opt
->usage
) fprintf( stderr
, " %s\n", opt
->usage
);
200 fprintf( stderr
, "\nExactly one of --spec, --def, --exe, --debug, --glue, --relay16 or --relay32 must be specified.\n\n" );
204 static void do_warnings(void)
206 display_warnings
= 1;
209 static void do_f_flags( const char *arg
)
211 if (!strcmp( arg
, "PIC" )) UsePIC
= 1;
212 /* ignore all other flags */
215 static void do_define( const char *arg
)
220 static void do_include( const char *arg
)
225 static void do_k_flags( const char *arg
)
227 /* Ignored, because cc generates correct code. */
228 /* if (!strcmp( arg, "PIC" )) UsePIC = 1; */
229 /* ignore all other flags */
232 static void do_heap( const char *arg
)
234 if (!isdigit(arg
[0]))
235 fatal_error( "Expected number argument with -H option instead of '%s'\n", arg
);
236 DLLHeapSize
= atoi(arg
);
237 if (DLLHeapSize
> 65535) fatal_error( "Invalid heap size %d, maximum is 65535\n", DLLHeapSize
);
240 static void do_name( const char *arg
)
242 strncpy( DLLName
, arg
, sizeof(DLLName
) );
243 DLLName
[sizeof(DLLName
) - 1] = 0;
246 static void do_entry( const char *arg
)
248 init_func
= xstrdup( arg
);
251 static void do_spec( const char *arg
)
253 if (exec_mode
!= MODE_NONE
|| !arg
[0]) do_usage();
254 exec_mode
= MODE_SPEC
;
255 input_file
= open_input_file( NULL
, arg
);
256 set_dll_file_name( arg
);
259 static void do_def( const char *arg
)
261 if (exec_mode
!= MODE_NONE
|| !arg
[0]) do_usage();
262 exec_mode
= MODE_DEF
;
263 input_file
= open_input_file( NULL
, arg
);
264 set_dll_file_name( arg
);
267 static void do_exe( const char *arg
)
271 if (exec_mode
!= MODE_NONE
|| !arg
[0]) do_usage();
272 exec_mode
= MODE_EXE
;
273 if ((p
= strrchr( arg
, '/' ))) p
++;
275 strcpy( DLLFileName
, p
);
276 if (!strchr( DLLFileName
, '.' )) strcat( DLLFileName
, ".exe" );
277 if (SpecMode
== SPEC_MODE_DLL
) SpecMode
= SPEC_MODE_GUIEXE
;
280 static void do_exe_mode( const char *arg
)
282 if (!strcmp( arg
, "gui" )) SpecMode
= SPEC_MODE_GUIEXE
;
283 else if (!strcmp( arg
, "cui" )) SpecMode
= SPEC_MODE_CUIEXE
;
284 else if (!strcmp( arg
, "guiw" )) SpecMode
= SPEC_MODE_GUIEXE_UNICODE
;
285 else if (!strcmp( arg
, "cuiw" )) SpecMode
= SPEC_MODE_CUIEXE_UNICODE
;
289 static void do_module( const char *arg
)
291 strcpy( owner_name
, arg
);
292 SpecType
= SPEC_WIN16
;
295 static void do_glue(void)
297 if (exec_mode
!= MODE_NONE
) do_usage();
298 exec_mode
= MODE_GLUE
;
301 static void do_debug(void)
303 if (exec_mode
!= MODE_NONE
) do_usage();
304 exec_mode
= MODE_DEBUG
;
307 static void do_chdir( const char *arg
)
309 current_src_dir
= arg
;
312 static void do_relay16(void)
314 if (exec_mode
!= MODE_NONE
) do_usage();
315 exec_mode
= MODE_RELAY16
;
318 static void do_relay32(void)
320 if (exec_mode
!= MODE_NONE
) do_usage();
321 exec_mode
= MODE_RELAY32
;
324 static void do_lib( const char *arg
)
326 lib_path
= xrealloc( lib_path
, (nb_lib_paths
+1) * sizeof(*lib_path
) );
327 lib_path
[nb_lib_paths
++] = xstrdup( arg
);
330 static void do_import( const char *arg
)
332 add_import_dll( arg
, 0 );
335 static void do_dimport( const char *arg
)
337 add_import_dll( arg
, 1 );
340 static void do_rsrc( const char *arg
)
342 res_files
= xrealloc( res_files
, (nb_res_files
+1) * sizeof(*res_files
) );
343 res_files
[nb_res_files
++] = xstrdup( arg
);
346 /* parse options from the argv array and remove all the recognized ones */
347 static void parse_options( char *argv
[] )
349 const struct option_descr
*opt
;
351 const char* arg
=NULL
;
353 for (ptr
= last
= argv
; *ptr
; ptr
++)
355 /* first check the exact option name */
356 for (opt
= option_table
; opt
->name
; opt
++)
358 if (!strcmp( *ptr
, opt
->name
) ||
359 /* for long option check without the first dash too */
360 (opt
->name
[1] == '-' && !strcmp( *ptr
, opt
->name
+1 )))
362 if (opt
->has_arg
) arg
= *(++ptr
);
368 /* now check for option name concatenated with argument */
371 for (opt
= option_table
; opt
->name
; opt
++)
373 if (opt
->has_arg
&& !strncmp( *ptr
, opt
->name
, strlen(opt
->name
) ))
375 arg
= *ptr
+ strlen(opt
->name
);
383 if (opt
->has_arg
&& arg
!= NULL
) opt
->func( arg
);
384 else opt
->func( "" );
386 else /* keep this argument */
388 if (last
!= ptr
) *last
= *ptr
;
396 /* load all specified resource files */
397 static void load_resources( char *argv
[] )
405 for (i
= 0; i
< nb_res_files
; i
++) load_res16_file( res_files
[i
] );
409 for (i
= 0; i
< nb_res_files
; i
++)
411 if (!load_res32_file( res_files
[i
] ))
412 fatal_error( "%s is not a valid Win32 resource file\n", res_files
[i
] );
415 /* load any resource file found in the remaining arguments */
416 for (ptr
= last
= argv
; *ptr
; ptr
++)
418 if (!load_res32_file( *ptr
))
419 *last
++ = *ptr
; /* not a resource file, keep it in the list */
426 /*******************************************************************
429 int main(int argc
, char **argv
)
431 output_file
= stdout
;
432 parse_options( argv
+ 1 );
437 load_resources( argv
+ 1 );
438 ParseTopLevel( input_file
);
443 fatal_error( "file argument '%s' not allowed in this mode\n", argv
[1] );
444 BuildSpec16File( output_file
);
447 read_undef_symbols( argv
+ 1 );
448 BuildSpec32File( output_file
);
454 if (SpecType
== SPEC_WIN16
) fatal_error( "Cannot build 16-bit exe files\n" );
455 load_resources( argv
+ 1 );
456 read_undef_symbols( argv
+ 1 );
457 BuildSpec32File( output_file
);
460 if (argv
[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv
[1] );
461 if (SpecType
== SPEC_WIN16
) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
462 ParseTopLevel( input_file
);
463 BuildDef32File( output_file
);
466 BuildDebugFile( output_file
, current_src_dir
, argv
+ 1 );
469 BuildGlue( output_file
, current_src_dir
, argv
+ 1 );
472 if (argv
[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv
[1] );
473 BuildRelays16( output_file
);
476 if (argv
[1]) fatal_error( "file argument '%s' not allowed in this mode\n", argv
[1] );
477 BuildRelays32( output_file
);
483 if (output_file_name
)
485 fclose( output_file
);
486 output_file_name
= NULL
;