msi: Update version resource.
[wine.git] / tools / wmc / wmc.c
blob9d34a40f30c2cb302b514ec0f6587e141e2461f8
1 /*
2 * Wine Message Compiler main program
4 * Copyright 2000 Bertho A. Stultiens (BS)
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <signal.h>
28 #ifdef HAVE_GETOPT_H
29 # include <getopt.h>
30 #endif
32 #include "wmc.h"
33 #include "utils.h"
34 #include "lang.h"
35 #include "write.h"
37 static const char usage[] =
38 "Usage: wmc [options...] [inputfile.mc]\n"
39 " -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
40 " (default is n[ative] which equals "
41 #ifdef WORDS_BIGENDIAN
42 "big"
43 #else
44 "little"
45 #endif
46 "-endian)\n"
47 " -c Set 'custom-bit' in values\n"
48 " -d Use decimal values in output\n"
49 " -D Set debug flag\n"
50 " -h, --help Print this message\n"
51 " -H FILE Write header file to FILE (default is inputfile.h)\n"
52 " -i Inline messagetable(s)\n"
53 " -o, --output=FILE Output to FILE (default is infile.rc)\n"
54 " -O, --output-format=FORMAT The output format (`rc', `res', or `pot')\n"
55 " -P, --po-dir=DIR Directory containing po files for translations\n"
56 " -u Input file is in unicode\n"
57 " -U Output unicode messagetable(s)\n"
58 " -v Show supported codepages and languages\n"
59 " -V, --version Print version end exit\n"
60 " -W, --pedantic Enable pedantic warnings\n"
61 "Input is taken from stdin if no inputfile is specified.\n"
62 "Byteorder of unicode input is based upon the first couple of\n"
63 "bytes read, which should be 0x0000..0x00ff.\n"
66 static const char version_string[] =
67 "Wine Message Compiler version " PACKAGE_VERSION "\n"
68 "Copyright 2000 Bertho A. Stultiens\n"
72 * The output byte-order of resources (set with -B)
74 int byteorder = WMC_BO_NATIVE;
77 * Custom bit (bit 29) in output values must be set (-c option)
79 int custombit = 0;
82 * Output decimal values (-d option)
84 int decimal = 0;
87 * Enable pedantic warnings; check arg references (-W option)
89 int pedantic = 0;
92 * Unicode input (-u option)
94 int unicodein = 0;
97 * Unicode output (-U option)
99 int unicodeout = 0;
102 * Inline the messagetables (don't write *.bin files; -i option)
104 int rcinline = 0;
107 * Debugging flag (-D option)
109 static int dodebug = 0;
111 static char *po_dir;
113 char *output_name = NULL; /* The name given by the -o option */
114 char *input_name = NULL; /* The name given on the command-line */
115 char *header_name = NULL; /* The name given by the -H option */
117 int line_number = 1; /* The current line */
118 int char_number = 1; /* The current char pos within the line */
120 char *cmdline; /* The entire commandline */
121 time_t now; /* The time of start of wmc */
123 int mcy_debug;
125 FILE *yyin;
127 static enum
129 FORMAT_RC,
130 FORMAT_RES,
131 FORMAT_POT
132 } output_format;
134 static const char short_options[] = "B:cdDhH:io:O:P:uUvVW";
135 static const struct option long_options[] =
137 { "help", 0, NULL, 'h' },
138 { "output", 1, NULL, 'o' },
139 { "output-format", 1, NULL, 'O' },
140 { "pedantic", 0, NULL, 'W' },
141 { "po-dir", 1, NULL, 'P' },
142 { "version", 0, NULL, 'v' }
145 static void segvhandler(int sig);
147 static void cleanup_files(void)
149 if (output_name) unlink( output_name );
150 if (header_name) unlink( header_name );
153 static void exit_on_signal( int sig )
155 exit(1); /* this will call the atexit functions */
158 int main(int argc,char *argv[])
160 extern char* optarg;
161 extern int optind;
162 int optc;
163 int opti = 0;
164 int lose = 0;
165 int ret;
166 int i;
167 int cmdlen;
169 atexit( cleanup_files );
170 signal(SIGSEGV, segvhandler);
171 signal( SIGTERM, exit_on_signal );
172 signal( SIGINT, exit_on_signal );
173 #ifdef SIGHUP
174 signal( SIGHUP, exit_on_signal );
175 #endif
177 /* First rebuild the commandline to put in destination */
178 /* Could be done through env[], but not all OS-es support it */
179 cmdlen = 5; /* for "wmc " and \0 */
180 for(i = 1; i < argc; i++)
181 cmdlen += strlen(argv[i]) + 1;
182 cmdline = xmalloc(cmdlen);
183 strcpy(cmdline, "wmc ");
184 for(i = 1; i < argc; i++)
186 strcat(cmdline, argv[i]);
187 if(i < argc-1)
188 strcat(cmdline, " ");
191 while((optc = getopt_long(argc, argv, short_options, long_options, &opti)) != EOF)
193 switch(optc)
195 case 'B':
196 switch(optarg[0])
198 case 'n':
199 case 'N':
200 byteorder = WMC_BO_NATIVE;
201 break;
202 case 'l':
203 case 'L':
204 byteorder = WMC_BO_LITTLE;
205 break;
206 case 'b':
207 case 'B':
208 byteorder = WMC_BO_BIG;
209 break;
210 default:
211 fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
212 lose++;
214 break;
215 case 'c':
216 custombit = 1;
217 break;
218 case 'd':
219 decimal = 1;
220 break;
221 case 'D':
222 dodebug = 1;
223 break;
224 case 'h':
225 printf("%s", usage);
226 exit(0);
227 /* No return */
228 case 'H':
229 header_name = xstrdup(optarg);
230 break;
231 case 'i':
232 rcinline = 1;
233 break;
234 case 'o':
235 output_name = xstrdup(optarg);
236 break;
237 case 'O':
238 if (!strcmp( optarg, "rc" )) output_format = FORMAT_RC;
239 else if (!strcmp( optarg, "res" )) output_format = FORMAT_RES;
240 else if (!strcmp( optarg, "pot" )) output_format = FORMAT_POT;
241 else
243 fprintf(stderr, "Output format must be rc or res\n" );
244 lose++;
246 break;
247 case 'P':
248 po_dir = xstrdup( optarg );
249 break;
250 case 'u':
251 unicodein = 1;
252 break;
253 case 'U':
254 unicodeout = 1;
255 break;
256 case 'v':
257 show_languages();
258 show_codepages();
259 exit(0);
260 /* No return */
261 case 'V':
262 printf(version_string);
263 exit(0);
264 /* No return */
265 case 'W':
266 pedantic = 1;
267 break;
268 default:
269 lose++;
270 break;
274 if(lose)
276 fprintf(stderr, "%s", usage);
277 return 1;
280 mcy_debug = dodebug;
281 if(dodebug)
283 setbuf(stdout, NULL);
284 setbuf(stderr, NULL);
287 /* Check for input file on command-line */
288 if(optind < argc)
290 input_name = argv[optind];
293 /* Generate appropriate outfile names */
294 if(!output_name)
296 output_name = dup_basename(input_name, ".mc");
297 strcat(output_name, ".rc");
300 if(!header_name)
302 header_name = dup_basename(input_name, ".mc");
303 strcat(header_name, ".h");
306 if(input_name)
308 if(!(yyin = fopen(input_name, "rb")))
309 error("Could not open %s for input\n", input_name);
311 else
312 yyin = stdin;
314 ret = mcy_parse();
316 if(input_name)
317 fclose(yyin);
319 if(ret)
321 /* Error during parse */
322 exit(1);
325 #ifdef WORDS_BIGENDIAN
326 byte_swapped = (byteorder == WMC_BO_LITTLE);
327 #else
328 byte_swapped = (byteorder == WMC_BO_BIG);
329 #endif
331 switch (output_format)
333 case FORMAT_RC:
334 write_h_file(header_name);
335 write_rc_file(output_name);
336 if(!rcinline)
337 write_bin_files();
338 break;
339 case FORMAT_RES:
340 add_translations( po_dir );
341 write_res_file( output_name );
342 break;
343 case FORMAT_POT:
344 write_pot_file( output_name );
345 break;
347 output_name = NULL;
348 header_name = NULL;
349 return 0;
352 static void segvhandler(int sig)
354 fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
355 fflush(stdout);
356 fflush(stderr);
357 abort();