X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=lexer.c;h=66a0c451564a443aa62911fdd028ec0405f470a2;hb=2a3e7c1cff95a06b85ca2860735433cc59da64f5;hp=80016288476d56433d4158eac175ad62f239d152;hpb=5c0a62be9616fd96bafc422b7fcd2105e4b445e5;p=xonotic%2Fgmqcc.git diff --git a/lexer.c b/lexer.c index 8001628..66a0c45 100644 --- a/lexer.c +++ b/lexer.c @@ -46,7 +46,11 @@ static size_t num_keywords_qc = sizeof(keywords_qc) / sizeof(keywords_qc[0]); static const char *keywords_fg[] = { "switch", "case", "default", "struct", "union", - "break", "continue" + "break", "continue", + "typedef", + "goto", + + "__builtin_debug_printtype" }; static size_t num_keywords_fg = sizeof(keywords_fg) / sizeof(keywords_fg[0]); @@ -317,6 +321,11 @@ static int lex_try_digraph(lex_file *lex, int ch) { int c2; c2 = lex_fgetc(lex); + /* we just used fgetc() so count lines + * need to offset a \n the ungetch would recognize + */ + if (!lex->push_line && c2 == '\n') + lex->line++; if (ch == '<' && c2 == ':') return '['; else if (ch == ':' && c2 == '>') @@ -432,7 +441,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); @@ -444,7 +453,8 @@ static bool lex_try_pragma(lex_file *lex) if (!strcmp(command, "push")) { if (!strcmp(param, "line")) { lex->push_line++; - --line; + if (lex->push_line == 1) + --line; } else goto unroll; @@ -453,7 +463,8 @@ static bool lex_try_pragma(lex_file *lex) if (!strcmp(param, "line")) { if (lex->push_line) lex->push_line--; - --line; + if (lex->push_line == 0) + --line; } else goto unroll; @@ -731,6 +742,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) { @@ -767,6 +779,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 */ @@ -790,7 +857,10 @@ static int GMQCC_WARN lex_finish_digit(lex_file *lex, int lastch) int ch = lastch; /* parse a number... */ - lex->tok.ttype = TOKEN_INTCONST; + if (ch == '.') + lex->tok.ttype = TOKEN_FLOATCONST; + else + lex->tok.ttype = TOKEN_INTCONST; lex_tokench(lex, ch); @@ -823,7 +893,7 @@ static int GMQCC_WARN lex_finish_digit(lex_file *lex, int lastch) } } /* NOT else, '.' can come from above as well */ - if (ch == '.' && !ishex) + if (lex->tok.ttype != TOKEN_FLOATCONST && ch == '.' && !ishex) { /* Allow floating comma in non-hex mode */ lex->tok.ttype = TOKEN_FLOATCONST; @@ -882,14 +952,14 @@ int lex_do(lex_file *lex) continue; } - lex->sline = lex->line; - lex->tok.ctx.line = lex->sline; - lex->tok.ctx.file = lex->name; - if (lex->flags.preprocessing && (ch == TOKEN_WHITE || ch == TOKEN_EOL || ch == TOKEN_FATAL)) { return (lex->tok.ttype = ch); } + lex->sline = lex->line; + lex->tok.ctx.line = lex->sline; + lex->tok.ctx.file = lex->name; + if (lex->eof) return (lex->tok.ttype = TOKEN_FATAL); @@ -899,7 +969,7 @@ int lex_do(lex_file *lex) } /* modelgen / spiritgen commands */ - if (ch == '$') { + if (ch == '$' && !lex->flags.preprocessing) { const char *v; size_t frame; @@ -1068,6 +1138,18 @@ int lex_do(lex_file *lex) break; } + if (ch == '.') { + nextch = lex_getch(lex); + /* digits starting with a dot */ + if (isdigit(nextch)) { + lex_ungetch(lex, nextch); + lex->tok.ttype = lex_finish_digit(lex, ch); + lex_endtoken(lex); + return lex->tok.ttype; + } + lex_ungetch(lex, nextch); + } + if (lex->flags.noops) { /* Detect characters early which are normally @@ -1075,8 +1157,10 @@ int lex_do(lex_file *lex) */ switch (ch) { + /* case '+': case '-': + */ case '*': case '/': case '<': @@ -1109,7 +1193,7 @@ int lex_do(lex_file *lex) nextch = lex_getch(lex); if (nextch != '.') { lex_ungetch(lex, nextch); - lex_ungetch(lex, nextch); + lex_ungetch(lex, '.'); lex_endtoken(lex); return (lex->tok.ttype = ch); } @@ -1135,7 +1219,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); @@ -1265,6 +1349,7 @@ int lex_do(lex_file *lex) lex_tokench(lex, ch); lex_endtoken(lex); + lex->tok.ttype = TOKEN_CHARCONST; /* It's a vector if we can successfully scan 3 floats */ #ifdef WIN32 if (sscanf_s(lex->tok.value, " %f %f %f ", @@ -1277,6 +1362,14 @@ int lex_do(lex_file *lex) { lex->tok.ttype = TOKEN_VECTORCONST; } + else + { + if (!lex->flags.preprocessing && strlen(lex->tok.value) > 1) { + if (lexwarn(lex, WARN_MULTIBYTE_CHARACTER, "multibyte character: `%s`", lex->tok.value)) + return (lex->tok.ttype = TOKEN_ERROR); + } + lex->tok.constval.i = lex->tok.value[0]; + } return lex->tok.ttype; } @@ -1288,6 +1381,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); }