wineps: Don't use CDECL for private functions.
[wine.git] / tools / wmc / wmc.c
blobe4f2377e77213a0064cfe28015bb03225a29af3e
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 <limits.h>
27 #include <sys/types.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 " -c Set 'custom-bit' in values\n"
37 " -d Use decimal values in output\n"
38 " -D Set debug flag\n"
39 " -h, --help Print this message\n"
40 " -H FILE Write header file to FILE (default is inputfile.h)\n"
41 " -i Inline messagetable(s)\n"
42 " --nls-dir=DIR Directory containing the NLS codepage mappings\n"
43 " -o, --output=FILE Output to FILE (default is infile.rc)\n"
44 " -O, --output-format=FORMAT The output format (`rc', `res', or `pot')\n"
45 " -P, --po-dir=DIR Directory containing po files for translations\n"
46 " -u Input file is in unicode\n"
47 " -U Output unicode messagetable(s)\n"
48 " -v Show supported codepages and languages\n"
49 " -V, --version Print version end exit\n"
50 " -W, --pedantic Enable pedantic warnings\n"
51 "Input is taken from stdin if no inputfile is specified.\n"
52 "Byteorder of unicode input is based upon the first couple of\n"
53 "bytes read, which should be 0x0000..0x00ff.\n"
56 static const char version_string[] =
57 "Wine Message Compiler version " PACKAGE_VERSION "\n"
58 "Copyright 2000 Bertho A. Stultiens\n"
62 * Custom bit (bit 29) in output values must be set (-c option)
64 int custombit = 0;
67 * Output decimal values (-d option)
69 int decimal = 0;
72 * Enable pedantic warnings; check arg references (-W option)
74 int pedantic = 0;
77 * Unicode input (-u option)
79 int unicodein = 0;
82 * Inline the messagetables (don't write *.bin files; -i option)
84 int rcinline = 0;
87 * Debugging flag (-D option)
89 static int dodebug = 0;
91 static char *po_dir;
93 char *output_name = NULL; /* The name given by the -o option */
94 const char *input_name = NULL; /* The name given on the command-line */
95 char *header_name = NULL; /* The name given by the -H option */
97 const char *nlsdirs[3] = { NULL, NLSDIR, NULL };
99 int line_number = 1; /* The current line */
100 int char_number = 1; /* The current char pos within the line */
102 char *cmdline; /* The entire commandline */
103 time_t now; /* The time of start of wmc */
105 int mcy_debug;
107 FILE *yyin;
109 static enum
111 FORMAT_UNKNOWN,
112 FORMAT_RC,
113 FORMAT_RES,
114 FORMAT_POT
115 } output_format;
117 enum long_options_values
119 LONG_OPT_NLS_DIR = 1,
122 static const char short_options[] = "cdDhH:io:O:P:uUvVW";
123 static const struct long_option long_options[] =
125 { "help", 0, 'h' },
126 { "nls-dir", 1, LONG_OPT_NLS_DIR },
127 { "output", 1, 'o' },
128 { "output-format", 1, 'O' },
129 { "pedantic", 0, 'W' },
130 { "po-dir", 1, 'P' },
131 { "version", 0, 'v' },
132 { NULL }
135 static void cleanup_files(void)
137 if (output_name) unlink( output_name );
138 if (header_name) unlink( header_name );
141 static void exit_on_signal( int sig )
143 exit(1); /* this will call the atexit functions */
146 static void init_argv0_dir( const char *argv0 )
148 char *dir = get_argv0_dir( argv0 );
150 if (!dir) return;
151 if (strendswith( dir, "/tools/wmc" )) nlsdirs[0] = strmake( "%s/../../nls", dir );
152 else nlsdirs[0] = strmake( "%s/%s", dir, BIN_TO_NLSDIR );
155 static void option_callback( int optc, char *optarg )
157 switch(optc)
159 case 'c':
160 custombit = 1;
161 break;
162 case 'd':
163 decimal = 1;
164 break;
165 case 'D':
166 dodebug = 1;
167 break;
168 case 'h':
169 printf("%s", usage);
170 exit(0);
171 /* No return */
172 case 'H':
173 header_name = xstrdup(optarg);
174 break;
175 case 'i':
176 rcinline = 1;
177 break;
178 case 'o':
179 output_name = xstrdup(optarg);
180 break;
181 case 'O':
182 if (!strcmp( optarg, "rc" )) output_format = FORMAT_RC;
183 else if (!strcmp( optarg, "res" )) output_format = FORMAT_RES;
184 else if (!strcmp( optarg, "pot" )) output_format = FORMAT_POT;
185 else error("Output format must be rc or res\n" );
186 break;
187 case 'P':
188 po_dir = xstrdup( optarg );
189 break;
190 case 'u':
191 unicodein = 1;
192 break;
193 case 'U': /* ignored for backwards compatibility */
194 break;
195 case 'v':
196 show_languages();
197 exit(0);
198 /* No return */
199 case 'V':
200 printf(version_string);
201 exit(0);
202 /* No return */
203 case 'W':
204 pedantic = 1;
205 break;
206 case LONG_OPT_NLS_DIR:
207 nlsdirs[0] = xstrdup( optarg );
208 break;
209 case '?':
210 fprintf(stderr, "wmc: %s\n\n%s", optarg, usage);
211 exit(1);
215 int main(int argc,char *argv[])
217 int ret;
218 int i;
219 int cmdlen;
220 struct strarray files;
222 atexit( cleanup_files );
223 init_signals( exit_on_signal );
224 init_argv0_dir( argv[0] );
226 /* First rebuild the commandline to put in destination */
227 /* Could be done through env[], but not all OS-es support it */
228 cmdlen = 5; /* for "wmc " and \0 */
229 for(i = 1; i < argc; i++)
230 cmdlen += strlen(argv[i]) + 1;
231 cmdline = xmalloc(cmdlen);
232 strcpy(cmdline, "wmc ");
233 for(i = 1; i < argc; i++)
235 strcat(cmdline, argv[i]);
236 if(i < argc-1)
237 strcat(cmdline, " ");
240 files = parse_options( argc, argv, short_options, long_options, 0, option_callback );
242 mcy_debug = dodebug;
243 if(dodebug)
245 setbuf(stdout, NULL);
246 setbuf(stderr, NULL);
249 /* Check for input file on command-line */
250 if (files.count) input_name = files.str[0];
252 /* Guess output format */
253 if (output_format == FORMAT_UNKNOWN)
255 if (output_name && strendswith( output_name, ".res" )) output_format = FORMAT_RES;
256 else if (output_name && strendswith( output_name, ".pot" )) output_format = FORMAT_POT;
257 else output_format = FORMAT_RC;
260 /* Generate appropriate outfile names */
261 if(!output_name)
263 const char *name = input_name ? get_basename(input_name) : "wmc.tab";
264 output_name = replace_extension( name, ".mc", ".rc" );
267 if(!header_name)
269 const char *name = input_name ? get_basename(input_name) : "wmc.tab";
270 header_name = replace_extension( name, ".mc", ".h" );
273 if(input_name)
275 if(!(yyin = fopen(input_name, "rb")))
276 error("Could not open %s for input\n", input_name);
278 else
279 yyin = stdin;
281 ret = mcy_parse();
283 if(input_name)
284 fclose(yyin);
286 if(ret)
288 /* Error during parse */
289 exit(1);
292 switch (output_format)
294 case FORMAT_RC:
295 write_h_file(header_name);
296 write_rc_file(output_name);
297 if(!rcinline)
298 write_bin_files();
299 break;
300 case FORMAT_RES:
301 add_translations( po_dir );
302 write_res_file( output_name );
303 break;
304 case FORMAT_POT:
305 write_pot_file( output_name );
306 break;
307 default:
308 break;
310 output_name = NULL;
311 header_name = NULL;
312 return 0;