#include "initialize_stack.hpp" #include <getopt.h> using namespace std; using namespace IRDB_SDK; using namespace InitStack; // // Print usage info // void usage(char *p_name) { cerr << "Usage: " << p_name << " <variant_id>\n"; cerr << "\t[--functions <file> | -f <file>] Read in the functions to " "auto-initialize " << endl; cerr << "\t[--initvalue <value> | -i <value>] Specify stack " "initialization value (default=0)" << endl; cerr << "\t[--verbose | -v] Verbose mode " " " << endl; cerr << "\t[--help,--usage,-?,-h] Display this message " " " << endl; } // // The entry point for a stand-alone executable transform. // Note: Thanos-enabled transforms are easier to write, faster to execute, and // generally preferred. Stand-alone transforms may be useful if the transform // has issues with memory leaks and/or memory errors. Memory issues in a stand // alone transform cannot affect correctness of other transforms. // int main(int argc, char **argv) { // // Sanity check that the command line has at least a variant ID, otherwise we // won't know what variant to operate on. // if (argc < 2) { usage(argv[0]); exit(1); } // constant parameters read from argv const auto program_name = string(argv[0]); const auto variantID = atoi(argv[1]); // initial values of parameters to parse auto verbose = false; auto funcs_filename = string(); auto init_value = 0; // declare some options for the transform const char *short_opts = "f:i:v?h"; struct option long_options[] = {{"functions", required_argument, 0, 'f'}, {"initvalue", required_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'}, {"usage", no_argument, 0, '?'}, {0, 0, 0, 0}}; // parse the options in a standard getopts_long loop while (true) { int c = getopt_long(argc, argv, short_opts, long_options, nullptr); if (c == -1) break; switch (c) { case 'f': funcs_filename = optarg; cout << "Reading file with function specifiers: " << funcs_filename << endl; break; case 'i': init_value = strtoll(optarg, NULL, 0); cout << " Stack initialization value: " << hex << init_value << endl; break; case 'v': verbose = true; break; case '?': case 'h': usage(argv[0]); exit(1); break; default: break; } } // stand alone transforms must setup the interface to the sql server auto pqxx_interface = pqxxDB_t::factory(); BaseObj_t::setInterface(pqxx_interface.get()); // stand alone transforms must create and read a variant ID from the database auto pidp = VariantID_t::factory(variantID); assert(pidp->isRegistered() == true); // stand alone transforms must create and read the main file's IR from the // datatbase auto this_file = pidp->getMainFile(); auto url = this_file->getURL(); // declare for later so we can return the right value auto success = false; // now try to load the IR and execute a transform try { // Create and download the file's IR. // Note: this is achieved differently with thanos-enabled plugins auto firp = FileIR_t::factory(pidp.get(), this_file); // sanity assert(firp && pidp); // log cout << "Transforming " << this_file->getURL() << endl; // create and invoke the transform InitStack_t is(firp.get(), funcs_filename, init_value, verbose); success = is.execute(); // conditionally write the IR back to the database on success if (success) { cout << "Writing changes for " << url << endl; // Stand alone trnasforms must manually write the IR back to the IRDB and // commit the transactions firp->writeToDB(); // and commit the the transaction to postgres pqxx_interface->commit(); } else { cout << "Skipping write back on failure. " << url << endl; } } catch (const DatabaseError_t &db_error) { // log any databse errors that might come up in the transform process cerr << program_name << ": Unexpected database error: " << db_error << "file url: " << url << endl; } catch (...) { // log any other errors cerr << program_name << ": Unexpected error file url: " << url << endl; } // // return success code to driver (as a shell-style return value). 0=success, // 1=warnings, 2=errors // return success ? 0 : 2; }