mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2024-11-30 15:41:12 +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;
|
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.
|
* Include a file.
|
||||||
* FIXME: do we need/want a -I option?
|
* FIXME: do we need/want a -I option?
|
||||||
|
@ -1513,14 +1464,6 @@ static bool ftepp_hash(ftepp_t *ftepp)
|
||||||
ftepp_out(ftepp, "#", false);
|
ftepp_out(ftepp, "#", false);
|
||||||
break;
|
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 {
|
else {
|
||||||
if (ftepp->output_on) {
|
if (ftepp->output_on) {
|
||||||
ftepp_error(ftepp, "unrecognized preprocessor directive: `%s`", ftepp_tokval(ftepp));
|
ftepp_error(ftepp, "unrecognized preprocessor directive: `%s`", ftepp_tokval(ftepp));
|
||||||
|
|
112
parser.c
112
parser.c
|
@ -3292,15 +3292,26 @@ static bool parse_eol(parser_t *parser)
|
||||||
return parser->tok == TOKEN_EOL;
|
return parser->tok == TOKEN_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_pragma_do(parser_t *parser)
|
/*
|
||||||
{
|
* Traditionally you'd implement warning, error, and message
|
||||||
if (!parser_next(parser) ||
|
* directives in the preprocessor. However, like #pragma, these
|
||||||
parser->tok != TOKEN_IDENT ||
|
* shouldn't depend on -fftepp to utilize. So they're instead
|
||||||
strcmp(parser_tokval(parser), "pragma"))
|
* implemented here.
|
||||||
{
|
*/
|
||||||
parseerror(parser, "expected `pragma` keyword after `#`, got `%s`", parser_tokval(parser));
|
enum {
|
||||||
return false;
|
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) {
|
if (!parse_skipwhite(parser) || parser->tok != TOKEN_IDENT) {
|
||||||
parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
|
parseerror(parser, "expected pragma, got `%s`", parser_tokval(parser));
|
||||||
return false;
|
return false;
|
||||||
|
@ -3311,35 +3322,102 @@ static bool parse_pragma_do(parser_t *parser)
|
||||||
parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
|
parseerror(parser, "`noref` pragma requires an argument: 0 or 1");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->noref = !!parser_token(parser)->constval.i;
|
parser->noref = !!parser_token(parser)->constval.i;
|
||||||
|
|
||||||
if (!parse_eol(parser)) {
|
if (!parse_eol(parser)) {
|
||||||
parseerror(parser, "parse error after `noref` pragma");
|
parseerror(parser, "parse error after `noref` pragma");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
(void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
|
(void)!parsewarning(parser, WARN_UNKNOWN_PRAGMAS, "ignoring #pragma %s", parser_tokval(parser));
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_pragma(parser_t *parser)
|
static bool parse_directive_or_pragma(parser_t *parser)
|
||||||
{
|
{
|
||||||
bool rv;
|
bool rv;
|
||||||
|
bool pragma; /* true when parsing pragma */
|
||||||
|
|
||||||
parser->lex->flags.preprocessing = true;
|
parser->lex->flags.preprocessing = true;
|
||||||
parser->lex->flags.mergelines = true;
|
parser->lex->flags.mergelines = true;
|
||||||
rv = parse_pragma_do(parser);
|
|
||||||
|
rv = parse_directive_or_pragma_do(parser, &pragma);
|
||||||
|
|
||||||
if (parser->tok != TOKEN_EOL) {
|
if (parser->tok != TOKEN_EOL) {
|
||||||
parseerror(parser, "junk after pragma");
|
parseerror(parser, "junk after %s", (pragma) ? "pragma" : "directive");
|
||||||
rv = false;
|
rv = false;
|
||||||
}
|
}
|
||||||
parser->lex->flags.preprocessing = false;
|
parser->lex->flags.preprocessing = false;
|
||||||
parser->lex->flags.mergelines = false;
|
parser->lex->flags.mergelines = false;
|
||||||
|
|
||||||
if (!parser_next(parser)) {
|
if (!parser_next(parser)) {
|
||||||
parseerror(parser, "parse error after pragma");
|
parseerror(parser, "parse error after %s", (pragma) ? "pragma" : "directive");
|
||||||
rv = false;
|
rv = false;
|
||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -5520,7 +5598,7 @@ static bool parser_global_statement(parser_t *parser)
|
||||||
}
|
}
|
||||||
else if (parser->tok == '#')
|
else if (parser->tok == '#')
|
||||||
{
|
{
|
||||||
return parse_pragma(parser);
|
return parse_directive_or_pragma(parser);
|
||||||
}
|
}
|
||||||
else if (parser->tok == '$')
|
else if (parser->tok == '$')
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue