convert from svn repository: remove tags directory
[lttv.git] / trunk / verif / Spin / Src5.1.6 / pc_zpp.c
1 /***** spin: pc_zpp.c *****/
2
3 /* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories. */
4 /* All Rights Reserved. This software is for educational purposes only. */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code. Permission is given to distribute this code provided that */
7 /* this introductory message is not removed and no monies are exchanged. */
8 /* Software written by Gerard J. Holzmann. For tool documentation see: */
9 /* http://spinroot.com/ */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com */
11
12 /* pc_zpp.c is only used in the PC version of Spin */
13 /* it is included to avoid too great a reliance on an external cpp */
14
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <string.h>
18 #include <ctype.h>
19
20 #ifdef PC
21 enum cstate { PLAIN, IN_STRING, IN_QUOTE, S_COMM, COMMENT, E_COMM };
22
23 #define MAXNEST 32
24 #define MAXDEF 128
25 #define MAXLINE 2048
26 #define GENEROUS 8192
27
28 #define debug(x,y) if (verbose) printf(x,y)
29
30 static FILE *outpp /* = stdout */;
31
32 static int if_truth[MAXNEST];
33 static int printing[MAXNEST];
34 static int if_depth, nr_defs, verbose = 0;
35 static enum cstate state = PLAIN;
36 static char Out1[GENEROUS], Out2[GENEROUS];
37
38 static struct Defines {
39 int exists;
40 char *src, *trg;
41 } d[MAXDEF];
42
43 static int process(char *, int, char *);
44 static int zpp_do(char *);
45
46 extern char *emalloc(size_t); /* main.c */
47
48 static int
49 do_define(char *p)
50 { char *q, *r, *s;
51
52 for (q = p+strlen(p)-1; q > p; q--)
53 if (*q == '\n' || *q == '\t' || *q == ' ')
54 *q = '\0';
55 else
56 break;
57
58 q = p + strspn(p, " \t");
59 if (!(r = strchr(q, '\t')))
60 r = strchr(q, ' ');
61 if (!r) { s = ""; goto adddef; }
62 s = r + strspn(r, " \t");
63 *r = '\0';
64 if (strchr(q, '('))
65 { debug("zpp: #define with arguments %s\n", q);
66 return 0;
67 }
68 for (r = q+strlen(q)-1; r > q; r--)
69 if (*r == ' ' || *r == '\t')
70 *r = '\0';
71 else
72 break;
73 if (nr_defs >= MAXDEF)
74 { debug("zpp: too many #defines (max %d)\n", nr_defs);
75 return 0;
76 }
77 if (strcmp(q, s) != 0)
78 { int j;
79 adddef: for (j = 0; j < nr_defs; j++)
80 if (!strcmp(d[j].src, q))
81 d[j].exists = 0;
82 d[nr_defs].src = emalloc(strlen(q)+1);
83 d[nr_defs].trg = emalloc(strlen(s)+1);
84 strcpy(d[nr_defs].src, q);
85 strcpy(d[nr_defs].trg, s);
86 d[nr_defs++].exists = 1;
87 }
88 return 1;
89 }
90
91 static int
92 isvalid(int c)
93 {
94 return (isalnum(c) || c == '_');
95 }
96
97 static char *
98 apply(char *p0)
99 { char *out, *in1, *in2, *startat;
100 int i, j;
101
102 startat = in1 = Out2; strcpy(Out2, p0);
103 out = Out1; *out = '\0';
104
105 for (i = nr_defs-1; i >= 0; i--)
106 { if (!d[i].exists) continue;
107 j = (int) strlen(d[i].src);
108 more: in2 = strstr(startat, d[i].src);
109 if (!in2) /* no more matches */
110 { startat = in1;
111 continue;
112 }
113 if ((in2 == in1 || !isvalid(*(in2-1)))
114 && (in2+j == '\0' || !isvalid(*(in2+j))))
115 { *in2 = '\0';
116
117 if (strlen(in1)+strlen(d[i].trg)+strlen(in2+j) >= GENEROUS)
118 {
119 printf("spin: macro expansion overflow %s -> %s ?\n",
120 d[i].src, d[i].trg);
121 return in1;
122 }
123 strcat(out, in1);
124 strcat(out, d[i].trg);
125 strcat(out, in2+j);
126 if (in1 == Out2)
127 { startat = in1 = Out1;
128 out = Out2;
129 } else
130 { startat = in1 = Out2;
131 out = Out1;
132 }
133 *out = '\0';
134 } else
135 { startat = in2+1; /* +1 not +j.. */
136 }
137 goto more; /* recursive defines */
138 }
139 return in1;
140 }
141
142 static char *
143 do_common(char *p)
144 { char *q, *s;
145
146 q = p + strspn(p, " \t");
147 for (s = (q + strlen(q) - 1); s > q; s--)
148 if (*s == ' ' || *s == '\t' || *s == '\n')
149 *s = '\0';
150 else
151 break;
152 return q;
153 }
154
155 static int
156 do_undefine(char *p)
157 { int i; char *q = do_common(p);
158
159 for (i = 0; i < nr_defs; i++)
160 if (!strcmp(d[i].src, q))
161 d[i].exists = 0;
162 return 1;
163 }
164
165 static char *
166 check_ifdef(char *p)
167 { int i; char *q = do_common(p);
168
169 for (i = 0; i < nr_defs; i++)
170 if (d[i].exists
171 && !strcmp(d[i].src, q))
172 return d[i].trg;
173 return (char *) 0;
174 }
175
176 static int
177 do_ifdef(char *p)
178 {
179 if (++if_depth >= MAXNEST)
180 { debug("zpp: too deeply nested (max %d)\n", MAXNEST);
181 return 0;
182 }
183 if_truth[if_depth] = (check_ifdef(p) != (char *)0);
184 printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
185
186 return 1;
187 }
188
189 static int
190 do_ifndef(char *p)
191 {
192 if (++if_depth >= MAXNEST)
193 { debug("zpp: too deeply nested (max %d)\n", MAXNEST);
194 return 0;
195 }
196 if_truth[if_depth] = (check_ifdef(p) == (char *)0);
197 printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
198
199 return 1;
200 }
201
202 static int
203 is_simple(char *q)
204 {
205 if (!q) return 0;
206 if (strcmp(q, "0") == 0)
207 if_truth[if_depth] = 0;
208 else if (strcmp(q, "1") == 0)
209 if_truth[if_depth] = 1;
210 else
211 return 0;
212 return 1;
213 }
214
215 static int
216 do_if(char *p)
217 { char *q = do_common(p);
218 if (++if_depth >= MAXNEST)
219 { debug("zpp: too deeply nested (max %d)\n", MAXNEST);
220 return 0;
221 }
222 if (!is_simple(q)
223 && !is_simple(check_ifdef(q)))
224 { debug("zpp: cannot handle #if %s\n", q);
225 return 0;
226 }
227 printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
228
229 return 1;
230 }
231
232 static int
233 do_else(char *unused)
234 {
235 if_truth[if_depth] = 1-if_truth[if_depth];
236 printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
237
238 return 1;
239 }
240
241 static int
242 do_endif(char *p)
243 {
244 if (--if_depth < 0)
245 { debug("zpp: unbalanced #endif %s\n", p);
246 return 0;
247 }
248 return 1;
249 }
250
251 static int
252 do_include(char *p)
253 { char *r, *q;
254
255 q = strchr(p, '<');
256 r = strrchr(p, '>');
257 if (!q || !r)
258 { q = strchr (p, '\"');
259 r = strrchr(p, '\"');
260 if (!q || !r || q == r)
261 { debug("zpp: malformed #include %s", p);
262 return 0;
263 } }
264 *r = '\0';
265 return zpp_do(++q);
266 }
267
268 static int
269 in_comment(char *p)
270 { char *q = p;
271
272 for (q = p; *q != '\n' && *q != '\0'; q++)
273 switch (state) {
274 case PLAIN:
275 switch (*q) {
276 case '"': state = IN_STRING; break;
277 case '\'': state = IN_QUOTE; break;
278 case '/': state = S_COMM; break;
279 case '\\': q++; break;
280 }
281 break;
282 case IN_STRING:
283 if (*q == '"') state = PLAIN;
284 else if (*q == '\\') q++;
285 break;
286 case IN_QUOTE:
287 if (*q == '\'') state = PLAIN;
288 else if (*q == '\\') q++;
289 break;
290 case S_COMM:
291 if (*q == '*')
292 { *(q-1) = *q = ' ';
293 state = COMMENT;
294 } else if (*q != '/')
295 state = PLAIN;
296 break;
297 case COMMENT:
298 state = (*q == '*') ? E_COMM: COMMENT;
299 *q = ' ';
300 break;
301 case E_COMM:
302 if (*q == '/')
303 state = PLAIN;
304 else if (*q != '*')
305 state = COMMENT;
306 *q = ' ';
307 break;
308 }
309 if (state == S_COMM) state = PLAIN;
310 else if (state == E_COMM) state = COMMENT;
311 return (state == COMMENT);
312 }
313
314 static int
315 zpp_do(char *fnm)
316 { char buf[2048], buf2[MAXLINE], *p; int n, on;
317 FILE *inp; int lno = 0, nw_lno = 0;
318
319 if ((inp = fopen(fnm, "r")) == NULL)
320 { fprintf(stdout, "spin: error, '%s': No such file\n", fnm);
321 return 0; /* 4.1.2 was stderr */
322 }
323 printing[0] = if_truth[0] = 1;
324 fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm);
325 while (fgets(buf, MAXLINE, inp))
326 { lno++; n = (int) strlen(buf);
327 on = 0; nw_lno = 0;
328 while (n > 2 && buf[n-2] == '\\')
329 { buf[n-2] = '\0';
330 feedme: if (!fgets(buf2, MAXLINE, inp))
331 { debug("zpp: unexpected EOF ln %d\n", lno);
332 return 0; /* switch to cpp */
333 }
334 lno++;
335 if (n + (int) strlen(buf2) >= 2048)
336 { debug("zpp: line %d too long\n", lno);
337 return 0;
338 }
339 strcat(buf, buf2);
340 n = (int) strlen(buf);
341 }
342 if (in_comment(&buf[on]))
343 { buf[n-1] = '\0'; /* eat newline */
344 on = n-1; nw_lno = 1;
345 goto feedme;
346 }
347 p = buf + strspn(buf, " \t");
348 if (nw_lno && *p != '#')
349 fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
350 if (*p == '#')
351 { if (!process(p+1, lno+1, fnm))
352 return 0;
353 } else if (printing[if_depth])
354 fprintf(outpp, "%s", apply(buf));
355 }
356 fclose(inp);
357 return 1;
358 }
359
360 int
361 try_zpp(char *fnm, char *onm)
362 { int r;
363 if ((outpp = fopen(onm, "w")) == NULL)
364 return 0;
365 r = zpp_do(fnm);
366 fclose(outpp);
367 return r; /* 1 = ok; 0 = use cpp */
368 }
369
370 static struct Directives {
371 int len;
372 char *directive;
373 int (*handler)(char *);
374 int interp;
375 } s[] = {
376 { 6, "define", do_define, 1 },
377 { 4, "else", do_else, 0 },
378 { 5, "endif", do_endif, 0 },
379 { 5, "ifdef", do_ifdef, 0 },
380 { 6, "ifndef", do_ifndef, 0 },
381 { 2, "if", do_if, 0 },
382 { 7, "include", do_include, 1 },
383 { 8, "undefine", do_undefine, 1 },
384 };
385
386 static int
387 process(char *q, int lno, char *fnm)
388 { char *p; int i, r;
389
390 for (p = q; *p; p++)
391 if (*p != ' ' && *p != '\t')
392 break;
393 for (i = 0; i < (int) (sizeof(s)/sizeof(struct Directives)); i++)
394 if (!strncmp(s[i].directive, p, s[i].len))
395 { if (s[i].interp
396 && !printing[if_depth])
397 return 1;
398 fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
399 r = s[i].handler(p + s[i].len);
400 if (i == 6) /* include */
401 fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
402 return r;
403 }
404
405 debug("zpp: unrecognized directive: %s", p);
406 return 0;
407 }
408 #endif
This page took 0.037624 seconds and 4 git commands to generate.