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