1 /***** spin: pc_zpp.c *****/
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 */
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 */
21 enum cstate
{ PLAIN
, IN_STRING
, IN_QUOTE
, S_COMM
, COMMENT
, E_COMM
};
28 #define debug(x,y) if (verbose) printf(x,y)
30 static FILE *outpp
/* = stdout */;
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
];
38 static struct Defines
{
43 static int process(char *, int, char *);
44 static int zpp_do(char *);
46 extern char *emalloc(size_t); /* main.c */
52 for (q
= p
+strlen(p
)-1; q
> p
; q
--)
53 if (*q
== '\n' || *q
== '\t' || *q
== ' ')
58 q
= p
+ strspn(p
, " \t");
59 if (!(r
= strchr(q
, '\t')))
61 if (!r
) { s
= ""; goto adddef
; }
62 s
= r
+ strspn(r
, " \t");
65 { debug("zpp: #define with arguments %s\n", q
);
68 for (r
= q
+strlen(q
)-1; r
> q
; r
--)
69 if (*r
== ' ' || *r
== '\t')
73 if (nr_defs
>= MAXDEF
)
74 { debug("zpp: too many #defines (max %d)\n", nr_defs
);
77 if (strcmp(q
, s
) != 0)
79 adddef
: for (j
= 0; j
< nr_defs
; j
++)
80 if (!strcmp(d
[j
].src
, q
))
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;
94 return (isalnum(c
) || c
== '_');
99 { char *out
, *in1
, *in2
, *startat
;
102 startat
= in1
= Out2
; strcpy(Out2
, p0
);
103 out
= Out1
; *out
= '\0';
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 */
113 if ((in2
== in1
|| !isvalid(*(in2
-1)))
114 && (in2
+j
== '\0' || !isvalid(*(in2
+j
))))
117 if (strlen(in1
)+strlen(d
[i
].trg
)+strlen(in2
+j
) >= GENEROUS
)
119 printf("spin: macro expansion overflow %s -> %s ?\n",
124 strcat(out
, d
[i
].trg
);
127 { startat
= in1
= Out1
;
130 { startat
= in1
= Out2
;
135 { startat
= in2
+1; /* +1 not +j.. */
137 goto more
; /* recursive defines */
146 q
= p
+ strspn(p
, " \t");
147 for (s
= (q
+ strlen(q
) - 1); s
> q
; s
--)
148 if (*s
== ' ' || *s
== '\t' || *s
== '\n')
157 { int i
; char *q
= do_common(p
);
159 for (i
= 0; i
< nr_defs
; i
++)
160 if (!strcmp(d
[i
].src
, q
))
167 { int i
; char *q
= do_common(p
);
169 for (i
= 0; i
< nr_defs
; i
++)
171 && !strcmp(d
[i
].src
, q
))
179 if (++if_depth
>= MAXNEST
)
180 { debug("zpp: too deeply nested (max %d)\n", MAXNEST
);
183 if_truth
[if_depth
] = (check_ifdef(p
) != (char *)0);
184 printing
[if_depth
] = printing
[if_depth
-1]&&if_truth
[if_depth
];
192 if (++if_depth
>= MAXNEST
)
193 { debug("zpp: too deeply nested (max %d)\n", MAXNEST
);
196 if_truth
[if_depth
] = (check_ifdef(p
) == (char *)0);
197 printing
[if_depth
] = printing
[if_depth
-1]&&if_truth
[if_depth
];
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;
217 { char *q
= do_common(p
);
218 if (++if_depth
>= MAXNEST
)
219 { debug("zpp: too deeply nested (max %d)\n", MAXNEST
);
223 && !is_simple(check_ifdef(q
)))
224 { debug("zpp: cannot handle #if %s\n", q
);
227 printing
[if_depth
] = printing
[if_depth
-1]&&if_truth
[if_depth
];
233 do_else(char *unused
)
235 if_truth
[if_depth
] = 1-if_truth
[if_depth
];
236 printing
[if_depth
] = printing
[if_depth
-1]&&if_truth
[if_depth
];
245 { debug("zpp: unbalanced #endif %s\n", p
);
258 { q
= strchr (p
, '\"');
259 r
= strrchr(p
, '\"');
260 if (!q
|| !r
|| q
== r
)
261 { debug("zpp: malformed #include %s", p
);
272 for (q
= p
; *q
!= '\n' && *q
!= '\0'; q
++)
276 case '"': state
= IN_STRING
; break;
277 case '\'': state
= IN_QUOTE
; break;
278 case '/': state
= S_COMM
; break;
279 case '\\': q
++; break;
283 if (*q
== '"') state
= PLAIN
;
284 else if (*q
== '\\') q
++;
287 if (*q
== '\'') state
= PLAIN
;
288 else if (*q
== '\\') q
++;
294 } else if (*q
!= '/')
298 state
= (*q
== '*') ? E_COMM
: COMMENT
;
309 if (state
== S_COMM
) state
= PLAIN
;
310 else if (state
== E_COMM
) state
= COMMENT
;
311 return (state
== COMMENT
);
316 { char buf
[2048], buf2
[MAXLINE
], *p
; int n
, on
;
317 FILE *inp
; int lno
= 0, nw_lno
= 0;
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 */
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
);
328 while (n
> 2 && buf
[n
-2] == '\\')
330 feedme
: if (!fgets(buf2
, MAXLINE
, inp
))
331 { debug("zpp: unexpected EOF ln %d\n", lno
);
332 return 0; /* switch to cpp */
335 if (n
+ (int) strlen(buf2
) >= 2048)
336 { debug("zpp: line %d too long\n", lno
);
340 n
= (int) strlen(buf
);
342 if (in_comment(&buf
[on
]))
343 { buf
[n
-1] = '\0'; /* eat newline */
344 on
= n
-1; nw_lno
= 1;
347 p
= buf
+ strspn(buf
, " \t");
348 if (nw_lno
&& *p
!= '#')
349 fprintf(outpp
, "#line %d \"%s\"\n", lno
, fnm
);
351 { if (!process(p
+1, lno
+1, fnm
))
353 } else if (printing
[if_depth
])
354 fprintf(outpp
, "%s", apply(buf
));
361 try_zpp(char *fnm
, char *onm
)
363 if ((outpp
= fopen(onm
, "w")) == NULL
)
367 return r
; /* 1 = ok; 0 = use cpp */
370 static struct Directives
{
373 int (*handler
)(char *);
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 },
387 process(char *q
, int lno
, char *fnm
)
391 if (*p
!= ' ' && *p
!= '\t')
393 for (i
= 0; i
< (int) (sizeof(s
)/sizeof(struct Directives
)); i
++)
394 if (!strncmp(s
[i
].directive
, p
, s
[i
].len
))
396 && !printing
[if_depth
])
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
);
405 debug("zpp: unrecognized directive: %s", p
);
This page took 0.050342 seconds and 5 git commands to generate.