From: Robert Spalek Date: Thu, 20 Apr 2006 10:50:44 +0000 (+0200) Subject: substantially changed the interface again X-Git-Tag: holmes-import~645^2~11^2~106 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=cbc4fc73a664cb0bdc84658989a7a38ad3524004;p=libucw.git substantially changed the interface again I realised that in the last interface I couldn't distinguish between static and dynamic arrays of length exactly 1. thinking about how to resolve the problem led me to a different solution that is as easy to use as before, but easier to implement, easier to extend by new basic types, and as a bonus I get a natural interface for static arrays. I then immediately scratched a duplicate code for parsing dynamic arrays, because it can be easily unified now. also, CF_ITEMS does not expect a parameter now, because they the compiler messes up line numbers when an error occurs. --- diff --git a/lib/conf2-test.c b/lib/conf2-test.c index 8794bf7b..87bf4dc3 100644 --- a/lib/conf2-test.c +++ b/lib/conf2-test.c @@ -14,7 +14,8 @@ struct sub_sect_1 { byte *name; byte *level; - int confidence; + int confidence[2]; + double *list; }; static byte * @@ -22,14 +23,15 @@ init_sec_1(struct sub_sect_1 *s) { s->name = "unknown"; s->level = "default"; - s->confidence = 5; + s->confidence[0] = 5; + s->confidence[1] = 6; return NULL; } static byte * commit_sec_1(struct sub_sect_1 *s) { - if (s->confidence < 0 || s->confidence > 10) + if (s->confidence[0] < 0 || s->confidence[0] > 10) return "Well, this can't be"; return NULL; } @@ -39,22 +41,23 @@ static struct cf_section cf_sec_1 = { CF_INIT(init_sec_1) CF_COMMIT(commit_sec_1) #define F(x) PTR_TO(struct sub_sect_1, x) - CF_ITEMS( + CF_START_ITEMS CF_STRING("name", F(name)) CF_STRING("level", F(level)) - CF_INT("confidence", F(confidence)) - ) + CF_INT_ARY("confidence", F(confidence[0]), 2) // XXX: the [0] is needed for the sake of macros :-( + CF_DOUBLE_DYN("list", F(list), 100) + CF_END_ITEMS #undef F }; static int nr1 = 15; -static int *nrs1 = ARRAY_ALLOC(int, 5, 5, 4, 3, 2, 1); -static int *nrs2; +static int *nrs1 = DYN_ALLOC(int, 5, 5, 4, 3, 2, 1); +static int nrs2[5]; static byte *str1 = "no worries"; -static byte **str2 = ARRAY_ALLOC(byte *, 2, "Alice", "Bob"); +static byte **str2 = DYN_ALLOC(byte *, 2, "Alice", "Bob"); static u64 u1 = 0xCafeBeefDeadC00ll; static double d1 = -1.1; -static struct sub_sect_1 sec1 = { "Charlie", "WBAFC", 0 }; +static struct sub_sect_1 sec1 = { "Charlie", "WBAFC", { 0, -1} }; static struct clist secs; static time_t t1, t2; @@ -73,21 +76,21 @@ time_parser(uns number, byte **pars, time_t *ptr) return NULL; } -static struct cf_section cf_top = { +static struct cf_section cf_top UNUSED = { CF_COMMIT(commit_top) - CF_ITEMS( + CF_START_ITEMS CF_INT("nr1", &nr1) - CF_INT_ARY("nrs1", &nrs1, 5) - CF_INT_ARY("nrs2", &nrs2, -1000) + CF_INT_DYN("nrs1", &nrs1, 1000) + CF_INT_ARY("nrs2", nrs2, 5) CF_STRING("str1", &str1) - CF_STRING_ARY("str2", &str2, 2) + CF_STRING_DYN("str2", &str2, 2) 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_END_ITEMS }; int diff --git a/lib/conf2.c b/lib/conf2.c index 90483d4c..cc95c3d0 100644 --- a/lib/conf2.c +++ b/lib/conf2.c @@ -49,19 +49,13 @@ cf_printf(char *fmt, ...) /* Undo journal */ -static uns journal_active; - -uns -cf_journal_active(uns flag) -{ - uns f = journal_active; - journal_active = flag; - return f; -} +static uns journal_active; // controls whether a call to cf_journal_block() is taken into account void cf_journal_block(void *ptr UNUSED, uns len UNUSED) { + if (!journal_active) + return; } /* Parsers for standard types */ @@ -103,7 +97,7 @@ lookup_unit(byte *value, byte *end, byte **msg) static char cf_rngerr[] = "Number out of range"; static byte * -cf_parse_int(uns number, byte **pars, int *ptr) +parse_int(uns number, byte **pars, int *ptr) { cf_journal_block(ptr, number * sizeof(int)); for (uns i=0; i=0 means exactly k, k<0 means at most -k + int number; // length of an array or #parameters of a parser void *ptr; // pointer to a global variable or an offset in a section union { + enum cf_type type; // type of a static or dynamic attribute struct cf_section *sub; // declaration of a section or a list cf_parser *par; // parser function - } ptr2; + } u; }; struct cf_section { uns size; // 0 for a global block, sizeof(struct) for a section - cf_hook *init; // fills in default values - cf_hook *commit; // verifies parsed data and checks ranges (optional) + cf_hook *init; // fills in default values (otherwise 0's are used) + cf_hook *commit; // verifies parsed data (optional) struct cf_item *cfg; // CT_END-terminated array of items }; @@ -52,28 +64,33 @@ struct cf_section { #define CF_TYPE(s) .size = sizeof(s), #define CF_INIT(f) .init = (cf_hook*) f, #define CF_COMMIT(f) .commit = (cf_hook*) f, -#define CF_ITEMS(i) .cfg = ( struct cf_item[] ) { i { .type = CT_END } }, -/* Configuration items for single variables */ -#define CF_INT(n,p) { .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,int*) }, -#define CF_U64(n,p) { .type = CT_U64, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u64*) }, -#define CF_DOUBLE(n,p) { .type = CT_DOUBLE, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,double*) }, -#define CF_STRING(n,p) { .type = CT_STRING, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,byte**) }, -/* Configuration items for arrays of variables */ -#define CF_INT_ARY(n,p,c) { .type = CT_INT, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,int**) }, -#define CF_U64_ARY(n,p,c) { .type = CT_U64, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,u64**) }, -#define CF_DOUBLE_ARY(n,p,c) { .type = CT_DOUBLE, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,double**) }, -#define CF_STRING_ARY(n,p,c) { .type = CT_STRING, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,byte***) }, - -#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 - -/* Configuration items for sections, lists, and parsed items */ +#define CF_START_ITEMS .cfg = ( struct cf_item[] ) { +#define CF_END_ITEMS { .cls = CC_END } }, +/* Configuration items */ struct clist; -#define CF_PARSER(n,p,f,c) { .type = CT_PARSER, .name = n, .number = c, .ptr = p, .ptr2.par = (cf_parser*) f }, -#define CF_SECTION(n,p,s) { .type = CT_SECTION, .name = n, .number = 1, .ptr = p, .ptr2.sub = s }, -#define CF_LIST(n,p,s) { .type = CT_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,struct clist*), .ptr2.sub = s }, +#define CF_STATIC(n,p,T,t,c) { .cls = CC_STATIC, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,t*), .u.type = CT_##T }, +#define CF_DYNAMIC(n,p,T,t,c) { .cls = CC_DYNAMIC, .name = n, .number = c, .ptr = CHECK_PTR_TYPE(p,t**), .u.type = CT_##T }, +#define CF_PARSER(n,p,f,c) { .cls = CC_PARSER, .name = n, .number = c, .ptr = p, .u.par = (cf_parser*) f }, +#define CF_SECTION(n,p,s) { .cls = CC_SECTION, .name = n, .number = 1, .ptr = p, .u.sub = s }, +#define CF_LIST(n,p,s) { .cls = CC_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,struct clist*), .u.sub = s }, +/* Configuration items for basic types */ +#define CF_INT(n,p) CF_STATIC(n,p,INT,int,1) +#define CF_INT_ARY(n,p,c) CF_STATIC(n,p,INT,int,c) +#define CF_INT_DYN(n,p,c) CF_DYNAMIC(n,p,INT,int,c) +#define CF_U64(n,p) CF_STATIC(n,p,U64,u64,1) +#define CF_U64_ARY(n,p,c) CF_STATIC(n,p,U64,u64,c) +#define CF_U64_DYN(n,p,c) CF_DYNAMIC(n,p,U64,u64,c) +#define CF_DOUBLE(n,p) CF_STATIC(n,p,DOUBLE,double,1) +#define CF_DOUBLE_ARY(n,p,c) CF_STATIC(n,p,DOUBLE,double,c) +#define CF_DOUBLE_DYN(n,p,c) CF_DYNAMIC(n,p,DOUBLE,double,c) +#define CF_STRING(n,p) CF_STATIC(n,p,STRING,byte*,1) +#define CF_STRING_ARY(n,p,c) CF_STATIC(n,p,STRING,byte*,c) +#define CF_STRING_DYN(n,p,c) CF_DYNAMIC(n,p,STRING,byte*,c) + +#define DYN_LEN(a) *(uns*)(a-1) + // length of a dynamic array +#define DYN_ALLOC(type,len,val...) (type[]) { (type)len, ##val } + 1 + // creates a static instance of a dynamic array /* Memory allocation */ void *cf_malloc(uns size); @@ -82,7 +99,6 @@ byte *cf_strdup(byte *s); byte *cf_printf(char *fmt, ...); /* Undo journal for error recovery */ -uns cf_journal_active(uns flag); void cf_journal_block(void *ptr, uns len); #endif