?? xml2click.cc
字號(hào):
// -*- c-basic-offset: 4 -*-/* * click2xml.cc -- translate Click configurations into and out of XML * Eddie Kohler * * Copyright (c) 2002 International Computer Science Institute * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/pathvars.h>#include <expat.h>#include "routert.hh"#include "lexert.hh"#include "lexertinfo.hh"#include <click/error.hh>#include <click/driver.hh>#include <click/straccum.hh>#include <click/confparse.hh>#include <click/clp.h>#include "toolutils.hh"#include "processingt.hh"#include "elementmap.hh"#include "xml2click.hh"#define HELP_OPT 300#define VERSION_OPT 301#define CLICKPATH_OPT 302#define ROUTER_OPT 303#define EXPRESSION_OPT 304#define OUTPUT_OPT 305#define FLATTEN_OPT 306static const Clp_Option options[] = { { "clickpath", 'C', CLICKPATH_OPT, Clp_ValString, 0 }, { "expression", 'e', EXPRESSION_OPT, Clp_ValString, 0 }, { "file", 'f', ROUTER_OPT, Clp_ValString, 0 }, { "flatten", 'F', FLATTEN_OPT, 0, Clp_Negate }, { "help", 0, HELP_OPT, 0, 0 }, { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 }, { "version", 'v', VERSION_OPT, 0, 0 },};static const char *program_name;static ErrorHandler *xml_errh;static String xml_file;static bool flatten = false;static inline Stringxml_landmark(XML_Parser parser){ return xml_file + ":" + String(XML_GetCurrentLineNumber(parser));}static intxml_error(XML_Parser parser, const char *format, ...){ va_list val; va_start(val, format); xml_errh->xmessage(xml_landmark(parser), ErrorHandler::e_error, format, val); va_end(val); return -EINVAL;}CxConfig::CxConfig(CxConfig *enclosing, const String &xml_landmark) : _enclosing(enclosing), _depth(enclosing ? enclosing->_depth + 1 : 0), _filled(false), _xml_landmark(xml_landmark), _decl_ninputs(-1), _decl_noutputs(-1), _decl_nformals(-1), _type(0), _router(0), _completing(false){}CxConfig::~CxConfig(){ if (_type) _type->unuse(); if (_router) _router->unuse();}StringCxConfig::readable_name() const{ return (_name ? _name : String("<anonymous>"));}enum CxState { CX_NONE, CX_CONFIGURATION, CX_ELEMENTCLASS, CX_COMPOUND, CX_IN_EMPTY, CX_ERROR };static Vector<CxState> xstates;static Vector<CxConfig *> xstack;static HashTable<String, int> class_id_map(-1);static Vector<CxConfig *> classes;static CxStatedo_element(XML_Parser parser, const XML_Char **attrs, ErrorHandler *errh){ String landmark = xml_landmark(parser); if (xstates.back() != CX_CONFIGURATION && xstates.back() != CX_COMPOUND) { if (xstates.back() != CX_ERROR) errh->lerror(landmark, "<element> tag outside of <configuration>"); return CX_ERROR; } CxElement e; e.xml_landmark = landmark; bool ok = true; String file, line; for (const XML_Char **a = attrs; *a; a += 2) if (strcmp(a[0], "name") == 0) { if (!cp_is_click_id(a[1])) errh->lerror(landmark, "'name' attribute not a Click identifier"); e.name = a[1]; } else if (strcmp(a[0], "classname") == 0) { if (!cp_is_click_id(a[1])) errh->lerror(landmark, "'classname' attribute not a Click identifier"); e.class_name = a[1]; } else if (strcmp(a[0], "classid") == 0) e.class_id = a[1]; else if (strcmp(a[0], "config") == 0) e.config = a[1]; else if (strcmp(a[0], "file") == 0) file = a[1]; else if (strcmp(a[0], "line") == 0) line = a[1]; else if (strcmp(a[0], "ninputs") == 0) { if (!cp_integer(a[1], &e.ninputs)) errh->lerror(landmark, "'ninputs' attribute must be an integer"); } else if (strcmp(a[0], "noutputs") == 0) { if (!cp_integer(a[1], &e.noutputs)) errh->lerror(landmark, "'noutputs' attribute must be an integer"); } if (file && line) e.landmark = file + ":" + line; else if (file) e.landmark = file; else if (line) e.landmark = "line " + line; if (e.class_name && e.class_id) { errh->lerror(landmark, "conflicting attributes 'classname' and 'classid'"); e.class_name = String(); } else if (!e.class_name && !e.class_id) { errh->lerror(landmark, "element declared without a class"); ok = false; } if (!e.name) { errh->lerror(landmark, "element declared without a name"); ok = false; } if (ok) xstack.back()->_elements.push_back(e); return CX_IN_EMPTY;}static CxStatedo_connection(XML_Parser parser, const XML_Char **attrs, ErrorHandler *errh){ String landmark = xml_landmark(parser); if (xstates.back() != CX_CONFIGURATION && xstates.back() != CX_COMPOUND) { if (xstates.back() != CX_ERROR) errh->lerror(landmark, "<connection> tag meaningless outside of <configuration>"); return CX_ERROR; } CxConnection e; e.xml_landmark = landmark; bool ok = true; for (const XML_Char **a = attrs; *a; a += 2) if (strcmp(a[0], "from") == 0) e.from = a[1]; else if (strcmp(a[0], "to") == 0) e.to = a[1]; else if (strcmp(a[0], "fromport") == 0) { if (!cp_integer(a[1], &e.fromport) && e.fromport >= 0) errh->lerror(landmark, "'fromport' should be port number"); } else if (strcmp(a[0], "toport") == 0) { if (!cp_integer(a[1], &e.toport) && e.toport >= 0) errh->lerror(landmark, "'toport' should be port number"); } if (!e.from || !e.to) { errh->lerror(landmark, "connection lacks 'from' or 'to' attribute"); ok = false; } if (ok) xstack.back()->_connections.push_back(e); return CX_IN_EMPTY;}static CxStatedo_start_elementclass(XML_Parser parser, const XML_Char **attrs, ErrorHandler *errh){ String landmark = xml_landmark(parser); if (xstates.back() != CX_CONFIGURATION && xstates.back() != CX_COMPOUND) { if (xstates.back() != CX_ERROR) errh->lerror(landmark, "<elementclass> tag outside of <configuration>"); return CX_ERROR; } CxConfig *nc = new CxConfig(xstack.back(), landmark); String file, line; for (const XML_Char **a = attrs; *a; a += 2) if (strcmp(a[0], "classname") == 0) { if (!cp_is_click_id(a[1])) errh->lerror(landmark, "'classname' attribute not a valid Click identifier"); nc->_name = a[1]; } else if (strcmp(a[0], "classid") == 0) nc->_id = a[1]; else if (strcmp(a[0], "file") == 0) file = a[1]; else if (strcmp(a[0], "line") == 0) line = a[1]; if (file && line) nc->_landmark = file + ":" + line; else if (file) nc->_landmark = file; else if (line) nc->_landmark = "line " + line; if (!nc->_id) errh->lerror(landmark, "element class declared without an ID"); else class_id_map.set(nc->_id, classes.size()); classes.push_back(nc); xstack.push_back(nc); return CX_ELEMENTCLASS;}static CxStatedo_synonym(XML_Parser parser, const XML_Char **attrs, ErrorHandler *errh){ String landmark = xml_landmark(parser); if (xstates.back() != CX_ELEMENTCLASS) { if (xstates.back() != CX_ERROR) errh->lerror(landmark, "<synonym> tag outside of <elementclass>"); return CX_ERROR; } else if (xstack.back()->_filled) { errh->lerror(landmark, "element class already defined"); return CX_ERROR; } CxConfig *cx = xstack.back(); for (const XML_Char **a = attrs; *a; a += 2) if (strcmp(a[0], "classname") == 0) { if (!cp_is_click_id(a[1])) errh->lerror(landmark, "'classname' attribute not a Click identifier"); cx->_prev_class_name = a[1]; } else if (strcmp(a[0], "classid") == 0) cx->_prev_class_id = a[1]; if (cx->_prev_class_name && cx->_prev_class_id) { errh->lerror(landmark, "conflicting attributes 'classname' and 'classid'"); cx->_prev_class_name = String(); } else if (!cx->_prev_class_name && !cx->_prev_class_id) errh->lerror(landmark, "synonym refers to no other class"); cx->_filled = true; cx->_is_synonym = true; return CX_IN_EMPTY;}static CxStatedo_start_compound(XML_Parser parser, const XML_Char **attrs, ErrorHandler *errh){ String landmark = xml_landmark(parser); if (xstates.back() != CX_ELEMENTCLASS) { if (xstates.back() != CX_ERROR) errh->lerror(landmark, "<compound> tag outside of <elementclass>"); return CX_ERROR; } else if (xstack.back()->_filled) { errh->lerror(landmark, "element class already defined"); return CX_ERROR; } CxConfig *cx = xstack.back(); for (const XML_Char **a = attrs; *a; a += 2) if (strcmp(a[0], "overloadclassname") == 0) { if (!cp_is_click_id(a[1])) errh->lerror(landmark, "'overloadclassname' attribute not a valid Click identifier"); cx->_prev_class_name = a[1]; } else if (strcmp(a[0], "overloadclassid") == 0) cx->_prev_class_id = a[1]; else if (strcmp(a[0], "ninputs") == 0) { if (!cp_integer(a[1], &cx->_decl_ninputs)) errh->lerror(landmark, "'ninputs' attribute must be an integer"); } else if (strcmp(a[0], "noutputs") == 0) { if (!cp_integer(a[1], &cx->_decl_noutputs)) errh->lerror(landmark, "'noutputs' attribute must be an integer"); } else if (strcmp(a[0], "nformals") == 0) { if (!cp_integer(a[1], &cx->_decl_nformals)) errh->lerror(landmark, "'noutputs' attribute must be an integer"); } // XXX nformals etc. if (cx->_prev_class_name && cx->_prev_class_id) { errh->lerror(landmark, "conflicting attributes 'classname' and 'classid'"); cx->_prev_class_name = String(); } cx->_filled = true; cx->_is_synonym = false; return CX_COMPOUND;}static CxStatedo_formal(XML_Parser parser, const XML_Char **attrs, ErrorHandler *errh){ String landmark = xml_landmark(parser); if (xstates.back() != CX_COMPOUND) { if (xstates.back() != CX_ERROR) errh->lerror(landmark, "<formal> tag meaningless outside of <compound>"); return CX_ERROR; } int number = -1; String name, key; for (const XML_Char **a = attrs; *a; a += 2) if (strcmp(a[0], "name") == 0) { name = a[1]; if (!cp_is_word(name)) errh->lerror(landmark, "'name' should be formal name"); } else if (strcmp(a[0], "number") == 0) { if (!cp_integer(a[1], &number) || number < 0) errh->lerror(landmark, "'number' should be formal argument position"); } else if (strcmp(a[0], "key") == 0) { key = a[1]; if (!cp_is_word(key)) errh->lerror(landmark, "'key' should be formal keyword"); } while (xstack.back()->_formals.size() <= number) { xstack.back()->_formals.push_back(String()); xstack.back()->_formal_types.push_back(String()); } if (xstack.back()->_formals[number]) errh->lerror(landmark, "formal parameter %d already defined as '$%s'", number, xstack.back()->_formals[number].c_str()); else { xstack.back()->_formals[number] = name; xstack.back()->_formal_types[number] = key; } return CX_IN_EMPTY;}extern "C" {static voidstart_element_handler(void *v, const XML_Char *name, const XML_Char **attrs){ XML_Parser parser = (XML_Parser)v; CxState next_state = CX_ERROR; // handle XML namespaces
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -