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