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