From 47e185847e729d49e6aa376e8299fd66ef834a0a Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 13 Aug 2014 03:50:44 +0200 Subject: Refactor option handling --- src/libmain/shared.cc | 82 +++++++++++++++++++++------------------------------ src/libmain/shared.hh | 35 +++++++++++----------- 2 files changed, 52 insertions(+), 65 deletions(-) (limited to 'src/libmain') diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 467a15e76023..ec05db0a6675 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -100,10 +100,16 @@ string getArg(const string & opt, void detectStackOverflow(); -/* Initialize and reorder arguments, then call the actual argument - processor. */ -static void initAndRun(int argc, char * * argv) +void initNix() { + /* Turn on buffering for cerr. */ +#if HAVE_PUBSETBUF + static char buf[1024]; + std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf)); +#endif + + std::ios::sync_with_stdio(false); + settings.processEnvironment(); settings.loadConfFile(); @@ -144,6 +150,14 @@ static void initAndRun(int argc, char * * argv) gettimeofday(&tv, 0); srandom(tv.tv_usec); + if (char *pack = getenv("_NIX_OPTIONS")) + settings.unpack(pack); +} + + +void parseCmdLine(int argc, char * * argv, + std::function parseArg) +{ /* Put the arguments in a vector. */ Strings args, remaining; while (argc--) args.push_back(*argv++); @@ -164,7 +178,6 @@ static void initAndRun(int argc, char * * argv) } else remaining.push_back(arg); } args = remaining; - remaining.clear(); /* Process default options. */ for (Strings::iterator i = args.begin(); i != args.end(); ++i) { @@ -179,14 +192,6 @@ static void initAndRun(int argc, char * * argv) settings.buildVerbosity = lvlVomit; else if (arg == "--print-build-trace") settings.printBuildTrace = true; - else if (arg == "--help") { - printHelp(); - return; - } - else if (arg == "--version") { - std::cout << format("%1% (Nix) %2%") % programId % nixVersion << std::endl; - return; - } else if (arg == "--keep-failed" || arg == "-K") settings.keepFailed = true; else if (arg == "--keep-going" || arg == "-k") @@ -216,25 +221,20 @@ static void initAndRun(int argc, char * * argv) string value = *i; settings.set(name, value); } - else if (arg == "--arg" || arg == "--argstr") { - remaining.push_back(arg); - ++i; if (i == args.end()) throw UsageError(format("`%1%' requires two arguments") % arg); - remaining.push_back(*i); - ++i; if (i == args.end()) throw UsageError(format("`%1%' requires two arguments") % arg); - remaining.push_back(*i); + else { + if (!parseArg(i, args.end())) + throw UsageError(format("unrecognised option `%1%'") % *i); } - else remaining.push_back(arg); } - if (char *pack = getenv("_NIX_OPTIONS")) - settings.unpack(pack); - settings.update(); +} - run(remaining); - /* Close the Nix database. */ - store.reset((StoreAPI *) 0); +void printVersion(const string & programName) +{ + std::cout << format("%1% (Nix) %2%") % programName % nixVersion << std::endl; + throw Exit(); } @@ -246,30 +246,11 @@ void showManPage(const string & name) } -int exitCode = 0; -char * * argvSaved = 0; - -} - - -static char buf[1024]; - -int main(int argc, char * * argv) +int handleExceptions(const string & programName, std::function fun) { - using namespace nix; - - argvSaved = argv; - - /* Turn on buffering for cerr. */ -#if HAVE_PUBSETBUF - std::cerr.rdbuf()->pubsetbuf(buf, sizeof(buf)); -#endif - - std::ios::sync_with_stdio(false); - try { try { - initAndRun(argc, argv); + fun(); } catch (...) { /* Subtle: we have to make sure that any `interrupted' condition is discharged before we reach printMsg() @@ -279,12 +260,14 @@ int main(int argc, char * * argv) _isInterrupted = 0; throw; } + } catch (Exit & e) { + return e.status; } catch (UsageError & e) { printMsg(lvlError, format( "error: %1%\n" "Try `%2% --help' for more information.") - % e.what() % programId); + % e.what() % programName); return 1; } catch (BaseError & e) { printMsg(lvlError, format("error: %1%%2%") % (settings.showTrace ? e.prefix() : "") % e.msg()); @@ -299,5 +282,8 @@ int main(int argc, char * * argv) return 1; } - return exitCode; + return 0; +} + + } diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh index b29b08bb597e..c74e7cbc197d 100644 --- a/src/libmain/shared.hh +++ b/src/libmain/shared.hh @@ -7,25 +7,28 @@ #include -/* These are not implemented here, but must be implemented by a - program linking against libmain. */ +namespace nix { -/* Main program. Called by main() after the ATerm library has been - initialised and some default arguments have been processed (and - removed from `args'). main() will catch all exceptions. */ -void run(nix::Strings args); +MakeError(UsageError, nix::Error); -/* Should print a help message to stdout and return. */ -void printHelp(); +class Exit : public std::exception +{ +public: + int status; + Exit() : status(0) { } + Exit(int status) : status(status) { } +}; -extern std::string programId; +class StoreAPI; +int handleExceptions(const string & programName, std::function fun); -namespace nix { +void initNix(); -MakeError(UsageError, nix::Error); +void parseCmdLine(int argc, char * * argv, + std::function parseArg); -class StoreAPI; +void printVersion(const string & programName); /* Ugh. No better place to put this. */ void printGCWarning(); @@ -36,6 +39,9 @@ void printMissing(const PathSet & willBuild, const PathSet & willSubstitute, const PathSet & unknown, unsigned long long downloadSize, unsigned long long narSize); +string getArg(const string & opt, + Strings::iterator & i, const Strings::iterator & end); + template N getIntArg(const string & opt, Strings::iterator & i, const Strings::iterator & end, bool allowUnit) { @@ -65,9 +71,4 @@ void showManPage(const string & name); extern volatile ::sig_atomic_t blockInt; -/* Exit code of the program. */ -extern int exitCode; - -extern char * * argvSaved; - } -- cgit 1.4.1