aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-06-27 10:56:44 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2011-06-27 11:38:48 +0300
commit901914e2277595eb102e9ac6f86b7894eb0318f9 (patch)
treea0ec73d3ed58ba06858143599b8595a845b72863
parent61a7ee9169f60501787f55f8480999c8b561a9f2 (diff)
downloadslb-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---------grecs0
-rw-r--r--src/config.c15
-rw-r--r--src/expr.y121
-rw-r--r--src/logger.c97
-rw-r--r--src/slb.c7
-rw-r--r--src/slb.h2
-rw-r--r--src/snmploop.c3
-rw-r--r--tests/intvar00.at4
-rw-r--r--tests/intvar01.at4
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;
}
diff --git a/src/expr.y b/src/expr.y
index f6b0c01..d9f23d8 100644
--- a/src/expr.y
+++ b/src/expr.y
@@ -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;
diff --git a/src/slb.c b/src/slb.c
index 974373e..04146ce 100644
--- a/src/slb.c
+++ b/src/slb.c
@@ -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)
{
diff --git a/src/slb.h b/src/slb.h
index 6b83c51..31fb0e5 100644
--- a/src/slb.h
+++ b/src/slb.h
@@ -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

Return to:

Send suggestions and report system problems to the System administrator.