2 * Insane tester of reading configuration files
4 * (c) 2006 Robert Spalek <robert@ucw.cz>
5 * (c) 2012--2014 Martin Mares <mj@ucw.cz>
6 * (c) 2014 Pavel Charvat <pchar@ucw.cz>
11 #include <ucw/getopt.h>
12 #include <ucw/clists.h>
13 #include <ucw/fastbuf.h>
15 #include <ucw/xtypes.h>
33 static struct sub_sect_1 sec1 = { {}, "Charlie", 0, "WBAFC", { 0, -1}, NULL };
36 init_sec_1(struct sub_sect_1 *s)
38 if (s == &sec1) // this is a static variable; skip clearing
44 // leave s->list==NULL
49 commit_sec_1(struct sub_sect_1 *s)
51 if (s->confidence[0] < 0 || s->confidence[0] > 10)
52 return "Well, this can't be";
57 time_parser(uint number, char **pars, time_t *ptr)
59 *ptr = number ? atoi(pars[0]) : time(NULL);
63 static struct cf_section cf_sec_1 = {
64 CF_TYPE(struct sub_sect_1),
66 CF_COMMIT(commit_sec_1),
67 #define F(x) PTR_TO(struct sub_sect_1, x)
69 CF_STRING("name", F(name)),
70 //CF_PARSER("t", F(t), time_parser, 0),
71 CF_STRING("level", F(level)),
72 CF_INT_ARY("confidence", F(confidence[0]), 2), // XXX: the [0] is needed for the sake of type checking
73 CF_DOUBLE_DYN("list", F(list), 100),
82 static char *str1 = "no worries";
84 static u64 u1 = 0xCafeBeefDeadC00ll;
85 static double d1 = -1.1;
90 static u16 numbers[10] = { 2, 100, 1, 5 };
91 static u32 bitmap1 = 0xff;
92 static u32 bitmap2 = 3;
93 static intmax_t intmax;
96 parse_u16(char *string, u16 *ptr)
99 char *msg = cf_parse_int(string, &a);
103 return "Come on, man, this doesn't fit to 16 bits";
109 dump_u16(struct fastbuf *fb, u16 *ptr)
111 bprintf(fb, "%d ", *ptr);
114 static struct cf_user_type u16_type = {
117 .parser = (cf_parser1*) parse_u16,
118 .dumper = (cf_dumper1*) dump_u16
122 init_top(void *ptr UNUSED)
124 for (uint i=0; i<5; i++)
126 struct sub_sect_1 *s = xmalloc(sizeof(struct sub_sect_1)); // XXX: cannot by cf_malloc(), because it's deleted when cf_reload()'ed
127 cf_init_section("slaves", &cf_sec_1, s, 1);
128 s->confidence[1] = i;
129 clist_add_tail(&secs, &s->n);
135 commit_top(void *ptr UNUSED)
138 return "Don't touch my variable!";
142 static const char * const alphabet[] = { "alpha", "beta", "gamma", "delta", NULL };
143 static struct cf_section cf_top = {
145 CF_COMMIT(commit_top),
147 CF_UINT("nr1", &nr1),
148 CF_INT_DYN("nrs1", &nrs1, 1000),
149 CF_INT_ARY("nrs2", nrs2, 5),
150 CF_STRING("str1", &str1),
151 CF_STRING_DYN("str2", &str2, 20),
153 CF_DOUBLE("d1", &d1),
154 CF_PARSER("FirstTime", &t1, time_parser, -1),
155 CF_PARSER("SecondTime", &t2, time_parser, 1),
156 CF_SECTION("master", &sec1, &cf_sec_1),
157 CF_LIST("slaves", &secs, &cf_sec_1),
159 CF_LOOKUP_DYN("look", &look, alphabet, 1000),
160 CF_USER_ARY("numbers", numbers, &u16_type, 10),
161 CF_XTYPE("intmax", &intmax, &xt_intmax),
162 CF_BITMAP_INT("bitmap1", &bitmap1),
163 CF_BITMAP_LOOKUP("bitmap2", &bitmap2, ((const char* const[]) {
164 "one", "two", "three", "four", "five", "six", "seven", "eight",
165 "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "seventeen",
166 "eighteen", "nineteen", "twenty", NULL // hidden joke here
172 static char short_opts[] = CF_SHORT_OPTS "rv";
173 static struct option long_opts[] = {
175 {"reload", 0, 0, 'r'},
176 {"verbose", 0, 0, 'v'},
180 static char *help = "\
181 Usage: conf-test [ctxt] [nojournal] <options>\n\
183 Options:\n" CF_USAGE "\
184 -r, --reload\t\tReload configuration\n\
185 -v, --verbose\t\tBe verbose\n\
189 usage(char *msg, ...)
194 vfprintf(stderr, msg, va);
200 main(int argc, char *argv[])
203 struct cf_context *cc = NULL, *prev = NULL;
205 // Special arguments which have to be parsed before cf_getopt()
207 if (!strcmp(argv[1], "ctxt")) {
208 cc = cf_new_context();
209 prev = cf_switch_context(cc);
211 } else if (!strcmp(argv[1], "nojournal")) {
212 cf_set_journalling(0);
218 cf_declare_section("top", &cf_top, 0);
219 cf_def_file = "ucw/conf-test.cf";
221 // Create and initialize dynamic arrays
223 memcpy(nrs1, (int []) { 5, 5, 4, 3, 2, 1 }, 6 * sizeof(int));
230 GARY_INIT(sec1.list, 3);
231 memcpy(sec1.list, (double []) { 1e4, -1e-4, 8 }, 3 * sizeof(double));
234 while ((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0)
236 case 'r': reload++; break;
237 case 'v': verbose++; break;
238 default: usage("unknown option %c\n", opt);
241 usage("too many parameters (%d more)\n", argc-optind);
249 struct fastbuf *out = bfdopen(1, 1<<14);
250 cf_dump_sections(out);
255 cf_switch_context(prev);
256 cf_delete_context(cc);