Added ability to turn on/off debug channels.
[wine.git] / tools / winedump / main.c
blob1ec0b50149c0828b989bfff15c50d895dd619e4e
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
20 #include "winedump.h"
23 _globals globals; /* All global variables */
26 static void do_include (const char *arg)
28 globals.directory = arg;
29 globals.do_code = 1;
33 static inline const char* strip_ext (const char *str)
35 char *ext = strstr(str, ".dll");
36 if (ext)
37 return str_substring (str, ext);
38 else
39 return strdup (str);
43 static void do_name (const char *arg)
45 globals.dll_name = strip_ext (arg);
49 static void do_spec (const char *arg)
51 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
52 globals.mode = SPEC;
56 static void do_demangle (const char *arg)
58 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
59 globals.mode = DMGL;
60 globals.do_code = 1;
64 static void do_dump (const char *arg)
66 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
67 globals.mode = DUMP;
68 globals.do_code = 1;
72 static void do_code (void)
74 globals.do_code = 1;
78 static void do_trace (void)
80 globals.do_trace = 1;
81 globals.do_code = 1;
85 static void do_forward (const char *arg)
87 globals.forward_dll = arg;
88 globals.do_trace = 1;
89 globals.do_code = 1;
92 static void do_document (void)
94 globals.do_documentation = 1;
97 static void do_cdecl (void)
99 globals.do_cdecl = 1;
103 static void do_quiet (void)
105 globals.do_quiet = 1;
109 static void do_start (const char *arg)
111 globals.start_ordinal = atoi (arg);
112 if (!globals.start_ordinal)
113 fatal ("Invalid -s option (must be numeric)");
117 static void do_end (const char *arg)
119 globals.end_ordinal = atoi (arg);
120 if (!globals.end_ordinal)
121 fatal ("Invalid -e option (must be numeric)");
125 static void do_verbose (void)
127 globals.do_verbose = 1;
131 static void do_symdmngl (void)
133 globals.do_demangle = 1;
136 static void do_dumphead (void)
138 globals.do_dumpheader = 1;
141 static void do_dumpsect (const char* arg)
143 globals.dumpsect = arg;
146 static void do_dumpall(void)
148 globals.do_dumpheader = 1;
149 globals.dumpsect = "ALL";
152 struct option
154 const char *name;
155 Mode mode;
156 int has_arg;
157 void (*func) ();
158 const char *usage;
161 static const struct option option_table[] = {
162 {"-h", NONE, 0, do_usage, "-h Display this help message"},
163 {"sym", DMGL, 0, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
164 {"spec", SPEC, 0, do_spec, "spec <dll> Use dll for input file and generate implementation code"},
165 {"-I", SPEC, 1, do_include, "-I dir Look for prototypes in 'dir' (implies -c)"},
166 {"-c", SPEC, 0, do_code, "-c Generate skeleton code (requires -I)"},
167 {"-t", SPEC, 0, do_trace, "-t TRACE arguments (implies -c)"},
168 {"-f", SPEC, 1, do_forward, "-f dll Forward calls to 'dll' (implies -t)"},
169 {"-D", SPEC, 0, do_document, "-D Generate documentation"},
170 {"-o", SPEC, 1, do_name, "-o name Set the output dll name (default: dll)"},
171 {"-C", SPEC, 0, do_cdecl, "-C Assume __cdecl calls (default: __stdcall)"},
172 {"-s", SPEC, 1, do_start, "-s num Start prototype search after symbol 'num'"},
173 {"-e", SPEC, 1, do_end, "-e num End prototype search after symbol 'num'"},
174 {"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."},
175 {"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."},
176 {"dump", DUMP, 0, do_dump, "dump <mod> Dumps the content of the module (dll, exe...) named <mod>"},
177 {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"},
178 {"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"},
179 {"-j", DUMP, 1, do_dumpsect, "-j sect_name Dumps only the content of section sect_name (import, export, debug)"},
180 {"-x", DUMP, 0, do_dumpall, "-x Dumps everything"},
181 {NULL, NONE, 0, NULL, NULL}
184 void do_usage (void)
186 const struct option *opt;
187 printf ("Usage: winedump [-h | sym <sym> | spec <dll> | dump <dll>]\n");
188 printf ("Mode options (can be put as the mode (sym/spec/dump...) is declared):\n");
189 printf ("\tWhen used in -h mode\n");
190 for (opt = option_table; opt->name; opt++)
191 if (opt->mode == NONE)
192 printf ("\t %s\n", opt->usage);
193 printf ("\tWhen used in sym mode\n");
194 for (opt = option_table; opt->name; opt++)
195 if (opt->mode == DMGL)
196 printf ("\t %s\n", opt->usage);
197 printf ("\tWhen used in spec mode\n");
198 for (opt = option_table; opt->name; opt++)
199 if (opt->mode == SPEC)
200 printf ("\t %s\n", opt->usage);
201 printf ("\tWhen used in dump mode\n");
202 for (opt = option_table; opt->name; opt++)
203 if (opt->mode == DUMP)
204 printf ("\t %s\n", opt->usage);
206 puts ("\n");
207 exit (1);
211 /*******************************************************************
212 * parse_options
214 * Parse options from the argv array
216 static void parse_options (char *argv[])
218 const struct option *opt;
219 char *const *ptr;
220 const char *arg = NULL;
222 ptr = argv + 1;
224 while (*ptr != NULL)
226 for (opt = option_table; opt->name; opt++)
228 if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
229 continue;
230 if (((opt->has_arg == 1) && !strncmp (*ptr, opt->name, strlen (opt->name))) ||
231 ((opt->has_arg == 2) && !strcmp (*ptr, opt->name)))
233 arg = *ptr + strlen (opt->name);
234 if (*arg == '\0') arg = *++ptr;
235 break;
237 if (!strcmp (*ptr, opt->name))
239 arg = NULL;
240 break;
244 if (!opt->name)
246 if ((*ptr)[0] == '-')
247 fatal ("Unrecognized option");
248 if (globals.input_name != NULL)
249 fatal ("Only one file can be treated at once");
250 globals.input_name = *ptr;
252 else if (opt->has_arg && arg != NULL)
253 opt->func (arg);
254 else
255 opt->func ("");
257 ptr++;
260 if (globals.mode == SPEC && globals.do_code && !globals.directory)
261 fatal ("-I must be used if generating code");
263 if (VERBOSE && QUIET)
264 fatal ("Options -v and -q are mutually exclusive");
267 static void set_module_name(unsigned setUC)
269 const char* ptr;
270 char* buf;
271 int len;
273 /* FIXME: we shouldn't assume all module extensions are .dll in winedump
274 * in some cases, we could have some .drv for example
276 /* get module name from name */
277 if ((ptr = strrchr (globals.input_name, '/')))
278 ptr++;
279 else
280 ptr = globals.input_name;
281 len = strlen(ptr);
282 if (len > 4 && strcmp(ptr + len - 4, ".dll") == 0)
283 len -= 4;
284 buf = malloc(len + 1);
285 memcpy(buf, (void*)ptr, len);
286 buf[len] = 0;
287 globals.input_module = buf;
288 OUTPUT_UC_DLL_NAME = (setUC) ? str_toupper( strdup (OUTPUT_DLL_NAME)) : "";
291 /*******************************************************************
292 * main
294 #ifdef __GNUC__
295 int main (int argc __attribute__((unused)), char *argv[])
296 #else
297 int main (int argc, char *argv[])
298 #endif
300 parsed_symbol symbol;
301 int count = 0;
303 globals.mode = NONE;
304 globals.forward_dll = NULL;
305 globals.input_name = NULL;
307 parse_options (argv);
309 memset (&symbol, 0, sizeof (parsed_symbol));
311 switch (globals.mode)
313 case DMGL:
314 globals.uc_dll_name = "";
315 VERBOSE = 1;
317 symbol_init (&symbol, globals.input_name);
318 globals.input_module = "";
319 if (symbol_demangle (&symbol) == -1)
320 fatal( "Symbol hasn't got a mangled name\n");
321 if (symbol.flags & SYM_DATA)
322 printf (symbol.arg_text[0]);
323 else
324 output_prototype (stdout, &symbol);
325 fputc ('\n', stdout);
326 symbol_clear(&symbol);
327 break;
329 case SPEC:
330 set_module_name(1);
331 dll_open (globals.input_name);
333 output_spec_preamble ();
334 output_header_preamble ();
335 output_c_preamble ();
337 while (!dll_next_symbol (&symbol))
339 count++;
341 if (NORMAL)
342 printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
343 VERBOSE ? '\n' : ' ');
345 if (globals.do_code && count >= globals.start_ordinal
346 && (!globals.end_ordinal || count <= globals.end_ordinal))
348 /* Attempt to get information about the symbol */
349 int result = symbol_demangle (&symbol);
351 if (result)
352 result = symbol_search (&symbol);
354 if (!result && symbol.function_name)
355 /* Clean up the prototype */
356 symbol_clean_string (symbol.function_name);
358 if (NORMAL)
359 puts (result ? "[Not Found]" : "[OK]");
361 else if (NORMAL)
362 puts ("[Ignoring]");
364 output_spec_symbol (&symbol);
365 output_header_symbol (&symbol);
366 output_c_symbol (&symbol);
368 symbol_clear (&symbol);
371 output_makefile ();
372 output_install_script ();
374 if (VERBOSE)
375 puts ("Finished, Cleaning up...");
376 break;
377 case NONE:
378 do_usage();
379 break;
380 case DUMP:
381 set_module_name(0);
382 dump_file(globals.input_name);
383 break;
386 return 0;