mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-02-27 21:50:53 +00:00
Parsing some basic #ifs with defined()
This commit is contained in:
parent
bd5b2a8b58
commit
6ab09ef3bf
1 changed files with 123 additions and 49 deletions
172
ftepp.c
172
ftepp.c
|
@ -198,53 +198,119 @@ static bool ftepp_define(ftepp_t *ftepp)
|
||||||
static bool ftepp_if_expr(ftepp_t *ftepp, bool *out)
|
static bool ftepp_if_expr(ftepp_t *ftepp, bool *out)
|
||||||
{
|
{
|
||||||
ppmacro *macro;
|
ppmacro *macro;
|
||||||
while (ftepp->token != TOKEN_EOL) {
|
|
||||||
switch (ftepp->token) {
|
if (!ftepp_skipspace(ftepp))
|
||||||
case TOKEN_IDENT:
|
return false;
|
||||||
case TOKEN_TYPENAME:
|
|
||||||
case TOKEN_KEYWORD:
|
switch (ftepp->token) {
|
||||||
|
case TOKEN_IDENT:
|
||||||
|
case TOKEN_TYPENAME:
|
||||||
|
case TOKEN_KEYWORD:
|
||||||
|
if (!strcmp(ftepp_tokval(ftepp), "defined")) {
|
||||||
|
ftepp->lex->flags.noops = true;
|
||||||
|
ftepp_next(ftepp);
|
||||||
|
if (!ftepp_skipspace(ftepp))
|
||||||
|
return false;
|
||||||
|
if (ftepp->token != '(') {
|
||||||
|
ftepp_error(ftepp, "`defined` keyword in #if requires a macro name in parenthesis");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ftepp->lex->flags.noops = false;
|
||||||
|
ftepp_next(ftepp);
|
||||||
|
if (!ftepp_skipspace(ftepp))
|
||||||
|
return false;
|
||||||
|
if (ftepp->token != TOKEN_IDENT &&
|
||||||
|
ftepp->token != TOKEN_TYPENAME &&
|
||||||
|
ftepp->token != TOKEN_KEYWORD)
|
||||||
|
{
|
||||||
|
ftepp_error(ftepp, "defined() used on an unexpected token type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp));
|
macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp));
|
||||||
if (!macro || !vec_size(macro->output)) {
|
*out = !!macro;
|
||||||
*out = false;
|
ftepp_next(ftepp);
|
||||||
} else {
|
if (!ftepp_skipspace(ftepp))
|
||||||
/* This does not expand recursively! */
|
return false;
|
||||||
switch (macro->output[0]->token) {
|
if (ftepp->token != ')') {
|
||||||
case TOKEN_INTCONST:
|
ftepp_error(ftepp, "expected closing paren");
|
||||||
*out = !!(macro->output[0]->constval.f);
|
return false;
|
||||||
break;
|
|
||||||
case TOKEN_FLOATCONST:
|
|
||||||
*out = !!(macro->output[0]->constval.f);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*out = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TOKEN_STRINGCONST:
|
}
|
||||||
*out = false;
|
|
||||||
break;
|
|
||||||
case TOKEN_INTCONST:
|
|
||||||
*out = !!(ftepp->lex->tok.constval.i);
|
|
||||||
break;
|
|
||||||
case TOKEN_FLOATCONST:
|
|
||||||
*out = !!(ftepp->lex->tok.constval.f);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
macro = ftepp_macro_find(ftepp, ftepp_tokval(ftepp));
|
||||||
ftepp_error(ftepp, "junk in #if");
|
if (!macro || !vec_size(macro->output)) {
|
||||||
|
*out = false;
|
||||||
|
} else {
|
||||||
|
/* This does not expand recursively! */
|
||||||
|
switch (macro->output[0]->token) {
|
||||||
|
case TOKEN_INTCONST:
|
||||||
|
*out = !!(macro->output[0]->constval.f);
|
||||||
|
break;
|
||||||
|
case TOKEN_FLOATCONST:
|
||||||
|
*out = !!(macro->output[0]->constval.f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
*out = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case TOKEN_STRINGCONST:
|
||||||
|
*out = false;
|
||||||
|
break;
|
||||||
|
case TOKEN_INTCONST:
|
||||||
|
*out = !!(ftepp->lex->tok.constval.i);
|
||||||
|
break;
|
||||||
|
case TOKEN_FLOATCONST:
|
||||||
|
*out = !!(ftepp->lex->tok.constval.f);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
ftepp_next(ftepp);
|
||||||
|
if (!ftepp_if_expr(ftepp, out))
|
||||||
return false;
|
return false;
|
||||||
}
|
if (ftepp->token != ')') {
|
||||||
|
ftepp_error(ftepp, "expected closing paren in #if expression");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ftepp_error(ftepp, "junk in #if");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftepp_next(ftepp);
|
||||||
|
if (!ftepp_skipspace(ftepp))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ftepp->token == ')')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (ftepp->token != TOKEN_OPERATOR)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!strcmp(ftepp_tokval(ftepp), "&&") ||
|
||||||
|
!strcmp(ftepp_tokval(ftepp), "||"))
|
||||||
|
{
|
||||||
|
bool next = false;
|
||||||
|
char opc = ftepp_tokval(ftepp)[0];
|
||||||
|
|
||||||
ftepp_next(ftepp);
|
ftepp_next(ftepp);
|
||||||
if (!ftepp_skipspace(ftepp))
|
if (!ftepp_if_expr(ftepp, &next))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
switch (ftepp->token) {
|
if (opc == '&')
|
||||||
}
|
*out = *out && next;
|
||||||
|
else
|
||||||
|
*out = *out || next;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ftepp_error(ftepp, "junk after #if");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
(void)ftepp_next(ftepp);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ftepp_if(ftepp_t *ftepp, ppcondition *cond)
|
static bool ftepp_if(ftepp_t *ftepp, ppcondition *cond)
|
||||||
|
@ -338,15 +404,17 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "ifdef")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "ifdef")) {
|
||||||
if (!ftepp_ifdef(ftepp, &cond))
|
if (!ftepp_ifdef(ftepp, &cond))
|
||||||
return false;
|
return false;
|
||||||
|
cond.was_on = cond.on;
|
||||||
vec_push(ftepp->conditions, cond);
|
vec_push(ftepp->conditions, cond);
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "ifndef")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "ifndef")) {
|
||||||
if (!ftepp_ifdef(ftepp, &cond))
|
if (!ftepp_ifdef(ftepp, &cond))
|
||||||
return false;
|
return false;
|
||||||
cond.on = !cond.on;
|
cond.on = !cond.on;
|
||||||
|
cond.was_on = cond.on;
|
||||||
vec_push(ftepp->conditions, cond);
|
vec_push(ftepp->conditions, cond);
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "elifdef")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "elifdef")) {
|
||||||
if (!ftepp_else_allowed(ftepp))
|
if (!ftepp_else_allowed(ftepp))
|
||||||
|
@ -356,7 +424,7 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
pc = &vec_last(ftepp->conditions);
|
pc = &vec_last(ftepp->conditions);
|
||||||
pc->on = !pc->was_on && cond.on;
|
pc->on = !pc->was_on && cond.on;
|
||||||
pc->was_on = pc->was_on || pc->on;
|
pc->was_on = pc->was_on || pc->on;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "elifndef")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "elifndef")) {
|
||||||
if (!ftepp_else_allowed(ftepp))
|
if (!ftepp_else_allowed(ftepp))
|
||||||
|
@ -367,7 +435,7 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
pc = &vec_last(ftepp->conditions);
|
pc = &vec_last(ftepp->conditions);
|
||||||
pc->on = !pc->was_on && cond.on;
|
pc->on = !pc->was_on && cond.on;
|
||||||
pc->was_on = pc->was_on || pc->on;
|
pc->was_on = pc->was_on || pc->on;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "elif")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "elif")) {
|
||||||
if (!ftepp_else_allowed(ftepp))
|
if (!ftepp_else_allowed(ftepp))
|
||||||
|
@ -377,13 +445,14 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
pc = &vec_last(ftepp->conditions);
|
pc = &vec_last(ftepp->conditions);
|
||||||
pc->on = !pc->was_on && cond.on;
|
pc->on = !pc->was_on && cond.on;
|
||||||
pc->was_on = pc->was_on || pc->on;
|
pc->was_on = pc->was_on || pc->on;
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "if")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "if")) {
|
||||||
if (!ftepp_if(ftepp, &cond))
|
if (!ftepp_if(ftepp, &cond))
|
||||||
return false;
|
return false;
|
||||||
|
cond.was_on = cond.on;
|
||||||
vec_push(ftepp->conditions, cond);
|
vec_push(ftepp->conditions, cond);
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "else")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "else")) {
|
||||||
if (!ftepp_else_allowed(ftepp))
|
if (!ftepp_else_allowed(ftepp))
|
||||||
|
@ -391,7 +460,8 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
pc = &vec_last(ftepp->conditions);
|
pc = &vec_last(ftepp->conditions);
|
||||||
pc->on = !pc->was_on;
|
pc->on = !pc->was_on;
|
||||||
pc->had_else = true;
|
pc->had_else = true;
|
||||||
return true;
|
ftepp_next(ftepp);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else if (!strcmp(ftepp_tokval(ftepp), "endif")) {
|
else if (!strcmp(ftepp_tokval(ftepp), "endif")) {
|
||||||
if (!vec_size(ftepp->conditions)) {
|
if (!vec_size(ftepp->conditions)) {
|
||||||
|
@ -399,6 +469,7 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
vec_pop(ftepp->conditions);
|
vec_pop(ftepp->conditions);
|
||||||
|
ftepp_next(ftepp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -416,12 +487,15 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
ftepp_error(ftepp, "missing newline at end of file", ftepp_tokval(ftepp));
|
ftepp_error(ftepp, "missing newline at end of file", ftepp_tokval(ftepp));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!ftepp_skipspace(ftepp))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ftepp_out(ftepp_t *ftepp, const char *str)
|
static void ftepp_out(ftepp_t *ftepp, const char *str, bool ignore_cond)
|
||||||
{
|
{
|
||||||
if (!vec_size(ftepp->conditions) ||
|
if (ignore_cond ||
|
||||||
|
!vec_size(ftepp->conditions) ||
|
||||||
vec_last(ftepp->conditions).on)
|
vec_last(ftepp->conditions).on)
|
||||||
{
|
{
|
||||||
printf("%s", str);
|
printf("%s", str);
|
||||||
|
@ -446,7 +520,7 @@ static bool ftepp_preprocess(ftepp_t *ftepp)
|
||||||
switch (ftepp->token) {
|
switch (ftepp->token) {
|
||||||
case '#':
|
case '#':
|
||||||
if (!ftepp->newline) {
|
if (!ftepp->newline) {
|
||||||
ftepp_out(ftepp, ftepp_tokval(ftepp));
|
ftepp_out(ftepp, ftepp_tokval(ftepp), false);
|
||||||
ftepp_next(ftepp);
|
ftepp_next(ftepp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -460,11 +534,11 @@ static bool ftepp_preprocess(ftepp_t *ftepp)
|
||||||
break;
|
break;
|
||||||
case TOKEN_EOL:
|
case TOKEN_EOL:
|
||||||
newline = true;
|
newline = true;
|
||||||
ftepp_out(ftepp, "\n");
|
ftepp_out(ftepp, "\n", true);
|
||||||
ftepp_next(ftepp);
|
ftepp_next(ftepp);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ftepp_out(ftepp, ftepp_tokval(ftepp));
|
ftepp_out(ftepp, ftepp_tokval(ftepp), false);
|
||||||
ftepp_next(ftepp);
|
ftepp_next(ftepp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue