Peter Kjellerstedt at axis.com writes:
No binary (build failed)
—
(log yok)
| @@ -138,10 +138,12 @@ dialog_checklist (const char *title, const char *prompt, int height, int width, | |
| /* Initializes status */ | |
| for (i = 0; i < item_no; i++) { | |
| - | status[i] = items[i]->selected; |
| - | if (!choice && status[i]) |
| - | choice = i; |
| + | status[i] = (items[i]->selected == 1); /* ON */ |
| + | if ((!choice && status[i]) || items[i]->selected == 2) /* SELECTED */ |
| + | choice = i + 1; |
| } | |
| + | if (choice) |
| + | choice--; |
| max_choice = MIN (list_height, item_no); | |
| @@ -303,6 +305,9 @@ dialog_checklist (const char *title, const char *prompt, int height, int width, | |
| case 'H': | |
| case 'h': | |
| case '?': | |
| + | for (i = 0; i < item_no; i++) |
| + | items[i]->selected = 0; |
| + | items[scroll + choice]->selected = 1; |
| delwin (dialog); | |
| free (status); | |
| return 1; | |
| @@ -341,7 +346,11 @@ dialog_checklist (const char *title, const char *prompt, int height, int width, | |
| for (i = 0; i < item_no; i++) { | |
| items[i]->selected = status[i]; | |
| } | |
| - | } |
| + | } else { |
| + | for (i = 0; i < item_no; i++) |
| + | items[i]->selected = 0; |
| + | items[scroll + choice]->selected = 1; |
| + | } |
| delwin (dialog); | |
| free (status); | |
| return button; | |
| @@ -225,6 +225,8 @@ int conf_read(const char *name) | |
| } | |
| fclose(in); | |
| + | if (modules_sym) |
| + | sym_calc_value(modules_sym); |
| for_all_symbols(i, sym) { | |
| sym_calc_value(sym); | |
| if (sym_has_value(sym) && !sym_is_choice_value(sym)) { | |
| @@ -265,8 +267,14 @@ int conf_write(const char *name) | |
| dirname[0] = 0; | |
| if (name && name[0]) { | |
| - | char *slash = strrchr(name, '/'); |
| - | if (slash) { |
| + | struct stat st; |
| + | char *slash; |
| + | |
| + | if (!stat(name, &st) && S_ISDIR(st.st_mode)) { |
| + | strcpy(dirname, name); |
| + | strcat(dirname, "/"); |
| + | basename = conf_def_filename; |
| + | } else if ((slash = strrchr(name, '/'))) { |
| int size = slash - name + 1; | |
| memcpy(dirname, name, size); | |
| dirname[size] = 0; | |
| @@ -10,6 +10,8 @@ | |
| #define LKC_DIRECT_LINK | |
| #include "lkc.h" | |
| + | #define DEBUG_EXPR 0 |
| + | |
| struct expr *expr_alloc_symbol(struct symbol *sym) | |
| { | |
| struct expr *e = malloc(sizeof(*e)); | |
| @@ -220,10 +222,12 @@ int expr_eq(struct expr *e1, struct expr *e2) | |
| /* panic */; | |
| } | |
| - | print_expr(0, e1, 0); |
| - | printf(" = "); |
| - | print_expr(0, e2, 0); |
| - | printf(" ?\n"); |
| + | if (DEBUG_EXPR) { |
| + | expr_fprint(e1, stdout); |
| + | printf(" = "); |
| + | expr_fprint(e2, stdout); |
| + | printf(" ?\n"); |
| + | } |
| return 0; | |
| } | |
| @@ -397,11 +401,13 @@ struct expr *expr_join_or(struct expr *e1, struct expr *e2) | |
| return expr_alloc_symbol(&symbol_yes); | |
| } | |
| - | printf("optimize "); |
| - | print_expr(0, e1, 0); |
| - | printf(" || "); |
| - | print_expr(0, e2, 0); |
| - | printf(" ?\n"); |
| + | if (DEBUG_EXPR) { |
| + | printf("optimize ("); |
| + | expr_fprint(e1, stdout); |
| + | printf(") || ("); |
| + | expr_fprint(e2, stdout); |
| + | printf(")?\n"); |
| + | } |
| return NULL; | |
| } | |
| @@ -444,6 +450,11 @@ struct expr *expr_join_and(struct expr *e1, struct expr *e2) | |
| // (a) && (a!='n') -> (a) | |
| return expr_alloc_symbol(sym1); | |
| + | if ((e1->type == E_SYMBOL && e2->type == E_UNEQUAL && e2->right.sym == &symbol_mod) || |
| + | (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_mod)) |
| + | // (a) && (a!='m') -> (a='y') |
| + | return expr_alloc_comp(E_EQUAL, sym1, &symbol_yes); |
| + | |
| if (sym1->type == S_TRISTATE) { | |
| if (e1->type == E_EQUAL && e2->type == E_UNEQUAL) { | |
| // (a='b') && (a!='c') -> 'b'='c' ? 'n' : a='b' | |
| @@ -483,11 +494,14 @@ struct expr *expr_join_and(struct expr *e1, struct expr *e2) | |
| (e2->type == E_SYMBOL && e1->type == E_UNEQUAL && e1->right.sym == &symbol_yes)) | |
| return NULL; | |
| } | |
| - | printf("optimize "); |
| - | print_expr(0, e1, 0); |
| - | printf(" && "); |
| - | print_expr(0, e2, 0); |
| - | printf(" ?\n"); |
| + | |
| + | if (DEBUG_EXPR) { |
| + | printf("optimize ("); |
| + | expr_fprint(e1, stdout); |
| + | printf(") && ("); |
| + | expr_fprint(e2, stdout); |
| + | printf(")?\n"); |
| + | } |
| return NULL; | |
| } | |
| @@ -1073,11 +1087,3 @@ void expr_fprint(struct expr *e, FILE *out) | |
| { | |
| expr_print(e, expr_print_file_helper, out, E_NONE); | |
| } | |
| - | |
| - | void print_expr(int mask, struct expr *e, int prevtoken) |
| - | { |
| - | if (!(cdebug & mask)) |
| - | return; |
| - | expr_fprint(e, stdout); |
| - | } |
| - | |
| @@ -174,7 +174,6 @@ void expr_extract_eq(enum expr_type type, struct expr **ep, struct expr **ep1, s | |
| struct expr *expr_trans_compare(struct expr *e, enum expr_type type, struct symbol *sym); | |
| void expr_fprint(struct expr *e, FILE *out); | |
| - | void print_expr(int mask, struct expr *e, int prevtoken); |
| static inline int expr_is_yes(struct expr *e) | |
| { | |
| @@ -515,9 +515,9 @@ static void conf_choice(struct menu *menu) | |
| struct menu *child; | |
| struct symbol *active; | |
| + | active = sym_get_choice_value(menu->sym); |
| while (1) { | |
| current_menu = menu; | |
| - | active = sym_get_choice_value(menu->sym); |
| cdone(); cinit(); | |
| for (child = menu->list; child; child = child->next) { | |
| if (!menu_is_visible(child)) | |
| @@ -525,19 +525,28 @@ static void conf_choice(struct menu *menu) | |
| cmake(); | |
| cprint_tag("%p", child); | |
| cprint_name("%s", menu_get_prompt(child)); | |
| - | items[item_no - 1]->selected = (child->sym == active); |
| + | if (child->sym == sym_get_choice_value(menu->sym)) |
| + | items[item_no - 1]->selected = 1; /* ON */ |
| + | else if (child->sym == active) |
| + | items[item_no - 1]->selected = 2; /* SELECTED */ |
| + | else |
| + | items[item_no - 1]->selected = 0; /* OFF */ |
| } | |
| switch (dialog_checklist(prompt ? prompt : "Main Menu", | |
| radiolist_instructions, 15, 70, 6, | |
| item_no, items, FLAG_RADIO)) { | |
| case 0: | |
| - | if (sscanf(first_sel_item(item_no, items)->tag, "%p", &menu) != 1) |
| + | if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) != 1) |
| break; | |
| - | sym_set_tristate_value(menu->sym, yes); |
| + | sym_set_tristate_value(child->sym, yes); |
| return; | |
| case 1: | |
| - | show_help(menu); |
| + | if (sscanf(first_sel_item(item_no, items)->tag, "%p", &child) == 1) { |
| + | show_help(child); |
| + | active = child->sym; |
| + | } else |
| + | show_help(menu); |
| break; | |
| case 255: | |
| return; | |
| @@ -16,6 +16,26 @@ static struct menu **last_entry_ptr; | |
| struct file *file_list; | |
| struct file *current_file; | |
| + | static void menu_warn(struct menu *menu, const char *fmt, ...) |
| + | { |
| + | va_list ap; |
| + | va_start(ap, fmt); |
| + | fprintf(stderr, "%s:%d:warning: ", menu->file->name, menu->lineno); |
| + | vfprintf(stderr, fmt, ap); |
| + | fprintf(stderr, "\n"); |
| + | va_end(ap); |
| + | } |
| + | |
| + | static void prop_warn(struct property *prop, const char *fmt, ...) |
| + | { |
| + | va_list ap; |
| + | va_start(ap, fmt); |
| + | fprintf(stderr, "%s:%d:warning: ", prop->file->name, prop->lineno); |
| + | vfprintf(stderr, fmt, ap); |
| + | fprintf(stderr, "\n"); |
| + | va_end(ap); |
| + | } |
| + | |
| void menu_init(void) | |
| { | |
| current_entry = current_menu = &rootmenu; | |
| @@ -94,9 +114,9 @@ void menu_set_type(int type) | |
| sym->type = type; | |
| return; | |
| } | |
| - | fprintf(stderr, "%s:%d:warning: type of '%s' redefined from '%s' to '%s'\n", |
| - | current_entry->file->name, current_entry->lineno, |
| - | sym->name ? sym->name : "<choice>", sym_type_name(sym->type), sym_type_name(type)); |
| + | menu_warn(current_entry, "type of '%s' redefined from '%s' to '%s'\n", |
| + | sym->name ? sym->name : "<choice>", |
| + | sym_type_name(sym->type), sym_type_name(type)); |
| } | |
| struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *expr, struct expr *dep) | |
| @@ -110,8 +130,7 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e | |
| if (prompt) { | |
| if (current_entry->prompt) | |
| - | fprintf(stderr, "%s:%d: prompt redefined\n", |
| - | current_entry->file->name, current_entry->lineno); |
| + | menu_warn(current_entry, "prompt redefined\n"); |
| current_entry->prompt = prop; | |
| } | |
| @@ -133,6 +152,50 @@ void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep) | |
| menu_add_prop(type, NULL, expr_alloc_symbol(sym), dep); | |
| } | |
| + | void sym_check_prop(struct symbol *sym) |
| + | { |
| + | struct property *prop; |
| + | struct symbol *sym2; |
| + | for (prop = sym->prop; prop; prop = prop->next) { |
| + | switch (prop->type) { |
| + | case P_DEFAULT: |
| + | if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && |
| + | prop->expr->type != E_SYMBOL) |
| + | prop_warn(prop, |
| + | "default for config symbol '%'" |
| + | " must be a single symbol", sym->name); |
| + | break; |
| + | case P_SELECT: |
| + | sym2 = prop_get_symbol(prop); |
| + | if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE) |
| + | prop_warn(prop, |
| + | "config symbol '%s' uses select, but is " |
| + | "not boolean or tristate", sym->name); |
| + | else if (sym2->type == S_UNKNOWN) |
| + | prop_warn(prop, |
| + | "'select' used by config symbol '%s' " |
| + | "refer to undefined symbol '%s'", |
| + | sym->name, sym2->name); |
| + | else if (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE) |
| + | prop_warn(prop, |
| + | "'%s' has wrong type. 'select' only " |
| + | "accept arguments of boolean and " |
| + | "tristate type", sym2->name); |
| + | break; |
| + | case P_RANGE: |
| + | if (sym->type != S_INT && sym->type != S_HEX) |
| + | prop_warn(prop, "range is only allowed " |
| + | "for int or hex symbols"); |
| + | if (!sym_string_valid(sym, prop->expr->left.sym->name) || |
| + | !sym_string_valid(sym, prop->expr->right.sym->name)) |
| + | prop_warn(prop, "range is invalid"); |
| + | break; |
| + | default: |
| + | ; |
| + | } |
| + | } |
| + | } |
| + | |
| void menu_finalize(struct menu *parent) | |
| { | |
| struct menu *menu, *last_menu; | |
| @@ -222,17 +285,16 @@ void menu_finalize(struct menu *parent) | |
| if (sym && sym_is_choice(sym) && menu->sym) { | |
| menu->sym->flags |= SYMBOL_CHOICEVAL; | |
| if (!menu->prompt) | |
| - | fprintf(stderr, "%s:%d:warning: choice value must have a prompt\n", |
| - | menu->file->name, menu->lineno); |
| + | menu_warn(menu, "choice value must have a prompt"); |
| for (prop = menu->sym->prop; prop; prop = prop->next) { | |
| if (prop->type == P_PROMPT && prop->menu != menu) { | |
| - | fprintf(stderr, "%s:%d:warning: choice values currently only support a single prompt\n", |
| - | prop->file->name, prop->lineno); |
| - | |
| + | prop_warn(prop, "choice values " |
| + | "currently only support a " |
| + | "single prompt"); |
| } | |
| if (prop->type == P_DEFAULT) | |
| - | fprintf(stderr, "%s:%d:warning: defaults for choice values not supported\n", |
| - | prop->file->name, prop->lineno); |
| + | prop_warn(prop, "defaults for choice " |
| + | "values not supported"); |
| } | |
| current_entry = menu; | |
| menu_set_type(sym->type); | |
| @@ -256,43 +318,15 @@ void menu_finalize(struct menu *parent) | |
| } | |
| if (sym && !(sym->flags & SYMBOL_WARNED)) { | |
| - | struct symbol *sym2; |
| if (sym->type == S_UNKNOWN) | |
| - | fprintf(stderr, "%s:%d:warning: config symbol defined without type\n", |
| - | parent->file->name, parent->lineno); |
| + | menu_warn(parent, "config symbol defined " |
| + | "without type\n"); |
| if (sym_is_choice(sym) && !parent->prompt) | |
| - | fprintf(stderr, "%s:%d:warning: choice must have a prompt\n", |
| - | parent->file->name, parent->lineno); |
| - | |
| - | for (prop = sym->prop; prop; prop = prop->next) { |
| - | switch (prop->type) { |
| - | case P_DEFAULT: |
| - | if ((sym->type == S_STRING || sym->type == S_INT || sym->type == S_HEX) && |
| - | prop->expr->type != E_SYMBOL) |
| - | fprintf(stderr, "%s:%d:warning: default must be a single symbol\n", |
| - | prop->file->name, prop->lineno); |
| - | break; |
| - | case P_SELECT: |
| - | sym2 = prop_get_symbol(prop); |
| - | if ((sym->type != S_BOOLEAN && sym->type != S_TRISTATE) || |
| - | (sym2->type != S_BOOLEAN && sym2->type != S_TRISTATE)) |
| - | fprintf(stderr, "%s:%d:warning: enable is only allowed with boolean and tristate symbols\n", |
| - | prop->file->name, prop->lineno); |
| - | break; |
| - | case P_RANGE: |
| - | if (sym->type != S_INT && sym->type != S_HEX) |
| - | fprintf(stderr, "%s:%d:warning: range is only allowed for int or hex symbols\n", |
| - | prop->file->name, prop->lineno); |
| - | if (!sym_string_valid(sym, prop->expr->left.sym->name) || |
| - | !sym_string_valid(sym, prop->expr->right.sym->name)) |
| - | fprintf(stderr, "%s:%d:warning: range is invalid\n", |
| - | prop->file->name, prop->lineno); |
| - | break; |
| - | default: |
| - | ; |
| - | } |
| - | } |
| + | menu_warn(parent, "choice must have a prompt\n"); |
| + | |
| + | /* Check properties connected to this symbol */ |
| + | sym_check_prop(sym); |
| sym->flags |= SYMBOL_WARNED; | |
| } | |
| @@ -12,25 +12,26 @@ | |
| #include "lkc.h" | |
| struct symbol symbol_yes = { | |
| - | name: "y", |
| - | curr: { "y", yes }, |
| - | flags: SYMBOL_YES|SYMBOL_VALID, |
| + | .name = "y", |
| + | .curr = { "y", yes }, |
| + | .flags = SYMBOL_YES|SYMBOL_VALID, |
| }, symbol_mod = { | |
| - | name: "m", |
| - | curr: { "m", mod }, |
| - | flags: SYMBOL_MOD|SYMBOL_VALID, |
| + | .name = "m", |
| + | .curr = { "m", mod }, |
| + | .flags = SYMBOL_MOD|SYMBOL_VALID, |
| }, symbol_no = { | |
| - | name: "n", |
| - | curr: { "n", no }, |
| - | flags: SYMBOL_NO|SYMBOL_VALID, |
| + | .name = "n", |
| + | .curr = { "n", no }, |
| + | .flags = SYMBOL_NO|SYMBOL_VALID, |
| }, symbol_empty = { | |
| - | name: "", |
| - | curr: { "", no }, |
| - | flags: SYMBOL_VALID, |
| + | .name = "", |
| + | .curr = { "", no }, |
| + | .flags = SYMBOL_VALID, |
| }; | |
| int sym_change_count; | |
| struct symbol *modules_sym; | |
| + | tristate modules_val; |
| void sym_add_default(struct symbol *sym, const char *def) | |
| { | |
| @@ -72,11 +73,8 @@ enum symbol_type sym_get_type(struct symbol *sym) | |
| if (type == S_TRISTATE) { | |
| if (sym_is_choice_value(sym) && sym->visible == yes) | |
| type = S_BOOLEAN; | |
| - | else { |
| - | sym_calc_value(modules_sym); |
| - | if (modules_sym->curr.tri == no) |
| - | type = S_BOOLEAN; |
| - | } |
| + | else if (modules_val == no) |
| + | type = S_BOOLEAN; |
| } | |
| return type; | |
| } | |
| @@ -146,6 +144,8 @@ static void sym_calc_visibility(struct symbol *sym) | |
| prop->visible.tri = expr_calc_value(prop->visible.expr); | |
| tri = E_OR(tri, prop->visible.tri); | |
| } | |
| + | if (tri == mod && (sym->type != S_TRISTATE || modules_val == no)) |
| + | tri = yes; |
| if (sym->visible != tri) { | |
| sym->visible = tri; | |
| sym_set_changed(sym); | |
| @@ -155,6 +155,8 @@ static void sym_calc_visibility(struct symbol *sym) | |
| tri = no; | |
| if (sym->rev_dep.expr) | |
| tri = expr_calc_value(sym->rev_dep.expr); | |
| + | if (tri == mod && sym_get_type(sym) == S_BOOLEAN) |
| + | tri = yes; |
| if (sym->rev_dep.tri != tri) { | |
| sym->rev_dep.tri = tri; | |
| sym_set_changed(sym); | |
| @@ -261,14 +263,8 @@ void sym_calc_value(struct symbol *sym) | |
| newval.tri = expr_calc_value(prop->expr); | |
| } | |
| } | |
| - | if (sym_get_type(sym) == S_BOOLEAN) { |
| - | if (newval.tri == mod) |
| - | newval.tri = yes; |
| - | if (sym->visible == mod) |
| - | sym->visible = yes; |
| - | if (sym->rev_dep.tri == mod) |
| - | sym->rev_dep.tri = yes; |
| - | } |
| + | if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN) |
| + | newval.tri = yes; |
| break; | |
| case S_STRING: | |
| case S_HEX: | |
| @@ -300,6 +296,8 @@ void sym_calc_value(struct symbol *sym) | |
| if (memcmp(&oldval, &sym->curr, sizeof(oldval))) | |
| sym_set_changed(sym); | |
| + | if (modules_sym == sym) |
| + | modules_val = modules_sym->curr.tri; |
| if (sym_is_choice(sym)) { | |
| int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE); | |
| @@ -320,6 +318,8 @@ void sym_clear_all_valid(void) | |
| for_all_symbols(i, sym) | |
| sym->flags &= ~SYMBOL_VALID; | |
| sym_change_count++; | |
| + | if (modules_sym) |
| + | sym_calc_value(modules_sym); |
| } | |
| void sym_set_changed(struct symbol *sym) | |
| @@ -699,7 +699,7 @@ struct symbol *sym_check_deps(struct symbol *sym) | |
| goto out; | |
| for (prop = sym->prop; prop; prop = prop->next) { | |
| - | if (prop->type == P_CHOICE) |
| + | if (prop->type == P_CHOICE || prop->type == P_SELECT) |
| continue; | |
| sym2 = sym_check_expr_deps(prop->visible.expr); | |
| if (sym2) | |
| @@ -27,8 +27,8 @@ static void print_line (WINDOW * win, int row, int width); | |
| static char *get_line (void); | |
| static void print_position (WINDOW * win, int height, int width); | |
| - | static int hscroll = 0, fd, file_size, bytes_read; |
| - | static int begin_reached = 1, end_reached = 0, page_length; |
| + | static int hscroll, fd, file_size, bytes_read; |
| + | static int begin_reached = 1, end_reached, page_length; |
| static char *buf, *page; | |
| /* | |
| @@ -348,7 +348,7 @@ first_alpha(const char *string, const char *exempt) | |
| c = tolower(string[i]); | |
| if (strchr("<[(", c)) ++in_paren; | |
| - | if (strchr(">])", c)) --in_paren; |
| + | if (strchr(">])", c) && in_paren > 0) --in_paren; |
| if ((! in_paren) && isalpha(c) && | |
| strchr(exempt, c) == 0) | |