Update the address of the Free Software Foundation.
[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 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 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 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 getopt (int argc, char *const *argv, const char *optstring);
117 static void segvhandler(int sig);
118
119 int main(int argc,char *argv[])
120 {
121         extern char* optarg;
122         extern int   optind;
123         int optc;
124         int lose = 0;
125         int ret;
126         int i;
127         int cmdlen;
128
129         signal(SIGSEGV, segvhandler);
130
131         now = time(NULL);
132
133         /* First rebuild the commandline to put in destination */
134         /* Could be done through env[], but not all OS-es support it */
135         cmdlen = 4; /* for "wmc " */
136         for(i = 1; i < argc; i++)
137                 cmdlen += strlen(argv[i]) + 1;
138         cmdline = (char *)xmalloc(cmdlen);
139         strcpy(cmdline, "wmc ");
140         for(i = 1; i < argc; i++)
141         {
142                 strcat(cmdline, argv[i]);
143                 if(i < argc-1)
144                         strcat(cmdline, " ");
145         }
146
147         while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF)
148         {
149                 switch(optc)
150                 {
151                 case 'B':
152                         switch(optarg[0])
153                         {
154                         case 'n':
155                         case 'N':
156                                 byteorder = WMC_BO_NATIVE;
157                                 break;
158                         case 'l':
159                         case 'L':
160                                 byteorder = WMC_BO_LITTLE;
161                                 break;
162                         case 'b':
163                         case 'B':
164                                 byteorder = WMC_BO_BIG;
165                                 break;
166                         default:
167                                 fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
168                                 lose++;
169                         }
170                         break;
171                 case 'c':
172                         custombit = 1;
173                         break;
174                 case 'd':
175                         decimal = 1;
176                         break;
177                 case 'D':
178                         dodebug = 1;
179                         break;
180                 case 'h':
181                         printf("%s", usage);
182                         exit(0);
183                         /* No return */
184                 case 'H':
185                         header_name = xstrdup(optarg);
186                         break;
187                 case 'i':
188                         rcinline = 1;
189                         break;
190                 case 'o':
191                         output_name = xstrdup(optarg);
192                         break;
193                 case 'u':
194                         unicodein = 1;
195                         break;
196                 case 'U':
197                         unicodeout = 1;
198                         break;
199                 case 'v':
200                         show_languages();
201                         show_codepages();
202                         exit(0);
203                         /* No return */
204                 case 'V':
205                         printf(version_string);
206                         exit(0);
207                         /* No return */
208                 case 'W':
209                         pedantic = 1;
210                         break;
211                 default:
212                         lose++;
213                         break;
214                 }
215         }
216
217         if(lose)
218         {
219                 fprintf(stderr, "%s", usage);
220                 return 1;
221         }
222
223         yydebug = dodebug;
224         if(dodebug)
225         {
226                 setbuf(stdout, 0);
227                 setbuf(stderr, 0);
228         }
229
230         /* Check for input file on command-line */
231         if(optind < argc)
232         {
233                 input_name = argv[optind];
234         }
235
236         /* Generate appropriate outfile names */
237         if(!output_name)
238         {
239                 output_name = dup_basename(input_name, ".mc");
240                 strcat(output_name, ".rc");
241         }
242
243         if(!header_name)
244         {
245                 header_name = dup_basename(input_name, ".mc");
246                 strcat(header_name, ".h");
247         }
248
249         if(input_name)
250         {
251                 if(!(yyin = fopen(input_name, "rb")))
252                         error("Could not open %s for input\n", input_name);
253         }
254         else
255                 yyin = stdin;
256
257         ret = yyparse();
258
259         if(input_name)
260                 fclose(yyin);
261
262         if(ret)
263         {
264                 /* Error during parse */
265                 exit(1);
266         }
267
268         write_h_file(header_name);
269         write_rc_file(output_name);
270         if(!rcinline)
271                 write_bin_files();
272
273         return 0;
274 }
275
276 static void segvhandler(int sig)
277 {
278         fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
279         fflush(stdout);
280         fflush(stderr);
281         abort();
282 }