- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[wine] / tools / wrc / preproc.c
1 /*
2  * Copyright 1998 Bertho A. Stultiens (BS)
3  *
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <config.h>
11 #include "wrc.h"
12 #include "utils.h"
13 #include "preproc.h"
14 #include "parser.h"
15
16
17 extern void set_pp_ignore(int); /* From parser.l */
18
19 static char *current_define;
20
21 #define HASHKEY         2039
22 static struct pp_entry *pp_defines[HASHKEY];
23
24 #define MAXIFSTACK      64
25 static struct if_state ifstack[MAXIFSTACK];
26 static int ifstackidx = 0;
27
28 #if 0
29 void pp_status(void)
30 {
31         int i;
32         int sum;
33         int total = 0;
34         struct pp_entry *ppp;
35
36         printf("Defines statistics:\n");
37         for(i = 0; i < HASHKEY; i++)
38         {
39                 sum = 0;
40                 for(ppp = pp_defines[i]; ppp; ppp = ppp->next)
41                         sum++;
42                 total += sum;
43                 printf("%4d, %3d\n", i, sum);
44         }
45         printf("Total defines: %d\n", total);
46 }
47 #pragma exit pp_status
48 #endif
49
50 /* Don't comment on the hash, its primitive but functional... */
51 int pp_hash(char *str)
52 {
53         int sum = 0;
54         while(*str)
55                 sum += *str++;
56         return sum % HASHKEY;
57 }
58
59 struct pp_entry *pp_lookup(char *ident)
60 {
61         int index = pp_hash(ident);
62         struct pp_entry *ppp;
63         for(ppp = pp_defines[index]; ppp; ppp = ppp->next)
64         {
65                 if(!strcmp(ident, ppp->ident))
66                         return ppp;
67         }
68         return NULL;
69 }
70
71 void set_define(char *name)
72 {
73         current_define = xstrdup(name);
74 }
75
76 void del_define(char *name)
77 {
78         int index;
79         struct pp_entry *ppp;
80
81         if((ppp = pp_lookup(name)) == NULL)
82         {
83                 if(pedantic)
84                         yywarning("%s was not defined", name);
85                 return;
86         }
87
88         index = pp_hash(name);
89         if(pp_defines[index] == ppp)
90         {
91                 pp_defines[index] = ppp->next;
92                 if(pp_defines[index])
93                         pp_defines[index]->prev = NULL;
94         }
95         else
96         {
97                 ppp->prev->next = ppp->next;
98                 if(ppp->next)
99                         ppp->next->prev = ppp->prev;
100         }
101         free(ppp);
102 }
103
104 void add_define(char *text)
105 {
106         int len;
107         char *cptr;
108         int index = pp_hash(current_define);
109         struct pp_entry *ppp;
110         if(pp_lookup(current_define) != NULL)
111         {
112                 if(pedantic)
113                         yywarning("Redefinition of %s", current_define);
114                 del_define(current_define);
115         }
116         ppp = (struct pp_entry *)xmalloc(sizeof(struct pp_entry));
117         ppp->ident = current_define;
118         ppp->subst = xstrdup(text);
119         ppp->next = pp_defines[index];
120         pp_defines[index] = ppp;
121         if(ppp->next)
122                 ppp->next->prev = ppp;
123         /* Strip trailing white space from subst text */
124         len = strlen(ppp->subst);
125         while(len && strchr(" \t\r\n", ppp->subst[len-1]))
126         {
127                 ppp->subst[--len] = '\0';
128         }
129         /* Strip leading white space from subst text */
130         for(cptr = ppp->subst; *cptr && strchr(" \t\r", *cptr); cptr++)
131                 ;
132         if(ppp->subst != cptr)
133                 memmove(ppp->subst, cptr, strlen(cptr)+1);
134         if(yydebug)
135                 printf("Added (%s, %d) <%s> to <%s>\n", input_name, line_number, ppp->ident, ppp->subst);
136 }
137
138 void add_cmdline_define(char *set)
139 {
140         char *cpy = xstrdup(set);       /* Because gcc passes a R/O string */
141         char *cptr = strchr(cpy, '=');
142         if(cptr)
143                 *cptr = '\0';
144         set_define(cpy);
145         add_define(cptr ? cptr+1 : "");
146         free(cpy);
147 }
148
149 #if defined(_Windows) || defined(__MSDOS__)
150 #define INCLUDESEPARATOR        ";"
151 #else
152 #define INCLUDESEPARATOR        ":"
153 #endif
154
155 static char **includepath;
156 static int nincludepath = 0;
157
158 void add_include_path(char *path)
159 {
160         char *tok;
161         char *cpy = xstrdup(path);
162
163         tok = strtok(cpy, INCLUDESEPARATOR);
164         while(tok)
165         {
166                 char *dir;
167                 char *cptr;
168                 if(strlen(tok) == 0)
169                         continue;
170                 dir = xstrdup(tok);
171                 for(cptr = dir; *cptr; cptr++)
172                 {
173                         /* Convert to forward slash */
174                         if(*cptr == '\\')
175                                 *cptr = '/';
176                 }
177                 /* Kill eventual trailing '/' */
178                 if(*(cptr = dir + strlen(dir)-1) == '/')
179                         *cptr = '\0';
180
181                 /* Add to list */
182                 nincludepath++;
183                 includepath = (char **)xrealloc(includepath, nincludepath * sizeof(*includepath));
184                 includepath[nincludepath-1] = dir;
185                 tok = strtok(NULL, INCLUDESEPARATOR);
186         }
187         free(cpy);
188 }
189
190 FILE *open_include(const char *name, int search)
191 {
192         char *cpy = xstrdup(name);
193         char *cptr;
194         FILE *fp;
195         int i;
196
197         for(cptr = cpy; *cptr; cptr++)
198         {
199                 /* kill double backslash */
200                 if(*cptr == '\\' && *(cptr+1) == '\\')
201                         memmove(cptr, cptr+1, strlen(cptr));
202                 /* Convert to forward slash */
203                 if(*cptr == '\\')
204                         *cptr = '/';
205         }
206
207         if(search)
208         {
209                 /* Search current dir and then -I path */
210                 fp = fopen(name, "rt");
211                 if(fp)
212                 {
213                         if(yydebug)
214                                 printf("Going to include <%s>\n", name);
215                         free(cpy);
216                         return fp;
217                 }
218         }
219         /* Search -I path */
220         for(i = 0; i < nincludepath; i++)
221         {
222                 char *path;
223                 path = (char *)xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
224                 strcpy(path, includepath[i]);
225                 strcat(path, "/");
226                 strcat(path, cpy);
227                 fp = fopen(path, "rt");
228                 if(fp && yydebug)
229                         printf("Going to include <%s>\n", path);
230                 free(path);
231                 if(fp)
232                 {
233                         free(cpy);
234                         return fp;
235                 }
236
237         }
238         free(cpy);
239         return NULL;
240 }
241
242 void push_if(int truecase, int wastrue, int nevertrue)
243 {
244         if(ifstackidx >= MAXIFSTACK-1)
245                 internal_error(__FILE__, __LINE__, "#if stack overflow");
246         ifstack[ifstackidx].current = truecase && !wastrue;
247         ifstack[ifstackidx].hasbeentrue = wastrue;
248         ifstack[ifstackidx].nevertrue = nevertrue;
249         if(nevertrue || !(truecase && !wastrue))
250                 set_pp_ignore(1);
251         if(yydebug)
252                 printf("push_if: %d %d %d (%d %d %d)\n",
253                         truecase,
254                         wastrue,
255                         nevertrue,
256                         ifstack[ifstackidx].current,
257                         ifstack[ifstackidx].hasbeentrue,
258                         ifstack[ifstackidx].nevertrue);
259         ifstackidx++;
260 }
261
262 int pop_if(void)
263 {
264         if(ifstackidx <= 0)
265                 yyerror("#endif without #if|#ifdef|#ifndef (#if stack underflow)");
266         ifstackidx--;
267         if(yydebug)
268                 printf("pop_if: %d %d %d\n",
269                         ifstack[ifstackidx].current,
270                         ifstack[ifstackidx].hasbeentrue,
271                         ifstack[ifstackidx].nevertrue);
272         if(ifstack[ifstackidx].nevertrue || !ifstack[ifstackidx].current)
273                 set_pp_ignore(0);
274         return ifstack[ifstackidx].hasbeentrue || ifstack[ifstackidx].current;
275 }
276
277 int isnevertrue_if(void)
278 {
279         return ifstackidx > 0 && ifstack[ifstackidx-1].nevertrue;
280 }
281