From: Robert Spalek Date: Fri, 5 May 2006 13:18:23 +0000 (+0200) Subject: configuration mechanism: added support for bitmaps X-Git-Tag: holmes-import~641^2~26 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=c5a0ac3d7d43bcffac66a43f364d53892e583f83;p=libucw.git configuration mechanism: added support for bitmaps --- diff --git a/lib/conf-dump.c b/lib/conf-dump.c index ee137ab1..073bf129 100644 --- a/lib/conf-dump.c +++ b/lib/conf-dump.c @@ -48,8 +48,7 @@ dump_basic(struct fastbuf *fb, void *ptr, enum cf_type type, union cf_union *u) static void dump_section(struct fastbuf *fb, struct cf_section *sec, int level, void *ptr); -static byte *class_names[] = { "end", "static", "dynamic", "parser", "section", "list" }; -static byte *type_names[] = { "int", "u64", "double", "ip", "string", "lookup", "user" }; +static byte *class_names[] = { "end", "static", "dynamic", "parser", "section", "list", "bitmap" }; static void dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr) @@ -64,8 +63,8 @@ dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr) bputs(fb, "any "); else bprintf(fb, "%d ", item->number); - if (item->cls == CC_STATIC || item->cls == CC_DYNAMIC) { - bprintf(fb, "T%s ", type_names[type]); + if (item->cls == CC_STATIC || item->cls == CC_DYNAMIC || item->cls == CC_BITMAP) { + bprintf(fb, "T%s ", cf_type_names[type]); if (item->type == CT_USER) bprintf(fb, "U%s S%d ", item->u.utype->name, size); } @@ -81,6 +80,18 @@ dump_item(struct fastbuf *fb, struct cf_item *item, int level, void *ptr) dump_basic(fb, ptr + i * size, type, &item->u); } else bprintf(fb, "NULL "); + } else if (item->cls == CC_BITMAP) { + u32 mask = * (u32*) ptr; + for (i=0; i<32; i++) { + if (item->type == CT_LOOKUP && !item->u.lookup[i]) + break; + if (mask & (1<type == CT_INT) + bprintf(fb, "%d ", i); + else if (item->type == CT_LOOKUP) + bprintf(fb, "%s ", item->u.lookup[i]); + } + } } bputc(fb, '\n'); if (item->cls == CC_SECTION) diff --git a/lib/conf-input.c b/lib/conf-input.c index e44cba1b..036181dc 100644 --- a/lib/conf-input.c +++ b/lib/conf-input.c @@ -246,8 +246,13 @@ parse_fastbuf(byte *name_fb, struct fastbuf *fb, uns depth) *c++ = 0; switch (Clocase(*c)) { case 's': op = OP_SET; break; + case 'u': op = OP_UNSET; break; case 'c': op = Clocase(c[1]) == 'l' ? OP_CLEAR: OP_COPY; break; - case 'a': op = Clocase(c[1]) == 'p' ? OP_APPEND : OP_AFTER; break; + case 'a': switch (Clocase(c[1])) { + case 'p': op = OP_APPEND; break; + case 'f': op = OP_AFTER; break; + default: op = OP_ALL; + }; break; case 'p': op = OP_PREPEND; break; case 'r': op = OP_REMOVE; break; case 'e': op = OP_EDIT; break; diff --git a/lib/conf-internal.h b/lib/conf-internal.h index 3760d0e5..aeb44721 100644 --- a/lib/conf-internal.h +++ b/lib/conf-internal.h @@ -18,6 +18,7 @@ #define OP_2ND 0x400 // in the 2nd phase real data are entered enum cf_operation; extern byte *cf_op_names[]; +extern byte *cf_type_names[]; uns cf_type_size(enum cf_type type, struct cf_user_type *utype); byte *cf_interpret_line(byte *name, enum cf_operation op, int number, byte **pars); diff --git a/lib/conf-intr.c b/lib/conf-intr.c index acbe702f..5a5f7eaa 100644 --- a/lib/conf-intr.c +++ b/lib/conf-intr.c @@ -100,6 +100,7 @@ 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(sizeof(uns), CPU_STRUCT_ALIGN) @@ -224,6 +225,31 @@ interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed return NULL; } +static byte * +interpret_bitmap(struct cf_item *item, int number, byte **pars, int *processed, u32 *ptr, enum cf_operation op) +{ + if (item->cls != CC_BITMAP) + return cf_printf("Expecting a bitmap"); + 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_STATIC && item->type == CT_STRING) { cf_journal_block(ptr, item->number * sizeof(byte*)); bzero(ptr, item->number * sizeof(byte*)); + } else if (item->cls == CC_BITMAP) { + cf_journal_block(ptr, sizeof(u32)); + * (u32*) ptr = 0; } 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; } +static byte * +interpret_set_all(struct cf_item *item, void *ptr) +{ + if (item->cls == CC_BITMAP) { + cf_journal_block(ptr, sizeof(u32)); + 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 + return "The item is not a bitmap"; +} + static int cmp_items(void *i1, void *i2, struct cf_item *item) { @@ -346,10 +396,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, @@ -359,6 +410,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 } @@ -368,8 +421,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_UNSET || pure_op == OP_ALL) + return "Bitmap operations are not supported for 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; @@ -487,11 +542,15 @@ 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 + int taken = 0; // process as many parameters as possible if (op == OP_CLEAR) - taken = 0, msg = interpret_clear(item, ptr); + msg = interpret_clear(item, ptr); + else if (op == OP_ALL) + msg = interpret_set_all(item, ptr); else if (op == OP_SET) msg = interpret_set_item(item, number, pars, &taken, ptr, 1); + else if (op == OP_UNSET) + msg = interpret_bitmap(item, number, pars, &taken, ptr, OP_UNSET); else if (item->cls == CC_DYNAMIC) msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op); else if (item->cls == CC_LIST) @@ -526,15 +585,20 @@ 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); break; + case OP_UNSET: + msg = interpret_bitmap(item, number, pars, &taken, item->ptr, OP_UNSET); + break; + case OP_ALL: + msg = interpret_set_all(item, item->ptr); + break; case OP_APPEND: case OP_PREPEND: if (item->cls == CC_DYNAMIC) diff --git a/lib/conf-section.c b/lib/conf-section.c index 2e27546a..b06b9fd6 100644 --- a/lib/conf-section.c +++ b/lib/conf-section.c @@ -91,7 +91,7 @@ inspect_section(struct cf_section *sec) } else if (ci->cls == CC_LIST) { inspect_section(ci->u.sec); sec->flags |= SEC_FLAG_DYNAMIC | SEC_FLAG_CANT_COPY; - } else if (ci->cls == CC_DYNAMIC) + } else if (ci->cls == CC_DYNAMIC || ci->cls == CC_BITMAP) sec->flags |= SEC_FLAG_DYNAMIC; else if (ci->cls == CC_PARSER) { sec->flags |= SEC_FLAG_CANT_COPY; diff --git a/lib/conf-test.c b/lib/conf-test.c index cefaa212..f4ca15fd 100644 --- a/lib/conf-test.c +++ b/lib/conf-test.c @@ -83,6 +83,8 @@ static time_t t1, t2; static u32 ip; static int *look = DARY_ALLOC(int, 2, 2, 1); static u16 numbers[10] = { 2, 100, 1, 5 }; +static u32 bitmap1 = 0xff; +static u32 bitmap2 = 3; static byte * parse_u16(byte *string, u16 *ptr) @@ -150,6 +152,12 @@ static struct cf_section cf_top = { CF_IP("ip", &ip), CF_LOOKUP_DYN("look", &look, alphabet, 1000), CF_USER_ARY("numbers", numbers, &u16_type, 10), + CF_BITMAP_INT("bitmap1", &bitmap1), + CF_BITMAP_LOOKUP("bitmap2", &bitmap2, ((byte*[]) { + "one", "two", "three", "four", "five", "six", "seven", "eight", + "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "seventeen", + "eighteen", "nineteen", "twenty", NULL // hidden joke here + })), CF_END } }; diff --git a/lib/conf-test.cf b/lib/conf-test.cf index 39b803be..43dbfdae 100644 --- a/lib/conf-test.cf +++ b/lib/conf-test.cf @@ -26,6 +26,10 @@ Top { \ look Alpha look:prepend Beta GAMMA numbers 11000 65535 + bitmap1 31 + bitmap1:unset 3 3 + bitmap2:all + bitmap2:unset eleven twelve one };;;;;; unknown.ignored :-) diff --git a/lib/conf.h b/lib/conf.h index 214d9da9..c56cea48 100644 --- a/lib/conf.h +++ b/lib/conf.h @@ -17,7 +17,8 @@ enum cf_class { CC_DYNAMIC, // dynamically allocated array CC_PARSER, // arbitrary parser function CC_SECTION, // section appears exactly once - CC_LIST // list with 0..many nodes + CC_LIST, // list with 0..many nodes + CC_BITMAP // of up to 32 items }; enum cf_type { @@ -99,6 +100,8 @@ struct cf_section { #define CF_PARSER(n,p,f,c) { .cls = CC_PARSER, .name = n, .number = c, .ptr = p, .u.par = (cf_parser*) f } #define CF_SECTION(n,p,s) { .cls = CC_SECTION, .name = n, .number = 1, .ptr = p, .u.sec = s } #define CF_LIST(n,p,s) { .cls = CC_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,clist*), .u.sec = s } +#define CF_BITMAP_INT(n,p) { .cls = CC_BITMAP, .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*) } +#define CF_BITMAP_LOOKUP(n,p,t) { .cls = CC_BITMAP, .type = CT_LOOKUP, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*), .u.lookup = t } /* Configuration items for basic types */ #define CF_INT(n,p) CF_STATIC(n,p,INT,int,1) #define CF_INT_ARY(n,p,c) CF_STATIC(n,p,INT,int,c) diff --git a/lib/getopt.h b/lib/getopt.h index a6f27786..042a1b05 100644 --- a/lib/getopt.h +++ b/lib/getopt.h @@ -22,8 +22,8 @@ int cf_set(byte *string); /* Direct access to configuration items: conf-intr.c */ -#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(APPEND) T(PREPEND) \ - T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(COPY) +#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(UNSET) T(ALL) \ + T(APPEND) T(PREPEND) T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(COPY) /* Closing brace finishes previous block. * Basic attributes (static, dynamic, parsed) can be used with SET. * Dynamic arrays can be used with SET, APPEND, PREPEND.