1 #include <u.h> 2 #include <libc.h> 3 #include <stdio.h> 4 #include "cpp.h" 5 6 #define OUTS 16384 7 char outbuf[OUTS]; 8 char *outp = outbuf; 9 Source *cursource; 10 int nerrs; 11 struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" }; 12 char *curtime; 13 int incdepth; 14 int ifdepth; 15 int ifsatisfied[NIF]; 16 int skipping; 17 18 int 19 main(int argc, char **argv) 20 { 21 Tokenrow tr; 22 long t; 23 char ebuf[BUFSIZ]; 24 25 setbuf(stderr, ebuf); 26 t = time(NULL); 27 curtime = ctime(t); 28 maketokenrow(3, &tr); 29 expandlex(); 30 setup(argc, argv); 31 fixlex(); 32 iniths(); 33 genline(); 34 process(&tr); 35 flushout(); 36 fflush(stderr); 37 exits(nerrs? "errors" : 0); 38 return 0; 39 } 40 41 void 42 process(Tokenrow *trp) 43 { 44 int anymacros = 0; 45 46 for (;;) { 47 if (trp->tp >= trp->lp) { 48 trp->tp = trp->lp = trp->bp; 49 outp = outbuf; 50 anymacros |= gettokens(trp, 1); 51 trp->tp = trp->bp; 52 } 53 if (trp->tp->type == END) { 54 if (--incdepth>=0) { 55 if (cursource->ifdepth) 56 error(ERROR, 57 "Unterminated conditional in #include"); 58 unsetsource(); 59 cursource->line += cursource->lineinc; 60 trp->tp = trp->lp; 61 genline(); 62 continue; 63 } 64 if (ifdepth) 65 error(ERROR, "Unterminated #if/#ifdef/#ifndef"); 66 break; 67 } 68 if (trp->tp->type==SHARP) { 69 trp->tp += 1; 70 control(trp); 71 } else if (!skipping && anymacros) 72 expandrow(trp, NULL); 73 if (skipping) 74 setempty(trp); 75 puttokens(trp); 76 anymacros = 0; 77 cursource->line += cursource->lineinc; 78 if (cursource->lineinc>1) { 79 genline(); 80 } 81 } 82 } 83 84 void 85 control(Tokenrow *trp) 86 { 87 Nlist *np; 88 Token *tp; 89 90 tp = trp->tp; 91 if (tp->type!=NAME) { 92 if (tp->type==NUMBER) 93 goto kline; 94 if (tp->type != NL) 95 error(ERROR, "Unidentifiable control line"); 96 return; /* else empty line */ 97 } 98 if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { 99 error(WARNING, "Unknown preprocessor control %t", tp); 100 return; 101 } 102 if (skipping) { 103 if ((np->flag&ISKW)==0) 104 return; 105 switch (np->val) { 106 case KENDIF: 107 if (--ifdepth<skipping) 108 skipping = 0; 109 --cursource->ifdepth; 110 setempty(trp); 111 return; 112 113 case KIFDEF: 114 case KIFNDEF: 115 case KIF: 116 if (++ifdepth >= NIF) 117 error(FATAL, "#if too deeply nested"); 118 ++cursource->ifdepth; 119 return; 120 121 case KELIF: 122 case KELSE: 123 if (ifdepth<=skipping) 124 break; 125 return; 126 127 default: 128 return; 129 } 130 } 131 switch (np->val) { 132 case KDEFINE: 133 dodefine(trp); 134 break; 135 136 case KUNDEF: 137 tp += 1; 138 if (tp->type!=NAME || trp->lp - trp->bp != 4) { 139 error(ERROR, "Syntax error in #undef"); 140 break; 141 } 142 if ((np = lookup(tp, 0))) { 143 if (np->flag&ISUNCHANGE) { 144 error(ERROR, "#defined token %t can't be undefined", tp); 145 return; 146 } 147 np->flag &= ~ISDEFINED; 148 } 149 break; 150 151 case KPRAGMA: 152 return; 153 154 case KIFDEF: 155 case KIFNDEF: 156 case KIF: 157 if (++ifdepth >= NIF) 158 error(FATAL, "#if too deeply nested"); 159 ++cursource->ifdepth; 160 ifsatisfied[ifdepth] = 0; 161 if (eval(trp, np->val)) 162 ifsatisfied[ifdepth] = 1; 163 else 164 skipping = ifdepth; 165 break; 166 167 case KELIF: 168 if (ifdepth==0) { 169 error(ERROR, "#elif with no #if"); 170 return; 171 } 172 if (ifsatisfied[ifdepth]==2) 173 error(ERROR, "#elif after #else"); 174 if (eval(trp, np->val)) { 175 if (ifsatisfied[ifdepth]) 176 skipping = ifdepth; 177 else { 178 skipping = 0; 179 ifsatisfied[ifdepth] = 1; 180 } 181 } else 182 skipping = ifdepth; 183 break; 184 185 case KELSE: 186 if (ifdepth==0 || cursource->ifdepth==0) { 187 error(ERROR, "#else with no #if"); 188 return; 189 } 190 if (ifsatisfied[ifdepth]==2) 191 error(ERROR, "#else after #else"); 192 if (trp->lp - trp->bp != 3) 193 error(ERROR, "Syntax error in #else"); 194 skipping = ifsatisfied[ifdepth]? ifdepth: 0; 195 ifsatisfied[ifdepth] = 2; 196 break; 197 198 case KENDIF: 199 if (ifdepth==0 || cursource->ifdepth==0) { 200 error(ERROR, "#endif with no #if"); 201 return; 202 } 203 --ifdepth; 204 --cursource->ifdepth; 205 if (trp->lp - trp->bp != 3) 206 error(WARNING, "Syntax error in #endif"); 207 break; 208 209 case KERROR: 210 trp->tp = tp+1; 211 error(WARNING, "#error directive: %r", trp); 212 break; 213 214 case KLINE: 215 trp->tp = tp+1; 216 expandrow(trp, "<line>"); 217 tp = trp->bp+2; 218 kline: 219 if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp 220 || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){ 221 error(ERROR, "Syntax error in #line"); 222 return; 223 } 224 cursource->line = atol((char*)tp->t)-1; 225 if (cursource->line<0 || cursource->line>=32768) 226 error(WARNING, "#line specifies number out of range"); 227 tp = tp+1; 228 if (tp+1<trp->lp) 229 cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); 230 return; 231 232 case KDEFINED: 233 error(ERROR, "Bad syntax for control line"); 234 break; 235 236 case KINCLUDE: 237 doinclude(trp); 238 trp->lp = trp->bp; 239 return; 240 241 case KEVAL: 242 eval(trp, np->val); 243 break; 244 245 default: 246 error(ERROR, "Preprocessor control `%t' not yet implemented", tp); 247 break; 248 } 249 setempty(trp); 250 return; 251 } 252 253 void * 254 dorealloc(void *ptr, int size) 255 { 256 void *p = realloc(ptr, size); 257 258 if (p==NULL) 259 error(FATAL, "Out of memory from realloc"); 260 return p; 261 } 262 263 void * 264 domalloc(int size) 265 { 266 void *p = malloc(size); 267 268 if (p==NULL) 269 error(FATAL, "Out of memory from malloc"); 270 return p; 271 } 272 273 void 274 dofree(void *p) 275 { 276 free(p); 277 } 278 279 void 280 error(enum errtype type, char *string, ...) 281 { 282 va_list ap; 283 char *cp, *ep; 284 Token *tp; 285 Tokenrow *trp; 286 Source *s; 287 int i; 288 void *p; 289 290 fprintf(stderr, "cpp: "); 291 for (s=cursource; s; s=s->next) 292 if (*s->filename) 293 fprintf(stderr, "%s:%d ", s->filename, s->line); 294 va_start(ap, string); 295 for (ep=string; *ep; ep++) { 296 if (*ep=='%') { 297 switch (*++ep) { 298 299 case 's': 300 cp = va_arg(ap, char *); 301 fprintf(stderr, "%s", cp); 302 break; 303 case 'd': 304 i = va_arg(ap, int); 305 fprintf(stderr, "%d", i); 306 break; 307 case 'p': 308 p = va_arg(ap, void *); 309 fprintf(stderr, "%p", p); 310 break; 311 case 't': 312 tp = va_arg(ap, Token *); 313 fprintf(stderr, "%.*s", tp->len, tp->t); 314 break; 315 316 case 'r': 317 trp = va_arg(ap, Tokenrow *); 318 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) { 319 if (tp>trp->tp && tp->wslen) 320 fputc(' ', stderr); 321 fprintf(stderr, "%.*s", tp->len, tp->t); 322 } 323 break; 324 325 default: 326 fputc(*ep, stderr); 327 break; 328 } 329 } else 330 fputc(*ep, stderr); 331 } 332 va_end(ap); 333 fputc('\n', stderr); 334 if (type==FATAL) 335 exits("error"); 336 if (type!=WARNING) 337 nerrs = 1; 338 fflush(stderr); 339 } 340