From a9e97e1e2f38dd2e9cdff4a196f96371580a9243 Mon Sep 17 00:00:00 2001 From: Robert Spalek Date: Tue, 18 Apr 2006 11:57:57 +0200 Subject: [PATCH] interface simplified and a few bugs removed - array macros renamed and extended - CF_FUNCTION renamed to CF_PARSER, and a number of parameters and a pointer to the target variable are passed into the parser function - init-, commit-, and parser-hooks only get parameters that they need and they get it in a nice way so that they don't have to work much - fixed CHECK_VAR_TYPE and a few other thingies --- lib/conf2-test.c | 33 ++++++++++++++------------------- lib/conf2.h | 38 +++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/lib/conf2-test.c b/lib/conf2-test.c index 540ffed3..8c91a6c7 100644 --- a/lib/conf2-test.c +++ b/lib/conf2-test.c @@ -18,7 +18,7 @@ struct sub_sect_1 { }; static byte * -init_sec_1(void *ptr, struct cf_section *sec UNUSED) +init_sec_1(void *ptr) { struct sub_sect_1 *s = ptr; s->name = "unknown"; @@ -28,7 +28,7 @@ init_sec_1(void *ptr, struct cf_section *sec UNUSED) } static byte * -commit_sec_1(void *ptr, struct cf_section *sec UNUSED) +commit_sec_1(void *ptr) { struct sub_sect_1 *s = ptr; if (s->confidence < 0 || s->confidence > 10) @@ -51,33 +51,28 @@ static struct cf_section cf_sec_1 = { }; static int nr1 = 15; -static int *nrs1 = DEFAULT_ARRAY(int, 5, 5, 4, 3, 2, 1); +static int *nrs1 = ARRAY_ALLOC(int, 5, 5, 4, 3, 2, 1); static int *nrs2; static byte *str1 = "no worries"; -static byte **str2 = DEFAULT_ARRAY(byte *, 2, "Alice", "Bob"); +static byte **str2 = ARRAY_ALLOC(byte *, 2, "Alice", "Bob"); static u64 u1 = 0xCafeBeefDeadC00ll; static double d1 = -1.1; -static struct sub_sect_1 sec_1 = { "Charlie", "WBAFC", 0 }; -static struct cnode secs; +static struct sub_sect_1 sec1 = { "Charlie", "WBAFC", 0 }; +static struct clist secs; static time_t t1, t2; static byte * -commit_top(void *ptr UNUSED, struct cf_section *sec UNUSED) +commit_top(void *ptr UNUSED) { + if (nr1 != 15) + return "Don't touch my variable!"; return NULL; } static byte * -time_parser(uns nr_pars, byte **pars, void *sec_ptr, struct cf_section *sec, uns index) +time_parser(byte *name UNUSED, uns number, byte **pars, void *ptr) { - if (nr_pars != 0 && nr_pars != 1) - return "Either now or 1 parameter!"; - ASSERT(!sec_ptr); - time_t t = nr_pars ? atoi(pars[0]) : time(NULL); - if (sec->cfg[index].name[0] == 'F') - t1 = t; - else - t2 = t; + * (time_t*) ptr = number ? atoi(pars[0]) : time(NULL); return NULL; } @@ -91,9 +86,9 @@ static struct cf_section cf_top = { CF_STRING_AR("str2", &str2, 2), CF_U64("u1", &u1), CF_DOUBLE("d1", &d1), - CF_FUNCTION("FirstTime", time_parser), - CF_FUNCTION("SecondTime", time_parser), - CF_SUB_SECTION("master", &sec_1, &cf_sec_1), + CF_PARSER("FirstTime", &t1, time_parser, -1), + CF_PARSER("SecondTime", &t2, time_parser, 1), + CF_SUB_SECTION("master", &sec1, &cf_sec_1), CF_LINK_LIST("slaves", &secs, &cf_sec_1), CF_END } diff --git a/lib/conf2.h b/lib/conf2.h index dfb024d3..9f5de68d 100644 --- a/lib/conf2.h +++ b/lib/conf2.h @@ -14,29 +14,30 @@ enum cf_type { CT_END, // end of list CT_INT, CT_U64, CT_DOUBLE, // number types CT_STRING, // string type - CT_FUNCTION, // arbitrary parser function + CT_PARSER, // arbitrary parser function CT_SUB_SECTION, // sub-section appears exactly once CT_LINK_LIST // link-list with 0..many nodes }; struct cf_section; -typedef byte *cf_hook(void *sec_ptr, struct cf_section *sec); +typedef byte *cf_hook(void *ptr); /* An init- or commit-hook gets a pointer to the sub-section or NULL if this - * is the global section, and a declaration of the section it is called on. - * It returns an error message or NULL if everything is all right. */ -typedef byte *cf_parser(uns nr_pars, byte **pars, void *sec_ptr, struct cf_section *sec, uns index); - /* A parser function gets an array of strings and stores it in any way it - * likes into its own data structures. It gets a pointer to the sub-section - * or NULL if this is the global section, a declaration of the section it is - * called in, and the index of the item it is called on. It returns an error - * message or NULL if everything is all right. */ + * is the global section. It returns an error message or NULL if everything + * is all right. */ +typedef byte *cf_parser(byte *name, uns number, byte **pars, void *ptr); + /* A parser function gets a name of the attribute and an array of strings, + * and stores the parsed value in any way it likes into *ptr. It returns an + * error message or NULL if everything is all right. */ struct cf_item { enum cf_type type; byte *name; - int number; // number of values: k>0 means exactly k, k<0 means at most k + int number; // number of values: k>=0 means exactly k, k<0 means at most -k void *ptr; // pointer to a global variable or an offset in a sub-section - struct cf_section *sub; // declaration of a sub-section or link-list + union { + struct cf_section *sub; // declaration of a sub-section or a link-list + cf_parser *par; // parser function + } ptr2; }; struct cf_section { @@ -46,10 +47,12 @@ struct cf_section { struct cf_item *cfg; // CT_END-terminated array of items }; -#define CHECK_VAR_TYPE(x,type) ((x)-(type)0 + (type)0) +#define CHECK_VAR_TYPE(x,type) ((x)-(type)(x) + (type)(x)) // for a pointer x it returns x, and performs a compile-time check whether typeof(x)==type -#define DEFAULT_ARRAY(type,len,val...) (type[]) { (type)len, ##val } + 1 +#define ARRAY_ALLOC(type,len,val...) (type[]) { (type)len, ##val } + 1 // creates an array with an allocated space in the front for the (Pascal-like) length +#define ARRAY_LEN(a) *(uns*)(a-1) + // length of the array #define CF_FIELD(str,f) &((str*)0)->f // returns a pointer to a field inside a structure suitable for passing as cf_item->ptr @@ -59,14 +62,15 @@ struct cf_section { #define CF_U64(n,p) { .type = CT_U64, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,u64*) } #define CF_DOUBLE(n,p) { .type = CT_DOUBLE, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,double*) } #define CF_STRING(n,p) { .type = CT_STRING, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,byte**) } -#define CF_FUNCTION(n,p) { .type = CT_FUNCTION, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,cf_parser*) } -#define CF_SUB_SECTION(n,p,s) { .type = CT_SUB_SECTION, .name = n, .number = 1, .ptr = p, .sub = s } -#define CF_LINK_LIST(n,p,s) { .type = CT_LINK_LIST, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,struct cnode*), .sub = s } // use the macros above to declare configuration items for single variables #define CF_INT_AR(n,p,c) { .type = CT_INT, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,int**) } #define CF_U64_AR(n,p,c) { .type = CT_U64, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,u64**) } #define CF_DOUBLE_AR(n,p,c) { .type = CT_DOUBLE, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,double**) } #define CF_STRING_AR(n,p,c) { .type = CT_STRING, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,byte***) } // use the macros above to declare configuration items for arrays of variables +struct clist; +#define CF_PARSER(n,p,f,c) { .type = CT_PARSER, .name = n, .number = c, .ptr = p, .ptr2.par = f } +#define CF_SUB_SECTION(n,p,s) { .type = CT_SUB_SECTION, .name = n, .number = 1, .ptr = p, .ptr2.sub = s } +#define CF_LINK_LIST(n,p,s) { .type = CT_LINK_LIST, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,struct clist*), .ptr2.sub = s } #endif -- 2.39.2