Removed trailing whitespace.
[wine] / tools / wrc / utils.c
1 /*
2  * Utility routines
3  *
4  * Copyright 1998 Bertho A. Stultiens
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 #include "wine/port.h"
23
24 #include <assert.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <ctype.h>
31
32 #include "wine/unicode.h"
33 #include "wrc.h"
34 #include "utils.h"
35 #include "parser.h"
36 #include "preproc.h"
37
38 /* #define WANT_NEAR_INDICATION */
39
40 static const union cptable *current_codepage;
41
42 #ifdef WANT_NEAR_INDICATION
43 void make_print(char *str)
44 {
45         while(*str)
46         {
47                 if(!isprint(*str))
48                         *str = ' ';
49                 str++;
50         }
51 }
52 #endif
53
54 static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
55 {
56         fprintf(stderr, "%s:%d:%d: %s: ", input_name ? input_name : "stdin", line_number, char_number, t);
57         vfprintf(stderr, s, ap);
58 #ifdef WANT_NEAR_INDICATION
59         {
60                 char *cpy;
61                 if(n)
62                 {
63                         cpy = xstrdup(n);
64                         make_print(cpy);
65                         fprintf(stderr, " near '%s'", cpy);
66                         free(cpy);
67                 }
68         }
69 #endif
70         fprintf(stderr, "\n");
71 }
72
73
74 int yyerror(const char *s, ...)
75 {
76         va_list ap;
77         va_start(ap, s);
78         generic_msg(s, "Error", yytext, ap);
79         va_end(ap);
80         exit(1);
81         return 1;
82 }
83
84 int yywarning(const char *s, ...)
85 {
86         va_list ap;
87         va_start(ap, s);
88         generic_msg(s, "Warning", yytext, ap);
89         va_end(ap);
90         return 0;
91 }
92
93 int pperror(const char *s, ...)
94 {
95         va_list ap;
96         va_start(ap, s);
97         generic_msg(s, "Error", pptext, ap);
98         va_end(ap);
99         exit(1);
100         return 1;
101 }
102
103 int ppwarning(const char *s, ...)
104 {
105         va_list ap;
106         va_start(ap, s);
107         generic_msg(s, "Warning", pptext, ap);
108         va_end(ap);
109         return 0;
110 }
111
112
113 void internal_error(const char *file, int line, const char *s, ...)
114 {
115         va_list ap;
116         va_start(ap, s);
117         fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
118         vfprintf(stderr, s, ap);
119         fprintf(stderr, "\n");
120         va_end(ap);
121         exit(3);
122 }
123
124 void error(const char *s, ...)
125 {
126         va_list ap;
127         va_start(ap, s);
128         fprintf(stderr, "Error: ");
129         vfprintf(stderr, s, ap);
130         fprintf(stderr, "\n");
131         va_end(ap);
132         exit(2);
133 }
134
135 void warning(const char *s, ...)
136 {
137         va_list ap;
138         va_start(ap, s);
139         fprintf(stderr, "Warning: ");
140         vfprintf(stderr, s, ap);
141         fprintf(stderr, "\n");
142         va_end(ap);
143 }
144
145 void chat(const char *s, ...)
146 {
147         if(debuglevel & DEBUGLEVEL_CHAT)
148         {
149                 va_list ap;
150                 va_start(ap, s);
151                 fprintf(stderr, "FYI: ");
152                 vfprintf(stderr, s, ap);
153                 fprintf(stderr, "\n");
154                 va_end(ap);
155         }
156 }
157
158 char *dup_basename(const char *name, const char *ext)
159 {
160         int namelen;
161         int extlen = strlen(ext);
162         char *base;
163         char *slash;
164
165         if(!name)
166                 name = "wrc.tab";
167
168         slash = strrchr(name, '/');
169         if (slash)
170                 name = slash + 1;
171
172         namelen = strlen(name);
173
174         /* +4 for later extension and +1 for '\0' */
175         base = (char *)xmalloc(namelen +4 +1);
176         strcpy(base, name);
177         if(!strcasecmp(name + namelen-extlen, ext))
178         {
179                 base[namelen - extlen] = '\0';
180         }
181         return base;
182 }
183
184 void *xmalloc(size_t size)
185 {
186     void *res;
187
188     assert(size > 0);
189     res = malloc(size);
190     if(res == NULL)
191     {
192         error("Virtual memory exhausted.\n");
193     }
194     /*
195      * We set it to 0.
196      * This is *paramount* because we depend on it
197      * just about everywhere in the rest of the code.
198      */
199     memset(res, 0, size);
200     return res;
201 }
202
203
204 void *xrealloc(void *p, size_t size)
205 {
206     void *res;
207
208     assert(size > 0);
209     res = realloc(p, size);
210     if(res == NULL)
211     {
212         error("Virtual memory exhausted.\n");
213     }
214     return res;
215 }
216
217 char *xstrdup(const char *str)
218 {
219         char *s;
220
221         assert(str != NULL);
222         s = (char *)xmalloc(strlen(str)+1);
223         return strcpy(s, str);
224 }
225
226 short *dupcstr2wstr(const char *str)
227 {
228         int len;
229         WCHAR *ws;
230
231         if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
232         len = cp_mbstowcs( current_codepage, 0, str, strlen(str), NULL, 0 );
233         ws = xmalloc( sizeof(WCHAR) * (len + 1) );
234         len = cp_mbstowcs( current_codepage, 0, str, strlen(str), ws, len );
235         ws[len] = 0;
236         return ws;
237 }
238
239 char *dupwstr2cstr(const short *str)
240 {
241         int len;
242         char *cs;
243
244         if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
245         len = cp_wcstombs( current_codepage, 0, str, strlenW(str), NULL, 0, NULL, NULL );
246         cs = xmalloc( len + 1 );
247         len = cp_wcstombs( current_codepage, 0, str, strlenW(str),  cs, len, NULL, NULL );
248         cs[len] = 0;
249         return cs;
250 }
251
252 /*
253  *****************************************************************************
254  * Function     : compare_name_id
255  * Syntax       : int compare_name_id(name_id_t *n1, name_id_t *n2)
256  * Input        :
257  * Output       :
258  * Description  :
259  * Remarks      :
260  *****************************************************************************
261 */
262 int compare_name_id(name_id_t *n1, name_id_t *n2)
263 {
264         if(n1->type == name_ord && n2->type == name_ord)
265         {
266                 return n1->name.i_name - n2->name.i_name;
267         }
268         else if(n1->type == name_str && n2->type == name_str)
269         {
270                 if(n1->name.s_name->type == str_char
271                 && n2->name.s_name->type == str_char)
272                 {
273                         return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
274                 }
275                 else if(n1->name.s_name->type == str_unicode
276                 && n2->name.s_name->type == str_unicode)
277                 {
278                         return strcmpiW(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
279                 }
280                 else
281                 {
282                         internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
283                 }
284         }
285         else if(n1->type == name_ord && n2->type == name_str)
286                 return 1;
287         else if(n1->type == name_str && n2->type == name_ord)
288                 return -1;
289         else
290                 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
291                                 n1->type, n2->type);
292
293         return 0; /* Keep the compiler happy */
294 }
295
296 string_t *convert_string(const string_t *str, enum str_e type)
297 {
298         string_t *ret = xmalloc(sizeof(*ret));
299
300         if((str->type == str_char) && (type == str_unicode))
301         {
302                 ret->str.wstr = dupcstr2wstr(str->str.cstr);
303                 ret->type     = str_unicode;
304                 ret->size     = strlenW(ret->str.wstr);
305         }
306         else if((str->type == str_unicode) && (type == str_char))
307         {
308                 ret->str.cstr = dupwstr2cstr(str->str.wstr);
309                 ret->type     = str_char;
310                 ret->size     = strlen(ret->str.cstr);
311         }
312         else if(str->type == str_unicode)
313         {
314                 ret->type     = str_unicode;
315                 ret->size     = strlenW(str->str.wstr);
316                 ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1));
317                 strcpyW(ret->str.wstr, str->str.wstr);
318         }
319         else /* str->type == str_char */
320         {
321                 ret->type     = str_char;
322                 ret->size     = strlen(str->str.cstr);
323                 ret->str.cstr = xmalloc( ret->size + 1 );
324                 strcpy(ret->str.cstr, str->str.cstr);
325         }
326         return ret;
327 }
328
329
330 struct lang2cp
331 {
332     unsigned short lang;
333     unsigned short sublang;
334     unsigned int   cp;
335 } lang2cp_t;
336
337 /* language to codepage conversion table */
338 /* specific sublanguages need only be specified if their codepage */
339 /* differs from the default (SUBLANG_NEUTRAL) */
340 static const struct lang2cp lang2cps[] =
341 {
342     { LANG_AFRIKAANS,      SUBLANG_NEUTRAL,              1252 },
343     { LANG_ALBANIAN,       SUBLANG_NEUTRAL,              1250 },
344     { LANG_ARABIC,         SUBLANG_NEUTRAL,              1256 },
345     { LANG_BASQUE,         SUBLANG_NEUTRAL,              1252 },
346     { LANG_BRETON,         SUBLANG_NEUTRAL,              1252 },
347     { LANG_BULGARIAN,      SUBLANG_NEUTRAL,              1251 },
348     { LANG_BYELORUSSIAN,   SUBLANG_NEUTRAL,              1251 },
349     { LANG_CATALAN,        SUBLANG_NEUTRAL,              1252 },
350     { LANG_CHINESE,        SUBLANG_NEUTRAL,              936  },
351     { LANG_CORNISH,        SUBLANG_NEUTRAL,              1252 },
352     { LANG_CZECH,          SUBLANG_NEUTRAL,              1250 },
353     { LANG_DANISH,         SUBLANG_NEUTRAL,              1252 },
354     { LANG_DUTCH,          SUBLANG_NEUTRAL,              1252 },
355     { LANG_ENGLISH,        SUBLANG_NEUTRAL,              1252 },
356     { LANG_ESPERANTO,      SUBLANG_NEUTRAL,              1252 },
357     { LANG_ESTONIAN,       SUBLANG_NEUTRAL,              1257 },
358     { LANG_FAEROESE,       SUBLANG_NEUTRAL,              1252 },
359     { LANG_FINNISH,        SUBLANG_NEUTRAL,              1252 },
360     { LANG_FRENCH,         SUBLANG_NEUTRAL,              1252 },
361     { LANG_GAELIC,         SUBLANG_NEUTRAL,              1252 },
362     { LANG_GERMAN,         SUBLANG_NEUTRAL,              1252 },
363     { LANG_GREEK,          SUBLANG_NEUTRAL,              1253 },
364     { LANG_HEBREW,         SUBLANG_NEUTRAL,              1255 },
365     { LANG_HUNGARIAN,      SUBLANG_NEUTRAL,              1250 },
366     { LANG_ICELANDIC,      SUBLANG_NEUTRAL,              1252 },
367     { LANG_INDONESIAN,     SUBLANG_NEUTRAL,              1252 },
368     { LANG_ITALIAN,        SUBLANG_NEUTRAL,              1252 },
369     { LANG_JAPANESE,       SUBLANG_NEUTRAL,              932  },
370     { LANG_KOREAN,         SUBLANG_NEUTRAL,              949  },
371     { LANG_LATVIAN,        SUBLANG_NEUTRAL,              1257 },
372     { LANG_LITHUANIAN,     SUBLANG_NEUTRAL,              1257 },
373     { LANG_MACEDONIAN,     SUBLANG_NEUTRAL,              1251 },
374     { LANG_MALAY,          SUBLANG_NEUTRAL,              1252 },
375     { LANG_NEUTRAL,        SUBLANG_NEUTRAL,              1252 },
376     { LANG_NORWEGIAN,      SUBLANG_NEUTRAL,              1252 },
377     { LANG_POLISH,         SUBLANG_NEUTRAL,              1250 },
378     { LANG_PORTUGUESE,     SUBLANG_NEUTRAL,              1252 },
379     { LANG_ROMANIAN,       SUBLANG_NEUTRAL,              1250 },
380     { LANG_RUSSIAN,        SUBLANG_NEUTRAL,              1251 },
381     { LANG_SERBO_CROATIAN, SUBLANG_NEUTRAL,              1250 },
382     { LANG_SERBO_CROATIAN, SUBLANG_SERBIAN,              1251 },
383     { LANG_SLOVAK,         SUBLANG_NEUTRAL,              1250 },
384     { LANG_SLOVENIAN,      SUBLANG_NEUTRAL,              1250 },
385     { LANG_SPANISH,        SUBLANG_NEUTRAL,              1252 },
386     { LANG_SWEDISH,        SUBLANG_NEUTRAL,              1252 },
387     { LANG_THAI,           SUBLANG_NEUTRAL,              874  },
388     { LANG_TURKISH,        SUBLANG_NEUTRAL,              1254 },
389     { LANG_UKRAINIAN,      SUBLANG_NEUTRAL,              1251 },
390     { LANG_VIETNAMESE,     SUBLANG_NEUTRAL,              1258 },
391     { LANG_WALON,          SUBLANG_NEUTRAL,              1252 },
392     { LANG_WELSH,          SUBLANG_NEUTRAL,              1252 }
393 };
394
395 void set_language( unsigned short lang, unsigned short sublang )
396 {
397     unsigned int i;
398     unsigned int cp = 0, defcp = 0;
399
400     for (i = 0; i < sizeof(lang2cps)/sizeof(lang2cps[0]); i++)
401     {
402         if (lang2cps[i].lang != lang) continue;
403         if (lang2cps[i].sublang == sublang)
404         {
405             cp = lang2cps[i].cp;
406             break;
407         }
408         if (lang2cps[i].sublang == SUBLANG_NEUTRAL) defcp = lang2cps[i].cp;
409     }
410
411     if (!cp) cp = defcp;
412     if (!cp)
413         error( "No codepage value for language %04x", MAKELANGID(lang,sublang) );
414     if (!(current_codepage = cp_get_table( cp )))
415         error( "Bad codepage %d for language %04x", cp, MAKELANGID(lang,sublang) );
416 }