📄 click-devirtualize.cc
字号:
/* * click-devirtualize.cc -- virtual function eliminator for Click routers * 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 <click/error.hh>#include <click/confparse.hh>#include <click/straccum.hh>#include "lexert.hh"#include "routert.hh"#include "toolutils.hh"#include "elementmap.hh"#include "cxxclass.hh"#include <click/archive.hh>#include "specializer.hh"#include "signature.hh"#include <click/clp.h>#include <click/driver.hh>#include <stdio.h>#include <ctype.h>#include <errno.h>#include <unistd.h>#define HELP_OPT 300#define VERSION_OPT 301#define CLICKPATH_OPT 302#define ROUTER_OPT 303#define EXPRESSION_OPT 304#define OUTPUT_OPT 305#define KERNEL_OPT 306#define USERLEVEL_OPT 307#define SOURCE_OPT 308#define CONFIG_OPT 309#define NO_DEVIRTUALIZE_OPT 310#define DEVIRTUALIZE_OPT 311#define INSTRS_OPT 312#define REVERSE_OPT 313static Clp_Option options[] = { { "clickpath", 'C', CLICKPATH_OPT, Clp_ArgString, 0 }, { "config", 'c', CONFIG_OPT, 0, Clp_Negate }, { "devirtualize", 0, DEVIRTUALIZE_OPT, Clp_ArgString, Clp_Negate }, { "expression", 'e', EXPRESSION_OPT, Clp_ArgString, 0 }, { "file", 'f', ROUTER_OPT, Clp_ArgString, 0 }, { "help", 0, HELP_OPT, 0, 0 }, { 0, 'n', NO_DEVIRTUALIZE_OPT, Clp_ArgString, 0 }, { "kernel", 'k', KERNEL_OPT, 0, Clp_Negate }, { "instructions", 'i', INSTRS_OPT, Clp_ArgString, 0 }, { "output", 'o', OUTPUT_OPT, Clp_ArgString, 0 }, { "reverse", 'r', REVERSE_OPT, 0, Clp_Negate }, { "source", 's', SOURCE_OPT, 0, Clp_Negate }, { "user", 'u', USERLEVEL_OPT, 0, Clp_Negate }, { "version", 'v', VERSION_OPT, 0, 0 },};static const char *program_name;Stringclick_to_cxx_name(const String &click){ StringAccum sa; const char *s = click.data(); const char *end_s = s + click.length(); for (; s < end_s; s++) if (*s == '_') sa << "_u"; else if (*s == '@') sa << "_a"; else if (*s == '/') sa << "_s"; else sa << *s; return sa.take_string();}Stringspecialized_click_name(ElementT *e){ return e->type_name() + "@@" + e->name();}static voidparse_instruction(const String &text, Signatures &sigs, ErrorHandler *errh){ Vector<String> words; cp_spacevec(text, words); if (words.size() == 0 || words[0].data()[0] == '#') /* nada */; else if (words[0] == "like") { if (words.size() < 3) errh->error("too few arguments to 'like'"); } else if (words[0] == "noclass") { if (words.size() < 2) errh->error("too few arguments to 'noclass'"); for (int i = 1; i < words.size(); i++) sigs.specialize_class(words[i], 0); } else errh->error("unknown command '%s'", words[0].cc());}static voidparse_instruction_file(const char *filename, Signatures &sigs, ErrorHandler *errh){ String text = file_string(filename, errh); const char *s = text.data(); int pos = 0; int len = text.length(); while (pos < len) { int pos1 = pos; while (pos < len && s[pos] != '\n' && s[pos] != '\r') pos++; parse_instruction(text.substring(pos1, pos - pos1), sigs, errh); while (pos < len && (s[pos] == '\n' || s[pos] == '\r')) pos++; }}static voidreverse_transformation(RouterT *r, ErrorHandler *){ // parse fastclassifier_config if (r->archive_index("devirtualize_info") < 0) return; ArchiveElement &fc_ae = r->archive("devirtualize_info"); Vector<String> new_click_names, old_click_names; parse_tabbed_lines(fc_ae.data, &new_click_names, &old_click_names, (void *)0); // prepare type_index_map : type -> configuration # HashMap<ElementClassT *, int> new_type_map(-1); Vector<ElementClassT *> old_class; for (int i = 0; i < new_click_names.size(); i++) { new_type_map.insert(ElementClassT::base_type(new_click_names[i]), old_class.size()); old_class.push_back(ElementClassT::base_type(old_click_names[i])); } // change configuration for (int i = 0; i < r->nelements(); i++) { ElementT *e = r->element(i); int nnm = new_type_map[e->type()]; if (nnm >= 0) e->set_type(old_class[nnm]); } // remove requirements { Vector<String> requirements = r->requirements(); for (int i = 0; i < requirements.size(); i++) if (requirements[i].substring(0, 12) == "devirtualize") r->remove_requirement(requirements[i]); } // remove archive elements for (int i = 0; i < r->narchive(); i++) { ArchiveElement &ae = r->archive(i); if (ae.name.substring(0, 12) == "devirtualize" || ae.name == "elementmap-devirtualize.xml") ae.name = String(); }}voidshort_usage(){ fprintf(stderr, "Usage: %s [OPTION]... [ROUTERFILE]\n\Try '%s --help' for more information.\n", program_name, program_name);}voidusage(){ printf("\'Click-devirtualize' transforms a router configuration by removing virtual\n\function calls from its elements' source code. The resulting configuration has\n\both Click-language files and object files.\n\\n\Usage: %s [OPTION]... [ROUTERFILE]\n\\n\Options:\n\ -f, --file FILE Read router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as router configuration.\n\ -o, --output FILE Write output to FILE.\n\ -k, --kernel Compile into Linux kernel binary package.\n\ -u, --user Compile into user-level binary package.\n\ -s, --source Write source code only.\n\ -c, --config Write new configuration only.\n\ -r, --reverse Reverse devirtualization.\n\ -n, --no-devirtualize CLASS Don't devirtualize element class CLASS.\n\ -i, --instructions FILE Read devirtualization instructions from FILE.\n\ -C, --clickpath PATH Use PATH for CLICKPATH.\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);}intmain(int argc, char **argv){ click_static_initialize(); CLICK_DEFAULT_PROVIDES; ErrorHandler *errh = ErrorHandler::default_handler(); ErrorHandler *p_errh = new PrefixErrorHandler(errh, "click-devirtualize: "); // 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; bool file_is_expr = false; const char *output_file = 0; int source_only = 0; int config_only = 0; int compile_kernel = 0; int compile_user = 0; int reverse = 0; Vector<const char *> instruction_files; HashMap<String, int> specializing; while (1) { int opt = Clp_Next(clp); switch (opt) { case HELP_OPT: usage(); exit(0); break; case VERSION_OPT: printf("click-devirtualize (Click) %s\n", CLICK_VERSION); printf("Copyright (c) 2000 Massachusetts Institute of Technology\n\Copyright (c) 2000 Mazu Networks, Inc.\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 CLICKPATH_OPT: set_clickpath(clp->arg); break; case ROUTER_OPT: case EXPRESSION_OPT: case Clp_NotOption: if (router_file) { p_errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->arg; file_is_expr = (opt == EXPRESSION_OPT); break; case OUTPUT_OPT: if (output_file) { p_errh->error("output file specified twice"); goto bad_option; } output_file = clp->arg; break; case SOURCE_OPT: source_only = !clp->negated; break; case CONFIG_OPT:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -