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