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 switch (np->val) { 104 case KENDIF: 105 if (--ifdepth<skipping) 106 skipping = 0; 107 --cursource->ifdepth; 108 setempty(trp); 109 return; 110 111 case KIFDEF: 112 case KIFNDEF: 113 case KIF: 114 if (++ifdepth >= NIF) 115 error(FATAL, "#if too deeply nested"); 116 ++cursource->ifdepth; 117 return; 118 119 case KELIF: 120 case KELSE: 121 if (ifdepth<=skipping) 122 break; 123 return; 124 125 default: 126 return; 127 } 128 } 129 switch (np->val) { 130 case KDEFINE: 131 dodefine(trp); 132 break; 133 134 case KUNDEF: 135 tp += 1; 136 if (tp->type!=NAME || trp->lp - trp->bp != 4) { 137 error(ERROR, "Syntax error in #undef"); 138 break; 139 } 140 if ((np = lookup(tp, 0))) { 141 if (np->flag&ISUNCHANGE) { 142 error(ERROR, "#defined token %t can't be undefined", tp); 143 return; 144 } 145 np->flag &= ~ISDEFINED; 146 } 147 break; 148 149 case KPRAGMA: 150 return; 151 152 case KIFDEF: 153 case KIFNDEF: 154 case KIF: 155 if (++ifdepth >= NIF) 156 error(FATAL, "#if too deeply nested"); 157 ++cursource->ifdepth; 158 ifsatisfied[ifdepth] = 0; 159 if (eval(trp, np->val)) 160 ifsatisfied[ifdepth] = 1; 161 else 162 skipping = ifdepth; 163 break; 164 165 case KELIF: 166 if (ifdepth==0) { 167 error(ERROR, "#elif with no #if"); 168 return; 169 } 170 if (ifsatisfied[ifdepth]==2) 171 error(ERROR, "#elif after #else"); 172 if (eval(trp, np->val)) { 173 if (ifsatisfied[ifdepth]) 174 skipping = ifdepth; 175 else { 176 skipping = 0; 177 ifsatisfied[ifdepth] = 1; 178 } 179 } else 180 skipping = ifdepth; 181 break; 182 183 case KELSE: 184 if (ifdepth==0 || cursource->ifdepth==0) { 185 error(ERROR, "#else with no #if"); 186 return; 187 } 188 if (ifsatisfied[ifdepth]==2) 189 error(ERROR, "#else after #else"); 190 if (trp->lp - trp->bp != 3) 191 error(ERROR, "Syntax error in #else"); 192 skipping = ifsatisfied[ifdepth]? ifdepth: 0; 193 ifsatisfied[ifdepth] = 2; 194 break; 195 196 case KENDIF: 197 if (ifdepth==0 || cursource->ifdepth==0) { 198 error(ERROR, "#endif with no #if"); 199 return; 200 } 201 --ifdepth; 202 --cursource->ifdepth; 203 if (trp->lp - trp->bp != 3) 204 error(WARNING, "Syntax error in #endif"); 205 break; 206 207 case KERROR: 208 trp->tp = tp+1; 209 error(WARNING, "#error directive: %r", trp); 210 break; 211 212 case KLINE: 213 trp->tp = tp+1; 214 expandrow(trp, "<line>"); 215 tp = trp->bp+2; 216 kline: 217 if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp 218 || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){ 219 error(ERROR, "Syntax error in #line"); 220 return; 221 } 222 cursource->line = atol((char*)tp->t)-1; 223 if (cursource->line<0 || cursource->line>=32768) 224 error(WARNING, "#line specifies number out of range"); 225 tp = tp+1; 226 if (tp+1<trp->lp) 227 cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0); 228 return; 229 230 case KDEFINED: 231 error(ERROR, "Bad syntax for control line"); 232 break; 233 234 case KINCLUDE: 235 doinclude(trp); 236 trp->lp = trp->bp; 237 return; 238 239 case KEVAL: 240 eval(trp, np->val); 241 break; 242 243 default: 244 error(ERROR, "Preprocessor control `%t' not yet implemented", tp); 245 break; 246 } 247 setempty(trp); 248 return; 249 } 250 251 void * 252 domalloc(int size) 253 { 254 void *p = malloc(size); 255 256 if (p==NULL) 257 error(FATAL, "Out of memory from malloc"); 258 return p; 259 } 260 261 void 262 dofree(void *p) 263 { 264 free(p); 265 } 266 267 void 268 error(enum errtype type, char *string, ...) 269 { 270 va_list ap; 271 char *cp, *ep; 272 Token *tp; 273 Tokenrow *trp; 274 Source *s; 275 int i; 276 277 fprintf(stderr, "cpp: "); 278 for (s=cursource; s; s=s->next) 279 if (*s->filename) 280 fprintf(stderr, "%s:%d ", s->filename, s->line); 281 va_start(ap, string); 282 for (ep=string; *ep; ep++) { 283 if (*ep=='%') { 284 switch (*++ep) { 285 286 case 's': 287 cp = va_arg(ap, char *); 288 fprintf(stderr, "%s", cp); 289 break; 290 case 'd': 291 i = va_arg(ap, int); 292 fprintf(stderr, "%d", i); 293 break; 294 case 't': 295 tp = va_arg(ap, Token *); 296 fprintf(stderr, "%.*s", tp->len, tp->t); 297 break; 298 299 case 'r': 300 trp = va_arg(ap, Tokenrow *); 301 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) { 302 if (tp>trp->tp && tp->wslen) 303 fputc(' ', stderr); 304 fprintf(stderr, "%.*s", tp->len, tp->t); 305 } 306 break; 307 308 default: 309 fputc(*ep, stderr); 310 break; 311 } 312 } else 313 fputc(*ep, stderr); 314 } 315 va_end(ap); 316 fputc('\n', stderr); 317 if (type==FATAL) 318 exits("error"); 319 if (type!=WARNING) 320 nerrs = 1; 321 fflush(stderr); 322 } 323