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