]> mj.ucw.cz Git - libucw.git/commitdiff
Forgotten commit... added arrays support to configuration parser.
authorPavel Charvat <pavel.charvat@netcentrum.cz>
Tue, 16 May 2006 13:50:39 +0000 (15:50 +0200)
committerPavel Charvat <pavel.charvat@netcentrum.cz>
Tue, 16 May 2006 13:50:39 +0000 (15:50 +0200)
lib/shell/config.c
lib/shell/config.t

index 1aecea053d02d2be85795ae33e01e1d699d84fb9..2395458408e5e36d466ba8f7f7dccd5324c50dc7 100644 (file)
@@ -38,13 +38,15 @@ Usage: config [-C<configfile>] [-S<section>.<option>=<value>] <sections>\n\
 \n\
 <sections>\t<section>[;<sections>]\n\
 <section>\t[*]<name>{[<items>]}\n\
-<items>\t\t<item>[;<items>]\n\
-<item>\t\t<static> | @<list>\n\
-<static>\t[-]<type><name>\n\
-<list>\t\t<name>{[<items>]}\n\
+<items>\t\t[-]<item>[;<items>]\n\
+<item>\t\t<static> | <array> | <list>\n\
+<static>\t<type><name>[=<value>]\n\
+<list>\t\t@<name>{[<items>]}\n\
+<array>\t\t<type><name><left-bracket>[<number>]<right-bracket>\n\
+<value>\t\t[a-zA-Z0-9.-/]* | 'string without single quotes'<value> | \"c-like string\"<value>\n\
 \n\
 Types:\n\
-<empty>\t\tString\n\
+:\t\tString\n\
 #\t\t32-bit integer\n\
 ##\t\t64-bit integer\n\
 $\t\tFloating point number\n\
@@ -118,6 +120,7 @@ parse_name(void)
 static void
 parse_section(struct section *section)
 {
+#define TRY(x) do{byte *_err=(x); if (_err) die(_err); }while(0)
   for (uns sep = 0; ; sep = 1)
     {
       parse_white();
@@ -154,10 +157,10 @@ parse_section(struct section *section)
            }
          item->cf.cls = CC_STATIC;
          item->cf.number = 1;
-         switch (*pos)
+         switch (*pos++)
            {
              case '#':
-               if (*++pos == '#')
+               if (*pos == '#')
                  {
                    pos++;
                    item->cf.type = CT_U64;
@@ -166,23 +169,48 @@ parse_section(struct section *section)
                  item->cf.type = CT_INT;
                break;
              case '$':
-               pos++;
                item->cf.type = CT_DOUBLE;
                break;
-             default:
-               if (!Cword(*pos))
-                 die("Invalid type syntax");
+             case ':':
                item->cf.type = CT_STRING;
                break;
+             default:
+               die("Invalid type syntax");
            }
+         parse_white();
          item->cf.name = parse_name();
          parse_white();
+         if (*pos == '[')
+           {
+             pos++;
+             parse_white();
+             item->cf.cls = CC_DYNAMIC;
+             byte *num = pos;
+             while (*pos && *pos != ']')
+               pos++;
+             if (!*pos)
+               die("Missing ']'");
+             *pos++ = 0;
+             if (!*num)
+               item->cf.number = CF_ANY_NUM;
+             else
+               {
+                 int inum;
+                 TRY(cf_parse_int(num, &inum));
+                 if (!inum)
+                   die("Invalid array length");
+                 item->cf.number = inum;
+               }
+             parse_white();
+           }
          if (*pos == '=')
            {
              pos++;
              parse_white();
              if (section->item.cf.cls == CC_LIST)
                die("List items can not have default values");
+             if (item->cf.cls == CC_DYNAMIC)
+               die("Arrays can not have default values");
              byte *def = pos, *d = def;
              while (*pos != ';' && *pos != '}' && !Cspace(*pos))
                {
@@ -224,7 +252,6 @@ parse_section(struct section *section)
              memcpy(buf, def, len);
              buf[len] = 0;
              switch (item->cf.type)
-#define TRY(x) do{byte *_err=(x); if (_err) die(_err); }while(0)
                {
                  case CT_STRING:
                    item->value.v_ptr = buf;
@@ -240,7 +267,6 @@ parse_section(struct section *section)
                    break;
                  default:
                    ASSERT(0);
-#undef TRY
                }
            }
        }
@@ -254,6 +280,7 @@ parse_section(struct section *section)
       clist_add_tail(&section->list, &item->node);
       section->count++;
     }
+#undef TRY
 }
 
 static void
@@ -303,63 +330,86 @@ generate_section(struct section *section)
 
 static bb_t path;
 
+static uns
+type_size(enum cf_type type)
+{
+  switch (type)
+    {
+      case CT_INT: return sizeof(int);
+      case CT_U64: return sizeof(u64);
+      case CT_DOUBLE: return sizeof(double);
+      case CT_STRING: return sizeof(byte *);
+      default: ASSERT(0);
+    }
+}
+
+static void
+dump_value(uns array, struct item *item, void *v)
+{
+  byte buf[128], *value = buf;
+  if (!array)
+    printf("CF_%s_%s='", path.ptr, item->cf.name);
+  else
+    printf("CF_%s_%s[%u]='", path.ptr, item->cf.name, ++item->index);
+  switch (item->cf.type)
+    {
+      case CT_INT:
+        sprintf(buf, "%d", *(int *)v);
+        break;
+      case CT_U64:
+        sprintf(buf, "%Lu", *(u64 *)v);
+       break;
+      case CT_DOUBLE:
+       sprintf(buf, "%g", *(double *)v);
+       break;
+      case CT_STRING:
+        if (*(byte **)v)
+          value = *(byte **)v;
+        else
+          *value = 0;
+        break;
+      default:
+        ASSERT(0);
+    }
+  while (*value) {
+    if (*value == '\'')
+      printf("'\\''");
+    else
+      putchar(*value);
+    value++;
+  }
+  printf("'\n");
+}
+
 static void
 dump_item(struct item *item, void *ptr, uns path_len)
 {
   if (item->flags & FLAG_HIDE)
     return;
-  union value *val = (union value *)((addr_int_t)ptr + (addr_int_t)item->cf.ptr);
+  byte *val = (byte *)((addr_int_t)ptr + (addr_int_t)item->cf.ptr);
   if (item->cf.cls == CC_LIST)
     {
       uns len = strlen(item->cf.name);
       bb_grow(&path, path_len + len + 1);
       path.ptr[path_len] = '_';
       memcpy(path.ptr + path_len + 1, item->cf.name, len);
-      CLIST_FOR_EACH(cnode *, ptr2, val->list)
+      CLIST_FOR_EACH(cnode *, ptr2, *(clist *)val)
         CLIST_FOR_EACH(struct item *, item2, ((struct section *)item)->list)
           dump_item(item2, ptr2, path_len + len + 1);
     }
   else
     {
-      byte *name = item->cf.name;
-      byte buf[128], *value = buf;
       bb_grow(&path, path_len + 1)[path_len] = 0;
-      if (!ptr)
-        printf("CF_%s_%s='", path.ptr, name);
+      if (item->cf.cls == CC_STATIC)
+       dump_value(!!ptr, item, val);
       else
-        printf("CF_%s_%s[%u]='", path.ptr, name, item->index++);
-      switch (item->cf.type)
         {
-          case CT_INT:
-           sprintf(buf, "%d", val->v_int);
-            break;
-          case CT_U64:
-           sprintf(buf, "%Lu", val->v_u64);
-           break;
-         case CT_DOUBLE:
-           sprintf(buf, "%g", val->v_double);
-           break;
-         case CT_STRING:
-           if (val->v_ptr)
-             value = val->v_ptr;
-           else
-             *value = 0;
-           break;
-         default:
-           ASSERT(0);
+         val = *(void **)val;
+         uns len = DARY_LEN(val);
+         uns size = type_size(item->cf.type);
+         for (uns i = 0; i < len; i++, val += size)
+           dump_value(1, item, val);
        }
-          while (*value) {
-#if 0
-            if (*value == '\'')
-             die("Apostrophes are not supported in config of scripts");
-#endif
-            if (*value == '\'')
-             printf("'\\''");
-           else
-              putchar(*value);
-           value++;
-          }
-         printf("'\n");
     }
 }
 
index b28bd393d0a7015ffdc0a166a248d888413d9e49..a6206971701c6fd25e6c1ee18c44339e3da94c1e 100644 (file)
@@ -1,27 +1,39 @@
 # Tests for configuration parser
 
-Run:   obj/lib/shell/config -C/dev/null -S 'sec1{int1=23; long1=1234567812345678; long2=4321; str1="s1"; str2="s2"}' 'sec1 {#int1; ##long1; -str1; str2; #int2=123; ##long2=1234}; sec2{str3}'
+Run:   obj/lib/shell/config -C/dev/null -S 'sec1{int1=23; long1=1234567812345678; long2=4321; str1="s1"; str2="s2"}' 'sec1 {#int1; ##long1; -:str1; :str2; #int2=123; ##long2=1234; #int3=0x10; #int4; $dbl1=001.100; $dbl2}; sec2{:str3}'
 Out:   CF_sec1_int1='23'
        CF_sec1_long1='1234567812345678'
        CF_sec1_str2='s2'
        CF_sec1_int2='123'
        CF_sec1_long2='4321'
+       CF_sec1_int3='16'
+       CF_sec1_int4='0'
+       CF_sec1_dbl1='1.1'
+       CF_sec1_dbl2='0'
        CF_sec2_str3=''
 
-Run:   obj/lib/shell/config -C/dev/null -S 'sec1{list1 1 a1 b1; list1:clear; list1 2 a2 b2 3 a3 b3}' 'sec1 {@list1 {#int1; str1; -str2}}'
-Out:   CF_sec1_list1_int1[0]='2'
-       CF_sec1_list1_str1[0]='a2'
-       CF_sec1_list1_int1[1]='3'
-       CF_sec1_list1_str1[1]='a3'
+Run:   obj/lib/shell/config -C/dev/null -S 'sec1{list1 1 a1 b1; list1:clear; list1 2 a2 b2 3 a3 b3}' 'sec1 {@list1 {#int1; :str1; -:str2}}'
+Out:   CF_sec1_list1_int1[1]='2'
+       CF_sec1_list1_str1[1]='a2'
+       CF_sec1_list1_int1[2]='3'
+       CF_sec1_list1_str1[2]='a3'
 
-Run:   obj/lib/shell/config -C/dev/null -S 'sec1{list1 {str1=1; list2=a b c}; list1 {str1=2; list2=d e}}' 'sec1 {@list1 {str1; @list2{str2}}}'
-Out:   CF_sec1_list1_str1[0]='1'
-       CF_sec1_list1_list2_str2[0]='a'
-       CF_sec1_list1_list2_str2[1]='b'
-       CF_sec1_list1_list2_str2[2]='c'
-       CF_sec1_list1_str1[1]='2'
-       CF_sec1_list1_list2_str2[3]='d'
-       CF_sec1_list1_list2_str2[4]='e'
+Run:   obj/lib/shell/config -C/dev/null -S 'sec1{ar1 a b c d; ar1 a b c; ar2 1 2; ar3 1.1}' 'sec1 {:ar1[]; #ar2[2]; $ar3[-2]}'
+Out:   CF_sec1_ar1[1]='a'
+       CF_sec1_ar1[2]='b'
+       CF_sec1_ar1[3]='c'
+       CF_sec1_ar2[1]='1'
+       CF_sec1_ar2[2]='2'
+       CF_sec1_ar3[1]='1.1'
 
-Run:   obj/lib/shell/config -C/dev/null 'sec{str=a'\''b"c'\''d"\\e'\''f"g}'
+Run:   obj/lib/shell/config -C/dev/null -S 'sec1{list1 {str1=1; list2=a b c}; list1 {str1=2; list2=d e}}' 'sec1 {@list1 {:str1; @list2{:str2}}}'
+Out:   CF_sec1_list1_str1[1]='1'
+       CF_sec1_list1_list2_str2[1]='a'
+       CF_sec1_list1_list2_str2[2]='b'
+       CF_sec1_list1_list2_str2[3]='c'
+       CF_sec1_list1_str1[2]='2'
+       CF_sec1_list1_list2_str2[4]='d'
+       CF_sec1_list1_list2_str2[5]='e'
+
+Run:   obj/lib/shell/config -C/dev/null 'sec{:str=a'\''b"c'\''d"\\e'\''f"g}'
 Out:   CF_sec_str='ab"cd\e'\''fg'