X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=lex.c;h=556f485536934d6a860ddc40197bb5aa6327cb0f;hp=76cfbf02a5e13c43cc5e3857416859fdb57a9647;hb=9493da4f8b373ba2266d411f6ec50f1920b9255c;hpb=248cd7af945adc9c5de019ec74c866626cd560ab diff --git a/lex.c b/lex.c index 76cfbf0..556f485 100644 --- a/lex.c +++ b/lex.c @@ -34,38 +34,31 @@ static const char *const lex_keywords[] = { "do", "else", "if", "while", "break", "continue", "return", "goto", - "for", "typedef", - - /* types */ - "void", - "string", - "float", - "vector", - "entity", + "for", "typedef" }; struct lex_file *lex_open(FILE *fp) { struct lex_file *lex = mem_a(sizeof(struct lex_file)); - if (lex) { - lex->file = fp; - fseek(lex->file, 0, SEEK_END); - lex->length = ftell(lex->file); - lex->size = lex->length; /* copy, this is never changed */ - fseek(lex->file, 0, SEEK_SET); - lex->last = 0; + if (!lex || !fp) + return NULL; - memset(lex->peek, 0, sizeof(lex->peek)); - } + lex->file = fp; + fseek(lex->file, 0, SEEK_END); + lex->length = ftell(lex->file); + 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; } -int lex_close(struct lex_file *file) { - int ret = -1; - if (file) { - ret = fclose(file->file); - mem_d(file); - } - return ret; +void lex_close(struct lex_file *file) { + if (!file) return; + + fclose(file->file); /* may already be closed */ + mem_d(file); } static void lex_addch(int ch, struct lex_file *file) { @@ -146,10 +139,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; } @@ -158,7 +162,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); @@ -245,7 +249,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 %d", file->line); + return error(ERROR_LEX, "malformatted comment at line", ""); else lex_addch(ch, file); } @@ -266,7 +270,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; } } @@ -277,7 +282,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); } @@ -289,13 +301,28 @@ int lex_token(struct lex_file *file) { if (!strncmp(file->lastok, lex_keywords[it], sizeof(lex_keywords[it]))) return it; + /* try a type? */ + #define TEST_TYPE(X) \ + do { \ + if (!strncmp(X, "float", sizeof("float"))) \ + return TOKEN_FLOAT; \ + if (!strncmp(X, "vector", sizeof("vector"))) \ + return TOKEN_VECTOR; \ + if (!strncmp(X, "string", sizeof("string"))) \ + return TOKEN_STRING; \ + if (!strncmp(X, "entity", sizeof("entity"))) \ + return TOKEN_ENTITY; \ + if (!strncmp(X, "void" , sizeof("void"))) \ + return TOKEN_VOID; \ + } while(0) + + TEST_TYPE(file->lastok); + /* try the hashtable for typedefs? */ if (typedef_find(file->lastok)) - for (it = 0; it < sizeof(lex_keywords)/sizeof(*lex_keywords); it++) - if (!strncmp(typedef_find(file->lastok)->name, lex_keywords[it], sizeof(lex_keywords[it]))) - return it; - + TEST_TYPE(typedef_find(file->lastok)->name); + #undef TEST_TYPE return LEX_IDENT; } return ch;