Quake-III-Arena

Quake III Arena GPL Source Release
Log | Files | Refs

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 }