📄 click-mkmindriver.cc
字号:
// -*- c-basic-offset: 4 -*-/* * click-mkmindriver.cc -- produce a minimum Click driver Makefile setup * Eddie Kohler * * Copyright (c) 2001 Massachusetts Institute of Technology * Copyright (c) 2001 International Computer Science Institute * Copyright (c) 2004 Regents of the University of California * * 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 <click/driver.hh>#include "lexert.hh"#include "routert.hh"#include "toolutils.hh"#include "elementmap.hh"#include <click/clp.h>#include <stdio.h>#include <ctype.h>#include <time.h>#define HELP_OPT 300#define VERSION_OPT 301#define CLICKPATH_OPT 302#define ROUTER_OPT 303#define EXPRESSION_OPT 304#define PACKAGE_OPT 306#define DIRECTORY_OPT 307#define KERNEL_OPT 308#define USERLEVEL_OPT 309#define ELEMENT_OPT 310#define ALIGN_OPT 311#define ALL_OPT 312#define CHECK_OPT 313#define VERBOSE_OPT 314static Clp_Option options[] = { { "align", 'A', ALIGN_OPT, 0, 0 }, { "all", 'a', ALL_OPT, 0, Clp_Negate }, { "check", 0, CHECK_OPT, 0, Clp_Negate }, { "clickpath", 'C', CLICKPATH_OPT, Clp_ArgString, 0 }, { "directory", 'd', DIRECTORY_OPT, Clp_ArgString, 0 }, { "elements", 'E', ELEMENT_OPT, Clp_ArgString, 0 }, { "expression", 'e', EXPRESSION_OPT, Clp_ArgString, 0 }, { "file", 'f', ROUTER_OPT, Clp_ArgString, Clp_Negate }, { "help", 0, HELP_OPT, 0, 0 }, { "kernel", 'k', KERNEL_OPT, 0, 0 }, { "linuxmodule", 0, KERNEL_OPT, 0, 0 }, { "package", 'p', PACKAGE_OPT, Clp_ArgString, 0 }, { "userlevel", 'u', USERLEVEL_OPT, 0, 0 }, { "verbose", 'V', VERBOSE_OPT, 0, Clp_Negate }};static const char *program_name;static String::Initializer string_initializer;static int driver = -1;static HashMap<String, int> initial_requirements(-1);static bool verbose = false;voidshort_usage(){ fprintf(stderr, "Usage: %s -p PKGNAME [OPTION]... [ROUTERFILE]...\n\Try '%s --help' for more information.\n", program_name, program_name);}voidusage(){ printf("\'Click-mkmindriver' produces a Makefile that builds a minimum Click driver\n\for a set of router configurations. This driver contains just the elements\n\those configurations require. Run 'click-mkmindriver' in the relevant driver's\n\build directory and supply a package name with the '-p PKG' option. The\n\resulting Makefile is called 'Makefile.PKG'; it will build either a 'PKGclick'\n\user-level driver or a 'PKGclick.o' kernel module.\n\\n\Usage: %s -p PKG [OPTION]... [ROUTERFILE]...\n\\n\Options:\n\ -p, --package PKG Name of package is PKG.\n\ -f, --file FILE Read a router configuration from FILE.\n\ -e, --expression EXPR Use EXPR as a router configuration.\n\ -a, --all Add all element classes from following configs,\n\ even those in unused compound elements.\n\ -k, --linuxmodule Build Makefile for Linux kernel module driver.\n\ -u, --userlevel Build Makefile for user-level driver (default).\n\ -d, --directory DIR Put files in DIR. DIR must contain a 'Makefile'\n\ for the relevant driver. Default is '.'.\n\ -E, --elements ELTS Include element classes ELTS.\n\ -A, --align Include element classes required by click-align.\n\ --no-file Don't read a configuration from standard input.\n\ --no-check Don't check the directory for a driver Makefile.\n\ -V, --verbose Print progress information.\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);}class Mindriver { public: Mindriver(); void provide(const String&, ErrorHandler*); void require(const String&, ErrorHandler*); void add_source_file(const String&, ErrorHandler*); void add_router_requirements(RouterT*, const ElementMap&, ErrorHandler*); bool add_traits(const Traits&, const ElementMap&, ErrorHandler*); bool resolve_requirement(const String& requirement, const ElementMap& emap, ErrorHandler* errh, bool complain = true); void print_elements_conf(FILE*, String package, const ElementMap&); HashMap<String, int> _provisions; HashMap<String, int> _requirements; HashMap<String, int> _source_files; };Mindriver::Mindriver() : _provisions(-1), _requirements(-1), _source_files(-1){}voidMindriver::provide(const String& req, ErrorHandler* errh){ if (verbose && _provisions[req] < 0) errh->message("providing '%s'", req.c_str()); _provisions.insert(req, 1);}voidMindriver::require(const String& req, ErrorHandler* errh){ if (_provisions[req] < 0) { if (verbose && _requirements[req] < 0) errh->message("requiring '%s'", req.c_str()); _requirements.insert(req, 1); }}voidMindriver::add_source_file(const String& fn, ErrorHandler* errh){ if (verbose && _source_files[fn] < 0) errh->message("adding source file '%s'", fn.c_str()); _source_files.insert(fn, 1);}voidMindriver::add_router_requirements(RouterT* router, const ElementMap& default_map, ErrorHandler* errh){ // find and parse elementmap ElementMap emap(default_map); emap.parse_requirement_files(router, CLICK_SHAREDIR, errh); // check whether suitable for driver if (!emap.driver_compatible(router, driver)) { errh->error("not compatible with %s driver; ignored", Driver::name(driver)); return; } emap.set_driver(driver); StringAccum missing_sa; int nmissing = 0; HashMap<ElementClassT*, int> primitives(-1); router->collect_types(primitives); for (HashMap<ElementClassT*, int>::iterator i = primitives.begin(); i; i++) { if (!i.key()->primitive()) continue; String tname = i.key()->name(); if (!emap.has_traits(tname)) missing_sa << (nmissing++ ? ", " : "") << tname; else if (emap.package(tname)) /* do nothing; element was defined in a package */; else require(tname, errh); } if (nmissing == 1) errh->fatal("cannot locate required element class '%s'\n(This may be due to a missing or out-of-date 'elementmap.xml'.)", missing_sa.c_str()); else if (nmissing > 1) errh->fatal("cannot locate these required element classes:\n %s\n(This may be due to a missing or out-of-date 'elementmap.xml'.)", missing_sa.c_str());}static voidhandle_router(Mindriver& md, String filename_in, const ElementMap &default_map, ErrorHandler *errh){ // decide if 'filename' should be flattened bool flattenable = (filename_in[0] != 'a'); bool file_is_expr = (filename_in[1] == 'e'); const char *filename = filename_in.c_str() + 2; // read file int before = errh->nerrors(); RouterT *router = read_router(filename, file_is_expr, errh); if (file_is_expr) filename = "<expr>"; else if (!filename || strcmp(filename, "-") == 0) filename = "<stdin>"; LandmarkErrorHandler lerrh(errh, filename); if (router && flattenable) router->flatten(&lerrh); if (router && errh->nerrors() == before) md.add_router_requirements(router, default_map, &lerrh); delete router;}boolMindriver::add_traits(const Traits& t, const ElementMap&, ErrorHandler* errh){ if (t.source_file) add_source_file(t.source_file, errh); if (t.name) provide(t.name, errh); if (t.provisions) { Vector<String> args; cp_spacevec(t.provisions, args); for (String* s = args.begin(); s < args.end(); s++) if (Driver::driver(*s) < 0) provide(*s, errh); } if (t.requirements) { Vector<String> args; cp_spacevec(t.requirements, args); for (String* s = args.begin(); s < args.end(); s++) require(*s, errh); } return true;}boolMindriver::resolve_requirement(const String& requirement, const ElementMap& emap, ErrorHandler* errh, bool complain){ LandmarkErrorHandler lerrh(errh, "resolving " + requirement); if (_provisions[requirement] > 0) return true; int try_name_emapi = emap.traits_index(requirement); if (try_name_emapi > 0) { add_traits(emap.traits_at(try_name_emapi), emap, &lerrh); return true; } for (int i = 1; i < emap.size(); i++) if (emap.traits_at(i).provides(requirement)) { add_traits(emap.traits_at(i), emap, &lerrh); return true; } // check for '|' requirements const char *begin = requirement.begin(), *bar; while ((bar = find(begin, requirement.end(), '|')) < requirement.end()) { if (resolve_requirement(requirement.substring(begin, bar), emap, errh, false)) return true; begin = bar + 1; } if (complain) errh->error("cannot satisfy requirement '%s'", requirement.c_str()); return false;}voidMindriver::print_elements_conf(FILE *f, String package, const ElementMap &emap){ Vector<String> sourcevec; for (HashMap<String, int>::iterator iter = _source_files.begin(); iter; iter++) { iter.value() = sourcevec.size(); sourcevec.push_back(iter.key()); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -