/* 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; }
/* parser_get_token */ int parser_get_token(Parser * parser, Token ** token) { int ret = 0; /* XXX not sure */ size_t i; ParserCallbackData * pcd; if((*token = token_new(parser->filename, parser->line, parser->col)) == NULL) return 1; if(parser->last == EOF) parser_scan_filter(parser); #ifdef DEBUG fprintf(stderr, "DEBUG: %s() %c\n", __func__, parser->last); #endif for(i = 0; i < parser->callbacks_cnt; i++) { pcd = &parser->callbacks[i]; if((ret = pcd->callback(parser, *token, parser->last, pcd->data)) <= 0) break; } if(ret == 0 && i != parser->callbacks_cnt) return 0; /* there is a token and no error */ token_delete(*token); *token = NULL; return (ret >= 0 && parser->last == EOF) ? 0 : 1; }
/* cpp_callback_operator */ static int _cpp_callback_operator(Parser * parser, Token * token, int c, void * data) /* FIXME probably fails for ".." and similar cases */ { CppParser * cp = data; size_t i; const size_t j = sizeof(_cpp_operators) / sizeof(*_cpp_operators); size_t pos; for(i = 0; i < _cpp_operators_cnt; i++) if(_cpp_operators[i].string[0] == c) break; if(i == _cpp_operators_cnt) /* nothing found */ return 1; DEBUG_CALLBACK(); for(pos = 0; i < j;) { if(_cpp_operators[i].string[pos] == '\0') break; if(c == _cpp_operators[i].string[pos]) { c = parser_scan_filter(parser); pos++; } else i++; } if(i == j) /* should not happen */ return -1; return _cpp_token_set(cp, token, _cpp_operators[i].code, _cpp_operators[i].string); }
/* cpp_callback_otherspace */ static int _cpp_callback_otherspace(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; char * str = NULL; size_t len = 0; char * p; assert(c != '\n'); if(!isspace(c)) return 1; DEBUG_CALLBACK(); do { if((p = realloc(str, len + 2)) == NULL) { free(str); return -1; } str = p; str[len++] = c; } while(isspace((c = parser_scan_filter(parser))) && c != '\n'); if(str != NULL) { str[len] = '\0'; _cpp_token_set(cp, token, CPP_CODE_WHITESPACE, str); free(str); } else _cpp_token_set(cp, token, CPP_CODE_WHITESPACE, " "); 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_comment */ static int _cpp_callback_comment(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; char * str = NULL; size_t len = 2; char * p; if(c != '/') return 1; DEBUG_CALLBACK(); if((c = parser_scan_filter(parser)) != '*') return _cpp_token_set(cp, token, CPP_CODE_OPERATOR_DIVIDE, "/"); for(c = parser_scan_filter(parser); c != EOF;) { if(!(cp->filters & CPP_FILTER_COMMENT)) { if((p = realloc(str, len + 3)) == NULL) return -error_set_code(1, "%s", strerror( errno)); str = p; str[len++] = c; } if(c == '*') { if((c = parser_scan_filter(parser)) == '/') break; } else c = parser_scan_filter(parser); } if(c == EOF) return -error_set_code(1, "%s", "End of file within a comment"); parser_scan_filter(parser); if(str == NULL) return _cpp_token_set(cp, token, CPP_CODE_WHITESPACE, " "); str[0] = '/'; str[1] = '*'; str[len++] = '/'; str[len] = '\0'; _cpp_token_set(cp, token, CPP_CODE_COMMENT, str); /* XXX may fail */ free(str); return 0; }
/* cpp_callback_comma */ static int _cpp_callback_comma(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; if(c != ',') return 1; DEBUG_CALLBACK(); parser_scan_filter(parser); return _cpp_token_set(cp, token, CPP_CODE_COMMA, ","); }
/* cpp_callback_unknown */ static int _cpp_callback_unknown(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; char buf[2] = "\0"; if(c == EOF) return 1; DEBUG_CALLBACK(); buf[0] = c; parser_scan_filter(parser); return _cpp_token_set(cp, token, CPP_CODE_UNKNOWN, buf); }
/* 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_inject */ static int _cpp_callback_inject(Parser * parser, Token * token, int c, void * data) { CppParser * cp = data; char buf[2] = "\0"; if(cp->inject_first == 0) return 1; DEBUG_CALLBACK(); if(c == EOF) return 1; /* the current character actually goes after the substitution */ buf[0] = c; if(string_append(&cp->inject, buf) != 0) return -1; parser_scan_filter(parser); return 1; }
/* 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_parse_word */ static char * _cpp_parse_word(Parser * parser, int c) { char * str = NULL; size_t len = 0; char * p; do { if((p = realloc(str, len + 2)) == NULL) { error_set_code(1, "%s", strerror(errno)); free(str); return NULL; } str = p; str[len++] = c; } while(_cpp_isword((c = parser_scan_filter(parser)))); str[len] = '\0'; return str; }
/* 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; }