Release 980628
[wine/multimedia.git] / tools / wrc / preproc.c
blobd523bc5ee7934d205d81a0251a1b6a1108642187
1 /*
2 * Copyright 1998 Bertho A. Stultiens (BS)
4 */
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
10 #include <config.h>
11 #include "wrc.h"
12 #include "utils.h"
13 #include "preproc.h"
14 #include "parser.h"
17 extern void set_pp_ignore(int); /* From parser.l */
19 static char *current_define;
21 #define HASHKEY 2039
22 static struct pp_entry *pp_defines[HASHKEY];
24 #define MAXIFSTACK 64
25 static struct if_state ifstack[MAXIFSTACK];
26 static int ifstackidx = 0;
28 #if 0
29 void pp_status(void)
31 int i;
32 int sum;
33 int total = 0;
34 struct pp_entry *ppp;
36 printf("Defines statistics:\n");
37 for(i = 0; i < HASHKEY; i++)
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);
45 printf("Total defines: %d\n", total);
47 #pragma exit pp_status
48 #endif
50 /* Don't comment on the hash, its primitive but functional... */
51 int pp_hash(char *str)
53 int sum = 0;
54 while(*str)
55 sum += *str++;
56 return sum % HASHKEY;
59 struct pp_entry *pp_lookup(char *ident)
61 int index = pp_hash(ident);
62 struct pp_entry *ppp;
63 for(ppp = pp_defines[index]; ppp; ppp = ppp->next)
65 if(!strcmp(ident, ppp->ident))
66 return ppp;
68 return NULL;
71 void set_define(char *name)
73 current_define = xstrdup(name);
76 void del_define(char *name)
78 int index;
79 struct pp_entry *ppp;
81 if((ppp = pp_lookup(name)) == NULL)
83 if(pedantic)
84 yywarning("%s was not defined", name);
85 return;
88 index = pp_hash(name);
89 if(pp_defines[index] == ppp)
91 pp_defines[index] = ppp->next;
92 if(pp_defines[index])
93 pp_defines[index]->prev = NULL;
95 else
97 ppp->prev->next = ppp->next;
98 if(ppp->next)
99 ppp->next->prev = ppp->prev;
101 free(ppp);
104 void add_define(char *text)
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)
112 if(pedantic)
113 yywarning("Redefinition of %s", current_define);
114 del_define(current_define);
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]))
127 ppp->subst[--len] = '\0';
129 /* Strip leading white space from subst text */
130 for(cptr = ppp->subst; *cptr && strchr(" \t\r", *cptr); cptr++)
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);
138 void add_cmdline_define(char *set)
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);
149 #if defined(_Windows) || defined(__MSDOS__)
150 #define INCLUDESEPARATOR ";"
151 #else
152 #define INCLUDESEPARATOR ":"
153 #endif
155 static char **includepath;
156 static int nincludepath = 0;
158 void add_include_path(char *path)
160 char *tok;
161 char *cpy = xstrdup(path);
163 tok = strtok(cpy, INCLUDESEPARATOR);
164 while(tok)
166 char *dir;
167 char *cptr;
168 if(strlen(tok) == 0)
169 continue;
170 dir = xstrdup(tok);
171 for(cptr = dir; *cptr; cptr++)
173 /* Convert to forward slash */
174 if(*cptr == '\\')
175 *cptr = '/';
177 /* Kill eventual trailing '/' */
178 if(*(cptr = dir + strlen(dir)-1) == '/')
179 *cptr = '\0';
181 /* Add to list */
182 nincludepath++;
183 includepath = (char **)xrealloc(includepath, nincludepath * sizeof(*includepath));
184 includepath[nincludepath-1] = dir;
185 tok = strtok(NULL, INCLUDESEPARATOR);
187 free(cpy);
190 FILE *open_include(const char *name, int search)
192 char *cpy = xstrdup(name);
193 char *cptr;
194 FILE *fp;
195 int i;
197 for(cptr = cpy; *cptr; cptr++)
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 = '/';
207 if(search)
209 /* Search current dir and then -I path */
210 fp = fopen(name, "rt");
211 if(fp)
213 if(yydebug)
214 printf("Going to include <%s>\n", name);
215 free(cpy);
216 return fp;
219 /* Search -I path */
220 for(i = 0; i < nincludepath; i++)
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)
233 free(cpy);
234 return fp;
238 free(cpy);
239 return NULL;
242 void push_if(int truecase, int wastrue, int nevertrue)
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++;
262 int pop_if(void)
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;
277 int isnevertrue_if(void)
279 return ifstackidx > 0 && ifstack[ifstackidx-1].nevertrue;