source: trunk/tools/wrc/utils.c

Last change on this file was 21945, checked in by dmik, 14 years ago

Work around broken tempnam().

See #63 for details. This is a regression of r21929.

File size: 14.6 KB
Line 
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
25/*
26 * Ease debugging on OS/2.
27 */
28#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
29#undef malloc
30#define malloc(a) _debug_malloc(a, pszFile, iLine)
31#undef realloc
32#define realloc(a,b) _debug_realloc(a, b, pszFile, iLine)
33#endif
34
35
36/* #define WANT_NEAR_INDICATION */
37
38static const union cptable *current_codepage;
39
40#ifdef WANT_NEAR_INDICATION
41void make_print(char *str)
42{
43 while(*str)
44 {
45 if(!isprint(*str))
46 *str = ' ';
47 str++;
48 }
49}
50#endif
51
52static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
53{
54 fprintf(stderr, "%s:%d:%d: %s: ", input_name ? input_name : "stdin", line_number, char_number, t);
55 vfprintf(stderr, s, ap);
56#ifdef WANT_NEAR_INDICATION
57 {
58 char *cpy;
59 if(n)
60 {
61 cpy = xstrdup(n);
62 make_print(cpy);
63 fprintf(stderr, " near '%s'", cpy);
64 free(cpy);
65 }
66 }
67#endif
68 fprintf(stderr, "\n");
69}
70
71
72int yyerror(const char *s, ...)
73{
74 va_list ap;
75 va_start(ap, s);
76 generic_msg(s, "Error", yytext, ap);
77 va_end(ap);
78 exit(1);
79 return 1;
80}
81
82int yywarning(const char *s, ...)
83{
84 va_list ap;
85 va_start(ap, s);
86 generic_msg(s, "Warning", yytext, ap);
87 va_end(ap);
88 return 0;
89}
90
91int pperror(const char *s, ...)
92{
93 va_list ap;
94 va_start(ap, s);
95 generic_msg(s, "Error", pptext, ap);
96 va_end(ap);
97 exit(1);
98 return 1;
99}
100
101int ppwarning(const char *s, ...)
102{
103 va_list ap;
104 va_start(ap, s);
105 generic_msg(s, "Warning", pptext, ap);
106 va_end(ap);
107 return 0;
108}
109
110
111void internal_error(const char *file, int line, const char *s, ...)
112{
113 va_list ap;
114 va_start(ap, s);
115 fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
116 vfprintf(stderr, s, ap);
117 fprintf(stderr, "\n");
118 va_end(ap);
119 exit(3);
120}
121
122void error(const char *s, ...)
123{
124 va_list ap;
125 va_start(ap, s);
126 fprintf(stderr, "Error: ");
127 vfprintf(stderr, s, ap);
128 fprintf(stderr, "\n");
129 va_end(ap);
130 exit(2);
131}
132
133void warning(const char *s, ...)
134{
135 va_list ap;
136 va_start(ap, s);
137 fprintf(stderr, "Warning: ");
138 vfprintf(stderr, s, ap);
139 fprintf(stderr, "\n");
140 va_end(ap);
141}
142
143void chat(const char *s, ...)
144{
145 if(debuglevel & DEBUGLEVEL_CHAT)
146 {
147 va_list ap;
148 va_start(ap, s);
149 fprintf(stderr, "FYI: ");
150 vfprintf(stderr, s, ap);
151 fprintf(stderr, "\n");
152 va_end(ap);
153 }
154}
155
156char *dup_basename(const char *name, const char *ext)
157{
158 int namelen;
159 int extlen = strlen(ext);
160 char *base;
161 char *slash;
162
163 if(!name)
164 name = "wrc.tab";
165
166 slash = strrchr(name, '/');
167 if (slash)
168 name = slash + 1;
169
170 namelen = strlen(name);
171
172 /* +4 for later extension and +1 for '\0' */
173 base = (char *)xmalloc(namelen +4 +1);
174 strcpy(base, name);
175 if(!strcasecmp(name + namelen-extlen, ext))
176 {
177 base[namelen - extlen] = '\0';
178 }
179 return base;
180}
181
182#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
183void *_xmalloc(size_t size, char *pszFile, int iLine)
184#else
185void *xmalloc(size_t size)
186#endif
187{
188 void *res;
189
190 assert(size > 0);
191 res = malloc(size);
192 if(res == NULL)
193 {
194 error("Virtual memory exhausted.\n");
195 }
196 /*
197 * We set it to 0.
198 * This is *paramount* because we depend on it
199 * just about everywhere in the rest of the code.
200 */
201 memset(res, 0, size);
202 return res;
203}
204
205
206
207#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
208void *_xrealloc(void *p, size_t size, char *pszFile, int iLine)
209#else
210void *xrealloc(void *p, size_t size)
211#endif
212{
213 void *res;
214
215 assert(size > 0);
216 res = realloc(p, size);
217 if(res == NULL)
218 {
219 error("Virtual memory exhausted.\n");
220 }
221 return res;
222}
223
224#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
225char *_xstrdup(const char *str, char *pszFile, int iLine)
226#else
227char *xstrdup(const char *str)
228#endif
229{
230 char *s;
231
232 assert(str != NULL);
233 #if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
234 s = (char *)_xmalloc(strlen(str)+1, pszFile, iLine);
235 #else
236 s = (char *)xmalloc(strlen(str)+1);
237 #endif
238 return strcpy(s, str);
239}
240
241char *xtempnam(const char *dir, const char *prefix)
242{
243#ifdef __EMX__
244 // fullpath() called internally by tempnam() is broken and changes CWD (see
245 // http://svn.netlabs.org/odin32/ticket/63 for details). Preserve it.
246 int drv = _getdrive();
247#endif
248 char *res = tempnam(dir, prefix);
249#ifdef __EMX__
250 _chdrive(drv);
251#endif
252 if (!res)
253 {
254 fprintf (stderr, "Virtual memory exhausted.\n");
255 exit (1);
256 }
257 return res;
258}
259
260short *dupcstr2wstr(const char *str)
261{
262 int len;
263 WCHAR *ws;
264
265 if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
266 len = cp_mbstowcs( current_codepage, 0, str, strlen(str), NULL, 0 );
267 ws = xmalloc( sizeof(WCHAR) * (len + 1) );
268 len = cp_mbstowcs( current_codepage, 0, str, strlen(str), ws, len );
269 ws[len] = 0;
270 return ws;
271}
272
273char *dupwstr2cstr(const short *str)
274{
275 int len;
276 char *cs;
277
278 if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
279 len = cp_wcstombs( current_codepage, 0, str, strlenW(str), NULL, 0, NULL, NULL );
280 cs = xmalloc( len + 1 );
281 len = cp_wcstombs( current_codepage, 0, str, strlenW(str), cs, len, NULL, NULL );
282 cs[len] = 0;
283 return cs;
284}
285
286/*
287 *****************************************************************************
288 * Function : compare_name_id
289 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
290 * Input :
291 * Output :
292 * Description :
293 * Remarks :
294 *****************************************************************************
295*/
296int compare_name_id(name_id_t *n1, name_id_t *n2)
297{
298 if(n1->type == name_ord && n2->type == name_ord)
299 {
300 return n1->name.i_name - n2->name.i_name;
301 }
302 else if(n1->type == name_str && n2->type == name_str)
303 {
304 if(n1->name.s_name->type == str_char
305 && n2->name.s_name->type == str_char)
306 {
307 return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
308 }
309 else if(n1->name.s_name->type == str_unicode
310 && n2->name.s_name->type == str_unicode)
311 {
312 return strcmpiW(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
313 }
314 else
315 {
316 internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
317 }
318 }
319 else if(n1->type == name_ord && n2->type == name_str)
320 return 1;
321 else if(n1->type == name_str && n2->type == name_ord)
322 return -1;
323 else
324 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
325 n1->type, n2->type);
326
327 return 0; /* Keep the compiler happy */
328}
329
330string_t *convert_string(const string_t *str, enum str_e type)
331{
332 string_t *ret = xmalloc(sizeof(*ret));
333
334 if((str->type == str_char) && (type == str_unicode))
335 {
336 ret->str.wstr = dupcstr2wstr(str->str.cstr);
337 ret->type = str_unicode;
338 ret->size = strlenW(ret->str.wstr);
339 }
340 else if((str->type == str_unicode) && (type == str_char))
341 {
342 ret->str.cstr = dupwstr2cstr(str->str.wstr);
343 ret->type = str_char;
344 ret->size = strlen(ret->str.cstr);
345 }
346 else if(str->type == str_unicode)
347 {
348 ret->type = str_unicode;
349 ret->size = strlenW(str->str.wstr);
350 ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1));
351 strcpyW(ret->str.wstr, str->str.wstr);
352 }
353 else /* str->type == str_char */
354 {
355 ret->type = str_char;
356 ret->size = strlen(str->str.cstr);
357 ret->str.cstr = xmalloc( ret->size + 1 );
358 strcpy(ret->str.cstr, str->str.cstr);
359 }
360 return ret;
361}
362
363
364struct lang2cp
365{
366 unsigned short lang;
367 unsigned short sublang;
368 unsigned int cp;
369} lang2cp_t;
370
371/* language to codepage conversion table */
372/* specific sublanguages need only be specified if their codepage */
373/* differs from the default (SUBLANG_NEUTRAL) */
374static const struct lang2cp lang2cps[] =
375{
376 { LANG_AFRIKAANS, SUBLANG_NEUTRAL, 1252 },
377 { LANG_ALBANIAN, SUBLANG_NEUTRAL, 1250 },
378 { LANG_ARABIC, SUBLANG_NEUTRAL, 1256 },
379 { LANG_ARMENIAN, SUBLANG_NEUTRAL, 0 },
380 { LANG_AZERI, SUBLANG_NEUTRAL, 1254 },
381 { LANG_AZERI, SUBLANG_AZERI_CYRILLIC, 1251 },
382 { LANG_BASQUE, SUBLANG_NEUTRAL, 1252 },
383 { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 },
384#ifdef LANG_BRETON
385 { LANG_BRETON, SUBLANG_NEUTRAL, 1252 },
386#endif /* LANG_BRETON */
387 { LANG_BULGARIAN, SUBLANG_NEUTRAL, 1251 },
388 { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 }, /* ?? */
389 { LANG_CATALAN, SUBLANG_NEUTRAL, 1252 },
390 { LANG_CHINESE, SUBLANG_NEUTRAL, 936 },
391 { LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE, 936 },
392 { LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED, 936 },
393#ifdef LANG_CORNISH
394 { LANG_CORNISH, SUBLANG_NEUTRAL, 1252 },
395#endif /* LANG_CORNISH */
396 { LANG_CROATIAN, SUBLANG_NEUTRAL, 1250 },
397 { LANG_CZECH, SUBLANG_NEUTRAL, 1250 },
398 { LANG_DANISH, SUBLANG_NEUTRAL, 1252 },
399 { LANG_DIVEHI, SUBLANG_NEUTRAL, 0 },
400 { LANG_DUTCH, SUBLANG_NEUTRAL, 1252 },
401 { LANG_ENGLISH, SUBLANG_NEUTRAL, 1252 },
402#ifdef LANG_ESPERANTO
403 { LANG_ESPERANTO, SUBLANG_NEUTRAL, 1252 },
404#endif /* LANG_ESPERANTO */
405 { LANG_ESTONIAN, SUBLANG_NEUTRAL, 1257 },
406 { LANG_FAEROESE, SUBLANG_NEUTRAL, 1252 },
407 { LANG_FARSI, SUBLANG_NEUTRAL, 1256 },
408 { LANG_FINNISH, SUBLANG_NEUTRAL, 1252 },
409 { LANG_FRENCH, SUBLANG_NEUTRAL, 1252 },
410#ifdef LANG_GAELIC
411 { LANG_GAELIC, SUBLANG_NEUTRAL, 1252 },
412#endif /* LANG_GAELIC */
413 { LANG_GALICIAN, SUBLANG_NEUTRAL, 1252 },
414 { LANG_GEORGIAN, SUBLANG_NEUTRAL, 0 },
415 { LANG_GERMAN, SUBLANG_NEUTRAL, 1252 },
416 { LANG_GREEK, SUBLANG_NEUTRAL, 1253 },
417 { LANG_GUJARATI, SUBLANG_NEUTRAL, 0 },
418 { LANG_HEBREW, SUBLANG_NEUTRAL, 1255 },
419 { LANG_HINDI, SUBLANG_NEUTRAL, 0 },
420 { LANG_HUNGARIAN, SUBLANG_NEUTRAL, 1250 },
421 { LANG_ICELANDIC, SUBLANG_NEUTRAL, 1252 },
422 { LANG_INDONESIAN, SUBLANG_NEUTRAL, 1252 },
423 { LANG_ITALIAN, SUBLANG_NEUTRAL, 1252 },
424 { LANG_JAPANESE, SUBLANG_NEUTRAL, 932 },
425 { LANG_KANNADA, SUBLANG_NEUTRAL, 0 },
426 { LANG_KAZAK, SUBLANG_NEUTRAL, 1251 },
427 { LANG_KONKANI, SUBLANG_NEUTRAL, 0 },
428 { LANG_KOREAN, SUBLANG_NEUTRAL, 949 },
429 { LANG_KYRGYZ, SUBLANG_NEUTRAL, 1251 },
430 { LANG_LATVIAN, SUBLANG_NEUTRAL, 1257 },
431 { LANG_LITHUANIAN, SUBLANG_NEUTRAL, 1257 },
432 { LANG_MACEDONIAN, SUBLANG_NEUTRAL, 1251 },
433 { LANG_MALAY, SUBLANG_NEUTRAL, 1252 },
434 { LANG_MARATHI, SUBLANG_NEUTRAL, 0 },
435 { LANG_MONGOLIAN, SUBLANG_NEUTRAL, 1251 },
436 { LANG_NEUTRAL, SUBLANG_NEUTRAL, 1252 },
437 { LANG_NORWEGIAN, SUBLANG_NEUTRAL, 1252 },
438 { LANG_POLISH, SUBLANG_NEUTRAL, 1250 },
439 { LANG_PORTUGUESE, SUBLANG_NEUTRAL, 1252 },
440 { LANG_PUNJABI, SUBLANG_NEUTRAL, 0 },
441 { LANG_ROMANIAN, SUBLANG_NEUTRAL, 1250 },
442 { LANG_RUSSIAN, SUBLANG_NEUTRAL, 1251 },
443 { LANG_SANSKRIT, SUBLANG_NEUTRAL, 0 },
444 { LANG_SERBIAN, SUBLANG_NEUTRAL, 1250 },
445 { LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC, 1251 },
446 { LANG_SLOVAK, SUBLANG_NEUTRAL, 1250 },
447 { LANG_SLOVENIAN, SUBLANG_NEUTRAL, 1250 },
448 { LANG_SPANISH, SUBLANG_NEUTRAL, 1252 },
449 { LANG_SWAHILI, SUBLANG_NEUTRAL, 1252 },
450 { LANG_SWEDISH, SUBLANG_NEUTRAL, 1252 },
451 { LANG_SYRIAC, SUBLANG_NEUTRAL, 0 },
452 { LANG_TAMIL, SUBLANG_NEUTRAL, 0 },
453 { LANG_TATAR, SUBLANG_NEUTRAL, 1251 },
454 { LANG_TELUGU, SUBLANG_NEUTRAL, 0 },
455 { LANG_THAI, SUBLANG_NEUTRAL, 874 },
456 { LANG_TURKISH, SUBLANG_NEUTRAL, 1254 },
457 { LANG_UKRAINIAN, SUBLANG_NEUTRAL, 1251 },
458 { LANG_URDU, SUBLANG_NEUTRAL, 1256 },
459 { LANG_UZBEK, SUBLANG_NEUTRAL, 1254 },
460 { LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC, 1251 },
461 { LANG_VIETNAMESE, SUBLANG_NEUTRAL, 1258 }
462#ifdef LANG_WALON
463 , { LANG_WALON, SUBLANG_NEUTRAL, 1252 }
464#endif /* LANG_WALON */
465#ifdef LANG_WELSH
466 , { LANG_WELSH, SUBLANG_NEUTRAL, 1252 }
467#endif /* LANG_WELSH */
468};
469
470void set_language( unsigned short lang, unsigned short sublang )
471{
472 unsigned int i;
473 unsigned int cp = 0, defcp = 0;
474
475 for (i = 0; i < sizeof(lang2cps)/sizeof(lang2cps[0]); i++)
476 {
477 if (lang2cps[i].lang != lang) continue;
478 if (lang2cps[i].sublang == sublang)
479 {
480 cp = lang2cps[i].cp;
481 break;
482 }
483 if (lang2cps[i].sublang == SUBLANG_NEUTRAL) defcp = lang2cps[i].cp;
484 }
485
486 if (!cp) cp = defcp;
487 if (!cp)
488 error( "No codepage value for language %04x", MAKELANGID(lang,sublang) );
489 if (!(current_codepage = cp_get_table( cp )))
490 error( "Bad codepage %d for language %04x", cp, MAKELANGID(lang,sublang) );
491}
492
493#if defined(__WIN32OS2__)
494INT WINAPI strcasecmp( LPCSTR p1, LPCSTR p2 )
495{
496 return stricmp( p1, p2 );
497}
498#if defined(__IBMC__)
499INT WINAPI lstrcmpiA(LPCSTR p1, LPCSTR p2)
500{
501 return stricmp( p1, p2 );
502}
503
504#endif
505#endif
Note: See TracBrowser for help on using the repository browser.