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