source: trunk/tools/wrc/utils.c@ 21929

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

Replace tmpnam() with tempnam().

The former in EMX returns paths relative to the current
directory while it should be relative to %TMP%.

r21928 also does that.

File size: 14.3 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 char *res = tempnam(dir, prefix);
244 if (!res)
245 {
246 fprintf (stderr, "Virtual memory exhausted.\n");
247 exit (1);
248 }
249 return res;
250}
251
252short *dupcstr2wstr(const char *str)
253{
254 int len;
255 WCHAR *ws;
256
257 if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
258 len = cp_mbstowcs( current_codepage, 0, str, strlen(str), NULL, 0 );
259 ws = xmalloc( sizeof(WCHAR) * (len + 1) );
260 len = cp_mbstowcs( current_codepage, 0, str, strlen(str), ws, len );
261 ws[len] = 0;
262 return ws;
263}
264
265char *dupwstr2cstr(const short *str)
266{
267 int len;
268 char *cs;
269
270 if (!current_codepage) set_language( LANG_NEUTRAL, SUBLANG_NEUTRAL );
271 len = cp_wcstombs( current_codepage, 0, str, strlenW(str), NULL, 0, NULL, NULL );
272 cs = xmalloc( len + 1 );
273 len = cp_wcstombs( current_codepage, 0, str, strlenW(str), cs, len, NULL, NULL );
274 cs[len] = 0;
275 return cs;
276}
277
278/*
279 *****************************************************************************
280 * Function : compare_name_id
281 * Syntax : int compare_name_id(name_id_t *n1, name_id_t *n2)
282 * Input :
283 * Output :
284 * Description :
285 * Remarks :
286 *****************************************************************************
287*/
288int compare_name_id(name_id_t *n1, name_id_t *n2)
289{
290 if(n1->type == name_ord && n2->type == name_ord)
291 {
292 return n1->name.i_name - n2->name.i_name;
293 }
294 else if(n1->type == name_str && n2->type == name_str)
295 {
296 if(n1->name.s_name->type == str_char
297 && n2->name.s_name->type == str_char)
298 {
299 return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
300 }
301 else if(n1->name.s_name->type == str_unicode
302 && n2->name.s_name->type == str_unicode)
303 {
304 return strcmpiW(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
305 }
306 else
307 {
308 internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
309 }
310 }
311 else if(n1->type == name_ord && n2->type == name_str)
312 return 1;
313 else if(n1->type == name_str && n2->type == name_ord)
314 return -1;
315 else
316 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
317 n1->type, n2->type);
318
319 return 0; /* Keep the compiler happy */
320}
321
322string_t *convert_string(const string_t *str, enum str_e type)
323{
324 string_t *ret = xmalloc(sizeof(*ret));
325
326 if((str->type == str_char) && (type == str_unicode))
327 {
328 ret->str.wstr = dupcstr2wstr(str->str.cstr);
329 ret->type = str_unicode;
330 ret->size = strlenW(ret->str.wstr);
331 }
332 else if((str->type == str_unicode) && (type == str_char))
333 {
334 ret->str.cstr = dupwstr2cstr(str->str.wstr);
335 ret->type = str_char;
336 ret->size = strlen(ret->str.cstr);
337 }
338 else if(str->type == str_unicode)
339 {
340 ret->type = str_unicode;
341 ret->size = strlenW(str->str.wstr);
342 ret->str.wstr = xmalloc(sizeof(WCHAR)*(ret->size+1));
343 strcpyW(ret->str.wstr, str->str.wstr);
344 }
345 else /* str->type == str_char */
346 {
347 ret->type = str_char;
348 ret->size = strlen(str->str.cstr);
349 ret->str.cstr = xmalloc( ret->size + 1 );
350 strcpy(ret->str.cstr, str->str.cstr);
351 }
352 return ret;
353}
354
355
356struct lang2cp
357{
358 unsigned short lang;
359 unsigned short sublang;
360 unsigned int cp;
361} lang2cp_t;
362
363/* language to codepage conversion table */
364/* specific sublanguages need only be specified if their codepage */
365/* differs from the default (SUBLANG_NEUTRAL) */
366static const struct lang2cp lang2cps[] =
367{
368 { LANG_AFRIKAANS, SUBLANG_NEUTRAL, 1252 },
369 { LANG_ALBANIAN, SUBLANG_NEUTRAL, 1250 },
370 { LANG_ARABIC, SUBLANG_NEUTRAL, 1256 },
371 { LANG_ARMENIAN, SUBLANG_NEUTRAL, 0 },
372 { LANG_AZERI, SUBLANG_NEUTRAL, 1254 },
373 { LANG_AZERI, SUBLANG_AZERI_CYRILLIC, 1251 },
374 { LANG_BASQUE, SUBLANG_NEUTRAL, 1252 },
375 { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 },
376#ifdef LANG_BRETON
377 { LANG_BRETON, SUBLANG_NEUTRAL, 1252 },
378#endif /* LANG_BRETON */
379 { LANG_BULGARIAN, SUBLANG_NEUTRAL, 1251 },
380 { LANG_BELARUSIAN, SUBLANG_NEUTRAL, 1251 }, /* ?? */
381 { LANG_CATALAN, SUBLANG_NEUTRAL, 1252 },
382 { LANG_CHINESE, SUBLANG_NEUTRAL, 936 },
383 { LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE, 936 },
384 { LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED, 936 },
385#ifdef LANG_CORNISH
386 { LANG_CORNISH, SUBLANG_NEUTRAL, 1252 },
387#endif /* LANG_CORNISH */
388 { LANG_CROATIAN, SUBLANG_NEUTRAL, 1250 },
389 { LANG_CZECH, SUBLANG_NEUTRAL, 1250 },
390 { LANG_DANISH, SUBLANG_NEUTRAL, 1252 },
391 { LANG_DIVEHI, SUBLANG_NEUTRAL, 0 },
392 { LANG_DUTCH, SUBLANG_NEUTRAL, 1252 },
393 { LANG_ENGLISH, SUBLANG_NEUTRAL, 1252 },
394#ifdef LANG_ESPERANTO
395 { LANG_ESPERANTO, SUBLANG_NEUTRAL, 1252 },
396#endif /* LANG_ESPERANTO */
397 { LANG_ESTONIAN, SUBLANG_NEUTRAL, 1257 },
398 { LANG_FAEROESE, SUBLANG_NEUTRAL, 1252 },
399 { LANG_FARSI, SUBLANG_NEUTRAL, 1256 },
400 { LANG_FINNISH, SUBLANG_NEUTRAL, 1252 },
401 { LANG_FRENCH, SUBLANG_NEUTRAL, 1252 },
402#ifdef LANG_GAELIC
403 { LANG_GAELIC, SUBLANG_NEUTRAL, 1252 },
404#endif /* LANG_GAELIC */
405 { LANG_GALICIAN, SUBLANG_NEUTRAL, 1252 },
406 { LANG_GEORGIAN, SUBLANG_NEUTRAL, 0 },
407 { LANG_GERMAN, SUBLANG_NEUTRAL, 1252 },
408 { LANG_GREEK, SUBLANG_NEUTRAL, 1253 },
409 { LANG_GUJARATI, SUBLANG_NEUTRAL, 0 },
410 { LANG_HEBREW, SUBLANG_NEUTRAL, 1255 },
411 { LANG_HINDI, SUBLANG_NEUTRAL, 0 },
412 { LANG_HUNGARIAN, SUBLANG_NEUTRAL, 1250 },
413 { LANG_ICELANDIC, SUBLANG_NEUTRAL, 1252 },
414 { LANG_INDONESIAN, SUBLANG_NEUTRAL, 1252 },
415 { LANG_ITALIAN, SUBLANG_NEUTRAL, 1252 },
416 { LANG_JAPANESE, SUBLANG_NEUTRAL, 932 },
417 { LANG_KANNADA, SUBLANG_NEUTRAL, 0 },
418 { LANG_KAZAK, SUBLANG_NEUTRAL, 1251 },
419 { LANG_KONKANI, SUBLANG_NEUTRAL, 0 },
420 { LANG_KOREAN, SUBLANG_NEUTRAL, 949 },
421 { LANG_KYRGYZ, SUBLANG_NEUTRAL, 1251 },
422 { LANG_LATVIAN, SUBLANG_NEUTRAL, 1257 },
423 { LANG_LITHUANIAN, SUBLANG_NEUTRAL, 1257 },
424 { LANG_MACEDONIAN, SUBLANG_NEUTRAL, 1251 },
425 { LANG_MALAY, SUBLANG_NEUTRAL, 1252 },
426 { LANG_MARATHI, SUBLANG_NEUTRAL, 0 },
427 { LANG_MONGOLIAN, SUBLANG_NEUTRAL, 1251 },
428 { LANG_NEUTRAL, SUBLANG_NEUTRAL, 1252 },
429 { LANG_NORWEGIAN, SUBLANG_NEUTRAL, 1252 },
430 { LANG_POLISH, SUBLANG_NEUTRAL, 1250 },
431 { LANG_PORTUGUESE, SUBLANG_NEUTRAL, 1252 },
432 { LANG_PUNJABI, SUBLANG_NEUTRAL, 0 },
433 { LANG_ROMANIAN, SUBLANG_NEUTRAL, 1250 },
434 { LANG_RUSSIAN, SUBLANG_NEUTRAL, 1251 },
435 { LANG_SANSKRIT, SUBLANG_NEUTRAL, 0 },
436 { LANG_SERBIAN, SUBLANG_NEUTRAL, 1250 },
437 { LANG_SERBIAN, SUBLANG_SERBIAN_CYRILLIC, 1251 },
438 { LANG_SLOVAK, SUBLANG_NEUTRAL, 1250 },
439 { LANG_SLOVENIAN, SUBLANG_NEUTRAL, 1250 },
440 { LANG_SPANISH, SUBLANG_NEUTRAL, 1252 },
441 { LANG_SWAHILI, SUBLANG_NEUTRAL, 1252 },
442 { LANG_SWEDISH, SUBLANG_NEUTRAL, 1252 },
443 { LANG_SYRIAC, SUBLANG_NEUTRAL, 0 },
444 { LANG_TAMIL, SUBLANG_NEUTRAL, 0 },
445 { LANG_TATAR, SUBLANG_NEUTRAL, 1251 },
446 { LANG_TELUGU, SUBLANG_NEUTRAL, 0 },
447 { LANG_THAI, SUBLANG_NEUTRAL, 874 },
448 { LANG_TURKISH, SUBLANG_NEUTRAL, 1254 },
449 { LANG_UKRAINIAN, SUBLANG_NEUTRAL, 1251 },
450 { LANG_URDU, SUBLANG_NEUTRAL, 1256 },
451 { LANG_UZBEK, SUBLANG_NEUTRAL, 1254 },
452 { LANG_UZBEK, SUBLANG_UZBEK_CYRILLIC, 1251 },
453 { LANG_VIETNAMESE, SUBLANG_NEUTRAL, 1258 }
454#ifdef LANG_WALON
455 , { LANG_WALON, SUBLANG_NEUTRAL, 1252 }
456#endif /* LANG_WALON */
457#ifdef LANG_WELSH
458 , { LANG_WELSH, SUBLANG_NEUTRAL, 1252 }
459#endif /* LANG_WELSH */
460};
461
462void set_language( unsigned short lang, unsigned short sublang )
463{
464 unsigned int i;
465 unsigned int cp = 0, defcp = 0;
466
467 for (i = 0; i < sizeof(lang2cps)/sizeof(lang2cps[0]); i++)
468 {
469 if (lang2cps[i].lang != lang) continue;
470 if (lang2cps[i].sublang == sublang)
471 {
472 cp = lang2cps[i].cp;
473 break;
474 }
475 if (lang2cps[i].sublang == SUBLANG_NEUTRAL) defcp = lang2cps[i].cp;
476 }
477
478 if (!cp) cp = defcp;
479 if (!cp)
480 error( "No codepage value for language %04x", MAKELANGID(lang,sublang) );
481 if (!(current_codepage = cp_get_table( cp )))
482 error( "Bad codepage %d for language %04x", cp, MAKELANGID(lang,sublang) );
483}
484
485#if defined(__WIN32OS2__)
486INT WINAPI strcasecmp( LPCSTR p1, LPCSTR p2 )
487{
488 return stricmp( p1, p2 );
489}
490#if defined(__IBMC__)
491INT WINAPI lstrcmpiA(LPCSTR p1, LPCSTR p2)
492{
493 return stricmp( p1, p2 );
494}
495
496#endif
497#endif
Note: See TracBrowser for help on using the repository browser.