Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

cpp.c

Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <string.h>
00004 #include <time.h>
00005 #include <stdarg.h>
00006 #include "cpp.h"
00007 
00008 char rcsid[] = "cpp.c - faked rcsid";
00009 
00010 #define OUTS    16384
00011 char    outbuf[OUTS];
00012 char    *outp = outbuf;
00013 Source  *cursource;
00014 int nerrs;
00015 struct  token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
00016 char    *curtime;
00017 int incdepth;
00018 int ifdepth;
00019 int ifsatisfied[NIF];
00020 int skipping;
00021 
00022 
00023 int
00024 main(int argc, char **argv)
00025 {
00026     Tokenrow tr;
00027     time_t t;
00028     char ebuf[BUFSIZ];
00029 
00030     setbuf(stderr, ebuf);
00031     t = time(NULL);
00032     curtime = ctime(&t);
00033     maketokenrow(3, &tr);
00034     expandlex();
00035     setup(argc, argv);
00036     fixlex();
00037     iniths();
00038     genline();
00039     process(&tr);
00040     flushout();
00041     fflush(stderr);
00042     exit(nerrs > 0);
00043     return 0;
00044 }
00045 
00046 void
00047 process(Tokenrow *trp)
00048 {
00049     int anymacros = 0;
00050 
00051     for (;;) {
00052         if (trp->tp >= trp->lp) {
00053             trp->tp = trp->lp = trp->bp;
00054             outp = outbuf;
00055             anymacros |= gettokens(trp, 1);
00056             trp->tp = trp->bp;
00057         }
00058         if (trp->tp->type == END) {
00059             if (--incdepth>=0) {
00060                 if (cursource->ifdepth)
00061                     error(ERROR,
00062                      "Unterminated conditional in #include");
00063                 unsetsource();
00064                 cursource->line += cursource->lineinc;
00065                 trp->tp = trp->lp;
00066                 genline();
00067                 continue;
00068             }
00069             if (ifdepth)
00070                 error(ERROR, "Unterminated #if/#ifdef/#ifndef");
00071             break;
00072         }
00073         if (trp->tp->type==SHARP) {
00074             trp->tp += 1;
00075             control(trp);
00076         } else if (!skipping && anymacros)
00077             expandrow(trp, NULL);
00078         if (skipping)
00079             setempty(trp);
00080         puttokens(trp);
00081         anymacros = 0;
00082         cursource->line += cursource->lineinc;
00083         if (cursource->lineinc>1) {
00084             genline();
00085         }
00086     }
00087 }
00088     
00089 void
00090 control(Tokenrow *trp)
00091 {
00092     Nlist *np;
00093     Token *tp;
00094 
00095     tp = trp->tp;
00096     if (tp->type!=NAME) {
00097         if (tp->type==NUMBER)
00098             goto kline;
00099         if (tp->type != NL)
00100             error(ERROR, "Unidentifiable control line");
00101         return;         /* else empty line */
00102     }
00103     if ((np = lookup(tp, 0))==NULL || (np->flag&ISKW)==0 && !skipping) {
00104         error(WARNING, "Unknown preprocessor control %t", tp);
00105         return;
00106     }
00107     if (skipping) {
00108         switch (np->val) {
00109         case KENDIF:
00110             if (--ifdepth<skipping)
00111                 skipping = 0;
00112             --cursource->ifdepth;
00113             setempty(trp);
00114             return;
00115 
00116         case KIFDEF:
00117         case KIFNDEF:
00118         case KIF:
00119             if (++ifdepth >= NIF)
00120                 error(FATAL, "#if too deeply nested");
00121             ++cursource->ifdepth;
00122             return;
00123 
00124         case KELIF:
00125         case KELSE:
00126             if (ifdepth<=skipping)
00127                 break;
00128             return;
00129 
00130         default:
00131             return;
00132         }
00133     }
00134     switch (np->val) {
00135     case KDEFINE:
00136         dodefine(trp);
00137         break;
00138 
00139     case KUNDEF:
00140         tp += 1;
00141         if (tp->type!=NAME || trp->lp - trp->bp != 4) {
00142             error(ERROR, "Syntax error in #undef");
00143             break;
00144         }
00145         if ((np = lookup(tp, 0)) != NULL)
00146             np->flag &= ~ISDEFINED;
00147         break;
00148 
00149     case KPRAGMA:
00150         return;
00151 
00152     case KIFDEF:
00153     case KIFNDEF:
00154     case KIF:
00155         if (++ifdepth >= NIF)
00156             error(FATAL, "#if too deeply nested");
00157         ++cursource->ifdepth;
00158         ifsatisfied[ifdepth] = 0;
00159         if (eval(trp, np->val))
00160             ifsatisfied[ifdepth] = 1;
00161         else
00162             skipping = ifdepth;
00163         break;
00164 
00165     case KELIF:
00166         if (ifdepth==0) {
00167             error(ERROR, "#elif with no #if");
00168             return;
00169         }
00170         if (ifsatisfied[ifdepth]==2)
00171             error(ERROR, "#elif after #else");
00172         if (eval(trp, np->val)) {
00173             if (ifsatisfied[ifdepth])
00174                 skipping = ifdepth;
00175             else {
00176                 skipping = 0;
00177                 ifsatisfied[ifdepth] = 1;
00178             }
00179         } else
00180             skipping = ifdepth;
00181         break;
00182 
00183     case KELSE:
00184         if (ifdepth==0 || cursource->ifdepth==0) {
00185             error(ERROR, "#else with no #if");
00186             return;
00187         }
00188         if (ifsatisfied[ifdepth]==2)
00189             error(ERROR, "#else after #else");
00190         if (trp->lp - trp->bp != 3)
00191             error(ERROR, "Syntax error in #else");
00192         skipping = ifsatisfied[ifdepth]? ifdepth: 0;
00193         ifsatisfied[ifdepth] = 2;
00194         break;
00195 
00196     case KENDIF:
00197         if (ifdepth==0 || cursource->ifdepth==0) {
00198             error(ERROR, "#endif with no #if");
00199             return;
00200         }
00201         --ifdepth;
00202         --cursource->ifdepth;
00203         if (trp->lp - trp->bp != 3)
00204             error(WARNING, "Syntax error in #endif");
00205         break;
00206 
00207     case KERROR:
00208         trp->tp = tp+1;
00209         error(WARNING, "#error directive: %r", trp);
00210         break;
00211 
00212     case KLINE:
00213         trp->tp = tp+1;
00214         expandrow(trp, "<line>");
00215         tp = trp->bp+2;
00216     kline:
00217         if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
00218          || (tp+3==trp->lp && ((tp+1)->type!=STRING)||*(tp+1)->t=='L')){
00219             error(ERROR, "Syntax error in #line");
00220             return;
00221         }
00222         cursource->line = atol((char*)tp->t)-1;
00223         if (cursource->line<0 || cursource->line>=32768)
00224             error(WARNING, "#line specifies number out of range");
00225         tp = tp+1;
00226         if (tp+1<trp->lp)
00227             cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
00228         return;
00229 
00230     case KDEFINED:
00231         error(ERROR, "Bad syntax for control line");
00232         break;
00233 
00234     case KINCLUDE:
00235         doinclude(trp);
00236         trp->lp = trp->bp;
00237         return;
00238 
00239     case KEVAL:
00240         eval(trp, np->val);
00241         break;
00242 
00243     default:
00244         error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
00245         break;
00246     }
00247     setempty(trp);
00248     return;
00249 }
00250 
00251 void *
00252 domalloc(int size)
00253 {
00254     void *p = malloc(size);
00255 
00256     if (p==NULL)
00257         error(FATAL, "Out of memory from malloc");
00258     return p;
00259 }
00260 
00261 void
00262 dofree(void *p)
00263 {
00264     free(p);
00265 }
00266 
00267 void
00268 error(enum errtype type, char *string, ...)
00269 {
00270     va_list ap;
00271     char *cp, *ep;
00272     Token *tp;
00273     Tokenrow *trp;
00274     Source *s;
00275     int i;
00276 
00277     fprintf(stderr, "cpp: ");
00278     for (s=cursource; s; s=s->next)
00279         if (*s->filename)
00280             fprintf(stderr, "%s:%d ", s->filename, s->line);
00281     va_start(ap, string);
00282     for (ep=string; *ep; ep++) {
00283         if (*ep=='%') {
00284             switch (*++ep) {
00285 
00286             case 's':
00287                 cp = va_arg(ap, char *);
00288                 fprintf(stderr, "%s", cp);
00289                 break;
00290             case 'd':
00291                 i = va_arg(ap, int);
00292                 fprintf(stderr, "%d", i);
00293                 break;
00294             case 't':
00295                 tp = va_arg(ap, Token *);
00296                 fprintf(stderr, "%.*s", tp->len, tp->t);
00297                 break;
00298 
00299             case 'r':
00300                 trp = va_arg(ap, Tokenrow *);
00301                 for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
00302                     if (tp>trp->tp && tp->wslen)
00303                         fputc(' ', stderr);
00304                     fprintf(stderr, "%.*s", tp->len, tp->t);
00305                 }
00306                 break;
00307 
00308             default:
00309                 fputc(*ep, stderr);
00310                 break;
00311             }
00312         } else
00313             fputc(*ep, stderr);
00314     }
00315     va_end(ap);
00316     fputc('\n', stderr);
00317     if (type==FATAL)
00318         exit(1);
00319     if (type!=WARNING)
00320         nerrs = 1;
00321     fflush(stderr);
00322 }

Generated on Thu Aug 25 12:38:08 2005 for Quake III Arena by  doxygen 1.3.9.1