From: Felix Fietkau Date: Sat, 19 Jan 2008 22:05:45 +0000 (+0100) Subject: more error handling X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=7952092949fb0dccd126d5ff6f73807feb4211b8;p=uci.git more error handling --- diff --git a/err.h b/err.h index 469164c..cf42856 100644 --- a/err.h +++ b/err.h @@ -38,7 +38,7 @@ * functions from other uci functions is only allowed at the end of the * calling function. */ -#define UCI_HANDLE_ERR(ctx) do { \ +#define UCI_HANDLE_ERR(ctx) do { \ int __val; \ if (!ctx) \ return UCI_ERR_INVAL; \ @@ -49,6 +49,26 @@ } \ } while (0) +/* + * In a block enclosed by UCI_TRAP_SAVE and UCI_TRAP_RESTORE, all exceptions + * are intercepted and redirected to the label specified in 'handler' + * after UCI_TRAP_RESTORE, or when reaching the 'handler' label, the old + * exception handler is restored + */ +#define UCI_TRAP_SAVE(ctx, handler) do { \ + jmp_buf __old_trap; \ + int __val; \ + memcpy(__old_trap, ctx->trap, sizeof(ctx->trap)); \ + __val = setjmp(ctx->trap); \ + if (__val) { \ + ctx->errno = __val; \ + memcpy(ctx->trap, __old_trap, sizeof(ctx->trap)); \ + goto handler; \ + } +#define UCI_TRAP_RESTORE(ctx) \ + memcpy(ctx->trap, __old_trap, sizeof(ctx->trap)); \ +} while(0) + /* * check the specified condition. * throw an invalid argument exception if it's false diff --git a/libuci.h b/libuci.h index aba4359..50c20f1 100644 --- a/libuci.h +++ b/libuci.h @@ -81,6 +81,8 @@ struct uci_context /* private: */ int errno; jmp_buf trap; + jmp_buf trap_saved; + int saved; }; struct uci_parse_context diff --git a/list.c b/list.c index 5888042..51fca61 100644 --- a/list.c +++ b/list.c @@ -46,24 +46,68 @@ static inline void uci_list_del(struct uci_list *ptr) next->prev = prev; } -static struct uci_config *uci_alloc_file(struct uci_context *ctx, const char *name) +static void uci_drop_section(struct uci_section *section) { - struct uci_config *cfg; + if (!section) + return; + if (section->name) + free(section->name); + if (section->type) + free(section->type); + free(section); +} - cfg = (struct uci_config *) uci_malloc(ctx, sizeof(struct uci_config)); - uci_list_init(&cfg->list); - uci_list_init(&cfg->sections); - cfg->name = uci_strdup(ctx, name); - cfg->ctx = ctx; +static struct uci_section *uci_add_section(struct uci_config *cfg, const char *type, const char *name) +{ + struct uci_section *section = NULL; + struct uci_context *ctx = cfg->ctx; - return cfg; + UCI_TRAP_SAVE(ctx, error) + section = (struct uci_section *) uci_malloc(ctx, sizeof(struct uci_section)); + section->config = cfg; + uci_list_init(§ion->list); + uci_list_init(§ion->options); + uci_list_add(&cfg->sections, §ion->list); + section->type = uci_strdup(ctx, type); + if (name) + section->name = uci_strdup(ctx, name); + UCI_TRAP_RESTORE(ctx); + + return section; + +error: + uci_drop_section(section); + UCI_THROW(ctx, ctx->errno); + return NULL; } static void uci_drop_file(struct uci_config *cfg) { /* TODO: free children */ - uci_list_del(&cfg->list); + if(!cfg) + return; if (cfg->name) free(cfg->name); free(cfg); } + + +static struct uci_config *uci_alloc_file(struct uci_context *ctx, const char *name) +{ + struct uci_config *cfg = NULL; + + UCI_TRAP_SAVE(ctx, error) + cfg = (struct uci_config *) uci_malloc(ctx, sizeof(struct uci_config)); + uci_list_init(&cfg->list); + uci_list_init(&cfg->sections); + cfg->name = uci_strdup(ctx, name); + cfg->ctx = ctx; + UCI_TRAP_RESTORE(ctx); + return cfg; + +error: + uci_drop_file(cfg); + UCI_THROW(ctx, ctx->errno); + return NULL; +} + diff --git a/parse.c b/parse.c index f5e6c29..a0a3ec8 100644 --- a/parse.c +++ b/parse.c @@ -72,8 +72,10 @@ static void uci_parse_cleanup(struct uci_context *ctx) if (!pctx) return; - if (pctx->cfg) + if (pctx->cfg) { + uci_list_del(&pctx->cfg->list); uci_drop_file(pctx->cfg); + } if (pctx->buf) free(pctx->buf); if (pctx->file) diff --git a/test.c b/test.c index 44e2dc8..53b2a6a 100644 --- a/test.c +++ b/test.c @@ -20,11 +20,11 @@ int main(int argc, char **argv) fprintf(stderr, "Failed to allocate uci context"); return 1; } - + if (uci_parse(ctx, argv[1])) { uci_perror(ctx, "uci_parse"); return 1; } - + return 0; }