d2d1/tests: Declare "level" as D3D_FEATURE_LEVEL in create_d3d11_device().
[wine.git] / tools / wmc / wmc.c
blobf3cd88402761b7fc05e9c160860d2aaee99e2b21
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"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <limits.h>
28 #include <sys/types.h>
29 #ifdef HAVE_SYS_SYSCTL_H
30 # include <sys/sysctl.h>
31 #endif
33 #include "wmc.h"
34 #include "utils.h"
35 #include "lang.h"
36 #include "write.h"
38 static const char usage[] =
39 "Usage: wmc [options...] [inputfile.mc]\n"
40 " -c Set 'custom-bit' in values\n"
41 " -d Use decimal values in output\n"
42 " -D Set debug flag\n"
43 " -h, --help Print this message\n"
44 " -H FILE Write header file to FILE (default is inputfile.h)\n"
45 " -i Inline messagetable(s)\n"
46 " --nls-dir=DIR Directory containing the NLS codepage mappings\n"
47 " -o, --output=FILE Output to FILE (default is infile.rc)\n"
48 " -O, --output-format=FORMAT The output format (`rc', `res', or `pot')\n"
49 " -P, --po-dir=DIR Directory containing po files for translations\n"
50 " -u Input file is in unicode\n"
51 " -U Output unicode messagetable(s)\n"
52 " -v Show supported codepages and languages\n"
53 " -V, --version Print version end exit\n"
54 " -W, --pedantic Enable pedantic warnings\n"
55 "Input is taken from stdin if no inputfile is specified.\n"
56 "Byteorder of unicode input is based upon the first couple of\n"
57 "bytes read, which should be 0x0000..0x00ff.\n"
60 static const char version_string[] =
61 "Wine Message Compiler version " PACKAGE_VERSION "\n"
62 "Copyright 2000 Bertho A. Stultiens\n"
66 * Custom bit (bit 29) in output values must be set (-c option)
68 int custombit = 0;
71 * Output decimal values (-d option)
73 int decimal = 0;
76 * Enable pedantic warnings; check arg references (-W option)
78 int pedantic = 0;
81 * Unicode input (-u option)
83 int unicodein = 0;
86 * Inline the messagetables (don't write *.bin files; -i option)
88 int rcinline = 0;
91 * Debugging flag (-D option)
93 static int dodebug = 0;
95 static char *po_dir;
97 char *output_name = NULL; /* The name given by the -o option */
98 const char *input_name = NULL; /* The name given on the command-line */
99 char *header_name = NULL; /* The name given by the -H option */
101 const char *nlsdirs[3] = { NULL, NLSDIR, NULL };
103 int line_number = 1; /* The current line */
104 int char_number = 1; /* The current char pos within the line */
106 char *cmdline; /* The entire commandline */
107 time_t now; /* The time of start of wmc */
109 int mcy_debug;
111 FILE *yyin;
113 static enum
115 FORMAT_UNKNOWN,
116 FORMAT_RC,
117 FORMAT_RES,
118 FORMAT_POT
119 } output_format;
121 enum long_options_values
123 LONG_OPT_NLS_DIR = 1,
126 static const char short_options[] = "cdDhH:io:O:P:uUvVW";
127 static const struct long_option long_options[] =
129 { "help", 0, 'h' },
130 { "nls-dir", 1, LONG_OPT_NLS_DIR },
131 { "output", 1, 'o' },
132 { "output-format", 1, 'O' },
133 { "pedantic", 0, 'W' },
134 { "po-dir", 1, 'P' },
135 { "version", 0, 'v' },
136 { NULL }
139 static void cleanup_files(void)
141 if (output_name) unlink( output_name );
142 if (header_name) unlink( header_name );
145 static void exit_on_signal( int sig )
147 exit(1); /* this will call the atexit functions */
150 static void init_argv0_dir( const char *argv0 )
152 #ifndef _WIN32
153 char *dir;
155 #if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
156 dir = realpath( "/proc/self/exe", NULL );
157 #elif defined (__FreeBSD__) || defined(__DragonFly__)
158 static int pathname[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
159 size_t path_size = PATH_MAX;
160 char *path = malloc( path_size );
161 if (path && !sysctl( pathname, sizeof(pathname)/sizeof(pathname[0]), path, &path_size, NULL, 0 ))
162 dir = realpath( path, NULL );
163 free( path );
164 #else
165 dir = realpath( argv0, NULL );
166 #endif
167 if (!dir) return;
168 dir = get_dirname( dir );
169 if (strendswith( dir, "/tools/wmc" )) nlsdirs[0] = strmake( "%s/../../nls", dir );
170 else nlsdirs[0] = strmake( "%s/%s", dir, BIN_TO_NLSDIR );
171 #endif
174 static void option_callback( int optc, char *optarg )
176 switch(optc)
178 case 'c':
179 custombit = 1;
180 break;
181 case 'd':
182 decimal = 1;
183 break;
184 case 'D':
185 dodebug = 1;
186 break;
187 case 'h':
188 printf("%s", usage);
189 exit(0);
190 /* No return */
191 case 'H':
192 header_name = xstrdup(optarg);
193 break;
194 case 'i':
195 rcinline = 1;
196 break;
197 case 'o':
198 output_name = xstrdup(optarg);
199 break;
200 case 'O':
201 if (!strcmp( optarg, "rc" )) output_format = FORMAT_RC;
202 else if (!strcmp( optarg, "res" )) output_format = FORMAT_RES;
203 else if (!strcmp( optarg, "pot" )) output_format = FORMAT_POT;
204 else error("Output format must be rc or res\n" );
205 break;
206 case 'P':
207 po_dir = xstrdup( optarg );
208 break;
209 case 'u':
210 unicodein = 1;
211 break;
212 case 'U': /* ignored for backwards compatibility */
213 break;
214 case 'v':
215 show_languages();
216 exit(0);
217 /* No return */
218 case 'V':
219 printf(version_string);
220 exit(0);
221 /* No return */
222 case 'W':
223 pedantic = 1;
224 break;
225 case LONG_OPT_NLS_DIR:
226 nlsdirs[0] = xstrdup( optarg );
227 break;
228 case '?':
229 fprintf(stderr, "wmc: %s\n\n%s", optarg, usage);
230 exit(1);
234 int main(int argc,char *argv[])
236 int ret;
237 int i;
238 int cmdlen;
239 struct strarray files;
241 atexit( cleanup_files );
242 signal( SIGTERM, exit_on_signal );
243 signal( SIGINT, exit_on_signal );
244 #ifdef SIGHUP
245 signal( SIGHUP, exit_on_signal );
246 #endif
247 init_argv0_dir( argv[0] );
249 /* First rebuild the commandline to put in destination */
250 /* Could be done through env[], but not all OS-es support it */
251 cmdlen = 5; /* for "wmc " and \0 */
252 for(i = 1; i < argc; i++)
253 cmdlen += strlen(argv[i]) + 1;
254 cmdline = xmalloc(cmdlen);
255 strcpy(cmdline, "wmc ");
256 for(i = 1; i < argc; i++)
258 strcat(cmdline, argv[i]);
259 if(i < argc-1)
260 strcat(cmdline, " ");
263 files = parse_options( argc, argv, short_options, long_options, 0, option_callback );
265 mcy_debug = dodebug;
266 if(dodebug)
268 setbuf(stdout, NULL);
269 setbuf(stderr, NULL);
272 /* Check for input file on command-line */
273 if (files.count) input_name = files.str[0];
275 /* Guess output format */
276 if (output_format == FORMAT_UNKNOWN)
278 if (output_name && strendswith( output_name, ".res" )) output_format = FORMAT_RES;
279 else if (output_name && strendswith( output_name, ".pot" )) output_format = FORMAT_POT;
280 else output_format = FORMAT_RC;
283 /* Generate appropriate outfile names */
284 if(!output_name)
286 const char *name = input_name ? get_basename(input_name) : "wmc.tab";
287 output_name = replace_extension( name, ".mc", ".rc" );
290 if(!header_name)
292 const char *name = input_name ? get_basename(input_name) : "wmc.tab";
293 header_name = replace_extension( name, ".mc", ".h" );
296 if(input_name)
298 if(!(yyin = fopen(input_name, "rb")))
299 error("Could not open %s for input\n", input_name);
301 else
302 yyin = stdin;
304 ret = mcy_parse();
306 if(input_name)
307 fclose(yyin);
309 if(ret)
311 /* Error during parse */
312 exit(1);
315 switch (output_format)
317 case FORMAT_RC:
318 write_h_file(header_name);
319 write_rc_file(output_name);
320 if(!rcinline)
321 write_bin_files();
322 break;
323 case FORMAT_RES:
324 add_translations( po_dir );
325 write_res_file( output_name );
326 break;
327 case FORMAT_POT:
328 write_pot_file( output_name );
329 break;
330 default:
331 break;
333 output_name = NULL;
334 header_name = NULL;
335 return 0;