📄 click-devirtualize.cc
字号:
break; case ROUTER_OPT: case EXPRESSION_OPT: router_file: if (router_file) { p_errh->error("router configuration specified twice"); goto bad_option; } router_file = clp->vstr; file_is_expr = (opt == EXPRESSION_OPT); break; case Clp_NotOption: if (!click_maybe_define(clp->vstr, p_errh)) goto router_file; break; case OUTPUT_OPT: if (output_file) { p_errh->error("output file specified twice"); goto bad_option; } output_file = clp->vstr; break; case SOURCE_OPT: source_only = !clp->negated; break; case CONFIG_OPT: config_only = !clp->negated; break; case KERNEL_OPT: compile_kernel = !clp->negated; break; case USERLEVEL_OPT: compile_user = !clp->negated; break; case DEVIRTUALIZE_OPT: specializing.set(clp->vstr, !clp->negated); break; case NO_DEVIRTUALIZE_OPT: specializing.set(clp->vstr, 0); break; case INSTRS_OPT: instruction_files.push_back(clp->vstr); break; case REVERSE_OPT: reverse = !clp->negated; break; bad_option: case Clp_BadOption: short_usage(); exit(1); break; case Clp_Done: goto done; } } done: if (config_only) compile_kernel = compile_user = 0; // read router RouterT *router = read_router(router_file, file_is_expr, errh); if (router) router->flatten(errh); if (!router || 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)); } // handle reversing case if (reverse) { reverse_transformation(router, errh); write_router_file(router, outf, errh); exit(0); } // find and parse elementmap ElementMap full_elementmap; full_elementmap.parse_all_files(router, CLICK_DATADIR, errh); // initialize signatures Signatures sigs(router); // follow instructions embedded in router definition ElementClassT *devirtualize_info_class = ElementClassT::base_type("DevirtualizeInfo"); for (RouterT::type_iterator x = router->begin_elements(devirtualize_info_class); x; x++) { Vector<String> args; cp_argvec(x->configuration(), args); for (int j = 0; j < args.size(); j++) parse_instruction(args[j], sigs, p_errh); } // follow instructions from command line { for (int i = 0; i < instruction_files.size(); i++) parse_instruction_file(instruction_files[i], sigs, errh); for (StringMap::iterator iter = specializing.begin(); iter.live(); iter++) sigs.specialize_class(iter.key(), iter.value()); } // choose driver for output full_elementmap.check_completeness(router, p_errh); String suffix = ""; String driver_requirement = ""; if (!full_elementmap.driver_indifferent(router)) { bool linuxmodule_ok = full_elementmap.driver_compatible (router, Driver::LINUXMODULE); bool userlevel_ok = full_elementmap.driver_compatible (router, Driver::USERLEVEL); if (linuxmodule_ok && userlevel_ok && (compile_kernel > 0) == (compile_user > 0)) p_errh->fatal("kernel and user-level drivers require different code;\nyou must specify either '-k' or '-u'"); else if (!linuxmodule_ok && compile_kernel > 0) p_errh->fatal("configuration incompatible with kernel driver"); else if (!userlevel_ok && compile_user > 0) p_errh->fatal("configuration incompatible with user-level driver"); else if (compile_kernel > 0 || (linuxmodule_ok && compile_user <= 0)) { suffix = ".k"; driver_requirement = "linuxmodule "; full_elementmap.set_driver(Driver::LINUXMODULE); } else { suffix = ".u"; driver_requirement = "userlevel "; full_elementmap.set_driver(Driver::USERLEVEL); } } // analyze signatures to determine specialization sigs.analyze(full_elementmap); // initialize specializer Specializer specializer(router, full_elementmap); specializer.specialize(sigs, errh); // quit early if nothing was done if (specializer.nspecials() == 0) { if (source_only) errh->message("nothing to devirtualize"); else write_router_file(router, outf, errh); exit(0); } // find name of package String package_name; { md5_state_t pms; char buf[MD5_TEXT_DIGEST_MAX_SIZE]; String s = router->configuration_string(); md5_init(&pms); md5_append(&pms, (const md5_byte_t *) s.data(), s.length()); int buflen = md5_finish_text(&pms, buf, 0); md5_free(&pms); package_name = "clickdv_" + String(buf, buflen); } router->add_requirement(package_name); // output StringAccum header, source; source << "/** click-compile: -w -fno-access-control */\n"; header << "#ifndef CLICK_" << package_name << "_HH\n" << "#define CLICK_" << package_name << "_HH\n" << "#include <click/package.hh>\n#include <click/element.hh>\n"; specializer.output_package(package_name, suffix, source, errh); specializer.output(header, source); header << "#endif\n"; // output source code if required if (source_only) { ignore_result(fwrite(header.data(), 1, header.length(), outf)); ignore_result(fwrite(source.data(), 1, source.length(), outf)); fclose(outf); exit(0); } // add source to archive { ArchiveElement ae = init_archive_element(package_name + suffix + ".cc", 0600); ae.data = source.take_string(); router->add_archive(ae); ae.name = package_name + suffix + ".hh"; ae.data = header.take_string(); router->add_archive(ae); } // add compiled versions to archive if (compile_user > 0 || compile_kernel > 0) { int source_ae = router->archive_index(package_name + suffix + ".cc"); BailErrorHandler berrh(errh); bool tmpdir_populated = false; if (compile_kernel > 0) if (String fn = click_compile_archive_file(router->archive(), &router->archive()[source_ae], package_name, "linuxmodule", "", tmpdir_populated, &berrh)) { ArchiveElement ae = init_archive_element(package_name + ".ko", 0600); ae.data = file_string(fn, errh); router->add_archive(ae); } if (compile_user > 0) if (String fn = click_compile_archive_file(router->archive(), &router->archive()[source_ae], package_name, "userlevel", "", tmpdir_populated, &berrh)) { ArchiveElement ae = init_archive_element(package_name + ".uo", 0600); ae.data = file_string(fn, errh); router->add_archive(ae); } } // retype elements specializer.fix_elements(); // add elementmap to archive { if (router->archive_index("elementmap-devirtualize.xml") < 0) router->add_archive(init_archive_element("elementmap-devirtualize.xml", 0600)); ArchiveElement &ae = router->archive("elementmap-devirtualize.xml"); ElementMap em(ae.data); specializer.output_new_elementmap(full_elementmap, em, package_name + suffix, driver_requirement); ae.data = em.unparse("devirtualize"); } // add devirtualize_info to archive { if (router->archive_index("devirtualize_info") < 0) router->add_archive(init_archive_element("devirtualize_info", 0600)); ArchiveElement &ae = router->archive("devirtualize_info"); StringAccum sa; for (int i = 0; i < specializer.nspecials(); i++) { const SpecializedClass &c = specializer.special(i); if (c.special()) sa << c.click_name << '\t' << c.old_click_name << '\n'; } ae.data += sa.take_string(); } // write configuration if (config_only) { String s = router->configuration_string(); ignore_result(fwrite(s.data(), 1, s.length(), outf)); } else write_router_file(router, outf, errh); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -