diff options
-rw-r--r-- | src/Make.am | 2 | ||||
-rw-r--r-- | src/bind-gram.y | 68 | ||||
-rw-r--r-- | src/bind-lex.l | 58 | ||||
-rw-r--r-- | src/diag.c | 18 | ||||
-rw-r--r-- | src/format.c | 59 | ||||
-rw-r--r-- | src/git-parser.c | 93 | ||||
-rw-r--r-- | src/grecs-gram.y | 43 | ||||
-rw-r--r-- | src/grecs-lex.l | 102 | ||||
-rw-r--r-- | src/grecs-locus.h | 56 | ||||
-rw-r--r-- | src/grecs.h | 45 | ||||
-rw-r--r-- | src/join.c | 27 | ||||
-rw-r--r-- | src/lookup.c | 54 | ||||
-rw-r--r-- | src/meta1-gram.y | 37 | ||||
-rw-r--r-- | src/meta1-lex.l | 27 | ||||
-rw-r--r-- | src/parser.c | 5 | ||||
-rw-r--r-- | src/path-parser.c | 172 | ||||
-rw-r--r-- | src/preproc.c | 22 | ||||
-rw-r--r-- | src/tree.c | 45 | ||||
-rw-r--r-- | tests/Makefile.am | 9 | ||||
-rw-r--r-- | tests/format01.at | 28 | ||||
-rw-r--r-- | tests/gcf1.conf | 12 | ||||
-rw-r--r-- | tests/gcffmt.c | 14 | ||||
-rw-r--r-- | tests/gcfpeek.c | 20 | ||||
-rw-r--r-- | tests/join.at | 16 | ||||
-rw-r--r-- | tests/locus-bind.at | 40 | ||||
-rw-r--r-- | tests/locus-git.at | 61 | ||||
-rw-r--r-- | tests/locus-meta1.at | 37 | ||||
-rw-r--r-- | tests/locus00.at | 30 | ||||
-rw-r--r-- | tests/locus01.at | 34 | ||||
-rw-r--r-- | tests/locus02.at | 32 | ||||
-rw-r--r-- | tests/path-locus.at | 92 | ||||
-rw-r--r-- | tests/set.at | 2 | ||||
-rw-r--r-- | tests/testsuite.at | 22 |
33 files changed, 1034 insertions, 348 deletions
diff --git a/src/Make.am b/src/Make.am index bc70edc..286bf4c 100644 --- a/src/Make.am +++ b/src/Make.am @@ -59,7 +59,7 @@ GRECS_SRC = \ $(GRECS_PARSER_GIT)\ $(GRECS_PARSER_META1) -noinst_HEADERS = +noinst_HEADERS = grecs-locus.h EXTRA_DIST=\ grecs-gram.h\ diff --git a/src/bind-gram.y b/src/bind-gram.y index c751ae1..e353a54 100644 --- a/src/bind-gram.y +++ b/src/bind-gram.y @@ -19,7 +19,8 @@ # include <config.h> #endif #include <grecs.h> -#include <grecs-gram.h> +#include <grecs-locus.h> +#include <bind-gram.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> @@ -30,17 +31,16 @@ int yyerror(char *s); static struct grecs_node *parse_tree; extern int yy_flex_debug; -extern int grecs_bind_new_source(const char *name); +extern int grecs_bind_new_source(const char *name, grecs_locus_t *loc); extern void grecs_bind_close_sources(void); static struct grecs_value *stmtlist_to_value(struct grecs_node *node); %} +%error-verbose +%locations + %union { - struct { - grecs_locus_t locus; - char *string; - } ident; char *string; grecs_value_t svalue, *pvalue; struct grecs_list *list; @@ -49,8 +49,7 @@ static struct grecs_value *stmtlist_to_value(struct grecs_node *node); struct { struct grecs_node *head, *tail; } node_list; } -%token <ident> BIND_IDENT BIND_CONTROLS -%token <string> BIND_STRING +%token <string> BIND_STRING BIND_IDENT BIND_CONTROLS %type <string> string %type <svalue> value ctlsub %type <pvalue> vallist tag @@ -62,8 +61,7 @@ static struct grecs_value *stmtlist_to_value(struct grecs_node *node); input : maybe_stmtlist { - parse_tree = grecs_node_create(grecs_node_root, - &grecs_current_locus); + parse_tree = grecs_node_create(grecs_node_root, &@1); parse_tree->v.texttab = grecs_text_table(); grecs_node_bind(parse_tree, $1, 1); } @@ -102,38 +100,44 @@ stmt : simple simple : BIND_IDENT vallist ';' { - if (strcmp($1.string, "include") == 0 && + if (strcmp($1, "include") == 0 && $2->type == GRECS_TYPE_STRING) { - grecs_bind_new_source($2->v.string); + grecs_bind_new_source($2->v.string, &@1); $$ = NULL; } else { - $$ = grecs_node_create(grecs_node_stmt, &$1.locus); - $$->ident = $1.string; + $$ = grecs_node_create_points(grecs_node_stmt, + @1.beg, @2.end); + $$->ident = $1; + $$->idloc = @1; $$->v.value = $2; } } | string ';' { - $$ = grecs_node_create(grecs_node_stmt, - &grecs_current_locus); + $$ = grecs_node_create(grecs_node_stmt, &@1); $$->ident = $1; + $$->idloc = @1; $$->v.value = NULL; } | '!' string ';' { - $$ = grecs_node_create(grecs_node_stmt, - &grecs_current_locus); - $$->ident = grecs_strdup("!"); - $$->v.value = grecs_malloc(sizeof($$->v.value[0])); - $$->v.value->type = GRECS_TYPE_STRING; - $$->v.value->v.string = $2; + $$ = grecs_node_create_points(grecs_node_stmt, + @1.beg, @2.end); + $$->ident = grecs_strdup("!"); + $$->idloc = @1; + $$->v.value = grecs_malloc(sizeof($$->v.value[0])); + $$->v.value->type = GRECS_TYPE_STRING; + $$->v.value->locus = @2; + $$->v.value->v.string = $2; } ; block : BIND_IDENT tag '{' maybe_stmtlist '}' ';' { - $$ = grecs_node_create(grecs_node_block, &$1.locus); - $$->ident = $1.string; + $$ = grecs_node_create_points(grecs_node_block, + @1.beg, @5.end); + $$->ident = $1; + $$->idloc = @1; $$->v.value = $2; grecs_node_bind($$, $4, 1); } @@ -151,8 +155,10 @@ block : BIND_IDENT tag '{' maybe_stmtlist '}' ';' (127.0.0.1, 127.0.0.2), keys, (rndc-key)) */ { - $$ = grecs_node_create(grecs_node_stmt, &$1.locus); - $$->ident = $1.string; + $$ = grecs_node_create_points(grecs_node_stmt, + @1.beg, @4.end); + $$->ident = $1; + $$->idloc = @1; $$->v.value = grecs_value_ptr_from_static(&$3); } ; @@ -176,6 +182,7 @@ vallist : vlist $$ = grecs_malloc(sizeof($$[0])); $$->type = GRECS_TYPE_ARRAY; + $$->locus = @1; $$->v.arg.c = n; $$->v.arg.v = grecs_calloc(n, sizeof($$->v.arg.v[0])); @@ -201,20 +208,19 @@ vlist : value value : string { $$.type = GRECS_TYPE_STRING; + $$.locus = @1; $$.v.string = $1; } ; string : BIND_STRING | BIND_IDENT - { - $$ = $1.string; - } ; ctlsub : ctllist ';' { $$.type = GRECS_TYPE_LIST; + $$.locus = @1; $$.v.list = $1; } ; @@ -240,7 +246,7 @@ ctllist : value int yyerror(char *s) { - grecs_error(&grecs_current_locus, 0, "%s", s); + grecs_error(&yylloc, 0, "%s", s); return 0; } @@ -249,7 +255,7 @@ grecs_bind_parser(const char *name, int traceflags) { int rc; - if (grecs_bind_new_source(name)) + if (grecs_bind_new_source(name, NULL)) return NULL; yy_flex_debug = traceflags & GRECS_TRACE_LEX; yydebug = traceflags & GRECS_TRACE_GRAM; diff --git a/src/bind-lex.l b/src/bind-lex.l index 10df618..ef1598c 100644 --- a/src/bind-lex.l +++ b/src/bind-lex.l @@ -22,6 +22,7 @@ with Grecs. If not, see <http://www.gnu.org/licenses/>. */ #include <grecs.h> +#include <grecs-locus.h> #include <bind-gram.h> #include <unistd.h> #include <fcntl.h> @@ -32,6 +33,14 @@ #include <wordsplit.h> +#define YY_USER_ACTION do { \ + if (YYSTATE == 0) { \ + yylloc.beg = grecs_current_locus_point; \ + yylloc.beg.col++; \ + } \ + grecs_current_locus_point.col += yyleng; \ + yylloc.end = grecs_current_locus_point; \ + } while (0); %} %x COMMENT STR @@ -45,26 +54,27 @@ P [1-9][0-9]* "/*" BEGIN(COMMENT); <COMMENT>[^*\n]* /* eat anything that's not a '*' */ <COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ -<COMMENT>\n ++grecs_current_locus.line; +<COMMENT>\n grecs_locus_point_advance_line(grecs_current_locus_point); <COMMENT>"*"+"/" BEGIN(INITIAL); /* Line directive */ ^[ \t]*#[ \t]*{P}[ \t]+\".*\".*\n { grecs_parse_line_directive_cpp(yytext, - &grecs_current_locus, + &yylloc, + &grecs_current_locus_point, NULL); } ^[ \t]*#[ \t]*line[ \t].*\n { grecs_parse_line_directive(yytext, - &grecs_current_locus, + &yylloc, + &grecs_current_locus_point, NULL); } /* End-of-line comments */ -#.*\n { grecs_current_locus.line++; } +#.*\n { grecs_locus_point_advance_line(grecs_current_locus_point); } #.* /* end-of-file comment */; -"//".*\n { grecs_current_locus.line++; } +"//".*\n { grecs_locus_point_advance_line(grecs_current_locus_point); } "//".* /* end-of-file comment */; /* Identifiers */ {ID} { grecs_line_begin(); grecs_line_add(yytext, yyleng); - yylval.ident.string = grecs_line_finish(); - yylval.ident.locus = grecs_current_locus; - return strcmp(yylval.ident.string, "controls") == 0 ? + yylval.string = grecs_line_finish(); + return strcmp(yylval.string, "controls") == 0 ? BIND_CONTROLS : BIND_IDENT; } /* Strings */ @@ -97,19 +107,20 @@ P [1-9][0-9]* return BIND_STRING; } {WS} ; /* Other tokens */ -\n { grecs_current_locus.line++; } +\n { grecs_locus_point_advance_line(grecs_current_locus_point); } [,;{}()!] return yytext[0]; . { if (isascii(yytext[0]) && isprint(yytext[0])) - grecs_error(&grecs_current_locus, 0, + grecs_error(&yylloc, 0, _("stray character %c"), yytext[0]); else - grecs_error(&grecs_current_locus, 0, _("stray character \\%03o"), - (unsigned char) yytext[0]); } + grecs_error(&yylloc, 0, _("stray character \\%03o"), + (unsigned char) yytext[0]); } %% struct bind_input_context { ino_t i_node; dev_t i_dev; + struct grecs_locus_point point; grecs_locus_t locus; /* Current input location */ YY_BUFFER_STATE state; FILE *input; @@ -135,7 +146,7 @@ cmp_context(const void *a, const void *b) } static int -_push_context(const char *name, ino_t i_node, dev_t i_dev) +_push_context(const char *name, ino_t i_node, dev_t i_dev, grecs_locus_t *loc) { struct bind_input_context ctx, *pctx; @@ -148,7 +159,7 @@ _push_context(const char *name, ino_t i_node, dev_t i_dev) ctx.i_node = i_node; pctx = grecs_list_locate(input_stack, &ctx); if (pctx) { - grecs_error(&grecs_current_locus, 0, + grecs_error(&yylloc, 0, _("%s has already been included"), name); grecs_error(&pctx->locus, 0, _("this is where the previous inclusion occurred")); @@ -158,7 +169,11 @@ _push_context(const char *name, ino_t i_node, dev_t i_dev) pctx = grecs_malloc(sizeof(*pctx)); pctx->i_node = i_node; pctx->i_dev = i_dev; - pctx->locus = grecs_current_locus; + if (loc) + pctx->locus = *loc; + else + memset(&pctx->locus, 0, sizeof(pctx->locus)); /* FIXME */ + pctx->point = grecs_current_locus_point; pctx->state = YY_CURRENT_BUFFER; pctx->input = yyin; grecs_list_push(input_stack, pctx); @@ -184,7 +199,7 @@ _pop_context() } i_node = pctx->i_node; i_dev = pctx->i_dev; - grecs_current_locus = pctx->locus; + grecs_current_locus_point = pctx->point; yyin = pctx->input; yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(pctx->state); @@ -199,10 +214,8 @@ yywrap() } int -grecs_bind_new_source(const char *name) +grecs_bind_new_source(const char *name, grecs_locus_t *loc) { - grecs_locus_t *loc = grecs_current_locus.file ? - &grecs_current_locus : NULL; struct stat st; FILE *fp; @@ -245,15 +258,16 @@ grecs_bind_new_source(const char *name) grecs_free(cmd); } - if (_push_context(name, st.st_ino, st.st_dev)) { + if (_push_context(name, st.st_ino, st.st_dev, loc)) { return 1; } i_node = st.st_ino; i_dev = st.st_dev; yyin = fp; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); - 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; return 0; } @@ -18,17 +18,22 @@ # include <config.h> #endif #include <grecs.h> +#include <grecs-locus.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> static void -default_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg) +default_print_diag(grecs_locus_t const *locus, int err, int errcode, + const char *msg) { fflush(stdout); - if (locus) - fprintf(stderr, "%s:%d: ", locus->file, locus->line); + if (locus) { + YY_LOCATION_PRINT(stderr, *locus); + fputc(':', stderr); + fputc(' ', stderr); + } if (!err) fprintf(stderr, "warning: "); fprintf(stderr, "%s", msg); @@ -37,11 +42,12 @@ default_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg) fputc('\n', stderr); } -void (*grecs_print_diag_fun)(grecs_locus_t *, int, int, const char *msg) = +void (*grecs_print_diag_fun)(grecs_locus_t const *, int, int, + const char *msg) = default_print_diag; void -grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...) +grecs_warning(grecs_locus_t const *locus, int errcode, const char *fmt, ...) { va_list ap; char *buf = NULL; @@ -56,7 +62,7 @@ grecs_warning(grecs_locus_t *locus, int errcode, const char *fmt, ...) } void -grecs_error(grecs_locus_t *locus, int errcode, const char *fmt, ...) +grecs_error(grecs_locus_t const *locus, int errcode, const char *fmt, ...) { va_list ap; char *buf = NULL; diff --git a/src/format.c b/src/format.c index d65f712..f1a876f 100644 --- a/src/format.c +++ b/src/format.c @@ -31,7 +31,7 @@ grecs_data_type_string(enum grecs_data_type type) switch (type) { case grecs_type_void: return "void"; - + case grecs_type_string: return "string"; @@ -47,13 +47,13 @@ grecs_data_type_string(enum grecs_data_type type) case grecs_type_time: return "time"; - + case grecs_type_bool: return "boolean"; - + case grecs_type_ipv4: return "IPv4"; - + case grecs_type_cidr: return "CIDR"; @@ -125,7 +125,7 @@ grecs_print_simple_statement(struct grecs_keyword *kwp, unsigned level, FILE *stream) { const char *argstr; - + if (kwp->docstring) grecs_print_docstring(kwp->docstring, level, stream); format_level(level, stream); @@ -192,7 +192,33 @@ grecs_format_locus(grecs_locus_t *locus, struct grecs_format_closure *clos) if (locus) { char *str = NULL; size_t size = 0; - grecs_asprintf(&str, &size, "%s:%d", locus->file, locus->line); + + if (locus->beg.col == 0) + grecs_asprintf(&str, &size, "%s:%u", + locus->beg.file, + locus->beg.line); + else if (strcmp(locus->beg.file, locus->end.file)) + grecs_asprintf(&str, &size, "%s:%u.%u-%s:%u.%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.file, + locus->end.line, locus->end.col); + else if (locus->beg.line != locus->end.line) + grecs_asprintf(&str, &size, "%s:%u.%u-%u.%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.line, locus->end.col); + else if (locus->beg.col != locus->end.col) + grecs_asprintf(&str, &size, "%s:%u.%u-%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.col); + else + grecs_asprintf(&str, &size, "%s:%u.%u", + locus->beg.file, + locus->beg.line, + locus->beg.col); + clos->fmtfun(str, clos->data); free(str); } @@ -203,7 +229,7 @@ grecs_format_node_path(struct grecs_node *node, int flags, struct grecs_format_closure *clos) { char delim[2] = "."; - + if (node->up) grecs_format_node_path(node->up, flags, clos); if (node->type == grecs_node_root) @@ -277,7 +303,7 @@ grecs_format_node(struct grecs_node *node, int flags, struct grecs_format_closure *clos) { const char *delim_str = NULL; - + if (!(flags & _GRECS_NODE_MASK_OUTPUT)) { errno = EINVAL; return 1; @@ -297,7 +323,18 @@ grecs_format_node(struct grecs_node *node, int flags, case grecs_node_stmt: if (flags & GRECS_NODE_FLAG_LOCUS) { - grecs_format_locus(&node->locus, clos); + grecs_locus_t *locus; + + if (flags & GRECS_NODE_FLAG_PATH) { + if (flags & GRECS_NODE_FLAG_VALUE) + locus = &node->locus; + else + locus = &node->idloc; + } else if (flags & GRECS_NODE_FLAG_VALUE) + locus = &node->v.value->locus; + else + locus = &node->locus; + grecs_format_locus(locus, clos); delim_str = ": "; } if (flags & GRECS_NODE_FLAG_PATH) { @@ -367,7 +404,3 @@ grecs_print_node(struct grecs_node *node, int flags, FILE *fp) struct grecs_format_closure clos = { file_fmt, fp }; return grecs_format_node(node, flags, &clos); } - - - - 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); diff --git a/src/grecs-gram.y b/src/grecs-gram.y index bbe3d5e..92de6b2 100644 --- a/src/grecs-gram.y +++ b/src/grecs-gram.y @@ -19,6 +19,7 @@ # include <config.h> #endif #include <grecs.h> +#include <grecs-locus.h> #include <grecs-gram.h> #include <stdlib.h> #include <stdarg.h> @@ -31,11 +32,10 @@ int yyerror(char *s); static struct grecs_node *parse_tree; %} +%error-verbose +%locations + %union { - struct { - grecs_locus_t locus; - char *string; - } ident; char *string; grecs_value_t svalue, *pvalue; struct grecs_list *list; @@ -44,8 +44,7 @@ static struct grecs_node *parse_tree; struct { struct grecs_node *head, *tail; } node_list; } -%token <ident> IDENT -%token <string> STRING QSTRING MSTRING +%token <string> STRING QSTRING MSTRING IDENT %type <string> string slist %type <list> slist0 %type <svalue> value @@ -58,8 +57,7 @@ static struct grecs_node *parse_tree; input : maybe_stmtlist { - parse_tree = grecs_node_create(grecs_node_root, - &grecs_current_locus); + parse_tree = grecs_node_create(grecs_node_root, &@1); parse_tree->v.texttab = grecs_text_table(); grecs_node_bind(parse_tree, $1, 1); } @@ -92,25 +90,27 @@ stmt : simple simple : IDENT vallist ';' { - $$ = grecs_node_create(grecs_node_stmt, - &$1.locus); - $$->ident = $1.string; + $$ = grecs_node_create_points(grecs_node_stmt, + @1.beg, @2.end); + $$->ident = $1; + $$->idloc = @1; $$->v.value = $2; } | IDENT ';' { - $$ = grecs_node_create(grecs_node_stmt, - &$1.locus); - $$->ident = $1.string; + $$ = grecs_node_create(grecs_node_stmt, &@1); + $$->ident = $1; + $$->idloc = @1; $$->v.value = NULL; } ; block : IDENT tag '{' stmtlist '}' opt_sc { - $$ = grecs_node_create(grecs_node_block, - &$1.locus); - $$->ident = $1.string; + $$ = grecs_node_create_points(grecs_node_block, + @1.beg, @5.end); + $$->ident = $1; + $$->idloc = @1; $$->v.value = $2; grecs_node_bind($$, $4.head, 1); } @@ -135,6 +135,7 @@ vallist : vlist $$ = grecs_malloc(sizeof($$[0])); $$->type = GRECS_TYPE_ARRAY; + $$->locus = @1; $$->v.arg.c = n; $$->v.arg.v = grecs_calloc(n, sizeof($$->v.arg.v[0])); @@ -160,25 +161,25 @@ vlist : value value : string { $$.type = GRECS_TYPE_STRING; + $$.locus = @1; $$.v.string = $1; } | list { $$.type = GRECS_TYPE_LIST; + $$.locus = @1; $$.v.list = $1; } | MSTRING { $$.type = GRECS_TYPE_STRING; + $$.locus = @1; $$.v.string = $1; } ; string : STRING | IDENT - { - $$ = $1.string; - } | slist ; @@ -244,7 +245,7 @@ opt_sc : /* empty */ int yyerror(char *s) { - grecs_error(&grecs_current_locus, 0, "%s", s); + grecs_error(&yylloc, 0, "%s", s); return 0; } diff --git a/src/grecs-lex.l b/src/grecs-lex.l index 5ca4e31..ba7a386 100644 --- a/src/grecs-lex.l +++ b/src/grecs-lex.l @@ -2,7 +2,7 @@ %top { #ifdef HAVE_CONFIG_H # include <config.h> -#endif +#endif } %{ /* grecs - Gray's Extensible Configuration System @@ -22,6 +22,7 @@ with Grecs. If not, see <http://www.gnu.org/licenses/>. */ #include <grecs.h> +#include <grecs-locus.h> #include <grecs-gram.h> #include <unistd.h> #include <fcntl.h> @@ -37,7 +38,7 @@ static int multiline_unescape; /* Unescape here-document contents */ static int (*char_to_strip)(char); /* Strip matching characters of each here-document line */ -grecs_locus_t grecs_current_locus; /* Input file location */ +struct grecs_locus_point grecs_current_locus_point; /* Input file location */ /* Line correction. Equals to the number of #line |