openflow build environment setup
This commit is contained in:
228
openflow/include/clicktool/eclasst.hh
Normal file
228
openflow/include/clicktool/eclasst.hh
Normal file
@@ -0,0 +1,228 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_ECLASST_HH
|
||||
#define CLICK_ECLASST_HH
|
||||
#include <click/string.hh>
|
||||
#include <stddef.h>
|
||||
#include <click/vector.hh>
|
||||
#include <click/hashtable.hh>
|
||||
#include "elementmap.hh"
|
||||
class ErrorHandler;
|
||||
class StringAccum;
|
||||
class RouterT;
|
||||
class ElementT;
|
||||
class VariableEnvironment;
|
||||
class ElementMap;
|
||||
class SynonymElementClassT;
|
||||
class LandmarkT;
|
||||
|
||||
class ElementClassT { public:
|
||||
|
||||
ElementClassT(const String &name);
|
||||
virtual ~ElementClassT();
|
||||
|
||||
static void set_base_type_factory(ElementClassT *(*factory)(const String &));
|
||||
static ElementClassT *base_type(const String &);
|
||||
static ElementClassT *tunnel_type();
|
||||
|
||||
void use() { _use_count++; }
|
||||
void unuse() { if (--_use_count <= 0) delete this; }
|
||||
|
||||
const String &name() const { return _name; }
|
||||
String printable_name() const { return _printable_name; }
|
||||
const char *printable_name_c_str() const { return _printable_name.c_str(); }
|
||||
void set_printable_name(const String &s) { _printable_name = s; }
|
||||
virtual String landmark() const { return String(); }
|
||||
|
||||
// 'primitive' means 'not tunnel, not compound, not synonym'.
|
||||
virtual bool primitive() const { return true; }
|
||||
virtual bool overloaded() const { return false; }
|
||||
bool tunnel() const { return this == tunnel_type(); }
|
||||
|
||||
ElementTraits &force_traits() const;
|
||||
ElementTraits &force_traits(ElementMap *emap) const;
|
||||
inline const ElementTraits &traits() const;
|
||||
inline const ElementTraits &traits(ElementMap *emap) const;
|
||||
virtual const ElementTraits *find_traits(ElementMap *emap) const;
|
||||
|
||||
inline const String &port_count_code() const;
|
||||
inline const String &processing_code() const;
|
||||
inline bool requires(const String &) const;
|
||||
inline bool provides(const String &) const;
|
||||
const String &package() const;
|
||||
const String &documentation_name() const;
|
||||
String documentation_url() const;
|
||||
|
||||
// where was this type declared?
|
||||
virtual RouterT *declaration_scope() const;
|
||||
virtual ElementClassT *overload_type() const;
|
||||
|
||||
virtual void collect_types(HashTable<ElementClassT *, int> &) const;
|
||||
virtual void collect_overloads(Vector<ElementClassT *> &) const;
|
||||
|
||||
static ElementT *expand_element(ElementT *element, RouterT *dest,
|
||||
const String &prefix,
|
||||
const VariableEnvironment &env,
|
||||
ErrorHandler *errh);
|
||||
|
||||
virtual bool need_resolve() const;
|
||||
|
||||
/** @brief Resolve an element declaration.
|
||||
* @param ninputs number of inputs used
|
||||
* @param noutputs number of outputs used
|
||||
* @param[in,out] args configuration arguments
|
||||
* @param errh error handler
|
||||
* @param landmark landmark for errors
|
||||
*/
|
||||
virtual ElementClassT *resolve(int ninputs, int noutputs,
|
||||
Vector<String> &args,
|
||||
ErrorHandler *errh,
|
||||
const LandmarkT &landmark);
|
||||
|
||||
/** @brief Create a new scope with the appropriate declarations.
|
||||
* @param args configuration arguments
|
||||
* @param scope original scope
|
||||
* @param[out] new_scope new scope
|
||||
* @pre &scope != &new_scope
|
||||
*
|
||||
* The new scope equals the old scope, possibly restricted according to
|
||||
* lexical scoping, plus declarations for the configuration arguments. */
|
||||
virtual void create_scope(const Vector<String> &args,
|
||||
const VariableEnvironment &scope,
|
||||
VariableEnvironment &new_scope);
|
||||
|
||||
virtual ElementT *complex_expand_element(ElementT *element,
|
||||
const Vector<String> &conf,
|
||||
RouterT *dest,
|
||||
const String &prefix,
|
||||
const VariableEnvironment &env,
|
||||
ErrorHandler *errh);
|
||||
|
||||
enum UnparseKind { UNPARSE_NAMED, UNPARSE_ANONYMOUS, UNPARSE_OVERLOAD };
|
||||
virtual void unparse_declaration(StringAccum &, const String &, UnparseKind, ElementClassT *stop);
|
||||
virtual String unparse_signature() const;
|
||||
static String unparse_signature(const String &name, const Vector<String> *formal_types, int nargs, int ninputs, int noutputs);
|
||||
|
||||
virtual void *cast(const char *) { return 0; }
|
||||
virtual SynonymElementClassT *cast_synonym() { return 0; }
|
||||
virtual RouterT *cast_router() { return 0; }
|
||||
|
||||
private:
|
||||
|
||||
String _name;
|
||||
String _printable_name;
|
||||
int _use_count;
|
||||
|
||||
mutable int _traits_version;
|
||||
mutable const ElementTraits *_traits;
|
||||
|
||||
static ElementClassT *the_tunnel_type;
|
||||
|
||||
ElementClassT(const ElementClassT &);
|
||||
ElementClassT &operator=(const ElementClassT &);
|
||||
|
||||
ElementT *direct_expand_element(ElementT *element, RouterT *dest,
|
||||
const String &prefix,
|
||||
const VariableEnvironment &env,
|
||||
ErrorHandler *errh);
|
||||
|
||||
};
|
||||
|
||||
class SynonymElementClassT : public ElementClassT { public:
|
||||
|
||||
SynonymElementClassT(const String &, ElementClassT *, RouterT *);
|
||||
|
||||
ElementClassT *synonym_of() const { return _eclass; }
|
||||
|
||||
bool need_resolve() const;
|
||||
ElementClassT *resolve(int, int, Vector<String> &, ErrorHandler *, const LandmarkT &);
|
||||
void create_scope(const Vector<String> &, const VariableEnvironment &, VariableEnvironment &);
|
||||
ElementT *complex_expand_element(ElementT *, const Vector<String> &, RouterT *, const String &prefix, const VariableEnvironment &, ErrorHandler *);
|
||||
|
||||
void collect_types(HashTable<ElementClassT *, int> &) const;
|
||||
void collect_overloads(Vector<ElementClassT *> &) const;
|
||||
|
||||
void unparse_declaration(StringAccum &, const String &, UnparseKind, ElementClassT *);
|
||||
|
||||
bool primitive() const { return false; }
|
||||
bool overloaded() const { return _eclass->overloaded(); }
|
||||
const ElementTraits *find_traits(ElementMap *emap) const;
|
||||
|
||||
RouterT *declaration_scope() const;
|
||||
ElementClassT *overload_type() const { return _eclass; }
|
||||
|
||||
SynonymElementClassT *cast_synonym() { return this; }
|
||||
RouterT *cast_router();
|
||||
|
||||
private:
|
||||
|
||||
ElementClassT *_eclass;
|
||||
RouterT *_declaration_scope;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline ElementClassT *
|
||||
ElementClassT::tunnel_type()
|
||||
{
|
||||
assert(the_tunnel_type);
|
||||
return the_tunnel_type;
|
||||
}
|
||||
|
||||
inline const ElementTraits &
|
||||
ElementClassT::traits(ElementMap *emap) const
|
||||
{
|
||||
if (_traits_version != emap->version()) {
|
||||
_traits = find_traits(emap);
|
||||
_traits_version = emap->version();
|
||||
}
|
||||
return *_traits;
|
||||
}
|
||||
|
||||
inline const ElementTraits &
|
||||
ElementClassT::traits() const
|
||||
{
|
||||
return traits(ElementMap::default_map());
|
||||
}
|
||||
|
||||
inline ElementTraits &
|
||||
ElementClassT::force_traits() const
|
||||
{
|
||||
return force_traits(ElementMap::default_map());
|
||||
}
|
||||
|
||||
inline const String &
|
||||
ElementClassT::documentation_name() const
|
||||
{
|
||||
return traits().documentation_name;
|
||||
}
|
||||
|
||||
inline const String &
|
||||
ElementClassT::port_count_code() const
|
||||
{
|
||||
return traits().port_count_code;
|
||||
}
|
||||
|
||||
inline const String &
|
||||
ElementClassT::processing_code() const
|
||||
{
|
||||
return traits().processing_code;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ElementClassT::requires(const String &req) const
|
||||
{
|
||||
return traits().requires(req);
|
||||
}
|
||||
|
||||
inline bool
|
||||
ElementClassT::provides(const String &req) const
|
||||
{
|
||||
return traits().provides(req);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline size_t hashcode(const ElementClassT * const &e) {
|
||||
return CLICK_NAME(hashcode)(static_cast<const void *>(e));
|
||||
}
|
||||
|
||||
#endif
|
||||
179
openflow/include/clicktool/elementmap.hh
Normal file
179
openflow/include/clicktool/elementmap.hh
Normal file
@@ -0,0 +1,179 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_ELEMENTMAP_HH
|
||||
#define CLICK_ELEMENTMAP_HH
|
||||
#include "etraits.hh"
|
||||
#include <click/hashtable.hh>
|
||||
class RouterT;
|
||||
class ErrorHandler;
|
||||
|
||||
class ElementMap { public:
|
||||
|
||||
ElementMap();
|
||||
ElementMap(const String&, ErrorHandler* = 0);
|
||||
~ElementMap();
|
||||
|
||||
static ElementMap* default_map() { return the_element_map; }
|
||||
static void push_default(ElementMap *emap);
|
||||
static void pop_default(ElementMap *emap);
|
||||
static void pop_default();
|
||||
|
||||
void use() { _use_count++; }
|
||||
void unuse() { _use_count--; }
|
||||
|
||||
int size() const { return _e.size(); }
|
||||
bool empty() const { return _e.size() == 1; }
|
||||
int32_t version() const { return _version; }
|
||||
|
||||
Traits &force_traits(const String &class_name);
|
||||
inline const Traits &traits(const String &class_name) const;
|
||||
const Traits &traits_at(int i) const { return _e[i]; }
|
||||
inline bool has_traits(const String &class_name) const;
|
||||
inline int traits_index(const String &class_name) const;
|
||||
|
||||
bool provides_global(const String&) const;
|
||||
|
||||
int definition_index(int i) const { return _e[i].def_index; }
|
||||
const String& source_directory(const Traits&) const;
|
||||
const String& package(const Traits&) const;
|
||||
const String& package(const String&) const;
|
||||
String documentation_url(const Traits&) const;
|
||||
|
||||
class TraitsIterator;
|
||||
TraitsIterator begin_elements() const;
|
||||
|
||||
int add(const Traits &traits);
|
||||
void remove_at(int i);
|
||||
|
||||
void parse(const String& data, ErrorHandler* = 0);
|
||||
void parse(const String& data, const String& package_name, ErrorHandler* = 0);
|
||||
void parse_xml(const String& data, const String& package_name, ErrorHandler*);
|
||||
bool parse_default_file(const String& default_path, ErrorHandler* errh, bool verbose = false);
|
||||
bool parse_package_file(const String& package_name, const RouterT* router, const String& default_path, ErrorHandler* errh, bool verbose = false);
|
||||
bool parse_requirement_files(RouterT*, const String& default_path, ErrorHandler* errh, bool verbose = false);
|
||||
bool parse_all_files(RouterT*, const String& default_path, ErrorHandler*);
|
||||
static void report_file_not_found(String default_path, bool found_default, ErrorHandler*);
|
||||
String unparse(const String& package = String()) const;
|
||||
String unparse_nonxml() const;
|
||||
|
||||
int check_completeness(const RouterT*, ErrorHandler*) const;
|
||||
bool driver_indifferent(const RouterT*, int driver_mask = Driver::ALLMASK, ErrorHandler* = 0) const;
|
||||
bool driver_compatible(const RouterT*, int driver, ErrorHandler* = 0) const;
|
||||
|
||||
int provided_driver_mask() const { return _provided_driver_mask; }
|
||||
int driver_mask() const { return _driver_mask; }
|
||||
void set_driver(int d) { set_driver_mask(1 << d); }
|
||||
void set_driver_mask(int mask);
|
||||
int pick_driver(int wanted_driver, const RouterT* router, ErrorHandler* = 0) const;
|
||||
|
||||
private:
|
||||
|
||||
struct Globals {
|
||||
String srcdir;
|
||||
String compile_flags;
|
||||
String package;
|
||||
String dochref;
|
||||
int driver_mask;
|
||||
};
|
||||
|
||||
Vector<Traits> _e;
|
||||
HashTable<String, int> _name_map;
|
||||
|
||||
Vector<Globals> _def;
|
||||
|
||||
int _use_count;
|
||||
int _driver_mask;
|
||||
int _provided_driver_mask;
|
||||
mutable int32_t _version;
|
||||
|
||||
int get_driver_mask(const String&);
|
||||
int driver_elt_index(int) const;
|
||||
|
||||
void collect_indexes(const RouterT*, Vector<int>&, ErrorHandler*) const;
|
||||
int compatible_driver_mask(const RouterT*, ErrorHandler* = 0) const;
|
||||
|
||||
static int32_t version_counter;
|
||||
static ElementMap* the_element_map;
|
||||
void incr_version() const;
|
||||
|
||||
bool find_and_parse_package_file(const String& package_name, const RouterT* router, const String& default_path, ErrorHandler* errh, const String& filetype, bool verbose);
|
||||
|
||||
};
|
||||
|
||||
|
||||
class ElementMap::TraitsIterator { public:
|
||||
|
||||
TraitsIterator(const ElementMap*, bool elements_only);
|
||||
|
||||
operator bool() { return _index < _emap->size(); }
|
||||
void operator++(int);
|
||||
|
||||
const ElementTraits& value() const { return _emap->traits_at(_index); }
|
||||
int traits_index() const { return _index; }
|
||||
|
||||
private:
|
||||
|
||||
const ElementMap* _emap;
|
||||
int _index;
|
||||
bool _elements_only;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline int
|
||||
ElementMap::traits_index(const String &class_name) const
|
||||
{
|
||||
int i = _name_map[class_name];
|
||||
if (!(_e[i].driver_mask & _driver_mask) && i > 0)
|
||||
i = driver_elt_index(i);
|
||||
return i;
|
||||
}
|
||||
|
||||
inline const Traits &
|
||||
ElementMap::traits(const String &class_name) const
|
||||
{
|
||||
return _e[traits_index(class_name)];
|
||||
}
|
||||
|
||||
inline bool
|
||||
ElementMap::has_traits(const String &class_name) const
|
||||
{
|
||||
return traits_index(class_name) > 0;
|
||||
}
|
||||
|
||||
inline const String&
|
||||
ElementMap::source_directory(const ElementTraits& t) const
|
||||
{
|
||||
return _def[t.def_index].srcdir;
|
||||
}
|
||||
|
||||
inline const String&
|
||||
ElementMap::package(const ElementTraits& t) const
|
||||
{
|
||||
return _def[t.def_index].package;
|
||||
}
|
||||
|
||||
inline const String&
|
||||
ElementMap::package(const String& name) const
|
||||
{
|
||||
return package(traits(name));
|
||||
}
|
||||
|
||||
inline void
|
||||
ElementMap::incr_version() const
|
||||
{
|
||||
_version = version_counter = (version_counter + 1) & 0x7FFFFFFF;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ElementMap::provides_global(const String& req) const
|
||||
{
|
||||
return _e[0].provides(req);
|
||||
}
|
||||
|
||||
inline ElementMap::TraitsIterator
|
||||
ElementMap::begin_elements() const
|
||||
{
|
||||
return TraitsIterator(this, true);
|
||||
}
|
||||
|
||||
#endif
|
||||
313
openflow/include/clicktool/elementt.hh
Normal file
313
openflow/include/clicktool/elementt.hh
Normal file
@@ -0,0 +1,313 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_ELEMENTT_HH
|
||||
#define CLICK_ELEMENTT_HH
|
||||
#include "eclasst.hh"
|
||||
#include "landmarkt.hh"
|
||||
|
||||
class ElementT { public:
|
||||
|
||||
int flags;
|
||||
|
||||
ElementT();
|
||||
ElementT(const String &name, ElementClassT *type, const String &config, const LandmarkT &landmark = LandmarkT::empty_landmark());
|
||||
~ElementT();
|
||||
|
||||
RouterT *router() const { return _owner; }
|
||||
int eindex() const { return _eindex; }
|
||||
|
||||
bool live() const { return _type; }
|
||||
bool dead() const { return !_type; }
|
||||
void kill();
|
||||
|
||||
const String &name() const { return _name; }
|
||||
const char *name_c_str() const { return _name.c_str(); }
|
||||
bool name_unassigned() const { return _name && _name[0] == ';'; }
|
||||
bool was_anonymous() const { return _was_anonymous; }
|
||||
|
||||
ElementClassT *type() const { return _type; }
|
||||
ElementClassT *resolve(const VariableEnvironment &env,
|
||||
VariableEnvironment *new_env,
|
||||
ErrorHandler *errh = 0) const;
|
||||
ElementClassT *resolved_type(const VariableEnvironment &env, ErrorHandler *errh = 0) const;
|
||||
|
||||
String type_name() const { return _type->name(); }
|
||||
String printable_type_name() const { return _type->printable_name(); }
|
||||
const char *type_name_c_str() const { return _type->printable_name_c_str(); }
|
||||
|
||||
void set_type(ElementClassT *);
|
||||
inline RouterT *resolved_router(const VariableEnvironment &env, ErrorHandler *errh = 0) const;
|
||||
|
||||
inline const String &flow_code(ElementMap *emap) const;
|
||||
inline const String &flow_code() const;
|
||||
|
||||
const String &config() const { return _configuration; }
|
||||
const String &configuration() const { return _configuration; }
|
||||
inline void set_configuration(const String &s);
|
||||
|
||||
const LandmarkT &landmarkt() const { return _landmark; }
|
||||
String landmark() const { return _landmark.str(); }
|
||||
String decorated_landmark() const { return _landmark.decorated_str(); }
|
||||
void set_landmark(const LandmarkT &lm) { _landmark = lm; }
|
||||
|
||||
inline bool tunnel() const;
|
||||
inline bool tunnel_connected() const;
|
||||
ElementT *tunnel_input() const { return _tunnel_input; }
|
||||
ElementT *tunnel_output() const { return _tunnel_output; }
|
||||
|
||||
int nports(bool isoutput) const { return isoutput ? _noutputs : _ninputs; }
|
||||
int ninputs() const { return _ninputs; }
|
||||
int noutputs() const { return _noutputs; }
|
||||
|
||||
inline String declaration() const;
|
||||
inline String reverse_declaration() const;
|
||||
|
||||
void *user_data() const { return _user_data; }
|
||||
void set_user_data(void *v) { _user_data = v; }
|
||||
void set_user_data(intptr_t v) { _user_data = (void *)v; }
|
||||
|
||||
static bool name_ok(const String &, bool allow_anon_names = false);
|
||||
static void redeclaration_error(ErrorHandler *, const char *type, String name, const String &landmark, const String &old_landmark);
|
||||
|
||||
private:
|
||||
|
||||
int _eindex;
|
||||
String _name;
|
||||
ElementClassT *_type;
|
||||
mutable ElementClassT *_resolved_type;
|
||||
enum { resolved_type_error = 1, resolved_type_fragile = 2 };
|
||||
mutable short _resolved_type_status;
|
||||
bool _was_anonymous;
|
||||
String _configuration;
|
||||
LandmarkT _landmark;
|
||||
int _ninputs;
|
||||
int _noutputs;
|
||||
ElementT *_tunnel_input;
|
||||
ElementT *_tunnel_output;
|
||||
RouterT *_owner;
|
||||
void *_user_data;
|
||||
|
||||
ElementT(const ElementT &);
|
||||
ElementT &operator=(const ElementT &);
|
||||
|
||||
inline void semiresolve_type() const {
|
||||
if (!_resolved_type && _type && _type->primitive()) {
|
||||
_resolved_type = _type;
|
||||
_resolved_type->use();
|
||||
}
|
||||
}
|
||||
inline void unresolve_type() {
|
||||
if (_resolved_type) {
|
||||
_resolved_type->unuse();
|
||||
_resolved_type = 0;
|
||||
}
|
||||
}
|
||||
inline void set_ninputs(int n) {
|
||||
unresolve_type();
|
||||
_ninputs = n;
|
||||
}
|
||||
inline void set_noutputs(int n) {
|
||||
unresolve_type();
|
||||
_noutputs = n;
|
||||
}
|
||||
|
||||
friend class RouterT;
|
||||
|
||||
};
|
||||
|
||||
struct PortT {
|
||||
|
||||
ElementT *element;
|
||||
int port;
|
||||
|
||||
PortT() : element(0), port(-1) { }
|
||||
PortT(ElementT *e, int p) : element(e), port(p) { }
|
||||
|
||||
static const PortT null_port;
|
||||
|
||||
typedef bool (PortT::*unspecified_bool_type)() const;
|
||||
|
||||
operator unspecified_bool_type() const {
|
||||
return element != 0 ? &PortT::live : 0;
|
||||
}
|
||||
|
||||
bool live() const { return element != 0; }
|
||||
bool dead() const { return element == 0; }
|
||||
RouterT *router() const { return (element ? element->router() : 0); }
|
||||
|
||||
int eindex() const { return (element ? element->eindex() : -1); }
|
||||
|
||||
int index_in(const Vector<PortT> &, int start = 0) const;
|
||||
int force_index_in(Vector<PortT> &, int start = 0) const;
|
||||
|
||||
String unparse(bool isoutput, bool with_class = false) const;
|
||||
String unparse_input(bool with_class = false) const {
|
||||
return unparse(false, with_class);
|
||||
}
|
||||
String unparse_output(bool with_class = false) const {
|
||||
return unparse(true, with_class);
|
||||
}
|
||||
|
||||
static void sort(Vector<PortT> &);
|
||||
|
||||
};
|
||||
|
||||
class ConnectionT { public:
|
||||
|
||||
inline ConnectionT();
|
||||
ConnectionT(const PortT &from, const PortT &to,
|
||||
const LandmarkT &landmark = LandmarkT::empty_landmark());
|
||||
|
||||
typedef PortT::unspecified_bool_type unspecified_bool_type;
|
||||
inline operator unspecified_bool_type() const;
|
||||
|
||||
enum { end_to = 0, end_from = 1 };
|
||||
|
||||
bool live() const { return _end[end_from].live(); }
|
||||
bool dead() const { return _end[end_from].dead(); }
|
||||
|
||||
RouterT *router() const { return _end[end_to].router(); }
|
||||
|
||||
const PortT &end(bool isoutput) const {
|
||||
return _end[isoutput];
|
||||
}
|
||||
ElementT *element(bool isoutput) const {
|
||||
return _end[isoutput].element;
|
||||
}
|
||||
int eindex(bool isoutput) const {
|
||||
return _end[isoutput].eindex();
|
||||
}
|
||||
int port(bool isoutput) const {
|
||||
return _end[isoutput].port;
|
||||
}
|
||||
|
||||
const PortT &from() const { return end(end_from); }
|
||||
const PortT &to() const { return end(end_to); }
|
||||
ElementT *from_element() const { return element(end_from); }
|
||||
int from_eindex() const { return eindex(end_from); }
|
||||
int from_port() const { return port(end_from); }
|
||||
ElementT *to_element() const { return element(end_to); }
|
||||
int to_eindex() const { return eindex(end_to); }
|
||||
int to_port() const { return port(end_to); }
|
||||
String landmark() const { return _landmark.str(); }
|
||||
String decorated_landmark() const { return _landmark.decorated_str(); }
|
||||
const LandmarkT &landmarkt() const { return _landmark; }
|
||||
|
||||
String unparse(bool with_class = false) const;
|
||||
String unparse_end(bool isoutput, bool with_class = false) const {
|
||||
return end(isoutput).unparse(isoutput, with_class);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
PortT _end[2];
|
||||
LandmarkT _landmark;
|
||||
|
||||
friend class RouterT;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline RouterT *
|
||||
ElementT::resolved_router(const VariableEnvironment &env, ErrorHandler *errh) const
|
||||
{
|
||||
if (ElementClassT *t = resolved_type(env, errh))
|
||||
return t->cast_router();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void
|
||||
ElementT::set_configuration(const String &configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
unresolve_type();
|
||||
}
|
||||
|
||||
inline String
|
||||
ElementT::declaration() const
|
||||
{
|
||||
assert(_type);
|
||||
return _name + " :: " + _type->printable_name();
|
||||
}
|
||||
|
||||
inline String
|
||||
ElementT::reverse_declaration() const
|
||||
{
|
||||
assert(_type);
|
||||
return _type->printable_name() + " " + _name;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ElementT::tunnel() const
|
||||
{
|
||||
return _type == ElementClassT::tunnel_type();
|
||||
}
|
||||
|
||||
inline bool
|
||||
ElementT::tunnel_connected() const
|
||||
{
|
||||
return _tunnel_input || _tunnel_output;
|
||||
}
|
||||
|
||||
inline const String &
|
||||
ElementT::flow_code(ElementMap *emap) const
|
||||
{
|
||||
semiresolve_type();
|
||||
return _resolved_type->traits(emap).flow_code;
|
||||
}
|
||||
|
||||
inline const String &
|
||||
ElementT::flow_code() const
|
||||
{
|
||||
semiresolve_type();
|
||||
return _resolved_type->traits(ElementMap::default_map()).flow_code;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const PortT &h1, const PortT &h2)
|
||||
{
|
||||
return h1.element == h2.element && h1.port == h2.port;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(const PortT &h1, const PortT &h2)
|
||||
{
|
||||
return h1.element != h2.element || h1.port != h2.port;
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator<(const PortT &h1, const PortT &h2)
|
||||
{
|
||||
return h1.eindex() < h2.eindex() || (h1.element == h2.element && h1.port < h2.port);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator>(const PortT &h1, const PortT &h2)
|
||||
{
|
||||
return h1.eindex() > h2.eindex() || (h1.element == h2.element && h1.port > h2.port);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator<=(const PortT &h1, const PortT &h2)
|
||||
{
|
||||
return h1.eindex() < h2.eindex() || (h1.element == h2.element && h1.port <= h2.port);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator>=(const PortT &h1, const PortT &h2)
|
||||
{
|
||||
return h1.eindex() > h2.eindex() || (h1.element == h2.element && h1.port >= h2.port);
|
||||
}
|
||||
|
||||
inline
|
||||
ConnectionT::ConnectionT()
|
||||
{
|
||||
}
|
||||
|
||||
inline
|
||||
ConnectionT::operator unspecified_bool_type() const
|
||||
{
|
||||
return (unspecified_bool_type) _end[end_from];
|
||||
}
|
||||
|
||||
#endif
|
||||
94
openflow/include/clicktool/etraits.hh
Normal file
94
openflow/include/clicktool/etraits.hh
Normal file
@@ -0,0 +1,94 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_ETRAITS_HH
|
||||
#define CLICK_ETRAITS_HH
|
||||
#include <click/string.hh>
|
||||
|
||||
struct Driver {
|
||||
enum {
|
||||
USERLEVEL = 0, LINUXMODULE = 1, BSDMODULE = 2, NSMODULE = 3,
|
||||
ALLMASK = 0xF, COUNT = 4, MULTITHREAD = COUNT
|
||||
};
|
||||
static const char *name(int);
|
||||
static const char *multithread_name(int);
|
||||
static const char *requirement(int);
|
||||
static int driver(const String&);
|
||||
static int driver_mask(const String&);
|
||||
};
|
||||
|
||||
|
||||
struct ElementTraits {
|
||||
|
||||
String name;
|
||||
String cxx;
|
||||
String documentation_name;
|
||||
String header_file;
|
||||
String source_file;
|
||||
String port_count_code;
|
||||
String processing_code;
|
||||
String flow_code;
|
||||
String flags;
|
||||
String methods;
|
||||
String requirements;
|
||||
String provisions;
|
||||
String libs;
|
||||
String noexport;
|
||||
int def_index;
|
||||
int driver_mask;
|
||||
int name_next;
|
||||
|
||||
ElementTraits();
|
||||
|
||||
static const ElementTraits &null_traits() { return the_null_traits; }
|
||||
|
||||
bool allows_driver(int d) const { return (driver_mask&(1<<d)) != 0; }
|
||||
|
||||
bool requires(const String &str) const;
|
||||
bool provides(const String &str) const;
|
||||
inline int flag_value(const String &str) const;
|
||||
int hard_flag_value(const String &str) const;
|
||||
|
||||
String *component(int);
|
||||
String *component(const String &);
|
||||
|
||||
void calculate_driver_mask();
|
||||
|
||||
enum {
|
||||
D_NONE,
|
||||
D_CLASS, D_CXX_CLASS, D_HEADER_FILE, D_PORT_COUNT, D_PROCESSING,
|
||||
D_FLOW_CODE, D_FLAGS, D_METHODS, D_REQUIREMENTS, D_PROVISIONS, D_LIBS,
|
||||
D_SOURCE_FILE, D_DOC_NAME, D_NOEXPORT,
|
||||
D_FIRST_DEFAULT = D_CLASS, D_LAST_DEFAULT = D_LIBS
|
||||
};
|
||||
static int parse_component(const String &);
|
||||
static ElementTraits make(int, ...);
|
||||
|
||||
private:
|
||||
|
||||
static ElementTraits the_null_traits;
|
||||
|
||||
friend class ElementMap;
|
||||
|
||||
};
|
||||
|
||||
typedef ElementTraits Traits;
|
||||
|
||||
|
||||
inline
|
||||
ElementTraits::ElementTraits()
|
||||
: def_index(0), driver_mask(Driver::ALLMASK), name_next(0)
|
||||
{
|
||||
}
|
||||
|
||||
inline String *
|
||||
ElementTraits::component(const String &s)
|
||||
{
|
||||
return component(parse_component(s));
|
||||
}
|
||||
|
||||
inline int
|
||||
ElementTraits::flag_value(const String &str) const
|
||||
{
|
||||
return flags ? hard_flag_value(str) : -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
180
openflow/include/clicktool/landmarkt.hh
Normal file
180
openflow/include/clicktool/landmarkt.hh
Normal file
@@ -0,0 +1,180 @@
|
||||
#ifndef CLICKTOOL_LANDMARKT_HH
|
||||
#define CLICKTOOL_LANDMARKT_HH 1
|
||||
#include <click/string.hh>
|
||||
#include <click/vector.hh>
|
||||
class LandmarkSetT;
|
||||
|
||||
class LandmarkT { public:
|
||||
|
||||
inline LandmarkT();
|
||||
inline LandmarkT(const String &filename, unsigned lineno);
|
||||
//inline LandmarkT(LandmarkSetT *lset, unsigned offset);
|
||||
inline LandmarkT(LandmarkSetT *lset, unsigned offset1, unsigned offset2);
|
||||
inline LandmarkT(const LandmarkT &o);
|
||||
inline ~LandmarkT();
|
||||
|
||||
static void static_initialize();
|
||||
|
||||
static const LandmarkT &empty_landmark();
|
||||
|
||||
typedef String (LandmarkT::*unspecified_bool_type)() const;
|
||||
inline operator unspecified_bool_type() const;
|
||||
|
||||
String str() const;
|
||||
operator String() const;
|
||||
String decorated_str() const;
|
||||
|
||||
unsigned offset1() const { return _offset1; }
|
||||
unsigned offset2() const { return _offset2; }
|
||||
|
||||
inline LandmarkT &operator=(const LandmarkT &o);
|
||||
|
||||
enum { noffset = (unsigned) -1 };
|
||||
|
||||
private:
|
||||
|
||||
LandmarkSetT *_lset;
|
||||
unsigned _offset1;
|
||||
unsigned _offset2;
|
||||
|
||||
static LandmarkT *empty;
|
||||
|
||||
};
|
||||
|
||||
class LandmarkSetT { public:
|
||||
|
||||
LandmarkSetT();
|
||||
LandmarkSetT(const String &filename, unsigned lineno);
|
||||
|
||||
inline void ref();
|
||||
inline void unref();
|
||||
|
||||
String offset_to_string(unsigned offset) const;
|
||||
String offset_to_decorated_string(unsigned offset1, unsigned offset2) const;
|
||||
void new_line(unsigned offset, const String &filename, unsigned lineno);
|
||||
|
||||
struct LandmarkInfo {
|
||||
unsigned end_offset;
|
||||
int filename;
|
||||
unsigned lineno;
|
||||
|
||||
LandmarkInfo(unsigned o, int f, unsigned l)
|
||||
: end_offset(o), filename(f), lineno(l) {
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
int _refcount;
|
||||
Vector<LandmarkInfo> _linfo;
|
||||
Vector<String> _fnames;
|
||||
|
||||
LandmarkSetT(const LandmarkSetT &);
|
||||
~LandmarkSetT();
|
||||
LandmarkSetT &operator=(const LandmarkSetT &);
|
||||
|
||||
static LandmarkSetT *the_empty_set;
|
||||
friend class LandmarkT;
|
||||
|
||||
};
|
||||
|
||||
inline void
|
||||
LandmarkSetT::ref()
|
||||
{
|
||||
assert(_refcount >= 1);
|
||||
++_refcount;
|
||||
}
|
||||
|
||||
inline void
|
||||
LandmarkSetT::unref()
|
||||
{
|
||||
assert(_refcount >= 1);
|
||||
if (--_refcount == 0)
|
||||
delete this;
|
||||
}
|
||||
|
||||
inline
|
||||
LandmarkT::LandmarkT()
|
||||
: _lset(empty->_lset), _offset1(noffset), _offset2(noffset)
|
||||
{
|
||||
_lset->ref();
|
||||
}
|
||||
|
||||
inline
|
||||
LandmarkT::LandmarkT(const String &filename, unsigned lineno = 0)
|
||||
: _lset(new LandmarkSetT(filename, lineno)), _offset1(noffset), _offset2(noffset)
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
inline
|
||||
LandmarkT::LandmarkT(LandmarkSetT *lset, unsigned offset)
|
||||
: _lset(lset), _offset1(offset), _offset2(offset)
|
||||
{
|
||||
_lset->ref();
|
||||
}
|
||||
#endif
|
||||
|
||||
inline
|
||||
LandmarkT::LandmarkT(LandmarkSetT *lset, unsigned offset1, unsigned offset2)
|
||||
: _lset(lset), _offset1(offset1), _offset2(offset2)
|
||||
{
|
||||
_lset->ref();
|
||||
}
|
||||
|
||||
inline
|
||||
LandmarkT::LandmarkT(const LandmarkT &lm)
|
||||
: _lset(lm._lset), _offset1(lm._offset1), _offset2(lm._offset2)
|
||||
{
|
||||
_lset->ref();
|
||||
}
|
||||
|
||||
inline
|
||||
LandmarkT::~LandmarkT()
|
||||
{
|
||||
_lset->unref();
|
||||
}
|
||||
|
||||
inline const LandmarkT &
|
||||
LandmarkT::empty_landmark()
|
||||
{
|
||||
assert(empty);
|
||||
return *empty;
|
||||
}
|
||||
|
||||
inline LandmarkT &
|
||||
LandmarkT::operator=(const LandmarkT &lm)
|
||||
{
|
||||
lm._lset->ref();
|
||||
_lset->unref();
|
||||
_lset = lm._lset;
|
||||
_offset1 = lm._offset1;
|
||||
_offset2 = lm._offset2;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline
|
||||
LandmarkT::operator unspecified_bool_type() const
|
||||
{
|
||||
return _lset != empty->_lset ? &LandmarkT::str : 0;
|
||||
}
|
||||
|
||||
inline String
|
||||
LandmarkT::str() const
|
||||
{
|
||||
return _lset->offset_to_string(_offset1);
|
||||
}
|
||||
|
||||
inline
|
||||
LandmarkT::operator String() const
|
||||
{
|
||||
return _lset->offset_to_string(_offset1);
|
||||
}
|
||||
|
||||
inline String
|
||||
LandmarkT::decorated_str() const
|
||||
{
|
||||
return _lset->offset_to_decorated_string(_offset1, _offset2);
|
||||
}
|
||||
|
||||
#endif
|
||||
207
openflow/include/clicktool/lexert.hh
Normal file
207
openflow/include/clicktool/lexert.hh
Normal file
@@ -0,0 +1,207 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_LEXERT_HH
|
||||
#define CLICK_LEXERT_HH
|
||||
#include <click/error.hh>
|
||||
#include <click/hashtable.hh>
|
||||
#include <click/archive.hh>
|
||||
#include "landmarkt.hh"
|
||||
#include <stdio.h>
|
||||
class RouterT;
|
||||
class ElementClassT;
|
||||
class StringAccum;
|
||||
class LexerTInfo;
|
||||
class VariableEnvironment;
|
||||
struct ArchiveElement;
|
||||
|
||||
enum {
|
||||
lexEOF = 0,
|
||||
lexIdent = 256, // see also LexerT::lexeme_string
|
||||
lexVariable,
|
||||
lexConfig,
|
||||
lexArrow,
|
||||
lex2Arrow,
|
||||
lex2Colon,
|
||||
lex2Bar,
|
||||
lex3Dot,
|
||||
lexElementclass,
|
||||
lexRequire,
|
||||
lexProvide,
|
||||
lexDefine
|
||||
};
|
||||
|
||||
class Lexeme { public:
|
||||
|
||||
Lexeme() : _kind(lexEOF), _pos(0) { }
|
||||
Lexeme(int k, const String &s, const char *p) : _kind(k), _s(s), _pos(p) { }
|
||||
|
||||
int kind() const { return _kind; }
|
||||
bool is(int k) const { return _kind == k; }
|
||||
operator bool() const { return _kind != lexEOF; }
|
||||
|
||||
const String &string() const { return _s; }
|
||||
String &string() { return _s; }
|
||||
|
||||
const char *pos1() const { return _pos; }
|
||||
const char *pos2() const { return _pos + _s.length(); }
|
||||
|
||||
private:
|
||||
|
||||
int _kind;
|
||||
String _s;
|
||||
const char *_pos;
|
||||
|
||||
};
|
||||
|
||||
class LexerT { public:
|
||||
|
||||
LexerT(ErrorHandler *, bool ignore_line_directives);
|
||||
virtual ~LexerT();
|
||||
|
||||
void reset(const String &data, const Vector<ArchiveElement> &archive, const String &filename);
|
||||
void clear();
|
||||
void set_lexinfo(LexerTInfo *);
|
||||
void ignore_line_directives(bool x) { _ignore_line_directives = x; }
|
||||
void expand_groups(bool x) { _expand_groups = x; }
|
||||
|
||||
String remaining_text() const;
|
||||
void set_remaining_text(const String &);
|
||||
|
||||
Lexeme lex() {
|
||||
return _unlex_pos ? _unlex[--_unlex_pos] : next_lexeme();
|
||||
}
|
||||
void unlex(const Lexeme &t) {
|
||||
assert(_unlex_pos < UNLEX_SIZE);
|
||||
_unlex[_unlex_pos++] = t;
|
||||
}
|
||||
Lexeme lex_config() {
|
||||
assert(!_unlex_pos);
|
||||
return _file.lex_config(this);
|
||||
}
|
||||
String landmark() const;
|
||||
inline LandmarkT landmarkt(const char *pos1, const char *pos2) const;
|
||||
|
||||
bool yport(Vector<int> &ports, const char *pos[2]);
|
||||
bool yelement(Vector<int> &result, bool in_allowed, const char *epos[5]);
|
||||
bool yconnection();
|
||||
void ycompound_arguments(RouterT *);
|
||||
void yelementclass(const char *pos1);
|
||||
ElementClassT *ycompound(String, const char *decl_pos1, const char *name_pos1);
|
||||
void ygroup(String name, int group_nports[2], const char *open_pos1, const char *open_pos2);
|
||||
void yrequire();
|
||||
void yvar();
|
||||
bool ystatement(int nested = 0);
|
||||
|
||||
RouterT *router() const { return _router; }
|
||||
RouterT *finish(const VariableEnvironment &global_scope);
|
||||
|
||||
protected:
|
||||
|
||||
struct FileState {
|
||||
String _big_string;
|
||||
const char *_end;
|
||||
const char *_pos;
|
||||
String _filename;
|
||||
String _original_filename;
|
||||
unsigned _lineno;
|
||||
LandmarkSetT *_lset;
|
||||
|
||||
FileState(const String &text, const String &filename);
|
||||
FileState(const FileState &x)
|
||||
: _big_string(x._big_string), _end(x._end), _pos(x._pos),
|
||||
_filename(x._filename), _original_filename(x._original_filename),
|
||||
_lineno(x._lineno), _lset(x._lset) {
|
||||
_lset->ref();
|
||||
}
|
||||
~FileState() {
|
||||
_lset->unref();
|
||||
}
|
||||
FileState &operator=(const FileState &x);
|
||||
const char *skip_line(const char *s);
|
||||
const char *skip_slash_star(const char *s);
|
||||
const char *skip_backslash_angle(const char *s);
|
||||
const char *skip_quote(const char *s, char end_c);
|
||||
const char *process_line_directive(const char *s, LexerT *lexer);
|
||||
Lexeme next_lexeme(LexerT *lexer);
|
||||
Lexeme lex_config(LexerT *lexer);
|
||||
String landmark() const;
|
||||
unsigned offset(const char *s) const {
|
||||
assert(s >= _big_string.begin() && s <= _end);
|
||||
return s - _big_string.begin();
|
||||
}
|
||||
LandmarkT landmarkt(const char *pos1, const char *pos2) const {
|
||||
return LandmarkT(_lset, offset(pos1), offset(pos2));
|
||||
}
|
||||
};
|
||||
|
||||
// lexer
|
||||
FileState _file;
|
||||
bool _ignore_line_directives;
|
||||
bool _expand_groups;
|
||||
|
||||
bool get_data();
|
||||
Lexeme next_lexeme() {
|
||||
return _file.next_lexeme(this);
|
||||
}
|
||||
static String lexeme_string(int);
|
||||
|
||||
// parser
|
||||
enum { UNLEX_SIZE = 2 };
|
||||
Lexeme _unlex[UNLEX_SIZE];
|
||||
int _unlex_pos;
|
||||
|
||||
// router
|
||||
RouterT *_router;
|
||||
|
||||
int _anonymous_offset;
|
||||
int _anonymous_class_count;
|
||||
int _group_depth;
|
||||
int _ngroups;
|
||||
bool _last_connection_ends_output;
|
||||
|
||||
Vector<String> _libraries;
|
||||
|
||||
// what names represent types? (builds up linearly)
|
||||
HashTable<String, ElementClassT *> _base_type_map;
|
||||
|
||||
// errors
|
||||
LexerTInfo *_lexinfo;
|
||||
ErrorHandler *_errh;
|
||||
|
||||
void xlerror(const char *pos1, const char *pos2, const String &landmark,
|
||||
const char *anno, const char *format, va_list val);
|
||||
int lerror(const char *pos1, const char *pos2, const char *format, ...);
|
||||
int lerror(const Lexeme &t, const char *format, ...);
|
||||
int lwarning(const Lexeme &t, const char *format, ...);
|
||||
String anon_element_name(const String &) const;
|
||||
|
||||
bool expect(int, bool no_error = false);
|
||||
const char *next_pos() const {
|
||||
return _unlex_pos ? _unlex[_unlex_pos - 1].pos1() : _file._pos;
|
||||
}
|
||||
|
||||
ElementClassT *element_type(const Lexeme &) const;
|
||||
ElementClassT *force_element_type(const Lexeme &);
|
||||
void ydefine(RouterT *, const String &name, const String &value, const Lexeme &, bool &scope_order_error);
|
||||
void yrequire_library(const Lexeme &lexeme, const String &value);
|
||||
void yconnection_check_useless(const Vector<int> &x, bool isoutput, const char *epos[2], bool done);
|
||||
static void yconnection_analyze_ports(const Vector<int> &x, bool isoutput,
|
||||
int &min_ports, int &expandable);
|
||||
void yconnection_connect_all(Vector<int> &outputs, Vector<int> &inputs, int connector, const char *pos1, const char *pos2);
|
||||
|
||||
LexerT(const LexerT &);
|
||||
LexerT &operator=(const LexerT &);
|
||||
int make_element(String, const Lexeme &, const char *decl_pos2, ElementClassT *, const String &);
|
||||
int make_anon_element(const Lexeme &, const char *decl_pos2, ElementClassT *, const String &);
|
||||
void connect(int f1, int p1, int p2, int f2, const char *pos1, const char *pos2);
|
||||
|
||||
friend struct FileState;
|
||||
|
||||
};
|
||||
|
||||
inline LandmarkT
|
||||
LexerT::landmarkt(const char *pos1, const char *pos2) const
|
||||
{
|
||||
return _file.landmarkt(pos1, pos2);
|
||||
}
|
||||
|
||||
#endif
|
||||
29
openflow/include/clicktool/lexertinfo.hh
Normal file
29
openflow/include/clicktool/lexertinfo.hh
Normal file
@@ -0,0 +1,29 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_LEXERTINFO_HH
|
||||
#define CLICK_LEXERTINFO_HH
|
||||
#include "lexert.hh"
|
||||
class ElementT;
|
||||
class ElementClassT;
|
||||
|
||||
class LexerTInfo { public:
|
||||
|
||||
LexerTInfo() { }
|
||||
virtual ~LexerTInfo() { }
|
||||
|
||||
virtual void notify_comment(const char *pos1, const char *pos2);
|
||||
virtual void notify_error(const String &message, const char *pos1, const char *pos2);
|
||||
virtual void notify_line_directive(const char *pos1, const char *pos2);
|
||||
virtual void notify_keyword(const String &keyword, const char *pos1, const char *pos2);
|
||||
virtual void notify_config_string(const char *pos1, const char *pos2);
|
||||
virtual void notify_class_declaration(ElementClassT *, bool anonymous,
|
||||
const char *pos1, const char *name_pos1, const char *pos2);
|
||||
virtual void notify_class_extension(ElementClassT *, const char *pos1, const char *pos2);
|
||||
virtual void notify_class_reference(ElementClassT *, const char *pos1, const char *pos2);
|
||||
virtual void notify_element_declaration(
|
||||
ElementT *e, const char *pos1, const char *name_pos2, const char *decl_pos2);
|
||||
virtual void notify_element_reference(
|
||||
ElementT *e, const char *pos1, const char *pos2);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
260
openflow/include/clicktool/processingt.hh
Normal file
260
openflow/include/clicktool/processingt.hh
Normal file
@@ -0,0 +1,260 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_PROCESSINGT_HH
|
||||
#define CLICK_PROCESSINGT_HH
|
||||
#include "routert.hh"
|
||||
class ElementMap;
|
||||
class Bitvector;
|
||||
|
||||
class ProcessingT { public:
|
||||
|
||||
enum {
|
||||
end_to = ConnectionT::end_to,
|
||||
end_from = ConnectionT::end_from
|
||||
};
|
||||
|
||||
enum ProcessingCode {
|
||||
ppush = 1, ppull = 2, pagnostic = 4, perror = 8
|
||||
};
|
||||
static const char processing_letters[];
|
||||
static const char decorated_processing_letters[];
|
||||
|
||||
ProcessingT(bool resolve_agnostics, RouterT *router, ElementMap *emap,
|
||||
ErrorHandler *errh = 0);
|
||||
ProcessingT(RouterT *router, ElementMap *emap, ErrorHandler *errh = 0);
|
||||
ProcessingT(const ProcessingT &processing, ElementT *element,
|
||||
ErrorHandler *errh = 0);
|
||||
void check_types(ErrorHandler *errh = 0);
|
||||
|
||||
RouterT *router() const {
|
||||
return _router;
|
||||
}
|
||||
const VariableEnvironment &scope() const {
|
||||
return _scope;
|
||||
}
|
||||
int nelements() const {
|
||||
return _pidx[end_to].size() - 1;
|
||||
}
|
||||
int npidx(bool isoutput) const {
|
||||
return _pidx[isoutput].back();
|
||||
}
|
||||
ElementMap *element_map() const {
|
||||
return _element_map;
|
||||
}
|
||||
|
||||
int pidx(int eindex, int port, bool isoutput) const {
|
||||
return _pidx[isoutput][eindex] + port;
|
||||
}
|
||||
int pidx(const PortT &port, bool isoutput) const {
|
||||
assert(port.router() == _router);
|
||||
return pidx(port.eindex(), port.port, isoutput);
|
||||
}
|
||||
int pidx(const ConnectionT &conn, bool isoutput) const {
|
||||
return pidx(conn.end(isoutput), isoutput);
|
||||
}
|
||||
|
||||
PortT port(int pidx, bool isoutput) const {
|
||||
const ElementT *e = _elt[isoutput][pidx];
|
||||
return PortT(const_cast<ElementT *>(e), pidx - _pidx[isoutput][e->eindex()]);
|
||||
}
|
||||
|
||||
int ninput_pidx() const {
|
||||
return npidx(end_to);
|
||||
}
|
||||
int input_pidx(int eindex, int port = 0) const {
|
||||
return pidx(eindex, port, end_to);
|
||||
}
|
||||
int input_pidx(const PortT &port) const {
|
||||
return pidx(port, end_to);
|
||||
}
|
||||
int input_pidx(const ConnectionT &conn) const {
|
||||
return pidx(conn, end_to);
|
||||
}
|
||||
PortT input_port(int pidx) const {
|
||||
return port(pidx, end_to);
|
||||
}
|
||||
|
||||
int noutput_pidx() const {
|
||||
return npidx(end_from);
|
||||
}
|
||||
int output_pidx(int eindex, int port = 0) const {
|
||||
return pidx(eindex, port, end_from);
|
||||
}
|
||||
int output_pidx(const PortT &port) const {
|
||||
return pidx(port, end_from);
|
||||
}
|
||||
int output_pidx(const ConnectionT &conn) const {
|
||||
return pidx(conn, end_from);
|
||||
}
|
||||
PortT output_port(int pidx) const {
|
||||
return port(pidx, end_from);
|
||||
}
|
||||
|
||||
const String &flow_code(ElementT *e) const {
|
||||
if (_flow_overrides.size())
|
||||
if (const String &fc = _flow_overrides.get(e->name()))
|
||||
return fc;
|
||||
return e->flow_code(_element_map);
|
||||
}
|
||||
|
||||
int input_processing(const PortT &port) const;
|
||||
int output_processing(const PortT &port) const;
|
||||
char decorated_input_processing_letter(const PortT &port) const;
|
||||
char decorated_output_processing_letter(const PortT &port) const;
|
||||
int input_processing(int eindex, int port) const;
|
||||
int output_processing(int eindex, int port) const;
|
||||
|
||||
bool input_is_pull(int eindex, int port) const;
|
||||
bool output_is_push(int eindex, int port) const;
|
||||
|
||||
bool processing_error(int pidx, bool isoutput) const {
|
||||
return _processing[isoutput][pidx] & perror;
|
||||
}
|
||||
|
||||
bool same_processing(int a_eindex, int b_eindex) const;
|
||||
|
||||
String processing_code(const ElementT *element) const;
|
||||
String decorated_processing_code(const ElementT *element) const;
|
||||
|
||||
static const char *processing_code_next(const char *pos, const char *end_code, int &processing);
|
||||
static const char *processing_code_output(const char *code, const char *end_code, const char *pos = 0);
|
||||
static String processing_code_reverse(const String &pcode);
|
||||
|
||||
/** @brief Set @a x to those ports reachable from @a port in @a code.
|
||||
* @param code flow code
|
||||
* @param port port number
|
||||
* @param isoutput whether @a port is an output port
|
||||
* @param[out] x output bitvector
|
||||
* @param size size of @a x (number of !@a isoutput ports)
|
||||
* @param errh error handler
|
||||
* @return 0 on success, -1 if @a code is invalid
|
||||
*
|
||||
* On return, @a x.size() == @a size, and @a x[@em i] is true if and only
|
||||
* if @a code indicates flow between port @a port and port @em i. If @a
|
||||
* port < 0, then @a x is all false.
|
||||
*
|
||||
* For example, if @a code is @c "x/x", then @a x is all true.
|
||||
*/
|
||||
static int code_flow(const String &code, int port, bool isoutput, Bitvector *x, int size, ErrorHandler *errh = 0);
|
||||
int port_flow(const PortT &port, bool isoutput, Bitvector *x, ErrorHandler *errh = 0) const {
|
||||
return code_flow(flow_code(port.element), port.port, isoutput,
|
||||
x, port.element->nports(!isoutput), errh);
|
||||
}
|
||||
|
||||
static int forward_flow(const String &code, int input_port, Bitvector *x, int noutputs, ErrorHandler *errh = 0) {
|
||||
return code_flow(code, input_port, false, x, noutputs, errh);
|
||||
}
|
||||
int forward_flow(const PortT &port, Bitvector *x, ErrorHandler *errh = 0) {
|
||||
return port_flow(port, false, x, errh);
|
||||
}
|
||||
static int backward_flow(const String &code, int output_port, Bitvector *x, int ninputs, ErrorHandler *errh = 0) {
|
||||
return code_flow(code, output_port, true, x, ninputs, errh);
|
||||
}
|
||||
int backward_flow(const PortT &port, Bitvector *x, ErrorHandler *errh = 0) {
|
||||
return port_flow(port, true, x, errh);
|
||||
}
|
||||
|
||||
/** @brief Set bits in @a sink that are connected to ports in @a source.
|
||||
* @param source source ports
|
||||
* @param source_isoutput whether @a source represents output ports
|
||||
* @param[out] sink sink ports (input if @a source_isoutput, and vice versa)
|
||||
*/
|
||||
void follow_connections(const Bitvector &source, bool source_isoutput, Bitvector &sink) const;
|
||||
void follow_connections(const PortT &source, bool source_isoutput, Bitvector &sink) const;
|
||||
void follow_flow(const Bitvector &source, bool source_isoutput, Bitvector &sink, ErrorHandler *errh = 0) const;
|
||||
void follow_reachable(Bitvector &ports, bool isoutput, bool forward, ErrorHandler *errh = 0, ErrorHandler *debug_errh = 0) const;
|
||||
|
||||
String compound_port_count_code() const;
|
||||
String compound_processing_code() const;
|
||||
String compound_flow_code(ErrorHandler *errh = 0) const;
|
||||
|
||||
private:
|
||||
|
||||
RouterT *_router;
|
||||
String _router_name;
|
||||
ElementMap *_element_map;
|
||||
VariableEnvironment _scope;
|
||||
HashTable<String, String> _flow_overrides;
|
||||
|
||||
Vector<int> _pidx[2];
|
||||
Vector<const ElementT *> _elt[2];
|
||||
Vector<int> _processing[2];
|
||||
bool _pidx_created;
|
||||
|
||||
enum { classwarn_unknown = 1, classwarn_pcode = 2 };
|
||||
HashTable<ElementClassT *, int> _class_warnings;
|
||||
|
||||
void parse_flow_info(ElementT *e, ErrorHandler *errh);
|
||||
void create_pidx(ErrorHandler *errh);
|
||||
void create(const String &compound_pcode, bool resolve_agnostics, ErrorHandler *errh);
|
||||
|
||||
void initial_processing_for(int, const String &compound_pcode, ErrorHandler *);
|
||||
void initial_processing(const String &compound_pcode, ErrorHandler *);
|
||||
void processing_error(const ConnectionT &, int, ErrorHandler *);
|
||||
void check_processing(Vector<ConnectionT> &conn, Bitvector &invalid_conn, ErrorHandler *errh);
|
||||
void check_connections(Vector<ConnectionT> &conn, Bitvector &invalid_conn, ErrorHandler *errh);
|
||||
void check_nports(Vector<ConnectionT> &conn, const ElementT *, const int *, const int *, ErrorHandler *);
|
||||
void resolve_agnostics(); // change remaining AGNOSTICs to PUSH
|
||||
void debug_print_pidxes(const Bitvector &ports, bool isoutput, const String &prefix, ErrorHandler *debug_errh) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline int
|
||||
ProcessingT::input_processing(const PortT &h) const
|
||||
{
|
||||
return _processing[end_to][input_pidx(h)] & 3;
|
||||
}
|
||||
|
||||
inline int
|
||||
ProcessingT::output_processing(const PortT &h) const
|
||||
{
|
||||
return _processing[end_from][output_pidx(h)] & 3;
|
||||
}
|
||||
|
||||
inline char
|
||||
ProcessingT::decorated_input_processing_letter(const PortT &h) const
|
||||
{
|
||||
return decorated_processing_letters[_processing[end_to][input_pidx(h)] & 7];
|
||||
}
|
||||
|
||||
inline char
|
||||
ProcessingT::decorated_output_processing_letter(const PortT &h) const
|
||||
{
|
||||
return decorated_processing_letters[_processing[end_from][output_pidx(h)] & 7];
|
||||
}
|
||||
|
||||
inline int
|
||||
ProcessingT::input_processing(int i, int p) const
|
||||
{
|
||||
return _processing[end_to][input_pidx(i, p)] & 3;
|
||||
}
|
||||
|
||||
inline int
|
||||
ProcessingT::output_processing(int i, int p) const
|
||||
{
|
||||
return _processing[end_from][output_pidx(i, p)] & 3;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ProcessingT::input_is_pull(int i, int p) const
|
||||
{
|
||||
return _processing[end_to][input_pidx(i, p)] & ppull;
|
||||
}
|
||||
|
||||
inline bool
|
||||
ProcessingT::output_is_push(int i, int p) const
|
||||
{
|
||||
return _processing[end_from][output_pidx(i, p)] & ppush;
|
||||
}
|
||||
|
||||
inline const char *
|
||||
ProcessingT::processing_code_output(const char *code, const char *end_code, const char *pos)
|
||||
{
|
||||
if (!pos)
|
||||
pos = code;
|
||||
while (pos < end_code && *pos != '/')
|
||||
pos++;
|
||||
return (pos == end_code ? code : pos + 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
672
openflow/include/clicktool/routert.hh
Normal file
672
openflow/include/clicktool/routert.hh
Normal file
@@ -0,0 +1,672 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_ROUTERT_HH
|
||||
#define CLICK_ROUTERT_HH
|
||||
#include "elementt.hh"
|
||||
#include "eclasst.hh"
|
||||
#include <click/error.hh>
|
||||
#include <click/hashtable.hh>
|
||||
#include <click/archive.hh>
|
||||
#include <click/variableenv.hh>
|
||||
typedef HashTable<String, int> StringMap;
|
||||
|
||||
class RouterT : public ElementClassT { public:
|
||||
|
||||
RouterT();
|
||||
RouterT(const String &name, const LandmarkT &landmark, RouterT *declaration_scope = 0);
|
||||
virtual ~RouterT();
|
||||
|
||||
// ELEMENTS
|
||||
int nelements() const { return _elements.size(); }
|
||||
int n_live_elements() const { return _n_live_elements; }
|
||||
|
||||
inline const ElementT *element(const String &) const;
|
||||
inline ElementT *element(const String &);
|
||||
int eindex(const String &name) const { return _element_name_map[name]; }
|
||||
|
||||
const ElementT *element(int i) const{ return _elements[i]; }
|
||||
ElementT *element(int i) { return _elements[i]; }
|
||||
|
||||
class iterator;
|
||||
class const_iterator;
|
||||
class type_iterator;
|
||||
class const_type_iterator;
|
||||
inline iterator begin_elements();
|
||||
inline const_iterator begin_elements() const;
|
||||
inline type_iterator begin_elements(ElementClassT *);
|
||||
inline const_type_iterator begin_elements(ElementClassT *) const;
|
||||
inline iterator end_elements();
|
||||
inline const_iterator end_elements() const;
|
||||
|
||||
bool elive(int i) const { return _elements[i]->live(); }
|
||||
bool edead(int i) const { return _elements[i]->dead(); }
|
||||
inline String ename(int) const;
|
||||
inline ElementClassT *etype(int) const;
|
||||
inline String etype_name(int) const;
|
||||
|
||||
ElementT *get_element(const String &name, ElementClassT *eclass, const String &configuration, const LandmarkT &landmark);
|
||||
ElementT *add_anon_element(ElementClassT *eclass, const String &configuration = String(), const LandmarkT &landmark = LandmarkT::empty_landmark());
|
||||
void change_ename(int, const String &);
|
||||
int __map_element_name(const String &name, int new_eindex);
|
||||
void assign_element_names();
|
||||
void free_element(ElementT *);
|
||||
void free_dead_elements();
|
||||
|
||||
void set_new_eindex_collector(Vector<int> *v) { _new_eindex_collector=v; }
|
||||
|
||||
// TYPES
|
||||
ElementClassT *locally_declared_type(const String &) const;
|
||||
inline ElementClassT *declared_type(const String &) const;
|
||||
void add_declared_type(ElementClassT *, bool anonymous);
|
||||
|
||||
void collect_types(HashTable<ElementClassT *, int> &) const;
|
||||
void collect_locally_declared_types(Vector<ElementClassT *> &) const;
|
||||
void collect_overloads(Vector<ElementClassT *> &) const;
|
||||
|
||||
// CONNECTIONS
|
||||
enum { end_to = ConnectionT::end_to, end_from = ConnectionT::end_from };
|
||||
|
||||
class conn_iterator;
|
||||
inline conn_iterator begin_connections() const;
|
||||
inline conn_iterator end_connections() const;
|
||||
|
||||
conn_iterator find_connections_touching(int eindex, int port, bool isoutput) const;
|
||||
inline conn_iterator find_connections_touching(const PortT &port, bool isoutput) const;
|
||||
inline conn_iterator find_connections_touching(ElementT *e, bool isoutput) const;
|
||||
inline conn_iterator find_connections_touching(ElementT *e, int port, bool isoutput) const;
|
||||
|
||||
inline conn_iterator find_connections_from(const PortT &port) const;
|
||||
inline conn_iterator find_connections_from(ElementT *e) const;
|
||||
inline conn_iterator find_connections_from(ElementT *e, int port) const;
|
||||
inline conn_iterator find_connections_to(const PortT &port) const;
|
||||
inline conn_iterator find_connections_to(ElementT *e) const;
|
||||
inline conn_iterator find_connections_to(ElementT *e, int port) const;
|
||||
|
||||
bool has_connection(const PortT &from, const PortT &to) const;
|
||||
|
||||
void find_connections_touching(const PortT &port, bool isoutput, Vector<PortT> &v, bool clear = true) const;
|
||||
inline void find_connections_from(const PortT &output, Vector<PortT> &v, bool clear = true) const {
|
||||
find_connections_touching(output, end_from, v, clear);
|
||||
}
|
||||
void find_connections_to(const PortT &input, Vector<PortT> &v) const {
|
||||
find_connections_touching(input, end_to, v);
|
||||
}
|
||||
|
||||
void find_connection_vector_touching(const ElementT *e, bool isoutput, Vector<conn_iterator> &x) const;
|
||||
inline void find_connection_vector_from(const ElementT *e, Vector<conn_iterator> &x) const {
|
||||
find_connection_vector_touching(e, end_from, x);
|
||||
}
|
||||
inline void find_connection_vector_to(const ElementT *e, Vector<conn_iterator> &x) const {
|
||||
find_connection_vector_touching(e, end_to, x);
|
||||
}
|
||||
|
||||
void add_tunnel(const String &namein, const String &nameout, const LandmarkT &landmark, ErrorHandler *errh);
|
||||
|
||||
bool add_connection(const PortT &, const PortT &, const LandmarkT &landmark = LandmarkT::empty_landmark());
|
||||
inline bool add_connection(ElementT *, int, ElementT *, int, const LandmarkT &landmark = LandmarkT::empty_landmark());
|
||||
conn_iterator erase(conn_iterator it);
|
||||
void kill_bad_connections();
|
||||
|
||||
conn_iterator change_connection_to(conn_iterator it, PortT new_to);
|
||||
conn_iterator change_connection_from(conn_iterator it, PortT new_from);
|
||||
|
||||
bool insert_before(const PortT &, const PortT &);
|
||||
bool insert_after(const PortT &, const PortT &);
|
||||
inline bool insert_before(ElementT *, const PortT &);
|
||||
inline bool insert_after(ElementT *, const PortT &);
|
||||
|
||||
// REQUIREMENTS
|
||||
void add_requirement(const String &type, const String &value);
|
||||
void remove_requirement(const String &type, const String &value);
|
||||
const Vector<String> &requirements() const { return _requirements; }
|
||||
|
||||
// ARCHIVE
|
||||
void add_archive(const ArchiveElement &);
|
||||
int narchive() const { return _archive.size(); }
|
||||
int archive_index(const String &s) const { return _archive_map[s]; }
|
||||
const Vector<ArchiveElement> &archive() const{ return _archive; }
|
||||
ArchiveElement &archive(int i) { return _archive[i]; }
|
||||
const ArchiveElement &archive(int i) const { return _archive[i]; }
|
||||
inline ArchiveElement &archive(const String &s);
|
||||
inline const ArchiveElement &archive(const String &s) const;
|
||||
|
||||
void add_components_to(RouterT *, const String &prefix = String()) const;
|
||||
|
||||
// CHECKING, FLATTENING AND EXPANDING
|
||||
void check() const;
|
||||
|
||||
void remove_duplicate_connections();
|
||||
void remove_dead_elements();
|
||||
|
||||
void remove_compound_elements(ErrorHandler *, bool expand_vars);
|
||||
void remove_tunnels(ErrorHandler *errh = 0);
|
||||
void compact();
|
||||
|
||||
void expand_into(RouterT *dest, const String &prefix, VariableEnvironment &env, ErrorHandler *errh);
|
||||
void flatten(ErrorHandler *errh, bool expand_vars = false);
|
||||
|
||||
// UNPARSING
|
||||
void unparse(StringAccum &, const String & = String()) const;
|
||||
void unparse_requirements(StringAccum &, const String & = String()) const;
|
||||
void unparse_defines(StringAccum &, const String & = String()) const;
|
||||
void unparse_declarations(StringAccum &, const String & = String()) const;
|
||||
void unparse_connections(StringAccum &, const String & = String()) const;
|
||||
String configuration_string() const;
|
||||
|
||||
// COMPOUND ELEMENTS
|
||||
String landmark() const { return _type_landmark.str(); }
|
||||
String decorated_landmark() const { return _type_landmark.decorated_str(); }
|
||||
void set_landmarkt(const LandmarkT &l) { _type_landmark = l; }
|
||||
const ElementTraits *find_traits(ElementMap *emap) const;
|
||||
|
||||
bool primitive() const { return false; }
|
||||
bool overloaded() const;
|
||||
|
||||
inline bool defines(const String &name) const;
|
||||
|
||||
int nformals() const { return _formals.size(); }
|
||||
inline bool add_formal(const String &name, const String &type);
|
||||
const String &formal_name(int i) const { return _formals[i]; }
|
||||
const String &formal_type(int i) const { return _formal_types[i]; }
|
||||
|
||||
const VariableEnvironment &scope() const { return _scope; }
|
||||
inline bool define(const String &name, const String &value);
|
||||
inline void redefine(const VariableEnvironment &);
|
||||
int ninputs() const { return _ninputs; }
|
||||
int noutputs() const { return _noutputs; }
|
||||
|
||||
RouterT *declaration_scope() const { return _declaration_scope; }
|
||||
ElementClassT *overload_type() const { return _overload_type; }
|
||||
void set_overload_type(ElementClassT *);
|
||||
|
||||
int check_pseudoelement(const ElementT *e, bool isoutput, const char *name, ErrorHandler *errh) const;
|
||||
int finish_type(ErrorHandler *errh);
|
||||
|
||||
bool need_resolve() const;
|
||||
ElementClassT *resolve(int, int, Vector<String> &, ErrorHandler *, const LandmarkT &landmark);
|
||||
void create_scope(const Vector<String> &args, const VariableEnvironment &env, VariableEnvironment &new_env);
|
||||
ElementT *complex_expand_element(ElementT *, const Vector<String> &, RouterT *, const String &prefix, const VariableEnvironment &, ErrorHandler *);
|
||||
|
||||
String unparse_signature() const;
|
||||
void unparse_declaration(StringAccum &, const String &, UnparseKind, ElementClassT *);
|
||||
|
||||
RouterT *cast_router() { return this; }
|
||||
|
||||
private:
|
||||
|
||||
struct ElementType {
|
||||
ElementClassT * const type;
|
||||
int scope_cookie;
|
||||
int prev_name;
|
||||
ElementType(ElementClassT *c, int sc, int pn) : type(c), scope_cookie(sc), prev_name(pn) { assert(type); type->use(); }
|
||||
ElementType(const ElementType &o) : type(o.type), scope_cookie(o.scope_cookie), prev_name(o.prev_name) { type->use(); }
|
||||
~ElementType() { type->unuse(); }
|
||||
const String &name() const { return type->name(); }
|
||||
private:
|
||||
ElementType &operator=(const ElementType &);
|
||||
};
|
||||
|
||||
enum { end_all = 2 };
|
||||
|
||||
struct ConnectionX : public ConnectionT {
|
||||
ConnectionX **_pprev;
|
||||
ConnectionX *_next[3];
|
||||
ConnectionX(const PortT &from, const PortT &to,
|
||||
const LandmarkT &landmark)
|
||||
: ConnectionT(from, to, landmark) {
|
||||
}
|
||||
ConnectionX *next_from() const {
|
||||
return _next[end_from];
|
||||
}
|
||||
ConnectionX *next_to() const {
|
||||
return _next[end_to];
|
||||
}
|
||||
};
|
||||
|
||||
struct ConnectionSet {
|
||||
ConnectionSet *next;
|
||||
ConnectionX c[1];
|
||||
};
|
||||
|
||||
struct Pair {
|
||||
ConnectionX *end[2];
|
||||
Pair() { end[0] = end[1] = 0; }
|
||||
Pair(ConnectionX *from, ConnectionX *to) { end[end_from] = from; end[end_to] = to; }
|
||||
ConnectionX *&operator[](int i) { assert(i >= 0 && i <= 1); return end[i]; }
|
||||
ConnectionX *operator[](int i) const { assert(i >= 0 && i <= 1); return end[i]; }
|
||||
};
|
||||
|
||||
StringMap _element_name_map;
|
||||
Vector<ElementT *> _elements;
|
||||
ElementT *_free_element;
|
||||
int _n_live_elements;
|
||||
Vector<int> *_new_eindex_collector;
|
||||
|
||||
ConnectionSet *_connsets;
|
||||
int _nconnx;
|
||||
Vector<Pair> _first_conn;
|
||||
ConnectionX *_conn_head;
|
||||
ConnectionX **_conn_tail;
|
||||
ConnectionX *_free_conn;
|
||||
|
||||
StringMap _declared_type_map;
|
||||
Vector<ElementType> _declared_types;
|
||||
|
||||
Vector<String> _requirements;
|
||||
|
||||
StringMap _archive_map;
|
||||
Vector<ArchiveElement> _archive;
|
||||
|
||||
RouterT *_declaration_scope;
|
||||
int _declaration_scope_cookie;
|
||||
int _scope_cookie;
|
||||
|
||||
VariableEnvironment _scope;
|
||||
Vector<String> _formals;
|
||||
Vector<String> _formal_types;
|
||||
int _ninputs;
|
||||
int _noutputs;
|
||||
bool _scope_order_error;
|
||||
bool _circularity_flag;
|
||||
bool _potential_duplicate_connections;
|
||||
ElementClassT *_overload_type;
|
||||
LandmarkT _type_landmark;
|
||||
mutable ElementTraits _traits;
|
||||
|
||||
RouterT(const RouterT &);
|
||||
RouterT &operator=(const RouterT &);
|
||||
|
||||
ElementClassT *declared_type(const String &, int scope_cookie) const;
|
||||
void update_noutputs(int);
|
||||
void update_ninputs(int);
|
||||
ElementT *add_element(const ElementT &);
|
||||
void assign_element_name(int);
|
||||
void free_connection(ConnectionX *c);
|
||||
void unlink_connection_from(ConnectionX *c);
|
||||
void unlink_connection_to(ConnectionX *c);
|
||||
void expand_tunnel(Vector<PortT> *port_expansions, const Vector<PortT> &ports, bool is_output, int which, ErrorHandler *) const;
|
||||
int assign_arguments(const Vector<String> &, Vector<String> *) const;
|
||||
|
||||
friend class RouterUnparserT;
|
||||
friend class conn_iterator;
|
||||
|
||||
};
|
||||
|
||||
class RouterT::const_iterator { public:
|
||||
typedef int (const_iterator::*unspecified_bool_type)() const;
|
||||
operator unspecified_bool_type() const { return _e ? &const_iterator::eindex : 0; }
|
||||
int eindex() const { return _e->eindex(); }
|
||||
void operator++() { if (_e) step(_e->router(), eindex()+1);}
|
||||
void operator++(int) { ++(*this); }
|
||||
const ElementT *operator->() const { return _e; }
|
||||
const ElementT *get() const { return _e; }
|
||||
const ElementT &operator*() const { return *_e; }
|
||||
private:
|
||||
const ElementT *_e;
|
||||
const_iterator() : _e(0) { }
|
||||
const_iterator(const RouterT *r, int ei) { step(r, ei); }
|
||||
void step(const RouterT *, int);
|
||||
friend class RouterT;
|
||||
friend class RouterT::iterator;
|
||||
};
|
||||
|
||||
class RouterT::iterator : public RouterT::const_iterator { public:
|
||||
ElementT *operator->() const { return const_cast<ElementT *>(_e); }
|
||||
ElementT *get() const { return const_cast<ElementT *>(_e); }
|
||||
ElementT &operator*() const { return const_cast<ElementT &>(*_e); }
|
||||
private:
|
||||
iterator() : const_iterator() { }
|
||||
iterator(RouterT *r, int ei) : const_iterator(r, ei) { }
|
||||
friend class RouterT;
|
||||
};
|
||||
|
||||
class RouterT::const_type_iterator { public:
|
||||
typedef int (const_type_iterator::*unspecified_bool_type)() const;
|
||||
operator unspecified_bool_type() const { return _e ? &const_type_iterator::eindex : 0; }
|
||||
int eindex() const { return _e->eindex(); }
|
||||
inline void operator++();
|
||||
inline void operator++(int);
|
||||
const ElementT *operator->() const { return _e; }
|
||||
const ElementT *get() const { return _e; }
|
||||
const ElementT &operator*() const { return *_e; }
|
||||
private:
|
||||
const ElementT *_e;
|
||||
ElementClassT *_t;
|
||||
const_type_iterator() : _e(0), _t(0) { }
|
||||
const_type_iterator(const RouterT *r, ElementClassT *t, int i) : _t(t) { step(r, i); }
|
||||
void step(const RouterT *, int);
|
||||
friend class RouterT;
|
||||
friend class RouterT::type_iterator;
|
||||
};
|
||||
|
||||
class RouterT::type_iterator : public RouterT::const_type_iterator { public:
|
||||
ElementT *operator->() const { return const_cast<ElementT *>(_e); }
|
||||
ElementT *get() const { return const_cast<ElementT *>(_e); }
|
||||
ElementT &operator*() const { return const_cast<ElementT &>(*_e); }
|
||||
private:
|
||||
type_iterator() : const_type_iterator() { }
|
||||
type_iterator(RouterT *r, ElementClassT *t, int ei) : const_type_iterator(r, t, ei) { }
|
||||
friend class RouterT;
|
||||
};
|
||||
|
||||
class RouterT::conn_iterator { public:
|
||||
inline conn_iterator() : _conn(0), _by(0) { }
|
||||
typedef bool (conn_iterator::*unspecified_bool_type)() const;
|
||||
operator unspecified_bool_type() const { return _conn ? &conn_iterator::empty : 0; }
|
||||
inline bool empty() const { return !_conn; }
|
||||
inline bool is_back() const;
|
||||
inline conn_iterator &operator++();
|
||||
inline void operator++(int);
|
||||
const ConnectionT *operator->() const { return _conn; }
|
||||
const ConnectionT *get() const { return _conn; }
|
||||
const ConnectionT &operator*() const { return *_conn; }
|
||||
private:
|
||||
const ConnectionX *_conn;
|
||||
int _by;
|
||||
inline conn_iterator(const ConnectionX *conn, int by);
|
||||
void assign(const ConnectionX *conn, int by) {
|
||||
_conn = conn;
|
||||
_by = by;
|
||||
}
|
||||
void complex_step();
|
||||
friend class RouterT;
|
||||
};
|
||||
|
||||
|
||||
inline RouterT::iterator
|
||||
RouterT::begin_elements()
|
||||
{
|
||||
return iterator(this, 0);
|
||||
}
|
||||
|
||||
inline RouterT::const_iterator
|
||||
RouterT::begin_elements() const
|
||||
{
|
||||
return const_iterator(this, 0);
|
||||
}
|
||||
|
||||
inline RouterT::type_iterator
|
||||
RouterT::begin_elements(ElementClassT *t)
|
||||
{
|
||||
return type_iterator(this, t, 0);
|
||||
}
|
||||
|
||||
inline RouterT::const_type_iterator
|
||||
RouterT::begin_elements(ElementClassT *t) const
|
||||
{
|
||||
return const_type_iterator(this, t, 0);
|
||||
}
|
||||
|
||||
inline RouterT::const_iterator
|
||||
RouterT::end_elements() const
|
||||
{
|
||||
return const_iterator();
|
||||
}
|
||||
|
||||
inline RouterT::iterator
|
||||
RouterT::end_elements()
|
||||
{
|
||||
return iterator();
|
||||
}
|
||||
|
||||
inline void
|
||||
RouterT::const_type_iterator::operator++()
|
||||
{
|
||||
if (_e)
|
||||
step(_e->router(), _e->eindex() + 1);
|
||||
}
|
||||
|
||||
inline void
|
||||
RouterT::const_type_iterator::operator++(int)
|
||||
{
|
||||
++(*this);
|
||||
}
|
||||
|
||||
inline
|
||||
RouterT::conn_iterator::conn_iterator(const ConnectionX *conn, int by)
|
||||
: _conn(conn), _by(by)
|
||||
{
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator
|
||||
RouterT::begin_connections() const
|
||||
{
|
||||
return conn_iterator(_conn_head, end_all);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator
|
||||
RouterT::end_connections() const
|
||||
{
|
||||
return conn_iterator();
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_touching(const PortT &port, bool isoutput) const
|
||||
{
|
||||
assert(port.router() == this);
|
||||
return find_connections_touching(port.eindex(), port.port, isoutput);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_touching(ElementT *e, bool isoutput) const
|
||||
{
|
||||
assert(e->router() == this);
|
||||
return find_connections_touching(e->eindex(), -1, isoutput);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_touching(ElementT *e, int port, bool isoutput) const
|
||||
{
|
||||
assert(e->router() == this);
|
||||
return find_connections_touching(e->eindex(), port, isoutput);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_from(const PortT &port) const
|
||||
{
|
||||
return find_connections_touching(port, end_from);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_from(ElementT *e) const
|
||||
{
|
||||
return find_connections_touching(e, end_from);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_from(ElementT *e, int port) const
|
||||
{
|
||||
return find_connections_touching(e, port, end_from);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_to(const PortT &port) const
|
||||
{
|
||||
return find_connections_touching(port, end_to);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_to(ElementT *e) const
|
||||
{
|
||||
return find_connections_touching(e, end_to);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator RouterT::find_connections_to(ElementT *e, int port) const
|
||||
{
|
||||
return find_connections_touching(e, port, end_to);
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator &
|
||||
RouterT::conn_iterator::operator++()
|
||||
{
|
||||
if (_conn && unsigned(_by) <= end_all)
|
||||
_conn = _conn->_next[_by];
|
||||
else
|
||||
complex_step();
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void
|
||||
RouterT::conn_iterator::operator++(int)
|
||||
{
|
||||
++(*this);
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::conn_iterator::is_back() const
|
||||
{
|
||||
conn_iterator x(*this);
|
||||
return x && !++x;
|
||||
}
|
||||
|
||||
inline const ElementT *
|
||||
RouterT::element(const String &s) const
|
||||
{
|
||||
int i = _element_name_map[s];
|
||||
return (i >= 0 ? _elements[i] : 0);
|
||||
}
|
||||
|
||||
inline ElementT *
|
||||
RouterT::element(const String &s)
|
||||
{
|
||||
int i = _element_name_map.get(s);
|
||||
return (i >= 0 ? _elements[i] : 0);
|
||||
}
|
||||
|
||||
inline String
|
||||
RouterT::ename(int e) const
|
||||
{
|
||||
return _elements[e]->name();
|
||||
}
|
||||
|
||||
inline ElementClassT *
|
||||
RouterT::etype(int e) const
|
||||
{
|
||||
return _elements[e]->type();
|
||||
}
|
||||
|
||||
inline String
|
||||
RouterT::etype_name(int e) const
|
||||
{
|
||||
return _elements[e]->type()->name();
|
||||
}
|
||||
|
||||
inline ElementClassT *
|
||||
RouterT::declared_type(const String &name) const
|
||||
{
|
||||
return declared_type(name, 0x7FFFFFFF);
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::add_connection(ElementT *from_elt, int from_port, ElementT *to_elt,
|
||||
int to_port, const LandmarkT &landmark)
|
||||
{
|
||||
return add_connection(PortT(from_elt, from_port), PortT(to_elt, to_port), landmark);
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::insert_before(ElementT *e, const PortT &h)
|
||||
{
|
||||
return insert_before(PortT(e, 0), h);
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::insert_after(ElementT *e, const PortT &h)
|
||||
{
|
||||
return insert_after(PortT(e, 0), h);
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::defines(const String &name) const
|
||||
{
|
||||
for (const String *f = _formals.begin(); f != _formals.end(); ++f)
|
||||
if (*f == name)
|
||||
return true;
|
||||
return _scope.defines(name);
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::add_formal(const String &name, const String &type)
|
||||
{
|
||||
if (defines(name))
|
||||
return false;
|
||||
_formals.push_back(name);
|
||||
_formal_types.push_back(type);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
RouterT::define(const String &name, const String &value)
|
||||
{
|
||||
if (defines(name))
|
||||
return false;
|
||||
return _scope.define(name, value, false);
|
||||
}
|
||||
|
||||
inline void
|
||||
RouterT::redefine(const VariableEnvironment &ve)
|
||||
{
|
||||
for (int i = 0; i < ve.size(); i++)
|
||||
_scope.define(ve.name(i), ve.value(i), true);
|
||||
}
|
||||
|
||||
inline ArchiveElement &
|
||||
RouterT::archive(const String &name)
|
||||
{
|
||||
return _archive[_archive_map.get(name)];
|
||||
}
|
||||
|
||||
inline const ArchiveElement &
|
||||
RouterT::archive(const String &name) const
|
||||
{
|
||||
return _archive[_archive_map[name]];
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const RouterT::const_iterator &i, const RouterT::const_iterator &j)
|
||||
{
|
||||
return i.get() == j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(const RouterT::const_iterator &i, const RouterT::const_iterator &j)
|
||||
{
|
||||
return i.get() != j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const RouterT::const_type_iterator &i, const RouterT::const_type_iterator &j)
|
||||
{
|
||||
return i.get() == j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(const RouterT::const_type_iterator &i, const RouterT::const_type_iterator &j)
|
||||
{
|
||||
return i.get() != j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const RouterT::const_type_iterator &i, const RouterT::const_iterator &j)
|
||||
{
|
||||
return i.get() == j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(const RouterT::const_type_iterator &i, const RouterT::const_iterator &j)
|
||||
{
|
||||
return i.get() != j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const RouterT::conn_iterator &i, const RouterT::conn_iterator &j)
|
||||
{
|
||||
return i.get() == j.get();
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator!=(const RouterT::conn_iterator &i, const RouterT::conn_iterator &j)
|
||||
{
|
||||
return i.get() != j.get();
|
||||
}
|
||||
|
||||
inline RouterT::conn_iterator
|
||||
operator+(RouterT::conn_iterator it, int x)
|
||||
{
|
||||
while (x-- > 0)
|
||||
++it;
|
||||
return it;
|
||||
}
|
||||
|
||||
#endif
|
||||
31
openflow/include/clicktool/runparse.hh
Normal file
31
openflow/include/clicktool/runparse.hh
Normal file
@@ -0,0 +1,31 @@
|
||||
// -*- c-basic-offset: 4 -*-
|
||||
#ifndef CLICK_RUNPARSE_HH
|
||||
#define CLICK_RUNPARSE_HH
|
||||
#include "routert.hh"
|
||||
#include <click/pair.hh>
|
||||
|
||||
class RouterUnparserT { public:
|
||||
|
||||
RouterUnparserT(ErrorHandler *);
|
||||
|
||||
struct Pair {
|
||||
ElementClassT *first;
|
||||
ElementClassT *second;
|
||||
Pair(ElementClassT *a, ElementClassT *b) : first(a), second(b) { }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
HashTable<int, int> _tuid_map;
|
||||
Vector<ElementClassT *> _types;
|
||||
|
||||
enum { X_BAD = 0, X_UNK = 1, X_LT = 2, X_LEQ = 3, X_EQ = 4, X_GEQ = 5, X_GT = 6, X_NUM = 7 };
|
||||
static int relation_negater[X_NUM];
|
||||
static uint8_t relation_combiner[X_NUM][X_NUM];
|
||||
HashTable<Pair<ElementClassT *, ElementClassT *>, int> _relation;
|
||||
|
||||
ErrorHandler *_errh;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
21
openflow/include/clicktool/toolutils.hh
Normal file
21
openflow/include/clicktool/toolutils.hh
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef CLICK_TOOLUTILS_HH
|
||||
#define CLICK_TOOLUTILS_HH
|
||||
#include <click/userutils.hh>
|
||||
class RouterT;
|
||||
class VariableEnvironment;
|
||||
|
||||
extern VariableEnvironment global_scope;
|
||||
extern bool ignore_line_directives;
|
||||
|
||||
int click_maybe_define(const char *arg, ErrorHandler *errh);
|
||||
RouterT *read_router_string(const String &text, const String &landmark, ErrorHandler *);
|
||||
RouterT *read_router_string(String text, const String &landmark, bool, RouterT *, ErrorHandler *);
|
||||
RouterT *read_router_file(const char *filename, ErrorHandler *);
|
||||
RouterT *read_router_file(const char *filename, bool empty_ok, ErrorHandler *);
|
||||
RouterT *read_router(const String &, bool is_expr, ErrorHandler *);
|
||||
void write_router_file(RouterT *, FILE *, ErrorHandler * = 0);
|
||||
int write_router_file(RouterT *, const char *, ErrorHandler * = 0);
|
||||
|
||||
String xml_quote(const String &);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user