]> mj.ucw.cz Git - libucw.git/blobdiff - lib/shell/config.c
XML: Fixed reporting of characters via the PULL interface.
[libucw.git] / lib / shell / config.c
index 6efb6201437efaea2702ba9331b2394a0b80de20..4208b8665438987f55d834fe700176a8bcbe1362 100644 (file)
@@ -20,6 +20,7 @@
 #include "lib/lib.h"
 #include "lib/conf.h"
 #include "lib/getopt.h"
 #include "lib/lib.h"
 #include "lib/conf.h"
 #include "lib/getopt.h"
+#include "lib/conf-internal.h"
 #include "lib/clists.h"
 #include "lib/mempool.h"
 #include "lib/chartype.h"
 #include "lib/clists.h"
 #include "lib/mempool.h"
 #include "lib/chartype.h"
@@ -36,12 +37,14 @@ help(void)
   fputs("\n\
 Usage: config [-C<configfile>] [-S<section>.<option>=<value>] <sections>\n\
 \n\
   fputs("\n\
 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\
+<sections>\t<section>[;<sections>]\n\
+<section>\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\
 \n\
 Types:\n\
 <empty>\t\tString\n\
@@ -50,7 +53,7 @@ Types:\n\
 $\t\tFloating point number\n\
 \n\
 Modifiers:\n\
 $\t\tFloating point number\n\
 \n\
 Modifiers:\n\
-*\t\tReport unknown items as errors\n\
+!\t\tReport unknown items as errors\n\
 -\t\tDo not dump item's value\n\
 ", stderr);
   exit(1);
 -\t\tDo not dump item's value\n\
 ", stderr);
   exit(1);
@@ -72,6 +75,7 @@ struct item {
   uns flags;
   struct cf_item cf;
   union value value;
   uns flags;
   struct cf_item cf;
   union value value;
+  uns index;
 };
 
 struct section {
 };
 
 struct section {
@@ -117,13 +121,14 @@ parse_name(void)
 static void
 parse_section(struct section *section)
 {
 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();
       if (!*pos || *pos == '}')
        break;
       if (sep)
   for (uns sep = 0; ; sep = 1)
     {
       parse_white();
       if (!*pos || *pos == '}')
        break;
       if (sep)
-       parse_char(',');
+       parse_char(';');
       parse_white();
 
       struct item *item;
       parse_white();
 
       struct item *item;
@@ -174,11 +179,102 @@ parse_section(struct section *section)
                item->cf.type = CT_STRING;
                break;
            }
                item->cf.type = CT_STRING;
                break;
            }
+         parse_white();
          item->cf.name = parse_name();
          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))
+               {
+                 if (*pos == '\'')
+                   {
+                     pos++;
+                     while (*pos != '\'')
+                       {
+                         if (!*pos)
+                           die("Unterminated string");
+                         *d++ = *pos++;
+                       }
+                     pos++;
+                   }
+                 else if (*pos == '"')
+                   {
+                     pos++;
+                     byte *start = d;
+                     uns esc = 0;
+                     while (*pos != '"' || esc)
+                       {
+                         if (!*pos)
+                           die("Unterminated string");
+                         if (*pos == '\\')
+                           esc ^= 1;
+                         else
+                           esc = 0;
+                         *d++ = *pos++;
+                       }
+                     pos++;
+                     *d = 0;
+                     d = str_unesc(start, start);
+                   }
+                 else
+                   *d++ = *pos++;
+               }
+             uns len = d - def;
+             byte *buf = mp_alloc(pool, len + 1);
+             memcpy(buf, def, len);
+             buf[len] = 0;
+             switch (item->cf.type)
+               {
+                 case CT_STRING:
+                   item->value.v_ptr = buf;
+                   break;
+                 case CT_INT:
+                   TRY(cf_parse_int(buf, &item->value.v_int));
+                   break;
+                 case CT_U64:
+                   TRY(cf_parse_u64(buf, &item->value.v_u64));
+                   break;
+                 case CT_DOUBLE:
+                   TRY(cf_parse_double(buf, &item->value.v_double));
+                   break;
+                 default:
+                   ASSERT(0);
+               }
+           }
        }
       if (section->item.cf.cls == CC_LIST)
         {
        }
       if (section->item.cf.cls == CC_LIST)
         {
-          item->cf.ptr = (void *)section->size;
+          item->cf.ptr = (void *)(uintptr_t)section->size;
           section->size += sizeof(union value);
         }
       else
           section->size += sizeof(union value);
         }
       else
@@ -186,6 +282,7 @@ parse_section(struct section *section)
       clist_add_tail(&section->list, &item->node);
       section->count++;
     }
       clist_add_tail(&section->list, &item->node);
       section->count++;
     }
+#undef TRY
 }
 
 static void
 }
 
 static void
@@ -197,10 +294,10 @@ parse_outer(void)
       if (!*pos)
        break;
       if (sep)
       if (!*pos)
        break;
       if (sep)
-       parse_char(',');
+       parse_char(';');
       parse_white();
       struct section *sec = mp_alloc_zero(pool, sizeof(*sec));
       parse_white();
       struct section *sec = mp_alloc_zero(pool, sizeof(*sec));
-      if (*pos == '*')
+      if (*pos == '!')
         {
          pos++;
          sec->item.flags |= FLAG_NO_UNKNOWN;
         {
          pos++;
          sec->item.flags |= FLAG_NO_UNKNOWN;
@@ -235,63 +332,73 @@ generate_section(struct section *section)
 
 static bb_t path;
 
 
 static bb_t path;
 
+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, "%llu", (long long) *(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;
 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 *)((uintptr_t)ptr + (uintptr_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);
   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
     {
         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;
       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
       else
-        printf("CF_%s_%s[${#CF_%s_%s[*]}]='", path.ptr, name, path.ptr, name);
-      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 = cf_type_size(item->cf.type, NULL);
+         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");
     }
 }
 
     }
 }