X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=lexer.c;h=7fc606c22d56962882702f7303568c5713c250ba;hb=6b9eff19f189c9f07650944d383a1dddc61d0655;hp=662e7e7c4092453251c70cd3d149c809376ad6f5;hpb=2f5a26a4de1b8fdb8876f5b1efc34ec52127cdec;p=xonotic%2Fgmqcc.git diff --git a/lexer.c b/lexer.c index 662e7e7..7fc606c 100644 --- a/lexer.c +++ b/lexer.c @@ -50,6 +50,8 @@ static const char *keywords_fg[] = { "typedef", "goto", + "noreturn", + "__builtin_debug_printtype" }; static size_t num_keywords_fg = sizeof(keywords_fg) / sizeof(keywords_fg[0]); @@ -74,20 +76,17 @@ void lexerror(lex_file *lex, const char *fmt, ...) bool lexwarn(lex_file *lex, int warntype, const char *fmt, ...) { + bool r; + lex_ctx ctx; va_list ap; - int lvl = LVL_WARNING; - - if (!OPTS_WARN(warntype)) - return false; - if (opts_werror) - lvl = LVL_ERROR; + ctx.file = lex->name; + ctx.line = lex->sline; va_start(ap, fmt); - con_vprintmsg(lvl, lex->name, lex->sline, "warning", fmt, ap); + r = vcompile_warning(ctx, warntype, fmt, ap); va_end(ap); - - return opts_werror; + return r; } @@ -441,7 +440,7 @@ static bool lex_try_pragma(lex_file *lex) goto unroll; } - for (ch = lex_getch(lex); vec_size(param) < 32 && ch != ')' && ch != '\n'; ch = lex_getch(lex)) + for (ch = lex_getch(lex); vec_size(param) < 1024 && ch != ')' && ch != '\n'; ch = lex_getch(lex)) vec_push(param, ch); vec_push(param, 0); @@ -492,6 +491,7 @@ unroll: vec_pop(command); } vec_free(command); + lex_ungetch(lex, ' '); } if (command) { vec_pop(command); @@ -500,6 +500,7 @@ unroll: vec_pop(command); } vec_free(command); + lex_ungetch(lex, ' '); } if (pragma) { vec_pop(pragma); @@ -547,10 +548,10 @@ printf( "line one\n" * here is to store the line of the first character after skipping * the initial whitespace in lex->sline, this happens in lex_do. */ -static int lex_skipwhite(lex_file *lex) +static int lex_skipwhite(lex_file *lex, bool hadwhite) { int ch = 0; - bool haswhite = false; + bool haswhite = hadwhite; do { @@ -742,6 +743,7 @@ static bool lex_finish_frames(lex_file *lex) static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote) { int ch = 0; + int nextch; while (ch != EOF) { @@ -778,7 +780,61 @@ static int GMQCC_WARN lex_finish_string(lex_file *lex, int quote) case 't': ch = '\t'; break; case 'f': ch = '\f'; break; case 'v': ch = '\v'; break; + case 'x': + case 'X': + /* same procedure as in fteqcc */ + ch = 0; + nextch = lex_getch(lex); + if (nextch >= '0' && nextch <= '9') + ch += nextch - '0'; + else if (nextch >= 'a' && nextch <= 'f') + ch += nextch - 'a' + 10; + else if (nextch >= 'A' && nextch <= 'F') + ch += nextch - 'A' + 10; + else { + lexerror(lex, "bad character code"); + lex_ungetch(lex, nextch); + return (lex->tok.ttype = TOKEN_ERROR); + } + + ch *= 0x10; + nextch = lex_getch(lex); + if (nextch >= '0' && nextch <= '9') + ch += nextch - '0'; + else if (nextch >= 'a' && nextch <= 'f') + ch += nextch - 'a' + 10; + else if (nextch >= 'A' && nextch <= 'F') + ch += nextch - 'A' + 10; + else { + lexerror(lex, "bad character code"); + lex_ungetch(lex, nextch); + return (lex->tok.ttype = TOKEN_ERROR); + } + break; + + /* fteqcc support */ + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': + ch = 18 + ch - '0'; + break; + case '<': ch = 29; break; + case '-': ch = 30; break; + case '>': ch = 31; break; + case '[': ch = 16; break; + case ']': ch = 17; break; + case '{': + ch = 0; + for (nextch = lex_getch(lex); nextch != '}'; nextch = lex_getch(lex)) { + ch = ch * 10 + nextch - '0'; + if (nextch < '0' || nextch > '9' || ch > 255) { + lexerror(lex, "bad character code"); + return (lex->tok.ttype = TOKEN_ERROR); + } + } + break; case '\n': ch = '\n'; 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 */ @@ -875,6 +931,7 @@ static int GMQCC_WARN lex_finish_digit(lex_file *lex, int lastch) int lex_do(lex_file *lex) { int ch, nextch, thirdch; + bool hadwhite = false; lex_token_new(lex); #if 0 @@ -883,7 +940,8 @@ int lex_do(lex_file *lex) #endif while (true) { - ch = lex_skipwhite(lex); + ch = lex_skipwhite(lex, hadwhite); + hadwhite = true; if (!lex->flags.mergelines || ch != '\\') break; ch = lex_getch(lex); @@ -914,7 +972,7 @@ int lex_do(lex_file *lex) } /* modelgen / spiritgen commands */ - if (ch == '$') { + if (ch == '$' && !lex->flags.preprocessing) { const char *v; size_t frame; @@ -1005,7 +1063,6 @@ int lex_do(lex_file *lex) if (rc < 0) return (lex->tok.ttype = TOKEN_FATAL); - v = lex->tok.value; if (lex->modelname) { frame_macro m; m.value = lex->framevalue; @@ -1164,7 +1221,7 @@ int lex_do(lex_file *lex) lex_tokench(lex, ch); nextch = lex_getch(lex); - if (nextch == ch || nextch == '=') { + if (nextch == '=' || (nextch == ch && ch != '!')) { lex_tokench(lex, nextch); } else if (ch == '-' && nextch == '>') { lex_tokench(lex, nextch); @@ -1245,7 +1302,7 @@ int lex_do(lex_file *lex) if (!strcmp(v, keywords_qc[kw])) return (lex->tok.ttype = TOKEN_KEYWORD); } - if (opts_standard != COMPILER_QCC) { + if (opts.standard != COMPILER_QCC) { for (kw = 0; kw < num_keywords_fg; ++kw) { if (!strcmp(v, keywords_fg[kw])) return (lex->tok.ttype = TOKEN_KEYWORD); @@ -1267,7 +1324,7 @@ int lex_do(lex_file *lex) while (!lex->flags.preprocessing && lex->tok.ttype == TOKEN_STRINGCONST) { /* Allow c style "string" "continuation" */ - ch = lex_skipwhite(lex); + ch = lex_skipwhite(lex, false); if (ch != '"') { lex_ungetch(lex, ch); break; @@ -1296,7 +1353,7 @@ int lex_do(lex_file *lex) lex->tok.ttype = TOKEN_CHARCONST; /* It's a vector if we can successfully scan 3 floats */ -#ifdef WIN32 +#ifdef _MSC_VER if (sscanf_s(lex->tok.value, " %f %f %f ", &lex->tok.constval.v.x, &lex->tok.constval.v.y, &lex->tok.constval.v.z) == 3) #else @@ -1326,6 +1383,12 @@ int lex_do(lex_file *lex) return lex->tok.ttype; } + if (lex->flags.preprocessing) { + lex_tokench(lex, ch); + lex_endtoken(lex); + return (lex->tok.ttype = ch); + } + lexerror(lex, "unknown token"); return (lex->tok.ttype = TOKEN_ERROR); }