* 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;   \
        }                               \
 } 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
 
        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;
+}
+