⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 click-uncombine.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
字号:
/* * click-uncombine.cc -- separate one Click configuration from a combined * configuration * Eddie Kohler * * Copyright (c) 2000 Massachusetts Institute of Technology * * 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 "routert.hh"#include "lexert.hh"#include <click/error.hh>#include <click/clp.h>#include "toolutils.hh"#include "elementmap.hh"#include <click/confparse.hh>#include <click/straccum.hh>#include <click/driver.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		304static Clp_Option options[] = {  { "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;voidshort_usage(){  fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\Try '%s --help' for more information.\n",	  program_name, program_name);}voidusage(){  printf("\'Click-uncombine' reads a combined Click configuration produced by\n\click-combine and writes one of its components to the standard output.\n\\n\Usage: %s [OPTION]... [ROUTERFILE [COMPONENTNAME]]\n\\n\Options:\n\  -f, --file FILE             Read router configuration from FILE.\n\  -n, --name NAME             Output the router component named NAME.\n\  -o, --output FILE           Write output to FILE.\n\      --help                  Print this message and exit.\n\  -v, --version               Print version number and exit.\n\\n\Report bugs to <click@pdos.lcs.mit.edu>.\n", program_name);}static Vector<ElementT *> component_endpoints;static voidremove_component_links(RouterT *r, ErrorHandler *errh, const String &component){  // prepare  ElementClassT *link_type = ElementClassT::base_type("RouterLink");  if (!link_type)    return;  component_endpoints.clear();  // find all links  Vector<ElementT *> links;  for (RouterT::type_iterator x = r->begin_elements(link_type); x; x++)    links.push_back(x);  for (int i = 0; i < links.size(); i++) {    // check configuration string for correctness    String link_name = links[i]->name();    Vector<String> words;    cp_argvec(links[i]->configuration(), words);    int ninputs = links[i]->ninputs();    int noutputs = links[i]->noutputs();    if (words.size() != 2 * (ninputs + noutputs) || !ninputs || !noutputs) {      errh->error("RouterLink '%s' has strange configuration", link_name.cc());      continue;    }        // check if this RouterLink involves the interesting component    bool interesting = false, bad = false, subcomponent = false;    for (int j = 0; !bad && j < words.size(); j += 2) {      Vector<String> clauses;      cp_spacevec(words[j], clauses);      if (clauses.size() != 3) {	errh->error("RouterLink '%s' has strange configuration", link_name.cc());	bad = true;      } else if (clauses[0] == component)	interesting = true;      else if (clauses[0].substring(0, component.length()) == component	       && clauses[0][component.length()] == '/')	subcomponent = true;    }    if (subcomponent && !bad && !interesting)      // save as part of this component      component_endpoints.push_back(links[i]);    if (bad || !interesting)      continue;    // separate out this component    for (int j = 0; j < words.size(); j += 2) {      Vector<String> clauses;      cp_spacevec(words[j], clauses);      String name = clauses[0] + "/" + clauses[1];      if (ElementT *preexist = r->element(name)) {	errh->lerror(links[i]->landmark(), "RouterLink '%s' element '%s' already exists", link_name.cc(), name.cc());	errh->lerror(preexist->landmark(), "(previous definition was here)");      } else if (clauses[0] == component) {	ElementT *newe = r->get_element(clauses[1], ElementClassT::base_type(clauses[2]), words[j+1], "<click-uncombine>");	if (j/2 < ninputs)	  r->insert_before(newe, PortT(links[i], j/2));	else	  r->insert_after(newe, PortT(links[i], j/2 - ninputs));	component_endpoints.push_back(newe);      }    }    // remove link    r->free_element(links[i]);  }}static voidmark_component(RouterT *r, String compname, Vector<int> &live){  assert(compname.back() == '/');    int nh = r->nconnections();  const Vector<ConnectionT> &conn = r->connections();    // mark endpoints  for (int i = 0; i < component_endpoints.size(); i++)    live[component_endpoints[i]->eindex()] = 1;  // mark everything named with a 'compname' prefix  int compname_len = compname.length();  for (RouterT::iterator e = r->begin_elements(); e; e++)    if (e->name().substring(0, compname_len) == compname)      live[e->eindex()] = 1;  // now find things connected to live elements  bool changed;  do {    changed = false;    for (int i = 0; i < nh; i++)      if (conn[i].dead())	/* nada */;      else if (live[conn[i].from_eindex()] && !live[conn[i].to_eindex()]) {	live[conn[i].to_eindex()] = 1;	changed = true;      } else if (live[conn[i].to_eindex()] && !live[conn[i].from_eindex()]) {	live[conn[i].from_eindex()] = 1;	changed = true;      }  } while (changed);  // print names of lives  //for (int i = 0; i < ne; i++)  //if (live[i])  //fprintf(stderr, "%s\n", r->ename(i).cc());}static voidfrob_nested_routerlinks(RouterT *r, const String &compname){  ElementClassT *t = ElementClassT::base_type("RouterLink");  int cnamelen = compname.length();  for (RouterT::type_iterator x = r->begin_elements(t); x; x++) {    Vector<String> words;    cp_argvec(x->configuration(), words);    for (int j = 0; j < words.size(); j += 2) {      if (words[j].substring(0, cnamelen) == compname)	words[j] = words[j].substring(cnamelen);    }    x->configuration() = cp_unargvec(words);  }}static voidremove_toplevel_component(String component, RouterT *r, const char *filename,			  ErrorHandler *errh, const String &component_prefix){  // find component names  HashMap<String, int> component_map(-1);  Vector<String> component_names;  if (r->archive_index("componentmap") >= 0) {    ArchiveElement &ae = r->archive("componentmap");    cp_spacevec(ae.data, component_names);    for (int i = 0; i < component_names.size(); i++)      component_map.insert(component_names[i], 0);  }  // check if component exists  if (component_map[component] < 0) {    String g = component_prefix + component;    errh->fatal("%s: no '%s' component", filename, g.cc());  }  // remove top-level links  remove_component_links(r, errh, component);  // mark everything connected to the endpoints  component += "/";  Vector<int> live(r->nelements(), 0);  mark_component(r, component, live);    // remove everything not part of the component  for (RouterT::iterator e = r->begin_elements(); e; e++)    if (e->live() && !live[e->eindex()])      e->kill();  r->free_dead_elements();  // rename component  int cnamelen = component.length();  for (int i = 0; i < r->nelements(); i++)    if (live[i]) {      String name = r->element(i)->name();      if (name.substring(0, cnamelen) == component	  && r->eindex(name.substring(cnamelen)) < 0)	r->change_ename(i, name.substring(cnamelen));    }  // fix nested RouterLinks  frob_nested_routerlinks(r, component);    // exit if there have been errors  r->flatten(errh);    if (errh->nerrors() != 0)    exit(1);  // update or remove componentmap  {    ArchiveElement &ae = r->archive("componentmap");    StringAccum sa;    int len = component.length();    for (int i = 0; i < component_names.size(); i++)      if (component_names[i].substring(0, len) == component)	sa << component_names[i].substring(len) << '\n';    if (sa.length())      ae.data = sa.take_string();    else      ae.kill();  }}intmain(int argc, char **argv){  click_static_initialize();  CLICK_DEFAULT_PROVIDES;  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;  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", CLICK_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;      }      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 (router_file)	component = clp->arg;      else	router_file = clp->arg;      break;           bad_option:     case Clp_BadOption:      short_usage();      exit(1);      break;           case Clp_Done:      goto done;          }  }   done:  RouterT *r = read_router_file(router_file, errh);  if (r)    r->flatten(errh);  if (!r || errh->nerrors() > 0)    exit(1);  if (!router_file || strcmp(router_file, "-") == 0)    router_file = "<stdin>";  // find component names  if (r->archive_index("componentmap") < 0)    errh->fatal("%s: not created by 'click-combine' (no 'componentmap')", router_file);  else if (!component)    p_errh->fatal("no component specified");    // walk down one slash at a time  String prefix;  while (component) {    String toplevel = component.substring(component.begin(), find(component, '/'));    String suffix = component.substring(toplevel.end() + 1, component.end());    remove_toplevel_component(toplevel, r, router_file, errh, prefix);    component = suffix;    prefix += component + "/";  }    // 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);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -