q3rally/engine/code/tools/lcc/cpp/cpp.c
zturtleman 9b86138351 ioquake3 resync to revision 3550 from 3534.
Fix IQM quat normalize fail case
Remove erroneous newlines from Com_Error in sdl_glimp.c
Restore OpenGL 1.1 support (GL_CLAMP)
q3rcc: Allow to override build date
Fix lightning gun handling for corpses and single player podiums
Fix for macOS Catalina screen resolution issue
Fix team orders menu not listing clients with lower clientnums
Fix duplicate team join center print for bots and g_teamAutoJoin
E2K: fixed build by MCST lcc compiler when using USE_CURL=1 option
2020-03-15 19:40:23 +00:00

335 lines
6.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdarg.h>
#include "cpp.h"
char rcsid[] = "cpp.c - faked rcsid";
#define OUTS 16384
char outbuf[OUTS];
char *outbufp = outbuf;
Source *cursource;
int nerrs;
struct token nltoken = { NL, 0, 0, 0, 1, (uchar*)"\n" };
char *curtime;
int incdepth;
int ifdepth;
int ifsatisfied[NIF];
int skipping;
time_t reproducible_time()
{
char *source_date_epoch;
time_t t;
if ((source_date_epoch = getenv("SOURCE_DATE_EPOCH")) == NULL ||
(t = (time_t)strtol(source_date_epoch, NULL, 10)) <= 0)
return time(NULL);
return t;
}
int
main(int argc, char **argv)
{
Tokenrow tr;
time_t t;
char ebuf[BUFSIZ];
setbuf(stderr, ebuf);
t = reproducible_time();
curtime = ctime(&t);
maketokenrow(3, &tr);
expandlex();
setup(argc, argv);
fixlex();
iniths();
genline();
process(&tr);
flushout();
fflush(stderr);
exit(nerrs > 0);
return 0;
}
void
process(Tokenrow *trp)
{
int anymacros = 0;
for (;;) {
if (trp->tp >= trp->lp) {
trp->tp = trp->lp = trp->bp;
outbufp = outbuf;
anymacros |= gettokens(trp, 1);
trp->tp = trp->bp;
}
if (trp->tp->type == END) {
if (--incdepth>=0) {
if (cursource->ifdepth)
error(ERROR,
"Unterminated conditional in #include");
unsetsource();
cursource->line += cursource->lineinc;
trp->tp = trp->lp;
genline();
continue;
}
if (ifdepth)
error(ERROR, "Unterminated #if/#ifdef/#ifndef");
break;
}
if (trp->tp->type==SHARP) {
trp->tp += 1;
control(trp);
} else if (!skipping && anymacros)
expandrow(trp, NULL);
if (skipping)
setempty(trp);
puttokens(trp);
anymacros = 0;
cursource->line += cursource->lineinc;
if (cursource->lineinc>1) {
genline();
}
}
}
void
control(Tokenrow *trp)
{
Nlist *np;
Token *tp;
tp = trp->tp;
if (tp->type!=NAME) {
if (tp->type==NUMBER)
goto kline;
if (tp->type != NL)
error(ERROR, "Unidentifiable control line");
return; /* else empty line */
}
if ((np = lookup(tp, 0))==NULL || ((np->flag&ISKW)==0 && !skipping)) {
error(WARNING, "Unknown preprocessor control %t", tp);
return;
}
if (skipping) {
switch (np->val) {
case KENDIF:
if (--ifdepth<skipping)
skipping = 0;
--cursource->ifdepth;
setempty(trp);
return;
case KIFDEF:
case KIFNDEF:
case KIF:
if (++ifdepth >= NIF)
error(FATAL, "#if too deeply nested");
++cursource->ifdepth;
return;
case KELIF:
case KELSE:
if (ifdepth<=skipping)
break;
return;
default:
return;
}
}
switch (np->val) {
case KDEFINE:
dodefine(trp);
break;
case KUNDEF:
tp += 1;
if (tp->type!=NAME || trp->lp - trp->bp != 4) {
error(ERROR, "Syntax error in #undef");
break;
}
if ((np = lookup(tp, 0)) != NULL)
np->flag &= ~ISDEFINED;
break;
case KPRAGMA:
return;
case KIFDEF:
case KIFNDEF:
case KIF:
if (++ifdepth >= NIF)
error(FATAL, "#if too deeply nested");
++cursource->ifdepth;
ifsatisfied[ifdepth] = 0;
if (eval(trp, np->val))
ifsatisfied[ifdepth] = 1;
else
skipping = ifdepth;
break;
case KELIF:
if (ifdepth==0) {
error(ERROR, "#elif with no #if");
return;
}
if (ifsatisfied[ifdepth]==2)
error(ERROR, "#elif after #else");
if (eval(trp, np->val)) {
if (ifsatisfied[ifdepth])
skipping = ifdepth;
else {
skipping = 0;
ifsatisfied[ifdepth] = 1;
}
} else
skipping = ifdepth;
break;
case KELSE:
if (ifdepth==0 || cursource->ifdepth==0) {
error(ERROR, "#else with no #if");
return;
}
if (ifsatisfied[ifdepth]==2)
error(ERROR, "#else after #else");
if (trp->lp - trp->bp != 3)
error(ERROR, "Syntax error in #else");
skipping = ifsatisfied[ifdepth]? ifdepth: 0;
ifsatisfied[ifdepth] = 2;
break;
case KENDIF:
if (ifdepth==0 || cursource->ifdepth==0) {
error(ERROR, "#endif with no #if");
return;
}
--ifdepth;
--cursource->ifdepth;
if (trp->lp - trp->bp != 3)
error(WARNING, "Syntax error in #endif");
break;
case KWARNING:
trp->tp = tp+1;
error(WARNING, "#warning directive: %r", trp);
break;
case KERROR:
trp->tp = tp+1;
error(ERROR, "#error directive: %r", trp);
break;
case KLINE:
trp->tp = tp+1;
expandrow(trp, "<line>");
tp = trp->bp+2;
kline:
if (tp+1>=trp->lp || tp->type!=NUMBER || tp+3<trp->lp
|| ((tp+3==trp->lp && ((tp+1)->type!=STRING))||*(tp+1)->t=='L')){
error(ERROR, "Syntax error in #line");
return;
}
cursource->line = atol((char*)tp->t)-1;
if (cursource->line<0 || cursource->line>=32768)
error(WARNING, "#line specifies number out of range");
tp = tp+1;
if (tp+1<trp->lp)
cursource->filename=(char*)newstring(tp->t+1,tp->len-2,0);
return;
case KDEFINED:
error(ERROR, "Bad syntax for control line");
break;
case KINCLUDE:
doinclude(trp);
trp->lp = trp->bp;
return;
case KEVAL:
eval(trp, np->val);
break;
default:
error(ERROR, "Preprocessor control `%t' not yet implemented", tp);
break;
}
setempty(trp);
}
void *
domalloc(int size)
{
void *p = malloc(size);
if (p==NULL)
error(FATAL, "Out of memory from malloc");
return p;
}
void
dofree(void *p)
{
free(p);
}
void
error(enum errtype type, char *string, ...)
{
va_list ap;
char *cp, *ep;
Token *tp;
Tokenrow *trp;
Source *s;
int i;
fprintf(stderr, "cpp: ");
for (s=cursource; s; s=s->next)
if (*s->filename)
fprintf(stderr, "%s:%d ", s->filename, s->line);
va_start(ap, string);
for (ep=string; *ep; ep++) {
if (*ep=='%') {
switch (*++ep) {
case 's':
cp = va_arg(ap, char *);
fprintf(stderr, "%s", cp);
break;
case 'd':
i = va_arg(ap, int);
fprintf(stderr, "%d", i);
break;
case 't':
tp = va_arg(ap, Token *);
fprintf(stderr, "%.*s", tp->len, tp->t);
break;
case 'r':
trp = va_arg(ap, Tokenrow *);
for (tp=trp->tp; tp<trp->lp&&tp->type!=NL; tp++) {
if (tp>trp->tp && tp->wslen)
fputc(' ', stderr);
fprintf(stderr, "%.*s", tp->len, tp->t);
}
break;
default:
fputc(*ep, stderr);
break;
}
} else
fputc(*ep, stderr);
}
va_end(ap);
fputc('\n', stderr);
if (type==FATAL)
exit(1);
if (type!=WARNING)
nerrs = 1;
fflush(stderr);
}