#define T(x) #x,
byte *cf_op_names[] = { CF_OPERATIONS };
#undef T
+byte *cf_type_names[] = { "int", "u64", "double", "ip", "string", "lookup", "user" };
-#define DARY_HDR_SIZE ALIGN(sizeof(uns), CPU_STRUCT_ALIGN)
+#define DARY_HDR_SIZE ALIGN_TO(sizeof(uns), CPU_STRUCT_ALIGN)
static byte *
interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr)
for (struct cf_item *ci=sec->cfg; ci->cls; ci++)
{
int taken;
- byte *msg = interpret_set_item(ci, number, pars, &taken, ptr + (addr_int_t) ci->ptr, allow_dynamic && !ci[1].cls);
+ byte *msg = interpret_set_item(ci, number, pars, &taken, ptr + (uintptr_t) ci->ptr, allow_dynamic && !ci[1].cls);
if (msg)
return cf_printf("Item %s: %s", ci->name, msg);
*processed += taken;
return NULL;
}
+static byte *
+interpret_add_bitmap(struct cf_item *item, int number, byte **pars, int *processed, u32 *ptr, enum cf_operation op)
+{
+ if (op != OP_SET && op != OP_REMOVE)
+ return cf_printf("Cannot apply operation %s on a bitmap", cf_op_names[op]);
+ else if (item->type != CT_INT && item->type != CT_LOOKUP)
+ return cf_printf("Type %s cannot be used with bitmaps", cf_type_names[item->type]);
+ cf_journal_block(ptr, sizeof(u32));
+ for (int i=0; i<number; i++) {
+ uns idx;
+ if (item->type == CT_INT)
+ TRY( cf_parse_int(pars[i], &idx) );
+ else
+ TRY( cf_parse_lookup(pars[i], &idx, item->u.lookup) );
+ if (idx >= 32)
+ return "Bitmaps only have 32 bits";
+ if (op == OP_SET)
+ *ptr |= 1<<idx;
+ else
+ *ptr &= ~(1<<idx);
+ }
+ *processed = number;
+ return NULL;
+}
+
static byte *
interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic)
{
if (!allow_dynamic)
return "Lists cannot be used here";
return interpret_add_list(item, number, pars, processed, ptr, OP_SET);
+ case CC_BITMAP:
+ if (!allow_dynamic)
+ return "Bitmaps cannot be used here";
+ return interpret_add_bitmap(item, number, pars, processed, ptr, OP_SET);
default:
ASSERT(0);
}
}
static byte *
-interpret_clear(struct cf_item *item, void *ptr)
+interpret_set_all(struct cf_item *item, void *ptr, enum cf_operation op)
{
+ if (item->cls == CC_BITMAP) {
+ cf_journal_block(ptr, sizeof(u32));
+ if (op == OP_CLEAR)
+ * (u32*) ptr = 0;
+ else
+ if (item->type == CT_INT)
+ * (u32*) ptr = ~0u;
+ else {
+ uns nr = -1;
+ while (item->u.lookup[++nr]);
+ * (u32*) ptr = ~0u >> (32-nr);
+ }
+ return NULL;
+ } else if (op != OP_CLEAR)
+ return "The item is not a bitmap";
+
if (item->cls == CC_LIST) {
cf_journal_block(ptr, sizeof(clist));
clist_init(ptr);
cf_journal_block(ptr, item->number * sizeof(byte*));
bzero(ptr, item->number * sizeof(byte*));
} else
- return "The item is not a list, dynamic array, or string";
+ return "The item is not a list, dynamic array, bitmap, or string";
return NULL;
}
cmp_items(void *i1, void *i2, struct cf_item *item)
{
ASSERT(item->cls == CC_STATIC);
- i1 += (addr_int_t) item->ptr;
- i2 += (addr_int_t) item->ptr;
+ i1 += (uintptr_t) item->ptr;
+ i2 += (uintptr_t) item->ptr;
if (item->type == CT_STRING)
return strcmp(* (byte**) i1, * (byte**) i2);
else // all numeric types
{
if (level >= MAX_STACK_SIZE-1)
return "Too many nested sections";
+ enum cf_operation pure_op = op & OP_MASK;
stack[++level] = (struct item_stack) {
.sec = NULL,
.base_ptr = NULL,
- .op = op & OP_MASK,
+ .op = pure_op,
.list = NULL,
.mask = 0,
.item = NULL,
stack[level].sec = item->u.sec;
if (item->cls == CC_SECTION)
{
+ if (pure_op != OP_SET)
+ return "Only SET operation can be used with a section";
stack[level].base_ptr = ptr;
stack[level].op = OP_EDIT | OP_2ND; // this list operation does nothing
}
cf_init_section(item->name, item->u.sec, stack[level].base_ptr, 1);
stack[level].list = ptr;
stack[level].item = item;
- if ((op & OP_MASK) < OP_REMOVE) {
- add_to_list(ptr, stack[level].base_ptr, op & OP_MASK);
+ if (pure_op == OP_ALL)
+ return "Operation ALL cannot be applied on lists";
+ else if (pure_op < OP_REMOVE) {
+ add_to_list(ptr, stack[level].base_ptr, pure_op);
stack[level].op |= OP_2ND;
} else
stack[level].op |= OP_1ST;
*msg = cf_printf("Unknown item %s", name);
return NULL;
}
- *ptr += (addr_int_t) ci->ptr;
+ *ptr += (uintptr_t) ci->ptr;
if (!c)
return ci;
if (ci->cls != CC_SECTION)
return NULL;
op &= OP_MASK;
- int taken; // process as many parameters as possible
- if (op == OP_CLEAR)
- taken = 0, msg = interpret_clear(item, ptr);
+ int taken = 0; // process as many parameters as possible
+ if (op == OP_CLEAR || op == OP_ALL)
+ msg = interpret_set_all(item, ptr, op);
else if (op == OP_SET)
msg = interpret_set_item(item, number, pars, &taken, ptr, 1);
else if (item->cls == CC_DYNAMIC)
msg = interpret_add_dynamic(item, number, pars, &taken, ptr, op);
else if (item->cls == CC_LIST)
msg = interpret_add_list(item, number, pars, &taken, ptr, op);
+ else if (item->cls == CC_BITMAP)
+ msg = interpret_add_bitmap(item, number, pars, &taken, ptr, op);
else
return cf_printf("Operation %s not supported on attribute %s", cf_op_names[op], name);
if (msg)
cf_find_item(byte *name, struct cf_item *item)
{
byte *msg;
- void *ptr;
+ void *ptr = NULL;
struct cf_item *ci = find_item(&cf_sections, name, &msg, &ptr);
if (msg)
return msg;
cf_write_item(struct cf_item *item, enum cf_operation op, int number, byte **pars)
{
byte *msg;
- int taken;
+ int taken = 0;
switch (op) {
case OP_SET:
msg = interpret_set_item(item, number, pars, &taken, item->ptr, 1);
break;
case OP_CLEAR:
- taken = 0;
- msg = interpret_clear(item, item->ptr);
+ case OP_ALL:
+ msg = interpret_set_all(item, item->ptr, op);
break;
case OP_APPEND:
case OP_PREPEND:
else if (item->cls == CC_LIST)
msg = interpret_add_list(item, number, pars, &taken, item->ptr, op);
else
- return "The attribute class does not support append/prepend";
+ return "The attribute does not support append/prepend";
+ break;
+ case OP_REMOVE:
+ if (item->cls == CC_BITMAP)
+ msg = interpret_add_bitmap(item, number, pars, &taken, item->ptr, op);
+ else
+ return "Only applicable on bitmaps";
break;
default:
return "Unsupported operation";