This way, the caller has access to the full diagnostics. --- src/compiler/fpvm.c | 14 +++++++++++--- src/compiler/parser_helper.c | 34 +++++++++++++++++++++++++++++----- src/compiler/parser_helper.h | 2 +- src/compiler/ptest/ptest.c | 8 +++++++- 4 files changed, 48 insertions(+), 10 deletions(-)
diff --git a/src/compiler/fpvm.c b/src/compiler/fpvm.c index b6b75d6..5acd4ba 100644 --- a/src/compiler/fpvm.c +++ b/src/compiler/fpvm.c @@ -15,6 +15,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdlib.h> #include <stdio.h> #include <fpvm/fpvm.h> @@ -46,10 +47,13 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, const char *expr) { union parser_comm comm; + const char *error; int res; - if (!fpvm_parse(expr, TOK_START_EXPR, &comm)) { - snprintf(fragment->last_error, FPVM_MAXERRLEN, "Parse error"); + error = fpvm_parse(expr, TOK_START_EXPR, &comm); + if(error) { + snprintf(fragment->last_error, FPVM_MAXERRLEN, "%s", error); + free((void *) error); return 0; } @@ -65,6 +69,10 @@ int fpvm_assign(struct fpvm_fragment *fragment, const char *dest, int fpvm_chunk(struct fpvm_fragment *fragment, const char *chunk) { union parser_comm comm = { .fragment = fragment }; + const char *error; - return fpvm_parse(chunk, TOK_START_ASSIGN, &comm); + error = fpvm_parse(chunk, TOK_START_ASSIGN, &comm); + if (error) + free((void *) error); + return !error; } diff --git a/src/compiler/parser_helper.c b/src/compiler/parser_helper.c index 0b68b1c..4758d9f 100644 --- a/src/compiler/parser_helper.c +++ b/src/compiler/parser_helper.c @@ -15,6 +15,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <stdarg.h> +#include <stdlib.h> #include <stdio.h> #include <malloc.h> #include <fpvm/ast.h> @@ -42,8 +44,27 @@ static int printable_label(const char *s) return p-s; } +static const char *alloc_printf(const char *fmt, ...) +{ + va_list ap; + int n; + char *s; + + va_start(ap, fmt); + n = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + s = malloc(n+1); + + va_start(ap, fmt); + vsnprintf(s, n+1, fmt, ap); + va_end(ap); + + return s; +} -int fpvm_parse(const char *expr, int start_token, union parser_comm *comm) +const char *fpvm_parse(const char *expr, int start_token, + union parser_comm *comm) { struct scanner *s; struct parser_state state = { @@ -55,6 +76,7 @@ int fpvm_parse(const char *expr, int start_token, union parser_comm *comm) int tok; struct id *identifier; void *p; + const char *error = NULL; s = new_scanner((unsigned char *)expr); p = ParseAlloc(malloc); @@ -72,11 +94,12 @@ int fpvm_parse(const char *expr, int start_token, union parser_comm *comm) } state.id = identifier; if(tok == TOK_ERROR) { - printf("FPVM, line %d, near \"%c\": scan error\n", + error = alloc_printf( + "FPVM, line %d, near \"%c\": scan error", s->lineno, printable_char(s->cursor[-1])); ParseFree(p, free); delete_scanner(s); - return 0; + return error; } Parse(p, tok, identifier, &state); tok = scan(s); @@ -86,11 +109,12 @@ int fpvm_parse(const char *expr, int start_token, union parser_comm *comm) delete_scanner(s); if(!state.success) - printf("FPVM, line %d, near \"%.*s\": parse error\n", + error = alloc_printf( + "FPVM, line %d, near \"%.*s\": parse error", state.error_lineno, printable_label(state.error_label), state.error_label); - return state.success; + return error; } void fpvm_parse_free(struct ast_node *node) diff --git a/src/compiler/parser_helper.h b/src/compiler/parser_helper.h index b4e72d5..8b4babe 100644 --- a/src/compiler/parser_helper.h +++ b/src/compiler/parser_helper.h @@ -26,7 +26,7 @@ union parser_comm { struct fpvm_fragment *fragment; }; -int fpvm_parse(const char *expr, int start_token, +const char *fpvm_parse(const char *expr, int start_token, union parser_comm *comm); void fpvm_parse_free(struct ast_node *node); diff --git a/src/compiler/ptest/ptest.c b/src/compiler/ptest/ptest.c index eab3b0d..7db901b 100644 --- a/src/compiler/ptest/ptest.c +++ b/src/compiler/ptest/ptest.c @@ -187,6 +187,7 @@ int main(int argc, char **argv) int c; const char *buf; union parser_comm comm; + const char *error; while ((c = getopt(argc, argv, "q")) != EOF) switch (c) { @@ -207,5 +208,10 @@ int main(int argc, char **argv) usage(*argv); } - return !fpvm_parse(buf, TOK_START_ASSIGN, &comm); + error = fpvm_parse(buf, TOK_START_ASSIGN, &comm); + if (!error) + return 0; + fflush(stdout); + fprintf(stderr, "%s\n", error); + return 1; } -- 1.7.1 _______________________________________________ http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org IRC: #milkymist@Freenode
