6535d671cd3fd26d3529e45c968c279c9d7fe87e
[reactos.git] / reactos / tools / wmc / wmc.c
1 /*
2 * Wine Message Compiler main program
3 *
4 * Copyright 2000 Bertho A. Stultiens (BS)
5 *
6 */
7 #include <windows.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <signal.h>
12
13 #include "config.h"
14
15 #include "wmc.h"
16 #include "utils.h"
17 #include "lang.h"
18 #include "write.h"
19
20 static char usage[] =
21 "Usage: wmc [options...] [inputfile.mc]\n"
22 " -B x Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
23 " (default is n[ative] which equals "
24 #ifdef WORDS_BIGENDIAN
25 "big"
26 #else
27 "little"
28 #endif
29 "-endian)\n"
30 " -c Set 'custom-bit' in values\n"
31 " -d Use decimal values in output\n"
32 " -D Set debug flag\n"
33 " -h This message\n"
34 " -H file Write headerfile to file (default is inputfile.h)\n"
35 " -i Inline messagetable(s)\n"
36 " -o file Output to file (default is inputfile.rc)\n"
37 " -u Inputfile is in unicode\n"
38 " -U Output unicode messagetable(s)\n"
39 " -v Show supported codepages and languages\n"
40 " -V Print version end exit\n"
41 " -W Enable pedantic warnings\n"
42 "Input is taken from stdin if no inputfile is specified.\n"
43 "Byteorder of unicode input is based upon the first couple of\n"
44 "bytes read, which should be 0x0000..0x00ff.\n"
45 ;
46
47 static char version_string[] =
48 "Wine Message Compiler Version " WMC_FULLVERSION "\n"
49 "Copyright 2000 Bertho A. Stultiens\n"
50 ;
51
52 /*
53 * The output byte-order of resources (set with -B)
54 */
55 int byteorder = WMC_BO_NATIVE;
56
57 /*
58 * Custom bit (bit 29) in output values must be set (-c option)
59 */
60 int custombit = 0;
61
62 /*
63 * Output decimal values (-d option)
64 */
65 int decimal = 0;
66
67 /*
68 * Enable pedantic warnings; check arg references (-W option)
69 */
70 int pedantic = 0;
71
72 /*
73 * Unicode input (-u option)
74 */
75 int unicodein = 0;
76
77 /*
78 * Unicode output (-U option)
79 */
80 int unicodeout = 0;
81
82 /*
83 * Inline the messagetables (don't write *.bin files; -i option)
84 */
85 int rcinline = 0;
86
87 /*
88 * Debugging flag (-D option)
89 */
90 int dodebug = 0;
91
92 char *output_name = NULL; /* The name given by the -o option */
93 char *input_name = NULL; /* The name given on the command-line */
94 char *header_name = NULL; /* The name given by the -H option */
95
96 int line_number = 1; /* The current line */
97 int char_number = 1; /* The current char pos within the line */
98
99 char *cmdline; /* The entire commandline */
100 time_t now; /* The time of start of wmc */
101
102 int getopt (int argc, char *const *argv, const char *optstring);
103 static void segvhandler(int sig);
104
105 int main(int argc,char *argv[])
106 {
107 extern char* optarg;
108 extern int optind;
109 int optc;
110 int lose = 0;
111 int ret;
112 int i;
113 int cmdlen;
114
115 signal(SIGSEGV, segvhandler);
116
117 now = time(NULL);
118
119 /* First rebuild the commandline to put in destination */
120 /* Could be done through env[], but not all OS-es support it */
121 cmdlen = 4; /* for "wmc " */
122 for(i = 1; i < argc; i++)
123 cmdlen += strlen(argv[i]) + 1;
124 cmdline = (char *)xmalloc(cmdlen);
125 strcpy(cmdline, "wmc ");
126 for(i = 1; i < argc; i++)
127 {
128 strcat(cmdline, argv[i]);
129 if(i < argc-1)
130 strcat(cmdline, " ");
131 }
132
133 while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF)
134 {
135 switch(optc)
136 {
137 case 'B':
138 switch(optarg[0])
139 {
140 case 'n':
141 case 'N':
142 byteorder = WMC_BO_NATIVE;
143 break;
144 case 'l':
145 case 'L':
146 byteorder = WMC_BO_LITTLE;
147 break;
148 case 'b':
149 case 'B':
150 byteorder = WMC_BO_BIG;
151 break;
152 default:
153 fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
154 lose++;
155 }
156 break;
157 case 'c':
158 custombit = 1;
159 break;
160 case 'd':
161 decimal = 1;
162 break;
163 case 'D':
164 dodebug = 1;
165 break;
166 case 'h':
167 printf("%s", usage);
168 exit(0);
169 /* No return */
170 case 'H':
171 header_name = xstrdup(optarg);
172 break;
173 case 'i':
174 rcinline = 1;
175 break;
176 case 'o':
177 output_name = xstrdup(optarg);
178 break;
179 case 'u':
180 unicodein = 1;
181 break;
182 case 'U':
183 unicodeout = 1;
184 break;
185 case 'v':
186 show_languages();
187 show_codepages();
188 exit(0);
189 /* No return */
190 case 'V':
191 printf(version_string);
192 exit(0);
193 /* No return */
194 case 'W':
195 pedantic = 1;
196 break;
197 default:
198 lose++;
199 break;
200 }
201 }
202
203 if(lose)
204 {
205 fprintf(stderr, "%s", usage);
206 return 1;
207 }
208
209 yydebug = dodebug;
210 if(dodebug)
211 {
212 setbuf(stdout, 0);
213 setbuf(stderr, 0);
214 }
215
216 /* Check for input file on command-line */
217 if(optind < argc)
218 {
219 input_name = argv[optind];
220 }
221
222 /* Generate appropriate outfile names */
223 if(!output_name)
224 {
225 output_name = dup_basename(input_name, ".mc");
226 strcat(output_name, ".rc");
227 }
228
229 if(!header_name)
230 {
231 header_name = dup_basename(input_name, ".mc");
232 strcat(header_name, ".h");
233 }
234
235 if(input_name)
236 {
237 if(!(yyin = fopen(input_name, "rb")))
238 error("Could not open %s for input\n", input_name);
239 }
240 else
241 yyin = stdin;
242
243 ret = yyparse();
244
245 if(input_name)
246 fclose(yyin);
247
248 if(ret)
249 {
250 /* Error during parse */
251 exit(1);
252 }
253
254 write_h_file(header_name);
255 write_rc_file(output_name);
256 if(!rcinline)
257 write_bin_files();
258
259 return 0;
260 }
261
262 static void segvhandler(int sig)
263 {
264 fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
265 fflush(stdout);
266 fflush(stderr);
267 abort();
268 }
269