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 static char wbuf[2*OBS]; 73e12c5d1SDavid du Colombier static char *wbp = wbuf; 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier /* 103e12c5d1SDavid du Colombier * 1 for tokens that don't need whitespace when they get inserted 113e12c5d1SDavid du Colombier * by macro expansion 123e12c5d1SDavid du Colombier */ 133e12c5d1SDavid du Colombier static const char wstab[] = { 143e12c5d1SDavid du Colombier 0, /* END */ 153e12c5d1SDavid du Colombier 0, /* UNCLASS */ 163e12c5d1SDavid du Colombier 0, /* NAME */ 173e12c5d1SDavid du Colombier 0, /* NUMBER */ 183e12c5d1SDavid du Colombier 0, /* STRING */ 193e12c5d1SDavid du Colombier 0, /* CCON */ 203e12c5d1SDavid du Colombier 1, /* NL */ 213e12c5d1SDavid du Colombier 0, /* WS */ 223e12c5d1SDavid du Colombier 0, /* DSHARP */ 233e12c5d1SDavid du Colombier 0, /* EQ */ 243e12c5d1SDavid du Colombier 0, /* NEQ */ 253e12c5d1SDavid du Colombier 0, /* LEQ */ 263e12c5d1SDavid du Colombier 0, /* GEQ */ 273e12c5d1SDavid du Colombier 0, /* LSH */ 283e12c5d1SDavid du Colombier 0, /* RSH */ 293e12c5d1SDavid du Colombier 0, /* LAND */ 303e12c5d1SDavid du Colombier 0, /* LOR */ 313e12c5d1SDavid du Colombier 0, /* PPLUS */ 323e12c5d1SDavid du Colombier 0, /* MMINUS */ 333e12c5d1SDavid du Colombier 0, /* ARROW */ 343e12c5d1SDavid du Colombier 1, /* SBRA */ 353e12c5d1SDavid du Colombier 1, /* SKET */ 363e12c5d1SDavid du Colombier 1, /* LP */ 373e12c5d1SDavid du Colombier 1, /* RP */ 383e12c5d1SDavid du Colombier 0, /* DOT */ 393e12c5d1SDavid du Colombier 0, /* AND */ 403e12c5d1SDavid du Colombier 0, /* STAR */ 413e12c5d1SDavid du Colombier 0, /* PLUS */ 423e12c5d1SDavid du Colombier 0, /* MINUS */ 433e12c5d1SDavid du Colombier 0, /* TILDE */ 443e12c5d1SDavid du Colombier 0, /* NOT */ 453e12c5d1SDavid du Colombier 0, /* SLASH */ 463e12c5d1SDavid du Colombier 0, /* PCT */ 473e12c5d1SDavid du Colombier 0, /* LT */ 483e12c5d1SDavid du Colombier 0, /* GT */ 493e12c5d1SDavid du Colombier 0, /* CIRC */ 503e12c5d1SDavid du Colombier 0, /* OR */ 513e12c5d1SDavid du Colombier 0, /* QUEST */ 523e12c5d1SDavid du Colombier 0, /* COLON */ 533e12c5d1SDavid du Colombier 0, /* ASGN */ 543e12c5d1SDavid du Colombier 1, /* COMMA */ 553e12c5d1SDavid du Colombier 0, /* SHARP */ 563e12c5d1SDavid du Colombier 1, /* SEMIC */ 573e12c5d1SDavid du Colombier 1, /* CBRA */ 583e12c5d1SDavid du Colombier 1, /* CKET */ 593e12c5d1SDavid du Colombier 0, /* ASPLUS */ 603e12c5d1SDavid du Colombier 0, /* ASMINUS */ 613e12c5d1SDavid du Colombier 0, /* ASSTAR */ 623e12c5d1SDavid du Colombier 0, /* ASSLASH */ 633e12c5d1SDavid du Colombier 0, /* ASPCT */ 643e12c5d1SDavid du Colombier 0, /* ASCIRC */ 653e12c5d1SDavid du Colombier 0, /* ASLSH */ 663e12c5d1SDavid du Colombier 0, /* ASRSH */ 673e12c5d1SDavid du Colombier 0, /* ASOR */ 683e12c5d1SDavid du Colombier 0, /* ASAND */ 693e12c5d1SDavid du Colombier 0, /* ELLIPS */ 703e12c5d1SDavid du Colombier 0, /* DSHARP1 */ 713e12c5d1SDavid du Colombier 0, /* NAME1 */ 723e12c5d1SDavid du Colombier 0, /* DEFINED */ 733e12c5d1SDavid du Colombier 0, /* UMINUS */ 743e12c5d1SDavid du Colombier }; 753e12c5d1SDavid du Colombier 763e12c5d1SDavid du Colombier void 773e12c5d1SDavid du Colombier maketokenrow(int size, Tokenrow *trp) 783e12c5d1SDavid du Colombier { 793e12c5d1SDavid du Colombier trp->max = size; 803e12c5d1SDavid du Colombier trp->bp = (Token *)domalloc(size*sizeof(Token)); 813e12c5d1SDavid du Colombier trp->tp = trp->bp; 823e12c5d1SDavid du Colombier trp->lp = trp->bp; 833e12c5d1SDavid du Colombier } 843e12c5d1SDavid du Colombier 853e12c5d1SDavid du Colombier Token * 863e12c5d1SDavid du Colombier growtokenrow(Tokenrow *trp) 873e12c5d1SDavid du Colombier { 883e12c5d1SDavid du Colombier int ncur = trp->tp - trp->bp; 893e12c5d1SDavid du Colombier int nlast = trp->lp - trp->bp; 903e12c5d1SDavid du Colombier 913e12c5d1SDavid du Colombier trp->max = 3*trp->max/2 + 1; 923e12c5d1SDavid du Colombier trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token)); 933e12c5d1SDavid du Colombier trp->lp = &trp->bp[nlast]; 943e12c5d1SDavid du Colombier trp->tp = &trp->bp[ncur]; 953e12c5d1SDavid du Colombier return trp->lp; 963e12c5d1SDavid du Colombier } 973e12c5d1SDavid du Colombier 983e12c5d1SDavid du Colombier /* 993e12c5d1SDavid du Colombier * Compare a row of tokens, ignoring the content of WS; return !=0 if different 1003e12c5d1SDavid du Colombier */ 1013e12c5d1SDavid du Colombier int 1023e12c5d1SDavid du Colombier comparetokens(Tokenrow *tr1, Tokenrow *tr2) 1033e12c5d1SDavid du Colombier { 1043e12c5d1SDavid du Colombier Token *tp1, *tp2; 1053e12c5d1SDavid du Colombier 1063e12c5d1SDavid du Colombier tp1 = tr1->tp; 1073e12c5d1SDavid du Colombier tp2 = tr2->tp; 1083e12c5d1SDavid du Colombier if (tr1->lp-tp1 != tr2->lp-tp2) 1093e12c5d1SDavid du Colombier return 1; 1103e12c5d1SDavid du Colombier for (; tp1<tr1->lp ; tp1++, tp2++) { 1113e12c5d1SDavid du Colombier if (tp1->type != tp2->type 1123e12c5d1SDavid du Colombier || (tp1->wslen==0) != (tp2->wslen==0) 1133e12c5d1SDavid du Colombier || tp1->len != tp2->len 1143e12c5d1SDavid du Colombier || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0) 1153e12c5d1SDavid du Colombier return 1; 1163e12c5d1SDavid du Colombier } 1173e12c5d1SDavid du Colombier return 0; 1183e12c5d1SDavid du Colombier } 1193e12c5d1SDavid du Colombier 1203e12c5d1SDavid du Colombier /* 1213e12c5d1SDavid du Colombier * replace ntok tokens starting at dtr->tp with the contents of str. 1223e12c5d1SDavid du Colombier * tp ends up pointing just beyond the replacement. 1233e12c5d1SDavid du Colombier * Canonical whitespace is assured on each side. 1243e12c5d1SDavid du Colombier */ 1253e12c5d1SDavid du Colombier void 1263e12c5d1SDavid du Colombier insertrow(Tokenrow *dtr, int ntok, Tokenrow *str) 1273e12c5d1SDavid du Colombier { 1283e12c5d1SDavid du Colombier int nrtok = rowlen(str); 1293e12c5d1SDavid du Colombier 1303e12c5d1SDavid du Colombier dtr->tp += ntok; 1313e12c5d1SDavid du Colombier adjustrow(dtr, nrtok-ntok); 1323e12c5d1SDavid du Colombier dtr->tp -= ntok; 1333e12c5d1SDavid du Colombier movetokenrow(dtr, str); 1343e12c5d1SDavid du Colombier makespace(dtr); 1353e12c5d1SDavid du Colombier dtr->tp += nrtok; 1363e12c5d1SDavid du Colombier makespace(dtr); 1373e12c5d1SDavid du Colombier } 1383e12c5d1SDavid du Colombier 1393e12c5d1SDavid du Colombier /* 1403e12c5d1SDavid du Colombier * make sure there is WS before trp->tp, if tokens might merge in the output 1413e12c5d1SDavid du Colombier */ 1423e12c5d1SDavid du Colombier void 1433e12c5d1SDavid du Colombier makespace(Tokenrow *trp) 1443e12c5d1SDavid du Colombier { 1453e12c5d1SDavid du Colombier uchar *tt; 1463e12c5d1SDavid du Colombier Token *tp = trp->tp; 1473e12c5d1SDavid du Colombier 1483e12c5d1SDavid du Colombier if (tp >= trp->lp) 1493e12c5d1SDavid du Colombier return; 1503e12c5d1SDavid du Colombier if (tp->wslen) { 1513e12c5d1SDavid du Colombier if (tp->flag&XPWS 1523e12c5d1SDavid du Colombier && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) { 1533e12c5d1SDavid du Colombier tp->wslen = 0; 1543e12c5d1SDavid du Colombier return; 1553e12c5d1SDavid du Colombier } 1563e12c5d1SDavid du Colombier tp->t[-1] = ' '; 1573e12c5d1SDavid du Colombier return; 1583e12c5d1SDavid du Colombier } 1593e12c5d1SDavid du Colombier if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type]) 1603e12c5d1SDavid du Colombier return; 1613e12c5d1SDavid du Colombier tt = newstring(tp->t, tp->len, 1); 1623e12c5d1SDavid du Colombier *tt++ = ' '; 1633e12c5d1SDavid du Colombier tp->t = tt; 1643e12c5d1SDavid du Colombier tp->wslen = 1; 1653e12c5d1SDavid du Colombier tp->flag |= XPWS; 1663e12c5d1SDavid du Colombier } 1673e12c5d1SDavid du Colombier 1683e12c5d1SDavid du Colombier /* 1693e12c5d1SDavid du Colombier * Copy an entire tokenrow into another, at tp. 1703e12c5d1SDavid du Colombier * It is assumed that there is enough space. 1713e12c5d1SDavid du Colombier * Not strictly conforming. 1723e12c5d1SDavid du Colombier */ 1733e12c5d1SDavid du Colombier void 1743e12c5d1SDavid du Colombier movetokenrow(Tokenrow *dtr, Tokenrow *str) 1753e12c5d1SDavid du Colombier { 1763e12c5d1SDavid du Colombier int nby; 1773e12c5d1SDavid du Colombier 1783e12c5d1SDavid du Colombier /* nby = sizeof(Token) * (str->lp - str->bp); */ 1793e12c5d1SDavid du Colombier nby = (char *)str->lp - (char *)str->bp; 1803e12c5d1SDavid du Colombier memmove(dtr->tp, str->bp, nby); 1813e12c5d1SDavid du Colombier } 1823e12c5d1SDavid du Colombier 1833e12c5d1SDavid du Colombier /* 1843e12c5d1SDavid du Colombier * Move the tokens in a row, starting at tr->tp, rightward by nt tokens; 1853e12c5d1SDavid du Colombier * nt may be negative (left move). 1863e12c5d1SDavid du Colombier * The row may need to be grown. 1873e12c5d1SDavid du Colombier * Non-strictly conforming because of the (char *), but easily fixed 1883e12c5d1SDavid du Colombier */ 1893e12c5d1SDavid du Colombier void 1903e12c5d1SDavid du Colombier adjustrow(Tokenrow *trp, int nt) 1913e12c5d1SDavid du Colombier { 1923e12c5d1SDavid du Colombier int nby, size; 1933e12c5d1SDavid du Colombier 1943e12c5d1SDavid du Colombier if (nt==0) 1953e12c5d1SDavid du Colombier return; 1963e12c5d1SDavid du Colombier size = (trp->lp - trp->bp) + nt; 1973e12c5d1SDavid du Colombier while (size > trp->max) 1983e12c5d1SDavid du Colombier growtokenrow(trp); 1993e12c5d1SDavid du Colombier /* nby = sizeof(Token) * (trp->lp - trp->tp); */ 2003e12c5d1SDavid du Colombier nby = (char *)trp->lp - (char *)trp->tp; 2013e12c5d1SDavid du Colombier if (nby) 2023e12c5d1SDavid du Colombier memmove(trp->tp+nt, trp->tp, nby); 2033e12c5d1SDavid du Colombier trp->lp += nt; 2043e12c5d1SDavid du Colombier } 2053e12c5d1SDavid du Colombier 2063e12c5d1SDavid du Colombier /* 2073e12c5d1SDavid du Colombier * Copy a row of tokens into the destination holder, allocating 2083e12c5d1SDavid du Colombier * the space for the contents. Return the destination. 2093e12c5d1SDavid du Colombier */ 2103e12c5d1SDavid du Colombier Tokenrow * 2113e12c5d1SDavid du Colombier copytokenrow(Tokenrow *dtr, Tokenrow *str) 2123e12c5d1SDavid du Colombier { 2133e12c5d1SDavid du Colombier int len = rowlen(str); 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier maketokenrow(len, dtr); 2163e12c5d1SDavid du Colombier movetokenrow(dtr, str); 2173e12c5d1SDavid du Colombier dtr->lp += len; 2183e12c5d1SDavid du Colombier return dtr; 2193e12c5d1SDavid du Colombier } 2203e12c5d1SDavid du Colombier 2213e12c5d1SDavid du Colombier /* 2223e12c5d1SDavid du Colombier * Produce a copy of a row of tokens. Start at trp->tp. 2233e12c5d1SDavid du Colombier * The value strings are copied as well. The first token 2243e12c5d1SDavid du Colombier * has WS available. 2253e12c5d1SDavid du Colombier */ 2263e12c5d1SDavid du Colombier Tokenrow * 2273e12c5d1SDavid du Colombier normtokenrow(Tokenrow *trp) 2283e12c5d1SDavid du Colombier { 2293e12c5d1SDavid du Colombier Token *tp; 2303e12c5d1SDavid du Colombier Tokenrow *ntrp = new(Tokenrow); 2313e12c5d1SDavid du Colombier int len; 2323e12c5d1SDavid du Colombier 2333e12c5d1SDavid du Colombier len = trp->lp - trp->tp; 2343e12c5d1SDavid du Colombier if (len<=0) 2353e12c5d1SDavid du Colombier len = 1; 2363e12c5d1SDavid du Colombier maketokenrow(len, ntrp); 2373e12c5d1SDavid du Colombier for (tp=trp->tp; tp < trp->lp; tp++) { 2383e12c5d1SDavid du Colombier *ntrp->lp = *tp; 2393e12c5d1SDavid du Colombier if (tp->len) { 2403e12c5d1SDavid du Colombier ntrp->lp->t = newstring(tp->t, tp->len, 1); 2413e12c5d1SDavid du Colombier *ntrp->lp->t++ = ' '; 2423e12c5d1SDavid du Colombier if (tp->wslen) 2433e12c5d1SDavid du Colombier ntrp->lp->wslen = 1; 2443e12c5d1SDavid du Colombier } 2453e12c5d1SDavid du Colombier ntrp->lp++; 2463e12c5d1SDavid du Colombier } 2473e12c5d1SDavid du Colombier if (ntrp->lp > ntrp->bp) 2483e12c5d1SDavid du Colombier ntrp->bp->wslen = 0; 2493e12c5d1SDavid du Colombier return ntrp; 2503e12c5d1SDavid du Colombier } 2513e12c5d1SDavid du Colombier 2523e12c5d1SDavid du Colombier /* 2533e12c5d1SDavid du Colombier * Debugging 2543e12c5d1SDavid du Colombier */ 2553e12c5d1SDavid du Colombier void 2563e12c5d1SDavid du Colombier peektokens(Tokenrow *trp, char *str) 2573e12c5d1SDavid du Colombier { 2583e12c5d1SDavid du Colombier Token *tp; 2593e12c5d1SDavid du Colombier int c; 2603e12c5d1SDavid du Colombier 2613e12c5d1SDavid du Colombier tp = trp->tp; 2623e12c5d1SDavid du Colombier flushout(); 2633e12c5d1SDavid du Colombier if (str) 2643e12c5d1SDavid du Colombier fprintf(stderr, "%s ", str); 2653e12c5d1SDavid du Colombier if (tp<trp->bp || tp>trp->lp) 2663e12c5d1SDavid du Colombier fprintf(stderr, "(tp offset %d) ", tp-trp->bp); 2673e12c5d1SDavid du Colombier for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) { 2683e12c5d1SDavid du Colombier if (tp->type!=NL) { 2693e12c5d1SDavid du Colombier c = tp->t[tp->len]; 2703e12c5d1SDavid du Colombier tp->t[tp->len] = 0; 2713e12c5d1SDavid du Colombier fprintf(stderr, "%s", tp->t, tp->len); 2723e12c5d1SDavid du Colombier tp->t[tp->len] = c; 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier if (tp->type==NAME) { 2753e12c5d1SDavid du Colombier fprintf(stderr, tp==trp->tp?"{*":"{"); 2763e12c5d1SDavid du Colombier prhideset(tp->hideset); 2773e12c5d1SDavid du Colombier fprintf(stderr, "} "); 2783e12c5d1SDavid du Colombier } else 2793e12c5d1SDavid du Colombier fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type); 2803e12c5d1SDavid du Colombier } 2813e12c5d1SDavid du Colombier fprintf(stderr, "\n"); 2823e12c5d1SDavid du Colombier fflush(stderr); 2833e12c5d1SDavid du Colombier } 2843e12c5d1SDavid du Colombier 2853e12c5d1SDavid du Colombier void 2863e12c5d1SDavid du Colombier puttokens(Tokenrow *trp) 2873e12c5d1SDavid du Colombier { 2883e12c5d1SDavid du Colombier Token *tp; 2893e12c5d1SDavid du Colombier int len; 2903e12c5d1SDavid du Colombier uchar *p; 2913e12c5d1SDavid du Colombier 2923e12c5d1SDavid du Colombier if (verbose) 2933e12c5d1SDavid du Colombier peektokens(trp, ""); 2943e12c5d1SDavid du Colombier tp = trp->bp; 2953e12c5d1SDavid du Colombier for (; tp<trp->lp; tp++) { 2963e12c5d1SDavid du Colombier len = tp->len+tp->wslen; 2973e12c5d1SDavid du Colombier p = tp->t-tp->wslen; 2983e12c5d1SDavid du Colombier while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) { 2993e12c5d1SDavid du Colombier tp++; 3003e12c5d1SDavid du Colombier len += tp->wslen+tp->len; 3013e12c5d1SDavid du Colombier } 302*bd389b36SDavid du Colombier if (Mflag==0) { 3033e12c5d1SDavid du Colombier memcpy(wbp, p, len); 3043e12c5d1SDavid du Colombier wbp += len; 305*bd389b36SDavid du Colombier } 3063e12c5d1SDavid du Colombier if (wbp >= &wbuf[OBS]) { 3073e12c5d1SDavid du Colombier write(1, wbuf, OBS); 3083e12c5d1SDavid du Colombier if (wbp > &wbuf[OBS]) 3093e12c5d1SDavid du Colombier memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]); 3103e12c5d1SDavid du Colombier wbp -= OBS; 3113e12c5d1SDavid du Colombier } 3123e12c5d1SDavid du Colombier } 3133e12c5d1SDavid du Colombier trp->tp = tp; 3143e12c5d1SDavid du Colombier if (cursource->fd==0) 3153e12c5d1SDavid du Colombier flushout(); 3163e12c5d1SDavid du Colombier } 3173e12c5d1SDavid du Colombier 3183e12c5d1SDavid du Colombier void 3193e12c5d1SDavid du Colombier flushout(void) 3203e12c5d1SDavid du Colombier { 3213e12c5d1SDavid du Colombier if (wbp>wbuf) { 3223e12c5d1SDavid du Colombier write(1, wbuf, wbp-wbuf); 3233e12c5d1SDavid du Colombier wbp = wbuf; 3243e12c5d1SDavid du Colombier } 3253e12c5d1SDavid du Colombier } 3263e12c5d1SDavid du Colombier 3273e12c5d1SDavid du Colombier /* 3283e12c5d1SDavid du Colombier * turn a row into just a newline 3293e12c5d1SDavid du Colombier */ 3303e12c5d1SDavid du Colombier void 3313e12c5d1SDavid du Colombier setempty(Tokenrow *trp) 3323e12c5d1SDavid du Colombier { 3333e12c5d1SDavid du Colombier trp->tp = trp->bp; 3343e12c5d1SDavid du Colombier trp->lp = trp->bp+1; 3353e12c5d1SDavid du Colombier *trp->bp = nltoken; 3363e12c5d1SDavid du Colombier } 3373e12c5d1SDavid du Colombier 3383e12c5d1SDavid du Colombier /* 3393e12c5d1SDavid du Colombier * generate a number 3403e12c5d1SDavid du Colombier */ 3413e12c5d1SDavid du Colombier char * 3423e12c5d1SDavid du Colombier outnum(char *p, int n) 3433e12c5d1SDavid du Colombier { 3443e12c5d1SDavid du Colombier if (n>=10) 3453e12c5d1SDavid du Colombier p = outnum(p, n/10); 3463e12c5d1SDavid du Colombier *p++ = n%10 + '0'; 3473e12c5d1SDavid du Colombier return p; 3483e12c5d1SDavid du Colombier } 3493e12c5d1SDavid du Colombier 3503e12c5d1SDavid du Colombier /* 3513e12c5d1SDavid du Colombier * allocate and initialize a new string from s, of length l, at offset o 3523e12c5d1SDavid du Colombier * Null terminated. 3533e12c5d1SDavid du Colombier */ 3543e12c5d1SDavid du Colombier uchar * 3553e12c5d1SDavid du Colombier newstring(uchar *s, int l, int o) 3563e12c5d1SDavid du Colombier { 3573e12c5d1SDavid du Colombier uchar *ns = (uchar *)domalloc(l+o+1); 3583e12c5d1SDavid du Colombier 3593e12c5d1SDavid du Colombier ns[l+o] = '\0'; 3603e12c5d1SDavid du Colombier return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o; 3613e12c5d1SDavid du Colombier } 362