📄 specializer.cc
字号:
}voidSpecializer::do_simple_action(SpecializedClass &spc){ CxxFunction *simple_action = spc.cxxc->find("simple_action"); assert(simple_action); simple_action->kill(); spc.cxxc->defun (CxxFunction("smaction", false, "inline Packet *", simple_action->args(), simple_action->body(), simple_action->clean_body())); spc.cxxc->defun (CxxFunction("push", false, "void", "(int, Packet *p)", "\n if (Packet *q = smaction(p))\n\ output_push(0, q);\n", "")); spc.cxxc->defun (CxxFunction("pull", false, "Packet *", "(int)", "\n Packet *p = input_pull(0);\n\ return (p ? smaction(p) : 0);\n", "")); spc.cxxc->find("output_push")->unkill(); spc.cxxc->find("input_pull")->unkill();}inline const String &Specializer::enew_cxx_type(int i) const{ int j = _specialize[i]; return _specials[j].cxx_name;}voidSpecializer::create_connector_methods(SpecializedClass &spc){ assert(spc.cxxc); int eindex = spc.eindex; CxxClass *cxxc = spc.cxxc; // create mangled names of attached push and pull functions const Vector<ConnectionT> &conn = _router->connections(); int nhook = _router->nconnections(); Vector<String> input_class(_ninputs[eindex], String()); Vector<String> output_class(_noutputs[eindex], String()); Vector<int> input_port(_ninputs[eindex], -1); Vector<int> output_port(_noutputs[eindex], -1); for (int i = 0; i < nhook; i++) { if (conn[i].from_eindex() == eindex) { output_class[conn[i].from_port()] = enew_cxx_type(conn[i].to_eindex()); output_port[conn[i].from_port()] = conn[i].to_port(); } if (conn[i].to_eindex() == eindex) { input_class[conn[i].to_port()] = enew_cxx_type(conn[i].from_eindex()); input_port[conn[i].to_port()] = conn[i].from_port(); } } // create input_pull if (cxxc->find("input_pull")->alive()) { StringAccum sa; Vector<int> range1, range2; for (int i = 0; i < _ninputs[eindex]; i++) if (i > 0 && input_class[i] == input_class[i-1] && input_port[i] == input_port[i-1]) range2.back() = i; else { range1.push_back(i); range2.push_back(i); } for (int i = 0; i < range1.size(); i++) { int r1 = range1[i], r2 = range2[i]; if (!input_class[r1]) continue; sa << "\n "; if (r1 == r2) sa << "if (i == " << r1 << ") "; else sa << "if (i >= " << r1 << " && i <= " << r2 << ") "; sa << "return ((" << input_class[r1] << " *)input(i).element())->" << input_class[r1] << "::pull(" << input_port[r1] << ");"; } sa << "\n return input(i).pull();\n"; cxxc->find("input_pull")->set_body(sa.take_string()); } // create output_push if (cxxc->find("output_push")->alive()) { StringAccum sa; Vector<int> range1, range2; for (int i = 0; i < _noutputs[eindex]; i++) if (i > 0 && output_class[i] == output_class[i-1] && output_port[i] == output_port[i-1]) range2.back() = i; else { range1.push_back(i); range2.push_back(i); } for (int i = 0; i < range1.size(); i++) { int r1 = range1[i], r2 = range2[i]; if (!output_class[r1]) continue; sa << "\n "; if (r1 == r2) sa << "if (i == " << r1 << ") "; else sa << "if (i >= " << r1 << " && i <= " << r2 << ") "; sa << "{ ((" << output_class[r1] << " *)output(i).element())->" << output_class[r1] << "::push(" << output_port[r1] << ", p); return; }"; } sa << "\n output(i).push(p);\n"; cxxc->find("output_push")->set_body(sa.take_string()); sa.clear(); sa << "\n if (i < " << _noutputs[eindex] << ")\n output_push(i, p);\n"; sa << " else\n p->kill();\n"; cxxc->find("output_push_checked")->set_body(sa.take_string()); }}voidSpecializer::specialize(const Signatures &sigs, ErrorHandler *errh){ // decide what is to be specialized _specialize = sigs.signature_ids(); SpecializedClass spc; spc.eindex = SPCE_NOT_DONE; _specials.assign(sigs.nsignatures(), spc); _specials[0].eindex = SPCE_NOT_SPECIAL; for (int i = 0; i < _nelements; i++) check_specialize(i, errh); // actually do the work for (int s = 0; s < _specials.size(); s++) { if (create_class(_specials[s]) && _specials[s].cxxc->find("simple_action")) do_simple_action(_specials[s]); } for (int s = 0; s < _specials.size(); s++) if (_specials[s].special()) create_connector_methods(_specials[s]);}voidSpecializer::fix_elements(){ for (int i = 0; i < _nelements; i++) { SpecializedClass &spc = _specials[ _specialize[i] ]; if (spc.special()) _router->element(i)->set_type(ElementClassT::base_type(spc.click_name)); }}voidSpecializer::output_includes(ElementTypeInfo &eti, StringAccum &out){ // don't write includes twice for the same class if (eti.wrote_includes) return; // must massage includes. // we may have something like '#include "element.hh"', relying on the // assumption that we are compiling 'element.cc'. must transform this // to '#include "path/to/element.hh"'. // XXX this is probably not the best way to do this const String &includes = eti.includes; const char *s = includes.data(); int len = includes.length(); // skip past '#ifndef X\n#define X' (sort of) int p = 0; while (p < len && isspace(s[p])) p++; if (p + 7 < len && strncmp(s + p, "#ifndef", 7) == 0) { int next = p + 7; for (; next < len && s[next] != '\n'; next++) /* nada */; if (next + 8 < len && strncmp(s + next + 1, "#define", 7) == 0) { for (p = next + 8; p < len && s[p] != '\n'; p++) /* nada */; } } // now collect includes while (p < len) { int start = p; int p2 = p; while (p2 < len && s[p2] != '\n' && s[p2] != '\r') p2++; while (p < p2 && isspace(s[p])) p++; if (p < p2 && s[p] == '#') { // we have a preprocessing directive! // skip space after '#' for (p++; p < p2 && isspace(s[p]); p++) /* nada */; // check for '#include' if (p + 7 < p2 && strncmp(s+p, "include", 7) == 0) { // find what is "#include"d for (p += 7; p < p2 && isspace(s[p]); p++) /* nada */; // interested in "user includes", not <system includes> if (p < p2 && s[p] == '\"') { int left = p + 1; for (p++; p < p2 && s[p] != '\"'; p++) /* nada */; String include = includes.substring(left, p - left); int include_index = _header_file_map[include]; if (include_index >= 0) { if (!_etinfo[include_index].found_header_file) _etinfo[include_index].locate_header_file(_router, ErrorHandler::default_handler()); out << "#include \"" << _etinfo[include_index].found_header_file << "\"\n"; p = p2 + 1; continue; // don't use previous #include text } } } } out << includes.substring(start, p2 + 1 - start); p = p2 + 1; } eti.wrote_includes = true;}voidSpecializer::output(StringAccum& out_header, StringAccum& out){ // output headers for (int i = 0; i < _specials.size(); i++) { SpecializedClass &spc = _specials[i]; if (spc.eindex >= 0) { ElementTypeInfo &eti = etype_info(spc.eindex); if (eti.found_header_file) out_header << "#include \"" << eti.found_header_file << "\"\n"; if (spc.special()) spc.cxxc->header_text(out_header); } } // output C++ code for (int i = 0; i < _specials.size(); i++) { SpecializedClass &spc = _specials[i]; if (spc.special()) { ElementTypeInfo &eti = etype_info(spc.eindex); output_includes(eti, out); spc.cxxc->source_text(out); } }}voidSpecializer::output_package(const String &package_name, StringAccum &out, ErrorHandler* errh){ StringAccum elem2package, cmd_sa; for (int i = 0; i < _specials.size(); i++) if (_specials[i].special()) elem2package << "-\t\"" << package_name << ".hh\"\t" << _specials[i].cxx_name << '-' << _specials[i].click_name << '\n'; String click_buildtool_prog = clickpath_find_file("click-buildtool", "bin", CLICK_BINDIR, errh); cmd_sa << click_buildtool_prog << " elem2package " << package_name; out << shell_command_output_string(cmd_sa.take_string(), elem2package.take_string(), errh); }voidSpecializer::output_new_elementmap(const ElementMap &full_em, ElementMap &em, const String &filename, const String &requirements) const{ for (int i = 0; i < _specials.size(); i++) if (_specials[i].special()) { Traits e = full_em.traits(_specials[i].old_click_name); e.name = _specials[i].click_name; e.cxx = _specials[i].cxx_name; e.header_file = filename + ".hh"; e.source_file = filename + ".cc"; e.requirements = requirements + _specials[i].old_click_name; e.provisions = String(); em.add(e); }}// Vector template instantiation#include <click/vector.cc>template class Vector<ElementTypeInfo>;template class Vector<SpecializedClass>;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -