diff --git a/lexer.c b/lexer.c index 3f1aa76..bfa7443 100644 --- a/lexer.c +++ b/lexer.c @@ -24,6 +24,25 @@ void lexerror(lex_file *lex, const char *fmt, ...) printf("\n"); } +void lexwarn(lex_file *lex, int warn, const char *fmt, ...) +{ + va_list ap; + + if (!OPTS_WARN(warn)) + return; + + if (lex) + printf("warning %s:%lu: ", lex->name, (unsigned long)lex->sline); + else + printf("warning: "); + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + + printf("\n"); +} + token* token_new() { token *tok = (token*)mem_a(sizeof(token)); @@ -333,10 +352,6 @@ static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote) if (ch == quote) return TOKEN_STRINGCONST; - if (!lex_tokench(lex, ch)) - return (lex->tok->ttype = TOKEN_FATAL); - - /* as lexer we only care about \" to not terminate the string prematurely */ if (ch == '\\') { ch = lex_getch(lex); if (ch == EOF) { @@ -344,10 +359,28 @@ static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote) lex_ungetch(lex, EOF); /* next token to be TOKEN_EOF */ return (lex->tok->ttype = TOKEN_ERROR); } - /* so we just add the next character no matter what it actually is */ + + switch (ch) { + case '\\': break; + case 'a': ch = '\a'; break; + case 'b': ch = '\b'; break; + case 'r': ch = '\r'; break; + case 'n': ch = '\n'; break; + case 't': ch = '\t'; break; + case 'f': ch = '\f'; break; + case 'v': ch = '\v'; break; + default: + lexwarn(lex, WARN_UNKNOWN_CONTROL_SEQUENCE, "unrecognized control sequence: \\%c", ch); + /* so we just add the character plus backslash no matter what it actually is */ + if (!lex_tokench(lex, '\\')) + return (lex->tok->ttype = TOKEN_FATAL); + } + /* add the character finally */ if (!lex_tokench(lex, ch)) return (lex->tok->ttype = TOKEN_FATAL); } + else if (!lex_tokench(lex, ch)) + return (lex->tok->ttype = TOKEN_FATAL); } lexerror(lex, "unexpected end of file within string constant"); lex_ungetch(lex, EOF); /* next token to be TOKEN_EOF */ diff --git a/main.c b/main.c index 9cbf026..7edb2b5 100644 --- a/main.c +++ b/main.c @@ -308,6 +308,22 @@ static bool options_parse(int argc, char **argv) { return true; } +static void options_setflag(uint32_t *flags, size_t idx, bool on) +{ + longbit lb = LONGBIT(idx); +#if 0 + if (on) + flags[lb.idx] |= (1<<(lb.bit)); + else + flags[lb.idx] &= ~(1<<(lb.bit)); +#else + if (on) + flags[0] |= (1<<(lb)); + else + flags[0] &= ~(1<<(lb)); +#endif +} + bool parser_init(); bool parser_compile(const char *filename); bool parser_finish(const char *output); @@ -317,6 +333,9 @@ int main(int argc, char **argv) { size_t itr; app_name = argv[0]; + /* default options / warn flags */ + options_setflag(opts_warn, WARN_UNKNOWN_CONTROL_SEQUENCE, true); + if (!options_parse(argc, argv)) { return usage(); } diff --git a/warns.def b/warns.def index 6238e50..e7ebda7 100644 --- a/warns.def +++ b/warns.def @@ -3,3 +3,4 @@ #endif GMQCC_DEFINE_FLAG(UNUSED_VARIABLE) +GMQCC_DEFINE_FLAG(UNKNOWN_CONTROL_SEQUENCE)