diff options
Diffstat (limited to 'src/git-parser.c')
-rw-r--r-- | src/git-parser.c | 93 |
1 files changed, 68 insertions, 25 deletions
diff --git a/src/git-parser.c b/src/git-parser.c index 4ab64be..e332704 100644 --- a/src/git-parser.c +++ b/src/git-parser.c @@ -40,6 +40,8 @@ struct token { char chbuf[2]; int putback; struct grecs_list *path; + grecs_locus_t loc; + unsigned prev_col; } tok; #define ISSPACE(c) (strchr(" \t\r\f\n", c) != NULL) @@ -52,10 +54,13 @@ rawinput() if (!infile || feof(infile)) return input_char = 0; input_char = fgetc(infile); - if (input_char == '\n') - grecs_current_locus.line++; - else if (input_char < 0) + if (input_char == '\n') { + tok.prev_col = grecs_current_locus_point.col; + grecs_locus_point_advance_line(grecs_current_locus_point); + } else if (input_char < 0) input_char == 0; + else + grecs_current_locus_point.col++; return input_char; } @@ -75,8 +80,12 @@ unput() { if (!input_char) return; - if (input_char == '\n') - grecs_current_locus.line--; + if (input_char == '\n') { + grecs_current_locus_point.line--; + grecs_current_locus_point.col = tok.prev_col; + } else + grecs_current_locus_point.col--; + ungetc(input_char, infile); } @@ -113,7 +122,7 @@ collect_substring() while (rawinput()) { if (input_char == '\\') { if (!input()) { - grecs_error(&grecs_current_locus, 0, + grecs_error(&tok.loc, 0, "unexpected EOF in string"); break; } @@ -133,21 +142,39 @@ collect_substring() } } +#define endpoint(t,adj) do { \ + (t).loc.end = grecs_current_locus_point; \ + if (adj) { \ + if (input_char == '\n') \ + (t).loc.end.col = (t).prev_col; \ + else \ + (t).loc.end.col -= (adj); \ + } \ + } while (0) + static void gettoken(void) { int putback = tok.putback; tok.putback = 0; - if (putback) + if (putback) { + if (putback == '\n') + grecs_locus_point_advance_line(grecs_current_locus_point); + else + grecs_current_locus_point.col++; return; - + } + tok.buf = NULL; /* Skip whitespace */ while (input() && ISSPACE(input_char)) ; + tok.loc.beg = grecs_current_locus_point; + if (input_char <= 0) { tok.type = TOK_EOF; + endpoint(tok, 0); return; } @@ -171,7 +198,8 @@ gettoken(void) } if (input_char == TOK_EOF) { - grecs_error(&grecs_current_locus, 0, + endpoint(tok, 0); + grecs_error(&tok.loc, 0, "unexpected EOF in section header"); tok.type = TOK_ERR; return; @@ -179,7 +207,8 @@ gettoken(void) if (input_char == ']') break; if (input_char == '\n') { - grecs_error(&grecs_current_locus, 0, + endpoint(tok, 1); + grecs_error(&tok.loc, 0, "unexpect newline in in section header"); tok.type = TOK_ERR; return; @@ -197,7 +226,8 @@ gettoken(void) dot_delimited = input_char == '.'; else if (dot_delimited == 1) { if (input_char != '.' && input_char != ']') { - grecs_error(&grecs_current_locus, 0, + endpoint(tok, 1); + grecs_error(&tok.loc, 0, "unexpected character in section header"); tok.type = TOK_ERR; return; @@ -207,10 +237,10 @@ gettoken(void) p = grecs_txtacc_finish(acc, 0); grecs_list_append(tok.path, p); } - + + endpoint(tok, 1); if (grecs_list_size(tok.path) == 0) { - grecs_error(&grecs_current_locus, 0, - "empty section header"); + grecs_error(&tok.loc, 0, "empty section header"); tok.type = TOK_ERR; return; } @@ -227,6 +257,7 @@ gettoken(void) unput(); grecs_txtacc_grow_char(acc, 0); tok.buf = grecs_txtacc_finish(acc, 0); + endpoint(tok, 0); return; } @@ -234,6 +265,7 @@ gettoken(void) tok.chbuf[1] = 0; tok.buf = tok.chbuf; tok.type = input_char; + endpoint(tok, 0); } static void @@ -270,10 +302,18 @@ getvalue() { int len; struct grecs_value *val = grecs_malloc(sizeof(*val)); + while (input() && ISSPACE(input_char) && input_char != '\n') ; + + val->locus.beg = grecs_current_locus_point; + if (input_char != '\n') collect_value(); + val->locus.end = grecs_current_locus_point; + val->locus.end.line--; + val->locus.end.col = tok.prev_col; + grecs_txtacc_grow_char(acc, 0); tok.type = TOK_VALUE; tok.buf = grecs_txtacc_finish(acc, 1); @@ -296,28 +336,30 @@ read_statement(struct grecs_node *parent) return 0; } if (tok.type != TOK_KEYWORD) { - grecs_error(&grecs_current_locus, 0, "syntax error"); + grecs_error(&tok.loc, 0, "syntax error"); error_recovery(); return 1; } - node = grecs_node_create(grecs_node_stmt, &grecs_current_locus); + node = grecs_node_create(grecs_node_stmt, &tok.loc); node->ident = grecs_strdup(tok.buf); - + node->idloc = tok.loc; + gettoken(); if (tok.type == TOK_EOF) { - grecs_error(&grecs_current_locus, 0, "unexpected EOF"); + grecs_error(&tok.loc, 0, "unexpected EOF"); grecs_node_free(node); return 0; } if (tok.type != TOK_EQ) { - grecs_error(&grecs_current_locus, 0, + grecs_error(&tok.loc, 0, "expected `=', but found `%s'", tok.buf); error_recovery(); grecs_node_free(node); return 1; } node->v.value = getvalue(); + node->locus.end = node->v.value->locus.end; grecs_node_bind(parent, node, 1); return 1; } @@ -339,8 +381,7 @@ create_subsection_node(struct grecs_node *root) char *ident = ep->data; p = grecs_find_node(root, ident); if (!p) { - p = grecs_node_create(grecs_node_block, - &grecs_current_locus); + p = grecs_node_create(grecs_node_block, &tok.loc); p->ident = grecs_strdup(ident); grecs_node_bind(root, p, 1); } @@ -361,7 +402,7 @@ read_section(struct grecs_node *parent) } else if (tok.type == TOK_KEYWORD) { read_statement(parent); } else { - grecs_error(&grecs_current_locus, 0, "syntax error"); + grecs_error(&tok.loc, 0, "syntax error"); error_recovery(); } return 1; @@ -378,15 +419,17 @@ grecs_git_parser(const char *name, int traceflags) grecs_error(NULL, errno, _("cannot open `%s'"), name); return NULL; } - grecs_current_locus.file = grecs_install_text(name); - grecs_current_locus.line = 1; + grecs_current_locus_point.file = grecs_install_text(name); + grecs_current_locus_point.line = 1; + grecs_current_locus_point.col = 0; acc = grecs_txtacc_create(); tok.path = grecs_list_create(); - root = grecs_node_create(grecs_node_root, &grecs_current_locus); + root = grecs_node_create(grecs_node_root, &tok.loc); while (read_section(root)) ; + root->locus.end = grecs_current_locus_point; fclose(infile); grecs_txtacc_free(acc); grecs_list_free(tok.path); |