diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-06-26 15:18:29 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-06-26 21:23:42 +0300 |
commit | 440771ca0056eb20396e24f03d349a75ee1c9d22 (patch) | |
tree | 3ec58a85e96d21a855ad3dcefaa8adc51039fc38 /src/git-parser.c | |
parent | 4c1959a4848c30206de3be4b16bdf04b650daae8 (diff) | |
download | grecs-440771ca0056eb20396e24f03d349a75ee1c9d22.tar.gz grecs-440771ca0056eb20396e24f03d349a75ee1c9d22.tar.bz2 |
Keep track of columns in the node and value locations. Improve error diagnostics.
* src/grecs.h (grecs_locus_point): New struct.
(grecs_locus_point_advance_line): New macro.
(grecs_locus_t): Redesign.
(grecs_value) <locus>: New member.
(grecs_node) <idloc>: New member.
(grecs_print_diag_fun): Change signature.
(grecs_warning,grecs_error): Change signature.
(grecs_parse_line_directive)
(grecs_parse_line_directive_cpp)
(grecs_string_convert): Change signature.
(grecs_current_locus): Remove.
(grecs_current_locus_point): New extern.
* src/grecs-locus.h: New file.
* src/Make.am (noinst_HEADERS): Add grecs-locus.h.
* src/join.c (reset_locus): Rewrite.
* src/lookup.c: Initialize new members of grecs_value and grecs_node.
(split_cfg_path): Return wrdse error code.
(grecs_node_from_path_locus): Take two grecs_locus_t arguments.
Make sure all created nodes have their locus members
properly initialized.
* src/parser.c (grecs_parse): Initialize grecs_current_locus_point.
* src/tree.c (grecs_node_create_points): New function.
(string_to_bool,string_to_host,string_to_sockaddr)
(grecs_string_convert): Change signatures. Be more precise in
what locus to report.
* src/diag.c (default_print_diag): Use YY_LOCATION_PRINT to
output locus.
(grecs_print_diag_fun): Change signature.
(grecs_warning,grecs_error): Change signature.
* src/format.c (grecs_format_locus): Rewrite.
(grecs_format_node): Be more precise in what locus is being
output.
* src/bind-gram.y: Keep track of locations. Turn on error-verbose mode.
* src/grecs-gram.y: Likewise.
* src/meta1-gram.y: Likewise.
* src/bind-lex.l: Keep track of locations.
* src/git-parser.c: Likewise.
* src/grecs-lex.l: Likewise.
* src/meta1-lex.l: Likewise.
* src/path-parser.c: Likewise.
* src/preproc.c: Likewise.
* tests/gcf1.conf: Untabify.
* tests/format01.at: Reflect changes in the output.
* tests/join.at: Likewise.
* tests/set.at: Likewise.
* tests/locus-bind.at: New testcase.
* tests/locus-git.at: New testcase.
* tests/locus-meta1.at: New testcase.
* tests/locus00.at: New testcase.
* tests/locus01.at: New testcase.
* tests/locus02.at: New testcase.
* tests/path-locus.at: New testcase.
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); |