Fix the case of product and company names.
[wine] / libs / wpp / preproc.c
1 /*
2  * Copyright 1998 Bertho A. Stultiens (BS)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "config.h"
20 #include "wine/port.h"
21
22 #include <assert.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #ifdef HAVE_UNISTD_H
29 # include <unistd.h>
30 #endif
31
32 #include "wpp_private.h"
33
34 struct pp_status pp_status;
35
36 #define HASHKEY         2039
37
38 typedef struct pp_def_state
39 {
40     struct pp_def_state *next;
41     pp_entry_t          *defines[HASHKEY];
42 } pp_def_state_t;
43
44 static pp_def_state_t *pp_def_state;
45
46 #define MAXIFSTACK      64
47 static pp_if_state_t if_stack[MAXIFSTACK];
48 static int if_stack_idx = 0;
49
50 #if 0
51 void pp_print_status(void) __attribute__((destructor));
52 void pp_print_status(void)
53 {
54         int i;
55         int sum;
56         int total = 0;
57         pp_entry_t *ppp;
58
59         fprintf(stderr, "Defines statistics:\n");
60         for(i = 0; i < HASHKEY; i++)
61         {
62                 sum = 0;
63                 for(ppp = pp_def_state->defines[i]; ppp; ppp = ppp->next)
64                         sum++;
65                 total += sum;
66                 if (sum) fprintf(stderr, "%4d, %3d\n", i, sum);
67         }
68         fprintf(stderr, "Total defines: %d\n", total);
69 }
70 #endif
71
72 void *pp_xmalloc(size_t size)
73 {
74     void *res;
75
76     assert(size > 0);
77     res = malloc(size);
78     if(res == NULL)
79     {
80         fprintf(stderr, "Virtual memory exhausted.\n");
81         exit(2);
82     }
83     return res;
84 }
85
86 void *pp_xrealloc(void *p, size_t size)
87 {
88     void *res;
89
90     assert(size > 0);
91     res = realloc(p, size);
92     if(res == NULL)
93     {
94         fprintf(stderr, "Virtual memory exhausted.\n");
95         exit(2);
96     }
97     return res;
98 }
99
100 char *pp_xstrdup(const char *str)
101 {
102         char *s;
103
104         assert(str != NULL);
105         s = pp_xmalloc(strlen(str)+1);
106         return strcpy(s, str);
107 }
108
109 /* Don't comment on the hash, its primitive but functional... */
110 static int pphash(const char *str)
111 {
112         int sum = 0;
113         while(*str)
114                 sum += *str++;
115         return sum % HASHKEY;
116 }
117
118 pp_entry_t *pplookup(const char *ident)
119 {
120         int idx = pphash(ident);
121         pp_entry_t *ppp;
122
123         for(ppp = pp_def_state->defines[idx]; ppp; ppp = ppp->next)
124         {
125                 if(!strcmp(ident, ppp->ident))
126                         return ppp;
127         }
128         return NULL;
129 }
130
131 static void free_pp_entry( pp_entry_t *ppp, int idx )
132 {
133         if(ppp->iep)
134         {
135                 if(ppp->iep == pp_includelogiclist)
136                 {
137                         pp_includelogiclist = ppp->iep->next;
138                         if(pp_includelogiclist)
139                                 pp_includelogiclist->prev = NULL;
140                 }
141                 else
142                 {
143                         ppp->iep->prev->next = ppp->iep->next;
144                         if(ppp->iep->next)
145                                 ppp->iep->next->prev = ppp->iep->prev;
146                 }
147                 free(ppp->iep->filename);
148                 free(ppp->iep);
149         }
150
151         if(pp_def_state->defines[idx] == ppp)
152         {
153                 pp_def_state->defines[idx] = ppp->next;
154                 if(pp_def_state->defines[idx])
155                         pp_def_state->defines[idx]->prev = NULL;
156         }
157         else
158         {
159                 ppp->prev->next = ppp->next;
160                 if(ppp->next)
161                         ppp->next->prev = ppp->prev;
162         }
163
164         free(ppp);
165 }
166
167 /* push a new (empty) define state */
168 void pp_push_define_state(void)
169 {
170     pp_def_state_t *state = pp_xmalloc( sizeof(*state) );
171
172     memset( state->defines, 0, sizeof(state->defines) );
173     state->next = pp_def_state;
174     pp_def_state = state;
175 }
176
177 /* pop the current define state */
178 void pp_pop_define_state(void)
179 {
180     int i;
181     pp_entry_t *ppp;
182     pp_def_state_t *state;
183
184     for (i = 0; i < HASHKEY; i++)
185     {
186         while ((ppp = pp_def_state->defines[i]) != NULL) free_pp_entry( ppp, i );
187     }
188     state = pp_def_state;
189     pp_def_state = state->next;
190     free( state );
191 }
192
193 void pp_del_define(const char *name)
194 {
195         pp_entry_t *ppp;
196
197         if((ppp = pplookup(name)) == NULL)
198         {
199                 if(pp_status.pedantic)
200                         ppwarning("%s was not defined", name);
201                 return;
202         }
203
204         free_pp_entry( ppp, pphash(name) );
205
206         if(pp_status.debug)
207                 printf("Deleted (%s, %d) <%s>\n", pp_status.input, pp_status.line_number, name);
208 }
209
210 pp_entry_t *pp_add_define(char *def, char *text)
211 {
212         int len;
213         char *cptr;
214         int idx = pphash(def);
215         pp_entry_t *ppp;
216
217         if((ppp = pplookup(def)) != NULL)
218         {
219                 if(pp_status.pedantic)
220                         ppwarning("Redefinition of %s\n\tPrevious definition: %s:%d", def, ppp->filename, ppp->linenumber);
221                 pp_del_define(def);
222         }
223         ppp = pp_xmalloc(sizeof(pp_entry_t));
224         memset( ppp, 0, sizeof(*ppp) );
225         ppp->ident = def;
226         ppp->type = def_define;
227         ppp->subst.text = text;
228         ppp->filename = pp_status.input ? pp_xstrdup(pp_status.input) : "<internal or cmdline>";
229         ppp->linenumber = pp_status.input ? pp_status.line_number : 0;
230         ppp->next = pp_def_state->defines[idx];
231         pp_def_state->defines[idx] = ppp;
232         if(ppp->next)
233                 ppp->next->prev = ppp;
234         if(text)
235         {
236                 /* Strip trailing white space from subst text */
237                 len = strlen(text);
238                 while(len && strchr(" \t\r\n", text[len-1]))
239                 {
240                         text[--len] = '\0';
241                 }
242                 /* Strip leading white space from subst text */
243                 for(cptr = text; *cptr && strchr(" \t\r", *cptr); cptr++)
244                 ;
245                 if(text != cptr)
246                         memmove(text, cptr, strlen(cptr)+1);
247         }
248         if(pp_status.debug)
249                 printf("Added define (%s, %d) <%s> to <%s>\n", pp_status.input, pp_status.line_number, ppp->ident, text ? text : "(null)");
250
251         return ppp;
252 }
253
254 pp_entry_t *pp_add_macro(char *id, marg_t *args[], int nargs, mtext_t *exp)
255 {
256         int idx = pphash(id);
257         pp_entry_t *ppp;
258
259         if((ppp = pplookup(id)) != NULL)
260         {
261                 if(pp_status.pedantic)
262                         ppwarning("Redefinition of %s\n\tPrevious definition: %s:%d", id, ppp->filename, ppp->linenumber);
263                 pp_del_define(id);
264         }
265         ppp = pp_xmalloc(sizeof(pp_entry_t));
266         memset( ppp, 0, sizeof(*ppp) );
267         ppp->ident      = id;
268         ppp->type       = def_macro;
269         ppp->margs      = args;
270         ppp->nargs      = nargs;
271         ppp->subst.mtext= exp;
272         ppp->filename = pp_status.input ? pp_xstrdup(pp_status.input) : "<internal or cmdline>";
273         ppp->linenumber = pp_status.input ? pp_status.line_number : 0;
274         ppp->next       = pp_def_state->defines[idx];
275         pp_def_state->defines[idx] = ppp;
276         if(ppp->next)
277                 ppp->next->prev = ppp;
278
279         if(pp_status.debug)
280         {
281                 fprintf(stderr, "Added macro (%s, %d) <%s(%d)> to <", pp_status.input, pp_status.line_number, ppp->ident, nargs);
282                 for(; exp; exp = exp->next)
283                 {
284                         switch(exp->type)
285                         {
286                         case exp_text:
287                                 fprintf(stderr, " \"%s\" ", exp->subst.text);
288                                 break;
289                         case exp_stringize:
290                                 fprintf(stderr, " #(%d) ", exp->subst.argidx);
291                                 break;
292                         case exp_concat:
293                                 fprintf(stderr, "##");
294                                 break;
295                         case exp_subst:
296                                 fprintf(stderr, " <%d> ", exp->subst.argidx);
297                                 break;
298                         }
299                 }
300                 fprintf(stderr, ">\n");
301         }
302         return ppp;
303 }
304
305
306 /*
307  *-------------------------------------------------------------------------
308  * Include management
309  *-------------------------------------------------------------------------
310  */
311 #if defined(_Windows) || defined(__MSDOS__)
312 #define INCLUDESEPARATOR        ";"
313 #else
314 #define INCLUDESEPARATOR        ":"
315 #endif
316
317 static char **includepath;
318 static int nincludepath = 0;
319
320 void wpp_add_include_path(const char *path)
321 {
322         char *tok;
323         char *cpy = pp_xstrdup(path);
324
325         tok = strtok(cpy, INCLUDESEPARATOR);
326         while(tok)
327         {
328                 char *dir;
329                 char *cptr;
330                 if(strlen(tok) == 0)
331                         continue;
332                 dir = pp_xstrdup(tok);
333                 for(cptr = dir; *cptr; cptr++)
334                 {
335                         /* Convert to forward slash */
336                         if(*cptr == '\\')
337                                 *cptr = '/';
338                 }
339                 /* Kill eventual trailing '/' */
340                 if(*(cptr = dir + strlen(dir)-1) == '/')
341                         *cptr = '\0';
342
343                 /* Add to list */
344                 nincludepath++;
345                 includepath = pp_xrealloc(includepath, nincludepath * sizeof(*includepath));
346                 includepath[nincludepath-1] = dir;
347                 tok = strtok(NULL, INCLUDESEPARATOR);
348         }
349         free(cpy);
350 }
351
352 char *wpp_find_include(const char *name, int search)
353 {
354     char *cpy = pp_xstrdup(name);
355     char *cptr;
356     int i, fd;
357
358     for(cptr = cpy; *cptr; cptr++)
359     {
360         /* kill double backslash */
361         if(*cptr == '\\' && *(cptr+1) == '\\')
362             memmove(cptr, cptr+1, strlen(cptr));
363         /* Convert to forward slash */
364         if(*cptr == '\\')
365             *cptr = '/';
366     }
367
368     if(search)
369     {
370         /* Search current dir and then -I path */
371         fd = open( cpy, O_RDONLY );
372         if (fd != -1)
373         {
374             close( fd );
375             return cpy;
376         }
377     }
378     /* Search -I path */
379     for(i = 0; i < nincludepath; i++)
380     {
381         char *path;
382         path = pp_xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
383         strcpy(path, includepath[i]);
384         strcat(path, "/");
385         strcat(path, cpy);
386         fd = open( path, O_RDONLY );
387         if (fd != -1)
388         {
389             close( fd );
390             free( cpy );
391             return path;
392         }
393         free( path );
394     }
395     free( cpy );
396     return NULL;
397 }
398
399 FILE *pp_open_include(const char *name, int search, char **newpath)
400 {
401     char *path;
402     FILE *fp;
403
404     if (!(path = wpp_find_include( name, search ))) return NULL;
405     fp = fopen(path, "rt");
406
407     if (fp)
408     {
409         if (pp_status.debug)
410             printf("Going to include <%s>\n", path);
411         if (newpath) *newpath = path;
412         else free( path );
413         return fp;
414     }
415     free( path );
416     return NULL;
417 }
418
419 /*
420  *-------------------------------------------------------------------------
421  * #if, #ifdef, #ifndef, #else, #elif and #endif state management
422  *
423  * #if state transitions are made on basis of the current TOS and the next
424  * required state. The state transitions are required to housekeep because
425  * #if:s can be nested. The ignore case is activated to prevent output from
426  * within a false clause.
427  * Some special cases come from the fact that the #elif cases are not
428  * binary, but three-state. The problem is that all other elif-cases must
429  * be false when one true one has been found. A second problem is that the
430  * #else clause is a final clause. No extra #else:s may follow.
431  *
432  * The states mean:
433  * if_true      Process input to output
434  * if_false     Process input but no output
435  * if_ignore    Process input but no output
436  * if_elif      Process input but no output
437  * if_elsefalse Process input but no output
438  * if_elsettrue Process input to output
439  *
440  * The possible state-sequences are [state(stack depth)] (rest can be deduced):
441  *      TOS             #if 1           #else                   #endif
442  *      if_true(n)      if_true(n+1)    if_elsefalse(n+1)
443  *      if_false(n)     if_ignore(n+1)  if_ignore(n+1)
444  *      if_elsetrue(n)  if_true(n+1)    if_elsefalse(n+1)
445  *      if_elsefalse(n) if_ignore(n+1)  if_ignore(n+1)
446  *      if_elif(n)      if_ignore(n+1)  if_ignore(n+1)
447  *      if_ignore(n)    if_ignore(n+1)  if_ignore(n+1)
448  *
449  *      TOS             #if 1           #elif 0         #else           #endif
450  *      if_true(n)      if_true(n+1)    if_elif(n+1)    if_elif(n+1)
451  *      if_false(n)     if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
452  *      if_elsetrue(n)  if_true(n+1)    if_elif(n+1)    if_elif(n+1)
453  *      if_elsefalse(n) if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
454  *      if_elif(n)      if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
455  *      if_ignore(n)    if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
456  *
457  *      TOS             #if 0           #elif 1         #else           #endif
458  *      if_true(n)      if_false(n+1)   if_true(n+1)    if_elsefalse(n+1)
459  *      if_false(n)     if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
460  *      if_elsetrue(n)  if_false(n+1)   if_true(n+1)    if_elsefalse(n+1)
461  *      if_elsefalse(n) if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
462  *      if_elif(n)      if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
463  *      if_ignore(n)    if_ignore(n+1)  if_ignore(n+1)  if_ignore(n+1)
464  *
465  *-------------------------------------------------------------------------
466  */
467 static char *pp_if_state_str[] = {
468         "if_false",
469         "if_true",
470         "if_elif",
471         "if_elsefalse",
472         "if_elsetrue",
473         "if_ignore"
474 };
475
476 void pp_push_if(pp_if_state_t s)
477 {
478         if(if_stack_idx >= MAXIFSTACK)
479                 pp_internal_error(__FILE__, __LINE__, "#if-stack overflow; #{if,ifdef,ifndef} nested too deeply (> %d)", MAXIFSTACK);
480
481         if(pp_flex_debug)
482                 fprintf(stderr, "Push if %s:%d: %s(%d) -> %s(%d)\n", pp_status.input, pp_status.line_number, pp_if_state_str[pp_if_state()], if_stack_idx, pp_if_state_str[s], if_stack_idx+1);
483
484         if_stack[if_stack_idx++] = s;
485
486         switch(s)
487         {
488         case if_true:
489         case if_elsetrue:
490                 break;
491         case if_false:
492         case if_elsefalse:
493         case if_elif:
494         case if_ignore:
495                 pp_push_ignore_state();
496                 break;
497         }
498 }
499
500 pp_if_state_t pp_pop_if(void)
501 {
502         if(if_stack_idx <= 0)
503                 pperror("#{endif,else,elif} without #{if,ifdef,ifndef} (#if-stack underflow)");
504
505         switch(pp_if_state())
506         {
507         case if_true:
508         case if_elsetrue:
509                 break;
510         case if_false:
511         case if_elsefalse:
512         case if_elif:
513         case if_ignore:
514                 pp_pop_ignore_state();
515                 break;
516         }
517
518         if(pp_flex_debug)
519                 fprintf(stderr, "Pop if %s:%d: %s(%d) -> %s(%d)\n",
520                                 pp_status.input,
521                                 pp_status.line_number,
522                                 pp_if_state_str[pp_if_state()],
523                                 if_stack_idx,
524                                 pp_if_state_str[if_stack[if_stack_idx <= 1 ? if_true : if_stack_idx-2]],
525                                 if_stack_idx-1);
526
527         return if_stack[--if_stack_idx];
528 }
529
530 pp_if_state_t pp_if_state(void)
531 {
532         if(!if_stack_idx)
533                 return if_true;
534         else
535                 return if_stack[if_stack_idx-1];
536 }
537
538
539 void pp_next_if_state(int i)
540 {
541         switch(pp_if_state())
542         {
543         case if_true:
544         case if_elsetrue:
545                 pp_push_if(i ? if_true : if_false);
546                 break;
547         case if_false:
548         case if_elsefalse:
549         case if_elif:
550         case if_ignore:
551                 pp_push_if(if_ignore);
552                 break;
553         default:
554                 pp_internal_error(__FILE__, __LINE__, "Invalid pp_if_state (%d) in #{if,ifdef,ifndef} directive", (int)pp_if_state());
555         }
556 }
557
558 int pp_get_if_depth(void)
559 {
560         return if_stack_idx;
561 }
562
563 /* #define WANT_NEAR_INDICATION */
564
565 static void generic_msg(const char *s, const char *t, const char *n, va_list ap)
566 {
567         fprintf(stderr, "%s:%d:%d: %s: ", pp_status.input ? pp_status.input : "stdin",
568                 pp_status.line_number, pp_status.char_number, t);
569         vfprintf(stderr, s, ap);
570 #ifdef WANT_NEAR_INDICATION
571         {
572                 char *cpy, *p;
573                 if(n)
574                 {
575                         cpy = pp_xstrdup(n);
576                         for (p = cpy; *p; p++) if(!isprint(*p)) *p = ' ';
577                         fprintf(stderr, " near '%s'", cpy);
578                         free(cpy);
579                 }
580         }
581 #endif
582         fprintf(stderr, "\n");
583 }
584
585 int pperror(const char *s, ...)
586 {
587         va_list ap;
588         va_start(ap, s);
589         generic_msg(s, "Error", pptext, ap);
590         va_end(ap);
591         exit(1);
592         return 1;
593 }
594
595 int ppwarning(const char *s, ...)
596 {
597         va_list ap;
598         va_start(ap, s);
599         generic_msg(s, "Warning", pptext, ap);
600         va_end(ap);
601         return 0;
602 }
603
604 void pp_internal_error(const char *file, int line, const char *s, ...)
605 {
606         va_list ap;
607         va_start(ap, s);
608         fprintf(stderr, "Internal error (please report) %s %d: ", file, line);
609         vfprintf(stderr, s, ap);
610         fprintf(stderr, "\n");
611         va_end(ap);
612         exit(3);
613 }