]> mj.ucw.cz Git - libucw.git/commitdiff
configuration mechanism: added support for bitmaps
authorRobert Spalek <robert@ucw.cz>
Fri, 5 May 2006 13:18:23 +0000 (15:18 +0200)
committerRobert Spalek <robert@ucw.cz>
Fri, 5 May 2006 13:18:23 +0000 (15:18 +0200)
lib/conf-dump.c
lib/conf-input.c
lib/conf-internal.h
lib/conf-intr.c
lib/conf-section.c
lib/conf-test.c
lib/conf-test.cf
lib/conf.h
lib/getopt.h

index ee137ab147615c797c4c7e14f2ebc49863d74bc2..073bf129e4cd5096a2a11ca6c1a3dc609a993015 100644 (file)
@@ -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<<i)) {
+       if (item->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)
index e44cba1b3dcf9c025fd92b0b0230800812c35db6..036181dc81c7aaf48d098fa2db52dedcd69e9003 100644 (file)
@@ -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;
index 3760d0e5be2265b52efe4a4059b0a7dd3eee2468..aeb44721702d860766c55f94de4fa68f7627b708 100644 (file)
@@ -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);
index acbe702f2446def422ab06ac3dd97fc3a588693f..5a5f7eaab0e2c0d60b21fb556f957f400549ea06 100644 (file)
@@ -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; i<number; i++) {
+    uns idx;
+    if (item->type == 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<<idx;
+    else
+      *ptr &= ~(1<<idx);
+  }
+  *processed = number;
+  return NULL;
+}
+
 static byte *
 interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
 {
@@ -260,6 +286,10 @@ interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed
       if (!allow_dynamic)
        return "Lists cannot be used here";
       return interpret_add_list(item, number, pars, processed, ptr, OP_SET);
+    case CC_BITMAP:
+      if (!allow_dynamic)
+       return "Bitmaps cannot be used here";
+      return interpret_bitmap(item, number, pars, processed, ptr, OP_SET);
     default:
       ASSERT(0);
   }
@@ -278,11 +308,31 @@ interpret_clear(struct cf_item *item, void *ptr)
   } else if (item->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)
index 2e27546abc96fbc5173daaf224ae932d86060f52..b06b9fd6bca499534966740ed1b3c3c42c6baf8f 100644 (file)
@@ -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;
index cefaa212b17ee38fbe484dc0c9d4a81f516b5a32..f4ca15fdb7fba7022eb8da4ad34c876df3e853e9 100644 (file)
@@ -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
   }
 };
index 39b803be68c55810567a6a636b6b7e7bb8bbbf7b..43dbfdaea468ed697b793fe73f5087641792b323 100644 (file)
@@ -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 :-)
index 214d9da9be2235f82e2ed95fda4f34e977cb3646..c56cea48113ce0148a4b4f5670b7b45a20b17017 100644 (file)
@@ -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)
index a6f277863e3cbde0c0f569cbf99b3c479ff726c6..042a1b05eaec65407fa563a3a14b6420c33bf152 100644 (file)
@@ -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.