/** \brief Apply local context simplification at (OR args[0] ... args[num_args-1]) Basic idea: - Replace args[i] by false in the other arguments - If args[i] is of the form (not t), then replace t by true in the other arguments. To make sure the simplification is efficient we bound the depth. */ bool bool_rewriter::local_ctx_simp(unsigned num_args, expr * const * args, expr_ref & result) { expr_ref_vector old_args(m()); expr_ref_vector new_args(m()); expr_ref new_arg(m()); expr_fast_mark1 neg_lits; expr_fast_mark2 pos_lits; bool simp = false; bool modified = false; bool forward = true; unsigned rounds = 0; while (true) { rounds++; #if 0 if (rounds > 10) verbose_stream() << "rounds: " << rounds << "\n"; #endif #define PUSH_NEW_ARG(ARG) { \ new_args.push_back(ARG); \ if (m().is_not(ARG)) \ neg_lits.mark(to_app(ARG)->get_arg(0)); \ else \ pos_lits.mark(ARG); \ } #define PROCESS_ARG() \ { \ expr * arg = args[i]; \ if (m().is_not(arg) && m().is_or(to_app(arg)->get_arg(0)) && \ simp_nested_not_or(to_app(to_app(arg)->get_arg(0))->get_num_args(), \ to_app(to_app(arg)->get_arg(0))->get_args(), \ neg_lits, \ pos_lits, \ new_arg)) { \ modified = true; simp = true; \ arg = new_arg; \ } \ if (simp_nested_eq_ite(arg, neg_lits, pos_lits, new_arg)) { \ modified = true; simp = true; \ arg = new_arg; \ } \ if (m().is_false(arg)) \ continue; \ if (m().is_true(arg)) { \ result = arg; \ return true; \ } \ if (m_flat && m().is_or(arg)) { \ unsigned sz = to_app(arg)->get_num_args(); \ for (unsigned j = 0; j < sz; j++) { \ expr * arg_arg = to_app(arg)->get_arg(j); \ PUSH_NEW_ARG(arg_arg); \ } \ } \ else { \ PUSH_NEW_ARG(arg); \ } \ } m_local_ctx_cost += 2*num_args; #if 0 static unsigned counter = 0; counter++; if (counter % 10000 == 0) verbose_stream() << "local-ctx-cost: " << m_local_ctx_cost << "\n"; #endif if (forward) { for (unsigned i = 0; i < num_args; i++) { PROCESS_ARG(); } forward = false; } else { unsigned i = num_args; while (i > 0) { --i; PROCESS_ARG(); } if (!modified) { if (simp) { result = mk_or_app(num_args, args); return true; } return false; // didn't simplify } // preserve the original order... std::reverse(new_args.c_ptr(), new_args.c_ptr() + new_args.size()); modified = false; forward = true; } pos_lits.reset(); neg_lits.reset(); old_args.reset(); old_args.swap(new_args); SASSERT(new_args.empty()); args = old_args.c_ptr(); num_args = old_args.size(); } }
int build_args(const char *str, int *argc, char ***argv) { bool quote, backslash, endword; const char *p; bool empty; quote = false; empty = true; backslash = false; endword = true; *argc = 0; *argv = NULL; for (p = str; *p != '\0'; ++p) { if (*p == '\\') { if (backslash) { if (endword) { new_arg(argc, argv); endword = false; } append_str('\\', &(*argv)[*argc - 1]); empty = false; backslash = false; } else { backslash = true; } } else if (*p == '\"') { if (backslash) { if (endword) { new_arg(argc, argv); endword = false; } append_str('\"', &(*argv)[*argc - 1]); empty = false; backslash = false; } else { endword = true; if (quote) { if (empty) { new_arg(argc, argv); append_str('\0', &(*argv)[*argc - 1]); } quote = false; } else { quote = true; empty = true; } } } else if (isspace(*p)) { if (backslash) { if (endword) { new_arg(argc, argv); endword = false; } append_str(*p, &(*argv)[*argc - 1]); empty = false; backslash = false; } else { if (quote) { if (endword) { new_arg(argc, argv); endword = false; } append_str(*p, &(*argv)[*argc - 1]); empty = false; } else { endword = true; } } } else { if (endword) { new_arg(argc, argv); endword = false; } append_str(*p, &(*argv)[*argc - 1]); empty = false; } } return 0; }
/* * This function will try to populate an argumentbox. * This is slightly difficult due to the numerous different possible * input types, ie. v4addr, dotted quad netmask, /netmask, hex netmask, * v6addr, interface name etc. * This forces to have to try to guess what a user means in some cases. * This method can be fairly unforgiving with typos. */ struct argbox *get_boxargs(int argc, char *argv[], int argcount, struct argbox *abox_cur) { char expaddr[ARGLEN]; int x, y; /* * We use goto's here *gasp*. */ while (argv[argcount]) { /* * Baaad argument. Error out if this happens. */ if (strlen(argv[argcount]) > sizeof(expaddr) - 1) errx(1, "Invalid argument %s", expaddr); strlcpy(expaddr, argv[argcount], sizeof(expaddr)); /* * Is this a v6 address? */ x = validate_v6addr(expaddr); if (x) { strlcpy(abox_cur->str, expaddr, sizeof(abox_cur->str)); abox_cur->type = AT_V6; abox_cur->resolv = 0; abox_cur = new_arg(abox_cur); goto complete; } /* * Nope, is it an ipv4 address with a /xx mask? * * NOTE: validate_netmask returns different values if it finds * other types of netmasks to, but we only match on the above * here. */ x = validate_netmask(expaddr); if (x == 2) { strlcpy(abox_cur->str, expaddr, sizeof(abox_cur->str)); abox_cur->type = AT_V4; abox_cur->resolv = 0; abox_cur = new_arg(abox_cur); goto complete; } /* * No, so is it a plain ipv4 address? */ x = validate_v4addr(expaddr); if (x) { y = 0; /* * It is, does that mean the next argument is a * netmask? */ if (argcount + 1 < argc) y = validate_netmask(argv[argcount + 1]); /* * 1 == 'normal' netmask * 3 == hex netmask */ if (y == 1 || y == 3) { snprintf(abox_cur->str, 34, "%s %s", expaddr, argv[argcount + 1]); argcount++; } else snprintf(abox_cur->str, 18, "%s", expaddr); abox_cur->type = AT_V4; abox_cur->resolv = 0; abox_cur = new_arg(abox_cur); goto complete; } y = 0; if (argcount + 1 < argc) y = validate_netmask(argv[argcount + 1]); if (y == 1 || y == 3) { snprintf(abox_cur->str, sizeof(abox_cur->str), "%s %s", expaddr, argv[argcount + 1]); argcount++; } else strlcpy(abox_cur->str, expaddr, sizeof(abox_cur->str)); abox_cur->type = AT_UNKWN; abox_cur->resolv = 1; abox_cur = new_arg(abox_cur); complete: argcount++; } return abox_cur; }