⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 click-pretty.cc

📁 Click is a modular router toolkit. To use it you ll need to know how to compile and install the sof
💻 CC
📖 第 1 页 / 共 3 页
字号:
    String _config;};voidshort_usage(){    fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\Try '%s --help' for more information.\n",	    program_name, program_name);}static RouterT *pretty_read_router(const char *filename, bool file_is_expr,		   ErrorHandler *errh, String &config){    // This function is a paraphrase of read_router_file.    // read file string    int before_nerrors = errh->nerrors();    if (file_is_expr)	config = filename;    else	config = file_string(filename, errh);    if (!config && errh->nerrors() != before_nerrors)	return 0;    // set readable filename    if (file_is_expr)	filename = "config";    else if (!filename || strcmp(filename, "-") == 0)	filename = "<stdin>";    // check for archive    Vector<ArchiveElement> archive;    if (config.length() && config[0] == '!') {	ArchiveElement::parse(config, archive, errh);	if (ArchiveElement *ae = ArchiveElement::find(archive, "config"))	    config = ae->data;	else {	    errh->error("%s: archive has no %<config%> section", filename);	    config = String();	}    }    // clear list of items    items.clear();    end_items.clear();    items_prepared = false;    // read router    if (!config.length())	errh->warning("%s: empty configuration", filename);    LexerT lexer(ErrorHandler::silent_handler(), false);    PrettyLexerTInfo pinfo(config);    lexer.reset(config, archive, filename);    lexer.set_lexinfo(&pinfo);    // read statements    while (lexer.ystatement())	/* nada */;    // done    return lexer.finish(global_scope);}static voidactivate(OutputItem &item, int &first_active){    item.activate(true);    int iitem = item.item_index();    if (iitem < first_active)	first_active = iitem;}static voiddeactivate(OutputItem &item, int &first_active, int ipos){    item.activate(false);    int iitem = item.item_index();    if (iitem == first_active) {	for (first_active++;	     first_active < ipos && !items[first_active].active;	     first_active++)	    /* nada */;	if (first_active >= ipos)	    first_active = items.size();    }}static voidoutput_config(String r_config, FILE *outf){    // create two sorted lists of objects    // add sentinel item, sort item lists    if (!items_prepared)	prepare_items(r_config.length());    // loop over characters    const char *data = r_config.c_str();    int len = r_config.length();    int ipos = 0, eipos = 0;    int first_active = items.size();    fputs("<pre>", outf);    for (int pos = 0; pos < len; pos++) {	while (items[ipos].pos <= pos || end_items[eipos].pos <= pos)	    if (end_items[eipos].pos <= items[ipos].pos) {		if (end_items[eipos].active)		    fputs(end_items[eipos].text.c_str(), outf);		deactivate(end_items[eipos], first_active, ipos);		eipos++;	    } else {		fputs(items[ipos].text.c_str(), outf);		activate(items[ipos], first_active);		ipos++;	    }	switch (data[pos]) {	  case '\n': case '\r':	    for (int i = ipos - 1; i >= first_active; i--)		if (items[i].active)		    fputs(items[i].other()->text.c_str(), outf);	    fputc('\n', outf);	    if (data[pos] == '\r' && pos < len - 1 && data[pos+1] == '\n')		pos++;	    for (int i = first_active; i < ipos; i++)		if (items[i].active) {		    if (items[i].other()->pos <= pos + 1)			items[i].activate(false);		    else			fputs(items[i].text.c_str(), outf);		}	    break;	  case '<':	    fputs("&lt;", outf);	    break;	  case '>':	    fputs("&gt;", outf);	    break;	  case '&':	    fputs("&amp;", outf);	    break;	  default:	    fputc(data[pos], outf);	    break;	}    }    fputs("</pre>\n", outf);}static boolparse_columns(const String &s, int &which, int &count){    const char *slash = find(s, '/');    if (!cp_integer(s.substring(s.begin(), slash), &which)	|| !cp_integer(s.substring(slash + 1, s.end()), &count)	|| which <= 0 || which > count) {	which = count = 1;	return false;    } else	return true;}extern "C" {static const Vector<ConnectionT> *conn_compar_connvec;static bool conn_compar_from;static intconn_compar(const void *v1, const void *v2){    const int *i1 = (const int *)v1, *i2 = (const int *)v2;    const ConnectionT &c1 = (*conn_compar_connvec)[*i1];    const ConnectionT &c2 = (*conn_compar_connvec)[*i2];    const PortT &p1 = (conn_compar_from ? c1.from() : c1.to());    const PortT &p2 = (conn_compar_from ? c2.from() : c2.to());    if (p1.element == p2.element)	return p1.port - p2.port;    else	return click_strcmp(p1.element->name(), p2.element->name());}static intelement_name_compar(const void *v1, const void *v2){    const ElementT **e1 = (const ElementT **)v1, **e2 = (const ElementT **)v2;    return click_strcmp((*e1)->name(), (*e2)->name());}}static voidsort_connections(RouterT *r, Vector<int> &conn, bool from){    conn_compar_connvec = &r->connections();    conn_compar_from = from;    if (conn.size())	qsort(&conn[0], conn.size(), sizeof(int), conn_compar);}//// elements//static String type_landmark = "$fake_type$";class ElementsOutput { public:    ElementsOutput(RouterT *, const ProcessingT &, const HashTable<String, String> &);    ~ElementsOutput();    void run(ElementT *, FILE *);    void run(FILE *);  private:    RouterT *_router;    const ProcessingT &_processing;    const HashTable<String, String> &_main_attrs;    Vector<ElementT *> _entries;    Vector<ElementT *> _elements;    StringAccum _sa;    String _sep;    void run_template(String, ElementT *, int, bool);    String expand(const String &, ElementT *, int, bool);};ElementsOutput::ElementsOutput(RouterT *r, const ProcessingT &processing, const HashTable<String, String> &main_attrs)    : _router(r), _processing(processing), _main_attrs(main_attrs){    bool do_elements = main_attrs["entry"];    bool do_types = main_attrs["typeentry"];    // get list of elements and/or types    HashTable<ElementClassT *, int> done_types(-1);    for (RouterT::iterator x = r->begin_elements(); x; x++) {	_elements.push_back(x);	if (do_elements)	    _entries.push_back(x);	if (do_types && done_types[x->type()] < 0) {	    ElementT *fake = new ElementT(x->type_name(), x->type(), "", LandmarkT(type_landmark));	    _entries.push_back(fake);	    done_types.set(x->type(), 1);	}    }    // sort by name    if (_elements.size())	qsort(&_elements[0], _elements.size(), sizeof(ElementT *), element_name_compar);    if (_entries.size())	qsort(&_entries[0], _entries.size(), sizeof(ElementT *), element_name_compar);}ElementsOutput::~ElementsOutput(){    for (int i = 0; i < _entries.size(); i++)	if (_entries[i]->landmark() == type_landmark)	    delete _entries[i];}voidElementsOutput::run_template(String templ_str, ElementT *e, int port, bool is_output){    ElementClassT *t = e->type();    bool is_type = (e->landmark() == type_landmark);    String tag;    HashTable<String, String> attrs;    const char *templ = templ_str.c_str();    while (templ) {	templ = output_template_until_tag(templ, _sa, tag, attrs, true, &_sep);	String next_sep;	int pre_expansion_pos = _sa.length();	if (tag == "name") {	    String href, link = attrs["link"].lower();	    if (link == "type" || (is_type && link))		href = class_href(t);	    else if (link)		href = link_element_decl(e);	    if (href)		_sa << _sep << "<a href='" << href << "'>" << e->name() << "</a>";	    else		_sa << _sep << e->name();	} else if (tag == "type") {	    String href = (attrs["link"] ? class_href(t) : String());	    if (href)		_sa << _sep << "<a href='" << href << "'>" << t->name() << "</a>";	    else		_sa << _sep << t->name();	} else if (tag == "config" && !is_type) {	    int limit = 0;	    if (attrs["limit"])		cp_integer(html_unquote(attrs["limit"]), &limit);	    String config = e->configuration();	    if (limit && config.length() > limit)		config = config.substring(0, limit) + "...";	    if (config && attrs["parens"])		_sa << _sep << '(' << html_quote_text(config) << ')';	    else if (config)		_sa << _sep << html_quote_text(config);	} else if (tag == "typerefs") {	    String subsep = attrs["sep"];	    String text = attrs["entry"];	    if (!text)		text = _main_attrs["typeref"];	    for (int i = 0; i < _elements.size(); i++)		if (_elements[i]->type() == t) {		    run_template(text, _elements[i], -1, false);		    _sep = subsep;		}	} else if (tag == "configlink" && !is_type) {	    String text = attrs["text"];	    if (!text)		text = _main_attrs["configlink"];	    if (text) {		text = "<a href='#" + link_element_decl(e) + "'>" + text + "</a>";		run_template(text, e, port, is_output);		next_sep = attrs["sep"];	    }	} else if (tag == "ninputs" && !is_type) {	    _sa << _sep << e->ninputs();	    if (attrs["english"])		_sa << (e->ninputs() == 1 ? " input" : " inputs");	} else if (tag == "noutputs" && !is_type) {	    _sa << _sep << e->noutputs();	    if (attrs["english"])		_sa << (e->noutputs() == 1 ? " output" : " outputs");	} else if (tag == "inputs" && !is_type) {	    if (e->ninputs() == 0) {		String text = attrs["noentry"];		if (!text)		    text = _main_attrs["noinputentry"];		run_template(text, e, -1, false);	    } else {		String subsep = attrs["sep"];		String text = attrs["entry"];		if (!text)		    text = _main_attrs["inputentry"];		for (int i = 0; i < e->ninputs(); i++) {		    run_template(text, e, i, false);		    _sep = subsep;		}	    }	} 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::pagnostic)		_sa << _sep << "agnostic";	    else if (p & ProcessingT::ppush)		_sa << _sep << "push";	    else if (p & ProcessingT::ppull)		_sa << _sep << "pull";	    else		_sa << _sep << "??";	} else if (tag == "processingcode") {	    _sa << _sep << t->processing_code();	} else if (tag == "flowcode") {	    _sa << _sep << e->flow_code();	} else if (tag == "if") {	    String s = expand(attrs["test"], e, port, is_output);	    bool result;	    if (String v = attrs.get("eq"))		result = (expand(v, e, port, is_output) == s);	    else if (String v = attrs.get("ne"))		result = (expand(v, e, port, is_output) != s);	    else if (String v = attrs.get("gt"))		result = (click_strcmp(s, expand(v, e, port, is_output)) > 0);	    else if (String v = attrs.get("lt"))		result = (click_strcmp(s, expand(v, e, port, is_output)) < 0);	    else if (String v = attrs.get("ge"))		result = (click_strcmp(s, expand(v, e, port, is_output)) >= 0);	    else if (String v = attrs.get("le"))		result = (click_strcmp(s, expand(v, 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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -