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:
Dale Weiler 2013-01-30 01:24:58 +00:00
parent 7ea1033a43
commit 3d35804a7d
2 changed files with 97 additions and 76 deletions

57
ftepp.c
View file

@ -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
View file

@ -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 == '$')
{ {