📄 script.cc
字号:
else if (_args[_insn_pos] == label_error) last_insn = insn_error; } }#if CLICK_USERLEVEL if (last_insn == INSN_END && _type == type_signal) for (int i = 0; i < _signos.size(); i++) master()->add_signal_handler(_signos[i], router(), name() + ".run");#endif if (retval) { int x; *retval = String(); if (last_insn == INSN_RETURN || last_insn == insn_returnq) { if ((x = find_variable(String::make_stable("_", 1), false)) < _vars.size()) *retval = _vars[x + 1]; } else if (last_insn == INSN_END && _type == type_push) *retval = String::make_stable("0", 1); } if (last_insn == insn_error || last_insn == insn_errorq) return -1; else if (last_insn == INSN_STOP) return 1; else return 0;}voidScript::run_timer(Timer *){ // called when a timer expires assert(_insns[_insn_pos] == INSN_WAIT_TIME || _insns[_insn_pos] == INSN_INITIAL); ErrorHandler *errh = ErrorHandler::default_handler(); ContextErrorHandler cerrh(errh, "While executing %<%{element}%>:", this); step(1, STEP_TIMER, 0, &cerrh); complete_step(0);}voidScript::push(int port, Packet *p){ ErrorHandler *errh = ErrorHandler::default_handler(); ContextErrorHandler cerrh(errh, "While executing %<%{element}%>:", this); // This is slow, but it probably doesn't need to be fast. int i = find_variable(String::make_stable("input", 5), true); _vars[i + 1] = String(port); _insn_pos = 0; step(0, STEP_JUMP, 0, &cerrh); String out; complete_step(&out); port = -1; (void) cp_integer(out, &port); checked_output_push(port, p);}boolScript::Expander::expand(const String &vname, int vartype, int quote, StringAccum &sa) const{ int x = script->find_variable(vname, false); if (x < script->_vars.size()) { sa << cp_expand_in_quotes(script->_vars[x + 1], quote); return true; } if (vname.length() == 1 && vname[0] == '?') { sa << script->_write_status; return true; } if (vname.equals("args", 4)) { sa << cp_expand_in_quotes(script->_run_args, quote); return true; } if (vname.length() == 1 && vname[0] == '0') { sa << script->_run_handler_name; return true; } if (vname.length() > 0 && vname[0] >= '1' && vname[0] <= '9' && cp_integer(vname, &x)) { String arg, run_args = script->_run_args; for (; x > 0; --x) arg = cp_shift_spacevec(run_args); sa << cp_expand_in_quotes(arg, quote); return true; } if (vname.length() == 1 && vname[0] == '#') { String run_args = script->_run_args; for (x = 0; cp_shift_spacevec(run_args); ) ++x; sa << cp_expand_in_quotes(String(x), quote); return true; } if (vname.equals("write", 5)) { sa << cp_unparse_bool(script->_run_op & Handler::OP_WRITE); return true; } if (vartype == '(') { HandlerCall hc(vname); if (hc.initialize_read(script, errh) >= 0) { sa << cp_expand_in_quotes(hc.call_read(errh), quote); return true; } } return false;}intScript::step_handler(int op, String &str, Element *e, const Handler *h, ErrorHandler *errh){ Script *scr = (Script *) e; String data = cp_uncomment(str); int nsteps, steptype; int what = (uintptr_t) h->user_data1(); scr->_run_handler_name = h->name(); scr->_run_args = String(); scr->_run_op = op; if (what == ST_GOTO) { int step = scr->find_label(cp_uncomment(data)); if (step >= scr->_insns.size() || step < 0) return errh->error("jump to nonexistent label"); for (int i = step; i < scr->_insns.size(); i++) if (scr->_insns[i] == INSN_WAIT_STEP) scr->_args2[i] = 0; scr->_insn_pos = step; nsteps = 0, steptype = STEP_JUMP; } else if (what == ST_RUN) { scr->_insn_pos = 0; scr->_run_args = str; nsteps = 0, steptype = STEP_JUMP; } else { if (data == "router") nsteps = 1, steptype = STEP_ROUTER; else if (!data) nsteps = 1, steptype = STEP_NORMAL; else if (cp_integer(data, &nsteps)) steptype = STEP_NORMAL; else return errh->error("syntax error"); } if (!scr->_cur_steps) { int cur_steps = nsteps, njumps = 0; scr->_cur_steps = &cur_steps; while ((nsteps = cur_steps) >= 0) { cur_steps = -1; njumps = scr->step(nsteps, steptype, njumps, errh); steptype = ST_STEP; } scr->_cur_steps = 0; } else if (what == ST_STEP) *scr->_cur_steps += nsteps; return scr->complete_step(&str);}#if HAVE_INT64_TYPES# define click_intmax_t int64_t# define click_uintmax_t uint64_t# define CLICK_INTMAX_CVT "ll"#else# define click_intmax_t int32_t# define click_uintmax_t uint32_t# define CLICK_INTMAX_CVT 'l'#endifintScript::arithmetic_handler(int, String &str, Element *e, const Handler *h, ErrorHandler *errh){ int what = (uintptr_t) h->user_data1(); switch (what) { case AR_FIRST: str = cp_shift_spacevec(str); return 0; case AR_ADD: case AR_SUB: case AR_MUL: case AR_DIV: case AR_IDIV: { click_intmax_t accum = (what == AR_ADD || what == AR_SUB ? 0 : 1), arg; bool first = true;#if CLICK_USERLEVEL double daccum = (what == AR_ADD || what == AR_SUB ? 0 : 1), darg; bool use_daccum = (what == AR_DIV || what == AR_IDIV);#endif while (1) { String word = cp_shift_spacevec(str); if (!word && cp_is_space(str)) break;#if CLICK_USERLEVEL if (!use_daccum && !cp_integer(word, &arg)) { use_daccum = true; daccum = accum; } if (use_daccum && !cp_double(word, &darg)) return errh->error("expected list of numbers"); if (use_daccum) { if (first) daccum = darg; else if (what == AR_ADD) daccum += darg; else if (what == AR_SUB) daccum -= darg; else if (what == AR_MUL) daccum *= darg; else daccum /= darg; goto set_first; }#else if (!cp_integer(word, &arg)) return errh->error("expected list of numbers");#endif if (first) accum = arg; else if (what == AR_ADD) accum += arg; else if (what == AR_SUB) accum -= arg; else if (what == AR_MUL) accum *= arg; else {#if CLICK_USERLEVEL || !HAVE_INT64_TYPES accum /= arg;#else // no int64 divide in the kernel if (accum > 0x7FFFFFFF || arg > 0x7FFFFFFF) errh->warning("int64 divide truncated"); accum = (int32_t) accum / (int32_t) arg;#endif }#if CLICK_USERLEVEL set_first:#endif first = false; }#if CLICK_USERLEVEL if (what == AR_IDIV) { use_daccum = false; accum = (click_intmax_t) daccum; } str = (use_daccum ? String(daccum) : String(accum));#else str = String(accum);#endif return 0; } case ar_mod: case ar_rem: { String astr = cp_shift_spacevec(str), bstr = cp_shift_spacevec(str); click_intmax_t a, b; if (str || !astr || !bstr) goto expected_two_numbers; if (!cp_integer(astr, &a) || !cp_integer(bstr, &b)) {#if CLICK_USERLEVEL double da, db; if (what == ar_mod || !cp_double(astr, &da) || !cp_double(bstr, &db)) goto expected_two_numbers; str = String(fmod(da, db)); return 0;#else goto expected_two_numbers;#endif } else {#if CLICK_LINUXMODULE if ((int32_t) a != a || (int32_t) b != b) errh->warning("int64 divide truncated"); a = (int32_t) a % (int32_t) b;#else a %= b;#endif str = String(a); return 0; } } case AR_LT: case AR_EQ: case AR_GT: case AR_LE: case AR_NE: case AR_GE: { String astr = cp_shift_spacevec(str), bstr = cp_shift_spacevec(str); click_intmax_t a, b; int comparison; if (str || !astr || !bstr) goto expected_two_numbers;#if CLICK_USERLEVEL if (!cp_integer(astr, &a) || !cp_integer(bstr, &b)) { double da, db; if (!cp_double(astr, &da) || !cp_double(bstr, &db)) goto compare_strings; comparison = (da < db ? AR_LT : (da == db ? AR_EQ : AR_GT)); goto compare_return; }#else if (!cp_integer(astr, &a) || !cp_integer(bstr, &b)) goto compare_strings;#endif comparison = (a < b ? AR_LT : (a == b ? AR_EQ : AR_GT)); compare_return: str = cp_unparse_bool(what == comparison || (what >= AR_GE && what != comparison + 3)); return 0; compare_strings: a = String::compare(cp_unquote(astr), cp_unquote(bstr)); comparison = (a < 0 ? AR_LT : (a == 0 ? AR_EQ : AR_GT)); goto compare_return; } case AR_NOT: { bool x; if (!cp_bool(str, &x)) return errh->error("syntax error"); str = cp_unparse_bool(!x); return 0; } case ar_and: case ar_or: { bool zero = (what == ar_and), current_value = zero; while (current_value == zero && str) { bool x; if (!cp_bool(cp_shift_spacevec(str), &x)) return errh->error("syntax error"); current_value = (what == ar_and ? current_value && x : current_value || x); } str = cp_unparse_bool(current_value); return 0; } case ar_if: { bool x; if (!cp_bool(cp_shift_spacevec(str), &x)) return errh->error("syntax error"); if (x) str = cp_shift_spacevec(str); else { (void) cp_shift_spacevec(str); str = cp_shift_spacevec(str); } return 0; } case ar_now: str = Timestamp::now().unparse(); return 0; case AR_SPRINTF: { String format = cp_unquote(cp_shift_spacevec(str)); const char *s = format.begin(), *pct, *end = format.end(); StringAccum result; while ((pct = find(s, end, '%')) < end) { result << format.substring(s, pct); StringAccum pf; // flags do { pf << *pct++; } while (pct < end && (*pct == '0' || *pct == '#' || *pct == '-' || *pct == ' ' || *pct == '+')); // field width int fw; if (pct < end && *pct == '*') { if (!cp_integer(cp_shift_spacevec(str), &fw)) return errh->error("syntax error"); pf << fw; } else while (pct < end && *pct >= '0' && *pct <= '9') pf << *pct++; // precision if (pct < end && *pct == '.') { pct++; if (pct < end && *pct == '*') { if (!cp_integer(cp_shift_spacevec(str), &fw) || fw < 0) return errh->error("syntax error"); pf << '.' << fw; } else if (pct < end && *pct >= '0' && *pct <= '9') { pf << '.'; while (pct < end && *pct >= '0' && *pct <= '9') pf << *pct++; } } // width int width_flag = 0; while (1) { if (pct < end && *pct == 'h') width_flag = 'h', pct++; else if (pct < end && *pct == 'l') width_flag = (width_flag == 'l' ? 'q' : 'l'), pct++; else if (pct < end && (*pct == 'L' || *pct == 'q')) width_flag = 'q', pct++; else break; } // conversion if (pct < end && (*pct == 'o' || *pct == 'x' || *pct == 'X' || *pct == 'u')) { click_uintmax_t ival; String x = cp_shift_spacevec(str); if (!cp_integer(x, &ival)) return errh->error("syntax error"); if (width_flag == 'h') ival = (unsigned short) ival; else if (width_flag == 0 || width_flag == 'l') ival = (unsigned long) ival; pf << CLICK_INTMAX_CVT << *pct; result << ErrorHandler::xformat(pf.c_str(), ival); } else if (pct < end && (*pct == 'd' || *pct == 'i')) { click_intmax_t ival; if (!cp_integer(cp_shift_spacevec(str), &ival)) return errh->error("syntax error"); if (width_flag == 'h') ival = (short) ival; else if (width_flag == 0 || width_flag == 'l') ival = (long) ival; pf << CLICK_INTMAX_CVT << *pct; result << ErrorHandler::xformat(pf.c_str(), ival); } else if (pct < end && *pct == '%') { pf << '%'; result << ErrorHandler::xformat(pf.c_str()); } else if (pct < end && *pct == 's') { String s; if (!cp_string(cp_shift_spacevec(str), &s)) return errh->error("syntax error"); pf << *pct; result << ErrorHandler::xformat(pf.c_str(), s.c_str()); } else return errh->error("syntax error"); s = pct + 1; } if (str) return errh->error("syntax error"); result << format.substring(s, pct); str = result.take_string(); return 0; } case ar_random: { if (!str) str = String(click_random()); else { uint32_t n1, n2; bool have_n2 = false; if (cp_va_space_kparse(str, e, errh, "N1", cpkP+cpkM, cpUnsigned, &n1, "N2", cpkP+cpkM+cpkC, &have_n2, cpUnsigned, &n2, cpEnd) < 0) return -1; if ((have_n2 && n2 < n1) || (!have_n2 && n1 == 0)) return errh->error("bad N"); if (have_n2) str = String(click_random(n1, n2)); else str = String(click_random(0, n1 - 1)); } return 0; }#if CLICK_USERLEVEL case ar_cat: { String filename; if (!cp_filename(str, &filename)) return errh->error("bad FILE"); int nerrors = errh->nerrors(); str = file_string(filename, errh); return (errh->nerrors() == nerrors ? 0 : -errno); }#endif case ar_readable: case ar_writable: { Element *el; const Handler *h; int f = (what == ar_readable ? Handler::OP_READ : Handler::OP_WRITE); while (String hname = cp_shift_spacevec(str)) if (!cp_handler(hname, f, &el, &h, e)) { str = String(false); return 0; } str = String(true); return 0; } expected_two_numbers: return errh->error("expected two numbers"); } return -1;}intScript::star_write_handler(const String &str, Element *e, void *, ErrorHandler *){ Script *s = static_cast<Script *>(e); s->set_handler(str, Handler::OP_READ | Handler::READ_PARAM | Handler::OP_WRITE, step_handler, ST_RUN, 0); return Router::hindex(s, str);}voidScript::add_handlers(){ set_handler("step", Handler::OP_WRITE, step_handler, ST_STEP, 0); set_handler("goto", Handler::OP_WRITE, step_handler, ST_GOTO, 0); set_handler("run", Handler::OP_READ | Handler::READ_PARAM | Handler::OP_WRITE, step_handler, ST_RUN, 0); set_handler("add", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_ADD, 0); set_handler("sub", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_SUB, 0); set_handler("mul", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_MUL, 0); set_handler("div", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_DIV, 0); set_handler("idiv", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_IDIV, 0); set_handler("mod", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_mod, 0); set_handler("rem", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_rem, 0); set_handler("eq", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_EQ, 0); set_handler("ne", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_NE, 0); set_handler("gt", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_GT, 0); set_handler("ge", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_GE, 0); set_handler("lt", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_LT, 0); set_handler("le", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_LE, 0); set_handler("not", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_NOT, 0); set_handler("sprintf", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_SPRINTF, 0); set_handler("first", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, AR_FIRST, 0); set_handler("random", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_random, 0); set_handler("and", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_and, 0); set_handler("or", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_or, 0); set_handler("if", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_if, 0); set_handler("in", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_in, 0); set_handler("now", Handler::OP_READ, arithmetic_handler, ar_now, 0); set_handler("readable", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_readable, 0); set_handler("writable", Handler::OP_READ | Handler::READ_PARAM, arithmetic_handler, ar_writable, 0);#if CLICK_USERLEVEL set_handler("cat", Handler::OP_READ | Handler::READ_PARAM | Handler::READ_PRIVATE, arithmetic_handler, ar_cat, 0);#endif if (_type == type_proxy) add_write_handler("*", star_write_handler, 0);}EXPORT_ELEMENT(Script)CLICK_ENDDECLS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -