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

Reply via email to