X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Fconf-intr.c;h=84f555a29962cc5d3a809c9b863f6357ab8cdbdc;hb=df7c847391ff2bf5b58893932d998181192713a3;hp=cd015bd2282f2be8f4f386ebb6dc5f2e2d02fe4d;hpb=ce0e823dc4cdb520f63eca96a122896917a49e56;p=libucw.git diff --git a/lib/conf-intr.c b/lib/conf-intr.c index cd015bd2..84f555a2 100644 --- a/lib/conf-intr.c +++ b/lib/conf-intr.c @@ -17,18 +17,18 @@ #include #include -#define TRY(f) do { byte *_msg = f; if (_msg) return _msg; } while (0) +#define TRY(f) do { char *_msg = f; if (_msg) return _msg; } while (0) /* Register size of and parser for each basic type */ -static byte * -cf_parse_string(byte *str, byte **ptr) +static char * +cf_parse_string(char *str, char **ptr) { *ptr = cf_strdup(str); return NULL; } -typedef byte *cf_basic_parser(byte *str, void *ptr); +typedef char *cf_basic_parser(char *str, void *ptr); static struct { uns size; void *parser; @@ -37,7 +37,7 @@ static struct { { sizeof(u64), cf_parse_u64 }, { sizeof(double), cf_parse_double }, { sizeof(u32), cf_parse_ip }, - { sizeof(byte*), cf_parse_string }, + { sizeof(char*), cf_parse_string }, { sizeof(int), NULL }, // lookups are parsed extra { 0, NULL }, // user-defined types are parsed extra }; @@ -51,10 +51,10 @@ cf_type_size(enum cf_type type, struct cf_user_type *utype) return utype->size; } -static byte * -cf_parse_lookup(byte *str, int *ptr, byte **t) +static char * +cf_parse_lookup(char *str, int *ptr, char **t) { - byte **n = t; + char **n = t; uns total_len = 0; while (*n && strcasecmp(*n, str)) { total_len += strlen(*n) + 2; @@ -64,7 +64,7 @@ cf_parse_lookup(byte *str, int *ptr, byte **t) *ptr = n - t; return NULL; } - byte *err = cf_malloc(total_len + strlen(str) + 60), *c = err; + char *err = cf_malloc(total_len + strlen(str) + 60), *c = err; c += sprintf(err, "Invalid value %s, possible values are: ", str); for (n=t; *n; n++) c+= sprintf(c, "%s, ", *n); @@ -74,12 +74,12 @@ cf_parse_lookup(byte *str, int *ptr, byte **t) return err; } -static byte * -cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type, union cf_union *u) +static char * +cf_parse_ary(uns number, char **pars, void *ptr, enum cf_type type, union cf_union *u) { for (uns i=0; iutype); if (type < CT_LOOKUP) msg = ((cf_basic_parser*) parsers[type].parser) (pars[i], ptr + i * size); @@ -98,13 +98,14 @@ cf_parse_ary(uns number, byte **pars, void *ptr, enum cf_type type, union cf_uni /* Interpreter */ #define T(x) #x, -byte *cf_op_names[] = { CF_OPERATIONS }; +char *cf_op_names[] = { CF_OPERATIONS }; #undef T +char *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) +static char * +interpret_set_dynamic(struct cf_item *item, int number, char **pars, void **ptr) { enum cf_type type = item->type; cf_journal_block(ptr, sizeof(void*)); @@ -115,8 +116,8 @@ interpret_set_dynamic(struct cf_item *item, int number, byte **pars, void **ptr) return cf_parse_ary(number, pars, *ptr, type, &item->u); } -static byte * -interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *processed, void **ptr, enum cf_operation op) +static char * +interpret_add_dynamic(struct cf_item *item, int number, char **pars, int *processed, void **ptr, enum cf_operation op) { enum cf_type type = item->type; void *old_p = *ptr; @@ -140,17 +141,17 @@ interpret_add_dynamic(struct cf_item *item, int number, byte **pars, int *proces return cf_printf("Dynamic arrays do not support operation %s", cf_op_names[op]); } -static byte *interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic); +static char *interpret_set_item(struct cf_item *item, int number, char **pars, int *processed, void *ptr, uns allow_dynamic); -static byte * -interpret_section(struct cf_section *sec, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic) +static char * +interpret_section(struct cf_section *sec, int number, char **pars, int *processed, void *ptr, uns allow_dynamic) { cf_add_dirty(sec, ptr); *processed = 0; 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); + char *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; @@ -193,8 +194,8 @@ add_to_list(cnode *where, cnode *new_node, enum cf_operation op) } } -static byte * -interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, enum cf_operation op) +static char * +interpret_add_list(struct cf_item *item, int number, char **pars, int *processed, void *ptr, enum cf_operation op) { if (op >= OP_REMOVE) return cf_printf("You have to open a block for operation %s", cf_op_names[op]); @@ -212,7 +213,7 @@ interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed /* If the node contains any dynamic attribute at the end, we suppress * auto-repetition here and pass the flag inside instead. */ index++; - byte *msg = interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC); + char *msg = interpret_section(sec, number, pars, &taken, node, sec->flags & SEC_FLAG_DYNAMIC); if (msg) return sec->flags & SEC_FLAG_DYNAMIC ? msg : cf_printf("Node %d of list %s: %s", index, item->name, msg); *processed += taken; @@ -224,8 +225,33 @@ interpret_add_list(struct cf_item *item, int number, byte **pars, int *processed return NULL; } -static byte * -interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed, void *ptr, uns allow_dynamic) +static char * +interpret_add_bitmap(struct cf_item *item, int number, char **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; itype == 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<cls) @@ -260,14 +286,34 @@ interpret_set_item(struct cf_item *item, int number, byte **pars, int *processed 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) +static char * +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); @@ -276,10 +322,10 @@ interpret_clear(struct cf_item *item, void *ptr) static uns zero = 0; * (void**) ptr = (&zero) + 1; } else if (item->cls == CC_STATIC && item->type == CT_STRING) { - cf_journal_block(ptr, item->number * sizeof(byte*)); - bzero(ptr, item->number * sizeof(byte*)); + cf_journal_block(ptr, item->number * sizeof(char*)); + bzero(ptr, item->number * sizeof(char*)); } 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; } @@ -287,10 +333,10 @@ static int 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); + return strcmp(* (char**) i1, * (char**) i2); else // all numeric types return memcmp(i1, i2, cf_type_size(item->type, item->u.utype)); } @@ -314,7 +360,7 @@ find_list_node(clist *list, void *query, struct cf_section *sec, u32 mask) return NULL; } -static byte * +static char * record_selector(struct cf_item *item, struct cf_section *sec, u32 *mask) { uns nr = sec->flags & SEC_FLAG_NUMBER; @@ -341,15 +387,16 @@ static struct item_stack { } stack[MAX_STACK_SIZE]; static uns level; -static byte * +static char * opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) { 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, @@ -359,6 +406,8 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) 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 } @@ -368,8 +417,10 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) 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; @@ -379,8 +430,8 @@ opening_brace(struct cf_item *item, void *ptr, enum cf_operation op) return NULL; } -static byte * -closing_brace(struct item_stack *st, enum cf_operation op, int number, byte **pars) +static char * +closing_brace(struct item_stack *st, enum cf_operation op, int number, char **pars) { if (st->op == OP_CLOSE) // top-level return "Unmatched } parenthesis"; @@ -432,7 +483,7 @@ closing_brace(struct item_stack *st, enum cf_operation op, int number, byte **pa } static struct cf_item * -find_item(struct cf_section *curr_sec, byte *name, byte **msg, void **ptr) +find_item(struct cf_section *curr_sec, const char *name, char **msg, void **ptr) { *msg = NULL; if (name[0] == '^') // absolute name instead of relative @@ -443,7 +494,7 @@ find_item(struct cf_section *curr_sec, byte *name, byte **msg, void **ptr) { if (curr_sec != &cf_sections) cf_add_dirty(curr_sec, *ptr); - byte *c = strchr(name, '.'); + char *c = strchr(name, '.'); if (c) *c++ = 0; struct cf_item *ci = cf_find_subitem(curr_sec, name); @@ -453,7 +504,7 @@ find_item(struct cf_section *curr_sec, byte *name, byte **msg, void **ptr) *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) @@ -466,10 +517,10 @@ find_item(struct cf_section *curr_sec, byte *name, byte **msg, void **ptr) } } -byte * -cf_interpret_line(byte *name, enum cf_operation op, int number, byte **pars) +char * +cf_interpret_line(char *name, enum cf_operation op, int number, char **pars) { - byte *msg; + char *msg; if ((op & OP_MASK) == OP_CLOSE) return closing_brace(stack+level, op, number, pars); void *ptr = stack[level].base_ptr; @@ -487,15 +538,17 @@ cf_interpret_line(byte *name, enum cf_operation op, int number, byte **pars) 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) @@ -506,11 +559,11 @@ cf_interpret_line(byte *name, enum cf_operation op, int number, byte **pars) return NULL; } -byte * -cf_find_item(byte *name, struct cf_item *item) +char * +cf_find_item(const char *name, struct cf_item *item) { - byte *msg; - void *ptr; + char *msg; + void *ptr = NULL; struct cf_item *ci = find_item(&cf_sections, name, &msg, &ptr); if (msg) return msg; @@ -522,18 +575,18 @@ cf_find_item(byte *name, struct cf_item *item) return NULL; } -byte * -cf_write_item(struct cf_item *item, enum cf_operation op, int number, byte **pars) +char * +cf_write_item(struct cf_item *item, enum cf_operation op, int number, char **pars) { - byte *msg; - int taken; + char *msg; + 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: @@ -542,7 +595,13 @@ cf_write_item(struct cf_item *item, enum cf_operation op, int number, byte **par 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"; @@ -578,7 +637,7 @@ int cf_check_stack(void) { if (level > 0) { - log(L_ERROR, "Unterminated block"); + msg(L_ERROR, "Unterminated block"); return 1; } return 0;