xref: /plan9/sys/src/cmd/spin/pc_zpp.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier /***** spin: pc_zpp.c *****/
27dd7cddfSDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1997-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11312a1df1SDavid du Colombier 
12312a1df1SDavid du Colombier /* pc_zpp.c is only used in the PC version of Spin                        */
13312a1df1SDavid du Colombier /* it is included to avoid too great a reliance on an external cpp        */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier #include <stdlib.h>
167dd7cddfSDavid du Colombier #include <stdio.h>
177dd7cddfSDavid du Colombier #include <string.h>
187dd7cddfSDavid du Colombier #include <ctype.h>
19*00d97012SDavid du Colombier #include "spin.h"
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier #ifdef PC
227dd7cddfSDavid du Colombier enum cstate { PLAIN, IN_STRING, IN_QUOTE, S_COMM, COMMENT, E_COMM };
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier #define MAXNEST	32
257dd7cddfSDavid du Colombier #define MAXDEF	128
26*00d97012SDavid du Colombier #define MAXLINE	2048
27*00d97012SDavid du Colombier #define GENEROUS 8192
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier #define debug(x,y)	if (verbose) printf(x,y)
307dd7cddfSDavid du Colombier 
31312a1df1SDavid du Colombier static FILE *outpp /* = stdout */;
327dd7cddfSDavid du Colombier 
337dd7cddfSDavid du Colombier static int if_truth[MAXNEST];
347dd7cddfSDavid du Colombier static int printing[MAXNEST];
357dd7cddfSDavid du Colombier static int if_depth, nr_defs, verbose = 0;
367dd7cddfSDavid du Colombier static enum cstate state = PLAIN;
37312a1df1SDavid du Colombier static char Out1[GENEROUS], Out2[GENEROUS];
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier static struct Defines {
407dd7cddfSDavid du Colombier 	int exists;
417dd7cddfSDavid du Colombier 	char *src, *trg;
427dd7cddfSDavid du Colombier } d[MAXDEF];
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier static int process(char *, int, char *);
457dd7cddfSDavid du Colombier static int zpp_do(char *);
467dd7cddfSDavid du Colombier 
47*00d97012SDavid du Colombier extern char *emalloc(size_t);	/* main.c */
48312a1df1SDavid du Colombier 
497dd7cddfSDavid du Colombier static int
do_define(char * p)507dd7cddfSDavid du Colombier do_define(char *p)
517dd7cddfSDavid du Colombier {	char *q, *r, *s;
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier 	for (q = p+strlen(p)-1; q > p; q--)
547dd7cddfSDavid du Colombier 		if (*q == '\n' || *q == '\t' || *q == ' ')
557dd7cddfSDavid du Colombier 			*q = '\0';
567dd7cddfSDavid du Colombier 		else
577dd7cddfSDavid du Colombier 			break;
587dd7cddfSDavid du Colombier 
597dd7cddfSDavid du Colombier 	q = p + strspn(p, " \t");
607dd7cddfSDavid du Colombier 	if (!(r = strchr(q, '\t')))
617dd7cddfSDavid du Colombier 		r = strchr(q, ' ');
627dd7cddfSDavid du Colombier 	if (!r) { s = ""; goto adddef; }
637dd7cddfSDavid du Colombier 	s = r + strspn(r, " \t");
647dd7cddfSDavid du Colombier 	*r = '\0';
657dd7cddfSDavid du Colombier 	if (strchr(q, '('))
667dd7cddfSDavid du Colombier 	{	debug("zpp: #define with arguments %s\n", q);
677dd7cddfSDavid du Colombier 		return 0;
687dd7cddfSDavid du Colombier 	}
697dd7cddfSDavid du Colombier 	for (r = q+strlen(q)-1; r > q; r--)
707dd7cddfSDavid du Colombier 		if (*r == ' ' || *r == '\t')
717dd7cddfSDavid du Colombier 			*r = '\0';
727dd7cddfSDavid du Colombier 		else
737dd7cddfSDavid du Colombier 			break;
747dd7cddfSDavid du Colombier 	if (nr_defs >= MAXDEF)
757dd7cddfSDavid du Colombier 	{	debug("zpp: too many #defines (max %d)\n", nr_defs);
767dd7cddfSDavid du Colombier 		return 0;
777dd7cddfSDavid du Colombier 	}
787dd7cddfSDavid du Colombier 	if (strcmp(q, s) != 0)
797dd7cddfSDavid du Colombier 	{	int j;
807dd7cddfSDavid du Colombier adddef:		for (j = 0; j < nr_defs; j++)
817dd7cddfSDavid du Colombier 			if (!strcmp(d[j].src, q))
827dd7cddfSDavid du Colombier 				d[j].exists = 0;
83312a1df1SDavid du Colombier 		d[nr_defs].src = emalloc(strlen(q)+1);
84312a1df1SDavid du Colombier 		d[nr_defs].trg = emalloc(strlen(s)+1);
857dd7cddfSDavid du Colombier 		strcpy(d[nr_defs].src, q);
867dd7cddfSDavid du Colombier 		strcpy(d[nr_defs].trg, s);
877dd7cddfSDavid du Colombier 		d[nr_defs++].exists = 1;
887dd7cddfSDavid du Colombier 	}
897dd7cddfSDavid du Colombier 	return 1;
907dd7cddfSDavid du Colombier }
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier static int
isvalid(int c)937dd7cddfSDavid du Colombier isvalid(int c)
947dd7cddfSDavid du Colombier {
957dd7cddfSDavid du Colombier 	return (isalnum(c) || c == '_');
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier static char *
apply(char * p0)997dd7cddfSDavid du Colombier apply(char *p0)
1007dd7cddfSDavid du Colombier {	char *out, *in1, *in2, *startat;
1017dd7cddfSDavid du Colombier 	int i, j;
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier 	startat = in1 = Out2; strcpy(Out2, p0);
1047dd7cddfSDavid du Colombier 	out = Out1; *out = '\0';
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier 	for (i = nr_defs-1; i >= 0; i--)
1077dd7cddfSDavid du Colombier 	{	if (!d[i].exists) continue;
108312a1df1SDavid du Colombier 		j = (int) strlen(d[i].src);
1097dd7cddfSDavid du Colombier more:		in2 = strstr(startat, d[i].src);
1107dd7cddfSDavid du Colombier 		if (!in2)	/* no more matches */
1117dd7cddfSDavid du Colombier 		{	startat = in1;
1127dd7cddfSDavid du Colombier 			continue;
1137dd7cddfSDavid du Colombier 		}
1147dd7cddfSDavid du Colombier 		if ((in2 == in1 || !isvalid(*(in2-1)))
1157dd7cddfSDavid du Colombier 		&&  (in2+j == '\0' || !isvalid(*(in2+j))))
1167dd7cddfSDavid du Colombier 		{	*in2 = '\0';
117312a1df1SDavid du Colombier 
118312a1df1SDavid du Colombier 			if (strlen(in1)+strlen(d[i].trg)+strlen(in2+j) >= GENEROUS)
119312a1df1SDavid du Colombier 			{
120*00d97012SDavid du Colombier 				printf("spin: macro expansion overflow %s -> %s ?\n",
121312a1df1SDavid du Colombier 					d[i].src, d[i].trg);
122312a1df1SDavid du Colombier 				return in1;
123312a1df1SDavid du Colombier 			}
1247dd7cddfSDavid du Colombier 			strcat(out, in1);
1257dd7cddfSDavid du Colombier 			strcat(out, d[i].trg);
1267dd7cddfSDavid du Colombier 			strcat(out, in2+j);
1277dd7cddfSDavid du Colombier 			if (in1 == Out2)
1287dd7cddfSDavid du Colombier 			{	startat = in1 = Out1;
1297dd7cddfSDavid du Colombier 				out = Out2;
1307dd7cddfSDavid du Colombier 			} else
1317dd7cddfSDavid du Colombier 			{	startat = in1 = Out2;
1327dd7cddfSDavid du Colombier 				out = Out1;
1337dd7cddfSDavid du Colombier 			}
1347dd7cddfSDavid du Colombier 			*out = '\0';
1357dd7cddfSDavid du Colombier 		} else
1367dd7cddfSDavid du Colombier 		{	startat = in2+1;	/* +1 not +j.. */
1377dd7cddfSDavid du Colombier 		}
1387dd7cddfSDavid du Colombier 		goto more; /* recursive defines */
1397dd7cddfSDavid du Colombier 	}
1407dd7cddfSDavid du Colombier 	return in1;
1417dd7cddfSDavid du Colombier }
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier static char *
do_common(char * p)1447dd7cddfSDavid du Colombier do_common(char *p)
1457dd7cddfSDavid du Colombier {	char *q, *s;
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier 	q = p + strspn(p, " \t");
1487dd7cddfSDavid du Colombier 	for (s = (q + strlen(q) - 1); s > q; s--)
1497dd7cddfSDavid du Colombier 		if (*s == ' ' || *s == '\t' || *s == '\n')
1507dd7cddfSDavid du Colombier 			*s = '\0';
1517dd7cddfSDavid du Colombier 		else
1527dd7cddfSDavid du Colombier 			break;
1537dd7cddfSDavid du Colombier 	return q;
1547dd7cddfSDavid du Colombier }
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier static int
do_undefine(char * p)1577dd7cddfSDavid du Colombier do_undefine(char *p)
1587dd7cddfSDavid du Colombier {	int i; char *q = do_common(p);
1597dd7cddfSDavid du Colombier 
1607dd7cddfSDavid du Colombier 	for (i = 0; i < nr_defs; i++)
1617dd7cddfSDavid du Colombier 		if (!strcmp(d[i].src, q))
1627dd7cddfSDavid du Colombier 			d[i].exists = 0;
1637dd7cddfSDavid du Colombier 	return 1;
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier static char *
check_ifdef(char * p)1677dd7cddfSDavid du Colombier check_ifdef(char *p)
1687dd7cddfSDavid du Colombier {	int i; char *q = do_common(p);
1697dd7cddfSDavid du Colombier 
1707dd7cddfSDavid du Colombier 	for (i = 0; i < nr_defs; i++)
1717dd7cddfSDavid du Colombier 		if (d[i].exists
1727dd7cddfSDavid du Colombier 		&&  !strcmp(d[i].src, q))
1737dd7cddfSDavid du Colombier 			return d[i].trg;
1747dd7cddfSDavid du Colombier 	return (char *) 0;
1757dd7cddfSDavid du Colombier }
1767dd7cddfSDavid du Colombier 
1777dd7cddfSDavid du Colombier static int
do_ifdef(char * p)1787dd7cddfSDavid du Colombier do_ifdef(char *p)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier 	if (++if_depth >= MAXNEST)
1817dd7cddfSDavid du Colombier 	{	debug("zpp: too deeply nested (max %d)\n", MAXNEST);
1827dd7cddfSDavid du Colombier 		return 0;
1837dd7cddfSDavid du Colombier 	}
1847dd7cddfSDavid du Colombier 	if_truth[if_depth] = (check_ifdef(p) != (char *)0);
1857dd7cddfSDavid du Colombier 	printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	return 1;
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier static int
do_ifndef(char * p)1917dd7cddfSDavid du Colombier do_ifndef(char *p)
1927dd7cddfSDavid du Colombier {
1937dd7cddfSDavid du Colombier 	if (++if_depth >= MAXNEST)
1947dd7cddfSDavid du Colombier 	{	debug("zpp: too deeply nested (max %d)\n", MAXNEST);
1957dd7cddfSDavid du Colombier 		return 0;
1967dd7cddfSDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 	if_truth[if_depth] = (check_ifdef(p) == (char *)0);
1987dd7cddfSDavid du Colombier 	printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier 	return 1;
2017dd7cddfSDavid du Colombier }
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier static int
is_simple(char * q)2047dd7cddfSDavid du Colombier is_simple(char *q)
2057dd7cddfSDavid du Colombier {
2067dd7cddfSDavid du Colombier 	if (!q) return 0;
2077dd7cddfSDavid du Colombier 	if (strcmp(q, "0") == 0)
2087dd7cddfSDavid du Colombier 		if_truth[if_depth] = 0;
2097dd7cddfSDavid du Colombier 	else if (strcmp(q, "1") == 0)
2107dd7cddfSDavid du Colombier 		if_truth[if_depth] = 1;
2117dd7cddfSDavid du Colombier 	else
2127dd7cddfSDavid du Colombier 		return 0;
2137dd7cddfSDavid du Colombier 	return 1;
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier static int
do_if(char * p)2177dd7cddfSDavid du Colombier do_if(char *p)
2187dd7cddfSDavid du Colombier {	char *q = do_common(p);
2197dd7cddfSDavid du Colombier 	if (++if_depth >= MAXNEST)
2207dd7cddfSDavid du Colombier 	{	debug("zpp: too deeply nested (max %d)\n", MAXNEST);
2217dd7cddfSDavid du Colombier 		return 0;
2227dd7cddfSDavid du Colombier 	}
2237dd7cddfSDavid du Colombier 	if (!is_simple(q)
2247dd7cddfSDavid du Colombier 	&&  !is_simple(check_ifdef(q)))
2257dd7cddfSDavid du Colombier 	{	debug("zpp: cannot handle #if %s\n", q);
2267dd7cddfSDavid du Colombier 		return 0;
2277dd7cddfSDavid du Colombier 	}
2287dd7cddfSDavid du Colombier 	printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
2297dd7cddfSDavid du Colombier 
2307dd7cddfSDavid du Colombier 	return 1;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier static int
do_else(char * p)234*00d97012SDavid du Colombier do_else(char *p)
2357dd7cddfSDavid du Colombier {
236*00d97012SDavid du Colombier 	debug("zpp: do_else %s", p);
2377dd7cddfSDavid du Colombier 	if_truth[if_depth] = 1-if_truth[if_depth];
2387dd7cddfSDavid du Colombier 	printing[if_depth] = printing[if_depth-1]&&if_truth[if_depth];
2397dd7cddfSDavid du Colombier 
2407dd7cddfSDavid du Colombier 	return 1;
2417dd7cddfSDavid du Colombier }
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier static int
do_endif(char * p)2447dd7cddfSDavid du Colombier do_endif(char *p)
2457dd7cddfSDavid du Colombier {
2467dd7cddfSDavid du Colombier 	if (--if_depth < 0)
2477dd7cddfSDavid du Colombier 	{	debug("zpp: unbalanced #endif %s\n", p);
2487dd7cddfSDavid du Colombier 		return 0;
2497dd7cddfSDavid du Colombier 	}
2507dd7cddfSDavid du Colombier 	return 1;
2517dd7cddfSDavid du Colombier }
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier static int
do_include(char * p)2547dd7cddfSDavid du Colombier do_include(char *p)
2557dd7cddfSDavid du Colombier {	char *r, *q;
2567dd7cddfSDavid du Colombier 
2577dd7cddfSDavid du Colombier 	q = strchr(p, '<');
2587dd7cddfSDavid du Colombier 	r = strrchr(p, '>');
2597dd7cddfSDavid du Colombier 	if (!q || !r)
2607dd7cddfSDavid du Colombier 	{	q = strchr (p, '\"');
2617dd7cddfSDavid du Colombier 		r = strrchr(p, '\"');
2627dd7cddfSDavid du Colombier 		if (!q || !r || q == r)
2637dd7cddfSDavid du Colombier 		{	debug("zpp: malformed #include %s", p);
2647dd7cddfSDavid du Colombier 			return 0;
2657dd7cddfSDavid du Colombier 	}	}
2667dd7cddfSDavid du Colombier 	*r = '\0';
2677dd7cddfSDavid du Colombier 	return zpp_do(++q);
2687dd7cddfSDavid du Colombier }
2697dd7cddfSDavid du Colombier 
2707dd7cddfSDavid du Colombier static int
in_comment(char * p)2717dd7cddfSDavid du Colombier in_comment(char *p)
2727dd7cddfSDavid du Colombier {	char *q = p;
2737dd7cddfSDavid du Colombier 
2747dd7cddfSDavid du Colombier 	for (q = p; *q != '\n' && *q != '\0'; q++)
2757dd7cddfSDavid du Colombier 		switch (state) {
2767dd7cddfSDavid du Colombier 		case PLAIN:
2777dd7cddfSDavid du Colombier 			switch (*q) {
2787dd7cddfSDavid du Colombier 			case  '"': state = IN_STRING; break;
2797dd7cddfSDavid du Colombier 			case '\'': state = IN_QUOTE; break;
2807dd7cddfSDavid du Colombier 			case  '/': state = S_COMM; break;
2817dd7cddfSDavid du Colombier 			case '\\': q++; break;
2827dd7cddfSDavid du Colombier 			}
2837dd7cddfSDavid du Colombier 			break;
2847dd7cddfSDavid du Colombier 		case IN_STRING:
2857dd7cddfSDavid du Colombier 			if (*q == '"') state = PLAIN;
2867dd7cddfSDavid du Colombier 			else if (*q == '\\') q++;
2877dd7cddfSDavid du Colombier 			break;
2887dd7cddfSDavid du Colombier 		case IN_QUOTE:
2897dd7cddfSDavid du Colombier 			if (*q == '\'') state = PLAIN;
2907dd7cddfSDavid du Colombier 			else if (*q == '\\') q++;
2917dd7cddfSDavid du Colombier 			break;
2927dd7cddfSDavid du Colombier 		case S_COMM:
2937dd7cddfSDavid du Colombier 			if (*q == '*')
2947dd7cddfSDavid du Colombier 			{	*(q-1) = *q = ' ';
2957dd7cddfSDavid du Colombier 				state = COMMENT;
2967dd7cddfSDavid du Colombier 			} else if (*q != '/')
2977dd7cddfSDavid du Colombier 				state = PLAIN;
2987dd7cddfSDavid du Colombier 			break;
2997dd7cddfSDavid du Colombier 		case COMMENT:
3007dd7cddfSDavid du Colombier 			state = (*q == '*') ? E_COMM: COMMENT;
3017dd7cddfSDavid du Colombier 			*q = ' ';
3027dd7cddfSDavid du Colombier 			break;
3037dd7cddfSDavid du Colombier 		case E_COMM:
3047dd7cddfSDavid du Colombier 			if (*q == '/')
3057dd7cddfSDavid du Colombier 				state = PLAIN;
3067dd7cddfSDavid du Colombier 			else if (*q != '*')
3077dd7cddfSDavid du Colombier 				state = COMMENT;
3087dd7cddfSDavid du Colombier 			*q = ' ';
3097dd7cddfSDavid du Colombier 			break;
3107dd7cddfSDavid du Colombier 		}
3117dd7cddfSDavid du Colombier 	if (state == S_COMM) state = PLAIN;
3127dd7cddfSDavid du Colombier 	else if (state == E_COMM) state = COMMENT;
3137dd7cddfSDavid du Colombier 	return (state == COMMENT);
3147dd7cddfSDavid du Colombier }
3157dd7cddfSDavid du Colombier 
3167dd7cddfSDavid du Colombier static int
strip_cpp_comments(char * p)317*00d97012SDavid du Colombier strip_cpp_comments(char *p)
318*00d97012SDavid du Colombier {	char *q;
319*00d97012SDavid du Colombier 
320*00d97012SDavid du Colombier 	q = strstr(p, "//");
321*00d97012SDavid du Colombier 	if (q)
322*00d97012SDavid du Colombier 	{	if (q > p && *(q-1) == '\\')
323*00d97012SDavid du Colombier 		{	return strip_cpp_comments(q+1);
324*00d97012SDavid du Colombier 		}
325*00d97012SDavid du Colombier 		*q = '\n';
326*00d97012SDavid du Colombier 		*(q+1) = '\0';
327*00d97012SDavid du Colombier 		return 1;
328*00d97012SDavid du Colombier 	}
329*00d97012SDavid du Colombier 	return 0;
330*00d97012SDavid du Colombier }
331*00d97012SDavid du Colombier 
332*00d97012SDavid du Colombier static int
zpp_do(char * fnm)3337dd7cddfSDavid du Colombier zpp_do(char *fnm)
3347dd7cddfSDavid du Colombier {	char buf[2048], buf2[MAXLINE], *p; int n, on;
3357dd7cddfSDavid du Colombier 	FILE *inp; int lno = 0, nw_lno = 0;
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier 	if ((inp = fopen(fnm, "r")) == NULL)
338*00d97012SDavid du Colombier 	{	fprintf(stdout, "spin: error: No file '%s'\n", fnm);
339*00d97012SDavid du Colombier 		exit(1);	/* 4.1.2 was stderr */
3407dd7cddfSDavid du Colombier 	}
3417dd7cddfSDavid du Colombier 	printing[0] = if_truth[0] = 1;
3427dd7cddfSDavid du Colombier 	fprintf(outpp, "#line %d \"%s\"\n", lno+1, fnm);
3437dd7cddfSDavid du Colombier 	while (fgets(buf, MAXLINE, inp))
344312a1df1SDavid du Colombier 	{	lno++; n = (int) strlen(buf);
3457dd7cddfSDavid du Colombier 		on = 0; nw_lno = 0;
3467dd7cddfSDavid du Colombier 		while (n > 2 && buf[n-2] == '\\')
3477dd7cddfSDavid du Colombier 		{	buf[n-2] = '\0';
348*00d97012SDavid du Colombier feedme:
349*00d97012SDavid du Colombier 			if (!fgets(buf2, MAXLINE, inp))
3507dd7cddfSDavid du Colombier 			{	debug("zpp: unexpected EOF ln %d\n", lno);
3517dd7cddfSDavid du Colombier 				return 0;	/* switch to cpp */
3527dd7cddfSDavid du Colombier 			}
3537dd7cddfSDavid du Colombier 			lno++;
3547dd7cddfSDavid du Colombier 			if (n + (int) strlen(buf2) >= 2048)
3557dd7cddfSDavid du Colombier 			{	debug("zpp: line %d too long\n", lno);
3567dd7cddfSDavid du Colombier 				return 0;
3577dd7cddfSDavid du Colombier 			}
3587dd7cddfSDavid du Colombier 			strcat(buf, buf2);
359312a1df1SDavid du Colombier 			n = (int) strlen(buf);
3607dd7cddfSDavid du Colombier 		}
361*00d97012SDavid du Colombier 
362*00d97012SDavid du Colombier 		if (strip_cpp_comments(&buf[on]))
363*00d97012SDavid du Colombier 			n = (int) strlen(buf);
364*00d97012SDavid du Colombier 
3657dd7cddfSDavid du Colombier 		if (in_comment(&buf[on]))
3667dd7cddfSDavid du Colombier 		{	buf[n-1] = '\0'; /* eat newline */
3677dd7cddfSDavid du Colombier 			on = n-1; nw_lno = 1;
3687dd7cddfSDavid du Colombier 			goto feedme;
3697dd7cddfSDavid du Colombier 		}
3707dd7cddfSDavid du Colombier 		p = buf + strspn(buf, " \t");
3717dd7cddfSDavid du Colombier 		if (nw_lno && *p != '#')
3727dd7cddfSDavid du Colombier 			fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
3737dd7cddfSDavid du Colombier 		if (*p == '#')
3747dd7cddfSDavid du Colombier 		{	if (!process(p+1, lno+1, fnm))
3757dd7cddfSDavid du Colombier 				return 0;
3767dd7cddfSDavid du Colombier 		} else if (printing[if_depth])
3777dd7cddfSDavid du Colombier 			fprintf(outpp, "%s", apply(buf));
3787dd7cddfSDavid du Colombier 	}
3797dd7cddfSDavid du Colombier 	fclose(inp);
3807dd7cddfSDavid du Colombier 	return 1;
3817dd7cddfSDavid du Colombier }
3827dd7cddfSDavid du Colombier 
3837dd7cddfSDavid du Colombier int
try_zpp(char * fnm,char * onm)3847dd7cddfSDavid du Colombier try_zpp(char *fnm, char *onm)
3857dd7cddfSDavid du Colombier {	int r;
386*00d97012SDavid du Colombier 	if ((outpp = fopen(onm, MFLAGS)) == NULL)
3877dd7cddfSDavid du Colombier 		return 0;
3887dd7cddfSDavid du Colombier 	r = zpp_do(fnm);
3897dd7cddfSDavid du Colombier 	fclose(outpp);
3907dd7cddfSDavid du Colombier 	return r;	/* 1 = ok; 0 = use cpp */
3917dd7cddfSDavid du Colombier }
3927dd7cddfSDavid du Colombier 
3937dd7cddfSDavid du Colombier static struct Directives {
3947dd7cddfSDavid du Colombier 	int len;
3957dd7cddfSDavid du Colombier 	char *directive;
3967dd7cddfSDavid du Colombier 	int (*handler)(char *);
3977dd7cddfSDavid du Colombier 	int interp;
3987dd7cddfSDavid du Colombier } s[] = {
3997dd7cddfSDavid du Colombier 	{ 6, "define",	 do_define,	1 },
4007dd7cddfSDavid du Colombier 	{ 4, "else",	 do_else,	0 },
4017dd7cddfSDavid du Colombier 	{ 5, "endif",	 do_endif,	0 },
4027dd7cddfSDavid du Colombier 	{ 5, "ifdef",	 do_ifdef,	0 },
4037dd7cddfSDavid du Colombier 	{ 6, "ifndef",   do_ifndef,	0 },
404f3793cddSDavid du Colombier 	{ 2, "if",	 do_if,		0 },
4057dd7cddfSDavid du Colombier 	{ 7, "include",  do_include,	1 },
4067dd7cddfSDavid du Colombier 	{ 8, "undefine", do_undefine,	1 },
4077dd7cddfSDavid du Colombier };
4087dd7cddfSDavid du Colombier 
4097dd7cddfSDavid du Colombier static int
process(char * q,int lno,char * fnm)4107dd7cddfSDavid du Colombier process(char *q, int lno, char *fnm)
4117dd7cddfSDavid du Colombier {	char *p; int i, r;
4127dd7cddfSDavid du Colombier 
4137dd7cddfSDavid du Colombier 	for (p = q; *p; p++)
4147dd7cddfSDavid du Colombier 		if (*p != ' ' && *p != '\t')
4157dd7cddfSDavid du Colombier 			break;
416*00d97012SDavid du Colombier 
417*00d97012SDavid du Colombier 	if (strncmp(p, "line", 4) == 0)
418*00d97012SDavid du Colombier 	{	p += 4;
419*00d97012SDavid du Colombier 		while (*p == ' ' || *p == '\t')
420*00d97012SDavid du Colombier 		{	p++;
421*00d97012SDavid du Colombier 		}
422*00d97012SDavid du Colombier 		lno = atoi(p);
423*00d97012SDavid du Colombier 		return 1;	/* line directive */
424*00d97012SDavid du Colombier 	}
425*00d97012SDavid du Colombier 	if (isdigit((int) *p))
426*00d97012SDavid du Colombier 	{	lno = atoi(p);
427*00d97012SDavid du Colombier 		return 1;
428*00d97012SDavid du Colombier 	}
429*00d97012SDavid du Colombier 	if (strncmp(p, "error", 5) == 0)
430*00d97012SDavid du Colombier 	{	printf("spin: %s", p);
431*00d97012SDavid du Colombier 		exit(1);
432*00d97012SDavid du Colombier 	}
433*00d97012SDavid du Colombier 	if (strncmp(p, "warning", 7) == 0)
434*00d97012SDavid du Colombier 	{	printf("spin: %s", p);
435*00d97012SDavid du Colombier 		return 1;
436*00d97012SDavid du Colombier 	}
437f3793cddSDavid du Colombier 	for (i = 0; i < (int) (sizeof(s)/sizeof(struct Directives)); i++)
4387dd7cddfSDavid du Colombier 		if (!strncmp(s[i].directive, p, s[i].len))
4397dd7cddfSDavid du Colombier 		{	if (s[i].interp
4407dd7cddfSDavid du Colombier 			&&  !printing[if_depth])
4417dd7cddfSDavid du Colombier 				return 1;
4427dd7cddfSDavid du Colombier 			fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
4437dd7cddfSDavid du Colombier 			r = s[i].handler(p +  s[i].len);
4447dd7cddfSDavid du Colombier 			if (i == 6)	/* include */
4457dd7cddfSDavid du Colombier 				fprintf(outpp, "#line %d \"%s\"\n", lno, fnm);
4467dd7cddfSDavid du Colombier 			return r;
4477dd7cddfSDavid du Colombier 		}
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier 	debug("zpp: unrecognized directive: %s", p);
4507dd7cddfSDavid du Colombier 	return 0;
4517dd7cddfSDavid du Colombier }
4527dd7cddfSDavid du Colombier #endif
453