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 domalloc(int size) 255 { 256 void *p = malloc(size); 257 258 if (p==NULL) 259 error(FATAL, "Out of memory from malloc"); 260 return p; 261 } 262 263 void 264 dofree(void *p) 265 { 266 free(p); 267 } 268 269 void 270 error(enum errtype type, char *string, ...) 271 { 272 va_list ap; 273 char *cp, *ep; 274 Token *tp; 275 Tokenrow *trp; 276 Source *s; 277 int i; 278 void *p; 279 280 fprintf(stderr, "cpp: "); 281 for (s=cursource; s; s=s->next) 282 if (*s->filename) 283 fprintf(stderr, "%s:%d ", s->filename, s->line); 284 va_start(ap, string); 285 for (ep=string; *ep; ep++) { 286 if (*ep=='%') { 287 switch (*++ep) { 288 289 case 's': 290 cp = va_arg(ap, char *); 291 fprintf(stderr, "%s", cp); 292 break; 293 case 'd': 294 i = va_arg(ap, int); 295 fprintf(stderr, "%d", i); 296 break; 297 case 'p': 298 p = va_arg(ap, void *); 299 fprintf(stderr, "%p", p); 300 break; 301 case 't': 302 tp = va_arg(ap, Token *); 303 fprintf(stderr, "%.*s", tp->len, tp->t); 304 break; 305 306 case 'r': 307 trp = va_arg(ap, Tokenrow *); 308 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) { 309 if (tp>trp->tp && tp->wslen) 310 fputc(' ', stderr); 311 fprintf(stderr, "%.*s", tp->len, tp->t); 312 } 313 break; 314 315 default: 316 fputc(*ep, stderr); 317 break; 318 } 319 } else 320 fputc(*ep, stderr); 321 } 322 va_end(ap); 323 fputc('\n', stderr); 324 if (type==FATAL) 325 exits("error"); 326 if (type!=WARNING) 327 nerrs = 1; 328 fflush(stderr); 329 } 330