📄 xml2click.cc
字号:
name += 31; if (strcmp(name, "configuration") == 0) { String landmark = xml_landmark(parser); if (xstack.size()) xml_errh->lerror(landmark, "additional configuration section ignored"); else { xstack.push_back(new CxConfig(0, landmark)); next_state = CX_CONFIGURATION; } } else if (strcmp(name, "element") == 0) next_state = do_element(parser, attrs, xml_errh); else if (strcmp(name, "connection") == 0) next_state = do_connection(parser, attrs, xml_errh); else if (strcmp(name, "elementclass") == 0) next_state = do_start_elementclass(parser, attrs, xml_errh); else if (strcmp(name, "synonym") == 0) next_state = do_synonym(parser, attrs, xml_errh); else if (strcmp(name, "compound") == 0) next_state = do_start_compound(parser, attrs, xml_errh); else if (strcmp(name, "formal") == 0) next_state = do_formal(parser, attrs, xml_errh); else next_state = xstates.back(); xstates.push_back(next_state);}static voidend_element_handler(void *v, const XML_Char *name){ XML_Parser parser = (XML_Parser)v; if (strcmp(name, "elementclass") == 0) { if (xstates.back() == CX_ELEMENTCLASS) { if (!xstack.back()->_filled) xml_errh->lerror(xml_landmark(parser), "elementclass tag not filled"); xstack.pop_back(); } } xstates.pop_back();}}static ElementClassT *complete_elementclass(const String &id, const String &xml_landmark, ErrorHandler *errh){ assert(id); int which = class_id_map[id]; if (which < 0) { errh->lerror(xml_landmark, "no such element class '%s'", id.c_str()); return 0; } else { classes[which]->complete_elementclass(errh); return classes[which]->_type; }}intCxConfig::complete_elementclass(ErrorHandler *errh){ if (_type) // already complete return 0; if (_completing) return errh->lerror(_xml_landmark, "circular definition of elementclass '%s'", readable_name().cc()); _completing = true; ContextErrorHandler cerrh(errh, String("In definition of elementclass '") + _name + "' (id '" + _id + "'):", " ", _xml_landmark); int before_nerrors = cerrh.nerrors(); // get previous class ElementClassT *prev_class; if (_prev_class_id) prev_class = ::complete_elementclass(_prev_class_id, _xml_landmark, &cerrh); else if (_prev_class_name) prev_class = ElementClassT::base_type(_prev_class_name); else prev_class = 0; // get enclosing scope RouterT *enclosing_type = _enclosing->router(errh); // check for synonym or empty if (!_filled) // error already reported return 0; if (_is_synonym && prev_class) { _type = new SynonymElementClassT(_name, prev_class, enclosing_type); _type->use(); enclosing_type->add_declared_type(_type, true); return 0; } // otherwise, compound assert(_enclosing); _type = _router = new RouterT(_name, (_landmark ? _landmark : _xml_landmark), enclosing_type); _type->use(); _router->use(); enclosing_type->add_declared_type(_type, true); enclosing_type->check(); _router->set_overload_type(prev_class); // handle formals HashMap<String, int> formal_map(-1); int formal_state = 0; for (int i = 0; i < _formals.size(); i++) if (!_formals[i]) cerrh.lerror(_xml_landmark, "definition missing for formal %d", i); else if (_formals[i][0] != '$') cerrh.lerror(_xml_landmark, "formal %d ('%s') does not begin with '$'", i, _formals[i].c_str()); else if (formal_map[_formals[i]] >= 0) cerrh.lerror(_xml_landmark, "redeclaration of formal '%s'", _formals[i].cc()); else { if ((!_formal_types[i] && formal_state == 1) || (_formal_types[i] == "__REST__" && i != _formals.size() - 1)) cerrh.lerror(_xml_landmark, "formals out of order\n(The correct order is '[positional], [keywords], [__REST__]'.)"); if (_formal_types[i]) formal_state = 1; _router->add_formal(_formals[i], _formal_types[i]); } if (_decl_nformals >= 0 && _formals.size() != _decl_nformals) cerrh.lerror(_xml_landmark, "<formal> count and 'nformals' attribute disagree"); // handle elements if (complete(&cerrh) < 0) return -1; // finally, finish elementclass if (_router->finish_type(&cerrh) < 0) return -1; if (_decl_ninputs >= 0 && _router->ninputs() != _decl_ninputs) cerrh.lerror(_xml_landmark, "input port count and 'ninputs' attribute disagree"); if (_decl_noutputs >= 0 && _router->noutputs() != _decl_noutputs) cerrh.lerror(_xml_landmark, "output port count and 'noutputs' attribute disagree"); return (cerrh.nerrors() == before_nerrors ? 0 : -1);}RouterT *CxConfig::router(ErrorHandler *errh){ if (!_router) { if (_enclosing) { assert(_filled && !_is_synonym); complete_elementclass(errh); if (!_router) return _enclosing->router(errh); } else _router = new RouterT; } return _router;}intCxConfig::complete(ErrorHandler *errh){ RouterT *r = router(errh); if (!r) return -1; // set up elements for (CxElement *e = _elements.begin(); e != _elements.end(); e++) if (ElementT *old_e = r->element(e->name)) { int which = (intptr_t)(old_e->user_data()); ElementT::redeclaration_error(errh, "element", e->name, e->xml_landmark, _elements[which].xml_landmark); } else { ElementClassT *eclass = 0; if (e->class_id) eclass = ::complete_elementclass(e->class_id, e->xml_landmark, errh); else if (e->class_name) eclass = ElementClassT::base_type(e->class_name); ElementT *ne = r->get_element(e->name, (eclass ? eclass : ElementClassT::base_type("Error")), e->config, (e->landmark ? e->landmark : e->xml_landmark)); ne->set_user_data(e - _elements.begin()); } // set up connections for (CxConnection *c = _connections.begin(); c != _connections.end(); c++) { ElementT *frome = r->element(c->from); if (!frome) { errh->lerror(c->xml_landmark, "undeclared element '%s' (first use this block)", c->from.c_str()); frome = r->get_element(c->from, ElementClassT::base_type("Error"), String(), c->xml_landmark); } ElementT *toe = r->element(c->to); if (!toe) { errh->lerror(c->xml_landmark, "undeclared element '%s' (first use this block)", c->to.c_str()); toe = r->get_element(c->to, ElementClassT::base_type("Error"), String(), c->xml_landmark); } r->add_connection(frome, c->fromport, toe, c->toport, c->xml_landmark); } // check elements' ninputs and noutputs for (CxElement *e = _elements.begin(); e != _elements.end(); e++) if (e->ninputs >= 0 || e->noutputs >= 0) if (ElementT *et = r->element(e->name)) { if (e->ninputs >= 0 && et->ninputs() != e->ninputs) errh->lerror(et->landmark(), "'%s' input port count and 'ninputs' attribute disagree", e->name.c_str()); if (e->noutputs >= 0 && et->noutputs() != e->noutputs) errh->lerror(et->landmark(), "'%s' output port count and 'noutputs' attribute disagree", e->name.c_str()); } return 0;}static voidprocess(const char *infile, bool file_is_expr, const char *outfile, ErrorHandler *errh){ int before = errh->nerrors(); String contents; if (file_is_expr) contents = infile; else { contents = file_string(infile, errh); if (!contents && errh->nerrors() != before) return; } XML_Parser parser = XML_ParserCreateNS(0, '|'); XML_SetElementHandler(parser, start_element_handler, end_element_handler); XML_UseParserAsHandlerArg(parser); xml_errh = errh; xml_file = filename_landmark(infile, file_is_expr); xstates.clear(); xstates.push_back(CX_NONE); if (XML_Parse(parser, contents.data(), contents.length(), 1) == 0) { xml_error(parser, "XML parse error: %s", XML_ErrorString(XML_GetErrorCode(parser))); return; } if (xstack.size() == 0 && errh->nerrors() == before) errh->lerror(xml_file, "no configuration section"); // if no errors, resolve router if (errh->nerrors() == before) { for (int i = 0; i < classes.size(); i++) classes[i]->complete_elementclass(errh); xstack.back()->complete(errh); xstack.back()->router(errh)->check(); } // flatten router if appropriate if (errh->nerrors() == before && ::flatten) xstack.back()->router(errh)->flatten(errh); // if no errors, write output if (errh->nerrors() == before) write_router_file(xstack.back()->router(errh), outfile, errh); // delete state for (int i = 0; i < classes.size(); i++) delete classes[i]; classes.clear(); if (xstack.size()) delete xstack[0]; xstack.clear(); xstates.clear(); class_id_map.clear();}voidshort_usage(){ fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\Try '%s --help' for more information.\n", program_name, program_name);}voidusage(){ printf("\'Xml2click' reads an XML description of a Click router configuration and\n\outputs a Click-language file corresponding to that configuration.\n\\n\Usage: %s [OPTION]... [XMLFILE]\n\\n\Options:\n\ -f, --file FILE Read router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as XML router configuration.\n\ -o, --output FILE Write output to FILE.\n\ -F, --flatten Flatten configuration before output.\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; while (1) { int opt = Clp_Next(clp); switch (opt) { case HELP_OPT: usage(); exit(0); break; case VERSION_OPT: printf("xml2click (Click) %s\n", CLICK_VERSION); printf("Copyright (c) 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 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 FLATTEN_OPT: flatten = !clp->negated; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: process(router_file, file_is_expr, output_file, errh); exit(errh->nerrors() > 0 ? 1 : 0);}#include <click/vector.cc>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -