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
RevLine 
[882]1/*
2 * Utility routines
3 *
4 * Copyright 1998 Bertho A. Stultiens
5 *
6 */
7
8#include "config.h"
9
[5523]10#include <assert.h>
[882]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
[5523]18#include "wine/unicode.h"
[882]19#include "wrc.h"
20#include "utils.h"
21#include "parser.h"
[5523]22#include "preproc.h"
[882]23
[6112]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
[5523]36/* #define WANT_NEAR_INDICATION */
[882]37
[5523]38static const union cptable *current_codepage;
[882]39
40#ifdef WANT_NEAR_INDICATION
41void make_print(char *str)
42{
[6112]43 while(*str)
44 {
45 if(!isprint(*str))
46 *str = ' ';
47 str++;
48 }
[882]49}
50#endif
51
[5523]52static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
[882]53{
[6112]54 fprintf(stderr, "%s:%d:%d: %s: ", input_name ? input_name : "stdin", line_number, char_number, t);
55 vfprintf(stderr, s, ap);
[882]56#ifdef WANT_NEAR_INDICATION
[6112]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 }
[5523]67#endif
[6112]68 fprintf(stderr, "\n");
[5523]69}
70
71
72int yyerror(const char *s, ...)
73{
[6112]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;
[882]80}
81
82int yywarning(const char *s, ...)
83{
[6112]84 va_list ap;
85 va_start(ap, s);
86 generic_msg(s, "Warning", yytext, ap);
87 va_end(ap);
88 return 0;
[882]89}
90
[5523]91int pperror(const char *s, ...)
92{
[6112]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;
[5523]99}
100
101int ppwarning(const char *s, ...)
102{
[6112]103 va_list ap;
104 va_start(ap, s);
105 generic_msg(s, "Warning", pptext, ap);
106 va_end(ap);
107 return 0;
[5523]108}
109
110
[882]111void internal_error(const char *file, int line, const char *s, ...)
112{
[6112]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);
[882]120}
121
122void error(const char *s, ...)
123{
[6112]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);
[882]131}
132
133void warning(const char *s, ...)
134{
[6112]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);
[882]141}
142
143void chat(const char *s, ...)
144{
[6112]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 }
[882]154}
155
156char *dup_basename(const char *name, const char *ext)
157{
[6112]158 int namelen;
159 int extlen = strlen(ext);
160 char *base;
161 char *slash;
[882]162
[6112]163 if(!name)
164 name = "wrc.tab";
[882]165
[6112]166 slash = strrchr(name, '/');
167 if (slash)
168 name = slash + 1;
[882]169
[6112]170 namelen = strlen(name);
[882]171
[6112]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;
[882]180}
181
[6112]182#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
183void *_xmalloc(size_t size, char *pszFile, int iLine)
184#else
[882]185void *xmalloc(size_t size)
[6112]186#endif
[882]187{
188 void *res;
189
190 assert(size > 0);
191 res = malloc(size);
192 if(res == NULL)
193 {
[6112]194 error("Virtual memory exhausted.\n");
[882]195 }
[5523]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 */
[882]201 memset(res, 0, size);
202 return res;
203}
204
205
[6112]206
207#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
208void *_xrealloc(void *p, size_t size, char *pszFile, int iLine)
209#else
[882]210void *xrealloc(void *p, size_t size)
[6112]211#endif
[882]212{
213 void *res;
214
215 assert(size > 0);
216 res = realloc(p, size);
217 if(res == NULL)
218 {
[6112]219 error("Virtual memory exhausted.\n");
[882]220 }
221 return res;
222}
223
[6112]224#if defined(__DEBUG_ALLOC__) && defined(__IBMC__)
225char *_xstrdup(const char *str, char *pszFile, int iLine)
226#else
[882]227char *xstrdup(const char *str)
[6112]228#endif
[882]229{
[6112]230 char *s;
[5523]231
[6112]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);
[882]239}
240
[21929]241char *xtempnam(const char *dir, const char *prefix)
242{
[21945]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
[21929]248 char *res = tempnam(dir, prefix);
[21945]249#ifdef __EMX__
250 _chdrive(drv);
251#endif
[21929]252 if (!res)
253 {
254 fprintf (stderr, "Virtual memory exhausted.\n");
255 exit (1);
256 }
257 return res;
258}
259
[5523]260short *dupcstr2wstr(const char *str)
[882]261{
[6112]262 int len;
263 WCHAR *ws;
[5523]264
[6112]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;
[5523]271}
272
273char *dupwstr2cstr(const short *str)
274{
[6112]275 int len;
276 char *cs;
[5523]277
[6112]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;
[5523]284}
285
286/*
287 *****************************************************************************
[6112]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 :
[5523]294 *****************************************************************************
295*/
296int compare_name_id(name_id_t *n1, name_id_t *n2)
297{
[6112]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);
[5523]326
[6112]327 return 0; /* Keep the compiler happy */
[5523]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))
[6112]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)
[5523]347 {
[6112]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 */
[5523]354 {
[6112]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);
[5523]359 }
[6112]360 return ret;
[882]361}
362
[5523]363
364struct lang2cp
[882]365{
[5523]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 },
[10425]379 { LANG_ARMENIAN, SUBLANG_NEUTRAL, 0 },
380 { LANG_AZERI, SUBLANG_NEUTRAL, 1254 },
381 { LANG_AZERI, SUBLANG_AZERI_CYRILLIC, 1251 },
[5523]382 { LANG_BASQUE, SUBLANG_NEUTRAL, 1252 },
[10425]383 { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 },
384#ifdef LANG_BRETON
[5523]385 { LANG_BRETON, SUBLANG_NEUTRAL, 1252 },
[10425]386#endif /* LANG_BRETON */
[5523]387 { LANG_BULGARIAN, SUBLANG_NEUTRAL, 1251 },
[10425]388 { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 }, /* ?? */
[5523]389 { LANG_CATALAN, SUBLANG_NEUTRAL, 1252 },
390 { LANG_CHINESE, SUBLANG_NEUTRAL, 936 },
[10425]391 { LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE, 936 },
392 { LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED, 936 },
393#ifdef LANG_CORNISH
[5523]394 { LANG_CORNISH, SUBLANG_NEUTRAL, 1252 },
[10425]395#endif /* LANG_CORNISH */
396 { LANG_CROATIAN, SUBLANG_NEUTRAL, 1250 },
[5523]397 { LANG_CZECH, SUBLANG_NEUTRAL, 1250 },
398 { LANG_DANISH, SUBLANG_NEUTRAL, 1252 },
[10425]399 { LANG_DIVEHI, SUBLANG_NEUTRAL, 0 },
[5523]400 { LANG_DUTCH, SUBLANG_NEUTRAL, 1252 },
401 { LANG_ENGLISH, SUBLANG_NEUTRAL, 1252 },
[10425]402#ifdef LANG_ESPERANTO
[5523]403 { LANG_ESPERANTO, SUBLANG_NEUTRAL, 1252 },
[10425]404#endif /* LANG_ESPERANTO */
[5523]405 { LANG_ESTONIAN, SUBLANG_NEUTRAL, 1257 },
406 { LANG_FAEROESE, SUBLANG_NEUTRAL, 1252 },
[10425]407 { LANG_FARSI, SUBLANG_NEUTRAL, 1256 },
[5523]408 { LANG_FINNISH, SUBLANG_NEUTRAL, 1252 },
409 { LANG_FRENCH, SUBLANG_NEUTRAL, 1252 },
[10425]410#ifdef LANG_GAELIC
[5523]411 { LANG_GAELIC, SUBLANG_NEUTRAL, 1252 },
[10425]412#endif /* LANG_GAELIC */
413 { LANG_GALICIAN, SUBLANG_NEUTRAL, 1252 },
414 { LANG_GEORGIAN, SUBLANG_NEUTRAL, 0 },
[5523]415 { LANG_GERMAN, SUBLANG_NEUTRAL, 1252 },
416 { LANG_GREEK, SUBLANG_NEUTRAL, 1253 },
[10425]417 { LANG_GUJARATI, SUBLANG_NEUTRAL, 0 },
[5523]418 { LANG_HEBREW, SUBLANG_NEUTRAL, 1255 },
[10425]419 { LANG_HINDI, SUBLANG_NEUTRAL, 0 },
[5523]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 },
[10425]425 { LANG_KANNADA, SUBLANG_NEUTRAL, 0 },
426 { LANG_KAZAK, SUBLANG_NEUTRAL, 1251 },
427 { LANG_KONKANI, SUBLANG_NEUTRAL, 0 },
[5523]428 { LANG_KOREAN, SUBLANG_NEUTRAL, 949 },
[10425]429 { LANG_KYRGYZ, SUBLANG_NEUTRAL, 1251 },
[5523]430 { LANG_LATVIAN, SUBLANG_NEUTRAL, 1257 },
431 { LANG_LITHUANIAN, SUBLANG_NEUTRAL, 1257 },
432 { LANG_MACEDONIAN, SUBLANG_NEUTRAL, 1251 },
433 { LANG_MALAY, SUBLANG_NEUTRAL, 1252 },
[10425]434 { LANG_MARATHI, SUBLANG_NEUTRAL, 0 },
435 { LANG_MONGOLIAN, SUBLANG_NEUTRAL, 1251 },
[5523]436 { LANG_NEUTRAL, SUBLANG_NEUTRAL, 1252 },
437 { LANG_NORWEGIAN, SUBLANG_NEUTRAL, 1252 },
438 { LANG_POLISH, SUBLANG_NEUTRAL, 1250 },
439 { LANG_PORTUGUESE, SUBLANG_NEUTRAL, 1252 },
[10425]440 { LANG_PUNJABI, SUBLANG_NEUTRAL, 0 },
[5523]441 { LANG_ROMANIAN, SUBLANG_NEUTRAL, 1250 },
442 { LANG_RUSSIAN, SUBLANG_NEUTRAL, 1251 },
[10425]443 { LANG_SANSKRIT, SUBLANG_NEUTRAL, 0 },
444 { LANG_SERBIAN, SUBLANG_NEUTRAL, 1250 },
445 { LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC, 1251 },
[5523]446 { LANG_SLOVAK, SUBLANG_NEUTRAL, 1250 },
447 { LANG_SLOVENIAN, SUBLANG_NEUTRAL, 1250 },
448 { LANG_SPANISH, SUBLANG_NEUTRAL, 1252 },
[10425]449 { LANG_SWAHILI, SUBLANG_NEUTRAL, 1252 },
[5523]450 { LANG_SWEDISH, SUBLANG_NEUTRAL, 1252 },
[10425]451 { LANG_SYRIAC, SUBLANG_NEUTRAL, 0 },
452 { LANG_TAMIL, SUBLANG_NEUTRAL, 0 },
453 { LANG_TATAR, SUBLANG_NEUTRAL, 1251 },
454 { LANG_TELUGU, SUBLANG_NEUTRAL, 0 },
[5523]455 { LANG_THAI, SUBLANG_NEUTRAL, 874 },
456 { LANG_TURKISH, SUBLANG_NEUTRAL, 1254 },
457 { LANG_UKRAINIAN, SUBLANG_NEUTRAL, 1251 },
[10425]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 */
[5523]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) );
[882]491}
492
[6112]493#if defined(__WIN32OS2__)
[8596]494INT WINAPI strcasecmp( LPCSTR p1, LPCSTR p2 )
[882]495{
[6112]496 return stricmp( p1, p2 );
[882]497}
[21551]498#if defined(__IBMC__)
[7855]499INT WINAPI lstrcmpiA(LPCSTR p1, LPCSTR p2)
[882]500{
[6112]501 return stricmp( p1, p2 );
[882]502}
[6112]503
[5523]504#endif
[21551]505#endif
Note: See TracBrowser for help on using the repository browser.