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