123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395 |
- /***** spin: pc_zpp.c *****/
- /* Copyright (c) 1997-2000 by Lucent Technologies - Bell Laboratories */
- /* All Rights Reserved. This software is for educational purposes only. */
- /* Permission is given to distribute this code provided that this intro- */
- /* ductory message is not removed and no monies are exchanged. */
- /* No guarantee is expressed or implied by the distribution of this code. */
- /* Software written by Gerard J. Holzmann, gerard@research.bell-labs.com */
- /* pc_zpp.c is only used in the PC version of Spin, to avoid too great a */
- /* reliance on the cpp command. */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #ifdef PC
- enum cstate { PLAIN, IN_STRING, IN_QUOTE, S_COMM, COMMENT, E_COMM };
- #define MAXNEST 32
- #define MAXDEF 128
- #define MAXLINE 512
- #define debug(x,y) if (verbose) printf(x,y)
- static FILE *outpp = stdout;
- static int if_truth[MAXNEST];
- static int printing[MAXNEST];
- static int if_depth, nr_defs, verbose = 0;
- static enum cstate state = PLAIN;
- static char Out1[4096], Out2[4096];
- static struct Defines {
- int exists;
- char *src, *trg;
- } d[MAXDEF];
- static int process(char *, int, char *);
- static int zpp_do(char *);
- static int
- do_define(char *p)
- { char *q, *r, *s;
- for (q = p+strlen(p)-1; q > p; q--)
- if (*q == '\n' || *q == '\t' || *q == ' ')
- *q = '\0';
- else
- break;
- q = p + strspn(p, " \t");
- if (!(r = strchr(q, '\t')))
- r = strchr(q, ' ');
- if (!r) { s = ""; goto adddef; }
- s = r + strspn(r, " \t");
- *r = '\0';
- if (strchr(q, '('))
- { debug("zpp: #define with arguments %s\n", q);
- return 0;
- }
- for (r = q+strlen(q)-1; r > q; r--)
- if (*r == ' ' || *r == '\t')
- *r = '\0';
- else
- break;
- if (nr_defs >= MAXDEF)
- { debug("zpp: too many #defines (max %d)\n", nr_defs);
- return 0;
- }
- if (strcmp(q, s) != 0)
- { int j;
- adddef: for (j = 0; j < nr_defs; j++)
- if (!strcmp(d[j].src, q))
- d[j].exists = 0;
- d[nr_defs].src = malloc(strlen(q)+1);
- d[nr_defs].trg = malloc(strlen(s)+1);
- strcpy(d[nr_defs].src, q);
- strcpy(d[nr_defs].trg, s);
- d[nr_defs++].exists = 1;
- }
- return 1;
- }
- static int
- isvalid(int c)
- {
- return (isalnum(c) || c == '_');
- }
- static char *
- apply(char *p0)
- { char *out, *in1, *in2, *startat;
- int i, j;
- startat = in1 = Out2; strcpy(Out2, p0);
- out = Out1; *out = '\0';
- for (i = nr_defs-1; i >= 0; i--)
- { if (!d[i].exists) continue;
- j = strlen(d[i].src);
- more: in2 = strstr(startat, d[i].src);
- if (!in2) /* no more matches */
- { startat = in1;
- continue;
- }
- if ((in2 == in1 || !isvalid(*(in2-1)))
- && (in2+j == '\0' || !isvalid(*(in2+j))))
- { *in2 = '\0';
- strcat(out, in1);
- strcat(out, d[i].trg);
- strcat(out, in2+j);
- if (in1 == Out2)
- { startat = in1 = Out1;
- out = Out2;
- } else
- { startat = in1 = Out2;
- out = Out1;
- }
- *out = '\0';
- } else
- { startat = in2+1; /* +1 not +j.. */
- }
- goto more; /* recursive defines */
- }
- return in1;
- }
- static char *
- do_common(char *p)
- { char *q, *s;
- q = p + strspn(p, " \t");
- for (s = (q + strlen(q) - 1); s > q; s--)
- if (*s == ' ' || *s == '\t' || *s == '\n')
- *s = '\0';
- else
- break;
- return q;
- }
- static int
- do_undefine(char *p)
- { int i; char *q = do_common(p);
- for (i = 0; i < nr_defs; i++)
- if (!strcmp(d[i].src, q))
- d[i].exists = 0;
- return 1;
- }
- static char *
- check_ifdef(char *p)
- { int i; char *q = do_common(p);
- for (i = 0; i < nr_defs; i++)
- if (d[i].exists
- && !strcmp(d[i].src, q))
- return d[i].trg;
- return (char *) 0;
- }
- static int
- do_ifdef(char *p)
- {
- if (++if_depth >= MAXNEST)
- { debug("zpp: too deeply nested (max %d)\n", MAXNEST);
- return 0;
- }
- if_truth[if_depth] = (check_ifdef(p) != (char *)0);
- printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
- return 1;
- }
- static int
- do_ifndef(char *p)
- {
- if (++if_depth >= MAXNEST)
- { debug("zpp: too deeply nested (max %d)\n", MAXNEST);
- return 0;
- }
- if_truth[if_depth] = (check_ifdef(p) == (char *)0);
- printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
- return 1;
- }
- static int
- is_simple(char *q)
- {
- if (!q) return 0;
- if (strcmp(q, "0") == 0)
- if_truth[if_depth] = 0;
- else if (strcmp(q, "1") == 0)
- if_truth[if_depth] = 1;
- else
- return 0;
- return 1;
- }
- static int
- do_if(char *p)
- { char *q = do_common(p);
- if (++if_depth >= MAXNEST)
- { debug("zpp: too deeply nested (max %d)\n", MAXNEST);
- return 0;
- }
- if (!is_simple(q)
- && !is_simple(check_ifdef(q)))
- { debug("zpp: cannot handle #if %s\n", q);
- return 0;
- }
- printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
- return 1;
- }
- static int
- do_else(char *p)
- {
- if_truth[if_depth] = 1-if_truth[if_depth];
- printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
- return 1;
- }
- static int
- do_endif(char *p)
- {
- if (--if_depth < 0)
- { debug("zpp: unbalanced #endif %s\n", p);
- return 0;
- }
- return 1;
- }
- static int
- do_include(char *p)
- { char *r, *q;
- q = strchr(p, '<');
- r = strrchr(p, '>');
- if (!q || !r)
- { q = strchr (p, '\"');
- r = strrchr(p, '\"');
- if (!q || !r || q == r)
- { debug("zpp: malformed #include %s", p);
- return 0;
- } }
- *r = '\0';
- return zpp_do(++q);
- }
- static int
- in_comment(char *p)
- { char *q = p;
- for (q = p; *q != '\n' && *q != '\0'; q++)
- switch (state) {
- case PLAIN:
- switch (*q) {
- case '"': state = IN_STRING; break;
- case '\'': state = IN_QUOTE; break;
- case '/': state = S_COMM; break;
- case '\\': q++; break;
- }
- break;
- case IN_STRING:
- if (*q == '"') state = PLAIN;
- else if (*q == '\\') q++;
- break;
- case IN_QUOTE:
- if (*q == '\'') state = PLAIN;
- else if (*q == '\\') q++;
- break;
- case S_COMM:
- if (*q == '*')
- { *(q-1) = *q = ' ';
- state = COMMENT;
- } else if (*q != '/')
- state = PLAIN;
- break;
- case COMMENT:
- state = (*q == '*') ? E_COMM: COMMENT;
- *q = ' ';
- break;
- case E_COMM:
- if (*q == '/')
- state = PLAIN;
- else if (*q != '*')
- state = COMMENT;
- *q = ' ';
- break;
- }
- if (state == S_COMM) state = PLAIN;
- else if (state == E_COMM) state = COMMENT;
- return (state == COMMENT);
- }
- static int
- zpp_do(char *fnm)
- { char buf[2048], buf2[MAXLINE], *p; int n, on;
- FILE *inp; int lno = 0, nw_lno = 0;
- if ((inp = fopen(fnm, "r")) == NULL)
- { debug("error: cannot open %s\n", fnm);
- return 0;
- }
- printing[0] = if_truth[0] = 1;
- fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm);
- while (fgets(buf, MAXLINE, inp))
- { lno++; n = strlen(buf);
- on = 0; nw_lno = 0;
- while (n > 2 && buf[n-2] == '\\')
- { buf[n-2] = '\0';
- feedme: if (!fgets(buf2, MAXLINE, inp))
- { debug("zpp: unexpected EOF ln %d\n", lno);
- return 0; /* switch to cpp */
- }
- lno++;
- if (n + (int) strlen(buf2) >= 2048)
- { debug("zpp: line %d too long\n", lno);
- return 0;
- }
- strcat(buf, buf2);
- n = strlen(buf);
- }
- if (in_comment(&buf[on]))
- { buf[n-1] = '\0'; /* eat newline */
- on = n-1; nw_lno = 1;
- goto feedme;
- }
- p = buf + strspn(buf, " \t");
- if (nw_lno && *p != '#')
- fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
- if (*p == '#')
- { if (!process(p+1, lno+1, fnm))
- return 0;
- } else if (printing[if_depth])
- fprintf(outpp, "%s", apply(buf));
- }
- fclose(inp);
- return 1;
- }
- int
- try_zpp(char *fnm, char *onm)
- { int r;
- if ((outpp = fopen(onm, "w")) == NULL)
- return 0;
- r = zpp_do(fnm);
- fclose(outpp);
- return r; /* 1 = ok; 0 = use cpp */
- }
- static struct Directives {
- int len;
- char *directive;
- int (*handler)(char *);
- int interp;
- } s[] = {
- { 6, "define", do_define, 1 },
- { 4, "else", do_else, 0 },
- { 5, "endif", do_endif, 0 },
- { 2, "if", do_if, 0 },
- { 5, "ifdef", do_ifdef, 0 },
- { 6, "ifndef", do_ifndef, 0 },
- { 7, "include", do_include, 1 },
- { 8, "undefine", do_undefine, 1 },
- };
- static int
- process(char *q, int lno, char *fnm)
- { char *p; int i, r;
- for (p = q; *p; p++)
- if (*p != ' ' && *p != '\t')
- break;
- for (i = 0; i < sizeof(s)/sizeof(struct Directives); i++)
- if (!strncmp(s[i].directive, p, s[i].len))
- { if (s[i].interp
- && !printing[if_depth])
- return 1;
- fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
- r = s[i].handler(p + s[i].len);
- if (i == 6) /* include */
- fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
- return r;
- }
-
- debug("zpp: unrecognized directive: %s", p);
- return 0;
- }
- #endif
|