]> mj.ucw.cz Git - libucw.git/blobdiff - lib/conf-intr.c
Fixed bug in signal handling.
[libucw.git] / lib / conf-intr.c
index 5895bd6b97c2bfc75f86fe353a42f72f9cee7509..b90640f18563cce146db02dd6ed4182739cf3611 100644 (file)
@@ -90,7 +90,7 @@ cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type, union cf_uni
     else
       ASSERT(0);
     if (msg)
-      return cf_printf("Cannot parse item %d: %s", i+1, msg);
+      return number > 1 ? cf_printf("Item %d: %s", i+1, msg) : msg;
   }
   return NULL;
 }
@@ -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,9 +111,8 @@ 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((number+1) * size) + size;
-  * (uns*) (*ptr - size) = number;
+  *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);
 }
 
@@ -121,12 +123,12 @@ interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *proces
   void *old_p = *ptr;
   uns size = cf_type_size(item->type, item->u.utype);
   ASSERT(size >= sizeof(uns));
-  int old_nr = old_p ? * (int*) (old_p - size) : 0;
+  int old_nr = old_p ? DARY_LEN(old_p) : 0;
   int taken = MIN(number, ABS(item->number)-old_nr);
   *processed = taken;
   // stretch the dynamic array
-  void *new_p = cf_malloc((old_nr + taken + 1) * size) + size;
-  * (uns*) (new_p - size) = old_nr + taken;
+  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;
   if (op == OP_APPEND) {
@@ -201,6 +203,7 @@ interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed
     return "Nothing to add to the list";
   struct cf_section *sec = item->u.sec;
   *processed = 0;
+  uns index = 0;
   while (number > 0)
   {
     void *node = cf_malloc(sec->size);
@@ -209,7 +212,10 @@ interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed
     int taken;
     /* If the node contains any dynamic attribute at the end, we suppress
      * auto-repetition here and pass the flag inside instead.  */
-    TRY( interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC) );
+    index++;
+    byte *msg = interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC);
+    if (msg)
+      return sec->flags & SEC_FLAG_DYNAMIC ? msg : cf_printf("Node %d of list %s: %s", index, item->name, msg);
     *processed += taken;
     number -= taken;
     pars += taken;
@@ -219,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; 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)
 {
@@ -255,22 +286,46 @@ 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_add_bitmap(item, number, pars, processed, ptr, OP_SET);
     default:
       ASSERT(0);
   }
 }
 
 static byte *
-interpret_clear(struct cf_item *item, void *ptr)
+interpret_set_all(struct cf_item *item, void *ptr, enum cf_operation op)
 {
+  if (item->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);
   } else if (item->cls == CC_DYNAMIC) {
     cf_journal_block(ptr, sizeof(void *));
-    * (void**) ptr = NULL;
+    static uns zero = 0;
+    * (void**) ptr = (&zero) + 1;
+  } 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
-    return "The item is not a list or a dynamic array";
+    return "The item is not a list, dynamic array, bitmap, or string";
   return NULL;
 }
 
@@ -337,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,
@@ -350,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
   }
@@ -359,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;
@@ -478,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)
@@ -501,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;
@@ -517,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:
@@ -533,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";