Fixed copyright date.
[wine/testsucceed.git] / tools / winedump / main.c
blob55199a2b82a714b5550de9858086bc46940090fb
1 /*
2 * Option processing and main()
4 * Copyright 2000 Jon Griffiths
5 */
6 #include "winedump.h"
9 _globals globals; /* All global variables */
12 static void do_include (const char *arg)
14 globals.directory = arg;
15 globals.do_code = 1;
19 static inline const char* strip_ext (const char *str)
21 char *ext = strstr(str, ".dll");
22 if (ext)
23 return str_substring (str, ext);
24 else
25 return strdup (str);
29 static void do_name (const char *arg)
31 globals.dll_name = strip_ext (arg);
35 static void do_spec (const char *arg)
37 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
38 globals.mode = SPEC;
39 globals.input_name = arg;
43 static void do_demangle (const char *arg)
45 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
46 globals.mode = DMGL;
47 globals.do_code = 1;
48 globals.input_name = arg;
52 static void do_dump (const char *arg)
54 if (globals.mode != NONE) fatal("Only one mode can be specified\n");
55 globals.mode = DUMP;
56 globals.do_code = 1;
57 globals.input_name = arg;
61 static void do_code (void)
63 globals.do_code = 1;
67 static void do_trace (void)
69 globals.do_trace = 1;
70 globals.do_code = 1;
74 static void do_forward (const char *arg)
76 globals.forward_dll = arg;
77 globals.do_trace = 1;
78 globals.do_code = 1;
81 static void do_document (void)
83 globals.do_documentation = 1;
86 static void do_cdecl (void)
88 globals.do_cdecl = 1;
92 static void do_quiet (void)
94 globals.do_quiet = 1;
98 static void do_start (const char *arg)
100 globals.start_ordinal = atoi (arg);
101 if (!globals.start_ordinal)
102 fatal ("Invalid -s option (must be numeric)");
106 static void do_end (const char *arg)
108 globals.end_ordinal = atoi (arg);
109 if (!globals.end_ordinal)
110 fatal ("Invalid -e option (must be numeric)");
114 static void do_verbose (void)
116 globals.do_verbose = 1;
120 static void do_symdmngl (void)
122 globals.do_demangle = 1;
125 static void do_dumphead (void)
127 globals.do_dumpheader = 1;
130 static void do_dumpsect (const char* arg)
132 globals.dumpsect = arg;
135 static void do_dumpall(void)
137 globals.do_dumpheader = 1;
138 globals.dumpsect = "ALL";
141 struct option
143 const char *name;
144 Mode mode;
145 int has_arg;
146 void (*func) ();
147 const char *usage;
150 static const struct option option_table[] = {
151 {"-h", NONE, 0, do_usage, "-h Display this help message"},
152 {"sym", DMGL, 2, do_demangle, "sym <sym> Demangle C++ symbol <sym> and exit"},
153 {"spec", SPEC, 2, do_spec, "spec <dll> Use dll for input file and generate implementation code"},
154 {"-I", SPEC, 1, do_include, "-I dir Look for prototypes in 'dir' (implies -c)"},
155 {"-c", SPEC, 0, do_code, "-c Generate skeleton code (requires -I)"},
156 {"-t", SPEC, 0, do_trace, "-t TRACE arguments (implies -c)"},
157 {"-f", SPEC, 1, do_forward, "-f dll Forward calls to 'dll' (implies -t)"},
158 {"-D", SPEC, 0, do_document, "-D Generate documentation"},
159 {"-o", SPEC, 1, do_name, "-o name Set the output dll name (default: dll)"},
160 {"-C", SPEC, 0, do_cdecl, "-C Assume __cdecl calls (default: __stdcall)"},
161 {"-s", SPEC, 1, do_start, "-s num Start prototype search after symbol 'num'"},
162 {"-e", SPEC, 1, do_end, "-e num End prototype search after symbol 'num'"},
163 {"-q", SPEC, 0, do_quiet, "-q Don't show progress (quiet)."},
164 {"-v", SPEC, 0, do_verbose, "-v Show lots of detail while working (verbose)."},
165 {"dump", DUMP, 2, do_dump, "dump <mod> Dumps the content of the module (dll, exe...) named <mod>"},
166 {"-C", DUMP, 0, do_symdmngl, "-C Turns on symbol demangling"},
167 {"-f", DUMP, 0, do_dumphead, "-f Dumps file header information"},
168 {"-j", DUMP, 1, do_dumpsect, "-j sect_name Dumps only the content of section sect_name (import, export, debug)"},
169 {"-x", DUMP, 0, do_dumpall, "-x Dumps everything"},
170 {NULL, NONE, 0, NULL, NULL}
173 void do_usage (void)
175 const struct option *opt;
176 printf ("Usage: winedump [-h sym <sym> spec <dll> dump <dll>] [mode options]\n");
177 printf ("When used in -h mode\n");
178 for (opt = option_table; opt->name; opt++)
179 if (opt->mode == NONE)
180 printf (" %s\n", opt->usage);
181 printf ("When used in sym mode\n");
182 for (opt = option_table; opt->name; opt++)
183 if (opt->mode == DMGL)
184 printf (" %s\n", opt->usage);
185 printf ("When used in spec mode\n");
186 for (opt = option_table; opt->name; opt++)
187 if (opt->mode == SPEC)
188 printf (" %s\n", opt->usage);
189 printf ("When used in dump mode\n");
190 for (opt = option_table; opt->name; opt++)
191 if (opt->mode == DUMP)
192 printf (" %s\n", opt->usage);
194 puts ("\n");
195 exit (1);
199 /*******************************************************************
200 * parse_options
202 * Parse options from the argv array
204 static void parse_options (char *argv[])
206 const struct option *opt;
207 char *const *ptr;
208 const char *arg = NULL;
210 ptr = argv + 1;
212 while (*ptr != NULL)
214 for (opt = option_table; opt->name; opt++)
216 if (globals.mode != NONE && opt->mode != NONE && globals.mode != opt->mode)
217 continue;
218 if (((opt->has_arg == 1) && !strncmp (*ptr, opt->name, strlen (opt->name))) ||
219 ((opt->has_arg == 2) && !strcmp (*ptr, opt->name)))
221 arg = *ptr + strlen (opt->name);
222 if (*arg == '\0') arg = *++ptr;
223 break;
225 if (!strcmp (*ptr, opt->name))
227 arg = NULL;
228 break;
232 if (!opt->name)
233 fatal ("Unrecognized option");
235 if (opt->has_arg && arg != NULL)
236 opt->func (arg);
237 else
238 opt->func ("");
240 ptr++;
243 if (globals.mode == SPEC && globals.do_code && !globals.directory)
244 fatal ("-I must be used if generating code");
246 if (VERBOSE && QUIET)
247 fatal ("Options -v and -q are mutually exclusive");
250 static void set_module_name(unsigned setUC)
252 const char* ptr;
253 char* buf;
254 int len;
256 /* FIXME: we shouldn't assume all module extensions are .dll in winedump
257 * in some cases, we could have some .drv for example
259 /* get module name from name */
260 if ((ptr = strrchr (globals.input_name, '/')))
261 ptr++;
262 else
263 ptr = globals.input_name;
264 len = strlen(ptr);
265 if (len > 4 && strcmp(ptr + len - 4, ".dll") == 0)
266 len -= 4;
267 buf = malloc(len + 1);
268 memcpy(buf, (void*)ptr, len);
269 buf[len] = 0;
270 globals.input_module = buf;
271 OUTPUT_UC_DLL_NAME = (setUC) ? str_toupper( strdup (OUTPUT_DLL_NAME)) : "";
274 /*******************************************************************
275 * main
277 #ifdef __GNUC__
278 int main (int argc __attribute__((unused)), char *argv[])
279 #else
280 int main (int argc, char *argv[])
281 #endif
283 parsed_symbol symbol;
284 int count = 0;
286 globals.mode = NONE;
287 globals.forward_dll = NULL;
289 parse_options (argv);
291 memset (&symbol, 0, sizeof (parsed_symbol));
293 switch (globals.mode)
295 case DMGL:
296 globals.uc_dll_name = "";
297 VERBOSE = 1;
299 symbol_init (&symbol, globals.input_name);
300 globals.input_module = "";
301 if (symbol_demangle (&symbol) == -1)
302 fatal( "Symbol hasn't got a mangled name\n");
303 if (symbol.flags & SYM_DATA)
304 printf (symbol.arg_text[0]);
305 else
306 output_prototype (stdout, &symbol);
307 fputc ('\n', stdout);
308 symbol_clear(&symbol);
309 break;
311 case SPEC:
312 set_module_name(1);
313 dll_open (globals.input_name);
315 output_spec_preamble ();
316 output_header_preamble ();
317 output_c_preamble ();
319 while (!dll_next_symbol (&symbol))
321 count++;
323 if (NORMAL)
324 printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
325 VERBOSE ? '\n' : ' ');
327 if (globals.do_code && count >= globals.start_ordinal
328 && (!globals.end_ordinal || count <= globals.end_ordinal))
330 /* Attempt to get information about the symbol */
331 int result = symbol_demangle (&symbol);
333 if (result)
334 result = symbol_search (&symbol);
336 if (!result && symbol.function_name)
337 /* Clean up the prototype */
338 symbol_clean_string (symbol.function_name);
340 if (NORMAL)
341 puts (result ? "[Not Found]" : "[OK]");
343 else if (NORMAL)
344 puts ("[Ignoring]");
346 output_spec_symbol (&symbol);
347 output_header_symbol (&symbol);
348 output_c_symbol (&symbol);
350 symbol_clear (&symbol);
353 output_makefile ();
354 output_install_script ();
356 if (VERBOSE)
357 puts ("Finished, Cleaning up...");
358 break;
359 case NONE:
360 do_usage();
361 break;
362 case DUMP:
363 set_module_name(0);
364 dump_file(globals.input_name);
365 break;
368 return 0;