diff options
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/ChangeLog | 23 | ||||
-rw-r--r-- | e-util/e-sexp.c | 84 | ||||
-rw-r--r-- | e-util/e-sexp.h | 11 |
3 files changed, 104 insertions, 14 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 51e256028c..5487bd9012 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,26 @@ +2001-01-23 Not Zed <NotZed@Ximian.com> + + * e-sexp.c (e_sexp_parse): Setup error return and return error on + parse error. + (parse_list): Fail if we have a problem. + (parse_value): Here too. + (fatal_error): Fatal error handling function, jumps back to the + top caller. + (term_eval_and): + (e_sexp_term_eval): + (term_eval_sub): + (term_eval_plus): + (term_eval_gt): + (term_eval_lt): + (term_eval_or): Fail on error. + (e_sexp_term_eval): Added a comment about where this can be + called, which is only from inside e_sexp_eval(). + (e_sexp_eval): Setup setjmp error handler. + (e_sexp_error): Error accessor function. + + * e-sexp.h: Added a longjmp environment to the structure, and an + error return to parse. + 2001-01-22 JP Rosevear <jpr@ximian.com> * e-dbhash.c (md5_to_dbt): New function, can't use strlen on the md5 diff --git a/e-util/e-sexp.c b/e-util/e-sexp.c index 4b500b4914..70e63737bf 100644 --- a/e-util/e-sexp.c +++ b/e-util/e-sexp.c @@ -126,6 +126,28 @@ static GScannerConfig scanner_config = FALSE /* scope_0_fallback */, }; +/* jumps back to the caller of f->failenv, only to be called from inside a callback */ +void +e_sexp_fatal_error(struct _ESExp *f, char *why, ...) +{ + va_list args; + + if (f->error) + g_free(f->error); + + va_start(args, why); + f->error = g_strdup_vprintf(why, args); + va_end(args); + + longjmp(f->failenv, 1); +} + +const char * +e_sexp_error(struct _ESExp *f) +{ + return f->error; +} + struct _ESExpResult * e_sexp_result_new(int type) { @@ -200,7 +222,10 @@ term_eval_and(struct _ESExp *f, int argc, struct _ESExpTerm **argv, void *data) if (type == -1) type = r1->type; if (type != r1->type) { - printf("invalid types in and operation, all types must be the same\n"); + e_sexp_result_free(r); + e_sexp_result_free(r1); + g_hash_table_destroy(ht); + e_sexp_fatal_error(f, "Invalid types in AND"); } else if ( r1->type == ESEXP_RES_ARRAY_PTR ) { char **a1; int l1, j; @@ -253,7 +278,10 @@ term_eval_or(struct _ESExp *f, int argc, struct _ESExpTerm **argv, void *data) if (type == -1) type = r1->type; if (r1->type != type) { - printf("wrong types in or operation\n"); + e_sexp_result_free(r); + e_sexp_result_free(r1); + g_hash_table_destroy(ht); + e_sexp_fatal_error(f, "Invalid types in OR"); } else if (r1->type == ESEXP_RES_ARRAY_PTR) { char **a1; int l1, j; @@ -312,7 +340,10 @@ term_eval_lt(struct _ESExp *f, int argc, struct _ESExpTerm **argv, void *data) r1 = e_sexp_term_eval(f, argv[0]); r2 = e_sexp_term_eval(f, argv[1]); if (r1->type != r2->type) { - printf("error, invalid types in compare\n"); + e_sexp_result_free(r1); + e_sexp_result_free(r2); + e_sexp_result_free(r); + e_sexp_fatal_error(f, "Incompatible types in compare <"); } else if (r1->type == ESEXP_RES_INT) { r->type = ESEXP_RES_BOOL; r->value.bool = r1->value.number < r2->value.number; @@ -338,7 +369,10 @@ term_eval_gt(struct _ESExp *f, int argc, struct _ESExpTerm **argv, void *data) r1 = e_sexp_term_eval(f, argv[0]); r2 = e_sexp_term_eval(f, argv[1]); if (r1->type != r2->type) { - printf("error, invalid types in compare\n"); + e_sexp_result_free(r1); + e_sexp_result_free(r2); + e_sexp_result_free(r); + e_sexp_fatal_error(f, "Incompatible types in compare >"); } else if (r1->type == ESEXP_RES_INT) { r->type = ESEXP_RES_BOOL; r->value.bool = r1->value.number > r2->value.number; @@ -394,7 +428,8 @@ term_eval_plus(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *dat total += argv[i]->value.number; } if (i<argc) { - g_warning("Wrong type trying to add integers: ignored"); + /* FIXME: this leaks the results in argv */ + e_sexp_fatal_error(f, "Invalid types in (+ ints)"); } r = e_sexp_result_new(ESEXP_RES_INT); r->value.number = total; @@ -405,7 +440,7 @@ term_eval_plus(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *dat g_string_append(s, argv[i]->value.string); } if (i<argc) { - g_warning("Wrong type trying to concat strings: ignored"); + e_sexp_fatal_error(f, "Invalid types in (+ strings)"); } r = e_sexp_result_new(ESEXP_RES_STRING); r->value.string = s->str; @@ -438,7 +473,8 @@ term_eval_sub(struct _ESExp *f, int argc, struct _ESExpResult **argv, void *data total -= argv[i]->value.number; } if (i<argc) { - g_warning("Wrong type trying to subtract numbers: ignored"); + /* FIXME: this leaks the results in argv */ + e_sexp_fatal_error(f, "Invalid types in -"); } r = e_sexp_result_new(ESEXP_RES_INT); r->value.number = total; @@ -492,6 +528,7 @@ term_eval_begin(struct _ESExp *f, int argc, struct _ESExpTerm **argv, void *data } +/* this must only be called from inside term evaluation callbacks! */ struct _ESExpResult * e_sexp_term_eval(struct _ESExp *f, struct _ESExpTerm *t) { @@ -553,8 +590,7 @@ e_sexp_term_eval(struct _ESExp *f, struct _ESExpTerm *t) } break; } default: - printf("Warning: Unknown type encountered in parse tree: %d\n", t->type); - r->type = ESEXP_RES_UNDEFINED; + e_sexp_fatal_error(f, "Unknown type in parse tree: %d", t->type); } return r; @@ -692,7 +728,7 @@ parse_values(ESExp *f, int *len) p(printf("parsing values\n")); /* FIXME: This hardcoded nonsense!!! :) */ - terms = g_malloc0(20*sizeof(*terms)); + terms = g_malloc0(30*sizeof(*terms)); while ( (token = g_scanner_peek_next_token(gs)) != G_TOKEN_EOF && token != ')') { @@ -755,13 +791,16 @@ parse_value(ESExp *f) break; default: printf("Invalid symbol type: %d\n", s->type); + e_sexp_fatal_error(f, "Invalid symbol type: %s: %d", s->name, s->type); } break; case G_TOKEN_IDENTIFIER: printf("Unknown identifier encountered: %s\n", g_scanner_cur_value(gs).v_identifier); + e_sexp_fatal_error(f, "Unknown identifier: %s", g_scanner_cur_value(gs).v_identifier); break; default: printf("Innvalid token trying to parse a list of values\n"); + e_sexp_fatal_error(f, "Unexpected token encountered: %d", token); } p(printf("done parsing value\n")); return t; @@ -800,20 +839,26 @@ parse_list(ESExp *f, int gotbrace) t->value.func.terms = parse_values(f, &t->value.func.termcount); } else { printf("Error, trying to call variable as function\n"); + parse_term_free(t); + e_sexp_fatal_error(f, "Trying to call variable as function: %s", s->name); } break; } case G_TOKEN_IDENTIFIER: printf("Unknown identifier: %s\n", g_scanner_cur_value(gs).v_identifier); + e_sexp_fatal_error(f, "Unknown identifier: %s", g_scanner_cur_value(gs).v_identifier); break; default: printf("unknown sequence encountered, type = %d\n", token); + e_sexp_fatal_error(f, "Unexpected token encountered: %d", token); } token = g_scanner_get_next_token(gs); if (token != ')') { printf("Error, expected ')' not found\n"); + e_sexp_fatal_error(f, "Missing ')'"); } } else { printf("Error, list term without opening (\n"); + e_sexp_fatal_error(f, "Missing '('"); } p(printf("returning list %p\n", t)); @@ -1046,24 +1091,37 @@ e_sexp_input_file (ESExp *f, int fd) g_scanner_input_file(f->scanner, fd); } -/* needs some error return? */ -void +/* returns -1 on error */ +int e_sexp_parse(ESExp *f) { - g_return_if_fail(FILTER_IS_SEXP(f)); + g_return_val_if_fail(FILTER_IS_SEXP(f), -1); + + if (setjmp(f->failenv)) { + g_warning("Error in parsing: %s", f->error); + return -1; + } if (f->tree) parse_term_free(f->tree); f->tree = parse_list(f, FALSE); + + return 0; } +/* returns NULL on error */ struct _ESExpResult * e_sexp_eval(ESExp *f) { g_return_val_if_fail(FILTER_IS_SEXP(f), NULL); g_return_val_if_fail(f->tree != NULL, NULL); + if (setjmp(f->failenv)) { + g_warning("Error in execution: %s", f->error); + return NULL; + } + return e_sexp_term_eval(f, f->tree); } diff --git a/e-util/e-sexp.h b/e-util/e-sexp.h index 5cf2740fc1..cfedaea98b 100644 --- a/e-util/e-sexp.h +++ b/e-util/e-sexp.h @@ -5,6 +5,7 @@ #define _E_SEXP_H #include <glib.h> +#include <setjmp.h> #ifdef E_SEXP_IS_GTK_OBJECT #include <gtk/gtk.h> @@ -98,6 +99,10 @@ struct _ESExp { #endif GScanner *scanner; /* for parsing text version */ ESExpTerm *tree; /* root of expression tree */ + + /* private stuff */ + jmp_buf failenv; + char *error; }; struct _ESExpClass { @@ -124,7 +129,7 @@ void e_sexp_input_text (ESExp *f, const char *text, int len); void e_sexp_input_file (ESExp *f, int fd); -void e_sexp_parse (ESExp *f); +int e_sexp_parse (ESExp *f); ESExpResult *e_sexp_eval (ESExp *f); ESExpResult *e_sexp_term_eval (struct _ESExp *f, struct _ESExpTerm *t); @@ -135,4 +140,8 @@ void e_sexp_result_free (struct _ESExpResult *t); void e_sexp_encode_bool(GString *s, gboolean state); void e_sexp_encode_string(GString *s, const char *string); +/* only to be called from inside a callback to signal a fatal execution error */ +void e_sexp_fatal_error(struct _ESExp *f, char *why, ...); +const char *e_sexp_error(struct _ESExp *f); + #endif /* _E_SEXP_H */ |