]> mj.ucw.cz Git - libucw.git/blob - lib/shell/config.c
final changes to substr analyser... closes Bug 2385
[libucw.git] / lib / shell / config.c
1 /*
2  *      UCW Library -- Shell Interface to Configuration Files
3  *
4  *      (c) 2002--2005 Martin Mares <mj@ucw.cz>
5  *
6  *      Once we were using this beautiful Shell version, but it turned out
7  *      that it doesn't work with nested config files:
8  *
9  *              eval `sed <cf/sherlock '/^#/d;/^ *$/d;s/ \+$//;
10  *              h;s@[^  ]*@@;x;s@[      ].*@@;y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/;G;s/\n//;
11  *              /^\[SECTION\]/,/^\[/ {; /^[A-Z]/ { s/^\([^      ]\+\)[  ]*\(.*\)$/SH_\1="\2"/; p; }; };
12  *              d;'`
13  *
14  *      This software may be freely distributed and used according to the terms
15  *      of the GNU Lesser General Public License.
16  */
17
18 #include "lib/lib.h"
19 #include "lib/conf.h"
20
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <alloca.h>
25
26 static struct cfitem *items;
27 static byte *flags;
28
29 enum flag {
30   F_STRING = 0,
31   F_INT = 1,
32   F_DOUBLE = 2,
33   F_INT64 = 3,
34   F_TYPE_MASK = 7,
35   F_ARRAY = 0x80,
36 };
37
38 static void
39 help(void)
40 {
41   fputs("\n\
42 Usage: config [-C<configfile>] [-S<section>.<option>=<value>] <section> [@]<item><type>[=<default>] <item2> ... [*]\n\
43 \n\
44 Types:\n\
45 <empty>\t\tString\n\
46 #\t\t32-bit integer\n\
47 ##\t\t64-bit integer\n\
48 $\t\tFloating point number\n\
49 \n\
50 Modifiers:\n\
51 @\t\tMultiple occurences of the item are passed as an array (otherwise the last one wins)\n\
52 *\t\tIgnore unknown items instead of reporting them as errors\n\
53 ", stderr);
54   exit(1);
55 }
56
57 static byte *
58 report(struct cfitem *item, byte *value)
59 {
60   uns f = flags[item-items];
61   byte *err;
62   byte buf[128];
63
64   if (f & F_ARRAY)
65     printf("CF_%s[${#CF_%s[*]}]='", item->name, item->name);
66   else
67     printf("CF_%s='", item->name);
68
69   switch (f & F_TYPE_MASK)
70     {
71     case F_STRING:
72       break;
73     case F_INT: ;
74       uns val;
75       if (err = cf_parse_int(value, &val))
76         return err;
77       sprintf(buf, "%d", val);
78       value = buf;
79       break;
80     case F_INT64: ;
81       u64 val64;
82       if (err = cf_parse_u64(value, &val64))
83         return err;
84       sprintf(buf, "%Lu", val64);
85       value = buf;
86       break;
87     case F_DOUBLE: ;
88       double valf;
89       if (err = cf_parse_double(value, &valf))
90         return err;
91       sprintf(buf, "%g", valf);
92       value = buf;
93       break;
94     default:
95       ASSERT(0);
96     }
97   while (*value)
98     {
99       if (*value == '\'')
100         die("Apostrophes are not supported in config of scripts");
101       putchar(*value++);
102     }
103   puts("'");
104   return NULL;
105 }
106
107 int main(int argc, char **argv)
108 {
109   int i = 1;
110   int start;
111   struct cfitem *c;
112
113   log_init("config");
114   while (i < argc && argv[i][0] == '-')
115     i++;
116   if (i + 1 >= argc)
117     help();
118   start = i;
119   c = items = alloca(sizeof(struct cfitem) * (argc-i+1));
120   flags = alloca(argc);
121   bzero(flags, argc);
122   c->name = argv[i];
123   c->type = CT_SECTION;
124   c->var = NULL;
125   c++;
126   while (++i < argc)
127     {
128       char *arg = xstrdup(argv[i]);
129       if (!strcmp(arg, "*"))
130         items->type = CT_INCOMPLETE_SECTION;
131       else
132         {
133           uns id = c-items;
134           char *e = strchr(arg, '=');
135           if (e)
136             *e++ = 0;
137
138           char *t = arg + strlen(arg) - 1;
139           if (t > arg)
140             {
141               if (*t == '#')
142                 {
143                   *t-- = 0;
144                   if (t > arg && *t == '#')
145                     {
146                       *t-- = 0;
147                       flags[id] |= F_INT64;
148                     }
149                   else
150                     flags[id] |= F_INT;
151                 }
152               else if (*t == '$')
153                 {
154                   *t-- = 0;
155                   flags[id] |= F_DOUBLE;
156                 }
157             }
158
159           if (*arg == '@')
160             {
161               arg++;
162               printf("declare -a CF_%s ; CF_%s=()\n", arg, arg);
163               flags[id] |= F_ARRAY;
164             }
165
166           c->type = CT_FUNCTION;
167           c->var = report;
168           c->name = arg;
169           if (e)
170             report(c, e);
171           c++;
172         }
173     }
174   c->type = CT_STOP;
175   cf_register(items);
176   if (cf_getopt(start, argv, CF_SHORT_OPTS, CF_NO_LONG_OPTS, NULL) != -1)
177     help();
178   return 0;
179 }