spoolss: Implement AllocSplStr + DllFreeSplStr.
[wine/gsoc_dplay.git] / tools / winedump / main.c
blobf71c49abca0e57c846c9c8b9fd67e9369144ec1d
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include "winedump.h"
26 _globals globals; /* All global variables */
29 static void do_include (const char *arg)
31 char *newIncludes;
33 if (!globals.directory)
34 globals.directory = strdup(arg);
35 else {
36 newIncludes = str_create (3,globals.directory," ",arg);
37 free(globals.directory);
38 globals.directory = newIncludes;
40 globals.do_code = 1;
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);
49 else
50 return strdup (str);
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");
63 globals.mode = SPEC;
67 static void do_demangle (const char *arg)
69 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
70 globals.mode = DMGL;
71 globals.do_code = 1;
75 static void do_dump (const char *arg)
77 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
78 globals.mode = DUMP;
79 globals.do_code = 1;
83 static void do_dumpemf(void)
85 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
86 globals.mode = EMF;
90 static void do_dumplnk(void)
92 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
93 globals.mode = LNK;
97 static void do_code (void)
99 globals.do_code = 1;
103 static void do_trace (void)
105 globals.do_trace = 1;
106 globals.do_code = 1;
110 static void do_forward (const char *arg)
112 globals.forward_dll = arg;
113 globals.do_trace = 1;
114 globals.do_code = 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)
152 FILE *f;
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);
164 symbolp->found = 0;
165 symbolp->next = NULL;
166 *symbolptail = symbolp;
167 symbolptail = &symbolp->next;
169 if (fclose(f))
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";
206 struct my_option
208 const char *name;
209 Mode mode;
210 int has_arg;
211 void (*func) ();
212 const char *usage;
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}
244 void do_usage (void)
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);
274 puts ("");
275 exit (1);
279 /*******************************************************************
280 * parse_options
282 * Parse options from the argv array
284 static void parse_options (char *argv[])
286 const struct my_option *opt;
287 char *const *ptr;
288 const char *arg = NULL;
290 ptr = argv + 1;
292 while (*ptr != NULL)
294 for (opt = option_table; opt->name; opt++)
296 if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
297 continue;
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;
303 break;
305 if (!strcmp (*ptr, opt->name))
307 arg = NULL;
308 break;
312 if (!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)
321 opt->func (arg);
322 else
323 opt->func ("");
325 ptr++;
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)
337 const char* ptr;
338 char* buf;
339 int len;
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, '/')))
346 ptr++;
347 else
348 ptr = globals.input_name;
349 len = strlen(ptr);
350 if (len > 4 && strcmp(ptr + len - 4, ".dll") == 0)
351 len -= 4;
352 buf = malloc(len + 1);
353 memcpy(buf, (const void*)ptr, len);
354 buf[len] = 0;
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)))
367 return 0;
368 if (!globals.search_symbol)
369 return 1;
370 for (search_symbol = globals.search_symbol;
371 search_symbol;
372 search_symbol = search_symbol->next)
374 if (!strcmp(symbolname, search_symbol->symbolname))
376 search_symbol->found = 1;
377 return 1;
380 return 0;
383 /* return: some symbols weren't found */
384 static int symbol_finish(void)
386 const search_symbol *search_symbol;
387 int started = 0;
389 for (search_symbol = globals.search_symbol;
390 search_symbol;
391 search_symbol = search_symbol->next)
393 if (search_symbol->found)
394 continue;
395 if (!started)
397 /* stderr? not a practice here */
398 puts("These requested <symfile> symbols weren't found:");
399 started = 1;
401 printf("\t%s\n",search_symbol->symbolname);
403 return started;
406 /*******************************************************************
407 * main
409 #ifdef __GNUC__
410 int main (int argc __attribute__((unused)), char *argv[])
411 #else
412 int main (int argc, char *argv[])
413 #endif
415 parsed_symbol symbol;
416 int count = 0;
418 globals.mode = NONE;
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)
428 case DMGL:
429 globals.uc_dll_name = "";
430 VERBOSE = 1;
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]);
438 else
439 output_prototype (stdout, &symbol);
440 fputc ('\n', stdout);
441 symbol_clear(&symbol);
442 break;
444 case SPEC:
445 if (globals.input_name == NULL)
446 fatal("No file name has been given\n");
447 set_module_name(1);
448 if (!dll_open (globals.input_name))
449 break;
451 output_spec_preamble ();
452 output_header_preamble ();
453 output_c_preamble ();
455 while (!dll_next_symbol (&symbol))
457 count++;
459 if (NORMAL)
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);
468 if (result)
469 result = symbol_search (&symbol);
471 if (!result && symbol.function_name)
472 /* Clean up the prototype */
473 symbol_clean_string (symbol.function_name);
475 if (NORMAL)
476 puts (result ? "[Not Found]" : "[OK]");
478 else if (NORMAL)
479 puts ("[Ignoring]");
481 output_spec_symbol (&symbol);
482 output_header_symbol (&symbol);
483 output_c_symbol (&symbol);
485 symbol_clear (&symbol);
488 output_makefile ();
490 if (VERBOSE)
491 puts ("Finished, Cleaning up...");
492 if (symbol_finish())
493 return 1;
494 break;
495 case NONE:
496 do_usage();
497 break;
498 case DUMP:
499 if (globals.input_name == NULL)
500 fatal("No file name has been given\n");
501 set_module_name(0);
502 dump_file(globals.input_name);
503 break;
504 case EMF:
505 if (globals.input_name == NULL)
506 fatal("No file name has been given\n");
507 dump_emf(globals.input_name);
508 break;
509 case LNK:
510 if (globals.input_name == NULL)
511 fatal("No file name has been given\n");
512 dump_lnk(globals.input_name);
513 break;
516 return 0;