X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=lex.c;h=5673701157a7aaf1b47fd043d821054dcaa0e488;hp=3be0045e36d66e1db1c2dade7fce43c1f9cbcb3e;hb=f67b6ea240ed62fd40d7383968940b8f90f0c6c9;hpb=639fc8a32b35174fc4c2347fd38f76147093d6f4 diff --git a/lex.c b/lex.c index 3be0045..5673701 100644 --- a/lex.c +++ b/lex.c @@ -20,11 +20,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include -#include -#include -#include -#include #include "gmqcc.h" /* @@ -48,6 +43,7 @@ struct lex_file *lex_open(FILE *fp) { lex->size = lex->length; /* copy, this is never changed */ fseek(lex->file, 0, SEEK_SET); lex->last = 0; + lex->line = 0; memset(lex->peek, 0, sizeof(lex->peek)); return lex; @@ -57,7 +53,7 @@ void lex_close(struct lex_file *file) { if (!file) return; fclose(file->file); /* may already be closed */ - mem_d(file); + mem_d (file); } static void lex_addch(int ch, struct lex_file *file) { @@ -138,10 +134,21 @@ static int lex_digraph(struct lex_file *file, int first) { static int lex_getch(struct lex_file *file) { int ch = lex_inget(file); - if (ch == '?') - return lex_trigraph(file); - if (ch == '<' || ch == ':' || ch == '%') - return lex_digraph (file, ch); + + static int str = 0; + switch (ch) { + case '?' : + return lex_trigraph(file); + case '<' : + case ':' : + case '%' : + case '"' : str = !str; if (str) { file->line ++; } + return lex_digraph(file, ch); + + case '\n': + if (!str) + file->line++; + } return ch; } @@ -150,7 +157,7 @@ static int lex_get(struct lex_file *file) { int ch; if (!isspace(ch = lex_getch(file))) return ch; - + /* skip over all spaces */ while (isspace(ch) && ch != '\n') ch = lex_getch(file); @@ -237,7 +244,7 @@ static int lex_skipcmt(struct lex_file *file) { lex_addch(ch, file); while ((ch = lex_getch(file)) != '*') { if (ch == EOF) - return error(ERROR_LEX, "malformatted comment at line", ""); + return error(file, ERROR_LEX, "malformatted comment"); else lex_addch(ch, file); } @@ -258,7 +265,8 @@ static int lex_getsource(struct lex_file *file) { case '\'': return lex_skipchr(file); case '"': return lex_skipstr(file); case '/': return lex_skipcmt(file); - default: return ch; + default: + return ch; } } @@ -269,7 +277,14 @@ int lex_token(struct lex_file *file) { /* valid identifier */ if (ch > 0 && (ch == '_' || isalpha(ch))) { lex_clear(file); - while (ch > 0 && (isalpha(ch) || ch == '_')) { + + /* + * Yes this is dirty, but there is no other _sane_ easy + * way to do it, this is what I call defensive programming + * if something breaks, add more defense :-) + */ + while (ch > 0 && ch != ' ' && ch != '(' && + ch != '\n' && ch != ';' && ch != ')') { lex_addch(ch, file); ch = lex_getsource(file); } @@ -302,6 +317,7 @@ int lex_token(struct lex_file *file) { if (typedef_find(file->lastok)) TEST_TYPE(typedef_find(file->lastok)->name); + #undef TEST_TYPE return LEX_IDENT; } return ch; @@ -316,3 +332,24 @@ void lex_reset(struct lex_file *file) { memset(file->peek, 0, sizeof(file->peek )); memset(file->lastok, 0, sizeof(file->lastok)); } + +/* + * Include a file into the lexer / parsing process: This really + * should check if names are the same to prevent endless include + * recrusion. + */ +struct lex_file *lex_include(struct lex_file *lex, char *file) { + util_strrq(file); + if (strncmp(lex->name, file, strlen(lex->name)) == 0) { + error(lex, ERROR_LEX, "Source file cannot include itself\n"); + exit (-1); + } + + FILE *fp = fopen(file, "r"); + if (!fp) { + error(lex, ERROR_LEX, "Include file `%s` doesn't exist\n", file); + exit (-1); + } + + return lex_open(fp); +}