2 * Option processing and main()
4 * Copyright 2000 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 _globals globals
; /* All global variables */
29 static void do_include (const char *arg
)
33 if (!globals
.directory
)
34 globals
.directory
= strdup(arg
);
36 newIncludes
= str_create (3,globals
.directory
," ",arg
);
37 free(globals
.directory
);
38 globals
.directory
= newIncludes
;
44 static inline const char* strip_ext (const char *str
)
46 int len
= strlen(str
);
47 if (len
>4 && strcmp(str
+len
-4,".dll") == 0)
48 return str_substring (str
, str
+len
-4);
54 static void do_name (const char *arg
)
56 globals
.dll_name
= strip_ext (arg
);
60 static void do_spec (const char *arg
)
62 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
67 static void do_demangle (const char *arg
)
69 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
75 static void do_dump (const char *arg
)
77 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
83 static void do_dumpemf(void)
85 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
90 static void do_dumplnk(void)
92 if (globals
.mode
!= NONE
) fatal("Only one mode can be specified\n");
97 static void do_code (void)
103 static void do_trace (void)
105 globals
.do_trace
= 1;
110 static void do_forward (const char *arg
)
112 globals
.forward_dll
= arg
;
113 globals
.do_trace
= 1;
117 static void do_document (void)
119 globals
.do_documentation
= 1;
122 static void do_cdecl (void)
124 globals
.do_cdecl
= 1;
128 static void do_quiet (void)
130 globals
.do_quiet
= 1;
134 static void do_start (const char *arg
)
136 globals
.start_ordinal
= atoi (arg
);
137 if (!globals
.start_ordinal
)
138 fatal ("Invalid -s option (must be numeric)");
142 static void do_end (const char *arg
)
144 globals
.end_ordinal
= atoi (arg
);
145 if (!globals
.end_ordinal
)
146 fatal ("Invalid -e option (must be numeric)");
150 static void do_symfile (const char *arg
)
153 char symstring
[256]; /* keep count with "%<width>s" below */
154 search_symbol
*symbolp
,**symbolptail
= &globals
.search_symbol
;
156 if (!(f
= fopen(arg
, "rt")))
157 fatal ("Cannot open <symfile>");
158 while (1 == fscanf(f
, "%255s", symstring
)) /* keep count with [<width>] above */
160 symstring
[sizeof(symstring
)-1] = '\0';
161 if (!(symbolp
= malloc(sizeof(*symbolp
) + strlen(symstring
))))
162 fatal ("Out of memory");
163 strcpy(symbolp
->symbolname
, symstring
);
165 symbolp
->next
= NULL
;
166 *symbolptail
= symbolp
;
167 symbolptail
= &symbolp
->next
;
170 fatal ("Cannot close <symfile>");
174 static void do_verbose (void)
176 globals
.do_verbose
= 1;
180 static void do_symdmngl (void)
182 globals
.do_demangle
= 1;
185 static void do_dumphead (void)
187 globals
.do_dumpheader
= 1;
190 static void do_dumpsect (const char* arg
)
192 globals
.dumpsect
= arg
;
195 static void do_rawdebug (void)
197 globals
.do_debug
= 1;
200 static void do_dumpall(void)
202 globals
.do_dumpheader
= 1;
203 globals
.dumpsect
= "ALL";
215 static const struct my_option option_table
[] = {
216 {"--help",NONE
, 0, do_usage
, "--help Display this help message"},
217 {"-h", NONE
, 0, do_usage
, "-h Synonym for --help"},
218 {"-?", NONE
, 0, do_usage
, "-? Synonym for --help"},
219 {"sym", DMGL
, 0, do_demangle
, "sym <sym> Demangle C++ symbol <sym> and exit"},
220 {"spec", SPEC
, 0, do_spec
, "spec <dll> Use dll for input file and generate implementation code"},
221 {"-I", SPEC
, 1, do_include
, "-I dir Look for prototypes in 'dir' (implies -c)"},
222 {"-c", SPEC
, 0, do_code
, "-c Generate skeleton code (requires -I)"},
223 {"-t", SPEC
, 0, do_trace
, "-t TRACE arguments (implies -c)"},
224 {"-f", SPEC
, 1, do_forward
, "-f dll Forward calls to 'dll' (implies -t)"},
225 {"-D", SPEC
, 0, do_document
, "-D Generate documentation"},
226 {"-o", SPEC
, 1, do_name
, "-o name Set the output dll name (default: dll). note: strips .dll extensions"},
227 {"-C", SPEC
, 0, do_cdecl
, "-C Assume __cdecl calls (default: __stdcall)"},
228 {"-s", SPEC
, 1, do_start
, "-s num Start prototype search after symbol 'num'"},
229 {"-e", SPEC
, 1, do_end
, "-e num End prototype search after symbol 'num'"},
230 {"-S", SPEC
, 1, do_symfile
, "-S symfile Search only prototype names found in 'symfile'"},
231 {"-q", SPEC
, 0, do_quiet
, "-q Don't show progress (quiet)."},
232 {"-v", SPEC
, 0, do_verbose
, "-v Show lots of detail while working (verbose)."},
233 {"dump", DUMP
, 0, do_dump
, "dump <file> Dumps the contents of the file (dll, exe, lib...)"},
234 {"-C", DUMP
, 0, do_symdmngl
, "-C Turns on symbol demangling"},
235 {"-f", DUMP
, 0, do_dumphead
, "-f Dumps file header information"},
236 {"-G", DUMP
, 0, do_rawdebug
, "-G Dumps raw debug information"},
237 {"-j", DUMP
, 1, do_dumpsect
, "-j sect_name Dumps only the content of section sect_name (import, export, debug, resource, tls)"},
238 {"-x", DUMP
, 0, do_dumpall
, "-x Dumps everything"},
239 {"emf", EMF
, 0, do_dumpemf
, "emf Dumps an Enhanced Meta File"},
240 {"lnk", LNK
, 0, do_dumplnk
, "lnk Dumps a shortcut (.lnk) file"},
241 {NULL
, NONE
, 0, NULL
, NULL
}
246 const struct my_option
*opt
;
247 printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <file> | emf <emf> | lnk <lnk>]\n");
248 printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
249 printf ("\tWhen used in --help mode\n");
250 for (opt
= option_table
; opt
->name
; opt
++)
251 if (opt
->mode
== NONE
)
252 printf ("\t %s\n", opt
->usage
);
253 printf ("\tWhen used in sym mode\n");
254 for (opt
= option_table
; opt
->name
; opt
++)
255 if (opt
->mode
== DMGL
)
256 printf ("\t %s\n", opt
->usage
);
257 printf ("\tWhen used in spec mode\n");
258 for (opt
= option_table
; opt
->name
; opt
++)
259 if (opt
->mode
== SPEC
)
260 printf ("\t %s\n", opt
->usage
);
261 printf ("\tWhen used in dump mode\n");
262 for (opt
= option_table
; opt
->name
; opt
++)
263 if (opt
->mode
== DUMP
)
264 printf ("\t %s\n", opt
->usage
);
265 printf ("\tWhen used in emf mode\n");
266 for (opt
= option_table
; opt
->name
; opt
++)
267 if (opt
->mode
== EMF
)
268 printf ("\t %s\n", opt
->usage
);
269 printf ("\tWhen used in lnk mode\n");
270 for (opt
= option_table
; opt
->name
; opt
++)
271 if (opt
->mode
== LNK
)
272 printf ("\t %s\n", opt
->usage
);
279 /*******************************************************************
282 * Parse options from the argv array
284 static void parse_options (char *argv
[])
286 const struct my_option
*opt
;
288 const char *arg
= NULL
;
294 for (opt
= option_table
; opt
->name
; opt
++)
296 if (globals
.mode
!= NONE
&& opt
->mode
!= NONE
&& globals
.mode
!= opt
->mode
)
298 if (((opt
->has_arg
== 1) && !strncmp (*ptr
, opt
->name
, strlen (opt
->name
))) ||
299 ((opt
->has_arg
== 2) && !strcmp (*ptr
, opt
->name
)))
301 arg
= *ptr
+ strlen (opt
->name
);
302 if (*arg
== '\0') arg
= *++ptr
;
305 if (!strcmp (*ptr
, opt
->name
))
314 if ((*ptr
)[0] == '-')
315 fatal ("Unrecognized option");
316 if (globals
.input_name
!= NULL
)
317 fatal ("Only one file can be treated at once");
318 globals
.input_name
= *ptr
;
320 else if (opt
->has_arg
&& arg
!= NULL
)
328 if (globals
.mode
== SPEC
&& globals
.do_code
&& !globals
.directory
)
329 fatal ("-I must be used if generating code");
331 if (VERBOSE
&& QUIET
)
332 fatal ("Options -v and -q are mutually exclusive");
335 static void set_module_name(unsigned setUC
)
341 /* FIXME: we shouldn't assume all module extensions are .dll in winedump
342 * in some cases, we could have some .drv for example
344 /* get module name from name */
345 if ((ptr
= strrchr (globals
.input_name
, '/')))
348 ptr
= globals
.input_name
;
350 if (len
> 4 && strcmp(ptr
+ len
- 4, ".dll") == 0)
352 buf
= malloc(len
+ 1);
353 memcpy(buf
, (const void*)ptr
, len
);
355 globals
.input_module
= buf
;
356 OUTPUT_UC_DLL_NAME
= (setUC
) ? str_toupper( strdup (OUTPUT_DLL_NAME
)) : "";
359 /* Marks the symbol as 'found'! */
360 /* return: perform-search */
361 static int symbol_searched(int count
, const char *symbolname
)
363 search_symbol
*search_symbol
;
365 if (!(count
>= globals
.start_ordinal
366 && (!globals
.end_ordinal
|| count
<= globals
.end_ordinal
)))
368 if (!globals
.search_symbol
)
370 for (search_symbol
= globals
.search_symbol
;
372 search_symbol
= search_symbol
->next
)
374 if (!strcmp(symbolname
, search_symbol
->symbolname
))
376 search_symbol
->found
= 1;
383 /* return: some symbols weren't found */
384 static int symbol_finish(void)
386 const search_symbol
*search_symbol
;
389 for (search_symbol
= globals
.search_symbol
;
391 search_symbol
= search_symbol
->next
)
393 if (search_symbol
->found
)
397 /* stderr? not a practice here */
398 puts("These requested <symfile> symbols weren't found:");
401 printf("\t%s\n",search_symbol
->symbolname
);
406 /*******************************************************************
410 int main (int argc
__attribute__((unused
)), char *argv
[])
412 int main (int argc
, char *argv
[])
415 parsed_symbol symbol
;
419 globals
.forward_dll
= NULL
;
420 globals
.input_name
= NULL
;
422 parse_options (argv
);
424 memset (&symbol
, 0, sizeof (parsed_symbol
));
426 switch (globals
.mode
)
429 globals
.uc_dll_name
= "";
432 symbol_init (&symbol
, globals
.input_name
);
433 globals
.input_module
= "";
434 if (symbol_demangle (&symbol
) == -1)
435 fatal( "Symbol hasn't got a mangled name\n");
436 if (symbol
.flags
& SYM_DATA
)
437 printf (symbol
.arg_text
[0]);
439 output_prototype (stdout
, &symbol
);
440 fputc ('\n', stdout
);
441 symbol_clear(&symbol
);
445 if (globals
.input_name
== NULL
)
446 fatal("No file name has been given\n");
448 if (!dll_open (globals
.input_name
))
451 output_spec_preamble ();
452 output_header_preamble ();
453 output_c_preamble ();
455 while (!dll_next_symbol (&symbol
))
460 printf ("Export %3d - '%s' ...%c", count
, symbol
.symbol
,
461 VERBOSE
? '\n' : ' ');
463 if (globals
.do_code
&& symbol_searched(count
, symbol
.symbol
))
465 /* Attempt to get information about the symbol */
466 int result
= symbol_demangle (&symbol
);
469 result
= symbol_search (&symbol
);
471 if (!result
&& symbol
.function_name
)
472 /* Clean up the prototype */
473 symbol_clean_string (symbol
.function_name
);
476 puts (result
? "[Not Found]" : "[OK]");
481 output_spec_symbol (&symbol
);
482 output_header_symbol (&symbol
);
483 output_c_symbol (&symbol
);
485 symbol_clear (&symbol
);
491 puts ("Finished, Cleaning up...");
499 if (globals
.input_name
== NULL
)
500 fatal("No file name has been given\n");
502 dump_file(globals
.input_name
);
505 if (globals
.input_name
== NULL
)
506 fatal("No file name has been given\n");
507 dump_emf(globals
.input_name
);
510 if (globals
.input_name
== NULL
)
511 fatal("No file name has been given\n");
512 dump_lnk(globals
.input_name
);