mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-24 04:41:25 +00:00
Removed #warning and #error from ftepp, and made it part of the parser routine. These are "directives" that should exist regardless if -fftepp is enabled, like #pragma. Implemented #warning, #message and #error as directives in parser instead.
This commit is contained in:
parent
7ea1033a43
commit
3d35804a7d
2 changed files with 97 additions and 76 deletions
57
ftepp.c
57
ftepp.c
|
@ -1269,55 +1269,6 @@ static char *ftepp_include_find(ftepp_t *ftepp, const char *file)
|
|||
return filename;
|
||||
}
|
||||
|
||||
static bool ftepp_directive_warning(ftepp_t *ftepp) {
|
||||
char *message = NULL;
|
||||
|
||||
if (!ftepp_skipspace(ftepp))
|
||||
return false;
|
||||
|
||||
/* handle the odd non string constant case so it works like C */
|
||||
if (ftepp->token != TOKEN_STRINGCONST) {
|
||||
bool store = false;
|
||||
vec_upload(message, "#warning", 8);
|
||||
ftepp_next(ftepp);
|
||||
while (ftepp->token != TOKEN_EOL) {
|
||||
vec_upload(message, ftepp_tokval(ftepp), strlen(ftepp_tokval(ftepp)));
|
||||
ftepp_next(ftepp);
|
||||
}
|
||||
vec_push(message, '\0');
|
||||
store = ftepp_warn(ftepp, WARN_CPP, message);
|
||||
vec_free(message);
|
||||
return store;
|
||||
}
|
||||
|
||||
unescape (ftepp_tokval(ftepp), ftepp_tokval(ftepp));
|
||||
return ftepp_warn(ftepp, WARN_CPP, "#warning %s", ftepp_tokval(ftepp));
|
||||
}
|
||||
|
||||
static void ftepp_directive_error(ftepp_t *ftepp) {
|
||||
char *message = NULL;
|
||||
|
||||
if (!ftepp_skipspace(ftepp))
|
||||
return;
|
||||
|
||||
/* handle the odd non string constant case so it works like C */
|
||||
if (ftepp->token != TOKEN_STRINGCONST) {
|
||||
vec_upload(message, "#error", 6);
|
||||
ftepp_next(ftepp);
|
||||
while (ftepp->token != TOKEN_EOL) {
|
||||
vec_upload(message, ftepp_tokval(ftepp), strlen(ftepp_tokval(ftepp)));
|
||||
ftepp_next(ftepp);
|
||||
}
|
||||
vec_push(message, '\0');
|
||||
ftepp_error(ftepp, message);
|
||||
vec_free(message);
|
||||
return;
|
||||
}
|
||||
|
||||
unescape (ftepp_tokval(ftepp), ftepp_tokval(ftepp));
|
||||
ftepp_error(ftepp, "#error %s", ftepp_tokval(ftepp));
|
||||
}
|
||||
|
||||
/**
|
||||
* Include a file.
|
||||
* FIXME: do we need/want a -I option?
|
||||
|
@ -1513,14 +1464,6 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
|||
ftepp_out(ftepp, "#", false);
|
||||
break;
|
||||
}
|
||||
else if (!strcmp(ftepp_tokval(ftepp), "warning")) {
|
||||
ftepp_directive_warning(ftepp);
|
||||
break;
|
||||
}
|
||||
else if (!strcmp(ftepp_tokval(ftepp), "error")) {
|
||||
ftepp_directive_error(ftepp);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
if (ftepp->output_on) {
|
||||
ftepp_error(ftepp, "unrecognized preprocessor directive: `%s`", ftepp_tokval(ftepp));
|
||||
|
|
116
parser.c
116
parser.c
|
@ -3292,15 +3292,26 @@ static bool parse_eol(parser_t *parser)
|
|||
return parser->tok == TOKEN_EOL;
|
||||
}
|
||||
|
||||
static bool parse_pragma_do(parser_t *parser)
|
||||
{
|
||||
if (!parser_next(parser) ||
|
||||
parser->tok != TOKEN_IDENT ||
|
||||
strcmp(parser_tokval(parser), "pragma"))
|
||||
{
|
||||
parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* Traditionally you'd implement warning, error, and message
|
||||
* directives in the preprocessor. However, like #pragma, these
|
||||
* shouldn't depend on -fftepp to utilize. So they're instead
|
||||
* implemented here.
|
||||
*/
|
||||
enum {
|
||||
PARSE_DIRECTIVE_ERROR,
|
||||
PARSE_DIRECTIVE_MESSAGE,
|
||||
PARSE_DIRECTIVE_WARNING,
|
||||
PARSE_DIRECTIVE_COUNT
|
||||
};
|
||||
|
||||
static const char *parser_directives[PARSE_DIRECTIVE_COUNT] = {
|
||||
"error",
|
||||
"message",
|
||||
"warning"
|
||||
};
|
||||
|
||||
static bool parse_pragma_do(parser_t *parser) {
|
||||
if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
|
||||
parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
|
||||
return false;
|
||||
|
@ -3311,35 +3322,102 @@ static bool parse_pragma_do(parser_t *parser)
|
|||
parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
|
||||
return false;
|
||||
}
|
||||
|
||||
parser->noref = !!parser_token(parser)->constval.i;
|
||||
|
||||
if (!parse_eol(parser)) {
|
||||
parseerror(parser, "parse error after `noref` pragma");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
(void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_directive_or_pragma_do(parser_t *parser, bool *pragma) {
|
||||
|
||||
size_t type = PARSE_DIRECTIVE_COUNT;
|
||||
|
||||
if (!parser_next(parser) || parser->tok != TOKEN_IDENT) {
|
||||
parseerror(parser, "expected `pragma, error, message, warning` after `#`, got `%s`",
|
||||
parser_tokval(parser));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strcmp(parser_tokval(parser), "pragma" )) {
|
||||
*pragma = true;
|
||||
|
||||
return parse_pragma_do(parser);
|
||||
}
|
||||
|
||||
if (!strcmp(parser_tokval(parser), "error" )) type = PARSE_DIRECTIVE_ERROR;
|
||||
if (!strcmp(parser_tokval(parser), "message")) type = PARSE_DIRECTIVE_MESSAGE;
|
||||
if (!strcmp(parser_tokval(parser), "warning")) type = PARSE_DIRECTIVE_WARNING;
|
||||
|
||||
switch (type) {
|
||||
case PARSE_DIRECTIVE_ERROR:
|
||||
case PARSE_DIRECTIVE_MESSAGE:
|
||||
case PARSE_DIRECTIVE_WARNING:
|
||||
*pragma = false;
|
||||
|
||||
if (!parse_skipwhite(parser) || parser->tok != TOKEN_STRINGCONST) {
|
||||
parseerror(parser, "expected %s, got `%`", parser_directives[type], parser_tokval(parser));
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case PARSE_DIRECTIVE_ERROR:
|
||||
con_cprintmsg(&parser->lex->tok.ctx, LVL_ERROR, "error", parser_tokval(parser));
|
||||
compile_errors ++; /* hack */
|
||||
break;
|
||||
/*break;*/
|
||||
|
||||
case PARSE_DIRECTIVE_MESSAGE:
|
||||
con_cprintmsg(&parser->lex->tok.ctx, LVL_MSG, "message", parser_tokval(parser));
|
||||
break;
|
||||
|
||||
case PARSE_DIRECTIVE_WARNING:
|
||||
con_cprintmsg(&parser->lex->tok.ctx, LVL_WARNING, "warning", parser_tokval(parser));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!parse_eol(parser)) {
|
||||
parseerror(parser, "parse error after `%` directive", parser_directives[type]);
|
||||
return false;
|
||||
}
|
||||
|
||||
return (type != PARSE_DIRECTIVE_ERROR);
|
||||
|
||||
default:
|
||||
parseerror(parser, "invalid directive `%s`", parser_tokval(parser));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse_pragma(parser_t *parser)
|
||||
static bool parse_directive_or_pragma(parser_t *parser)
|
||||
{
|
||||
bool rv;
|
||||
bool pragma; /* true when parsing pragma */
|
||||
|
||||
parser->lex->flags.preprocessing = true;
|
||||
parser->lex->flags.mergelines = true;
|
||||
rv = parse_pragma_do(parser);
|
||||
parser->lex->flags.mergelines = true;
|
||||
|
||||
rv = parse_directive_or_pragma_do(parser, &pragma);
|
||||
|
||||
if (parser->tok != TOKEN_EOL) {
|
||||
parseerror(parser, "junk after pragma");
|
||||
parseerror(parser, "junk after %s", (pragma) ? "pragma" : "directive");
|
||||
rv = false;
|
||||
}
|
||||
parser->lex->flags.preprocessing = false;
|
||||
parser->lex->flags.mergelines = false;
|
||||
parser->lex->flags.mergelines = false;
|
||||
|
||||
if (!parser_next(parser)) {
|
||||
parseerror(parser, "parse error after pragma");
|
||||
parseerror(parser, "parse error after %s", (pragma) ? "pragma" : "directive");
|
||||
rv = false;
|
||||
}
|
||||
return rv;
|
||||
|
@ -5520,7 +5598,7 @@ static bool parser_global_statement(parser_t *parser)
|
|||
}
|
||||
else if (parser->tok == '#')
|
||||
{
|
||||
return parse_pragma(parser);
|
||||
return parse_directive_or_pragma(parser);
|
||||
}
|
||||
else if (parser->tok == '$')
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue