struct feature_selection *collapse_tree(struct id3_node *current,struct feature_selection **head){ struct feature_selection *n; if(!current->feature) return NULL; if(!head) { head=malloc(sizeof(struct feature_selection *)); *head=malloc(sizeof(struct feature_selection)); (*head)->feature=current->feature; (*head)->next=NULL; } if(current->child_no_evidence){ for(n=(*head);n!=NULL;n=n->next){ if (n->feature==current->child_no_evidence->feature) goto found1; } n=malloc(sizeof(struct feature_selection)); n->next=*head; n->feature=current->child_no_evidence->feature; *head=n; found1: collapse_tree(current->child_no_evidence,head); } if(current->child_evidence){ for(n=*head;n!=NULL;n=n->next){ if (n->feature==current->child_evidence->feature) goto found2; } n=malloc(sizeof(struct feature_selection)); n->feature=current->child_evidence->feature; n->next=*head; *head=n; found2: collapse_tree(current->child_no_evidence,head); } n=*head; if(current->parent==NULL) free(head); return n; }
void tdu_interface_collapse (int redraw) { node_s *n; long scrolllines; n = find_node_numbered(root_node, cursor_line); if (!n) return; scrolllines = collapse_tree(n); if (!scrolllines) return; if (redraw) { display_nodes(cursor_line - start_line, visible_lines - (cursor_line - start_line), root_node, cursor_line, cursor_line); tdu_interface_refresh(); } else { long maxlines = visible_lines - (cursor_line - start_line); if (scrolllines >= maxlines - 1) { display_nodes(cursor_line - start_line, visible_lines - (cursor_line - start_line), root_node, cursor_line, cursor_line); } else { tdu_interface_refresh(); winsdelln(main_window, -scrolllines); display_nodes(cursor_line - start_line, 1, root_node, cursor_line, cursor_line); display_nodes(visible_lines - scrolllines, scrolllines, root_node, cursor_line + maxlines - scrolllines, cursor_line); } tdu_interface_refresh(); } }
static int process_filter(struct event_format *event, struct filter_arg **parg, char **error_str, int not) { enum event_type type; char *token = NULL; struct filter_arg *current_op = NULL; struct filter_arg *current_exp = NULL; struct filter_arg *left_item = NULL; struct filter_arg *arg = NULL; enum op_type op_type; enum filter_op_type btype; enum filter_exp_type etype; enum filter_cmp_type ctype; int ret; *parg = NULL; do { free(token); type = read_token(&token); switch (type) { case EVENT_SQUOTE: case EVENT_DQUOTE: case EVENT_ITEM: arg = create_arg_item(event, token, type, error_str); if (!arg) goto fail; if (!left_item) left_item = arg; else if (current_exp) { ret = add_right(current_exp, arg, error_str); if (ret < 0) goto fail; left_item = NULL; /* Not's only one one expression */ if (not) { arg = NULL; if (current_op) goto fail_print; free(token); *parg = current_exp; return 0; } } else goto fail_print; arg = NULL; break; case EVENT_DELIM: if (*token == ',') { show_error(error_str, "Illegal token ','"); goto fail; } if (*token == '(') { if (left_item) { show_error(error_str, "Open paren can not come after item"); goto fail; } if (current_exp) { show_error(error_str, "Open paren can not come after expression"); goto fail; } ret = process_filter(event, &arg, error_str, 0); if (ret != 1) { if (ret == 0) show_error(error_str, "Unbalanced number of '('"); goto fail; } ret = 0; /* A not wants just one expression */ if (not) { if (current_op) goto fail_print; *parg = arg; return 0; } if (current_op) ret = add_right(current_op, arg, error_str); else current_exp = arg; if (ret < 0) goto fail; } else { /* ')' */ if (!current_op && !current_exp) goto fail_print; /* Make sure everything is finished at this level */ if (current_exp && !check_op_done(current_exp)) goto fail_print; if (current_op && !check_op_done(current_op)) goto fail_print; if (current_op) *parg = current_op; else *parg = current_exp; return 1; } break; case EVENT_OP: op_type = process_op(token, &btype, &ctype, &etype); /* All expect a left arg except for NOT */ switch (op_type) { case OP_BOOL: /* Logic ops need a left expression */ if (!current_exp && !current_op) goto fail_print; /* fall through */ case OP_NOT: /* logic only processes ops and exp */ if (left_item) goto fail_print; break; case OP_EXP: case OP_CMP: if (!left_item) goto fail_print; break; case OP_NONE: show_error(error_str, "Unknown op token %s", token); goto fail; } ret = 0; switch (op_type) { case OP_BOOL: arg = create_arg_op(btype); if (current_op) ret = add_left(arg, current_op); else ret = add_left(arg, current_exp); current_op = arg; current_exp = NULL; break; case OP_NOT: arg = create_arg_op(btype); if (current_op) ret = add_right(current_op, arg, error_str); if (ret < 0) goto fail; current_exp = arg; ret = process_filter(event, &arg, error_str, 1); if (ret < 0) goto fail; ret = add_right(current_exp, arg, error_str); if (ret < 0) goto fail; break; case OP_EXP: case OP_CMP: if (op_type == OP_EXP) arg = create_arg_exp(etype); else arg = create_arg_cmp(ctype); if (current_op) ret = add_right(current_op, arg, error_str); if (ret < 0) goto fail; ret = add_left(arg, left_item); if (ret < 0) { arg = NULL; goto fail_print; } current_exp = arg; break; default: break; } arg = NULL; if (ret < 0) goto fail_print; break; case EVENT_NONE: break; default: goto fail_print; } } while (type != EVENT_NONE); if (!current_op && !current_exp) goto fail_print; if (!current_op) current_op = current_exp; current_op = collapse_tree(current_op); *parg = current_op; return 0; fail_print: show_error(error_str, "Syntax error"); fail: free_arg(current_op); free_arg(current_exp); free_arg(arg); free(token); return -1; }