2 * UCW Library -- Reading of configuration files
4 * (c) 2006 Robert Spalek <robert@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
14 CT_END, // end of list
15 CT_INT, CT_U64, CT_DOUBLE, // number types
16 CT_STRING, // string type
17 CT_PARSER, // arbitrary parser function
18 CT_SUB_SECTION, // sub-section appears exactly once
19 CT_LINK_LIST // link-list with 0..many nodes
23 typedef byte *cf_hook(void *ptr);
24 /* An init- or commit-hook gets a pointer to the sub-section or NULL if this
25 * is the global section. It returns an error message or NULL if everything
27 typedef byte *cf_parser(byte *name, uns number, byte **pars, void *ptr);
28 /* A parser function gets a name of the attribute and an array of strings,
29 * and stores the parsed value in any way it likes into *ptr. It returns an
30 * error message or NULL if everything is all right. */
35 int number; // number of values: k>=0 means exactly k, k<0 means at most -k
36 void *ptr; // pointer to a global variable or an offset in a sub-section
38 struct cf_section *sub; // declaration of a sub-section or a link-list
39 cf_parser *par; // parser function
44 uns size; // 0 for a global block, sizeof(struct) for a sub-section
45 cf_hook *init; // fills in default values
46 cf_hook *commit; // verifies parsed data and checks ranges (optional)
47 struct cf_item *cfg; // CT_END-terminated array of items
50 #define CHECK_VAR_TYPE(x,type) ((x)-(type)(x) + (type)(x))
51 // for a pointer x it returns x, and performs a compile-time check whether typeof(x)==type
52 #define ARRAY_ALLOC(type,len,val...) (type[]) { (type)len, ##val } + 1
53 // creates an array with an allocated space in the front for the (Pascal-like) length
54 #define ARRAY_LEN(a) *(uns*)(a-1)
55 // length of the array
56 #define CF_FIELD(str,f) &((str*)0)->f
57 // returns a pointer to a field inside a structure suitable for passing as cf_item->ptr
59 #define CF_END { .type = CT_END }
60 // please better put this at the end of each section
61 #define CF_INT(n,p) { .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,int*) }
62 #define CF_U64(n,p) { .type = CT_U64, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,u64*) }
63 #define CF_DOUBLE(n,p) { .type = CT_DOUBLE, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,double*) }
64 #define CF_STRING(n,p) { .type = CT_STRING, .name = n, .number = 1, .ptr = CHECK_VAR_TYPE(p,byte**) }
65 // use the macros above to declare configuration items for single variables
66 #define CF_INT_AR(n,p,c) { .type = CT_INT, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,int**) }
67 #define CF_U64_AR(n,p,c) { .type = CT_U64, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,u64**) }
68 #define CF_DOUBLE_AR(n,p,c) { .type = CT_DOUBLE, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,double**) }
69 #define CF_STRING_AR(n,p,c) { .type = CT_STRING, .name = n, .number = c, .ptr = CHECK_VAR_TYPE(p,byte***) }
70 // use the macros above to declare configuration items for arrays of variables
72 #define CF_PARSER(n,p,f,c) { .type = CT_PARSER, .name = n, .number = c, .ptr = p, .ptr2.par = f }
73 #define CF_SUB_SECTION(n,p,s) { .type = CT_SUB_SECTION, .name = n, .number = 1, .ptr = p, .ptr2.sub = s }
74 #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 }