1 #include <u.h> 2 #include <libc.h> 3 #include <stdio.h> 4 #include "cpp.h" 5 6 static char wbuf[2*OBS]; 7 static char *wbp = wbuf; 8 9 /* 10 * 1 for tokens that don't need whitespace when they get inserted 11 * by macro expansion 12 */ 13 static const char wstab[] = { 14 0, /* END */ 15 0, /* UNCLASS */ 16 0, /* NAME */ 17 0, /* NUMBER */ 18 0, /* STRING */ 19 0, /* CCON */ 20 1, /* NL */ 21 0, /* WS */ 22 0, /* DSHARP */ 23 0, /* EQ */ 24 0, /* NEQ */ 25 0, /* LEQ */ 26 0, /* GEQ */ 27 0, /* LSH */ 28 0, /* RSH */ 29 0, /* LAND */ 30 0, /* LOR */ 31 0, /* PPLUS */ 32 0, /* MMINUS */ 33 0, /* ARROW */ 34 1, /* SBRA */ 35 1, /* SKET */ 36 1, /* LP */ 37 1, /* RP */ 38 0, /* DOT */ 39 0, /* AND */ 40 0, /* STAR */ 41 0, /* PLUS */ 42 0, /* MINUS */ 43 0, /* TILDE */ 44 0, /* NOT */ 45 0, /* SLASH */ 46 0, /* PCT */ 47 0, /* LT */ 48 0, /* GT */ 49 0, /* CIRC */ 50 0, /* OR */ 51 0, /* QUEST */ 52 0, /* COLON */ 53 0, /* ASGN */ 54 1, /* COMMA */ 55 0, /* SHARP */ 56 1, /* SEMIC */ 57 1, /* CBRA */ 58 1, /* CKET */ 59 0, /* ASPLUS */ 60 0, /* ASMINUS */ 61 0, /* ASSTAR */ 62 0, /* ASSLASH */ 63 0, /* ASPCT */ 64 0, /* ASCIRC */ 65 0, /* ASLSH */ 66 0, /* ASRSH */ 67 0, /* ASOR */ 68 0, /* ASAND */ 69 0, /* ELLIPS */ 70 0, /* DSHARP1 */ 71 0, /* NAME1 */ 72 0, /* DEFINED */ 73 0, /* UMINUS */ 74 }; 75 76 void 77 maketokenrow(int size, Tokenrow *trp) 78 { 79 trp->max = size; 80 trp->bp = (Token *)domalloc(size*sizeof(Token)); 81 trp->tp = trp->bp; 82 trp->lp = trp->bp; 83 } 84 85 Token * 86 growtokenrow(Tokenrow *trp) 87 { 88 int ncur = trp->tp - trp->bp; 89 int nlast = trp->lp - trp->bp; 90 91 trp->max = 3*trp->max/2 + 1; 92 trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token)); 93 trp->lp = &trp->bp[nlast]; 94 trp->tp = &trp->bp[ncur]; 95 return trp->lp; 96 } 97 98 /* 99 * Compare a row of tokens, ignoring the content of WS; return !=0 if different 100 */ 101 int 102 comparetokens(Tokenrow *tr1, Tokenrow *tr2) 103 { 104 Token *tp1, *tp2; 105 106 tp1 = tr1->tp; 107 tp2 = tr2->tp; 108 if (tr1->lp-tp1 != tr2->lp-tp2) 109 return 1; 110 for (; tp1<tr1->lp ; tp1++, tp2++) { 111 if (tp1->type != tp2->type 112 || (tp1->wslen==0) != (tp2->wslen==0) 113 || tp1->len != tp2->len 114 || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0) 115 return 1; 116 } 117 return 0; 118 } 119 120 /* 121 * replace ntok tokens starting at dtr->tp with the contents of str. 122 * tp ends up pointing just beyond the replacement. 123 * Canonical whitespace is assured on each side. 124 */ 125 void 126 insertrow(Tokenrow *dtr, int ntok, Tokenrow *str) 127 { 128 int nrtok = rowlen(str); 129 130 dtr->tp += ntok; 131 adjustrow(dtr, nrtok-ntok); 132 dtr->tp -= ntok; 133 movetokenrow(dtr, str); 134 makespace(dtr); 135 dtr->tp += nrtok; 136 makespace(dtr); 137 } 138 139 /* 140 * make sure there is WS before trp->tp, if tokens might merge in the output 141 */ 142 void 143 makespace(Tokenrow *trp) 144 { 145 uchar *tt; 146 Token *tp = trp->tp; 147 148 if (tp >= trp->lp) 149 return; 150 if (tp->wslen) { 151 if (tp->flag&XPWS 152 && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) { 153 tp->wslen = 0; 154 return; 155 } 156 tp->t[-1] = ' '; 157 return; 158 } 159 if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type]) 160 return; 161 tt = newstring(tp->t, tp->len, 1); 162 *tt++ = ' '; 163 tp->t = tt; 164 tp->wslen = 1; 165 tp->flag |= XPWS; 166 } 167 168 /* 169 * Copy an entire tokenrow into another, at tp. 170 * It is assumed that there is enough space. 171 * Not strictly conforming. 172 */ 173 void 174 movetokenrow(Tokenrow *dtr, Tokenrow *str) 175 { 176 int nby; 177 178 /* nby = sizeof(Token) * (str->lp - str->bp); */ 179 nby = (char *)str->lp - (char *)str->bp; 180 memmove(dtr->tp, str->bp, nby); 181 } 182 183 /* 184 * Move the tokens in a row, starting at tr->tp, rightward by nt tokens; 185 * nt may be negative (left move). 186 * The row may need to be grown. 187 * Non-strictly conforming because of the (char *), but easily fixed 188 */ 189 void 190 adjustrow(Tokenrow *trp, int nt) 191 { 192 int nby, size; 193 194 if (nt==0) 195 return; 196 size = (trp->lp - trp->bp) + nt; 197 while (size > trp->max) 198 growtokenrow(trp); 199 /* nby = sizeof(Token) * (trp->lp - trp->tp); */ 200 nby = (char *)trp->lp - (char *)trp->tp; 201 if (nby) 202 memmove(trp->tp+nt, trp->tp, nby); 203 trp->lp += nt; 204 } 205 206 /* 207 * Copy a row of tokens into the destination holder, allocating 208 * the space for the contents. Return the destination. 209 */ 210 Tokenrow * 211 copytokenrow(Tokenrow *dtr, Tokenrow *str) 212 { 213 int len = rowlen(str); 214 215 maketokenrow(len, dtr); 216 movetokenrow(dtr, str); 217 dtr->lp += len; 218 return dtr; 219 } 220 221 /* 222 * Produce a copy of a row of tokens. Start at trp->tp. 223 * The value strings are copied as well. The first token 224 * has WS available. 225 */ 226 Tokenrow * 227 normtokenrow(Tokenrow *trp) 228 { 229 Token *tp; 230 Tokenrow *ntrp = new(Tokenrow); 231 int len; 232 233 len = trp->lp - trp->tp; 234 if (len<=0) 235 len = 1; 236 maketokenrow(len, ntrp); 237 for (tp=trp->tp; tp < trp->lp; tp++) { 238 *ntrp->lp = *tp; 239 if (tp->len) { 240 ntrp->lp->t = newstring(tp->t, tp->len, 1); 241 *ntrp->lp->t++ = ' '; 242 if (tp->wslen) 243 ntrp->lp->wslen = 1; 244 } 245 ntrp->lp++; 246 } 247 if (ntrp->lp > ntrp->bp) 248 ntrp->bp->wslen = 0; 249 return ntrp; 250 } 251 252 /* 253 * Debugging 254 */ 255 void 256 peektokens(Tokenrow *trp, char *str) 257 { 258 Token *tp; 259 int c; 260 261 tp = trp->tp; 262 flushout(); 263 if (str) 264 fprintf(stderr, "%s ", str); 265 if (tp <trp->bp || tp>trp->lp) 266 fprintf(stderr, "(tp offset %d) ", tp-trp->bp); 267 for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) { 268 if (tp->type!=NL) { 269 c = tp->t[tp->len]; 270 tp->t[tp->len] = 0; 271 fprintf(stderr, "%s", tp->t, tp->len); 272 tp->t[tp->len] = c; 273 } 274 if (tp->type==NAME) { 275 fprintf(stderr, tp==trp->tp?"{*":"{"); 276 prhideset(tp->hideset); 277 fprintf(stderr, "} "); 278 } else 279 fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type); 280 } 281 fprintf(stderr, "\n"); 282 fflush(stderr); 283 } 284 285 void 286 puttokens(Tokenrow *trp) 287 { 288 Token *tp; 289 int len; 290 uchar *p; 291 292 if (verbose) 293 peektokens(trp, ""); 294 tp = trp->bp; 295 for (; tp<trp->lp; tp++) { 296 len = tp->len+tp->wslen; 297 p = tp->t-tp->wslen; 298 while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) { 299 tp++; 300 len += tp->wslen+tp->len; 301 } 302 memcpy(wbp, p, len); 303 wbp += len; 304 if (wbp >= &wbuf[OBS]) { 305 write(1, wbuf, OBS); 306 if (wbp > &wbuf[OBS]) 307 memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]); 308 wbp -= OBS; 309 } 310 } 311 trp->tp = tp; 312 if (cursource->fd==0) 313 flushout(); 314 } 315 316 void 317 flushout(void) 318 { 319 if (wbp>wbuf) { 320 write(1, wbuf, wbp-wbuf); 321 wbp = wbuf; 322 } 323 } 324 325 /* 326 * turn a row into just a newline 327 */ 328 void 329 setempty(Tokenrow *trp) 330 { 331 trp->tp = trp->bp; 332 trp->lp = trp->bp+1; 333 *trp->bp = nltoken; 334 } 335 336 /* 337 * generate a number 338 */ 339 char * 340 outnum(char *p, int n) 341 { 342 if (n>=10) 343 p = outnum(p, n/10); 344 *p++ = n%10 + '0'; 345 return p; 346 } 347 348 /* 349 * allocate and initialize a new string from s, of length l, at offset o 350 * Null terminated. 351 */ 352 uchar * 353 newstring(uchar *s, int l, int o) 354 { 355 uchar *ns = (uchar *)domalloc(l+o+1); 356 357 ns[l+o] = '\0'; 358 return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o; 359 } 360