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

📄 specializer.cc

📁 COPE the first practical network coding scheme which is developped on click
💻 CC
📖 第 1 页 / 共 2 页
字号:
/* * specializer.{cc,hh} -- specializer * Eddie Kohler * * Copyright (c) 2000 Massachusetts Institute of Technology * Copyright (c) 2000 Mazu Networks, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, subject to the conditions * listed in the Click LICENSE file. These conditions include: you must * preserve this copyright notice, and you cannot mention the copyright * holders in advertising related to the Software without their permission. * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This * notice is a summary of the Click LICENSE file; the license in that file is * legally binding. */#include <click/config.h>#include <click/pathvars.h>#include "specializer.hh"#include "routert.hh"#include <click/error.hh>#include "toolutils.hh"#include "elementmap.hh"#include <click/straccum.hh>#include "signature.hh"#include <ctype.h>Specializer::Specializer(RouterT *router, const ElementMap &em)  : _router(router), _nelements(router->nelements()),    _ninputs(router->nelements(), 0), _noutputs(router->nelements(), 0),    _etinfo_map(0), _header_file_map(-1), _parsed_sources(-1){  _etinfo.push_back(ElementTypeInfo());    for (RouterT::iterator x = router->begin_elements(); x; x++) {    _noutputs[x->eindex()] = x->noutputs();    _ninputs[x->eindex()] = x->ninputs();  }  // prepare from element map  for (ElementMap::TraitsIterator x = em.begin_elements(); x; x++) {    const Traits &e = x.value();    add_type_info(e.name, e.cxx, e.header_file, em.source_directory(e));  }}inline ElementTypeInfo &Specializer::etype_info(int eindex){  return type_info(_router->etype_name(eindex));}inline const ElementTypeInfo &Specializer::etype_info(int eindex) const{  return type_info(_router->etype_name(eindex));}voidSpecializer::add_type_info(const String &click_name, const String &cxx_name,			   const String &header_file, const String &source_dir){  ElementTypeInfo eti;  eti.click_name = click_name;  eti.cxx_name = cxx_name;  eti.header_file = header_file;  eti.source_directory = source_dir;  _etinfo.push_back(eti);  int i = _etinfo.size() - 1;  _etinfo_map.insert(click_name, i);  if (header_file) {    int slash = header_file.find_right('/');    _header_file_map.insert(header_file.substring(slash < 0 ? 0 : slash + 1),			    i);  }}voidElementTypeInfo::locate_header_file(RouterT *for_archive, ErrorHandler *errh){  if (!found_header_file) {    if (!source_directory && for_archive->archive_index(header_file) >= 0)      found_header_file = header_file;    else if (String found = clickpath_find_file(header_file, 0, source_directory))      found_header_file = found;    else {      errh->warning("can't locate header file \"%s\"", header_file.cc());      found_header_file = header_file;    }  }}voidSpecializer::parse_source_file(ElementTypeInfo &etinfo,			       bool do_header, String *includes){  String fn = etinfo.header_file;  if (!do_header && fn.substring(-3) == ".hh")    fn = etinfo.header_file.substring(0, -3) + ".cc";    // don't parse a source file twice  if (_parsed_sources[fn] < 0) {    String text;    if (!etinfo.source_directory && _router->archive_index(fn) >= 0) {      text = _router->archive(fn).data;      if (do_header)	etinfo.found_header_file = fn;    } else if (String found = clickpath_find_file(fn, 0, etinfo.source_directory)) {      text = file_string(found);      if (do_header)	etinfo.found_header_file = found;    }    _cxxinfo.parse_file(text, do_header, includes);    _parsed_sources.insert(fn, 1);  }}voidSpecializer::read_source(ElementTypeInfo &etinfo, ErrorHandler *errh){  if (!etinfo.click_name || etinfo.read_source)    return;  etinfo.read_source = true;  if (!etinfo.header_file) {    errh->warning("element class '%s' has no source file", etinfo.click_name.cc());    return;  }  // parse source text  String text, filename = etinfo.header_file;  if (filename.substring(-3) == ".hh")    parse_source_file(etinfo, true, 0);  parse_source_file(etinfo, false, &etinfo.includes);  // now, read source for the element class's parents  CxxClass *cxxc = _cxxinfo.find_class(etinfo.cxx_name);  if (cxxc)    for (int i = 0; i < cxxc->nparents(); i++) {      const String &p = cxxc->parent(i)->name();      if (p != "Element" && p != "TimedElement" && p != "UnlimitedElement")	read_source(type_info(p), errh);    }}voidSpecializer::check_specialize(int eindex, ErrorHandler *errh){  int sp = _specialize[eindex];  if (_specials[sp].eindex > SPCE_NOT_DONE)    return;  _specials[sp].eindex = SPCE_NOT_SPECIAL;    // get type info  ElementTypeInfo &old_eti = etype_info(eindex);  if (!old_eti.click_name) {    errh->warning("no information about element class '%s'",		  _router->etype_name(eindex).cc());    return;  }    // read source code  if (!old_eti.read_source)    read_source(old_eti, errh);  CxxClass *old_cxxc = _cxxinfo.find_class(old_eti.cxx_name);  if (!old_cxxc) {    errh->warning("C++ class '%s' not found for element class '%s'",		  old_eti.cxx_name.cc(), old_eti.click_name.cc());    return;  }  // don't specialize if there are no reachable functions  SpecializedClass &spc = _specials[sp];  spc.old_click_name = old_eti.click_name;  spc.eindex = eindex;  if (!old_cxxc->find_should_rewrite()) {    spc.click_name = spc.old_click_name;    spc.cxx_name = old_eti.cxx_name;  } else {    spc.click_name = specialized_click_name(_router->element(eindex));    spc.cxx_name = click_to_cxx_name(spc.click_name);    add_type_info(spc.click_name, spc.cxx_name, String(), String());  }}boolSpecializer::create_class(SpecializedClass &spc){  assert(!spc.cxxc);  int eindex = spc.eindex;  if (spc.click_name == spc.old_click_name)    return false;  // create new C++ class  const ElementTypeInfo &old_eti = etype_info(eindex);  CxxClass *old_cxxc = _cxxinfo.find_class(old_eti.cxx_name);  CxxClass *new_cxxc = _cxxinfo.make_class(spc.cxx_name);  assert(old_cxxc && new_cxxc);  bool specialize_away = (old_cxxc->find("devirtualize_all") != 0);  String parent_cxx_name = old_eti.cxx_name;  if (specialize_away) {    CxxClass *parent = old_cxxc->parent(0);    new_cxxc->add_parent(parent);    parent_cxx_name = parent->name();  } else    new_cxxc->add_parent(old_cxxc);  spc.cxxc = new_cxxc;  // add helper functions: constructor, destructor, class_name, cast  if (specialize_away) {    CxxFunction *f = old_cxxc->find(old_eti.cxx_name);    new_cxxc->defun      (CxxFunction(spc.cxx_name, true, "", "()", f->body(), f->clean_body()));    f = old_cxxc->find("~" + old_eti.cxx_name);    new_cxxc->defun      (CxxFunction("~" + spc.cxx_name, true, "", "()", f->body(), f->clean_body()));  } else {    new_cxxc->defun      (CxxFunction(spc.cxx_name, true, "", "()", " ", ""));    new_cxxc->defun      (CxxFunction("~" + spc.cxx_name, true, "", "()", " ", ""));  }    new_cxxc->defun    (CxxFunction("class_name", true, "const char *", "() const",		 String(" return \"") + spc.click_name + "\"; ", ""));  new_cxxc->defun    (CxxFunction("cast", false, "void *", "(const char *n)",		 "\n  if (void *v = " + parent_cxx_name + "::cast(n))\n\    return v;\n  else if (strcmp(n, \"" + spc.click_name + "\") == 0\n\	  || strcmp(n, \"" + old_eti.click_name + "\") == 0)\n\    return (Element *)this;\n  else\n    return 0;\n", ""));    // placeholders for input_pull and output_push  new_cxxc->defun    (CxxFunction("input_pull", false, "inline Packet *",		 (_ninputs[eindex] ? "(int i) const" : "(int) const"),		 "", ""));  new_cxxc->defun    (CxxFunction("output_push", false, "inline void",		 (_noutputs[eindex] ? "(int i, Packet *p) const" : "(int, Packet *p) const"),		 "", ""));  new_cxxc->defun    (CxxFunction("output_push_checked", false, "inline void",		 (_noutputs[eindex] ? "(int i, Packet *p) const" : "(int, Packet *p) const"),		 "", ""));  new_cxxc->defun    (CxxFunction("never_devirtualize", true, "void", "()", "", ""));  // transfer reachable rewritable functions to new C++ class  // with pattern replacements  {    String ninputs_pat = compile_pattern("ninputs()");    String ninputs_repl = String(_ninputs[eindex]);    String noutputs_pat = compile_pattern("noutputs()");    String noutputs_repl = String(_noutputs[eindex]);    String push_pat = compile_pattern("output(#0).push(#1)");    String push_repl = "output_push(#0, #1)";    String checked_push_pat = compile_pattern("checked_output_push(#0, #1)");    String checked_push_repl = compile_pattern("output_push_checked(#0, #1)");    String pull_pat = compile_pattern("input(#0).pull()");    String pull_repl = "input_pull(#0)";    bool any_checked_push = false, any_push = false, any_pull = false;    for (int i = 0; i < old_cxxc->nfunctions(); i++)      if (old_cxxc->should_rewrite(i)) {	const CxxFunction &old_fn = old_cxxc->function(i);	if (new_cxxc->find(old_fn.name())) // don't add again	  continue;	CxxFunction &new_fn = new_cxxc->defun(old_fn);	while (new_fn.replace_expr(ninputs_pat, ninputs_repl)) ;	while (new_fn.replace_expr(noutputs_pat, noutputs_repl)) ;	while (new_fn.replace_expr(push_pat, push_repl))	  any_push = true;	while (new_fn.replace_expr(checked_push_pat, checked_push_repl))	  any_checked_push = true;	while (new_fn.replace_expr(pull_pat, pull_repl))	  any_pull = true;      }    if (!any_push && !any_checked_push)      new_cxxc->find("output_push")->kill();    if (!any_checked_push)      new_cxxc->find("output_push_checked")->kill();    if (!any_pull)      new_cxxc->find("input_pull")->kill();  }  return true;

⌨️ 快捷键说明

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