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