};
static byte *
-init_sec_1(void *ptr)
+init_sec_1(struct sub_sect_1 *s)
{
- struct sub_sect_1 *s = ptr;
s->name = "unknown";
s->level = "default";
s->confidence = 5;
}
static byte *
-commit_sec_1(void *ptr)
+commit_sec_1(struct sub_sect_1 *s)
{
- struct sub_sect_1 *s = ptr;
if (s->confidence < 0 || s->confidence > 10)
return "Well, this can't be";
return NULL;
}
static struct cf_section cf_sec_1 = {
- .size = sizeof(struct sub_sect_1),
- .init = init_sec_1,
- .commit = commit_sec_1,
- .cfg = (struct cf_item[]) {
-#define F(x) CF_FIELD(struct sub_sect_1, x)
- CF_STRING("name", F(name)),
- CF_STRING("level", F(level)),
- CF_INT("confidence", F(confidence)),
- CF_END
+ 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_STRING("level", F(level))
+ CF_INT("confidence", F(confidence))
+ )
#undef F
- }
};
static int nr1 = 15;
}
static byte *
-time_parser(byte *name UNUSED, uns number, byte **pars, void *ptr)
+time_parser(uns number, byte **pars, time_t *ptr)
{
- * (time_t*) ptr = number ? atoi(pars[0]) : time(NULL);
+ *ptr = number ? atoi(pars[0]) : time(NULL);
return NULL;
}
static struct cf_section cf_top = {
- .commit = commit_top,
- .cfg = (struct cf_item []) {
- CF_INT("nr1", &nr1),
- CF_INT_AR("nrs1", &nrs1, 5),
- CF_INT_AR("nrs2", &nrs2, -1000),
- CF_STRING("str1", &str1),
- CF_STRING_AR("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_SUB_SECTION("master", &sec1, &cf_sec_1),
- CF_LINK_LIST("slaves", &secs, &cf_sec_1),
- CF_END
- }
+ CF_COMMIT(commit_top)
+ CF_ITEMS(
+ CF_INT("nr1", &nr1)
+ CF_INT_ARY("nrs1", &nrs1, 5)
+ CF_INT_ARY("nrs2", &nrs2, -1000)
+ CF_STRING("str1", &str1)
+ CF_STRING_ARY("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)
+ )
};
int
* of the GNU Lesser General Public License.
*/
-#ifndef _LIB_CONF2_H
-#define _LIB_CONF2_H
+#ifndef _UCW_CONF2_H
+#define _UCW_CONF2_H
enum cf_type {
CT_END, // end of list
CT_INT, CT_U64, CT_DOUBLE, // number types
CT_STRING, // string type
CT_PARSER, // arbitrary parser function
- CT_SUB_SECTION, // sub-section appears exactly once
- CT_LINK_LIST // link-list with 0..many nodes
+ CT_SECTION, // section appears exactly once
+ CT_LIST // list with 0..many nodes
};
struct cf_section;
typedef byte *cf_hook(void *ptr);
- /* An init- or commit-hook gets a pointer to the sub-section or NULL if this
+ /* An init- or commit-hook gets a pointer to the section or NULL if this
* 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. */
+typedef byte *cf_parser(uns number, byte **pars, void *ptr);
+ /* A parser function 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
- void *ptr; // pointer to a global variable or an offset in a sub-section
+ void *ptr; // pointer to a global variable or an offset in a section
union {
- struct cf_section *sub; // declaration of a sub-section or a link-list
+ struct cf_section *sub; // declaration of a section or a list
cf_parser *par; // parser function
} ptr2;
};
struct cf_section {
- uns size; // 0 for a global block, sizeof(struct) for a sub-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)
struct cf_item *cfg; // CT_END-terminated array of items
};
-#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 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
-#define CF_END { .type = CT_END }
- // please better put this at the end of each section
-#define CF_INT(n,p) { .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,int*) }
-#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**) }
- // 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
+/* Declaration of cf_items */
+#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***) },
+/* Configuration items for sections, lists, and parsed items */
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 }
+#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 },
#endif