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