Added an unknown VxD error code.
[wine] / tools / specmaker / main.c
1 /*
2  *  Option processing and main()
3  *
4  *  Copyright 2000 Jon Griffiths
5  */
6 #include "specmaker.h"
7
8
9 _globals globals; /* All global variables */
10
11
12 static void do_include (const char *arg)
13 {
14   globals.directory = arg;
15   globals.do_code = 1;
16 }
17
18
19 static inline const char* strip_ext (const char *str)
20 {
21   char *ext = strstr(str, ".dll");
22   if (ext)
23     return str_substring (str, ext);
24   else
25     return strdup (str);
26 }
27
28
29 static void do_name (const char *arg)
30 {
31   globals.dll_name = strip_ext (arg);
32 }
33
34
35 static void do_input (const char *arg)
36 {
37   globals.input_name = strip_ext (arg);
38 }
39
40
41 static void do_demangle (const char *arg)
42 {
43   globals.do_demangle = 1;
44   globals.do_code = 1;
45   globals.input_name = arg;
46 }
47
48
49 static void do_code (void)
50 {
51   globals.do_code = 1;
52 }
53
54
55 static void do_trace (void)
56 {
57   globals.do_trace = 1;
58   globals.do_code = 1;
59 }
60
61
62 static void do_forward (const char *arg)
63 {
64   globals.forward_dll = arg;
65   globals.do_trace = 1;
66   globals.do_code = 1;
67 }
68
69 static void do_document (void)
70 {
71   globals.do_documentation = 1;
72 }
73
74 static void do_cdecl (void)
75 {
76   globals.do_cdecl = 1;
77 }
78
79
80 static void do_quiet (void)
81 {
82   globals.do_quiet = 1;
83 }
84
85
86 static void do_start (const char *arg)
87 {
88   globals.start_ordinal = atoi (arg);
89   if (!globals.start_ordinal)
90     fatal ("Invalid -s option (must be numeric)");
91 }
92
93
94 static void do_end (const char *arg)
95 {
96   globals.end_ordinal = atoi (arg);
97   if (!globals.end_ordinal)
98     fatal ("Invalid -e option (must be numeric)");
99 }
100
101
102 static void do_verbose (void)
103 {
104   globals.do_verbose = 1;
105 }
106
107
108 struct option
109 {
110   const char *name;
111   int   has_arg;
112   void  (*func) ();
113   const char *usage;
114 };
115
116
117 static const struct option option_table[] = {
118   {"-d", 1, do_input,    "-d dll   Use dll for input file (mandatory)"},
119   {"-S", 1, do_demangle, "-S sym   Demangle C++ symbol 'sym' and exit"},
120   {"-h", 0, do_usage,    "-h       Display this help message"},
121   {"-I", 1, do_include,  "-I dir   Look for prototypes in 'dir' (implies -c)"},
122   {"-o", 1, do_name,     "-o name  Set the output dll name (default: dll)"},
123   {"-c", 0, do_code,     "-c       Generate skeleton code (requires -I)"},
124   {"-t", 0, do_trace,    "-t       TRACE arguments (implies -c)"},
125   {"-f", 1, do_forward,  "-f dll   Forward calls to 'dll' (implies -t)"},
126   {"-D", 0, do_document, "-D       Generate documentation"},
127   {"-C", 0, do_cdecl,    "-C       Assume __cdecl calls (default: __stdcall)"},
128   {"-s", 1, do_start,    "-s num   Start prototype search after symbol 'num'"},
129   {"-e", 1, do_end,      "-e num   End prototype search after symbol 'num'"},
130   {"-q", 0, do_quiet,    "-q       Don't show progress (quiet)."},
131   {"-v", 0, do_verbose,  "-v       Show lots of detail while working (verbose)."},
132   {NULL, 0, NULL, NULL}
133 };
134
135
136 void do_usage (void)
137 {
138   const struct option *opt;
139   printf ("Usage: specmaker [options] [-d dll | -S sym]\n\nOptions:\n");
140   for (opt = option_table; opt->name; opt++)
141     printf ("   %s\n", opt->usage);
142   puts ("\n");
143   exit (1);
144 }
145
146
147 /*******************************************************************
148  *          parse_options
149  *
150  * Parse options from the argv array
151  */
152 static void parse_options (char *argv[])
153 {
154   const struct option *opt;
155   char *const *ptr;
156   const char *arg = NULL;
157
158   ptr = argv + 1;
159
160   while (*ptr != NULL)
161   {
162     for (opt = option_table; opt->name; opt++)
163     {
164       if (opt->has_arg && !strncmp (*ptr, opt->name, strlen (opt->name)))
165       {
166         arg = *ptr + strlen (opt->name);
167         if (*arg == '\0')
168         {
169           ptr++;
170           arg = *ptr;
171         }
172         break;
173       }
174       if (!strcmp (*ptr, opt->name))
175       {
176         arg = NULL;
177         break;
178       }
179     }
180
181     if (!opt->name)
182       fatal ("Unrecognized option");
183
184     if (opt->has_arg && arg != NULL)
185       opt->func (arg);
186     else
187       opt->func ("");
188
189     ptr++;
190   }
191
192   if (!globals.do_demangle && globals.do_code && !globals.directory)
193     fatal ("-I must be used if generating code");
194
195   if (!globals.input_name)
196     fatal ("Option -d is mandatory");
197
198   if (VERBOSE && QUIET)
199     fatal ("Options -v and -q are mutually exclusive");
200 }
201
202
203 /*******************************************************************
204  *         main
205  */
206 #ifdef __GNUC__
207 int   main (int argc __attribute__((unused)), char *argv[])
208 #else
209 int   main (int argc, char *argv[])
210 #endif
211 {
212   parsed_symbol symbol;
213   int count = 0;
214
215   parse_options (argv);
216
217   memset (&symbol, 0, sizeof (parsed_symbol));
218
219   if (globals.do_demangle)
220   {
221     int result;
222     globals.uc_dll_name = "";
223     VERBOSE = 1;
224     symbol.symbol = strdup(globals.input_name);
225     result = symbol_demangle (&symbol);
226     if (symbol.flags & SYM_DATA)
227       printf (symbol.arg_text[0]);
228     else
229       output_prototype (stdout, &symbol);
230     fputc ('\n', stdout);
231     return result ? 1 : 0;
232   }
233
234   dll_open (globals.input_name);
235
236   output_spec_preamble ();
237   output_header_preamble ();
238   output_c_preamble ();
239
240   while (!dll_next_symbol (&symbol))
241   {
242     count++;
243
244     if (NORMAL)
245       printf ("Export %3d - '%s' ...%c", count, symbol.symbol,
246               VERBOSE ? '\n' : ' ');
247
248     if (globals.do_code && count >= globals.start_ordinal
249         && (!globals.end_ordinal || count <= globals.end_ordinal))
250     {
251       /* Attempt to get information about the symbol */
252       int result = symbol_demangle (&symbol);
253
254       if (result)
255         result = symbol_search (&symbol);
256
257       if (!result && symbol.function_name)
258       /* Clean up the prototype */
259         symbol_clean_string (symbol.function_name);
260
261       if (NORMAL)
262         puts (result ? "[Not Found]" : "[OK]");
263     }
264     else if (NORMAL)
265       puts ("[Ignoring]");
266
267     output_spec_symbol (&symbol);
268     output_header_symbol (&symbol);
269     output_c_symbol (&symbol);
270
271     symbol_clear (&symbol);
272   }
273
274   output_makefile ();
275   output_install_script ();
276
277   if (VERBOSE)
278     puts ("Finished, Cleaning up...");
279
280   return 0;
281 }