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;
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 }