struct sub_sect_1 {
struct cnode n;
byte *name;
+ time_t t;
byte *level;
int confidence[2];
double *list;
};
-static struct sub_sect_1 sec1 = { {}, "Charlie", "WBAFC", { 0, -1}, DARY_ALLOC(double, 3, 1e4, -1e-4, 8) };
+static struct sub_sect_1 sec1 = { {}, "Charlie", 0, "WBAFC", { 0, -1}, DARY_ALLOC(double, 3, 1e4, -1e-4, 8) };
static byte *
init_sec_1(struct sub_sect_1 *s)
return NULL;
}
+static byte *
+time_parser(uns number, byte **pars, time_t *ptr)
+{
+ *ptr = number ? atoi(pars[0]) : time(NULL);
+ return NULL;
+}
+
static struct cf_section cf_sec_1 = {
CF_TYPE(struct sub_sect_1),
CF_INIT(init_sec_1),
#define F(x) PTR_TO(struct sub_sect_1, x)
CF_ITEMS {
CF_STRING("name", F(name)),
+ //CF_PARSER("t", F(t), time_parser, 0),
CF_STRING("level", F(level)),
CF_INT_ARY("confidence", F(confidence[0]), 2), // XXX: the [0] is needed for the sake of type checking
CF_DOUBLE_DYN("list", F(list), 100),
return NULL;
}
-static byte *
-time_parser(uns number, byte **pars, time_t *ptr)
-{
- *ptr = number ? atoi(pars[0]) : time(NULL);
- return NULL;
-}
-
static byte *alphabet[] = { "alpha", "beta", "gamma", "delta", NULL };
static struct cf_section cf_top = {
CF_INIT(init_top),
#define SEC_FLAG_DYNAMIC 0x80000000 // contains a dynamic attribute
#define SEC_FLAG_UNKNOWN 0x40000000 // ignore unknown entriies
+#define SEC_FLAG_CANT_DUPLICATE 0x20000000 // contains lists or parsers
#define SEC_FLAG_NUMBER 0x0fffffff // number of entries
static struct cf_section sections; // root section
for (ci=sec->cfg; ci->cls; ci++)
if (ci->cls == CC_SECTION) {
inspect_section(ci->u.sec);
- sec->flags |= ci->u.sec->flags & SEC_FLAG_DYNAMIC;
+ sec->flags |= ci->u.sec->flags & (SEC_FLAG_DYNAMIC | SEC_FLAG_CANT_DUPLICATE);
} else if (ci->cls == CC_LIST) {
inspect_section(ci->u.sec);
+ sec->flags |= SEC_FLAG_DYNAMIC | SEC_FLAG_CANT_DUPLICATE;
+ } else if (ci->cls == CC_DYNAMIC)
sec->flags |= SEC_FLAG_DYNAMIC;
- } else if (ci->cls == CC_DYNAMIC || ci->cls == CC_PARSER && ci->number < 0)
- sec->flags |= SEC_FLAG_DYNAMIC;
+ else if (ci->cls == CC_PARSER) {
+ sec->flags |= SEC_FLAG_CANT_DUPLICATE;
+ if (ci->number < 0)
+ sec->flags |= SEC_FLAG_DYNAMIC;
+ }
sec->flags |= ci - sec->cfg; // record the number of entries
}
break;
case OP_AFTER: // implementation dependend (prepend_head = after(list)), and where==list, see clists.h:74
case OP_PREPEND:
+ case OP_DUPLICATE:
cf_journal_block(&where->next->prev, sizeof(void*));
cf_journal_block(&where->next, sizeof(void*));
clist_insert_after(new_node, where);
st->base_ptr = st->list;
else if (pure_op == OP_AFTER || pure_op == OP_BEFORE)
cf_init_section(st->item->name, st->sec, st->base_ptr, 1);
- else
+ else if (pure_op == OP_DUPLICATE) {
+ if (st->sec->flags & SEC_FLAG_CANT_DUPLICATE)
+ return cf_printf("Item %s cannot be duplicated", st->item->name);
+ memcpy(st->base_ptr, st->list, st->sec->size); // strings and dynamic arrays are shared
+ } else
ASSERT(0);
if (op & OP_OPEN) { // stay at the same recursion level
st->op = (st->op | OP_2ND) & ~OP_1ST;
case 'r': op = OP_REMOVE; break;
case 'e': op = OP_EDIT; break;
case 'b': op = OP_BEFORE; break;
+ case 'd': op = OP_DUPLICATE; break;
default: op = OP_SET; break;
}
if (strcasecmp(c, op_names[op])) {
/* Direct access to configuration items */
#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(APPEND) T(PREPEND) \
- T(REMOVE) T(EDIT) T(AFTER) T(BEFORE)
+ T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(DUPLICATE)
/* Closing brace finishes previous block.
* Basic attributes (static, dynamic, parsed) can be used with SET.
* Dynamic arrays can be used with SET, APPEND, PREPEND.