Initial release of the message compiler.
[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 <stdio.h>
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <string.h>
14 #include <assert.h>
15 #include <ctype.h>
16
17 #include "wrc.h"
18 #include "utils.h"
19 #include "parser.h"
20 #include "preproc.h"
21
22 /* #define WANT_NEAR_INDICATION */
23
24
25 #ifdef WANT_NEAR_INDICATION
26 void make_print(char *str)
27 {
28         while(*str)
29         {
30                 if(!isprint(*str))
31                         *str = ' ';
32                 str++;
33         }
34 }
35 #endif
36
37 static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
38 {
39         fprintf(stderr, "%s %s: %d, %d: ", t, input_name ? input_name : "stdin", line_number, char_number);
40         vfprintf(stderr, s, ap);
41 #ifdef WANT_NEAR_INDICATION
42         {
43                 char *cpy;
44                 if(n)
45                 {
46                         cpy = xstrdup(n);
47                         make_print(cpy);
48                         fprintf(stderr, " near '%s'", cpy);
49                         free(cpy);
50                 }
51         }
52 #endif
53         fprintf(stderr, "\n");
54 }
55
56
57 int yyerror(const char *s, ...)
58 {
59         va_list ap;
60         va_start(ap, s);
61         generic_msg(s, "Error", yytext, ap);
62         va_end(ap);
63         exit(1);
64         return 1;
65 }
66
67 int yywarning(const char *s, ...)
68 {
69         va_list ap;
70         va_start(ap, s);
71         generic_msg(s, "Warning", yytext, ap);
72         va_end(ap);
73         return 0;
74 }
75
76 int pperror(const char *s, ...)
77 {
78         va_list ap;
79         va_start(ap, s);
80         generic_msg(s, "Error", pptext, ap);
81         va_end(ap);
82         exit(1);
83         return 1;
84 }
85
86 int ppwarning(const char *s, ...)
87 {
88         va_list ap;
89         va_start(ap, s);
90         generic_msg(s, "Warning", pptext, ap);
91         va_end(ap);
92         return 0;
93 }
94
95
96 void internal_error(const char *file, int line, const char *s, ...)
97 {
98         va_list ap;
99         va_start(ap, s);
100         fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
101         vfprintf(stderr, s, ap);
102         fprintf(stderr, "\n");
103         va_end(ap);
104         exit(3);
105 }
106
107 void error(const char *s, ...)
108 {
109         va_list ap;
110         va_start(ap, s);
111         fprintf(stderr, "Error: ");
112         vfprintf(stderr, s, ap);
113         fprintf(stderr, "\n");
114         va_end(ap);
115         exit(2);
116 }
117
118 void warning(const char *s, ...)
119 {
120         va_list ap;
121         va_start(ap, s);
122         fprintf(stderr, "Warning: ");
123         vfprintf(stderr, s, ap);
124         fprintf(stderr, "\n");
125         va_end(ap);
126 }
127
128 void chat(const char *s, ...)
129 {
130         if(debuglevel & DEBUGLEVEL_CHAT)
131         {
132                 va_list ap;
133                 va_start(ap, s);
134                 fprintf(stderr, "FYI: ");
135                 vfprintf(stderr, s, ap);
136                 fprintf(stderr, "\n");
137                 va_end(ap);
138         }
139 }
140
141 char *dup_basename(const char *name, const char *ext)
142 {
143         int namelen;
144         int extlen = strlen(ext);
145         char *base;
146         char *slash;
147
148         if(!name)
149                 name = "wrc.tab";
150
151         slash = strrchr(name, '/');
152         if (slash)
153                 name = slash + 1;
154
155         namelen = strlen(name);
156
157         /* +4 for later extension and +1 for '\0' */
158         base = (char *)xmalloc(namelen +4 +1);
159         strcpy(base, name);
160         if(!strcasecmp(name + namelen-extlen, ext))
161         {
162                 base[namelen - extlen] = '\0';
163         }
164         return base;
165 }
166
167 void *xmalloc(size_t size)
168 {
169     void *res;
170
171     assert(size > 0);
172     assert(size < 102400);
173     res = malloc(size);
174     if(res == NULL)
175     {
176         error("Virtual memory exhausted.\n");
177     }
178     /*
179      * We set it to 0.
180      * This is *paramount* because we depend on it
181      * just about everywhere in the rest of the code.
182      */
183     memset(res, 0, size);
184     return res;
185 }
186
187
188 void *xrealloc(void *p, size_t size)
189 {
190     void *res;
191
192     assert(size > 0);
193     assert(size < 102400);
194     res = realloc(p, size);
195     if(res == NULL)
196     {
197         error("Virtual memory exhausted.\n");
198     }
199     return res;
200 }
201
202 char *xstrdup(const char *str)
203 {
204         char *s;
205
206         assert(str != NULL);
207         s = (char *)xmalloc(strlen(str)+1);
208         return strcpy(s, str);
209 }
210
211 int string_compare(const string_t *s1, const string_t *s2)
212 {
213         if(s1->type == str_char && s2->type == str_char)
214         {
215                 return strcasecmp(s1->str.cstr, s2->str.cstr);
216         }
217         else
218         {
219                 internal_error(__FILE__, __LINE__, "Cannot yet compare unicode strings");
220         }
221         return 0;
222 }
223
224 int wstrlen(const short *s)
225 {
226         int cnt = 0;
227         while(*s++)
228                 cnt++;
229         return cnt;
230 }
231
232 short *wstrcpy(short *dst, const short *src)
233 {
234         short *d = dst;
235         while(*src)
236                 *d++ = *src++;
237         return dst;
238 }
239
240 int wstricmp(const short *s1, const short *s2)
241 {
242         char *cs1 = dupwstr2cstr(s1);
243         char *cs2 = dupwstr2cstr(s2);
244         int retval = strcasecmp(cs1, cs2);
245         free(cs1);
246         free(cs2);
247         warning("Comparing unicode strings without case -> converting to ascii");
248         return retval;;
249 }
250
251 short *dupcstr2wstr(const char *str)
252 {
253         int len = strlen(str) + 1;
254         short *ws = (short *)xmalloc(len*2);
255         short *wptr;
256
257         wptr = ws;
258         /* FIXME: codepage translation */
259         while(*str)
260                 *wptr++ = (short)(*str++ & 0xff);
261         *wptr = 0;
262         return ws;
263 }
264
265 char *dupwstr2cstr(const short *str)
266 {
267         int len = wstrlen(str) + 1;
268         char *cs = (char *)xmalloc(len);
269         char *cptr;
270
271         cptr = cs;
272         /* FIXME: codepage translation */
273         while(*str)
274                 *cptr++ = (char)*str++;
275         *cptr = 0;
276         return cs;
277 }
278
279 /*
280  *****************************************************************************
281  * Function     : compare_name_id
282  * Syntax       : int compare_name_id(name_id_t *n1, name_id_t *n2)
283  * Input        :
284  * Output       :
285  * Description  :
286  * Remarks      :
287  *****************************************************************************
288 */
289 int compare_name_id(name_id_t *n1, name_id_t *n2)
290 {
291         if(n1->type == name_ord && n2->type == name_ord)
292         {
293                 return n1->name.i_name - n2->name.i_name;
294         }
295         else if(n1->type == name_str && n2->type == name_str)
296         {
297                 if(n1->name.s_name->type == str_char
298                 && n2->name.s_name->type == str_char)
299                 {
300                         return strcasecmp(n1->name.s_name->str.cstr, n2->name.s_name->str.cstr);
301                 }
302                 else if(n1->name.s_name->type == str_unicode
303                 && n2->name.s_name->type == str_unicode)
304                 {
305                         return wstricmp(n1->name.s_name->str.wstr, n2->name.s_name->str.wstr);
306                 }
307                 else
308                 {
309                         internal_error(__FILE__, __LINE__, "Can't yet compare strings of mixed type");
310                 }
311         }
312         else if(n1->type == name_ord && n2->type == name_str)
313                 return 1;
314         else if(n1->type == name_str && n2->type == name_ord)
315                 return -1;
316         else
317                 internal_error(__FILE__, __LINE__, "Comparing name-ids with unknown types (%d, %d)",
318                                 n1->type, n2->type);
319
320         return 0; /* Keep the compiler happy */
321 }
322