Added a few missing languages.
[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     assert(size < 102400);
176     res = malloc(size);
177     if(res == NULL)
178     {
179         error("Virtual memory exhausted.\n");
180     }
181     /*
182      * We set it to 0.
183      * This is *paramount* because we depend on it
184      * just about everywhere in the rest of the code.
185      */
186     memset(res, 0, size);
187     return res;
188 }
189
190
191 void *xrealloc(void *p, size_t size)
192 {
193     void *res;
194
195     assert(size > 0);
196     assert(size < 102400);
197     res = realloc(p, size);
198     if(res == NULL)
199     {
200         error("Virtual memory exhausted.\n");
201     }
202     return res;
203 }
204
205 char *xstrdup(const char *str)
206 {
207         char *s;
208
209         assert(str != NULL);
210         s = (char *)xmalloc(strlen(str)+1);
211         return strcpy(s, str);
212 }
213
214 short *dupcstr2wstr(const char *str)
215 {
216         int len;
217         WCHAR *ws;
218
219         if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
220         len = cp_mbstowcs( current_codepage, 0, str, strlen(str), NULL, 0 );
221         ws = xmalloc( sizeof(WCHAR) * (len + 1) );
222         len = cp_mbstowcs( current_codepage, 0, str, strlen(str), ws, len );
223         ws[len] = 0;
224         return ws;
225 }
226
227 char *dupwstr2cstr(const short *str)
228 {
229         int len;
230         char *cs;
231
232         if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
233         len = cp_wcstombs( current_codepage, 0, str, strlenW(str), NULL, 0, NULL, NULL );
234         cs = xmalloc( len + 1 );
235         len = cp_wcstombs( current_codepage, 0, str, strlenW(str),  cs, len, NULL, NULL );
236         cs[len] = 0;
237         return cs;
238 }
239
240 /*
241  *****************************************************************************
242  * Function     : compare_name_id
243  * Syntax       : int compare_name_id(name_id_t *n1, name_id_t *n2)
244  * Input        :
245  * Output       :
246  * Description  :
247  * Remarks      :
248  *****************************************************************************
249 */
250 int compare_name_id(name_id_t *n1, name_id_t *n2)
251 {
252         if(n1->type == name_ord && n2->type == name_ord)
253         {
254                 return n1->name.i_name - n2->name.i_name;
255         }
256         else if(n1->type == name_str && n2->type == name_str)
257         {
258                 if(n1->name.s_name->type == str_char
259                 && n2->name.s_name->type == str_char)
260                 {
261                         return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
262                 }
263                 else if(n1->name.s_name->type == str_unicode
264                 && n2->name.s_name->type == str_unicode)
265                 {
266                         return strcmpiW(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
267                 }
268                 else
269                 {
270                         internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
271                 }
272         }
273         else if(n1->type == name_ord && n2->type == name_str)
274                 return 1;
275         else if(n1->type == name_str && n2->type == name_ord)
276                 return -1;
277         else
278                 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
279                                 n1->type, n2->type);
280
281         return 0; /* Keep the compiler happy */
282 }
283
284 string_t *convert_string(const string_t *str, enum str_e type)
285 {
286         string_t *ret = xmalloc(sizeof(*ret));
287
288         if((str->type == str_char) && (type == str_unicode))
289         {
290                 ret->str.wstr = dupcstr2wstr(str->str.cstr);
291                 ret->type     = str_unicode;
292                 ret->size     = strlenW(ret->str.wstr);
293         }
294         else if((str->type == str_unicode) && (type == str_char))
295         {
296                 ret->str.cstr = dupwstr2cstr(str->str.wstr);
297                 ret->type     = str_char;
298                 ret->size     = strlen(ret->str.cstr);
299         }
300         else if(str->type == str_unicode)
301         {
302                 ret->type     = str_unicode;
303                 ret->size     = strlenW(str->str.wstr);
304                 ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1));
305                 strcpyW(ret->str.wstr, str->str.wstr);
306         }  
307         else /* str->type == str_char */
308         {
309                 ret->type     = str_char;
310                 ret->size     = strlen(str->str.cstr);
311                 ret->str.cstr = xmalloc( ret->size + 1 );
312                 strcpy(ret->str.cstr, str->str.cstr);
313         }
314         return ret;
315 }
316
317
318 struct lang2cp
319 {
320     unsigned short lang;
321     unsigned short sublang;
322     unsigned int   cp;
323 } lang2cp_t;
324
325 /* language to codepage conversion table */
326 /* specific sublanguages need only be specified if their codepage */
327 /* differs from the default (SUBLANG_NEUTRAL) */
328 static const struct lang2cp lang2cps[] =
329 {
330     { LANG_AFRIKAANS,      SUBLANG_NEUTRAL,              1252 },
331     { LANG_ALBANIAN,       SUBLANG_NEUTRAL,              1250 },
332     { LANG_ARABIC,         SUBLANG_NEUTRAL,              1256 },
333     { LANG_BASQUE,         SUBLANG_NEUTRAL,              1252 },
334     { LANG_BRETON,         SUBLANG_NEUTRAL,              1252 },
335     { LANG_BULGARIAN,      SUBLANG_NEUTRAL,              1251 },
336     { LANG_BYELORUSSIAN,   SUBLANG_NEUTRAL,              1251 },
337     { LANG_CATALAN,        SUBLANG_NEUTRAL,              1252 },
338     { LANG_CHINESE,        SUBLANG_NEUTRAL,              936  },
339     { LANG_CORNISH,        SUBLANG_NEUTRAL,              1252 },
340     { LANG_CZECH,          SUBLANG_NEUTRAL,              1250 },
341     { LANG_DANISH,         SUBLANG_NEUTRAL,              1252 },
342     { LANG_DUTCH,          SUBLANG_NEUTRAL,              1252 },
343     { LANG_ENGLISH,        SUBLANG_NEUTRAL,              1252 },
344     { LANG_ESPERANTO,      SUBLANG_NEUTRAL,              1252 },
345     { LANG_ESTONIAN,       SUBLANG_NEUTRAL,              1257 },
346     { LANG_FAEROESE,       SUBLANG_NEUTRAL,              1252 },
347     { LANG_FINNISH,        SUBLANG_NEUTRAL,              1252 },
348     { LANG_FRENCH,         SUBLANG_NEUTRAL,              1252 },
349     { LANG_GAELIC,         SUBLANG_NEUTRAL,              1252 },
350     { LANG_GERMAN,         SUBLANG_NEUTRAL,              1252 },
351     { LANG_GREEK,          SUBLANG_NEUTRAL,              1253 },
352     { LANG_HUNGARIAN,      SUBLANG_NEUTRAL,              1250 },
353     { LANG_ICELANDIC,      SUBLANG_NEUTRAL,              1252 },
354     { LANG_INDONESIAN,     SUBLANG_NEUTRAL,              1252 },
355     { LANG_ITALIAN,        SUBLANG_NEUTRAL,              1252 },
356     { LANG_JAPANESE,       SUBLANG_NEUTRAL,              932  },
357     { LANG_KOREAN,         SUBLANG_NEUTRAL,              949  },
358     { LANG_LATVIAN,        SUBLANG_NEUTRAL,              1257 },
359     { LANG_LITHUANIAN,     SUBLANG_NEUTRAL,              1257 },
360     { LANG_MACEDONIAN,     SUBLANG_NEUTRAL,              1251 },
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_LATIN,        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 }