From 1010ae06bfa4ab1fd3c6708a9a2e8f5e0f329ac3 Mon Sep 17 00:00:00 2001 From: Duncaen Date: Mon, 28 Jan 2019 15:00:56 +0100 Subject: mpick: add support for multiline expressions and comments --- mpick.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 12 deletions(-) (limited to 'mpick.c') diff --git a/mpick.c b/mpick.c index 78509d4..eb6afc9 100644 --- a/mpick.c +++ b/mpick.c @@ -154,6 +154,12 @@ struct file { struct file *next; }; +struct pos { + char *pos; + char *line; + size_t linenr; +}; + static struct thread *thr; static char *argv0; @@ -167,10 +173,14 @@ static long num; static struct expr *expr; static long cur_idx; static char *cur; -static char *pos; static time_t now; static int prune; +static char *pos; +static const char *fname; +static char *line = NULL; +static int linenr = 0; + static struct file *files, *fileq = NULL; static void * @@ -196,8 +206,21 @@ xstrdup(const char *s) static void ws() { - while (isspace((unsigned char)*pos)) - pos++; + for (; *pos;) { + while (isspace((unsigned char)*pos)) { + if (*pos == '\n') { + line = pos+1; + linenr++; + } + pos++; + } + if (*pos != '#') + break; + + pos += strcspn(pos, "\n\0"); + if (*pos != '\n') + break; + } } static int @@ -223,12 +246,34 @@ parse_error(char *msg, ...) { va_list ap; va_start(ap, msg); - fprintf(stderr, "%s: parse error: ", argv0); + fprintf(stderr, "%s: parse error: %s:%d:%ld: ", argv0, fname, linenr, pos-line+1); vfprintf(stderr, msg, ap); fprintf(stderr, "\n"); exit(2); } +noreturn static void +parse_error_at(struct pos *savepos, char *msg, ...) +{ + char *e; + + if (savepos) { + pos = savepos->pos; + line = savepos->line; + linenr = savepos->linenr; + } + + va_list ap; + va_start(ap, msg); + fprintf(stderr, "%s: parse error: %s:%d:%ld: ", argv0, fname, linenr, pos-line+1); + vfprintf(stderr, msg, ap); + fprintf(stderr, " at '"); + for (e = pos+15; *pos && *pos != '\n' && pos <= e; pos++) + putc(*pos, stderr); + fprintf(stderr, "'\n"); + exit(2); +} + static struct expr * mkexpr(enum op op) { @@ -460,11 +505,11 @@ parse_strcmp() else if (token("!==") || token("!=")) negate = 1, op = EXPR_STREQ; else - parse_error("invalid string operator at '%.15s'", pos); + parse_error_at(NULL, "invalid string operator"); char *s; if (!parse_string(&s)) { - parse_error("invalid string at '%.15s'", pos); + parse_error_at(NULL, "invalid string"); return 0; } @@ -598,7 +643,7 @@ parse_cmp() return parse_flag(); if (!(op = parse_op())) - parse_error("invalid comparison at '%.15s'", pos); + parse_error_at(NULL, "invalid comparison"); int64_t n; if (parse_num(&n)) { @@ -716,7 +761,7 @@ parse_timecmp() op = parse_op(); if (!op) - parse_error("invalid comparison at '%.15s'", pos); + parse_error_at(NULL, "invalid comparison"); int64_t n; if (parse_num(&n) || parse_dur(&n)) { @@ -740,7 +785,7 @@ parse_redir(struct expr *e) if (token("|")) { if (!parse_string(&s)) - parse_error("expected command"); + parse_error_at(NULL, "expected command"); struct expr *r = mkexpr(EXPR_REDIR_PIPE); r->a.string = s; r->b.string = xstrdup("w"); @@ -751,7 +796,7 @@ parse_redir(struct expr *e) else return e; if (!parse_string(&s)) - parse_error("expected file name"); + parse_error_at(NULL, "expected file name"); struct expr *r = mkexpr(EXPR_REDIR_FILE); r->a.string = s; r->b.string = xstrdup(m); @@ -802,7 +847,7 @@ parse_cond() return r; } else { - parse_error("expected : at '%.15s'", pos); + parse_error_at(NULL, "expected :", pos); } } @@ -815,7 +860,7 @@ parse_expr() pos = s; struct expr *e = parse_cond(); if (*pos) - parse_error("trailing garbage at '%.15s'", pos); + parse_error_at(NULL, "trailing garbage"); return e; } -- cgit 1.4.1