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 clearwstab(void) 78 { 79 int i; 80 81 for (i = 0; i < sizeof(wstab); i++) 82 wstab[i] = 0; 83 } 84 85 void 86 maketokenrow(int size, Tokenrow *trp) 87 { 88 trp->max = size; 89 if (size>0) 90 trp->bp = (Token *)domalloc(size*sizeof(Token)); 91 else 92 trp->bp = NULL; 93 trp->tp = trp->bp; 94 trp->lp = trp->bp; 95 } 96 97 Token * 98 growtokenrow(Tokenrow *trp) 99 { 100 int ncur = trp->tp - trp->bp; 101 int nlast = trp->lp - trp->bp; 102 103 trp->max = 3*trp->max/2 + 1; 104 trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token)); 105 trp->lp = &trp->bp[nlast]; 106 trp->tp = &trp->bp[ncur]; 107 return trp->lp; 108 } 109 110 /* 111 * Compare a row of tokens, ignoring the content of WS; return !=0 if different 112 */ 113 int 114 comparetokens(Tokenrow *tr1, Tokenrow *tr2) 115 { 116 Token *tp1, *tp2; 117 118 tp1 = tr1->tp; 119 tp2 = tr2->tp; 120 if (tr1->lp-tp1 != tr2->lp-tp2) 121 return 1; 122 for (; tp1<tr1->lp ; tp1++, tp2++) { 123 if (tp1->type != tp2->type 124 || (tp1->wslen==0) != (tp2->wslen==0) 125 || tp1->len != tp2->len 126 || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0) 127 return 1; 128 } 129 return 0; 130 } 131 132 /* 133 * replace ntok tokens starting at dtr->tp with the contents of str. 134 * tp ends up pointing just beyond the replacement. 135 * Canonical whitespace is assured on each side. 136 */ 137 void 138 insertrow(Tokenrow *dtr, int ntok, Tokenrow *str) 139 { 140 int nrtok = rowlen(str); 141 142 dtr->tp += ntok; 143 adjustrow(dtr, nrtok-ntok); 144 dtr->tp -= ntok; 145 movetokenrow(dtr, str); 146 makespace(dtr); 147 dtr->tp += nrtok; 148 makespace(dtr); 149 } 150 151 /* 152 * make sure there is WS before trp->tp, if tokens might merge in the output 153 */ 154 void 155 makespace(Tokenrow *trp) 156 { 157 uchar *tt; 158 Token *tp = trp->tp; 159 160 if (tp >= trp->lp) 161 return; 162 if (tp->wslen) { 163 if (tp->flag&XPWS 164 && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) { 165 tp->wslen = 0; 166 return; 167 } 168 tp->t[-1] = ' '; 169 return; 170 } 171 if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type]) 172 return; 173 tt = newstring(tp->t, tp->len, 1); 174 *tt++ = ' '; 175 tp->t = tt; 176 tp->wslen = 1; 177 tp->flag |= XPWS; 178 } 179 180 /* 181 * Copy an entire tokenrow into another, at tp. 182 * It is assumed that there is enough space. 183 * Not strictly conforming. 184 */ 185 void 186 movetokenrow(Tokenrow *dtr, Tokenrow *str) 187 { 188 int nby; 189 190 /* nby = sizeof(Token) * (str->lp - str->bp); */ 191 nby = (char *)str->lp - (char *)str->bp; 192 memmove(dtr->tp, str->bp, nby); 193 } 194 195 /* 196 * Move the tokens in a row, starting at tr->tp, rightward by nt tokens; 197 * nt may be negative (left move). 198 * The row may need to be grown. 199 * Non-strictly conforming because of the (char *), but easily fixed 200 */ 201 void 202 adjustrow(Tokenrow *trp, int nt) 203 { 204 int nby, size; 205 206 if (nt==0) 207 return; 208 size = (trp->lp - trp->bp) + nt; 209 while (size > trp->max) 210 growtokenrow(trp); 211 /* nby = sizeof(Token) * (trp->lp - trp->tp); */ 212 nby = (char *)trp->lp - (char *)trp->tp; 213 if (nby) 214 memmove(trp->tp+nt, trp->tp, nby); 215 trp->lp += nt; 216 } 217 218 /* 219 * Copy a row of tokens into the destination holder, allocating 220 * the space for the contents. Return the destination. 221 */ 222 Tokenrow * 223 copytokenrow(Tokenrow *dtr, Tokenrow *str) 224 { 225 int len = rowlen(str); 226 227 maketokenrow(len, dtr); 228 movetokenrow(dtr, str); 229 dtr->lp += len; 230 return dtr; 231 } 232 233 /* 234 * Produce a copy of a row of tokens. Start at trp->tp. 235 * The value strings are copied as well. The first token 236 * has WS available. 237 */ 238 Tokenrow * 239 normtokenrow(Tokenrow *trp) 240 { 241 Token *tp; 242 Tokenrow *ntrp = new(Tokenrow); 243 int len; 244 245 len = trp->lp - trp->tp; 246 if (len<=0) 247 len = 1; 248 maketokenrow(len, ntrp); 249 for (tp=trp->tp; tp < trp->lp; tp++) { 250 *ntrp->lp = *tp; 251 if (tp->len) { 252 ntrp->lp->t = newstring(tp->t, tp->len, 1); 253 *ntrp->lp->t++ = ' '; 254 if (tp->wslen) 255 ntrp->lp->wslen = 1; 256 } 257 ntrp->lp++; 258 } 259 if (ntrp->lp > ntrp->bp) 260 ntrp->bp->wslen = 0; 261 return ntrp; 262 } 263 264 /* 265 * Debugging 266 */ 267 void 268 peektokens(Tokenrow *trp, char *str) 269 { 270 Token *tp; 271 int c; 272 273 tp = trp->tp; 274 flushout(); 275 if (str) 276 fprintf(stderr, "%s ", str); 277 if (tp<trp->bp || tp>trp->lp) 278 fprintf(stderr, "(tp offset %d) ", tp-trp->bp); 279 for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) { 280 if (tp->type!=NL) { 281 c = tp->t[tp->len]; 282 tp->t[tp->len] = 0; 283 fprintf(stderr, "%s", tp->t, tp->len); 284 tp->t[tp->len] = c; 285 } 286 if (tp->type==NAME) { 287 fprintf(stderr, tp==trp->tp?"{*":"{"); 288 prhideset(tp->hideset); 289 fprintf(stderr, "} "); 290 } else 291 fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type); 292 } 293 fprintf(stderr, "\n"); 294 fflush(stderr); 295 } 296 297 void 298 puttokens(Tokenrow *trp) 299 { 300 Token *tp; 301 int len; 302 uchar *p; 303 304 if (verbose) 305 peektokens(trp, ""); 306 tp = trp->bp; 307 for (; tp<trp->lp; tp++) { 308 len = tp->len+tp->wslen; 309 p = tp->t-tp->wslen; 310 while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) { 311 tp++; 312 len += tp->wslen+tp->len; 313 } 314 if (Mflag==0) { 315 if (len>OBS/2) { /* handle giant token */ 316 if (wbp > wbuf) 317 write(1, wbuf, wbp-wbuf); 318 write(1, p, len); 319 wbp = wbuf; 320 } else { 321 memcpy(wbp, p, len); 322 wbp += len; 323 } 324 } 325 if (wbp >= &wbuf[OBS]) { 326 write(1, wbuf, OBS); 327 if (wbp > &wbuf[OBS]) 328 memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]); 329 wbp -= OBS; 330 } 331 } 332 trp->tp = tp; 333 if (cursource->fd==0) 334 flushout(); 335 } 336 337 void 338 flushout(void) 339 { 340 if (wbp>wbuf) { 341 write(1, wbuf, wbp-wbuf); 342 wbp = wbuf; 343 } 344 } 345 346 /* 347 * turn a row into just a newline 348 */ 349 void 350 setempty(Tokenrow *trp) 351 { 352 trp->tp = trp->bp; 353 trp->lp = trp->bp+1; 354 *trp->bp = nltoken; 355 } 356 357 /* 358 * generate a number 359 */ 360 char * 361 outnum(char *p, int n) 362 { 363 if (n>=10) 364 p = outnum(p, n/10); 365 *p++ = n%10 + '0'; 366 return p; 367 } 368 369 /* 370 * allocate and initialize a new string from s, of length l, at offset o 371 * Null terminated. 372 */ 373 uchar * 374 newstring(uchar *s, int l, int o) 375 { 376 uchar *ns = (uchar *)domalloc(l+o+1); 377 378 ns[l+o] = '\0'; 379 return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o; 380 } 381