📄 click-pretty.cc
字号:
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.c_str(), 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; HashTable<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 (String text = definitions.get(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_DATADIR, errh); emap.set_driver(emap.pick_driver(specified_driver, r, errh)); ProcessingT processing(r, &emap, errh); processing.check_types(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;}// This algorithm based on the original click-viz script,// donated by Jose Vasconcellos <jvasco@bellatlantic.net>static voidpretty_process_dot(const char *infile, bool file_is_expr, const char *outfile, ErrorHandler *errh){ RouterT *r = read_router(infile, file_is_expr, errh); if (!r) return; // open output file FILE *outf = open_output_file(outfile, errh); if (!outf) { delete r; return; } // write dot configuration fprintf(outf, "digraph clickrouter {\n\ node [shape=record,height=.1]\n\ edge [arrowhead=normal,arrowtail=none,tailclip=false]\n"); // print all nodes for (RouterT::const_iterator n = r->begin_elements(); n != r->end_elements(); n++) {#if 1 fprintf(outf, " \"%s\" [label=\"", n->name_c_str()); if (n->ninputs() || n->noutputs()) fprintf(outf, "{"); if (n->ninputs()) { fprintf(outf, "{"); for (int i = 0; i < n->ninputs(); i++) fprintf(outf, (i ? "|<i%d>" : "<i%d>"), i); fprintf(outf, "}|"); } fputs(n->type_name_c_str(), outf); if (n->noutputs()) { fprintf(outf, "|{"); for (int i = 0; i < n->noutputs(); i++) fprintf(outf, (i ? "|<o%d>" : "<o%d>"), i); fprintf(outf, "}"); } if (n->ninputs() || n->noutputs()) fprintf(outf, "}"); fprintf(outf, "\"];\n");#else if (!n->ninputs() && !n->noutputs()) fprintf(outf, " \"%s\" [label=\"%s\"];\n", n->name_c_str(), n->type_name_c_str()); else { fprintf(outf, " \"%s\" [label=< <TABLE BORDER=\"0\">", n->name_c_str()); if (n->ninputs() > 0) { fprintf(outf, "<TR><TD><TABLE BORDER=\"0\"><TR>"); for (int i = 0; i < n->ninputs(); i++) fprintf(outf, "<TD PORT=\"i%d\">X</TD>", i); fprintf(outf, "</TR></TABLE></TD></TR>"); } fprintf(outf, "<TR><TD>%s</TD></TR>", n->type_name_c_str()); if (n->noutputs() > 0) { fprintf(outf, "<TR><TD><TABLE BORDER=\"0\"><TR>"); for (int i = 0; i < n->noutputs(); i++) fprintf(outf, "<TD PORT=\"o%d\">X</TD>", i); fprintf(outf, "</TR></TABLE></TD></TR>"); } fprintf(outf, "</TABLE> >];\n"); }#endif } // print all connections const Vector<ConnectionT> &conns = r->connections(); for (const ConnectionT *c = conns.begin(); c != conns.end(); c++) fprintf(outf, " \"%s\":o%d -> \"%s\":i%d;\n", c->from_element()->name_c_str(), c->from_port(), c->to_element()->name_c_str(), c->to_port()); fprintf(outf, "}\n"); // close files, return if (outf != stdout) fclose(outf); delete r;}static voidpretty_process_gml(const char *infile, bool file_is_expr, const char *outfile, ErrorHandler *errh){ RouterT *r = read_router(infile, file_is_expr, errh); if (!r) return; // open output file FILE *outf = open_output_file(outfile, errh); if (!outf) { delete r; return; } // write dot configuration fprintf(outf, "Creator \"click-pretty\"\n\graph\n[ hierarchic 1\n\ directed 1\n"); // print all nodes for (RouterT::const_iterator n = r->begin_elements(); n != r->end_elements(); n++) fprintf(outf, " node\n [ id %d\n label \"%s\"\n ]\n", n->eindex(), n->name().c_str()); // print all connections const Vector<ConnectionT> &conns = r->connections(); for (const ConnectionT *c = conns.begin(); c != conns.end(); c++) { fprintf(outf, " edge\n [ source %d\n target %d\n", c->from_eindex(), c->to_eindex()); double amt_from = 1. / c->from_element()->noutputs(); double first_from = -(c->from_element()->noutputs() - 1.) * amt_from; double amt_to = 1. / c->to_element()->ninputs(); double first_to = -(c->to_element()->ninputs() - 1.) * amt_to; fprintf(outf, " edgeAnchor\n [ xSource %f\n xTarget %f\n ySource 1\n yTarget -1\n ]\n", first_from + c->from_port() * amt_from, first_to + c->to_port() * amt_to); fprintf(outf, " ]\n"); } fprintf(outf, "]\n"); // close files, return if (outf != stdout) fclose(outf); delete r;}static voidpretty_process_graphml(const char *infile, bool file_is_expr, const char *outfile, ErrorHandler *errh){ RouterT *r = read_router(infile, file_is_expr, errh); if (!r) return; // get element map and processing ElementMap emap; emap.parse_all_files(r, CLICK_DATADIR, errh); emap.set_driver(emap.pick_driver(specified_driver, r, errh)); ProcessingT processing(r, &emap, errh); processing.check_types(errh); // open output file FILE *outf = open_output_file(outfile, errh); if (!outf) { delete r; return; } // write dot configuration fprintf(outf, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n\<key id=\"kn\" for=\"node\" attr.name=\"name\" attr.type=\"string\" />\n\<key id=\"kc\" for=\"node\" attr.name=\"class\" attr.type=\"string\" />\n\<key id=\"kp\" for=\"port\" attr.name=\"processing\" attr.type=\"string\">\n\ <default>a</default>\n\</key>\n\<graph id=\"G\" edgedefault=\"directed\">\n"); // print all nodes int nodeid = 0; for (RouterT::iterator n = r->begin_elements(); n != r->end_elements(); n++) { fprintf(outf, " <node id=\"n%d\" parse.indegree=\"%d\" parse.outdegree=\"%d\">\n\ <data key=\"kn\">%s</data> <data key=\"kc\">%s</data>\n", nodeid++, n->ninputs(), n->noutputs(), n->name().c_str(), n->type_name().c_str()); for (int i = 0; i < n->ninputs(); i++) fprintf(outf, " <port name=\"i%d\"> <data key=\"kp\">%c</data> </port>\n", i, processing.decorated_input_processing_letter(PortT(n.operator->(), i))); for (int i = 0; i < n->noutputs(); i++) fprintf(outf, " <port name=\"o%d\"> <data key=\"kp\">%c</data> </port>\n", i, processing.decorated_output_processing_letter(PortT(n.operator->(), i))); fprintf(outf, " </node>\n"); } // print all connections int edgeid = 0; const Vector<ConnectionT> &conns = r->connections(); for (const ConnectionT *c = conns.begin(); c != conns.end(); c++) fprintf(outf, " <edge id=\"e%d\" source=\"n%d\" target=\"n%d\" sourceport=\"o%d\" targetport=\"i%d\" />\n", edgeid++, c->from_eindex(), c->to_eindex(), c->from_port(), c->to_port()); fprintf(outf, "</graph>\n</graphml>\n"); // 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\ -l, --linuxmodule Prefer Linux kernel module elements.\n\ -b, --bsdmodule Prefer FreeBSD kernel module elements.\n\ --userlevel Prefer user-level driver elements.\n\ --write-template Write template as is, without including router.\n\ --dot Output a 'dot' graph definition.\n\ --gml Output a GML graph definition.\n\ --graphml Output a GraphML XML graph definition.\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; int action = 0; 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\Copyright (c) 2007 Regents of the University of California\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->vstr); break; case CLASS_URLS_OPT: package_hrefs.set("x", clp->vstr); break; case PACKAGE_URLS_OPT: { String s = clp->vstr; 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.set("x" + s.substring(s.begin(), equals), s.substring(equals + 1, s.end())); break; } case TEMPLATE_OPT: html_template = file_string(clp->vstr, p_errh); break; case DEFINE_OPT: { String s = clp->vstr; const char *equals = find(s, '='); if (equals < s.end()) definitions.set(s.substring(s.begin(), equals), s.substring(equals + 1, s.end())); else definitions.set(s, ""); break; } case ROUTER_OPT: case EXPRESSION_OPT: router_file: if (router_file) { p_errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->vstr; file_is_expr = (opt == EXPRESSION_OPT); break; case Clp_NotOption: if (!click_maybe_define(clp->vstr, p_errh)) goto router_file; break; case OUTPUT_OPT: if (output_file) { p_errh->error("output file specified twice"); goto bad_option; } output_file = clp->vstr; 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; case WRITE_TEMPLATE_OPT: case DOT_OPT: case GML_OPT: case GRAPHML_OPT: if (action) { p_errh->error("action specified twice"); goto bad_option; } action = opt; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: if (action == WRITE_TEMPLATE_OPT) { if (FILE *f = open_output_file(output_file, errh)) { fputs(html_template.c_str(), f); fclose(f); } } else if (action == DOT_OPT) pretty_process_dot(router_file, file_is_expr, output_file, errh); else if (action == GML_OPT) pretty_process_gml(router_file, file_is_expr, output_file, errh); else if (action == GRAPHML_OPT) pretty_process_graphml(router_file, file_is_expr, output_file, errh); else pretty_process(router_file, file_is_expr, output_file, html_template.c_str(), errh); exit(errh->nerrors() > 0 ? 1 : 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -