13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <stdio.h>
43e12c5d1SDavid du Colombier #include "cpp.h"
53e12c5d1SDavid du Colombier
63e12c5d1SDavid du Colombier #define OUTS 16384
73e12c5d1SDavid du Colombier char outbuf[OUTS];
83e12c5d1SDavid du Colombier char *outp = outbuf;
93e12c5d1SDavid du Colombier Source *cursource;
103e12c5d1SDavid du Colombier int nerrs;
113e12c5d1SDavid du Colombier struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
123e12c5d1SDavid du Colombier char *curtime;
133e12c5d1SDavid du Colombier int incdepth;
143e12c5d1SDavid du Colombier int ifdepth;
153e12c5d1SDavid du Colombier int ifsatisfied[NIF];
163e12c5d1SDavid du Colombier int skipping;
173e12c5d1SDavid du Colombier
18219b2ee8SDavid du Colombier int
main(int argc,char ** argv)193e12c5d1SDavid du Colombier main(int argc, char **argv)
203e12c5d1SDavid du Colombier {
213e12c5d1SDavid du Colombier Tokenrow tr;
223e12c5d1SDavid du Colombier long t;
233e12c5d1SDavid du Colombier char ebuf[BUFSIZ];
243e12c5d1SDavid du Colombier
253e12c5d1SDavid du Colombier setbuf(stderr, ebuf);
263e12c5d1SDavid du Colombier t = time(NULL);
273e12c5d1SDavid du Colombier curtime = ctime(t);
283e12c5d1SDavid du Colombier maketokenrow(3, &tr);
293e12c5d1SDavid du Colombier expandlex();
303e12c5d1SDavid du Colombier setup(argc, argv);
313e12c5d1SDavid du Colombier fixlex();
323e12c5d1SDavid du Colombier iniths();
333e12c5d1SDavid du Colombier genline();
343e12c5d1SDavid du Colombier process(&tr);
353e12c5d1SDavid du Colombier flushout();
363e12c5d1SDavid du Colombier fflush(stderr);
373e12c5d1SDavid du Colombier exits(nerrs? "errors" : 0);
38219b2ee8SDavid du Colombier return 0;
393e12c5d1SDavid du Colombier }
403e12c5d1SDavid du Colombier
413e12c5d1SDavid du Colombier void
process(Tokenrow * trp)423e12c5d1SDavid du Colombier process(Tokenrow *trp)
433e12c5d1SDavid du Colombier {
443e12c5d1SDavid du Colombier int anymacros = 0;
453e12c5d1SDavid du Colombier
463e12c5d1SDavid du Colombier for (;;) {
473e12c5d1SDavid du Colombier if (trp->tp >= trp->lp) {
483e12c5d1SDavid du Colombier trp->tp = trp->lp = trp->bp;
493e12c5d1SDavid du Colombier outp = outbuf;
503e12c5d1SDavid du Colombier anymacros |= gettokens(trp, 1);
513e12c5d1SDavid du Colombier trp->tp = trp->bp;
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier if (trp->tp->type == END) {
543e12c5d1SDavid du Colombier if (--incdepth>=0) {
553e12c5d1SDavid du Colombier if (cursource->ifdepth)
563e12c5d1SDavid du Colombier error(ERROR,
573e12c5d1SDavid du Colombier "Unterminated conditional in #include");
583e12c5d1SDavid du Colombier unsetsource();
593e12c5d1SDavid du Colombier cursource->line += cursource->lineinc;
603e12c5d1SDavid du Colombier trp->tp = trp->lp;
613e12c5d1SDavid du Colombier genline();
623e12c5d1SDavid du Colombier continue;
633e12c5d1SDavid du Colombier }
643e12c5d1SDavid du Colombier if (ifdepth)
653e12c5d1SDavid du Colombier error(ERROR, "Unterminated #if/#ifdef/#ifndef");
663e12c5d1SDavid du Colombier break;
673e12c5d1SDavid du Colombier }
683e12c5d1SDavid du Colombier if (trp->tp->type==SHARP) {
693e12c5d1SDavid du Colombier trp->tp += 1;
703e12c5d1SDavid du Colombier control(trp);
713e12c5d1SDavid du Colombier } else if (!skipping && anymacros)
7205dd1647SDavid du Colombier expandrow(trp, NULL, Notinmacro);
733e12c5d1SDavid du Colombier if (skipping)
743e12c5d1SDavid du Colombier setempty(trp);
753e12c5d1SDavid du Colombier puttokens(trp);
763e12c5d1SDavid du Colombier anymacros = 0;
773e12c5d1SDavid du Colombier cursource->line += cursource->lineinc;
783e12c5d1SDavid du Colombier if (cursource->lineinc>1) {
793e12c5d1SDavid du Colombier genline();
803e12c5d1SDavid du Colombier }
813e12c5d1SDavid du Colombier }
823e12c5d1SDavid du Colombier }
833e12c5d1SDavid du Colombier
843e12c5d1SDavid du Colombier void
control(Tokenrow * trp)853e12c5d1SDavid du Colombier control(Tokenrow *trp)
863e12c5d1SDavid du Colombier {
873e12c5d1SDavid du Colombier Nlist *np;
883e12c5d1SDavid du Colombier Token *tp;
893e12c5d1SDavid du Colombier
903e12c5d1SDavid du Colombier tp = trp->tp;
913e12c5d1SDavid du Colombier if (tp->type!=NAME) {
923e12c5d1SDavid du Colombier if (tp->type==NUMBER)
933e12c5d1SDavid du Colombier goto kline;
943e12c5d1SDavid du Colombier if (tp->type != NL)
953e12c5d1SDavid du Colombier error(ERROR, "Unidentifiable control line");
963e12c5d1SDavid du Colombier return; /* else empty line */
973e12c5d1SDavid du Colombier }
983e12c5d1SDavid du Colombier if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) {
993e12c5d1SDavid du Colombier error(WARNING, "Unknown preprocessor control %t", tp);
1003e12c5d1SDavid du Colombier return;
1013e12c5d1SDavid du Colombier }
1023e12c5d1SDavid du Colombier if (skipping) {
1039a747e4fSDavid du Colombier if ((np->flag&ISKW)==0)
1049a747e4fSDavid du Colombier return;
1053e12c5d1SDavid du Colombier switch (np->val) {
1063e12c5d1SDavid du Colombier case KENDIF:
1073e12c5d1SDavid du Colombier if (--ifdepth<skipping)
1083e12c5d1SDavid du Colombier skipping = 0;
1093e12c5d1SDavid du Colombier --cursource->ifdepth;
1103e12c5d1SDavid du Colombier setempty(trp);
1113e12c5d1SDavid du Colombier return;
1123e12c5d1SDavid du Colombier
1133e12c5d1SDavid du Colombier case KIFDEF:
1143e12c5d1SDavid du Colombier case KIFNDEF:
1153e12c5d1SDavid du Colombier case KIF:
1163e12c5d1SDavid du Colombier if (++ifdepth >= NIF)
1173e12c5d1SDavid du Colombier error(FATAL, "#if too deeply nested");
1183e12c5d1SDavid du Colombier ++cursource->ifdepth;
1193e12c5d1SDavid du Colombier return;
1203e12c5d1SDavid du Colombier
1213e12c5d1SDavid du Colombier case KELIF:
1223e12c5d1SDavid du Colombier case KELSE:
1233e12c5d1SDavid du Colombier if (ifdepth<=skipping)
1243e12c5d1SDavid du Colombier break;
1253e12c5d1SDavid du Colombier return;
1263e12c5d1SDavid du Colombier
1273e12c5d1SDavid du Colombier default:
1283e12c5d1SDavid du Colombier return;
1293e12c5d1SDavid du Colombier }
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier switch (np->val) {
1323e12c5d1SDavid du Colombier case KDEFINE:
1333e12c5d1SDavid du Colombier dodefine(trp);
1343e12c5d1SDavid du Colombier break;
1353e12c5d1SDavid du Colombier
1363e12c5d1SDavid du Colombier case KUNDEF:
1373e12c5d1SDavid du Colombier tp += 1;
1383e12c5d1SDavid du Colombier if (tp->type!=NAME || trp->lp - trp->bp != 4) {
1393e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #undef");
1403e12c5d1SDavid du Colombier break;
1413e12c5d1SDavid du Colombier }
1427dd7cddfSDavid du Colombier if ((np = lookup(tp, 0))) {
1437dd7cddfSDavid du Colombier if (np->flag&ISUNCHANGE) {
1447dd7cddfSDavid du Colombier error(ERROR, "#defined token %t can't be undefined", tp);
1457dd7cddfSDavid du Colombier return;
1467dd7cddfSDavid du Colombier }
1473e12c5d1SDavid du Colombier np->flag &= ~ISDEFINED;
1487dd7cddfSDavid du Colombier }
1493e12c5d1SDavid du Colombier break;
1503e12c5d1SDavid du Colombier
1513e12c5d1SDavid du Colombier case KPRAGMA:
1523e12c5d1SDavid du Colombier return;
1533e12c5d1SDavid du Colombier
1543e12c5d1SDavid du Colombier case KIFDEF:
1553e12c5d1SDavid du Colombier case KIFNDEF:
1563e12c5d1SDavid du Colombier case KIF:
157bd389b36SDavid du Colombier if (++ifdepth >= NIF)
1583e12c5d1SDavid du Colombier error(FATAL, "#if too deeply nested");
1593e12c5d1SDavid du Colombier ++cursource->ifdepth;
1603e12c5d1SDavid du Colombier ifsatisfied[ifdepth] = 0;
1613e12c5d1SDavid du Colombier if (eval(trp, np->val))
1623e12c5d1SDavid du Colombier ifsatisfied[ifdepth] = 1;
1633e12c5d1SDavid du Colombier else
1643e12c5d1SDavid du Colombier skipping = ifdepth;
1653e12c5d1SDavid du Colombier break;
1663e12c5d1SDavid du Colombier
1673e12c5d1SDavid du Colombier case KELIF:
1683e12c5d1SDavid du Colombier if (ifdepth==0) {
1693e12c5d1SDavid du Colombier error(ERROR, "#elif with no #if");
1703e12c5d1SDavid du Colombier return;
1713e12c5d1SDavid du Colombier }
1723e12c5d1SDavid du Colombier if (ifsatisfied[ifdepth]==2)
1733e12c5d1SDavid du Colombier error(ERROR, "#elif after #else");
1743e12c5d1SDavid du Colombier if (eval(trp, np->val)) {
1753e12c5d1SDavid du Colombier if (ifsatisfied[ifdepth])
1763e12c5d1SDavid du Colombier skipping = ifdepth;
1773e12c5d1SDavid du Colombier else {
1783e12c5d1SDavid du Colombier skipping = 0;
1793e12c5d1SDavid du Colombier ifsatisfied[ifdepth] = 1;
1803e12c5d1SDavid du Colombier }
1813e12c5d1SDavid du Colombier } else
1823e12c5d1SDavid du Colombier skipping = ifdepth;
1833e12c5d1SDavid du Colombier break;
1843e12c5d1SDavid du Colombier
1853e12c5d1SDavid du Colombier case KELSE:
1863e12c5d1SDavid du Colombier if (ifdepth==0 || cursource->ifdepth==0) {
1873e12c5d1SDavid du Colombier error(ERROR, "#else with no #if");
1883e12c5d1SDavid du Colombier return;
1893e12c5d1SDavid du Colombier }
1903e12c5d1SDavid du Colombier if (ifsatisfied[ifdepth]==2)
1913e12c5d1SDavid du Colombier error(ERROR, "#else after #else");
1923e12c5d1SDavid du Colombier if (trp->lp - trp->bp != 3)
1933e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #else");
1943e12c5d1SDavid du Colombier skipping = ifsatisfied[ifdepth]? ifdepth: 0;
1953e12c5d1SDavid du Colombier ifsatisfied[ifdepth] = 2;
1963e12c5d1SDavid du Colombier break;
1973e12c5d1SDavid du Colombier
1983e12c5d1SDavid du Colombier case KENDIF:
1993e12c5d1SDavid du Colombier if (ifdepth==0 || cursource->ifdepth==0) {
2003e12c5d1SDavid du Colombier error(ERROR, "#endif with no #if");
2013e12c5d1SDavid du Colombier return;
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier --ifdepth;
2043e12c5d1SDavid du Colombier --cursource->ifdepth;
2053e12c5d1SDavid du Colombier if (trp->lp - trp->bp != 3)
2063e12c5d1SDavid du Colombier error(WARNING, "Syntax error in #endif");
2073e12c5d1SDavid du Colombier break;
2083e12c5d1SDavid du Colombier
2093e12c5d1SDavid du Colombier case KERROR:
2103e12c5d1SDavid du Colombier trp->tp = tp+1;
211*ad1af469SDavid du Colombier error(ERROR, "#error directive: %r", trp);
212*ad1af469SDavid du Colombier break;
213*ad1af469SDavid du Colombier
214*ad1af469SDavid du Colombier case KWARNING:
215*ad1af469SDavid du Colombier trp->tp = tp+1;
216*ad1af469SDavid du Colombier error(WARNING, "#warning directive: %r", trp);
2173e12c5d1SDavid du Colombier break;
2183e12c5d1SDavid du Colombier
2193e12c5d1SDavid du Colombier case KLINE:
2203e12c5d1SDavid du Colombier trp->tp = tp+1;
22105dd1647SDavid du Colombier expandrow(trp, "<line>", Notinmacro);
2223e12c5d1SDavid du Colombier tp = trp->bp+2;
2233e12c5d1SDavid du Colombier kline:
2243e12c5d1SDavid du Colombier if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
2253e12c5d1SDavid du Colombier || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
2263e12c5d1SDavid du Colombier error(ERROR, "Syntax error in #line");
2273e12c5d1SDavid du Colombier return;
2283e12c5d1SDavid du Colombier }
2293e12c5d1SDavid du Colombier cursource->line = atol((char*)tp->t)-1;
2303e12c5d1SDavid du Colombier if (cursource->line<0 || cursource->line>=32768)
2313e12c5d1SDavid du Colombier error(WARNING, "#line specifies number out of range");
2323e12c5d1SDavid du Colombier tp = tp+1;
2333e12c5d1SDavid du Colombier if (tp+1<trp->lp)
2343e12c5d1SDavid du Colombier cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
2353e12c5d1SDavid du Colombier return;
2363e12c5d1SDavid du Colombier
2373e12c5d1SDavid du Colombier case KDEFINED:
2383e12c5d1SDavid du Colombier error(ERROR, "Bad syntax for control line");
2393e12c5d1SDavid du Colombier break;
2403e12c5d1SDavid du Colombier
2413e12c5d1SDavid du Colombier case KINCLUDE:
2423e12c5d1SDavid du Colombier doinclude(trp);
2433e12c5d1SDavid du Colombier trp->lp = trp->bp;
2443e12c5d1SDavid du Colombier return;
2453e12c5d1SDavid du Colombier
2463e12c5d1SDavid du Colombier case KEVAL:
2473e12c5d1SDavid du Colombier eval(trp, np->val);
2483e12c5d1SDavid du Colombier break;
2493e12c5d1SDavid du Colombier
2503e12c5d1SDavid du Colombier default:
2513e12c5d1SDavid du Colombier error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
2523e12c5d1SDavid du Colombier break;
2533e12c5d1SDavid du Colombier }
2543e12c5d1SDavid du Colombier setempty(trp);
2553e12c5d1SDavid du Colombier return;
2563e12c5d1SDavid du Colombier }
2573e12c5d1SDavid du Colombier
2583e12c5d1SDavid du Colombier void *
dorealloc(void * ptr,int size)259a8453668SDavid du Colombier dorealloc(void *ptr, int size)
260a8453668SDavid du Colombier {
261a8453668SDavid du Colombier void *p = realloc(ptr, size);
262a8453668SDavid du Colombier
263a8453668SDavid du Colombier if (p==NULL)
264a8453668SDavid du Colombier error(FATAL, "Out of memory from realloc");
265a8453668SDavid du Colombier return p;
266a8453668SDavid du Colombier }
267a8453668SDavid du Colombier
268a8453668SDavid du Colombier void *
domalloc(int size)2693e12c5d1SDavid du Colombier domalloc(int size)
2703e12c5d1SDavid du Colombier {
2713e12c5d1SDavid du Colombier void *p = malloc(size);
2723e12c5d1SDavid du Colombier
2733e12c5d1SDavid du Colombier if (p==NULL)
2743e12c5d1SDavid du Colombier error(FATAL, "Out of memory from malloc");
2753e12c5d1SDavid du Colombier return p;
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier
2783e12c5d1SDavid du Colombier void
dofree(void * p)2793e12c5d1SDavid du Colombier dofree(void *p)
2803e12c5d1SDavid du Colombier {
2813e12c5d1SDavid du Colombier free(p);
2823e12c5d1SDavid du Colombier }
2833e12c5d1SDavid du Colombier
2843e12c5d1SDavid du Colombier void
error(enum errtype type,char * string,...)2853e12c5d1SDavid du Colombier error(enum errtype type, char *string, ...)
2863e12c5d1SDavid du Colombier {
2873e12c5d1SDavid du Colombier va_list ap;
2883e12c5d1SDavid du Colombier char *cp, *ep;
2893e12c5d1SDavid du Colombier Token *tp;
2903e12c5d1SDavid du Colombier Tokenrow *trp;
291219b2ee8SDavid du Colombier Source *s;
2923e12c5d1SDavid du Colombier int i;
29380ee5cbfSDavid du Colombier void *p;
2943e12c5d1SDavid du Colombier
2953e12c5d1SDavid du Colombier fprintf(stderr, "cpp: ");
296219b2ee8SDavid du Colombier for (s=cursource; s; s=s->next)
297219b2ee8SDavid du Colombier if (*s->filename)
298219b2ee8SDavid du Colombier fprintf(stderr, "%s:%d ", s->filename, s->line);
2993e12c5d1SDavid du Colombier va_start(ap, string);
3003e12c5d1SDavid du Colombier for (ep=string; *ep; ep++) {
3013e12c5d1SDavid du Colombier if (*ep=='%') {
3023e12c5d1SDavid du Colombier switch (*++ep) {
3033e12c5d1SDavid du Colombier
3043e12c5d1SDavid du Colombier case 's':
3053e12c5d1SDavid du Colombier cp = va_arg(ap, char *);
3063e12c5d1SDavid du Colombier fprintf(stderr, "%s", cp);
3073e12c5d1SDavid du Colombier break;
3083e12c5d1SDavid du Colombier case 'd':
3093e12c5d1SDavid du Colombier i = va_arg(ap, int);
3103e12c5d1SDavid du Colombier fprintf(stderr, "%d", i);
3113e12c5d1SDavid du Colombier break;
31280ee5cbfSDavid du Colombier case 'p':
31380ee5cbfSDavid du Colombier p = va_arg(ap, void *);
31480ee5cbfSDavid du Colombier fprintf(stderr, "%p", p);
31580ee5cbfSDavid du Colombier break;
3163e12c5d1SDavid du Colombier case 't':
3173e12c5d1SDavid du Colombier tp = va_arg(ap, Token *);
3183e12c5d1SDavid du Colombier fprintf(stderr, "%.*s", tp->len, tp->t);
3193e12c5d1SDavid du Colombier break;
3203e12c5d1SDavid du Colombier
3213e12c5d1SDavid du Colombier case 'r':
3223e12c5d1SDavid du Colombier trp = va_arg(ap, Tokenrow *);
3233e12c5d1SDavid du Colombier for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
3243e12c5d1SDavid du Colombier if (tp>trp->tp && tp->wslen)
3253e12c5d1SDavid du Colombier fputc(' ', stderr);
3263e12c5d1SDavid du Colombier fprintf(stderr, "%.*s", tp->len, tp->t);
3273e12c5d1SDavid du Colombier }
3283e12c5d1SDavid du Colombier break;
3293e12c5d1SDavid du Colombier
3303e12c5d1SDavid du Colombier default:
3313e12c5d1SDavid du Colombier fputc(*ep, stderr);
3323e12c5d1SDavid du Colombier break;
3333e12c5d1SDavid du Colombier }
3343e12c5d1SDavid du Colombier } else
3353e12c5d1SDavid du Colombier fputc(*ep, stderr);
3363e12c5d1SDavid du Colombier }
3373e12c5d1SDavid du Colombier va_end(ap);
3383e12c5d1SDavid du Colombier fputc('\n', stderr);
3393e12c5d1SDavid du Colombier if (type==FATAL)
3403e12c5d1SDavid du Colombier exits("error");
3413e12c5d1SDavid du Colombier if (type!=WARNING)
3423e12c5d1SDavid du Colombier nerrs = 1;
3433e12c5d1SDavid du Colombier fflush(stderr);
3443e12c5d1SDavid du Colombier }
345