📄 click-xform.cc
字号:
VariableEnvironment crap_ve(0); replacement->complex_expand_element(new_e, crap_args, _body, String(), crap_ve, errh); // mark replacement for (int i = 0; i < changed_elements.size(); i++) { ElementT *e = _body->element(changed_elements[i]); if (e->dead()) continue; e->flags = _patid; replace_config(e); } // save old element name if matched element and some replacement element // have the same name for (int i = 0; i < _match.size(); i++) if (_match[i]) { String n = _pat->ename(i); int new_index = _body->eindex(prefix + "/" + n); if (new_index >= 0) _body->change_ename(new_index, old_names[i]); } // find input and output, add connections to tunnels ElementT *new_pp = _body->element(prefix); for (int i = 0; i < _to_pp_from.size(); i++) _body->add_connection(_to_pp_from[i], PortT(new_pp, _to_pp_to[i].port), landmark); for (int i = 0; i < _from_pp_from.size(); i++) _body->add_connection(PortT(new_pp, _from_pp_from[i].port), _from_pp_to[i], landmark); // cleanup _body->remove_tunnels(); // remember to clear 'new_eindex_collector'! _body->set_new_eindex_collector(0); _match.clear(); // finally, update the adjacency matrix _body_m->update(changed_elements); //_body_m->init(_body);}// match configuration stringsboolmatch_config(const String &pat, const String &conf, HashTable<String, String> &defs){ Vector<String> patvec, confvec; HashTable<String, String> my_defs; // separate into vectors cp_argvec(pat, patvec); cp_argvec(conf, confvec); // not same size -> no match if (patvec.size() != confvec.size()) return false; // go over elements and compare; handle $variables for (int i = 0; i < patvec.size(); i++) { if (patvec[i] == confvec[i]) continue; if (patvec[i].length() <= 1 || patvec[i][0] != '$') return false; const String &p = patvec[i]; for (int j = 1; j < p.length(); j++) if (!isalnum((unsigned char) p[j]) && p[j] != '_') return false; if (HashTable<String, String>::iterator it = defs.find(p)) { if (it.value() != confvec[i]) return false; } else if (HashTable<String, String>::iterator it = my_defs.find(p)) { if (it.value() != confvec[i]) return false; } else my_defs.set(p, confvec[i]); } // insert my defs into defs for (HashTable<String, String>::iterator iter = my_defs.begin(); iter.live(); iter++) defs.set(iter.key(), iter.value()); return true;}#define HELP_OPT 300#define VERSION_OPT 301#define ROUTER_OPT 303#define EXPRESSION_OPT 304#define OUTPUT_OPT 305#define PATTERNS_OPT 306#define REVERSE_OPT 307static const Clp_Option options[] = { { "expression", 'e', EXPRESSION_OPT, Clp_ValString, 0 }, { "file", 'f', ROUTER_OPT, Clp_ValString, 0 }, { "help", 0, HELP_OPT, 0, 0 }, { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, { "patterns", 'p', PATTERNS_OPT, Clp_ValString, 0 }, { "reverse", 'r', REVERSE_OPT, 0, Clp_Negate }, { "version", 'v', VERSION_OPT, 0, 0 },};static const char *program_name;voidshort_usage(){ fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE] [PATTERNFILE]...\n\Try '%s --help' for more information.\n", program_name, program_name);}voidusage(){ printf("\'Click-xform' replaces patterns of elements with other sets of elements inside\n\a Click router configuration. Both patterns and configuration are Click-\n\language files. The transformed router configuration is written to the\n\standard output.\n\\n\Usage: %s [OPTION]... [ROUTERFILE] [PATTERNFILE]...\n\\n\Options:\n\ -p, --patterns PATTERNFILE Read patterns from PATTERNFILE. Can be given\n\ more than once.\n\ -f, --file FILE Read router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as router configuration.\n\ -o, --output FILE Write output to FILE.\n\ -r, --reverse Apply patterns in reverse.\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);}static Vector<RouterT *> patterns;static Vector<RouterT *> replacements;static Vector<String> pat_names;static int patterns_attempted;voidread_pattern_file(const char *name, ErrorHandler *errh){ patterns_attempted++; RouterT *pat_file = read_router_file(name, true, errh); if (!pat_file) return; Vector<ElementClassT *> compounds; pat_file->collect_locally_declared_types(compounds); for (int i = 0; i < compounds.size(); i++) { String name = compounds[i]->name(); if (compounds[i]->cast_router() && name.length() > 12 && name.substring(-12) == "_Replacement") { ElementClassT *tt = pat_file->locally_declared_type(name.substring(0, -12)); if (tt && tt->cast_router()) { RouterT *rep = compounds[i]->cast_router(); RouterT *pat = tt->cast_router(); if (rep && pat) { patterns.push_back(pat); replacements.push_back(rep); pat_names.push_back(name.substring(0, -12)); } } } }}intmain(int argc, char **argv){ click_static_initialize(); CLICK_DEFAULT_PROVIDES; ErrorHandler *errh = ErrorHandler::default_handler(); // 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); int num_nondash_args = 0; const char *router_file = 0; bool file_is_expr = false; const char *output_file = 0; bool reverse = 0; while (1) { int opt = Clp_Next(clp); switch (opt) { case HELP_OPT: usage(); exit(0); break; case VERSION_OPT: printf("click-xform (Click) %s\n", CLICK_VERSION); printf("Copyright (c) 1999-2000 Massachusetts Institute of Technology\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 PATTERNS_OPT: read_pattern_file(clp->vstr, errh); break; case ROUTER_OPT: case EXPRESSION_OPT: if (router_file) { errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->vstr; file_is_expr = (opt == EXPRESSION_OPT); break; case OUTPUT_OPT: if (output_file) { errh->error("output file specified twice"); goto bad_option; } output_file = clp->vstr; break; case REVERSE_OPT: reverse = !clp->negated; break; case Clp_NotOption: if (click_maybe_define(clp->vstr, errh)) break; if (num_nondash_args == 0 && router_file) { errh->error("router configuration specified twice"); goto bad_option; } else if (num_nondash_args == 0) router_file = clp->vstr; else read_pattern_file(clp->vstr, errh); num_nondash_args++; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: RouterT *r = read_router(router_file, file_is_expr, errh); if (r) r->flatten(errh); if (!r || errh->nerrors() > 0) exit(1); if (!patterns_attempted) errh->warning("no patterns read"); // manipulate patterns if (patterns.size()) { // reverse if necessary if (reverse) { Vector<RouterT *> new_patterns, new_replacements; for (int i = patterns.size() - 1; i >= 0; i--) { new_patterns.push_back(replacements[i]); new_replacements.push_back(patterns[i]); } patterns.swap(new_patterns); replacements.swap(new_replacements); } // flatten patterns for (int i = 0; i < patterns.size(); i++) patterns[i]->flatten(errh); } // clear r's flags, so we know the current element complement // didn't come from replacements (paranoia) for (int i = 0; i < r->nelements(); i++) r->element(i)->flags = 0; // get adjacency matrices Vector<AdjacencyMatrix *> patterns_adj; for (int i = 0; i < patterns.size(); i++) patterns_adj.push_back(new AdjacencyMatrix(patterns[i])); bool any = true; int nreplace = 0; AdjacencyMatrix matrix(r); while (any) { any = false; for (int i = 0; i < patterns.size(); i++) { Matcher m(patterns[i], patterns_adj[i], r, &matrix, i + 1, errh); if (m.next_match()) { m.replace(replacements[i], pat_names[i], LandmarkT(), errh); nreplace++; any = true; break; } } } // write result if (nreplace) r->remove_dead_elements(0); if (write_router_file(r, output_file, errh) < 0) exit(1); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -