diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-06-27 10:56:44 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2011-06-27 11:38:48 +0300 |
commit | 901914e2277595eb102e9ac6f86b7894eb0318f9 (patch) | |
tree | a0ec73d3ed58ba06858143599b8595a845b72863 | |
parent | 61a7ee9169f60501787f55f8480999c8b561a9f2 (diff) | |
download | slb-901914e2277595eb102e9ac6f86b7894eb0318f9.tar.gz slb-901914e2277595eb102e9ac6f86b7894eb0318f9.tar.bz2 |
Keep track of column numbers in expressions.
* grecs: Upgrade.
* src/config.c (cb_define_expression): Get locus directly from
the value.
(config_init): Set grecs_adjust_string_locations.
Set grecs_print_diag_fun.
* src/logger.c (syslog_printer, stderr_printer)
(log_printer,logmsg_at_locus): Locus is const.
(grecs_print_diag): Move to config.c
* src/slb.h (logmsg_at_locus): Change signature.
* src/expr.y: Keep track of column numbers.
Turn on verbose error messages.
* src/logger.c (syslog_printer): Rewrite.
(stderr_printer): Use YY_LOCATION_PRINT from grecs.
* src/snmploop.c (process_result): Use new grecs_locus_t structure.
* tests/intvar00.at: Update.
* tests/intvar01.at: Update.
m--------- | grecs | 0 | ||||
-rw-r--r-- | src/config.c | 15 | ||||
-rw-r--r-- | src/expr.y | 121 | ||||
-rw-r--r-- | src/logger.c | 97 | ||||
-rw-r--r-- | src/slb.c | 7 | ||||
-rw-r--r-- | src/slb.h | 2 | ||||
-rw-r--r-- | src/snmploop.c | 3 | ||||
-rw-r--r-- | tests/intvar00.at | 4 | ||||
-rw-r--r-- | tests/intvar01.at | 4 |
9 files changed, 159 insertions, 94 deletions
diff --git a/grecs b/grecs -Subproject 4c1959a4848c30206de3be4b16bdf04b650daae +Subproject 5a37057b0ca1b7314f7f338134efc5100dc9223 diff --git a/src/config.c b/src/config.c index a39f1ff..edf9524 100644 --- a/src/config.c +++ b/src/config.c @@ -139,7 +139,8 @@ cb_define_expression(enum grecs_callback_command cmd, if (assert_n_strings(locus, cmd, value, 2, 2)) return 1; - if (compile_expression(value->v.arg.v[1]->v.string, locus, &expr)) + if (compile_expression(value->v.arg.v[1]->v.string, + &value->v.arg.v[1]->locus, &expr)) return 1; expr->ex_name = value->v.arg.v[0]->v.string; @@ -160,7 +161,7 @@ cb_server_expression(enum grecs_callback_command cmd, if (assert_string_value(locus, cmd, value)) return 1; - return compile_expression(value->v.string, locus, pexpr); + return compile_expression(value->v.string, &value->locus, pexpr); } int @@ -789,6 +790,14 @@ config_help() grecs_print_statement_array(slb_kw, 1, 0, stdout); } + +static void +grecs_print_diag(grecs_locus_t const *locus, int err, int errcode, + const char *msg) +{ + logmsg_at_locus(err ? LOG_ERR : LOG_WARNING, locus, "%s", msg); +} + void config_init() { @@ -796,6 +805,8 @@ config_init() DEFAULT_INCLUDE_DIR, NULL); grecs_preprocessor = DEFAULT_PREPROCESSOR; grecs_log_to_stderr = 1; + grecs_adjust_string_locations = 1; + grecs_print_diag_fun = grecs_print_diag; } @@ -16,12 +16,14 @@ %{ #include "slb.h" +#include "grecs-locus.h" #include <math.h> double round(double x); double trunc(double x); -static grecs_locus_t *input_locus; + +static struct grecs_locus_point current_point; static const char *inbuf; static const char *curp; static int input_char; @@ -41,7 +43,8 @@ static struct slb_node *parse_tree; static int yylex(void); static void yyerror(char *s); -static struct slb_node *alloc_node(void); +static struct slb_node *alloc_node(struct grecs_locus_point beg, + struct grecs_locus_point end); static struct function *function_lookup(const char *name, size_t len); struct daemon_only_closure @@ -66,6 +69,9 @@ request_daemon_mode_hook(void *ptr) %} +%error-verbose +%locations + %token <number> T_NUMBER %token <var> T_VARIABLE %token <func> T_FUNC @@ -81,7 +87,7 @@ request_daemon_mode_hook(void *ptr) %left '+' '-' %left '*' '/' %left T_UMINUS -%right T_POW +%right T_POW %left '?' %type <node> expr atom opte func asgn @@ -103,7 +109,7 @@ input: elst if ($1.count == 1) parse_tree = $1.head; else { - parse_tree = alloc_node(); + parse_tree = alloc_node(@1.beg, @1.end); parse_tree->n_type = node_list; parse_tree->n_next = $1.head; } @@ -126,98 +132,98 @@ elst : expr expr : expr T_EQ expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_eq; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_NE expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_ne; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_LT expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_lt; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_LE expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_le; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_GT expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_gt; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_GE expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_ge; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_OR expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_or; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_AND expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_and; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr '+' expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_add; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr '-' expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_sub; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr '*' expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_mul; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr '/' expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_div; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | expr T_POW expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_pow; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; } | '-' expr %prec T_UMINUS { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @2.end); $$->n_type = node_uminus; $$->v.n_arg[0] = $2; } @@ -227,7 +233,7 @@ expr : expr T_EQ expr } | T_NOT expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @2.end); $$->n_type = node_not; $$->v.n_arg[0] = $2; } @@ -237,7 +243,7 @@ expr : expr T_EQ expr } | expr '?' opte ':' expr %prec '?' { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @5.end); $$->n_type = node_cond; $$->v.n_arg[0] = $1; $$->v.n_arg[1] = $3; @@ -250,7 +256,7 @@ expr : expr T_EQ expr asgn : T_VARIABLE '=' expr { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @3.end); $$->n_type = node_asgn; $$->v.n_asgn.var = $1; $$->v.n_asgn.expr = $3; @@ -266,19 +272,19 @@ opte : /* empty */ atom : T_NUMBER { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @1.end); $$->n_type = node_const; $$->v.n_const = $1; } | T_VARIABLE { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @1.end); $$->n_type = node_variable; $$->v.n_var = $1; } | T_EXPR { - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @1.end); $$->n_type = node_subexpr; $$->v.n_expr.name = grecs_malloc($1.len + 1); memcpy($$->v.n_expr.name, $1.name, $1.len + 1); @@ -289,24 +295,22 @@ atom : T_NUMBER func : T_FUNC '(' args ')' { if ($3.count < $1->minargs) { - grecs_error(input_locus, 0, - "too few arguments in call to %s", + grecs_error(&@1, 0, "too few arguments in call to %s", $1->name); YYERROR; } else if ($3.count > $1->maxargs) { - grecs_error(input_locus, 0, - "too many arguments in call to %s", + grecs_error(&@1, 0, "too many arguments in call to %s", $1->name); YYERROR; } if ($1->flags & FUN_DAEMON_ONLY) { struct daemon_only_closure *p = grecs_malloc(sizeof(*p)); p->func = $1; - p->locus = *input_locus; + p->locus = @1; add_config_finish_hook(request_daemon_mode_hook, p); } - $$ = alloc_node(); + $$ = alloc_node(@1.beg, @4.end); $$->n_type = node_func; $$->n_min_eval = $1->min_eval; $$->v.n_func.func = $1->func; @@ -343,7 +347,7 @@ argl : expr void yyerror(char *s) { - grecs_error(input_locus, 0, "%s", s); + grecs_error(&yylloc, 0, "%s", s); } static int @@ -355,8 +359,14 @@ input() input_char = *curp; if (!input_char) yyeof++; - else + else { curp++; + if (input_char == '\n') { + current_point.line++; + current_point.col = 1; + } else + current_point.col++; + } } return input_char; } @@ -370,6 +380,14 @@ unput() --curp; if (curp > inbuf) input_char = curp[-1]; + if (input_char == '\n') { + const char *p; + + current_point.line--; + for (p = curp, current_point.col = 1; p > inbuf && *p != '\n'; + current_point.col++); + } else + current_point.col--; } static int @@ -380,13 +398,23 @@ yylex() ; if (!input_char) return 0; + + yylloc.beg = current_point; + yylloc.beg.col--; + yylloc.end = yylloc.beg; + /* * A number */ if (isdigit(input_char)) { - yylval.number = strtod(curp - 1, (char**)&curp); + const char *p; + + yylval.number = strtod(curp - 1, (char**)&p); debug(SLB_DEBCAT_ELEX, 1, ("yylex: NUMBER %f", yylval.number)); + current_point.col += p - curp; + yylloc.end = current_point; + curp = p; return T_NUMBER; } @@ -401,7 +429,8 @@ yylex() isdigit(input_char))) len++; unput(); - + yylloc.end = current_point; + fp = function_lookup(p, len); if (fp) { yylval.func = fp; @@ -426,7 +455,8 @@ yylex() isdigit(input_char))) len++; unput(); - + yylloc.end = current_point; + yylval.expr.name = p; yylval.expr.len = len; return T_EXPR; @@ -442,10 +472,12 @@ yylex() debug(SLB_DEBCAT_ELEX, 1, ("yylex: %s", input_char == '&' ? "AND" : "OR")); + yylloc.end = current_point; return input_char == '&' ? T_AND : T_OR; } unput(); - + yylloc.end = current_point; + debug(SLB_DEBCAT_ELEX, 1, ("yylex: %c", c)); return c; } @@ -459,19 +491,24 @@ yylex() switch (c) { case '<': debug(SLB_DEBCAT_ELEX, 1, ("yylex: LE")); + yylloc.end = current_point; return T_LE; case '>': debug(SLB_DEBCAT_ELEX, 1, ("yylex: GE")); + yylloc.end = current_point; return T_GE; case '=': debug(SLB_DEBCAT_ELEX, 1, ("yylex: EQ")); + yylloc.end = current_point; return T_EQ; case '!': debug(SLB_DEBCAT_ELEX, 1, ("yylex: NE")); + yylloc.end = current_point; return T_NE; } } else { unput(); + yylloc.end = current_point; switch (c) { case '<': debug(SLB_DEBCAT_ELEX, 1, ("yylex: LT")); @@ -495,12 +532,14 @@ yylex() if (input_char == '*') { if (input() == '*') { debug(SLB_DEBCAT_ELEX, 1, ("yylex: **")); + yylloc.end = current_point; return T_POW; } unput(); } debug(SLB_DEBCAT_ELEX, 1, ("yylex: %c", input_char)); + yylloc.end = current_point; return input_char; } @@ -512,7 +551,8 @@ compile_expression(const char *text, grecs_locus_t *locus, inbuf = curp = text; yyeof = 0; - input_locus = locus; + yylloc = *locus; + current_point = yylloc.beg; parse_tree = NULL; parse_vartab = grecs_symtab_create_default(sizeof(struct slb_varref)); @@ -539,10 +579,11 @@ compile_expression(const char *text, grecs_locus_t *locus, } static struct slb_node * -alloc_node() +alloc_node(struct grecs_locus_point beg, struct grecs_locus_point end) { struct slb_node *p = grecs_zalloc(sizeof(*p)); - p->n_locus = *input_locus; + p->n_locus.beg = beg; + p->n_locus.end = end; p->n_type = node_unknown; return p; } @@ -1142,7 +1183,7 @@ copy_node(struct slb_node *node, struct grecs_symtab *vartab) if (!node) return NULL; - new_node = alloc_node(); + new_node = alloc_node(node->n_locus.beg, node->n_locus.end); new_node->n_type = node->n_type; new_node->n_min_eval = node->n_min_eval; diff --git a/src/logger.c b/src/logger.c index 79314d2..cc2daea 100644 --- a/src/logger.c +++ b/src/logger.c @@ -15,6 +15,7 @@ along with SLB. If not, see <http://www.gnu.org/licenses/>. */ #include "slb.h" +#include "grecs-locus.h" int log_to_stderr = -1; /* -1 means autodetect */ int syslog_facility = LOG_DAEMON; @@ -92,63 +93,81 @@ string_to_syslog_facility(const char *str, int *pfacility) /* Logging */ void -syslog_printer(int prio, grecs_locus_t *locus, const char *fmt, va_list ap) +syslog_printer(int prio, grecs_locus_t const *locus, const char *fmt, + va_list ap) { static char *fmtbuf; static size_t fmtsize; - size_t size; - char linebuf[128]; - size_t locsize = 0; + char *locstr = NULL; + char *pfxbuf = NULL; + const char *p; if (locus) { - snprintf(linebuf, sizeof(linebuf), "%u", locus->line); - locsize = strlen(locus->file) + 1 + strlen(linebuf) + 2; - } - if (syslog_include_prio) { - const char *p; - - if (n_to_syslog(prio_trans, prio, &p) == 0) { - size = strlen(p) + 3 + strlen(fmt) + locsize + 1; - - if (size > fmtsize) { - fmtsize = size; - fmtbuf = grecs_realloc(fmtbuf, fmtsize); - } - if (locsize) { - sprintf(fmtbuf, "%s:%s: [%s] %s", - locus->file, linebuf, p, fmt); - locsize = 0; - } else - sprintf(fmtbuf, "[%s] %s", p, fmt); - fmt = fmtbuf; - } - } - if (locsize) { - size = strlen(fmt) + locsize + 1; - if (size > fmtsize) { - fmtsize = size; - fmtbuf = grecs_realloc(fmtbuf, fmtsize); - } - sprintf(fmtbuf, "%s:%s: %s", locus->file, linebuf, fmt); + size_t size = 0; + + if (locus->beg.col == 0) + grecs_asprintf(&locstr, &size, "%s:%u", + locus->beg.file, + locus->beg.line); + else if (strcmp(locus->beg.file, locus->end.file)) + grecs_asprintf(&locstr, &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(&locstr, &size, "%s:%u.%u-%u.%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.line, locus->end.col); + else + grecs_asprintf(&locstr, &size, "%s:%u.%u-%u", + locus->beg.file, + locus->beg.line, locus->beg.col, + locus->end.col); } - vsyslog(prio, fmt, ap); + + if (syslog_include_prio && n_to_syslog(prio_trans, prio, &p) == 0) { + size_t size = 0; + + if (locstr) { + grecs_asprintf(&pfxbuf, &size, "%s: [%s]", + locstr, p); + free(locstr); + locstr = NULL; + } else + grecs_asprintf(&pfxbuf, &size, "[%s]", + p); + } else + pfxbuf = locstr; + + grecs_vasprintf(&fmtbuf, &fmtsize, fmt, ap); + + if (pfxbuf) { + syslog(prio, "%s: %s", pfxbuf, fmtbuf); + free(pfxbuf); + } else + syslog(prio, "%s", fmtbuf); } void -stderr_printer(int prio, grecs_locus_t *locus, const char *fmt, va_list ap) +stderr_printer(int prio, grecs_locus_t const *locus, const char *fmt, + va_list ap) { const char *p; fprintf (stderr, "%s: ", syslog_tag); - if (locus) - fprintf(stderr, "%s:%u: ", locus->file, locus->line); + if (locus) { + YY_LOCATION_PRINT(stderr, *locus); + fprintf(stderr, ": "); + } if (n_to_syslog(prio_trans, prio, &p) == 0) fprintf(stderr, "[%s] ", p); vfprintf(stderr, fmt, ap); fputc('\n', stderr); } -static void (*log_printer)(int prio, grecs_locus_t *locus, +static void (*log_printer)(int prio, grecs_locus_t const *locus, const char *fmt, va_list ap) = stderr_printer; void @@ -188,7 +207,7 @@ logmsg(int prio, const char *fmt, ...) } void -logmsg_at_locus(int prio, grecs_locus_t *locus, const char *fmt, ...) +logmsg_at_locus(int prio, grecs_locus_t const *locus, const char *fmt, ...) { va_list ap; @@ -98,13 +98,6 @@ parse_debug_level(const char *arg) #include "cmdline.h" -void -grecs_print_diag(grecs_locus_t *locus, int err, int errcode, const char *msg) -{ - logmsg_at_locus(err ? LOG_ERR : LOG_WARNING, locus, "%s", msg); -} - - static int logger_callback(int majorID, int minorID, void *serverarg, void *clientarg) { @@ -342,7 +342,7 @@ extern int syslog_include_prio; void logger_setup(void); void logmsg(int prio, const char *fmt, ...) SLB_PRINTFLIKE(2,3); -void logmsg_at_locus(int prio, grecs_locus_t *locus, const char *fmt, ...) +void logmsg_at_locus(int prio, grecs_locus_t const *locus, const char *fmt, ...) SLB_PRINTFLIKE(3,4); void debug_printf(const char *fmt, ...) SLB_PRINTFLIKE(1,2); diff --git a/src/snmploop.c b/src/snmploop.c index 680c249..d54b84f 100644 --- a/src/snmploop.c +++ b/src/snmploop.c @@ -123,7 +123,8 @@ process_result(struct slb_server *srv, struct snmp_pdu *pdu) if (ap && assertion_test(ap, vp)) { logmsg(LOG_NOTICE, "%s:%d: %s: assertion \"%s\" failed", - ap->locus.file, ap->locus.line, srvid(srv), + ap->locus.beg.file, ap->locus.beg.line, + srvid(srv), ap->text); return; } diff --git a/tests/intvar00.at b/tests/intvar00.at index 568a232..ca5f175 100644 --- a/tests/intvar00.at +++ b/tests/intvar00.at @@ -27,7 +27,7 @@ server "srv1" { } ], [EX_CONFIG], -[test.conf:7: use of uninitialized variable x +[slb: test.conf:1.26-27: [[ERR]] use of uninitialized variable x ]) -AT_CLEANUP
\ No newline at end of file +AT_CLEANUP diff --git a/tests/intvar01.at b/tests/intvar01.at index 03741d3..231f5cf 100644 --- a/tests/intvar01.at +++ b/tests/intvar01.at @@ -27,7 +27,7 @@ server "srv1" { } ], [EX_CONFIG], -[test.conf:7: use of uninitialized variable x +[slb: test.conf:1.30-31: [[ERR]] use of uninitialized variable x ]) -AT_CLEANUP
\ No newline at end of file +AT_CLEANUP |