Temporarily implemented the LCMAP_SORTKEY flag in the LCMapStringW()
[wine/multimedia.git] / tools / wrc / preproc.c
blobcf033b5fdfca5891ecd553ffd0fd8a84876268bb
1 /*
2 * Copyright 1998 Bertho A. Stultiens (BS)
4 */
6 #include "config.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
12 #include "wrc.h"
13 #include "utils.h"
14 #include "preproc.h"
15 #include "parser.h"
18 extern void set_pp_ignore(int); /* From parser.l */
20 static char *current_define;
22 #define HASHKEY 2039
23 static struct pp_entry *pp_defines[HASHKEY];
25 #define MAXIFSTACK 64
26 static struct if_state ifstack[MAXIFSTACK];
27 static int ifstackidx = 0;
29 #if 0
30 void pp_status(void)
32 int i;
33 int sum;
34 int total = 0;
35 struct pp_entry *ppp;
37 printf("Defines statistics:\n");
38 for(i = 0; i < HASHKEY; i++)
40 sum = 0;
41 for(ppp = pp_defines[i]; ppp; ppp = ppp->next)
42 sum++;
43 total += sum;
44 printf("%4d, %3d\n", i, sum);
46 printf("Total defines: %d\n", total);
48 #pragma exit pp_status
49 #endif
51 /* Don't comment on the hash, its primitive but functional... */
52 int pp_hash(char *str)
54 int sum = 0;
55 while(*str)
56 sum += *str++;
57 return sum % HASHKEY;
60 struct pp_entry *pp_lookup(char *ident)
62 int index = pp_hash(ident);
63 struct pp_entry *ppp;
64 for(ppp = pp_defines[index]; ppp; ppp = ppp->next)
66 if(!strcmp(ident, ppp->ident))
67 return ppp;
69 return NULL;
72 void set_define(char *name)
74 current_define = xstrdup(name);
77 void del_define(char *name)
79 int index;
80 struct pp_entry *ppp;
82 if((ppp = pp_lookup(name)) == NULL)
84 if(pedantic)
85 yywarning("%s was not defined", name);
86 return;
89 index = pp_hash(name);
90 if(pp_defines[index] == ppp)
92 pp_defines[index] = ppp->next;
93 if(pp_defines[index])
94 pp_defines[index]->prev = NULL;
96 else
98 ppp->prev->next = ppp->next;
99 if(ppp->next)
100 ppp->next->prev = ppp->prev;
102 free(ppp);
105 void add_define(char *text)
107 int len;
108 char *cptr;
109 int index = pp_hash(current_define);
110 struct pp_entry *ppp;
111 if(pp_lookup(current_define) != NULL)
113 if(pedantic)
114 yywarning("Redefinition of %s", current_define);
115 del_define(current_define);
117 ppp = (struct pp_entry *)xmalloc(sizeof(struct pp_entry));
118 ppp->ident = current_define;
119 ppp->subst = xstrdup(text);
120 ppp->next = pp_defines[index];
121 pp_defines[index] = ppp;
122 if(ppp->next)
123 ppp->next->prev = ppp;
124 /* Strip trailing white space from subst text */
125 len = strlen(ppp->subst);
126 while(len && strchr(" \t\r\n", ppp->subst[len-1]))
128 ppp->subst[--len] = '\0';
130 /* Strip leading white space from subst text */
131 for(cptr = ppp->subst; *cptr && strchr(" \t\r", *cptr); cptr++)
133 if(ppp->subst != cptr)
134 memmove(ppp->subst, cptr, strlen(cptr)+1);
135 if(yydebug)
136 printf("Added (%s, %d) <%s> to <%s>\n", input_name, line_number, ppp->ident, ppp->subst);
139 void add_cmdline_define(char *set)
141 char *cpy = xstrdup(set); /* Because gcc passes a R/O string */
142 char *cptr = strchr(cpy, '=');
143 if(cptr)
144 *cptr = '\0';
145 set_define(cpy);
146 add_define(cptr ? cptr+1 : "");
147 free(cpy);
150 #if defined(_Windows) || defined(__MSDOS__)
151 #define INCLUDESEPARATOR ";"
152 #else
153 #define INCLUDESEPARATOR ":"
154 #endif
156 static char **includepath;
157 static int nincludepath = 0;
159 void add_include_path(char *path)
161 char *tok;
162 char *cpy = xstrdup(path);
164 tok = strtok(cpy, INCLUDESEPARATOR);
165 while(tok)
167 char *dir;
168 char *cptr;
169 if(strlen(tok) == 0)
170 continue;
171 dir = xstrdup(tok);
172 for(cptr = dir; *cptr; cptr++)
174 /* Convert to forward slash */
175 if(*cptr == '\\')
176 *cptr = '/';
178 /* Kill eventual trailing '/' */
179 if(*(cptr = dir + strlen(dir)-1) == '/')
180 *cptr = '\0';
182 /* Add to list */
183 nincludepath++;
184 includepath = (char **)xrealloc(includepath, nincludepath * sizeof(*includepath));
185 includepath[nincludepath-1] = dir;
186 tok = strtok(NULL, INCLUDESEPARATOR);
188 free(cpy);
191 FILE *open_include(const char *name, int search)
193 char *cpy = xstrdup(name);
194 char *cptr;
195 FILE *fp;
196 int i;
198 for(cptr = cpy; *cptr; cptr++)
200 /* kill double backslash */
201 if(*cptr == '\\' && *(cptr+1) == '\\')
202 memmove(cptr, cptr+1, strlen(cptr));
203 /* Convert to forward slash */
204 if(*cptr == '\\')
205 *cptr = '/';
208 if(search)
210 /* Search current dir and then -I path */
211 fp = fopen(name, "rt");
212 if(fp)
214 if(yydebug)
215 printf("Going to include <%s>\n", name);
216 free(cpy);
217 return fp;
220 /* Search -I path */
221 for(i = 0; i < nincludepath; i++)
223 char *path;
224 path = (char *)xmalloc(strlen(includepath[i]) + strlen(cpy) + 2);
225 strcpy(path, includepath[i]);
226 strcat(path, "/");
227 strcat(path, cpy);
228 fp = fopen(path, "rt");
229 if(fp && yydebug)
230 printf("Going to include <%s>\n", path);
231 free(path);
232 if(fp)
234 free(cpy);
235 return fp;
239 free(cpy);
240 return NULL;
243 void push_if(int truecase, int wastrue, int nevertrue)
245 if(ifstackidx >= MAXIFSTACK-1)
246 internal_error(__FILE__, __LINE__, "#if stack overflow");
247 ifstack[ifstackidx].current = truecase && !wastrue;
248 ifstack[ifstackidx].hasbeentrue = wastrue;
249 ifstack[ifstackidx].nevertrue = nevertrue;
250 if(nevertrue || !(truecase && !wastrue))
251 set_pp_ignore(1);
252 if(yydebug)
253 printf("push_if: %d %d %d (%d %d %d)\n",
254 truecase,
255 wastrue,
256 nevertrue,
257 ifstack[ifstackidx].current,
258 ifstack[ifstackidx].hasbeentrue,
259 ifstack[ifstackidx].nevertrue);
260 ifstackidx++;
263 int pop_if(void)
265 if(ifstackidx <= 0)
266 yyerror("#endif without #if|#ifdef|#ifndef (#if stack underflow)");
267 ifstackidx--;
268 if(yydebug)
269 printf("pop_if: %d %d %d\n",
270 ifstack[ifstackidx].current,
271 ifstack[ifstackidx].hasbeentrue,
272 ifstack[ifstackidx].nevertrue);
273 if(ifstack[ifstackidx].nevertrue || !ifstack[ifstackidx].current)
274 set_pp_ignore(0);
275 return ifstack[ifstackidx].hasbeentrue || ifstack[ifstackidx].current;
278 int isnevertrue_if(void)
280 return ifstackidx > 0 && ifstack[ifstackidx-1].nevertrue;