1 /* 2 * libuci - Library for the Unified Configuration Interface 3 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 */ 14 15 #ifndef __UCI_INTERNAL_H 16 #define __UCI_INTERNAL_H 17 18 #define __private __attribute__((visibility("hidden"))) 19 #define __public 20 21 struct uci_parse_context 22 { 23 /* error context */ 24 const char *reason; 25 int line; 26 size_t byte; 27 28 /* private: */ 29 struct uci_package *package; 30 struct uci_section *section; 31 bool merge; 32 FILE *file; 33 const char *name; 34 char *buf; 35 size_t bufsz; 36 size_t buf_filled; 37 size_t pos; 38 }; 39 #define pctx_pos(pctx) ((pctx)->pos) 40 #define pctx_str(pctx, i) (&(pctx)->buf[(i)]) 41 #define pctx_cur_str(pctx) pctx_str(pctx, pctx_pos(pctx)) 42 #define pctx_char(pctx, i) ((pctx)->buf[(i)]) 43 #define pctx_cur_char(pctx) pctx_char(pctx, pctx_pos(pctx)) 44 45 #define uci_alloc_element(ctx, type, name, datasize) \ 46 uci_to_ ## type (uci_alloc_generic(ctx, uci_type_ ## type, name, sizeof(struct uci_ ## type) + datasize)) 47 48 extern const char *uci_confdir; 49 extern const char *uci_savedir; 50 51 __private void *uci_malloc(struct uci_context *ctx, size_t size); 52 __private void *uci_realloc(struct uci_context *ctx, void *ptr, size_t size); 53 __private char *uci_strdup(struct uci_context *ctx, const char *str); 54 __private bool uci_validate_str(const char *str, bool name, bool package); 55 __private void uci_add_delta(struct uci_context *ctx, struct uci_list *list, int cmd, const char *section, const char *option, const char *value); 56 __private void uci_free_delta(struct uci_delta *h); 57 __private struct uci_package *uci_alloc_package(struct uci_context *ctx, const char *name); 58 59 __private FILE *uci_open_stream(struct uci_context *ctx, const char *filename, const char *origfilename, int pos, bool write, bool create); 60 __private void uci_close_stream(FILE *stream); 61 __private void uci_getln(struct uci_context *ctx, size_t offset); 62 63 __private void uci_parse_error(struct uci_context *ctx, char *reason); 64 __private void uci_alloc_parse_context(struct uci_context *ctx); 65 66 __private void uci_cleanup(struct uci_context *ctx); 67 __private struct uci_element *uci_lookup_list(struct uci_list *list, const char *name); 68 __private void uci_free_package(struct uci_package **package); 69 __private struct uci_element *uci_alloc_generic(struct uci_context *ctx, int type, const char *name, int size); 70 __private void uci_free_element(struct uci_element *e); 71 __private struct uci_element *uci_expand_ptr(struct uci_context *ctx, struct uci_ptr *ptr, bool complete); 72 73 __private int uci_load_delta(struct uci_context *ctx, struct uci_package *p, bool flush); 74 75 static inline bool uci_validate_package(const char *str) 76 { 77 return uci_validate_str(str, false, true); 78 } 79 80 static inline bool uci_validate_type(const char *str) 81 { 82 return uci_validate_str(str, false, false); 83 } 84 85 static inline bool uci_validate_name(const char *str) 86 { 87 return uci_validate_str(str, true, false); 88 } 89 90 /* initialize a list head/item */ 91 static inline void uci_list_init(struct uci_list *ptr) 92 { 93 ptr->prev = ptr; 94 ptr->next = ptr; 95 } 96 97 /* inserts a new list entry after a given entry */ 98 static inline void uci_list_insert(struct uci_list *list, struct uci_list *ptr) 99 { 100 list->next->prev = ptr; 101 ptr->prev = list; 102 ptr->next = list->next; 103 list->next = ptr; 104 } 105 106 /* inserts a new list entry at the tail of the list */ 107 static inline void uci_list_add(struct uci_list *head, struct uci_list *ptr) 108 { 109 /* NB: head->prev points at the tail */ 110 uci_list_insert(head->prev, ptr); 111 } 112 113 static inline void uci_list_del(struct uci_list *ptr) 114 { 115 struct uci_list *next, *prev; 116 117 next = ptr->next; 118 prev = ptr->prev; 119 120 prev->next = next; 121 next->prev = prev; 122 123 uci_list_init(ptr); 124 } 125 126 127 extern struct uci_backend uci_file_backend; 128 129 #ifdef UCI_PLUGIN_SUPPORT 130 /** 131 * uci_add_backend: add an extra backend 132 * @ctx: uci context 133 * @name: name of the backend 134 * 135 * The default backend is "file", which uses /etc/config for config storage 136 */ 137 __private int uci_add_backend(struct uci_context *ctx, struct uci_backend *b); 138 139 /** 140 * uci_add_backend: add an extra backend 141 * @ctx: uci context 142 * @name: name of the backend 143 * 144 * The default backend is "file", which uses /etc/config for config storage 145 */ 146 __private int uci_del_backend(struct uci_context *ctx, struct uci_backend *b); 147 #endif 148 149 #define UCI_BACKEND(_var, _name, ...) \ 150 struct uci_backend _var = { \ 151 .e.list = { \ 152 .next = &_var.e.list, \ 153 .prev = &_var.e.list, \ 154 }, \ 155 .e.name = _name, \ 156 .e.type = UCI_TYPE_BACKEND, \ 157 .ptr = &_var, \ 158 __VA_ARGS__ \ 159 } 160 161 162 /* 163 * functions for debug and error handling, for internal use only 164 */ 165 166 #ifdef UCI_DEBUG 167 #define DPRINTF(...) fprintf(stderr, __VA_ARGS__) 168 #else 169 #define DPRINTF(...) 170 #endif 171 172 /* 173 * throw an uci exception and store the error number 174 * in the context. 175 */ 176 #define UCI_THROW(ctx, err) do { \ 177 DPRINTF("Exception: %s in %s, %s:%d\n", #err, __func__, __FILE__, __LINE__); \ 178 longjmp(ctx->trap, err); \ 179 } while (0) 180 181 /* 182 * store the return address for handling exceptions 183 * needs to be called in every externally visible library function 184 * 185 * NB: this does not handle recursion at all. Calling externally visible 186 * functions from other uci functions is only allowed at the end of the 187 * calling function, or by wrapping the function call in UCI_TRAP_SAVE 188 * and UCI_TRAP_RESTORE. 189 */ 190 #define UCI_HANDLE_ERR(ctx) do { \ 191 DPRINTF("ENTER: %s\n", __func__); \ 192 int __val = 0; \ 193 if (!ctx) \ 194 return UCI_ERR_INVAL; \ 195 ctx->err = 0; \ 196 if (!ctx->internal && !ctx->nested) \ 197 __val = setjmp(ctx->trap); \ 198 ctx->internal = false; \ 199 ctx->nested = false; \ 200 if (__val) { \ 201 DPRINTF("LEAVE: %s, ret=%d\n", __func__, __val); \ 202 ctx->err = __val; \ 203 return __val; \ 204 } \ 205 } while (0) 206 207 /* 208 * In a block enclosed by UCI_TRAP_SAVE and UCI_TRAP_RESTORE, all exceptions 209 * are intercepted and redirected to the label specified in 'handler' 210 * after UCI_TRAP_RESTORE, or when reaching the 'handler' label, the old 211 * exception handler is restored 212 */ 213 #define UCI_TRAP_SAVE(ctx, handler) do { \ 214 jmp_buf __old_trap; \ 215 int __val; \ 216 memcpy(__old_trap, ctx->trap, sizeof(ctx->trap)); \ 217 __val = setjmp(ctx->trap); \ 218 if (__val) { \ 219 ctx->err = __val; \ 220 memcpy(ctx->trap, __old_trap, sizeof(ctx->trap)); \ 221 goto handler; \ 222 } while(0) 223 #define UCI_TRAP_RESTORE(ctx) \ 224 memcpy(ctx->trap, __old_trap, sizeof(ctx->trap)); \ 225 } while(0) 226 227 /** 228 * UCI_INTERNAL: Do an internal call of a public API function 229 * 230 * Sets Exception handling to passthrough mode. 231 * Allows API functions to change behavior compared to public use 232 */ 233 #define UCI_INTERNAL(func, ctx, ...) do { \ 234 ctx->internal = true; \ 235 func(ctx, __VA_ARGS__); \ 236 } while (0) 237 238 /** 239 * UCI_NESTED: Do an normal nested call of a public API function 240 * 241 * Sets Exception handling to passthrough mode. 242 * Allows API functions to change behavior compared to public use 243 */ 244 #define UCI_NESTED(func, ctx, ...) do { \ 245 ctx->nested = true; \ 246 func(ctx, __VA_ARGS__); \ 247 } while (0) 248 249 250 /* 251 * check the specified condition. 252 * throw an invalid argument exception if it's false 253 */ 254 #define UCI_ASSERT(ctx, expr) do { \ 255 if (!(expr)) { \ 256 DPRINTF("[%s:%d] Assertion failed\n", __FILE__, __LINE__); \ 257 UCI_THROW(ctx, UCI_ERR_INVAL); \ 258 } \ 259 } while (0) 260 261 #endif 262
This page was automatically generated by LXR 0.3.1. • OpenWrt