From: Wolfgang (Blub) Bumiller Date: Sun, 18 Nov 2012 14:14:42 +0000 (+0100) Subject: Experimental support for push/pop(line) pragmas X-Git-Tag: 0.1.9~404^2~18 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=79619fbf50c473672f268b27b8c667f0a2e83271;p=xonotic%2Fgmqcc.git Experimental support for push/pop(line) pragmas --- diff --git a/lexer.c b/lexer.c index bdea722..c28ad88 100644 --- a/lexer.c +++ b/lexer.c @@ -289,13 +289,13 @@ static int lex_getch(lex_file *lex) if (lex->peekpos) { lex->peekpos--; - if (lex->peek[lex->peekpos] == '\n') + if (!lex->push_line && lex->peek[lex->peekpos] == '\n') lex->line++; return lex->peek[lex->peekpos]; } ch = lex_fgetc(lex); - if (ch == '\n') + if (!lex->push_line && ch == '\n') lex->line++; else if (ch == '?') return lex_try_trigraph(lex, ch); @@ -307,7 +307,7 @@ static int lex_getch(lex_file *lex) static void lex_ungetch(lex_file *lex, int ch) { lex->peek[lex->peekpos++] = ch; - if (ch == '\n') + if (!lex->push_line && ch == '\n') lex->line--; } @@ -347,6 +347,102 @@ static void lex_endtoken(lex_file *lex) vec_shrinkby(lex->tok.value, 1); } +static bool lex_try_pragma(lex_file *lex) +{ + int ch; + char *pragma = NULL; + char *command = NULL; + char *param = NULL; + + if (lex->flags.preprocessing) + return false; + + ch = lex_getch(lex); + if (ch != '#') { + lex_ungetch(lex, ch); + return false; + } + + for (ch = lex_getch(lex); vec_size(pragma) < 8 && ch >= 'a' && ch <= 'z'; ch = lex_getch(lex)) + vec_push(pragma, ch); + vec_push(pragma, 0); + + if (ch != ' ' || strcmp(pragma, "pragma")) { + lex_ungetch(lex, ch); + goto unroll; + } + + for (ch = lex_getch(lex); vec_size(command) < 32 && ch >= 'a' && ch <= 'z'; ch = lex_getch(lex)) + vec_push(command, ch); + vec_push(command, 0); + + if (ch != '(') { + lex_ungetch(lex, ch); + goto unroll; + } + + for (ch = lex_getch(lex); vec_size(param) < 32 && ch != ')' && ch != '\n'; ch = lex_getch(lex)) + vec_push(param, ch); + vec_push(param, 0); + + if (ch != ')') { + lex_ungetch(lex, ch); + goto unroll; + } + + if (!strcmp(command, "push")) { + if (!strcmp(param, "line")) { + lex->push_line++; + lex->line--; + } + else + goto unroll; + } + else if (!strcmp(command, "pop")) { + if (!strcmp(param, "line")) { + if (lex->push_line) + lex->push_line--; + lex->line--; + } + else + goto unroll; + } + else + goto unroll; + + while (ch != '\n') + ch = lex_getch(lex); + return true; + +unroll: + if (command) { + vec_pop(command); + while (vec_size(command)) { + lex_ungetch(lex, vec_last(command)); + vec_pop(command); + } + vec_free(command); + } + if (command) { + vec_pop(command); + while (vec_size(command)) { + lex_ungetch(lex, vec_last(command)); + vec_pop(command); + } + vec_free(command); + } + if (pragma) { + vec_pop(pragma); + while (vec_size(pragma)) { + lex_ungetch(lex, vec_last(pragma)); + vec_pop(pragma); + } + vec_free(pragma); + } + lex_ungetch(lex, '#'); + return false; +} + /* Skip whitespace and comments and return the first * non-white character. * As this makes use of the above getch() ungetch() functions, @@ -388,6 +484,12 @@ static int lex_skipwhite(lex_file *lex) { ch = lex_getch(lex); while (ch != EOF && isspace(ch)) { + if (ch == '\n') { + if (lex_try_pragma(lex)) { + ch = lex_getch(lex); + continue; + } + } if (lex->flags.preprocessing) { if (ch == '\n') { /* end-of-line */ diff --git a/lexer.h b/lexer.h index b8e2e01..561148c 100644 --- a/lexer.h +++ b/lexer.h @@ -125,6 +125,8 @@ typedef struct { int framevalue; frame_macro *frames; char *modelname; + + size_t push_line; } lex_file; lex_file* lex_open (const char *file);