Commit dd356707 authored by eddietwo's avatar eddietwo

click-combine

parent 05b18e3d
......@@ -15,7 +15,7 @@ bindir = @bindir@
INSTALL = @INSTALL@
mkinstalldirs = @top_srcdir@/mkinstalldirs
TOOLDIRS = click-align click-check click-devirtualize click-fastclassifier click-install click-xform udpgen
TOOLDIRS = click-align click-check click-combine click-devirtualize click-fastclassifier click-install click-xform udpgen
TARGETS = @TOOL_TARGETS@
all: $(TARGETS)
......@@ -26,6 +26,8 @@ click-align: lib Makefile
@cd click-align; $(MAKE) all-local
click-check: lib Makefile
@cd click-check; $(MAKE) all-local
click-combine: lib Makefile
@cd click-combine; $(MAKE) all-local
click-devirtualize: lib Makefile
@cd click-devirtualize; $(MAKE) all-local
click-fastclassifier: lib Makefile
......@@ -76,6 +78,8 @@ DISTFILES = Makefile.in lib/Makefile.in \
click-align/alignclass.cc click-align/alignclass.hh \
click-check/Makefile.in \
click-check/click-check.cc \
click-combine/Makefile.in \
click-combine/click-combine.cc click-combine/click-uncombine.cc \
click-compile.in \
click-devirtualize/Makefile.in \
click-devirtualize/click-devirtualize.cc \
......
/*
* click-fastclassifier.cc -- specialize Click classifiers
* click-check.cc -- check Click configurations for obvious errors
* Eddie Kohler
*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology.
* Copyright (c) 2000 Massachusetts Institute of Technology.
*
* This software is being provided by the copyright holders under the GNU
* General Public License, either version 2 or, at your discretion, any later
......
Makefile *.d
click-combine click-uncombine
SHELL = @SHELL@
@SUBMAKE@
srcdir := @srcdir@
top_srcdir := @top_srcdir@
top_builddir := ../..
subdir := tools/click-combine
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
sbindir = @sbindir@
libdir = @libdir@
datadir = @datadir@/click
VPATH = .:$(top_srcdir)/$(subdir):$(top_srcdir)/tools/lib:$(top_srcdir)/lib
CC = @CC@
CPP = @CPP@
CXX = @CXX@
CXXCPP = @CXXCPP@
PACKAGE = @PACKAGE@
VERSION = @VERSION@
INSTALL = @INSTALL@
mkinstalldirs = @top_srcdir@/mkinstalldirs
.SUFFIXES:
.SUFFIXES: .S .c .cc .o .s
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
.cc.o:
$(CXXCOMPILE) -c $<
OBJS = click-combine.o
UNOBJS = click-uncombine.o
CPPFLAGS = @CPPFLAGS@ -MMD -DCLICK_TOOL
CFLAGS = @CFLAGS@
CXXFLAGS = @CXXFLAGS@
DEFS = @DEFS@ -DCLICK_SHAREDIR='"$(datadir)"' -DCLICK_BINDIR='"$(bindir)"' \
-I. -I$(top_builddir) -I$(srcdir) \
-I$(top_srcdir)/tools/lib -I$(top_srcdir)/lib
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CXXFLAGS)
CXXLD = $(CXX)
CXXLINK = $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(CFLAGS) $(LDFLAGS) -o $@
all: libclicktool.a all-local
all-local: click-combine click-uncombine
libclicktool.a:
@cd ../lib; $(MAKE) libclicktool.a
click-combine: Makefile $(OBJS) ../lib/libclicktool.a
$(CXXLINK) $(OBJS) ../lib/libclicktool.a
click-uncombine: Makefile $(UNOBJS) ../lib/libclicktool.a
$(CXXLINK) $(UNOBJS) ../lib/libclicktool.a
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_ELEMLISTS=no CONFIG_HEADERS= $(SHELL) ./config.status
DEPFILES := $(wildcard *.d)
ifneq ($(DEPFILES),)
include $(DEPFILES)
endif
install: click-check
$(mkinstalldirs) $(bindir)
$(INSTALL) click-combine $(bindir)/click-combine
$(INSTALL) click-uncombine $(bindir)/click-uncombine
install-man:
clean:
rm -f *.d *.o click-combine click-uncombine
distclean: clean
-rm -f Makefile
.PHONY: all all-local clean distclean install install-bin install-man libclicktool.a
This diff is collapsed.
/*
* click-uncombine.cc -- separate one Click configuration from a combined
* configuration
* Eddie Kohler
*
* Copyright (c) 2000 Massachusetts Institute of Technology.
*
* This software is being provided by the copyright holders under the GNU
* General Public License, either version 2 or, at your discretion, any later
* version. For more information, see the `COPYRIGHT' file in the source
* distribution.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "routert.hh"
#include "lexert.hh"
#include "error.hh"
#include "clp.h"
#include "toolutils.hh"
#include "confparse.hh"
#include "straccum.hh"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <stdarg.h>
#define HELP_OPT 300
#define VERSION_OPT 301
#define ROUTER_OPT 302
#define OUTPUT_OPT 303
#define NAME_OPT 304
static Clp_Option options[] = {
{ "component", 'c', NAME_OPT, Clp_ArgString, 0 },
{ "file", 'f', ROUTER_OPT, Clp_ArgString, 0 },
{ "help", 0, HELP_OPT, 0, 0 },
{ "name", 'n', NAME_OPT, Clp_ArgString, 0 },
{ "output", 'o', OUTPUT_OPT, Clp_ArgString, 0 },
{ "version", 'v', VERSION_OPT, 0, 0 },
};
static const char *program_name;
static String::Initializer string_initializer;
static String runclick_prog;
void
short_usage()
{
fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\
Try `%s --help' for more information.\n",
program_name, program_name);
}
void
usage()
{
printf("\
`Click-uncombine' reads a combined Click configuration produced by\n\
click-combine, separates one of its components, and writes that component to\n\
the standard output.\n\
\n\
Usage: %s [OPTION]... [COMPONENTNAME | ROUTERFILE COMPONENTNAME]\n\
\n\
Options:\n\
-f, --file FILE Read router configuration from FILE.\n\
-o, --output FILE Write output to FILE.\n\
-c, --component NAME Separate component named NAME.\n\
--help Print this message and exit.\n\
-v, --version Print version number and exit.\n\
\n\
Report bugs to <click@pdos.lcs.mit.edu>.\n", program_name);
}
static void
remove_links(RouterT *r, ErrorHandler *errh)
{
int link_type = r->type_index("RouterLink");
if (link_type < 0)
return;
Vector<int> links;
for (int i = 0; i < r->nelements(); i++)
if (r->etype(i) == link_type && r->ename(i).find_left('/') < 0)
links.push_back(i);
for (int i = 0; i < links.size(); i++) {
Vector<String> words;
cp_argvec(r->econfiguration(links[i]), words);
String link_name = r->ename(i);
if (words.size() != 6)
errh->error("RouterLink `%s' has strange configuration", link_name.cc());
else if (r->eindex(words[0]) >= 0)
errh->error("RouterLink `%s' element `%s' already exists", link_name.cc(), words[0].cc());
else if (r->eindex(words[3]) >= 0)
errh->error("RouterLink `%s' element `%s' already exists", link_name.cc(), words[3].cc());
else {
int e1 = r->get_eindex(words[0], r->get_type_index(words[1]), words[2], String());
int e2 = r->get_eindex(words[3], r->get_type_index(words[4]), words[5], String());
r->insert_before(e1, Hookup(links[i], 0));
r->insert_after(e2, Hookup(links[i], 0));
r->free_element(links[i]);
}
}
}
int
main(int argc, char **argv)
{
String::static_initialize();
ErrorHandler::static_initialize(new FileErrorHandler(stderr));
ErrorHandler *errh = ErrorHandler::default_handler();
ErrorHandler *p_errh = new PrefixErrorHandler(errh, "click-uncombine: ");
// 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;
const char *output_file = 0;
bool auto_router_file = true;
String component;
while (1) {
int opt = Clp_Next(clp);
switch (opt) {
case HELP_OPT:
usage();
exit(0);
break;
case VERSION_OPT:
printf("click-uncombine (Click) %s\n", VERSION);
printf("Copyright (C) 2000 Massachusetts Institute of Technology\n\
This is free software; see the source for copying conditions.\n\
There is NO warranty, not even for merchantability or fitness for a\n\
particular purpose.\n");
exit(0);
break;
case ROUTER_OPT:
if (router_file) {
p_errh->error("combined router specified twice");
goto bad_option;
}
auto_router_file = false;
router_file = clp->arg;
break;
case OUTPUT_OPT:
if (output_file) {
p_errh->error("output file specified twice");
goto bad_option;
}
output_file = clp->arg;
break;
case NAME_OPT:
if (component) {
p_errh->error("component name specified twice");
goto bad_option;
}
component = clp->arg;
break;
case Clp_NotOption:
// if only one argument given, it's a component name
if (router_file && component) {
p_errh->error("component name specified twice");
goto bad_option;
} else if (component)
router_file = component;
component = clp->arg;
break;
bad_option:
case Clp_BadOption:
short_usage();
exit(1);
break;
case Clp_Done:
goto done;
}
}
done:
RouterT *r = 0;
r = read_router_file(router_file, errh);
if (!r || errh->nerrors() > 0)
exit(1);
r->flatten(errh);
// remove links
remove_links(r, errh);
// find component names
HashMap<String, int> component_map(-1);
int link_type = r->type_index("RouterLink");
for (int i = 0; i < r->nelements(); i++)
if (!r->eblank(i)) {
String s = r->ename(i);
int slash = s.find_left('/');
if (slash >= 0)
component_map.insert(s.substring(0, slash), 0);
else if (r->etype(i) != link_type) {
static int warned = 0;
if (!warned)
p_errh->warning("router might not be a combination (strange element names)");
warned++;
}
}
// check if component exists
if (!component)
p_errh->fatal("no component specified");
else if (component_map[component] < 0)
p_errh->fatal("no component `%s' in r router", component.cc());
// remove everything not part of the component
component += "/";
int clen = component.length();
for (int i = 0; i < r->nelements(); i++)
if (!r->eblank(i)) {
String name = r->ename(i);
if (name.substring(0, clen) != component)
r->blank_element(i);
else
r->change_ename(i, name.substring(clen));
}
// exit if there have been errors
r->flatten(errh);
if (errh->nerrors() != 0)
exit(1);
// open output file
FILE *outf = stdout;
if (output_file && strcmp(output_file, "-") != 0) {
outf = fopen(output_file, "w");
if (!outf)
errh->fatal("%s: %s", output_file, strerror(errno));
}
write_router_file(r, outf, errh);
exit(0);
}
......@@ -230,6 +230,18 @@ RouterT::get_anon_eindex(int type_index, const String &config,
return get_anon_eindex(name, type_index, config, landmark);
}
void
RouterT::change_ename(int ei, const String &new_name)
{
ElementT &e = _elements[ei];
if (e.type >= 0) {
if (_element_name_map[e.name] == ei)
_element_name_map.insert(e.name, -1);
e.name = new_name;
_element_name_map.insert(new_name, ei);
}
}
void
RouterT::get_types_from(const RouterT *r)
{
......@@ -736,6 +748,14 @@ RouterT::finish_free_elements(Vector<int> &new_eindex)
}
}
void
RouterT::free_element(int e)
{
Vector<int> new_eindex(nelements(), 0);
new_eindex[e] = -1;
finish_free_elements(new_eindex);
}
void
RouterT::free_blank_elements()
{
......
......@@ -77,6 +77,7 @@ class RouterT : public ElementClassT {
int eindex(const String &s) const { return _element_name_map[s]; }
const ElementT &element(int i) const { return _elements[i]; }
ElementT &element(int i) { return _elements[i]; }
bool eblank(int ei) const { return _elements[ei].type < 0; }
String ename(int) const;
String ename_upref(int) const;
int etype(int) const;
......@@ -90,6 +91,9 @@ class RouterT : public ElementClassT {
int get_eindex(const String &name, int etype_index, const String &configuration, const String &landmark);
int get_anon_eindex(const String &name, int ftype_index, const String &configuration = String(), const String &landmark = String());
int get_anon_eindex(int ftype_index, const String &configuration = String(), const String &landmark = String());
void free_element(int);
void blank_element(int i) { _elements[i].type = -1; }
void change_ename(int, const String &);
void set_new_eindex_collector(Vector<int> *v) { _new_eindex_collector = v; }
......@@ -125,8 +129,8 @@ class RouterT : public ElementClassT {
void find_connection_vector_to(int, Vector<int> &) const;
void count_ports(Vector<int> &, Vector<int> &) const;
bool insert_before(int fidx, const Hookup &);
bool insert_after(int fidx, const Hookup &);
bool insert_before(int, const Hookup &);
bool insert_after(int, const Hookup &);
void add_components_to(RouterT *, const String &prefix = String()) const;
......
......@@ -466,12 +466,14 @@ ElementMap::processing_code(const String &n) const
}
void
ElementMap::add(const String &click_name, const String &cxx_name,
ElementMap::add(const String &click_name, String cxx_name,
String header_file, String processing_code)
{
if (!click_name || !cxx_name)
if (!click_name)
return;
if (cxx_name == "?")
cxx_name = String();
if (header_file == "?")
header_file = String();
if (processing_code == "?")
......@@ -531,7 +533,11 @@ ElementMap::unparse() const
{
StringAccum sa;
for (int i = 0; i < size(); i++) {
sa << _name[i] << '\t' << _cxx_name[i] << '\t';
sa << _name[i] << '\t';
if (_cxx_name[i])
sa << _cxx_name[i] << '\t';
else
sa << "?\t";
if (_header_file[i])
sa << _header_file[i] << '\t';
else
......
......@@ -49,7 +49,7 @@ class ElementMap {
int find(const String &n) const { return _name_map[n]; }
int find_cxx(const String &n) const { return _cxx_name_map[n]; }
void add(const String &, const String &, String, String);
void add(const String &, String, String, String);
void remove(int);
void remove(const String &n) { remove(find(n)); }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment