cpp.c (5899B)
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 char rcsid[] = "cpp.c - faked rcsid"; 9 10 #define OUTS 16384 11 char outbuf[OUTS]; 12 char *outp = outbuf; 13 Source *cursource; 14 int nerrs; 15 struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" }; 16 char *curtime; 17 int incdepth; 18 int ifdepth; 19 int ifsatisfied[NIF]; 20 int skipping; 21 22 23 int 24 main(int argc, char **argv) 25 { 26 Tokenrow tr; 27 time_t t; 28 char ebuf[BUFSIZ]; 29 30 setbuf(stderr, ebuf); 31 t = time(NULL); 32 curtime = ctime(&t); 33 maketokenrow(3, &tr); 34 expandlex(); 35 setup(argc, argv); 36 fixlex(); 37 iniths(); 38 genline(); 39 process(&tr); 40 flushout(); 41 fflush(stderr); 42 exit(nerrs > 0); 43 return 0; 44 } 45 46 void 47 process(Tokenrow *trp) 48 { 49 int anymacros = 0; 50 51 for (;;) { 52 if (trp->tp >= trp->lp) { 53 trp->tp = trp->lp = trp->bp; 54 outp = outbuf; 55 anymacros |= gettokens(trp, 1); 56 trp->tp = trp->bp; 57 } 58 if (trp->tp->type == END) { 59 if (--incdepth>=0) { 60 if (cursource->ifdepth) 61 error(ERROR, 62 "Unterminated conditional in #include"); 63 unsetsource(); 64 cursource->line += cursource->lineinc; 65 trp->tp = trp->lp; 66 genline(); 67 continue; 68 } 69 if (ifdepth) 70 error(ERROR, "Unterminated #if/#ifdef/#ifndef"); 71 break; 72 } 73 if (trp->tp->type==SHARP) { 74 trp->tp += 1; 75 control(trp); 76 } else if (!skipping && anymacros) 77 expandrow(trp, NULL); 78 if (skipping) 79 setempty(trp); 80 puttokens(trp); 81 anymacros = 0; 82 cursource->line += cursource->lineinc; 83 if (cursource->lineinc>1) { 84 genline(); 85 } 86 } 87 } 88 89 void 90 control(Tokenrow *trp) 91 { 92 Nlist *np; 93 Token *tp; 94 95 tp = trp->tp; 96 if (tp->type!=NAME) { 97 if (tp->type==NUMBER) 98 goto kline; 99 if (tp->type != NL) 100 error(ERROR, "Unidentifiable control line"); 101 return; /* else empty line */ 102 } 103 if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) { 104 error(WARNING, "Unknown preprocessor control %t", tp); 105 return; 106 } 107 if (skipping) { 108 switch (np->val) { 109 case KENDIF: 110 if (--ifdepth<skipping) 111 skipping = 0; 112 --cursource->ifdepth; 113 setempty(trp); 114 return; 115 116 case KIFDEF: 117 case KIFNDEF: 118 case KIF: 119 if (++ifdepth >= NIF) 120 error(FATAL, "#if too deeply nested"); 121 ++cursource->ifdepth; 122 return; 123 124 case KELIF: 125 case KELSE: 126 if (ifdepth<=skipping) 127 break; 128 return; 129 130 default: 131 return; 132 } 133 } 134 switch (np->val) { 135 case KDEFINE: 136 dodefine(trp); 137 break; 138 139 case KUNDEF: 140 tp += 1; 141 if (tp->type!=NAME || trp->lp - trp->bp != 4) { 142 error(ERROR, "Syntax error in #undef"); 143 break; 144 } 145 if ((np = lookup(tp, 0)) != NULL) 146 np->flag &= ~ISDEFINED; 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 exit(1); 319 if (type!=WARNING) 320 nerrs = 1; 321 fflush(stderr); 322 }