ref: 37a8fc6168b3bf82df198fb20be5a8a53996187c
dir: /sys/src/cmd/cpp/tokens.c/
#include <u.h> #include <libc.h> #include <stdio.h> #include "cpp.h" static char wbuf[2*OBS]; static char *wbp = wbuf; /* * 1 for tokens that don't need whitespace when they get inserted * by macro expansion */ static char wstab[] = { 0, /* END */ 0, /* UNCLASS */ 0, /* NAME */ 0, /* NUMBER */ 0, /* STRING */ 0, /* CCON */ 1, /* NL */ 0, /* WS */ 0, /* DSHARP */ 0, /* EQ */ 0, /* NEQ */ 0, /* LEQ */ 0, /* GEQ */ 0, /* LSH */ 0, /* RSH */ 0, /* LAND */ 0, /* LOR */ 0, /* PPLUS */ 0, /* MMINUS */ 0, /* ARROW */ 1, /* SBRA */ 1, /* SKET */ 1, /* LP */ 1, /* RP */ 0, /* DOT */ 0, /* AND */ 0, /* STAR */ 0, /* PLUS */ 0, /* MINUS */ 0, /* TILDE */ 0, /* NOT */ 0, /* SLASH */ 0, /* PCT */ 0, /* LT */ 0, /* GT */ 0, /* CIRC */ 0, /* OR */ 0, /* QUEST */ 0, /* COLON */ 0, /* ASGN */ 1, /* COMMA */ 0, /* SHARP */ 1, /* SEMIC */ 1, /* CBRA */ 1, /* CKET */ 0, /* ASPLUS */ 0, /* ASMINUS */ 0, /* ASSTAR */ 0, /* ASSLASH */ 0, /* ASPCT */ 0, /* ASCIRC */ 0, /* ASLSH */ 0, /* ASRSH */ 0, /* ASOR */ 0, /* ASAND */ 0, /* ELLIPS */ 0, /* DSHARP1 */ 0, /* NAME1 */ 0, /* DEFINED */ 0, /* UMINUS */ }; void maketokenrow(int size, Tokenrow *trp) { trp->max = size; if (size>0) trp->bp = (Token *)domalloc(size*sizeof(Token)); else trp->bp = NULL; trp->tp = trp->bp; trp->lp = trp->bp; } Token * growtokenrow(Tokenrow *trp) { int ncur = trp->tp - trp->bp; int nlast = trp->lp - trp->bp; trp->max = 3*trp->max/2 + 1; trp->bp = (Token *)dorealloc(trp->bp, trp->max*sizeof(Token)); trp->lp = &trp->bp[nlast]; trp->tp = &trp->bp[ncur]; return trp->lp; } /* * Compare a row of tokens, ignoring the content of WS; return !=0 if different */ int comparetokens(Tokenrow *tr1, Tokenrow *tr2) { Token *tp1, *tp2; tp1 = tr1->tp; tp2 = tr2->tp; if (tr1->lp-tp1 != tr2->lp-tp2) return 1; for (; tp1<tr1->lp ; tp1++, tp2++) { if (tp1->type != tp2->type || (tp1->wslen==0) != (tp2->wslen==0) || tp1->len != tp2->len || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0) return 1; } return 0; } /* * replace ntok tokens starting at dtr->tp with the contents of str. * tp ends up pointing just beyond the replacement. * Canonical whitespace is assured on each side. */ void insertrow(Tokenrow *dtr, int ntok, Tokenrow *str) { int nrtok = rowlen(str); dtr->tp += ntok; adjustrow(dtr, nrtok-ntok); dtr->tp -= ntok; movetokenrow(dtr, str); makespace(dtr); dtr->tp += nrtok; makespace(dtr); } /* * make sure there is WS before trp->tp, if tokens might merge in the output */ void makespace(Tokenrow *trp) { uchar *tt; Token *tp = trp->tp; if (tp >= trp->lp) return; if (tp->wslen) { if (tp->flag&XPWS && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) { tp->wslen = 0; return; } tp->t[-1] = ' '; return; } if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type]) return; tt = newstring(tp->t, tp->len, 1); *tt++ = ' '; tp->t = tt; tp->wslen = 1; tp->flag |= XPWS; } /* * Copy an entire tokenrow into another, at tp. * It is assumed that there is enough space. * Not strictly conforming. */ void movetokenrow(Tokenrow *dtr, Tokenrow *str) { int nby; /* nby = sizeof(Token) * (str->lp - str->bp); */ nby = (char *)str->lp - (char *)str->bp; memmove(dtr->tp, str->bp, nby); } /* * Move the tokens in a row, starting at tr->tp, rightward by nt tokens; * nt may be negative (left move). * The row may need to be grown. * Non-strictly conforming because of the (char *), but easily fixed */ void adjustrow(Tokenrow *trp, int nt) { int nby, size; if (nt==0) return; size = (trp->lp - trp->bp) + nt; while (size > trp->max) growtokenrow(trp); /* nby = sizeof(Token) * (trp->lp - trp->tp); */ nby = (char *)trp->lp - (char *)trp->tp; if (nby) memmove(trp->tp+nt, trp->tp, nby); trp->lp += nt; } /* * Copy a row of tokens into the destination holder, allocating * the space for the contents. Return the destination. */ Tokenrow * copytokenrow(Tokenrow *dtr, Tokenrow *str) { int len = rowlen(str); maketokenrow(len, dtr); movetokenrow(dtr, str); dtr->lp += len; return dtr; } /* * Produce a copy of a row of tokens. Start at trp->tp. * The value strings are copied as well. The first token * has WS available. */ Tokenrow * normtokenrow(Tokenrow *trp) { Token *tp; Tokenrow *ntrp = new(Tokenrow); int len; len = trp->lp - trp->tp; if (len<=0) len = 1; maketokenrow(len, ntrp); for (tp=trp->tp; tp < trp->lp; tp++) { *ntrp->lp = *tp; if (tp->len) { ntrp->lp->t = newstring(tp->t, tp->len, 1); *ntrp->lp->t++ = ' '; if (tp->wslen) ntrp->lp->wslen = 1; } ntrp->lp++; } if (ntrp->lp > ntrp->bp) ntrp->bp->wslen = 0; return ntrp; } /* * Debugging */ void peektokens(Tokenrow *trp, char *str) { Token *tp; int c; tp = trp->tp; flushout(); if (str) fprintf(stderr, "%s ", str); if (tp<trp->bp || tp>trp->lp) fprintf(stderr, "(tp offset %d) ", tp-trp->bp); for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) { if (tp->type!=NL) { c = tp->t[tp->len]; tp->t[tp->len] = 0; fprintf(stderr, "%s", tp->t, tp->len); tp->t[tp->len] = c; } if (tp->type==NAME) { fprintf(stderr, tp==trp->tp?"{*":"{"); prhideset(tp->hideset); fprintf(stderr, "} "); } else fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type); } fprintf(stderr, "\n"); fflush(stderr); } void puttokens(Tokenrow *trp) { Token *tp; int len; uchar *p; if (verbose) peektokens(trp, ""); tp = trp->bp; for (; tp<trp->lp; tp++) { len = tp->len+tp->wslen; p = tp->t-tp->wslen; while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) { tp++; len += tp->wslen+tp->len; } if (Mflag==0) { if (len>OBS/2) { /* handle giant token */ if (wbp > wbuf) write(1, wbuf, wbp-wbuf); write(1, p, len); wbp = wbuf; } else { memcpy(wbp, p, len); wbp += len; } } if (wbp >= &wbuf[OBS]) { write(1, wbuf, OBS); if (wbp > &wbuf[OBS]) memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]); wbp -= OBS; } } trp->tp = tp; if (cursource->fd==0) flushout(); } void flushout(void) { if (wbp>wbuf) { write(1, wbuf, wbp-wbuf); wbp = wbuf; } } /* * turn a row into just a newline */ void setempty(Tokenrow *trp) { trp->tp = trp->bp; trp->lp = trp->bp+1; *trp->bp = nltoken; } /* * generate a number */ char * outnum(char *p, int n) { if (n>=10) p = outnum(p, n/10); *p++ = n%10 + '0'; return p; } /* * allocate and initialize a new string from s, of length l, at offset o * Null terminated. */ uchar * newstring(uchar *s, int l, int o) { uchar *ns = (uchar *)domalloc(l+o+1); ns[l+o] = '\0'; return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o; }