X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fconf-intr.c;h=b90640f18563cce146db02dd6ed4182739cf3611;hb=5e52d50a1ae65de7545213b433e06e993e2d24bf;hp=7b1564e2f185fbfa0c47739fddbe96b94dc9c576;hpb=894ab13170a1f14ec1920976c531fe02ffb5a2ab;p=libucw.git diff --git a/lib/conf-intr.c b/lib/conf-intr.c index 7b1564e2..b90640f1 100644 --- a/lib/conf-intr.c +++ b/lib/conf-intr.c @@ -100,6 +100,9 @@ cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type, union cf_uni #define T(x) #x, byte *cf_op_names[] = { CF_OPERATIONS }; #undef T +byte *cf_type_names[] = { "int", "u64", "double", "ip", "string", "lookup", "user" }; + +#define DARY_HDR_SIZE ALIGN_TO(sizeof(uns), CPU_STRUCT_ALIGN) static byte * interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr) @@ -108,8 +111,7 @@ interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr) cf_journal_block(ptr, sizeof(void*)); // boundary checks done by the caller uns size = cf_type_size(item->type, item->u.utype); - ASSERT(size >= sizeof(uns)); - *ptr = cf_malloc(sizeof(uns) + number * size) + sizeof(uns); + *ptr = cf_malloc(DARY_HDR_SIZE + number * size) + DARY_HDR_SIZE; DARY_LEN(*ptr) = number; return cf_parse_ary(number, pars, *ptr, type, &item->u); } @@ -125,7 +127,7 @@ interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *proces int taken = MIN(number, ABS(item->number)-old_nr); *processed = taken; // stretch the dynamic array - void *new_p = cf_malloc(sizeof(uns) + (old_nr + taken) * size) + sizeof(uns); + void *new_p = cf_malloc(DARY_HDR_SIZE + (old_nr + taken) * size) + DARY_HDR_SIZE; DARY_LEN(new_p) = old_nr + taken; cf_journal_block(ptr, sizeof(void*)); *ptr = new_p; @@ -223,6 +225,31 @@ interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed return NULL; } +static byte * +interpret_add_bitmap(struct cf_item *item, int number, byte **pars, int *processed, u32 *ptr, enum cf_operation op) +{ + 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 + TRY( cf_parse_lookup(pars[i], &idx, item->u.lookup) ); + if (idx >= 32) + return "Bitmaps only have 32 bits"; + if (op == OP_SET) + *ptr |= 1<cls == CC_BITMAP) { + cf_journal_block(ptr, sizeof(u32)); + if (op == OP_CLEAR) + * (u32*) ptr = 0; + else + if (item->type == CT_INT) + * (u32*) ptr = ~0u; + else { + uns nr = -1; + while (item->u.lookup[++nr]); + * (u32*) ptr = ~0u >> (32-nr); + } + return NULL; + } else if (op != OP_CLEAR) + return "The item is not a bitmap"; + if (item->cls == CC_LIST) { cf_journal_block(ptr, sizeof(clist)); clist_init(ptr); @@ -278,7 +325,7 @@ interpret_clear(struct cf_item *item, void *ptr) cf_journal_block(ptr, item->number * sizeof(byte*)); bzero(ptr, item->number * sizeof(byte*)); } else - return "The item is not a list, dynamic array, or string"; + return "The item is not a list, dynamic array, bitmap, or string"; return NULL; } @@ -345,10 +392,11 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) { if (level >= MAX_STACK_SIZE-1) return "Too many nested sections"; + enum cf_operation pure_op = op & OP_MASK; stack[++level] = (struct item_stack) { .sec = NULL, .base_ptr = NULL, - .op = op & OP_MASK, + .op = pure_op, .list = NULL, .mask = 0, .item = NULL, @@ -358,6 +406,8 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) 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 } @@ -367,8 +417,10 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) cf_init_section(item->name, item->u.sec, stack[level].base_ptr, 1); stack[level].list = ptr; stack[level].item = item; - if ((op & OP_MASK) < OP_REMOVE) { - add_to_list(ptr, stack[level].base_ptr, op & OP_MASK); + 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; } else stack[level].op |= OP_1ST; @@ -486,15 +538,17 @@ cf_interpret_line(byte *name, enum cf_operation op, int number, byte **pars) return NULL; op &= OP_MASK; - int taken; // process as many parameters as possible - if (op == OP_CLEAR) - taken = 0, msg = interpret_clear(item, ptr); + 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); if (msg) @@ -509,7 +563,7 @@ byte * cf_find_item(byte *name, struct cf_item *item) { byte *msg; - void *ptr; + void *ptr = NULL; struct cf_item *ci = find_item(&cf_sections, name, &msg, &ptr); if (msg) return msg; @@ -525,14 +579,14 @@ byte * cf_write_item(struct cf_item *item, enum cf_operation op, int number, byte **pars) { byte *msg; - int taken; + int taken = 0; switch (op) { case OP_SET: msg = interpret_set_item(item, number, pars, &taken, item->ptr, 1); break; case OP_CLEAR: - taken = 0; - msg = interpret_clear(item, item->ptr); + case OP_ALL: + msg = interpret_set_all(item, item->ptr, op); break; case OP_APPEND: case OP_PREPEND: @@ -541,7 +595,13 @@ cf_write_item(struct cf_item *item, enum cf_operation op, int number, byte **par else if (item->cls == CC_LIST) msg = interpret_add_list(item, number, pars, &taken, item->ptr, op); else - return "The attribute class does not support append/prepend"; + return "The attribute does not support append/prepend"; + break; + case OP_REMOVE: + if (item->cls == CC_BITMAP) + msg = interpret_add_bitmap(item, number, pars, &taken, item->ptr, op); + else + return "Only applicable on bitmaps"; break; default: return "Unsupported operation";