diff --git a/.monadid b/.monadid index f10a407930ddecc817846bb1735502d9f850d563..dd982b4e68174f4b7f05621dd3d03234660fbcfd 100644 --- a/.monadid +++ b/.monadid @@ -1,4 +1,4 @@ monad identification file This file is used for monad directory identification Built by toole1 on linux4.ews.illinois.edu -Build Date: Wed Oct 26 16:33:52 CDT 2011 +Build Date: Sat Oct 29 04:30:53 CDT 2011 diff --git a/monad b/monad index 9d1ca1f8b1c4c91babed89d8bd64d628d923b52b..018e061bc485b1180462fc3140e6197328632ef6 100755 Binary files a/monad and b/monad differ diff --git a/proxy.cpp b/proxy.cpp index bc8454f1dbc67336e6b18bae197032b5bf0af140..275ec25baa68d0de4cb106712dae252241b3d572 100644 --- a/proxy.cpp +++ b/proxy.cpp @@ -543,7 +543,7 @@ void test_execution::child_valgrind() nums_pipe.close_write(); start_timeout(); - exec("valgrind", "--trace-children=yes", /*"--log-fd=-1",*/ "-q", "./proxy", test.name, NULL); + exec("valgrind", "--dsymutil=yes", "--trace-children=yes", /*"--log-fd=-1",*/ "-q", "./proxy", test.name, NULL); } diff --git a/proxy.h b/proxy.h index ea3f656840778d8e6e14b698488a88e623deba24..12b44899b8104c57822bbbc5e6b93ec1e6506166 100644 --- a/proxy.h +++ b/proxy.h @@ -219,7 +219,7 @@ using std::endl; namespace proxy { template <typename T> -inline std::string assert_equals_help(T expected, T actual, const char * expstr, const char * actstr) +inline std::string assert_equals_help(const T & expected, const T & actual, const char * expstr, const char * actstr) { std::stringstream ss; if (actual != expected) @@ -267,24 +267,42 @@ namespace proxy uint64_t totalTime; }; - template <typename Generator, typename Timer> TimeIterationsData timeIterationsImpl(Generator gen, Timer timeFunctor, size_t input_size); - template <typename Generator, typename Timer> TimeIterationsData timeIterations (Generator gen, Timer timeFunctor, size_t input_size); - template <typename GenResult, typename GenArg, typename Timer> TimeIterationsData timeIterations (GenResult (*gen)(GenArg), Timer timeFunctor, size_t input_size); + template <typename Generator, typename Timer, typename Cleaner> TimeIterationsData timeIterationsImpl(Generator gen, Timer timeFunctor, Cleaner cleanupFunc, size_t input_size); + template <typename Generator, typename Timer, typename Cleaner> TimeIterationsData timeIterations (Generator gen, Timer timeFunctor, Cleaner cleanupFunc, size_t input_size); + template <typename GenResult, typename GenArg, typename Timer, typename Cleaner> TimeIterationsData timeIterations (GenResult (*gen)(GenArg), Timer timeFunctor, Cleaner cleanupFunc, size_t input_size); - template <typename Generator, typename Timer> - bool assert_time_impl(Generator gen, Timer functor, proxy_runtime_t expectedTime, size_t size1 = 100, size_t size2 = 400); + template <typename Generator, typename Timer, typename Cleaner> + bool assert_time_impl(Generator gen, Timer functor, Cleaner cleanupFunc, proxy_runtime_t expectedTime, size_t size1 = 100, size_t size2 = 400); + + struct nop + { + template <typename T> + void operator()(const T & t) { } + }; } -#define ASSERT_TIME3(gen, functor, expectedTime) \ - do { \ - if (proxy::assert_time_impl(gen, functor, expectedTime)) \ - FAIL(string("Runtime was larger than ") + proxy::runtime_str[expectedTime]); \ +#define ASSERT_TIME3(gen, functor, expectedTime) \ + do { \ + if (proxy::assert_time_impl(gen, functor, proxy::nop(), expectedTime)) \ + FAIL(string("Runtime was larger than ") + proxy::runtime_str[expectedTime]); \ + } while(0) + +#define ASSERT_TIME4(gen, functor, cleanupFunc, expectedTime) \ + do { \ + if (proxy::assert_time_impl(gen, functor, cleanupFunc, expectedTime)) \ + FAIL(string("Runtime was larger than ") + proxy::runtime_str[expectedTime]); \ } while(0) -#define ASSERT_TIME5(gen, functor, expectedTime, size1, size2) \ - do { \ - if (proxy::assert_time_impl(gen, functor, expectedTime, size1, size2)) \ - FAIL(string("Runtime was larger than ") + proxy::runtime_str[expectedTime]); \ +#define ASSERT_TIME5(gen, functor, expectedTime, size1, size2) \ + do { \ + if (proxy::assert_time_impl(gen, functor, proxy::nop(), expectedTime, size1, size2)) \ + FAIL(string("Runtime was larger than ") + proxy::runtime_str[expectedTime]); \ + } while(0) + +#define ASSERT_TIME6(gen, functor, cleanupFunc, expectedTime, size1, size2) \ + do { \ + if (proxy::assert_time_impl(gen, functor, cleanupFunc, expectedTime, size1, size2)) \ + FAIL(string("Runtime was larger than ") + proxy::runtime_str[expectedTime]); \ } while(0) // Crazy hack for overloading! @@ -292,30 +310,31 @@ namespace proxy // http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/ // Overloading tips: // http://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros -#define ASSERT_TIME_SIXTH_ARG(a, b, c, d, e, f, ...) f +#define ASSERT_TIME_SEVENTH_ARG(a, b, c, d, e, f, g, ...) g #define ASSERT_TIME(...) \ - ASSERT_TIME_SIXTH_ARG(__VA_ARGS__, ASSERT_TIME5, 0, ASSERT_TIME3, 0, 0) (__VA_ARGS__) + ASSERT_TIME_SEVENTH_ARG(__VA_ARGS__, ASSERT_TIME6, ASSERT_TIME5, ASSERT_TIME4, ASSERT_TIME3, 0, 0) (__VA_ARGS__) namespace proxy { -template <typename Generator, typename Timer> -TimeIterationsData timeIterations(Generator gen, Timer timeFunctor, size_t input_size) +template <typename Generator, typename Timer, typename Cleaner> +TimeIterationsData timeIterations(Generator gen, Timer timeFunctor, Cleaner cleanupFunc, size_t input_size) { return timeIterationsImpl( bind1st(mem_fun(&Generator::operator()), &gen), timeFunctor, + cleanupFunc, input_size); } -template <typename GenResult, typename GenArg, typename Timer> -TimeIterationsData timeIterations(GenResult (*gen)(GenArg), Timer timeFunctor, size_t input_size) +template <typename GenResult, typename GenArg, typename Timer, typename Cleaner> +TimeIterationsData timeIterations(GenResult (*gen)(GenArg), Timer timeFunctor, Cleaner cleanupFunc, size_t input_size) { - return timeIterationsImpl(ptr_fun(gen), timeFunctor, input_size); + return timeIterationsImpl(ptr_fun(gen), timeFunctor, cleanupFunc, input_size); } -template <typename Generator, typename Timer> -TimeIterationsData timeIterationsImpl(Generator gen, Timer timeFunctor, size_t input_size) +template <typename Generator, typename Timer, typename Cleaner> +TimeIterationsData timeIterationsImpl(Generator gen, Timer timeFunctor, Cleaner cleanupFunc, size_t input_size) { const uint64_t min_time = 1000000; // in microseconds const size_t max_gen_iterations = 1000000; @@ -341,7 +360,11 @@ TimeIterationsData timeIterationsImpl(Generator gen, Timer timeFunctor, size_t i uint64_t endtime = util::process_clock(); for (size_t i = 0; i < max_iterations; i++) + { + cleanupFunc(*inputs[i]); delete inputs[i]; + } + cleanupFunc(warmup_temp); TimeIterationsData result; result.timePerCall = static_cast<double>(endtime - starttime) / succeeded_iterations; @@ -357,12 +380,12 @@ inline void timeIterationsOutput(size_t size, const TimeIterationsData & data) << "for an average of " << data.timePerCall << " us per call" << endl; } -template <typename Generator, typename Timer> -bool assert_time_impl(Generator gen, Timer functor, proxy_runtime_t expectedTime, size_t size1, size_t size2) +template <typename Generator, typename Timer, typename Cleaner> +bool assert_time_impl(Generator gen, Timer functor, Cleaner cleanupMem, proxy_runtime_t expectedTime, size_t size1, size_t size2) { - TimeIterationsData diff0 = timeIterations(gen, functor, 1); - TimeIterationsData diff1 = timeIterations(gen, functor, size1); - TimeIterationsData diff2 = timeIterations(gen, functor, size2); + TimeIterationsData diff0 = timeIterations(gen, functor, cleanupMem, 1); + TimeIterationsData diff1 = timeIterations(gen, functor, cleanupMem, size1); + TimeIterationsData diff2 = timeIterations(gen, functor, cleanupMem, size2); timeIterationsOutput( 1, diff0); timeIterationsOutput(size1, diff1); timeIterationsOutput(size2, diff2); diff --git a/util.cpp b/util.cpp index e32ac36d4b2b33a5ef3e36e0e930f3237f49e805..f624c92dc791a55dc6da7c64d0b5abc5e39ce823 100644 --- a/util.cpp +++ b/util.cpp @@ -322,7 +322,7 @@ void protectDir(const string & dir) // Originally from Simon Biber // http://bytes.com/topic/c/answers/545614-list-files-current-directory -vector<string> get_files_in_dir(const string & dir) +vector<string> get_files_in_dir(const string & dir, bool concatdir /* = true */) { EXIT_IF_ERROR(dir == "" || dir[dir.length()-1] != '/', "Directory name must end in a '/'"); @@ -335,7 +335,7 @@ vector<string> get_files_in_dir(const string & dir) { string file = ent->d_name; if (file != "." && file != "..") - files.push_back(dir + file); + files.push_back(concatdir ? dir + file : file); ent = readdir(dirp); } @@ -592,6 +592,85 @@ void readFileGeneric(const string & filename, FileMap * map, vector<string> * li } +OptionsParser::OptionsParser() +{ + valueMap[""] = true; + + valueMap["yes"] = true; + valueMap["no"] = false; + + valueMap["on"] = true; + valueMap["off"] = false; + + valueMap["true"] = true; + valueMap["false"] = false; + + valueMap["1"] = true; + valueMap["0"] = false; +} + +vector<string> OptionsParser::parse(int argc, const char ** argv) +{ + vector<string> unprocessedArgs; + size_t out_arg_i = 0; + + for (int arg_i = 1; arg_i < argc; arg_i++) + { + string currarg = toLower(argv[arg_i]); + + if (currarg.compare(0, 2, "--") == 0) //long option + { + bool invert = (currarg.compare(2, 2, "no") == 0); + size_t name_i = (invert ? 4 : 2); + size_t equalspos = currarg.find_first_of("=-", name_i); + + string name = currarg.substr(name_i, equalspos - name_i); + string value = (equalspos >= currarg.length()) ? "" : currarg.substr(equalspos); + + optsMap_t::iterator option = optsMap.find(name); + if (option == optsMap.end()) + { + cerr << "Unknown option: " << currarg << endl; + exit(-1); + } + + valueMap_t::iterator valueIt = valueMap.find(value); + if (valueIt == valueMap.end()) + { + cerr << "Unknown value: " << currarg << endl; + exit(-1); + } + + *option->second = valueIt->second ^ invert; + } // "--" + + else if (currarg[0] == '-') //string of single char options + { + for (size_t c = 1; currarg[c] != '\0'; c++) + { + optsMap_t::iterator option = optsMap.find(string(1,currarg[c])); + if (option == optsMap.end()) + { + cerr << "Unknown option: -" << currarg[c] << endl; + exit(-1); + } + *option->second = true; + } + } + + else //positional argument + { + if (out_arg_i < args.size()) + *args[out_arg_i] = currarg; + else + unprocessedArgs.push_back(currarg); + out_arg_i++; + } + } + + return unprocessedArgs; +} + char * processOptions(int argc, char ** argv, OptionsMap & opts, vector<string> & args) { for (int arg_i = 1; arg_i < argc; arg_i++) diff --git a/util.h b/util.h index 93448dfe98538960d562fbbe145d1ff016862234..fd88ac05e25598a448123d05c77b3cf4f43f486a 100644 --- a/util.h +++ b/util.h @@ -1,3 +1,8 @@ +/* CS 225 Util Library + * + * @author Jack Toole + */ + #ifndef UTIL_H #define UTIL_H @@ -61,7 +66,22 @@ struct ci_less : std::binary_function<std::string, std::string, bool> typedef map<string, vector<string>, ci_less> FileMap; typedef map<string, bool, ci_less> OptionsMap; - +class OptionsParser +{ + private: + typedef map<string, bool*> optsMap_t; + typedef map<string, bool> valueMap_t; + valueMap_t valueMap; // not static to prevent still reachable memory + + optsMap_t optsMap; + vector<string *> args; + + public: + OptionsParser(); + void addOption(const string & name, bool & setValue) { optsMap[name] = &setValue; } + void addArg(string & setValue) { args.push_back(&setValue); } + vector<string> parse(int argc, const char ** argv); +}; // EXEC() int8_t exec(int redirect_fd, const char * command, @@ -110,7 +130,7 @@ void copyFiles(const string & sourceFolder, const string & destFolder, const vec void protectFiles(const string & folder, const vector<string> & files); void protectDir(const string & dir); void linkDirs(const string & sourceFolder, const string & destFolder, const vector<string> & dirs); -vector<string> get_files_in_dir(const string & dir); +vector<string> get_files_in_dir(const string & dir, bool concatdir = true); bool is_symlink(const string & file); string get_symlink_target(const string & symlink); @@ -143,6 +163,10 @@ string toLower(const string & str); // String concatenation template <typename T> string to_string(const T & value); +template <typename T> +T from_string(const string & s); +template <typename T, typename F> +T lexical_cast(const F & from); string operator+(const string & lhs, const string & rhs); // These 5 functions are to disambiguate string operator+(const string & lhs, const char * rhs); // operator+ so that the following string operator+(const string & lhs, char rhs); // templates may exist @@ -233,6 +257,34 @@ inline string to_string(const T & value) return ss.str(); } +// http://stackoverflow.com/questions/5017001/like-atoi-but-to-float +template <typename T> +inline T from_string(const string & s) +{ + stringstream ss(s); + T value; + ss >> value; + return value; +} + +template <typename T, typename F> +inline T lexical_cast(const F & from) +{ + T to; + stringstream ss; + if (!(ss << from)) + { + cerr << "ERROR: Could not convert types" << endl; + return to; + } + if (!(ss >> to)) + { + cerr << "ERROR: Could not convert types" << endl; + return to; + } + return to; +} + inline int intlen(unsigned int a) { int len = 1;