]> mj.ucw.cz Git - libucw.git/commitdiff
conf2: resolve an issue concerning variable numbers of parameters
authorRobert Spalek <robert@ucw.cz>
Fri, 21 Apr 2006 10:40:57 +0000 (12:40 +0200)
committerRobert Spalek <robert@ucw.cz>
Fri, 21 Apr 2006 10:40:57 +0000 (12:40 +0200)
When a node of a link list is parsed on one line, then the inner section
is checked for dynamic attributes at the end.  If they are present, the
outer node is just parsed once and the flag allowing dynamic parsing is
passed inside.  If we did not allow this, then an error would have occured
anyway, and this behaviour is actually useful.

Along the way, I unified the headers and semantics of most interpreters and
cleaned up the code.

lib/conf2.c

index 9e772e1603d68885a981721fb9cb570a955d3899..ca24e5658734c476b227792c3b6bd1f3ed2b9b98 100644 (file)
@@ -471,33 +471,33 @@ interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr)
 }
 
 static byte *
-interpret_add_dynamic(struct cf_item *item, int number, byte **pars, void **ptr, enum operation op)
+interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *processed, void **ptr, enum operation op)
 {
   enum cf_type type = item->u.type;
   void *old_p = *ptr;
   int old_nr = * (int*) (old_p - parsers[type].size);
-  if (old_nr + number > item->number)
-    return "Too many parameters for the dynamic array";
+  int taken = MIN(number, item->number-old_nr);
+  *processed = taken;
   // stretch the dynamic array
-  void *new_p = cf_malloc((old_nr + number + 1) * parsers[type].size) + parsers[type].size;
-  * (uns*) (new_p - parsers[type].size) = old_nr + number;
+  void *new_p = cf_malloc((old_nr + taken + 1) * parsers[type].size) + parsers[type].size;
+  * (uns*) (new_p - parsers[type].size) = old_nr + taken;
   cf_journal_block(ptr, sizeof(void*));
   *ptr = new_p;
   if (op == OP_APPEND)
   {
     memcpy(new_p, old_p, old_nr * parsers[type].size);
-    return cf_parse_ary(number, pars, new_p + old_nr * parsers[type].size, type);
+    return cf_parse_ary(taken, pars, new_p + old_nr * parsers[type].size, type);
   }
   else if (op == OP_PREPEND)
   {
-    memcpy(new_p + number * parsers[type].size, old_p, old_nr * parsers[type].size);
-    return cf_parse_ary(number, pars, new_p, type);
+    memcpy(new_p + taken * parsers[type].size, old_p, old_nr * parsers[type].size);
+    return cf_parse_ary(taken, pars, new_p, type);
   }
   else
     ASSERT(0);
 }
 
-static byte *interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, uns allow_dynamic, void *ptr);
+static byte *interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic);
 
 static byte *
 interpret_subsection(struct cf_section *sec, int number, byte **pars, int *processed, uns allow_dynamic, void *ptr)
@@ -506,7 +506,7 @@ interpret_subsection(struct cf_section *sec, int number, byte **pars, int *proce
   for (struct cf_item *ci=sec->cfg; ci->cls; ci++)
   {
     int taken;
-    byte *msg = interpret_set_item(ci, number, pars, &taken, allow_dynamic && !ci[1].cls, ptr + (addr_int_t) ci->ptr);
+    byte *msg = interpret_set_item(ci, number, pars, &taken, ptr + (addr_int_t) ci->ptr, allow_dynamic && !ci[1].cls);
     if (msg)
       return cf_printf("Item %s: %s", ci->name, msg);
     *processed += taken;
@@ -529,25 +529,40 @@ add_to_list(struct clist *list, struct cnode *node, enum operation op)
 }
 
 static byte *
-interpret_add_list(struct cf_item *item, int number, byte **pars, void *ptr, enum operation op)
+interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, enum operation op)
 {
+  struct cf_item *ci = item;
+  uns only_1_item = 0;
+  do
+    for (ci=ci->u.sec->cfg; ci->cls; ci++);
+  while ((--ci)->cls == CC_SECTION);
+  if (ci->cls == CC_DYNAMIC || ci->cls == CC_LIST
+      || ci->cls == CC_PARSER && ci->number < 0)
+    only_1_item = 1;
+  /* If the node contains any dynamic attribute at the end, we suppress
+   * repetition here and pass it instead inside.  */
+  struct cf_section *sec = item->u.sec;
+  *processed = 0;
   while (number > 0)
   {
-    void *node = cf_malloc(item->u.sec->size);
-    cf_init_section(item->name, item->u.sec, node);
+    void *node = cf_malloc(sec->size);
+    cf_init_section(item->name, sec, node);
     add_to_list(ptr, node, op);
     int taken;
-    byte *msg = interpret_subsection(item->u.sec, number, pars, &taken, 0, node);
+    byte *msg = interpret_subsection(sec, number, pars, &taken, only_1_item, node);
     if (msg)
       return msg;
+    *processed += taken;
     number -= taken;
     pars += taken;
+    if (only_1_item)
+      break;
   }
   return NULL;
 }
 
 static byte *
-interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, uns allow_dynamic, void *ptr)
+interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
 {
   int taken;
   switch (item->cls)
@@ -578,8 +593,7 @@ interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed
     case CC_LIST:
       if (!allow_dynamic)
        return "Lists cannot be used here";
-      *processed = number;
-      return interpret_add_list(item, number, pars, ptr, OP_APPEND);
+      return interpret_add_list(item, number, pars, ptr, processed, OP_APPEND);
     default:
       ASSERT(0);
   }
@@ -630,22 +644,21 @@ interpret_line(byte *name, enum operation op, int number, byte **pars)
       return "The item is not a list";
     cf_journal_block(ptr, sizeof(struct clist));
     clist_init(ptr);
+    return NULL;
   }
-  else if (op == OP_SET)
-  {
-    int taken;
-    msg = interpret_set_item(item, number, pars, &taken, 1, ptr);
-    if (msg)
-      return msg;
-    if (taken < number)
-      return "Too many parameters";
-  }
+  int taken;                   // process as many parameters as possible
+  if (op == OP_SET)
+    msg = interpret_set_item(item, number, pars, &taken, ptr, 1);
   else if (item->cls == CC_DYNAMIC)
-    return interpret_add_dynamic(item, number, pars, ptr, op);
+    msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op);
   else if (item->cls == CC_LIST)
-    return interpret_add_list(item, number, pars, ptr, op);
+    msg = interpret_add_list(item, number, pars, &taken, ptr, op);
   else
     return cf_printf("Operation %d not supported for class %d", op, item->cls);
+  if (msg)
+    return msg;
+  if (taken < number)
+    return cf_printf("Too many parameters: %d>%d", number, taken);
   return NULL;
 }