Browse Source

more error handling

Felix Fietkau 16 years ago
parent
commit
7952092949
5 changed files with 81 additions and 13 deletions
  1. 21 1
      err.h
  2. 2 0
      libuci.h
  3. 53 9
      list.c
  4. 3 1
      parse.c
  5. 2 2
      test.c

+ 21 - 1
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

+ 2 - 0
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

+ 53 - 9
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(&section->list);
+	uci_list_init(&section->options);
+	uci_list_add(&cfg->sections, &section->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;
+}
+

+ 3 - 1
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)

+ 2 - 2
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;
 }