X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fconf-test.c;h=f4ca15fdb7fba7022eb8da4ad34c876df3e853e9;hb=a46de3a8cefbe34d11b389687e2ca310bd81fcfe;hp=a2242be2d0389136a63c6c41a5865cee9572670d;hpb=521907ed0ed9a9b387b3870bc7128250fcbdab1b;p=libucw.git diff --git a/lib/conf-test.c b/lib/conf-test.c index a2242be2..f4ca15fd 100644 --- a/lib/conf-test.c +++ b/lib/conf-test.c @@ -1,128 +1,219 @@ -/* Test for configuration parser */ - -#include -#include -#include +/* + * Insane tester of reading configuration files + * + * (c) 2006 Robert Spalek + */ #include "lib/lib.h" #include "lib/conf.h" +#include "lib/getopt.h" +#include "lib/clists.h" +#include "lib/fastbuf.h" + +#include +#include +#include -static int robert=14; -static int spalek=-3; -static char *heslo="prazdne"; -static int nastaveni1=0,nastaveni2=1; +static int verbose; -static byte *set_nastaveni(struct cfitem *item, byte *value) +struct sub_sect_1 { + cnode n; + byte *name; + time_t t; + byte *level; + int confidence[2]; + double *list; +}; + +static struct sub_sect_1 sec1 = { {}, "Charlie", 0, "WBAFC", { 0, -1}, DARY_ALLOC(double, 3, 1e4, -1e-4, 8) }; + +static byte * +init_sec_1(struct sub_sect_1 *s) { - int id; - if(!strcasecmp(value,"one")) - id=1; - else if(!strcasecmp(value,"two")) - id=2; - else if(!strcasecmp(value,"three")) - id=3; - else if(!strcasecmp(value,"four")) - id=4; - else - return "Invalid value of nastaveni"; - if(!strcasecmp(item->name,"nastaveni1")) - nastaveni1=id; - else if(!strcasecmp(item->name,"nastaveni2")) - nastaveni2=id; - else - return "Internal error of nastaveni"; - return NULL; + if (s == &sec1) // this is a static variable; skip clearing + return NULL; + s->name = "unknown"; + s->level = "default"; + s->confidence[0] = 5; + s->confidence[1] = 6; + // leave s->list==NULL + return NULL; } -static struct cfitem jmeno[]={ - {"jmeno", CT_SECTION, NULL}, - {"robert", CT_INT, &robert}, - {"spalek", CT_INT, &spalek}, - {"heslo", CT_STRING, &heslo}, - {"nastaveni1", CT_FUNCTION, &set_nastaveni}, - {"nastaveni2", CT_FUNCTION, &set_nastaveni}, - {NULL, CT_STOP, NULL} +static byte * +commit_sec_1(struct sub_sect_1 *s) +{ + if (s->confidence[0] < 0 || s->confidence[0] > 10) + return "Well, this can't be"; + return NULL; +} + +static byte * +time_parser(uns number, byte **pars, time_t *ptr) +{ + *ptr = number ? atoi(pars[0]) : time(NULL); + return NULL; +} + +static struct cf_section cf_sec_1 = { + CF_TYPE(struct sub_sect_1), + CF_INIT(init_sec_1), + CF_COMMIT(commit_sec_1), +#define F(x) PTR_TO(struct sub_sect_1, x) + CF_ITEMS { + CF_STRING("name", F(name)), + //CF_PARSER("t", F(t), time_parser, 0), + CF_STRING("level", F(level)), + CF_INT_ARY("confidence", F(confidence[0]), 2), // XXX: the [0] is needed for the sake of type checking + CF_DOUBLE_DYN("list", F(list), 100), + CF_END + } +#undef F }; -static int vek=22; -static int vyska=178; -static int vaha=66; +static uns nr1 = 15; +static int *nrs1 = DARY_ALLOC(int, 5, 5, 4, 3, 2, 1); +static int nrs2[5]; +static byte *str1 = "no worries"; +static byte **str2 = DARY_ALLOC(byte *, 2, "Alice", "Bob"); +static u64 u1 = 0xCafeBeefDeadC00ll; +static double d1 = -1.1; +static clist secs; +static time_t t1, t2; +static u32 ip; +static int *look = DARY_ALLOC(int, 2, 2, 1); +static u16 numbers[10] = { 2, 100, 1, 5 }; +static u32 bitmap1 = 0xff; +static u32 bitmap2 = 3; + +static byte * +parse_u16(byte *string, u16 *ptr) +{ + uns a; + byte *msg = cf_parse_int(string, &a); + if (msg) + return msg; + if (a >= (1<<16)) + return "Come on, man, this doesn't fit to 16 bits"; + *ptr = a; + return NULL; +} -static struct cfitem telo[]={ - {"telo", CT_SECTION, NULL}, - {"vek", CT_INT, &vek}, - {"vyska", CT_INT, &vyska}, - {"vaha", CT_INT, &vaha}, - {NULL, CT_STOP, NULL} +static void +dump_u16(struct fastbuf *fb, u16 *ptr) +{ + bprintf(fb, "%d ", *ptr); +} + +static struct cf_user_type u16_type = { + .size = sizeof(u16), + .name = "u16", + .parser = (cf_parser1*) parse_u16, + .dumper = (cf_dumper1*) dump_u16 }; -static byte shortopts[] = CF_SHORT_OPTS "abcp:q:r::"; -static struct option longopts[] = +static byte * +init_top(void *ptr UNUSED) { + for (uns i=0; i<5; i++) + { + struct sub_sect_1 *s = xmalloc(sizeof(struct sub_sect_1)); // XXX: cannot by cf_malloc(), because it's deleted when cf_reload()'ed + cf_init_section("slaves", &cf_sec_1, s, 1); + s->confidence[1] = i; + clist_add_tail(&secs, &s->n); + } + return NULL; +} + +static byte * +commit_top(void *ptr UNUSED) +{ + if (nr1 != 15) + return "Don't touch my variable!"; + return NULL; +} + +static byte *alphabet[] = { "alpha", "beta", "gamma", "delta", NULL }; +static struct cf_section cf_top = { + CF_INIT(init_top), + CF_COMMIT(commit_top), + CF_ITEMS { + CF_UNS("nr1", &nr1), + CF_INT_DYN("nrs1", &nrs1, 1000), + CF_INT_ARY("nrs2", nrs2, 5), + CF_STRING("str1", &str1), + CF_STRING_DYN("str2", &str2, 20), + CF_U64("u1", &u1), + CF_DOUBLE("d1", &d1), + CF_PARSER("FirstTime", &t1, time_parser, -1), + CF_PARSER("SecondTime", &t2, time_parser, 1), + CF_SECTION("master", &sec1, &cf_sec_1), + CF_LIST("slaves", &secs, &cf_sec_1), + CF_IP("ip", &ip), + CF_LOOKUP_DYN("look", &look, alphabet, 1000), + CF_USER_ARY("numbers", numbers, &u16_type, 10), + CF_BITMAP_INT("bitmap1", &bitmap1), + CF_BITMAP_LOOKUP("bitmap2", &bitmap2, ((byte*[]) { + "one", "two", "three", "four", "five", "six", "seven", "eight", + "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "seventeen", + "eighteen", "nineteen", "twenty", NULL // hidden joke here + })), + CF_END + } +}; + +static byte short_opts[] = CF_SHORT_OPTS "v"; +static struct option long_opts[] = { CF_LONG_OPTS - {"ahoj", 0, 0, 'a'}, - {"bida", 0, 0, 'b'}, - {"citron", 0, 0, 'c'}, - {"pivo", 1, 0, 'p'}, - {"qwerty", 1, 0, 'q'}, - {"rada", 2, 0, 'r'}, + {"verbose", 0, 0, 'v'}, {NULL, 0, 0, 0} }; -int main(int argc, char *argv[]) +static char *help = "\ +Usage: conf-test \n\ +\n\ +Options:\n" +CF_USAGE +"-v\t\t\tBe verbose\n\ +"; + +static void NONRET +usage(byte *msg, ...) +{ + va_list va; + va_start(va, msg); + if (msg) + vfprintf(stderr, msg, va); + fputs(help, stderr); + exit(1); +} + +int +main(int argc, char *argv[]) { - int c; - - log_init(argv[0]); - - cf_register(jmeno); - cf_register(telo); - - while(1){ - c=cf_getopt(argc,argv,shortopts,longopts,NULL); - if(c==-1) - break; - else switch(c){ - case 'a': - case 'b': - case 'c': - printf("option %c\n",c); - break; - - case 'p': - case 'q': - printf("option %c with parameter %s\n",c,optarg); - break; - case 'r': - if(optarg) - printf("option r with optional parameter %s\n",optarg); - else - printf("option r without optional parameter\n"); - break; - case '?': - //printf("invalid parameter %d: %s\n",optind,argv[optind]); - break; - case ':': - //printf("missing parameter for %d: %s\n",optind,argv[optind]); - break; - default: - printf("getopt is confused, it returns %c\n",c); - break; - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - printf("robert=%d, spalek=%d, heslo=%s, nastaveni1/2=%d/%d\n", - robert,spalek,heslo,nastaveni1,nastaveni2); - printf("vek=%d, vyska=%d, vaha=%d\n", - vek,vyska,vaha); - - return 0; + log_init(argv[0]); + cf_declare_section("top", &cf_top, 0); + cf_def_file = "lib/conf-test.cf"; + + int opt; + while ((opt = cf_getopt(argc, argv, short_opts, long_opts, NULL)) >= 0) + switch (opt) { + case 'v': verbose++; break; + default: usage("unknown option %c\n", opt); + } + if (optind < argc) + usage("too many parameters (%d more)\n", argc-optind); + + /* + cf_load("non-existent file"); + //cf_reload("non-existent file"); + cf_load("non-existent file"); + cf_set("top.d1 -1.1; top.master b"); + */ + + struct fastbuf *out = bfdopen(1, 1<<14); + cf_dump_sections(out); + bclose(out); + + return 0; }