No need to add a reference to the apartment from new_stub_manager as
[wine/wine64.git] / tools / winedump / main.c
blobed6d2b4e1114de1e891c1319365b4583e9715635
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 char *newIncludes;
32 if (!globals.directory)
33 globals.directory = strdup(arg);
34 else {
35 newIncludes = str_create (3,globals.directory," ",arg);
36 free(globals.directory);
37 globals.directory = newIncludes;
39 globals.do_code = 1;
43 static inline const char* strip_ext (const char *str)
45 int len = strlen(str);
46 if (len>4 && strcmp(str+len-4,".dll") == 0)
47 return str_substring (str, str+len-4);
48 else
49 return strdup (str);
53 static void do_name (const char *arg)
55 globals.dll_name = strip_ext (arg);
59 static void do_spec (const char *arg)
61 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
62 globals.mode = SPEC;
66 static void do_demangle (const char *arg)
68 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
69 globals.mode = DMGL;
70 globals.do_code = 1;
74 static void do_dump (const char *arg)
76 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
77 globals.mode = DUMP;
78 globals.do_code = 1;
82 static void do_dumpemf(void)
84 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
85 globals.mode = EMF;
89 static void do_code (void)
91 globals.do_code = 1;
95 static void do_trace (void)
97 globals.do_trace = 1;
98 globals.do_code = 1;
102 static void do_forward (const char *arg)
104 globals.forward_dll = arg;
105 globals.do_trace = 1;
106 globals.do_code = 1;
109 static void do_document (void)
111 globals.do_documentation = 1;
114 static void do_cdecl (void)
116 globals.do_cdecl = 1;
120 static void do_quiet (void)
122 globals.do_quiet = 1;
126 static void do_start (const char *arg)
128 globals.start_ordinal = atoi (arg);
129 if (!globals.start_ordinal)
130 fatal ("Invalid -s option (must be numeric)");
134 static void do_end (const char *arg)
136 globals.end_ordinal = atoi (arg);
137 if (!globals.end_ordinal)
138 fatal ("Invalid -e option (must be numeric)");
142 static void do_symfile (const char *arg)
144 FILE *f;
145 char symstring[256]; /* keep count with "%<width>s" below */
146 search_symbol *symbolp,**symbolptail = &globals.search_symbol;
148 if (!(f = fopen(arg, "rt")))
149 fatal ("Cannot open <symfile>");
150 while (1 == fscanf(f, "%255s", symstring)) /* keep count with [<width>] above */
152 symstring[sizeof(symstring)-1] = '\0';
153 if (!(symbolp = malloc(sizeof(*symbolp) + strlen(symstring))))
154 fatal ("Out of memory");
155 strcpy(symbolp->symbolname, symstring);
156 symbolp->found = 0;
157 symbolp->next = NULL;
158 *symbolptail = symbolp;
159 symbolptail = &symbolp->next;
161 if (fclose(f))
162 fatal ("Cannot close <symfile>");
166 static void do_verbose (void)
168 globals.do_verbose = 1;
172 static void do_symdmngl (void)
174 globals.do_demangle = 1;
177 static void do_dumphead (void)
179 globals.do_dumpheader = 1;
182 static void do_dumpsect (const char* arg)
184 globals.dumpsect = arg;
187 static void do_dumpall(void)
189 globals.do_dumpheader = 1;
190 globals.dumpsect = "ALL";
193 struct option
195 const char *name;
196 Mode mode;
197 int has_arg;
198 void (*func) ();
199 const char *usage;
202 static const struct option option_table[] = {
203 {"-h", NONE, 0, do_usage, "-h Display this help message"},
204 {"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
205 {"spec", SPEC, 0, do_spec, "spec <dll> Use dll for input file and generate implementation code"},
206 {"-I", SPEC, 1, do_include, "-I dir Look for prototypes in 'dir' (implies -c)"},
207 {"-c", SPEC, 0, do_code, "-c Generate skeleton code (requires -I)"},
208 {"-t", SPEC, 0, do_trace, "-t TRACE arguments (implies -c)"},
209 {"-f", SPEC, 1, do_forward, "-f dll Forward calls to 'dll' (implies -t)"},
210 {"-D", SPEC, 0, do_document, "-D Generate documentation"},
211 {"-o", SPEC, 1, do_name, "-o name Set the output dll name (default: dll). note: strips .dll extensions"},
212 {"-C", SPEC, 0, do_cdecl, "-C Assume __cdecl calls (default: __stdcall)"},
213 {"-s", SPEC, 1, do_start, "-s num Start prototype search after symbol 'num'"},
214 {"-e", SPEC, 1, do_end, "-e num End prototype search after symbol 'num'"},
215 {"-S", SPEC, 1, do_symfile, "-S symfile Search only prototype names found in 'symfile'"},
216 {"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."},
217 {"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."},
218 {"dump", DUMP, 0, do_dump, "dump <mod> Dumps the content of the module (dll, exe...) named <mod>"},
219 {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"},
220 {"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"},
221 {"-j", DUMP, 1, do_dumpsect, "-j sect_name Dumps only the content of section sect_name (import, export, debug, resource, tls)"},
222 {"-x", DUMP, 0, do_dumpall, "-x Dumps everything"},
223 {"emf", EMF, 0, do_dumpemf, "emf Dumps an Enhanced Meta File"},
224 {NULL, NONE, 0, NULL, NULL}
227 void do_usage (void)
229 const struct option *opt;
230 printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <dll>]\n");
231 printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
232 printf ("\tWhen used in -h mode\n");
233 for (opt = option_table; opt->name; opt++)
234 if (opt->mode == NONE)
235 printf ("\t %s\n", opt->usage);
236 printf ("\tWhen used in sym mode\n");
237 for (opt = option_table; opt->name; opt++)
238 if (opt->mode == DMGL)
239 printf ("\t %s\n", opt->usage);
240 printf ("\tWhen used in spec mode\n");
241 for (opt = option_table; opt->name; opt++)
242 if (opt->mode == SPEC)
243 printf ("\t %s\n", opt->usage);
244 printf ("\tWhen used in dump mode\n");
245 for (opt = option_table; opt->name; opt++)
246 if (opt->mode == DUMP)
247 printf ("\t %s\n", opt->usage);
248 printf ("\tWhen used in emf mode\n");
249 for (opt = option_table; opt->name; opt++)
250 if (opt->mode == EMF)
251 printf ("\t %s\n", opt->usage);
253 puts ("\n");
254 exit (1);
258 /*******************************************************************
259 * parse_options
261 * Parse options from the argv array
263 static void parse_options (char *argv[])
265 const struct option *opt;
266 char *const *ptr;
267 const char *arg = NULL;
269 ptr = argv + 1;
271 while (*ptr != NULL)
273 for (opt = option_table; opt->name; opt++)
275 if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
276 continue;
277 if (((opt->has_arg == 1) && !strncmp (*ptr, opt->name, strlen (opt->name))) ||
278 ((opt->has_arg == 2) && !strcmp (*ptr, opt->name)))
280 arg = *ptr + strlen (opt->name);
281 if (*arg == '\0') arg = *++ptr;
282 break;
284 if (!strcmp (*ptr, opt->name))
286 arg = NULL;
287 break;
291 if (!opt->name)
293 if ((*ptr)[0] == '-')
294 fatal ("Unrecognized option");
295 if (globals.input_name != NULL)
296 fatal ("Only one file can be treated at once");
297 globals.input_name = *ptr;
299 else if (opt->has_arg && arg != NULL)
300 opt->func (arg);
301 else
302 opt->func ("");
304 ptr++;
307 if (globals.mode == SPEC && globals.do_code && !globals.directory)
308 fatal ("-I must be used if generating code");
310 if (VERBOSE && QUIET)
311 fatal ("Options -v and -q are mutually exclusive");
314 static void set_module_name(unsigned setUC)
316 const char* ptr;
317 char* buf;
318 int len;
320 /* FIXME: we shouldn't assume all module extensions are .dll in winedump
321 * in some cases, we could have some .drv for example
323 /* get module name from name */
324 if ((ptr = strrchr (globals.input_name, '/')))
325 ptr++;
326 else
327 ptr = globals.input_name;
328 len = strlen(ptr);
329 if (len > 4 && strcmp(ptr + len - 4, ".dll") == 0)
330 len -= 4;
331 buf = malloc(len + 1);
332 memcpy(buf, (const void*)ptr, len);
333 buf[len] = 0;
334 globals.input_module = buf;
335 OUTPUT_UC_DLL_NAME = (setUC) ? str_toupper( strdup (OUTPUT_DLL_NAME)) : "";
338 /* Marks the symbol as 'found'! */
339 /* return: perform-search */
340 static int symbol_searched(int count, const char *symbolname)
342 search_symbol *search_symbol;
344 if (!(count >= globals.start_ordinal
345 && (!globals.end_ordinal || count <= globals.end_ordinal)))
346 return 0;
347 if (!globals.search_symbol)
348 return 1;
349 for (search_symbol = globals.search_symbol;
350 search_symbol;
351 search_symbol = search_symbol->next)
353 if (!strcmp(symbolname, search_symbol->symbolname))
355 search_symbol->found = 1;
356 return 1;
359 return 0;
362 /* return: some symbols weren't found */
363 static int symbol_finish(void)
365 const search_symbol *search_symbol;
366 int started = 0;
368 for (search_symbol = globals.search_symbol;
369 search_symbol;
370 search_symbol = search_symbol->next)
372 if (search_symbol->found)
373 continue;
374 if (!started)
376 /* stderr? not a practice here */
377 puts("These requested <symfile> symbols weren't found:");
378 started = 1;
380 printf("\t%s\n",search_symbol->symbolname);
382 return started;
385 /*******************************************************************
386 * main
388 #ifdef __GNUC__
389 int main (int argc __attribute__((unused)), char *argv[])
390 #else
391 int main (int argc, char *argv[])
392 #endif
394 parsed_symbol symbol;
395 int count = 0;
397 globals.mode = NONE;
398 globals.forward_dll = NULL;
399 globals.input_name = NULL;
401 parse_options (argv);
403 memset (&symbol, 0, sizeof (parsed_symbol));
405 switch (globals.mode)
407 case DMGL:
408 globals.uc_dll_name = "";
409 VERBOSE = 1;
411 symbol_init (&symbol, globals.input_name);
412 globals.input_module = "";
413 if (symbol_demangle (&symbol) == -1)
414 fatal( "Symbol hasn't got a mangled name\n");
415 if (symbol.flags & SYM_DATA)
416 printf (symbol.arg_text[0]);
417 else
418 output_prototype (stdout, &symbol);
419 fputc ('\n', stdout);
420 symbol_clear(&symbol);
421 break;
423 case SPEC:
424 if (globals.input_name == NULL)
425 fatal("No file name has been given\n");
426 set_module_name(1);
427 if (!dll_open (globals.input_name))
428 break;
430 output_spec_preamble ();
431 output_header_preamble ();
432 output_c_preamble ();
434 while (!dll_next_symbol (&symbol))
436 count++;
438 if (NORMAL)
439 printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
440 VERBOSE ? '\n' : ' ');
442 if (globals.do_code && symbol_searched(count, symbol.symbol))
444 /* Attempt to get information about the symbol */
445 int result = symbol_demangle (&symbol);
447 if (result)
448 result = symbol_search (&symbol);
450 if (!result && symbol.function_name)
451 /* Clean up the prototype */
452 symbol_clean_string (symbol.function_name);
454 if (NORMAL)
455 puts (result ? "[Not Found]" : "[OK]");
457 else if (NORMAL)
458 puts ("[Ignoring]");
460 output_spec_symbol (&symbol);
461 output_header_symbol (&symbol);
462 output_c_symbol (&symbol);
464 symbol_clear (&symbol);
467 output_makefile ();
468 output_install_script ();
470 if (VERBOSE)
471 puts ("Finished, Cleaning up...");
472 if (symbol_finish())
473 return 1;
474 break;
475 case NONE:
476 do_usage();
477 break;
478 case DUMP:
479 if (globals.input_name == NULL)
480 fatal("No file name has been given\n");
481 set_module_name(0);
482 dump_file(globals.input_name);
483 break;
484 case EMF:
485 if (globals.input_name == NULL)
486 fatal("No file name has been given\n");
487 dump_emf(globals.input_name);
488 break;
491 return 0;