wmc: Add support for generating a po template file.
[wine.git] / tools / wmc / wmc.c
blob1dde0d8f65458c907f717a7e6efb1af830fa61fd
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>
29 #include "wmc.h"
30 #include "utils.h"
31 #include "lang.h"
32 #include "write.h"
34 static const char usage[] =
35 "Usage: wmc [options...] [inputfile.mc]\n"
36 " -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
37 " (default is n[ative] which equals "
38 #ifdef WORDS_BIGENDIAN
39 "big"
40 #else
41 "little"
42 #endif
43 "-endian)\n"
44 " -c Set 'custom-bit' in values\n"
45 " -d Use decimal values in output\n"
46 " -D Set debug flag\n"
47 " -h This message\n"
48 " -H file Write headerfile to file (default is inputfile.h)\n"
49 " -i Inline messagetable(s)\n"
50 " -o file Output to file (default is inputfile.rc)\n"
51 " -O fmt Set output format (rc, res, pot)\n"
52 " -u Inputfile is in unicode\n"
53 " -U Output unicode messagetable(s)\n"
54 " -v Show supported codepages and languages\n"
55 " -V Print version end exit\n"
56 " -W Enable pedantic warnings\n"
57 "Input is taken from stdin if no inputfile is specified.\n"
58 "Byteorder of unicode input is based upon the first couple of\n"
59 "bytes read, which should be 0x0000..0x00ff.\n"
62 static const char version_string[] =
63 "Wine Message Compiler version " PACKAGE_VERSION "\n"
64 "Copyright 2000 Bertho A. Stultiens\n"
68 * The output byte-order of resources (set with -B)
70 int byteorder = WMC_BO_NATIVE;
73 * Custom bit (bit 29) in output values must be set (-c option)
75 int custombit = 0;
78 * Output decimal values (-d option)
80 int decimal = 0;
83 * Enable pedantic warnings; check arg references (-W option)
85 int pedantic = 0;
88 * Unicode input (-u option)
90 int unicodein = 0;
93 * Unicode output (-U option)
95 int unicodeout = 0;
98 * Inline the messagetables (don't write *.bin files; -i option)
100 int rcinline = 0;
103 * Debugging flag (-D option)
105 static int dodebug = 0;
107 char *output_name = NULL; /* The name given by the -o option */
108 char *input_name = NULL; /* The name given on the command-line */
109 char *header_name = NULL; /* The name given by the -H option */
111 int line_number = 1; /* The current line */
112 int char_number = 1; /* The current char pos within the line */
114 char *cmdline; /* The entire commandline */
115 time_t now; /* The time of start of wmc */
117 int mcy_debug;
119 FILE *yyin;
121 static enum
123 FORMAT_RC,
124 FORMAT_RES,
125 FORMAT_POT
126 } output_format;
128 int getopt (int argc, char *const *argv, const char *optstring);
129 static void segvhandler(int sig);
131 static void cleanup_files(void)
133 if (output_name) unlink( output_name );
134 if (header_name) unlink( header_name );
137 static void exit_on_signal( int sig )
139 exit(1); /* this will call the atexit functions */
142 int main(int argc,char *argv[])
144 extern char* optarg;
145 extern int optind;
146 int optc;
147 int lose = 0;
148 int ret;
149 int i;
150 int cmdlen;
152 atexit( cleanup_files );
153 signal(SIGSEGV, segvhandler);
154 signal( SIGTERM, exit_on_signal );
155 signal( SIGINT, exit_on_signal );
156 #ifdef SIGHUP
157 signal( SIGHUP, exit_on_signal );
158 #endif
160 now = time(NULL);
162 /* First rebuild the commandline to put in destination */
163 /* Could be done through env[], but not all OS-es support it */
164 cmdlen = 4; /* for "wmc " */
165 for(i = 1; i < argc; i++)
166 cmdlen += strlen(argv[i]) + 1;
167 cmdline = xmalloc(cmdlen);
168 strcpy(cmdline, "wmc ");
169 for(i = 1; i < argc; i++)
171 strcat(cmdline, argv[i]);
172 if(i < argc-1)
173 strcat(cmdline, " ");
176 while((optc = getopt(argc, argv, "B:cdDhH:io:O:p:uUvVW")) != EOF)
178 switch(optc)
180 case 'B':
181 switch(optarg[0])
183 case 'n':
184 case 'N':
185 byteorder = WMC_BO_NATIVE;
186 break;
187 case 'l':
188 case 'L':
189 byteorder = WMC_BO_LITTLE;
190 break;
191 case 'b':
192 case 'B':
193 byteorder = WMC_BO_BIG;
194 break;
195 default:
196 fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
197 lose++;
199 break;
200 case 'c':
201 custombit = 1;
202 break;
203 case 'd':
204 decimal = 1;
205 break;
206 case 'D':
207 dodebug = 1;
208 break;
209 case 'h':
210 printf("%s", usage);
211 exit(0);
212 /* No return */
213 case 'H':
214 header_name = xstrdup(optarg);
215 break;
216 case 'i':
217 rcinline = 1;
218 break;
219 case 'o':
220 output_name = xstrdup(optarg);
221 break;
222 case 'O':
223 if (!strcmp( optarg, "rc" )) output_format = FORMAT_RC;
224 else if (!strcmp( optarg, "res" )) output_format = FORMAT_RES;
225 else if (!strcmp( optarg, "pot" )) output_format = FORMAT_POT;
226 else
228 fprintf(stderr, "Output format must be rc or res\n" );
229 lose++;
231 break;
232 case 'u':
233 unicodein = 1;
234 break;
235 case 'U':
236 unicodeout = 1;
237 break;
238 case 'v':
239 show_languages();
240 show_codepages();
241 exit(0);
242 /* No return */
243 case 'V':
244 printf(version_string);
245 exit(0);
246 /* No return */
247 case 'W':
248 pedantic = 1;
249 break;
250 default:
251 lose++;
252 break;
256 if(lose)
258 fprintf(stderr, "%s", usage);
259 return 1;
262 mcy_debug = dodebug;
263 if(dodebug)
265 setbuf(stdout, NULL);
266 setbuf(stderr, NULL);
269 /* Check for input file on command-line */
270 if(optind < argc)
272 input_name = argv[optind];
275 /* Generate appropriate outfile names */
276 if(!output_name)
278 output_name = dup_basename(input_name, ".mc");
279 strcat(output_name, ".rc");
282 if(!header_name)
284 header_name = dup_basename(input_name, ".mc");
285 strcat(header_name, ".h");
288 if(input_name)
290 if(!(yyin = fopen(input_name, "rb")))
291 error("Could not open %s for input\n", input_name);
293 else
294 yyin = stdin;
296 ret = mcy_parse();
298 if(input_name)
299 fclose(yyin);
301 if(ret)
303 /* Error during parse */
304 exit(1);
307 #ifdef WORDS_BIGENDIAN
308 byte_swapped = (byteorder == WMC_BO_LITTLE);
309 #else
310 byte_swapped = (byteorder == WMC_BO_BIG);
311 #endif
313 switch (output_format)
315 case FORMAT_RC:
316 write_h_file(header_name);
317 write_rc_file(output_name);
318 if(!rcinline)
319 write_bin_files();
320 break;
321 case FORMAT_RES:
322 write_res_file( output_name );
323 break;
324 case FORMAT_POT:
325 write_pot_file( output_name );
326 break;
328 output_name = NULL;
329 header_name = NULL;
330 return 0;
333 static void segvhandler(int sig)
335 fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
336 fflush(stdout);
337 fflush(stderr);
338 abort();