/* cpp_token_set */ static int _cpp_token_set(CppParser * cp, Token * token, TokenCode code, char const * string) { if(token_set_string(token, string) != 0) return -1; if(cp->queue_code == CPP_CODE_NULL) { token_set_code(token, code); return 0; } /* we are parsing a directive */ token_set_code(token, CPP_CODE_META_DATA); if(code == CPP_CODE_COMMENT) /* comments within directives are whitespaces */ string = " "; if(cp->queue_string == NULL) { /* left-trim spaces */ for(; isspace((unsigned char)string[0]); string++); if((cp->queue_string = string_new(string)) == NULL) return -1; } else if(string_append(&cp->queue_string, string) != 0) return -1; return 0; }
static int _parser_scan(State * state) { int ret; TokenCode code; char const * string; if(state->token != NULL) token_delete(state->token); if((ret = _scan_skip_meta(state)) != 0 || state->token == NULL) return ret; code = token_get_code(state->token); string = token_get_string(state->token); if(code == AS_CODE_WORD) { if(string != NULL && string[0] == '$') token_set_code(state->token, AS_CODE_IMMEDIATE); } else if(code == AS_CODE_OPERATOR_MODULO) { /* FIXME ugly workaround */ if((ret = _scan_skip_meta(state)) != 0) return ret; if(_parser_is_code(state, AS_CODE_WORD)) token_set_code(state->token, AS_CODE_REGISTER); } return 0; }
/* cpp_callback_directive */ static int _cpp_callback_directive(Parser * parser, Token * token, int c, void * data) { CppParser * cpp = data; char * str; size_t i; if(cpp->directive_control != 1 || cpp->queue_code != CPP_CODE_NULL || !_cpp_isword(c)) return 1; DEBUG_CALLBACK(); if((str = _cpp_parse_word(parser, c)) == NULL) return -1; for(i = 0; _cpp_directives[i] != NULL; i++) if(strcmp(str, _cpp_directives[i]) == 0) break; if(_cpp_directives[i] != NULL) { cpp->queue_code = CPP_CODE_META_FIRST + i; cpp->queue_string = NULL; } else { cpp->queue_code = CPP_CODE_META_ERROR; cpp->queue_string = string_new_append("Invalid directive: #", str, ":", NULL); /* XXX check for errors */ } token_set_code(token, CPP_CODE_META_DATA); token_set_string(token, str); free(str); return 0; }
/* cpp_callback_quote */ static int _cpp_callback_quote(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; int escape = 0; char * str = NULL; size_t len = 0; char * p; if(c == '\'') token_set_code(token, CPP_CODE_SQUOTE); else if(c == '"') token_set_code(token, CPP_CODE_DQUOTE); else return 1; DEBUG_CALLBACK(); while((p = realloc(str, len + 3)) != NULL) { str = p; str[len++] = c; if((c = parser_scan_filter(parser)) == EOF || c == '\n') break; if(escape) escape = 0; else if(c == str[0]) break; else if(c == '\\') escape = 1; } if(p == NULL) /* there was an error with realloc() */ { error_set_code(1, "%s", strerror(errno)); free(str); return -1; } else if(c == str[0]) /* the quoted string is properly closed */ { str[len++] = str[0]; parser_scan_filter(parser); } /* XXX else we should probably issue a warning */ str[len] = '\0'; /* XXX keep code earlier, may fail */ _cpp_token_set(cp, token, token_get_code(token), str); free(str); return 0; }
/* cpp_callback_header */ static int _cpp_callback_header(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; char end; char * str = NULL; size_t len = 0; char * p; if(cp->directive_control != 1 || cp->queue_code != CPP_CODE_META_INCLUDE || (c != '<' && c != '"')) return 1; DEBUG_CALLBACK(); end = (c == '<') ? '>' : '"'; while((p = realloc(str, len + 3)) != NULL) { str = p; str[len++] = c; if((c = parser_scan_filter(parser)) == EOF || c == '\n') break; else if(c == end) break; } if(p == NULL) /* there was an error with realloc() */ { error_set_code(1, "%s", strerror(errno)); free(str); return -1; } else if(c == end) /* the header name is properly closed */ { str[len++] = c; parser_scan_filter(parser); } str[len] = '\0'; token_set_code(token, CPP_CODE_META_DATA); token_set_string(token, str); if(cp->queue_string == NULL || strlen(cp->queue_string) == 0) { free(cp->queue_string); cp->queue_string = str; } else { free(str); cp->queue_code = CPP_CODE_META_ERROR; free(cp->queue_string); /* XXX may be followed by junk */ cp->queue_string = strdup("Syntax error"); } return 0; }
/* cpp_callback_newline */ static int _cpp_callback_newline(Parser * parser, Token * token, int c, void * data) { CppParser * cpp = data; if(c != '\n') return 1; DEBUG_CALLBACK(); cpp->directive_newline = 1; cpp->queue_ready = 1; parser_scan_filter(parser); token_set_code(token, CPP_CODE_NEWLINE); token_set_string(token, "\n"); return 0; }
/* cpp_callback_control */ static int _cpp_callback_control(Parser * parser, Token * token, int c, void * data) { CppParser * cpp = data; if(cpp->directive_newline != 1 || c != '#') { cpp->directive_newline = 0; return 1; } DEBUG_CALLBACK(); parser_scan_filter(parser); token_set_code(token, CPP_CODE_META_DATA); token_set_string(token, "#"); cpp->directive_newline = 0; cpp->directive_control = 1; cpp->queue_code = CPP_CODE_NULL; return 0; }
/* cpp_callback_dequeue */ static int _cpp_callback_dequeue(Parser * parser, Token * token, int c, void * data) { int ret = 0; CppParser * cpp = data; if(cpp->queue_ready == 0) return 1; cpp->queue_ready = 0; if(cpp->queue_code == CPP_CODE_NULL && cpp->queue_string == NULL) return 1; DEBUG_CALLBACK(); token_set_code(token, cpp->queue_code); switch(cpp->queue_code) { case CPP_CODE_META_DEFINE: case CPP_CODE_META_ELIF: case CPP_CODE_META_IF: case CPP_CODE_META_IFDEF: case CPP_CODE_META_IFNDEF: case CPP_CODE_META_INCLUDE: case CPP_CODE_META_UNDEF: token_set_string(token, ""); token_set_data(token, cpp->queue_string); cpp->queue_string = NULL; break; case CPP_CODE_META_ERROR: case CPP_CODE_META_WARNING: token_set_string(token, (cpp->queue_string != NULL) ? cpp->queue_string : ""); break; default: token_set_string(token, ""); break; } cpp->queue_code = CPP_CODE_NULL; string_delete(cpp->queue_string); cpp->queue_string = NULL; cpp->directive_newline = 1; cpp->directive_control = 0; return ret; }
/* cpp_callback_whitespace */ static int _cpp_callback_whitespace(Parser * parser, Token * token, int c, void * data) { CppParser * cpp = data; char * str = NULL; size_t len = 0; char * p; if(!isspace(c)) return 1; DEBUG_CALLBACK(); do { if(c != '\n') continue; if((p = realloc(str, len + 2)) == NULL) { free(str); return -1; } str = p; str[len++] = c; } while(isspace((c = parser_scan_filter(parser)))); token_set_code(token, CPP_CODE_WHITESPACE); if(str != NULL) /* some newlines were encountered */ { str[len] = '\0'; token_set_string(token, str); free(str); cpp->directive_newline = 1; cpp->queue_ready = 1; return 0; } token_set_string(token, " "); if(cpp->queue_code != CPP_CODE_NULL && cpp->queue_string != NULL) string_append(&cpp->queue_string, " "); return 0; }