O_RDONLY==0 but it's cleaner to pass it to DRIVE_OpenDevice() anyway.
[wine.git] / tools / winedump / main.c
blob5807622b20ea6651a02bbbf7b313af54591b3eb5
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include "winedump.h"
25 _globals globals; /* All global variables */
28 static void do_include (const char *arg)
30 globals.directory = arg;
31 globals.do_code = 1;
35 static inline const char* strip_ext (const char *str)
37 char *ext = strstr(str, ".dll");
38 if (ext)
39 return str_substring (str, ext);
40 else
41 return strdup (str);
45 static void do_name (const char *arg)
47 globals.dll_name = strip_ext (arg);
51 static void do_spec (const char *arg)
53 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
54 globals.mode = SPEC;
58 static void do_demangle (const char *arg)
60 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
61 globals.mode = DMGL;
62 globals.do_code = 1;
66 static void do_dump (const char *arg)
68 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
69 globals.mode = DUMP;
70 globals.do_code = 1;
74 static void do_code (void)
76 globals.do_code = 1;
80 static void do_trace (void)
82 globals.do_trace = 1;
83 globals.do_code = 1;
87 static void do_forward (const char *arg)
89 globals.forward_dll = arg;
90 globals.do_trace = 1;
91 globals.do_code = 1;
94 static void do_document (void)
96 globals.do_documentation = 1;
99 static void do_cdecl (void)
101 globals.do_cdecl = 1;
105 static void do_quiet (void)
107 globals.do_quiet = 1;
111 static void do_start (const char *arg)
113 globals.start_ordinal = atoi (arg);
114 if (!globals.start_ordinal)
115 fatal ("Invalid -s option (must be numeric)");
119 static void do_end (const char *arg)
121 globals.end_ordinal = atoi (arg);
122 if (!globals.end_ordinal)
123 fatal ("Invalid -e option (must be numeric)");
127 static void do_symfile (const char *arg)
129 FILE *f;
130 char symstring[256]; /* keep count with "%<width>s" below */
131 search_symbol *symbolp,**symbolptail = &globals.search_symbol;
133 if (!(f = fopen(arg, "rt")))
134 fatal ("Cannot open <symfile>");
135 while (1 == fscanf(f, "%255s", symstring)) /* keep count with [<width>] above */
137 symstring[sizeof(symstring)-1] = '\0';
138 if (!(symbolp = malloc(sizeof(*symbolp) + strlen(symstring))))
139 fatal ("Out of memory");
140 strcpy(symbolp->symbolname, symstring);
141 symbolp->found = 0;
142 symbolp->next = NULL;
143 *symbolptail = symbolp;
144 symbolptail = &symbolp->next;
146 if (fclose(f))
147 fatal ("Cannot close <symfile>");
151 static void do_verbose (void)
153 globals.do_verbose = 1;
157 static void do_symdmngl (void)
159 globals.do_demangle = 1;
162 static void do_dumphead (void)
164 globals.do_dumpheader = 1;
167 static void do_dumpsect (const char* arg)
169 globals.dumpsect = arg;
172 static void do_dumpall(void)
174 globals.do_dumpheader = 1;
175 globals.dumpsect = "ALL";
178 struct option
180 const char *name;
181 Mode mode;
182 int has_arg;
183 void (*func) ();
184 const char *usage;
187 static const struct option option_table[] = {
188 {"-h", NONE, 0, do_usage, "-h Display this help message"},
189 {"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
190 {"spec", SPEC, 0, do_spec, "spec <dll> Use dll for input file and generate implementation code"},
191 {"-I", SPEC, 1, do_include, "-I dir Look for prototypes in 'dir' (implies -c)"},
192 {"-c", SPEC, 0, do_code, "-c Generate skeleton code (requires -I)"},
193 {"-t", SPEC, 0, do_trace, "-t TRACE arguments (implies -c)"},
194 {"-f", SPEC, 1, do_forward, "-f dll Forward calls to 'dll' (implies -t)"},
195 {"-D", SPEC, 0, do_document, "-D Generate documentation"},
196 {"-o", SPEC, 1, do_name, "-o name Set the output dll name (default: dll)"},
197 {"-C", SPEC, 0, do_cdecl, "-C Assume __cdecl calls (default: __stdcall)"},
198 {"-s", SPEC, 1, do_start, "-s num Start prototype search after symbol 'num'"},
199 {"-e", SPEC, 1, do_end, "-e num End prototype search after symbol 'num'"},
200 {"-S", SPEC, 1, do_symfile, "-S symfile Search only prototype names found in 'symfile'"},
201 {"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."},
202 {"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."},
203 {"dump", DUMP, 0, do_dump, "dump <mod> Dumps the content of the module (dll, exe...) named <mod>"},
204 {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"},
205 {"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"},
206 {"-j", DUMP, 1, do_dumpsect, "-j sect_name Dumps only the content of section sect_name (import, export, debug, resource, tls)"},
207 {"-x", DUMP, 0, do_dumpall, "-x Dumps everything"},
208 {NULL, NONE, 0, NULL, NULL}
211 void do_usage (void)
213 const struct option *opt;
214 printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <dll>]\n");
215 printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
216 printf ("\tWhen used in -h mode\n");
217 for (opt = option_table; opt->name; opt++)
218 if (opt->mode == NONE)
219 printf ("\t %s\n", opt->usage);
220 printf ("\tWhen used in sym mode\n");
221 for (opt = option_table; opt->name; opt++)
222 if (opt->mode == DMGL)
223 printf ("\t %s\n", opt->usage);
224 printf ("\tWhen used in spec mode\n");
225 for (opt = option_table; opt->name; opt++)
226 if (opt->mode == SPEC)
227 printf ("\t %s\n", opt->usage);
228 printf ("\tWhen used in dump mode\n");
229 for (opt = option_table; opt->name; opt++)
230 if (opt->mode == DUMP)
231 printf ("\t %s\n", opt->usage);
233 puts ("\n");
234 exit (1);
238 /*******************************************************************
239 * parse_options
241 * Parse options from the argv array
243 static void parse_options (char *argv[])
245 const struct option *opt;
246 char *const *ptr;
247 const char *arg = NULL;
249 ptr = argv + 1;
251 while (*ptr != NULL)
253 for (opt = option_table; opt->name; opt++)
255 if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
256 continue;
257 if (((opt->has_arg == 1) && !strncmp (*ptr, opt->name, strlen (opt->name))) ||
258 ((opt->has_arg == 2) && !strcmp (*ptr, opt->name)))
260 arg = *ptr + strlen (opt->name);
261 if (*arg == '\0') arg = *++ptr;
262 break;
264 if (!strcmp (*ptr, opt->name))
266 arg = NULL;
267 break;
271 if (!opt->name)
273 if ((*ptr)[0] == '-')
274 fatal ("Unrecognized option");
275 if (globals.input_name != NULL)
276 fatal ("Only one file can be treated at once");
277 globals.input_name = *ptr;
279 else if (opt->has_arg && arg != NULL)
280 opt->func (arg);
281 else
282 opt->func ("");
284 ptr++;
287 if (globals.mode == SPEC && globals.do_code && !globals.directory)
288 fatal ("-I must be used if generating code");
290 if (VERBOSE && QUIET)
291 fatal ("Options -v and -q are mutually exclusive");
294 static void set_module_name(unsigned setUC)
296 const char* ptr;
297 char* buf;
298 int len;
300 /* FIXME: we shouldn't assume all module extensions are .dll in winedump
301 * in some cases, we could have some .drv for example
303 /* get module name from name */
304 if ((ptr = strrchr (globals.input_name, '/')))
305 ptr++;
306 else
307 ptr = globals.input_name;
308 len = strlen(ptr);
309 if (len > 4 && strcmp(ptr + len - 4, ".dll") == 0)
310 len -= 4;
311 buf = malloc(len + 1);
312 memcpy(buf, (void*)ptr, len);
313 buf[len] = 0;
314 globals.input_module = buf;
315 OUTPUT_UC_DLL_NAME = (setUC) ? str_toupper( strdup (OUTPUT_DLL_NAME)) : "";
318 /* Marks the symbol as 'found'! */
319 /* return: perform-search */
320 static int symbol_searched(int count, const char *symbolname)
322 search_symbol *search_symbol;
324 if (!(count >= globals.start_ordinal
325 && (!globals.end_ordinal || count <= globals.end_ordinal)))
326 return 0;
327 if (!globals.search_symbol)
328 return 1;
329 for (search_symbol = globals.search_symbol;
330 search_symbol;
331 search_symbol = search_symbol->next)
333 if (!strcmp(symbolname, search_symbol->symbolname))
335 search_symbol->found = 1;
336 return 1;
339 return 0;
342 /* return: some symbols weren't found */
343 static int symbol_finish(void)
345 const search_symbol *search_symbol;
346 int started = 0;
348 for (search_symbol = globals.search_symbol;
349 search_symbol;
350 search_symbol = search_symbol->next)
352 if (search_symbol->found)
353 continue;
354 if (!started)
356 /* stderr? not a practice here */
357 puts("These requested <symfile> symbols weren't found:");
358 started = 1;
360 printf("\t%s\n",search_symbol->symbolname);
362 return started;
365 /*******************************************************************
366 * main
368 #ifdef __GNUC__
369 int main (int argc __attribute__((unused)), char *argv[])
370 #else
371 int main (int argc, char *argv[])
372 #endif
374 parsed_symbol symbol;
375 int count = 0;
377 globals.mode = NONE;
378 globals.forward_dll = NULL;
379 globals.input_name = NULL;
381 parse_options (argv);
383 memset (&symbol, 0, sizeof (parsed_symbol));
385 switch (globals.mode)
387 case DMGL:
388 globals.uc_dll_name = "";
389 VERBOSE = 1;
391 symbol_init (&symbol, globals.input_name);
392 globals.input_module = "";
393 if (symbol_demangle (&symbol) == -1)
394 fatal( "Symbol hasn't got a mangled name\n");
395 if (symbol.flags & SYM_DATA)
396 printf (symbol.arg_text[0]);
397 else
398 output_prototype (stdout, &symbol);
399 fputc ('\n', stdout);
400 symbol_clear(&symbol);
401 break;
403 case SPEC:
404 if (globals.input_name == NULL)
405 fatal("No file name has been given\n");
406 set_module_name(1);
407 dll_open (globals.input_name);
409 output_spec_preamble ();
410 output_header_preamble ();
411 output_c_preamble ();
413 while (!dll_next_symbol (&symbol))
415 count++;
417 if (NORMAL)
418 printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
419 VERBOSE ? '\n' : ' ');
421 if (globals.do_code && symbol_searched(count, symbol.symbol))
423 /* Attempt to get information about the symbol */
424 int result = symbol_demangle (&symbol);
426 if (result)
427 result = symbol_search (&symbol);
429 if (!result && symbol.function_name)
430 /* Clean up the prototype */
431 symbol_clean_string (symbol.function_name);
433 if (NORMAL)
434 puts (result ? "[Not Found]" : "[OK]");
436 else if (NORMAL)
437 puts ("[Ignoring]");
439 output_spec_symbol (&symbol);
440 output_header_symbol (&symbol);
441 output_c_symbol (&symbol);
443 symbol_clear (&symbol);
446 output_makefile ();
447 output_install_script ();
449 if (VERBOSE)
450 puts ("Finished, Cleaning up...");
451 if (symbol_finish())
452 return 1;
453 break;
454 case NONE:
455 do_usage();
456 break;
457 case DUMP:
458 if (globals.input_name == NULL)
459 fatal("No file name has been given\n");
460 set_module_name(0);
461 dump_file(globals.input_name);
462 break;
465 return 0;