X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=ucw%2Fconf-intr.c;h=cf98b35bca112028037492e765e0825b373ff659;hb=0eb6d8317cdbdb28663ff779d31684b3c7a47274;hp=f7b678e155dd8d4058a922e4204e0b230a0c3abb;hpb=031256ad2e123eec58521f8e3eb9496c197641d2;p=libucw.git diff --git a/ucw/conf-intr.c b/ucw/conf-intr.c index f7b678e1..cf98b35b 100644 --- a/ucw/conf-intr.c +++ b/ucw/conf-intr.c @@ -2,17 +2,19 @@ * UCW Library -- Configuration files: interpreter * * (c) 2001--2006 Robert Spalek - * (c) 2003--2006 Martin Mares + * (c) 2003--2014 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. */ -#include "ucw/lib.h" -#include "ucw/conf.h" -#include "ucw/getopt.h" -#include "ucw/conf-internal.h" -#include "ucw/clists.h" +#include +#include +#include +#include +#include +#include +#include #include #include @@ -30,7 +32,7 @@ cf_parse_string(char *str, char **ptr) typedef char *cf_basic_parser(char *str, void *ptr); static struct { - uns size; + uint size; void *parser; } parsers[] = { { sizeof(int), cf_parse_int }, @@ -42,7 +44,7 @@ static struct { { 0, NULL }, // user-defined types are parsed extra }; -inline uns +inline uint cf_type_size(enum cf_type type, struct cf_user_type *utype) { if (type < CT_USER) @@ -55,7 +57,7 @@ static char * cf_parse_lookup(char *str, int *ptr, const char * const *t) { const char * const *n = t; - uns total_len = 0; + uint total_len = 0; while (*n && strcasecmp(*n, str)) { total_len += strlen(*n) + 2; n++; @@ -75,12 +77,12 @@ cf_parse_lookup(char *str, int *ptr, const char * const *t) } static char * -cf_parse_ary(uns number, char **pars, void *ptr, enum cf_type type, union cf_union *u) +cf_parse_ary(uint number, char **pars, void *ptr, enum cf_type type, union cf_union *u) { - for (uns i=0; iutype); + uint size = cf_type_size(type, u->utype); if (type < CT_LOOKUP) msg = ((cf_basic_parser*) parsers[type].parser) (pars[i], ptr + i * size); else if (type == CT_LOOKUP) @@ -102,17 +104,14 @@ char *cf_op_names[] = { CF_OPERATIONS }; #undef T char *cf_type_names[] = { "int", "u64", "double", "ip", "string", "lookup", "user" }; -#define DARY_HDR_SIZE ALIGN_TO(sizeof(uns), CPU_STRUCT_ALIGN) - static char * interpret_set_dynamic(struct cf_item *item, int number, char **pars, void **ptr) { enum cf_type type = item->type; + uint size = cf_type_size(type, item->u.utype); cf_journal_block(ptr, sizeof(void*)); // boundary checks done by the caller - uns size = cf_type_size(item->type, item->u.utype); - *ptr = cf_malloc(DARY_HDR_SIZE + number * size) + DARY_HDR_SIZE; - DARY_LEN(*ptr) = number; + *ptr = gary_init(size, number, mp_get_allocator(cf_get_pool())); return cf_parse_ary(number, pars, *ptr, type, &item->u); } @@ -121,14 +120,13 @@ interpret_add_dynamic(struct cf_item *item, int number, char **pars, int *proces { enum cf_type type = item->type; void *old_p = *ptr; - uns size = cf_type_size(item->type, item->u.utype); - ASSERT(size >= sizeof(uns)); - int old_nr = old_p ? DARY_LEN(old_p) : 0; + uint size = cf_type_size(item->type, item->u.utype); + ASSERT(size >= sizeof(uint)); + int old_nr = old_p ? GARY_SIZE(old_p) : 0; int taken = MIN(number, ABS(item->number)-old_nr); *processed = taken; // stretch the dynamic array - void *new_p = cf_malloc(DARY_HDR_SIZE + (old_nr + taken) * size) + DARY_HDR_SIZE; - DARY_LEN(new_p) = old_nr + taken; + void *new_p = gary_init(size, old_nr + taken, mp_get_allocator(cf_get_pool())); cf_journal_block(ptr, sizeof(void*)); *ptr = new_p; if (op == OP_APPEND) { @@ -141,10 +139,10 @@ interpret_add_dynamic(struct cf_item *item, int number, char **pars, int *proces return cf_printf("Dynamic arrays do not support operation %s", cf_op_names[op]); } -static char *interpret_set_item(struct cf_item *item, int number, char **pars, int *processed, void *ptr, uns allow_dynamic); +static char *interpret_set_item(struct cf_item *item, int number, char **pars, int *processed, void *ptr, uint allow_dynamic); static char * -interpret_section(struct cf_section *sec, int number, char **pars, int *processed, void *ptr, uns allow_dynamic) +interpret_section(struct cf_section *sec, int number, char **pars, int *processed, void *ptr, uint allow_dynamic) { cf_add_dirty(sec, ptr); *processed = 0; @@ -203,7 +201,7 @@ interpret_add_list(struct cf_item *item, int number, char **pars, int *processed return "Nothing to add to the list"; struct cf_section *sec = item->u.sec; *processed = 0; - uns index = 0; + uint index = 0; while (number > 0) { void *node = cf_malloc(sec->size); @@ -228,13 +226,15 @@ interpret_add_list(struct cf_item *item, int number, char **pars, int *processed static char * interpret_add_bitmap(struct cf_item *item, int number, char **pars, int *processed, u32 *ptr, enum cf_operation op) { + if (op == OP_PREPEND || op == OP_APPEND) + op = OP_SET; if (op != OP_SET && op != OP_REMOVE) return cf_printf("Cannot apply operation %s on a bitmap", cf_op_names[op]); else if (item->type != CT_INT && item->type != CT_LOOKUP) return cf_printf("Type %s cannot be used with bitmaps", cf_type_names[item->type]); cf_journal_block(ptr, sizeof(u32)); for (int i=0; itype == CT_INT) TRY( cf_parse_int(pars[i], &idx) ); else @@ -251,7 +251,7 @@ interpret_add_bitmap(struct cf_item *item, int number, char **pars, int *process } static char * -interpret_set_item(struct cf_item *item, int number, char **pars, int *processed, void *ptr, uns allow_dynamic) +interpret_set_item(struct cf_item *item, int number, char **pars, int *processed, void *ptr, uint allow_dynamic) { int taken; switch (item->cls) @@ -261,7 +261,7 @@ interpret_set_item(struct cf_item *item, int number, char **pars, int *processed return "Missing value"; taken = MIN(number, item->number); *processed = taken; - uns size = cf_type_size(item->type, item->u.utype); + uint size = cf_type_size(item->type, item->u.utype); cf_journal_block(ptr, taken * size); return cf_parse_ary(taken, pars, ptr, item->type, &item->u); case CC_DYNAMIC: @@ -306,7 +306,7 @@ interpret_set_all(struct cf_item *item, void *ptr, enum cf_operation op) if (item->type == CT_INT) * (u32*) ptr = ~0u; else { - uns nr = -1; + uint nr = -1; while (item->u.lookup[++nr]); * (u32*) ptr = ~0u >> (32-nr); } @@ -319,8 +319,7 @@ interpret_set_all(struct cf_item *item, void *ptr, enum cf_operation op) clist_init(ptr); } else if (item->cls == CC_DYNAMIC) { cf_journal_block(ptr, sizeof(void *)); - static uns zero = 0; - * (void**) ptr = (&zero) + 1; + * (void**) ptr = GARY_FOREVER_EMPTY; } else if (item->cls == CC_STATIC && item->type == CT_STRING) { cf_journal_block(ptr, item->number * sizeof(char*)); bzero(ptr, item->number * sizeof(char*)); @@ -346,8 +345,8 @@ find_list_node(clist *list, void *query, struct cf_section *sec, u32 mask) { CLIST_FOR_EACH(cnode *, n, *list) { - uns found = 1; - for (uns i=0; i<32; i++) + uint found = 1; + for (uint i=0; i<32; i++) if (mask & (1<cfg+i)) { @@ -363,10 +362,10 @@ find_list_node(clist *list, void *query, struct cf_section *sec, u32 mask) static char * record_selector(struct cf_item *item, struct cf_section *sec, u32 *mask) { - uns nr = sec->flags & SEC_FLAG_NUMBER; + uint nr = sec->flags & SEC_FLAG_NUMBER; if (item >= sec->cfg && item < sec->cfg + nr) // setting an attribute relative to this section { - uns i = item - sec->cfg; + uint i = item - sec->cfg; if (i >= 32) return "Cannot select list nodes by this attribute"; if (sec->cfg[i].cls != CC_STATIC) @@ -376,24 +375,13 @@ record_selector(struct cf_item *item, struct cf_section *sec, u32 *mask) return NULL; } -#define MAX_STACK_SIZE 10 -static struct item_stack { - struct cf_section *sec; // nested section - void *base_ptr; // because original pointers are often relative - enum cf_operation op; // it is performed when a closing brace is encountered - void *list; // list the operations should be done on - u32 mask; // bit array of selectors searching in a list - struct cf_item *item; // cf_item of the list -} stack[MAX_STACK_SIZE]; -static uns level; - static char * -opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) +opening_brace(struct cf_context *cc, struct cf_item *item, void *ptr, enum cf_operation op) { - if (level >= MAX_STACK_SIZE-1) + if (cc->stack_level >= MAX_STACK_SIZE-1) return "Too many nested sections"; enum cf_operation pure_op = op & OP_MASK; - stack[++level] = (struct item_stack) { + cc->stack[++cc->stack_level] = (struct item_stack) { .sec = NULL, .base_ptr = NULL, .op = pure_op, @@ -403,27 +391,27 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) }; if (!item) // unknown is ignored; we just need to trace recursion return NULL; - stack[level].sec = item->u.sec; + cc->stack[cc->stack_level].sec = item->u.sec; if (item->cls == CC_SECTION) { if (pure_op != OP_SET) return "Only SET operation can be used with a section"; - stack[level].base_ptr = ptr; - stack[level].op = OP_EDIT | OP_2ND; // this list operation does nothing + cc->stack[cc->stack_level].base_ptr = ptr; + cc->stack[cc->stack_level].op = OP_EDIT | OP_2ND; // this list operation does nothing } else if (item->cls == CC_LIST) { - stack[level].base_ptr = cf_malloc(item->u.sec->size); - cf_init_section(item->name, item->u.sec, stack[level].base_ptr, 1); - stack[level].list = ptr; - stack[level].item = item; + cc->stack[cc->stack_level].base_ptr = cf_malloc(item->u.sec->size); + cf_init_section(item->name, item->u.sec, cc->stack[cc->stack_level].base_ptr, 1); + cc->stack[cc->stack_level].list = ptr; + cc->stack[cc->stack_level].item = item; if (pure_op == OP_ALL) return "Operation ALL cannot be applied on lists"; else if (pure_op < OP_REMOVE) { - add_to_list(ptr, stack[level].base_ptr, pure_op); - stack[level].op |= OP_2ND; + add_to_list(ptr, cc->stack[cc->stack_level].base_ptr, pure_op); + cc->stack[cc->stack_level].op |= OP_2ND; } else - stack[level].op |= OP_1ST; + cc->stack[cc->stack_level].op |= OP_1ST; } else return "Opening brace can only be used on sections and lists"; @@ -431,13 +419,13 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) } static char * -closing_brace(struct item_stack *st, enum cf_operation op, int number, char **pars) +closing_brace(struct cf_context *cc, struct item_stack *st, enum cf_operation op, int number, char **pars) { if (st->op == OP_CLOSE) // top-level return "Unmatched } parenthesis"; if (!st->sec) { // dummy run on unknown section if (!(op & OP_OPEN)) - level--; + cc->stack_level--; return NULL; } enum cf_operation pure_op = st->op & OP_MASK; @@ -473,7 +461,7 @@ closing_brace(struct item_stack *st, enum cf_operation op, int number, char **pa } add_to_list(st->list, st->base_ptr, pure_op); } - level--; + cc->stack_level--; if (number) return "No parameters expected after the }"; else if (op & OP_OPEN) @@ -485,14 +473,15 @@ closing_brace(struct item_stack *st, enum cf_operation op, int number, char **pa static struct cf_item * find_item(struct cf_section *curr_sec, const char *name, char **msg, void **ptr) { + struct cf_context *cc = cf_get_context(); *msg = NULL; if (name[0] == '^') // absolute name instead of relative - name++, curr_sec = &cf_sections, *ptr = NULL; + name++, curr_sec = &cc->sections, *ptr = NULL; if (!curr_sec) // don't even search in an unknown section return NULL; while (1) { - if (curr_sec != &cf_sections) + if (curr_sec != &cc->sections) cf_add_dirty(curr_sec, *ptr); char *c = strchr(name, '.'); if (c) @@ -517,40 +506,59 @@ find_item(struct cf_section *curr_sec, const char *name, char **msg, void **ptr) } } +static char * +interpret_add(char *name, struct cf_item *item, int number, char **pars, int *takenp, void *ptr, enum cf_operation op) +{ + switch (item->cls) { + case CC_DYNAMIC: + return interpret_add_dynamic(item, number, pars, takenp, ptr, op); + case CC_LIST: + return interpret_add_list(item, number, pars, takenp, ptr, op); + case CC_BITMAP: + return interpret_add_bitmap(item, number, pars, takenp, ptr, op); + default: + return cf_printf("Operation %s not supported on attribute %s", cf_op_names[op], name); + } +} + char * -cf_interpret_line(char *name, enum cf_operation op, int number, char **pars) +cf_interpret_line(struct cf_context *cc, char *name, enum cf_operation op, int number, char **pars) { char *msg; if ((op & OP_MASK) == OP_CLOSE) - return closing_brace(stack+level, op, number, pars); - void *ptr = stack[level].base_ptr; - struct cf_item *item = find_item(stack[level].sec, name, &msg, &ptr); + return closing_brace(cc, cc->stack+cc->stack_level, op, number, pars); + void *ptr = cc->stack[cc->stack_level].base_ptr; + struct cf_item *item = find_item(cc->stack[cc->stack_level].sec, name, &msg, &ptr); if (msg) return msg; - if (stack[level].op & OP_1ST) - TRY( record_selector(item, stack[level].sec, &stack[level].mask) ); + if (cc->stack[cc->stack_level].op & OP_1ST) + TRY( record_selector(item, cc->stack[cc->stack_level].sec, &cc->stack[cc->stack_level].mask) ); if (op & OP_OPEN) { // the operation will be performed after the closing brace if (number) return "Cannot open a block after a parameter has been passed on a line"; - return opening_brace(item, ptr, op); + return opening_brace(cc, item, ptr, op); } if (!item) // ignored item in an unknown section return NULL; op &= OP_MASK; int taken = 0; // process as many parameters as possible - if (op == OP_CLEAR || op == OP_ALL) - msg = interpret_set_all(item, ptr, op); - else if (op == OP_SET) - msg = interpret_set_item(item, number, pars, &taken, ptr, 1); - else if (item->cls == CC_DYNAMIC) - msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op); - else if (item->cls == CC_LIST) - msg = interpret_add_list(item, number, pars, &taken, ptr, op); - else if (item->cls == CC_BITMAP) - msg = interpret_add_bitmap(item, number, pars, &taken, ptr, op); - else - return cf_printf("Operation %s not supported on attribute %s", cf_op_names[op], name); + switch (op) { + case OP_CLEAR: + case OP_ALL: + msg = interpret_set_all(item, ptr, op); + break; + case OP_SET: + msg = interpret_set_item(item, number, pars, &taken, ptr, 1); + break; + case OP_RESET: + msg = interpret_set_all(item, ptr, OP_CLEAR); + if (!msg) + msg = interpret_add(name, item, number, pars, &taken, ptr, OP_APPEND); + break; + default: + msg = interpret_add(name, item, number, pars, &taken, ptr, op); + } if (msg) return msg; if (taken < number) @@ -562,9 +570,10 @@ cf_interpret_line(char *name, enum cf_operation op, int number, char **pars) char * cf_find_item(const char *name, struct cf_item *item) { + struct cf_context *cc = cf_get_context(); char *msg; void *ptr = NULL; - struct cf_item *ci = find_item(&cf_sections, name, &msg, &ptr); + struct cf_item *ci = find_item(&cc->sections, name, &msg, &ptr); if (msg) return msg; if (ci) { @@ -576,7 +585,7 @@ cf_find_item(const char *name, struct cf_item *item) } char * -cf_write_item(struct cf_item *item, enum cf_operation op, int number, char **pars) +cf_modify_item(struct cf_item *item, enum cf_operation op, int number, char **pars) { char *msg; int taken = 0; @@ -590,12 +599,19 @@ cf_write_item(struct cf_item *item, enum cf_operation op, int number, char **par break; case OP_APPEND: case OP_PREPEND: - if (item->cls == CC_DYNAMIC) - msg = interpret_add_dynamic(item, number, pars, &taken, item->ptr, op); - else if (item->cls == CC_LIST) - msg = interpret_add_list(item, number, pars, &taken, item->ptr, op); - else - return "The attribute does not support append/prepend"; + switch (item->cls) { + case CC_DYNAMIC: + msg = interpret_add_dynamic(item, number, pars, &taken, item->ptr, op); + break; + case CC_LIST: + msg = interpret_add_list(item, number, pars, &taken, item->ptr, op); + break; + case CC_BITMAP: + msg = interpret_add_bitmap(item, number, pars, &taken, item->ptr, op); + break; + default: + return "The attribute does not support append/prepend"; + } break; case OP_REMOVE: if (item->cls == CC_BITMAP) @@ -614,17 +630,16 @@ cf_write_item(struct cf_item *item, enum cf_operation op, int number, char **par } void -cf_init_stack(void) +cf_init_stack(struct cf_context *cc) { - static uns initialized = 0; - if (!initialized++) { - cf_sections.flags |= SEC_FLAG_UNKNOWN; - cf_sections.size = 0; // size of allocated array used to be stored here - cf_init_section(NULL, &cf_sections, NULL, 0); + if (!cc->sections_initialized++) { + cc->sections.flags |= SEC_FLAG_UNKNOWN; + cc->sections.size = 0; // size of allocated array used to be stored here + cf_init_section(NULL, &cc->sections, NULL, 0); } - level = 0; - stack[0] = (struct item_stack) { - .sec = &cf_sections, + cc->stack_level = 0; + cc->stack[0] = (struct item_stack) { + .sec = &cc->sections, .base_ptr = NULL, .op = OP_CLOSE, .list = NULL, @@ -634,12 +649,7 @@ cf_init_stack(void) } int -cf_check_stack(void) +cf_done_stack(struct cf_context *cc) { - if (level > 0) { - msg(L_ERROR, "Unterminated block"); - return 1; - } - return 0; + return (cc->stack_level > 0); } -