CC_DYNAMIC, // dynamically allocated array
CC_PARSER, // arbitrary parser function
CC_SECTION, // section appears exactly once
- CC_LIST // list with 0..many nodes
+ CC_LIST, // list with 0..many nodes
+ CC_BITMAP // of up to 32 items
};
enum cf_type {
#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.sec = s }
#define CF_LIST(n,p,s) { .cls = CC_LIST, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,clist*), .u.sec = s }
+#define CF_BITMAP_INT(n,p) { .cls = CC_BITMAP, .type = CT_INT, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*) }
+#define CF_BITMAP_LOOKUP(n,p,t) { .cls = CC_BITMAP, .type = CT_LOOKUP, .name = n, .number = 1, .ptr = CHECK_PTR_TYPE(p,u32*), .u.lookup = t }
/* 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_USER(n,p,t) { .cls = CC_STATIC, .type = CT_USER, .name = n, .number = 1, .ptr = p, .u.utype = t }
#define CF_USER_ARY(n,p,t,c) { .cls = CC_STATIC, .type = CT_USER, .name = n, .number = c, .ptr = p, .u.utype = t }
#define CF_USER_DYN(n,p,t,c) { .cls = CC_DYNAMIC, .type = CT_USER, .name = n, .number = c, .ptr = p, .u.utype = t }
- // Beware that CF_USER_DYN can only be used on user-defined types of size at least 4
/* If you aren't picky about the number of parameters */
#define CF_ANY_NUM -0x7fffffff
-#define DARY_LEN(a) *(uns*)(a-1)
+#define DARY_LEN(a) ((uns*)a)[-1]
// length of a dynamic array
-#define DARY_ALLOC(type,len,val...) (type[]) { (type)len, ##val } + 1
- // creates a static instance of a dynamic array, works only for integer and pointer types
+#define DARY_ALLOC(type,len,val...) ((struct { uns l; type a[len]; }) { .l = len, .a = { val } }).a
+ // creates a static instance of a dynamic array
/* Memory allocation: conf-alloc.c */
struct mempool;