📄 click-pretty.cc
字号:
} } else if (tag == "outputs" && !is_type) { if (e->noutputs() == 0) { String text = attrs["noentry"]; if (!text) text = _main_attrs["nooutputentry"]; run_template(text, e, -1, true); } else { String subsep = attrs["sep"]; String text = attrs["entry"]; if (!text) text = _main_attrs["outputentry"]; for (int i = 0; i < e->noutputs(); i++) { run_template(text, e, i, true); _sep = subsep; } } } else if (tag == "inputconnections" && port >= 0 && !is_output) { Vector<int> conn; _router->find_connections_to(PortT(e, port), conn); if (conn.size() == 0) { String text = attrs["noentry"]; if (!text) text = _main_attrs["noinputconnection"]; run_template(text, e, port, false); } else { sort_connections(_router, conn, true); String subsep = attrs["sep"]; String text = attrs["entry"]; if (!text) text = _main_attrs["inputconnection"]; for (int i = 0; i < conn.size(); i++) { const ConnectionT &c = _router->connection(conn[i]); run_template(text, c.from_element(), c.from_port(), true); _sep = subsep; } } } else if (tag == "outputconnections" && port >= 0 && is_output) { Vector<int> conn; _router->find_connections_from(PortT(e, port), conn); if (conn.size() == 0) { String text = attrs["noentry"]; if (!text) text = _main_attrs["nooutputconnection"]; run_template(text, e, port, true); } else { sort_connections(_router, conn, false); String subsep = attrs["sep"]; String text = attrs["entry"]; if (!text) text = _main_attrs["outputconnection"]; for (int i = 0; i < conn.size(); i++) { const ConnectionT &c = _router->connection(conn[i]); run_template(text, c.to_element(), c.to_port(), false); _sep = subsep; } } } else if (tag == "port" && port >= 0) { _sa << _sep << port; } else if (tag == "processing" && port >= 0) { int p = (is_output ? _processing.output_processing(PortT(e, port)) : _processing.input_processing(PortT(e, port))); if (p == ProcessingT::VAGNOSTIC) _sa << _sep << "agnostic"; else if (p == ProcessingT::VPUSH) _sa << _sep << "push"; else if (p == ProcessingT::VPULL) _sa << _sep << "pull"; else _sa << _sep << "??"; } else if (tag == "processingcode") { _sa << _sep << t->processing_code(); } else if (tag == "flowcode") { _sa << _sep << t->flow_code(); } else if (tag == "if") { String s = expand(attrs["test"], e, port, is_output); bool result; if (attrs["eq"]) result = (expand(attrs["eq"], e, port, is_output) == s); else if (attrs["ne"]) result = (expand(attrs["ne"], e, port, is_output) != s); else if (attrs["gt"]) result = (click_strcmp(s, expand(attrs["gt"], e, port, is_output)) > 0); else if (attrs["lt"]) result = (click_strcmp(s, expand(attrs["lt"], e, port, is_output)) < 0); else if (attrs["ge"]) result = (click_strcmp(s, expand(attrs["ge"], e, port, is_output)) >= 0); else if (attrs["le"]) result = (click_strcmp(s, expand(attrs["le"], e, port, is_output)) <= 0); else result = (s.length() > 0); if (result) run_template(attrs["then"], e, port, is_output); else run_template(attrs["else"], e, port, is_output); } else if (_main_attrs[tag]) { String text = attrs[tag]; run_template(text, e, port, is_output); } else if (definitions[tag]) { String text = definitions[tag]; run_template(text, e, port, is_output); } if (_sa.length() != pre_expansion_pos) _sep = next_sep; }}StringElementsOutput::expand(const String &s, ElementT *e, int port, bool is_output){ int pos = _sa.length(); run_template(s, e, port, is_output); String result(_sa.data() + pos, _sa.length() - pos); _sa.pop_back(_sa.length() - pos); return result;}voidElementsOutput::run(ElementT *e, FILE *f){ bool is_type = e->landmark() == type_landmark; String templ = _main_attrs[is_type ? "typeentry" : "entry"]; run_template(templ, e, -1, false); fputs(_sa.cc(), f); _sa.clear(); _sep = _main_attrs["sep"];}voidElementsOutput::run(FILE *f){ // divide into columns int which_col, ncol; parse_columns(_main_attrs["column"], which_col, ncol); int per_col = ((_entries.size() - 1) / ncol) + 1; int first = (which_col - 1) * per_col; int last = which_col * per_col; if (which_col == ncol || last > _entries.size()) last = _entries.size(); // actually do output for (int i = first; i < last; i++) run(_entries[i], f);}//// main loop//static voidrun_template(const char *templ, RouterT *r, const String &r_config, const ElementMap &emap, const ProcessingT &processing, FILE *outf){ String tag; HashMap<String, String> attrs; while (templ) { templ = output_template_until_tag(templ, outf, tag, attrs, false); if (tag == "config") output_config(r_config, outf); else if (tag == "elements") { ElementsOutput eo(r, processing, attrs); eo.run(outf); } else if (definitions[tag]) { String text = definitions[tag]; run_template(text.c_str(), r, r_config, emap, processing, outf); } }}static FILE *open_output_file(const char *outfile, ErrorHandler *errh){ FILE *outf = stdout; if (outfile && strcmp(outfile, "-") != 0) { outf = fopen(outfile, "w"); if (!outf) errh->error("%s: %s", outfile, strerror(errno)); } return outf;}static voidpretty_process(const char *infile, bool file_is_expr, const char *outfile, const char *templ, ErrorHandler *errh){ String r_config; RouterT *r = pretty_read_router(infile, file_is_expr, errh, r_config); if (!r) return; // open output file FILE *outf = open_output_file(outfile, errh); if (!outf) { delete r; return; } // get element map and processing ElementMap emap; emap.parse_all_files(r, CLICK_SHAREDIR, errh); int driver = specified_driver; if (driver < 0) { int driver_mask = 0; for (int d = 0; d < Driver::COUNT; d++) if (emap.driver_compatible(r, d)) driver_mask |= 1 << d; if (driver_mask == 0) errh->warning("configuration not compatible with any driver"); else { for (int d = Driver::COUNT - 1; d >= 0; d--) if (driver_mask & (1 << d)) driver = d; // don't complain if only a single driver works if ((driver_mask & (driver_mask - 1)) != 0 && !emap.driver_indifferent(r, driver_mask, errh)) errh->warning("configuration not indifferent to driver, picking %s\n(You might want to specify a driver explicitly.)", Driver::name(driver)); } } else if (!emap.driver_compatible(r, driver)) errh->warning("configuration not compatible with %s driver", Driver::name(driver)); emap.set_driver(driver); ProcessingT processing(r, &emap, errh); ElementMap::push_default(&emap); // process template run_template(templ, r, r_config, emap, processing, outf); ElementMap::pop_default(); // close files, return if (outf != stdout) fclose(outf); delete r;}voidusage(){ printf("\'Click-pretty' reads a Click router configuration and outputs an HTML file,\n\based on a template, showing that configuration with syntax highlighting.\n\\n\Usage: %s [OPTION]... [ROUTERFILE]\n\\n\Options:\n\ -f, --file FILE Read router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as router configuration.\n\ -o, --output FILE Write HTML output to FILE.\n\ -t, --template FILE Use FILE as the template instead of default.\n\ -d, --define NAME=TEXT Define a new tag, NAME, that expands to TEXT.\n\ -u, --class-docs URL Link primitive element classes to URL.\n\ --package-docs PKG=URL Link element classes in package PKG to URL.\n\ --write-template Write template as is, without including router.\n\ -C, --clickpath PATH Use PATH for CLICKPATH.\n\ --help Print this message and exit.\n\ -v, --version Print version number and exit.\n\\n\Report bugs to <click@pdos.lcs.mit.edu>.\n", program_name);}intmain(int argc, char **argv){ click_static_initialize(); CLICK_DEFAULT_PROVIDES; ErrorHandler *errh = ErrorHandler::default_handler(); ErrorHandler *p_errh = new PrefixErrorHandler(errh, "click-pretty: "); // read command line arguments Clp_Parser *clp = Clp_NewParser(argc, argv, sizeof(options)/sizeof(options[0]), options); Clp_SetOptionChar(clp, '+', Clp_ShortNegated); program_name = Clp_ProgramName(clp); const char *router_file = 0; bool file_is_expr = false; const char *output_file = 0; String html_template = default_template; bool write_template = false; while (1) { int opt = Clp_Next(clp); switch (opt) { case HELP_OPT: usage(); exit(0); break; case VERSION_OPT: printf("click-pretty (Click) %s\n", CLICK_VERSION); printf("Copyright (c) 2001-2002 International Computer Science Institute\n\This is free software; see the source for copying conditions.\n\There is NO warranty, not even for merchantability or fitness for a\n\particular purpose.\n"); exit(0); break; case CLICKPATH_OPT: set_clickpath(clp->arg); break; case CLASS_URLS_OPT: package_hrefs.insert("x", clp->arg); break; case PACKAGE_URLS_OPT: { String s = clp->arg; const char *equals = find(s, '='); if (equals == s.end()) { p_errh->error("'--package-urls' option must contain an equals sign"); goto bad_option; } package_hrefs.insert("x" + s.substring(s.begin(), equals), s.substring(equals + 1, s.end())); break; } case TEMPLATE_OPT: html_template = file_string(clp->arg, p_errh); break; case DEFINE_OPT: { String s = clp->arg; const char *equals = find(s, '='); if (equals < s.end()) definitions.insert(s.substring(s.begin(), equals), s.substring(equals + 1, s.end())); else definitions.insert(s, ""); break; } case WRITE_TEMPLATE_OPT: write_template = !clp->negated; break; case ROUTER_OPT: case EXPRESSION_OPT: case Clp_NotOption: if (router_file) { p_errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->arg; file_is_expr = (opt == EXPRESSION_OPT); break; case OUTPUT_OPT: if (output_file) { p_errh->error("output file specified twice"); goto bad_option; } output_file = clp->arg; break; case USERLEVEL_OPT: case LINUXMODULE_OPT: case BSDMODULE_OPT: if (specified_driver >= 0) { p_errh->error("driver specified twice"); goto bad_option; } specified_driver = opt - FIRST_DRIVER_OPT; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: if (write_template) { if (FILE *f = open_output_file(output_file, errh)) { fputs(html_template.c_str(), f); fclose(f); } } else pretty_process(router_file, file_is_expr, output_file, html_template.c_str(), errh); exit(errh->nerrors() > 0 ? 1 : 0);}#include <click/vector.cc>#include <click/hashmap.cc>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -