Can we bundle everthing together?
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <signal.h>
27
28 #include "wmc.h"
29 #include "utils.h"
30 #include "lang.h"
31 #include "write.h"
32
33 static char usage[] =
34         "Usage: wmc [options...] [inputfile.mc]\n"
35         "   -B x        Set output byte-order x={n[ative], l[ittle], b[ig]}\n"
36         "               (default is n[ative] which equals "
37 #ifdef WORDS_BIGENDIAN
38         "big"
39 #else
40         "little"
41 #endif
42         "-endian)\n"
43         "   -c          Set 'custom-bit' in values\n"
44         "   -d          Use decimal values in output\n"
45         "   -D          Set debug flag\n"
46         "   -h          This message\n"
47         "   -H file     Write headerfile to file (default is inputfile.h)\n"
48         "   -i          Inline messagetable(s)\n"
49         "   -o file     Output to file (default is inputfile.rc)\n"
50         "   -u          Inputfile is in unicode\n"
51         "   -U          Output unicode messagetable(s)\n"
52         "   -v          Show supported codepages and languages\n"
53         "   -V          Print version end exit\n"
54         "   -W          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"
58         ;
59
60 static char version_string[] =
61         "Wine Message Compiler Version " WMC_FULLVERSION "\n"
62         "Copyright 2000 Bertho A. Stultiens\n"
63         ;
64
65 /*
66  * The output byte-order of resources (set with -B)
67  */
68 int byteorder = WMC_BO_NATIVE;
69
70 /*
71  * Custom bit (bit 29) in output values must be set (-c option)
72  */
73 int custombit = 0;
74
75 /*
76  * Output decimal values (-d option)
77  */
78 int decimal = 0;
79
80 /*
81  * Enable pedantic warnings; check arg references (-W option)
82  */
83 int pedantic = 0;
84
85 /*
86  * Unicode input (-u option)
87  */
88 int unicodein = 0;
89
90 /*
91  * Unicode output (-U option)
92  */
93 int unicodeout = 0;
94
95 /*
96  * Inline the messagetables (don't write *.bin files; -i option)
97  */
98 int rcinline = 0;
99
100 /*
101  * Debugging flag (-D option)
102  */
103 int dodebug = 0;
104
105 char *output_name = NULL;       /* The name given by the -o option */
106 char *input_name = NULL;        /* The name given on the command-line */
107 char *header_name = NULL;       /* The name given by the -H option */
108
109 int line_number = 1;            /* The current line */
110 int char_number = 1;            /* The current char pos within the line */
111
112 char *cmdline;                  /* The entire commandline */
113 time_t now;                     /* The time of start of wmc */
114
115 int getopt (int argc, char *const *argv, const char *optstring);
116 static void segvhandler(int sig);
117
118 int main(int argc,char *argv[])
119 {
120         extern char* optarg;
121         extern int   optind;
122         int optc;
123         int lose = 0;
124         int ret;
125         int i;
126         int cmdlen;
127
128         signal(SIGSEGV, segvhandler);
129
130         now = time(NULL);
131
132         /* First rebuild the commandline to put in destination */
133         /* Could be done through env[], but not all OS-es support it */
134         cmdlen = 4; /* for "wmc " */
135         for(i = 1; i < argc; i++)
136                 cmdlen += strlen(argv[i]) + 1;
137         cmdline = (char *)xmalloc(cmdlen);
138         strcpy(cmdline, "wmc ");
139         for(i = 1; i < argc; i++)
140         {
141                 strcat(cmdline, argv[i]);
142                 if(i < argc-1)
143                         strcat(cmdline, " ");
144         }
145
146         while((optc = getopt(argc, argv, "B:cdDhH:io:p:uUvVW")) != EOF)
147         {
148                 switch(optc)
149                 {
150                 case 'B':
151                         switch(optarg[0])
152                         {
153                         case 'n':
154                         case 'N':
155                                 byteorder = WMC_BO_NATIVE;
156                                 break;
157                         case 'l':
158                         case 'L':
159                                 byteorder = WMC_BO_LITTLE;
160                                 break;
161                         case 'b':
162                         case 'B':
163                                 byteorder = WMC_BO_BIG;
164                                 break;
165                         default:
166                                 fprintf(stderr, "Byteordering must be n[ative], l[ittle] or b[ig]\n");
167                                 lose++;
168                         }
169                         break;
170                 case 'c':
171                         custombit = 1;
172                         break;
173                 case 'd':
174                         decimal = 1;
175                         break;
176                 case 'D':
177                         dodebug = 1;
178                         break;
179                 case 'h':
180                         printf("%s", usage);
181                         exit(0);
182                         /* No return */
183                 case 'H':
184                         header_name = xstrdup(optarg);
185                         break;
186                 case 'i':
187                         rcinline = 1;
188                         break;
189                 case 'o':
190                         output_name = xstrdup(optarg);
191                         break;
192                 case 'u':
193                         unicodein = 1;
194                         break;
195                 case 'U':
196                         unicodeout = 1;
197                         break;
198                 case 'v':
199                         show_languages();
200                         show_codepages();
201                         exit(0);
202                         /* No return */
203                 case 'V':
204                         printf(version_string);
205                         exit(0);
206                         /* No return */
207                 case 'W':
208                         pedantic = 1;
209                         break;
210                 default:
211                         lose++;
212                         break;
213                 }
214         }
215
216         if(lose)
217         {
218                 fprintf(stderr, "%s", usage);
219                 return 1;
220         }
221
222         yydebug = dodebug;
223         if(dodebug)
224         {
225                 setbuf(stdout, 0);
226                 setbuf(stderr, 0);
227         }
228
229         /* Check for input file on command-line */
230         if(optind < argc)
231         {
232                 input_name = argv[optind];
233         }
234
235         /* Generate appropriate outfile names */
236         if(!output_name)
237         {
238                 output_name = dup_basename(input_name, ".mc");
239                 strcat(output_name, ".rc");
240         }
241
242         if(!header_name)
243         {
244                 header_name = dup_basename(input_name, ".mc");
245                 strcat(header_name, ".h");
246         }
247
248         if(input_name)
249         {
250                 if(!(yyin = fopen(input_name, "rb")))
251                         error("Could not open %s for input\n", input_name);
252         }
253         else
254                 yyin = stdin;
255
256         ret = yyparse();
257
258         if(input_name)
259                 fclose(yyin);
260
261         if(ret)
262         {
263                 /* Error during parse */
264                 exit(1);
265         }
266
267         write_h_file(header_name);
268         write_rc_file(output_name);
269         if(!rcinline)
270                 write_bin_files();
271
272         return 0;
273 }
274
275 static void segvhandler(int sig)
276 {
277         fprintf(stderr, "\n%s:%d: Oops, segment violation\n", input_name, line_number);
278         fflush(stdout);
279         fflush(stderr);
280         abort();
281 }
282