annotate osx/include/kj/main.h @ 54:5f67a29f0fc7

Rebuild MAD with 64-bit FPM
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 30 Nov 2016 20:59:17 +0000
parents 3ab5a40c4e3b
children 0994c39f1e94
rev   line source
cannam@49 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@49 2 // Licensed under the MIT License:
cannam@49 3 //
cannam@49 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@49 5 // of this software and associated documentation files (the "Software"), to deal
cannam@49 6 // in the Software without restriction, including without limitation the rights
cannam@49 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@49 8 // copies of the Software, and to permit persons to whom the Software is
cannam@49 9 // furnished to do so, subject to the following conditions:
cannam@49 10 //
cannam@49 11 // The above copyright notice and this permission notice shall be included in
cannam@49 12 // all copies or substantial portions of the Software.
cannam@49 13 //
cannam@49 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@49 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@49 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@49 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@49 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@49 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@49 20 // THE SOFTWARE.
cannam@49 21
cannam@49 22 #ifndef KJ_MAIN_H_
cannam@49 23 #define KJ_MAIN_H_
cannam@49 24
cannam@49 25 #if defined(__GNUC__) && !KJ_HEADER_WARNINGS
cannam@49 26 #pragma GCC system_header
cannam@49 27 #endif
cannam@49 28
cannam@49 29 #include "array.h"
cannam@49 30 #include "string.h"
cannam@49 31 #include "vector.h"
cannam@49 32 #include "function.h"
cannam@49 33
cannam@49 34 namespace kj {
cannam@49 35
cannam@49 36 class ProcessContext {
cannam@49 37 // Context for command-line programs.
cannam@49 38
cannam@49 39 public:
cannam@49 40 virtual StringPtr getProgramName() = 0;
cannam@49 41 // Get argv[0] as passed to main().
cannam@49 42
cannam@49 43 KJ_NORETURN(virtual void exit()) = 0;
cannam@49 44 // Indicates program completion. The program is considered successful unless `error()` was
cannam@49 45 // called. Typically this exits with _Exit(), meaning that the stack is not unwound, buffers
cannam@49 46 // are not flushed, etc. -- it is the responsibility of the caller to flush any buffers that
cannam@49 47 // matter. However, an alternate context implementation e.g. for unit testing purposes could
cannam@49 48 // choose to throw an exception instead.
cannam@49 49 //
cannam@49 50 // At first this approach may sound crazy. Isn't it much better to shut down cleanly? What if
cannam@49 51 // you lose data? However, it turns out that if you look at each common class of program, _Exit()
cannam@49 52 // is almost always preferable. Let's break it down:
cannam@49 53 //
cannam@49 54 // * Commands: A typical program you might run from the command line is single-threaded and
cannam@49 55 // exits quickly and deterministically. Commands often use buffered I/O and need to flush
cannam@49 56 // those buffers before exit. However, most of the work performed by destructors is not
cannam@49 57 // flushing buffers, but rather freeing up memory, placing objects into freelists, and closing
cannam@49 58 // file descriptors. All of this is irrelevant if the process is about to exit anyway, and
cannam@49 59 // for a command that runs quickly, time wasted freeing heap space may make a real difference
cannam@49 60 // in the overall runtime of a script. Meanwhile, it is usually easy to determine exactly what
cannam@49 61 // resources need to be flushed before exit, and easy to tell if they are not being flushed
cannam@49 62 // (because the command fails to produce the expected output). Therefore, it is reasonably
cannam@49 63 // easy for commands to explicitly ensure all output is flushed before exiting, and it is
cannam@49 64 // probably a good idea for them to do so anyway, because write failures should be detected
cannam@49 65 // and handled. For commands, a good strategy is to allocate any objects that require clean
cannam@49 66 // destruction on the stack, and allow them to go out of scope before the command exits.
cannam@49 67 // Meanwhile, any resources which do not need to be cleaned up should be allocated as members
cannam@49 68 // of the command's main class, whose destructor normally will not be called.
cannam@49 69 //
cannam@49 70 // * Interactive apps: Programs that interact with the user (whether they be graphical apps
cannam@49 71 // with windows or console-based apps like emacs) generally exit only when the user asks them
cannam@49 72 // to. Such applications may store large data structures in memory which need to be synced
cannam@49 73 // to disk, such as documents or user preferences. However, relying on stack unwind or global
cannam@49 74 // destructors as the mechanism for ensuring such syncing occurs is probably wrong. First of
cannam@49 75 // all, it's 2013, and applications ought to be actively syncing changes to non-volatile
cannam@49 76 // storage the moment those changes are made. Applications can crash at any time and a crash
cannam@49 77 // should never lose data that is more than half a second old. Meanwhile, if a user actually
cannam@49 78 // does try to close an application while unsaved changes exist, the application UI should
cannam@49 79 // prompt the user to decide what to do. Such a UI mechanism is obviously too high level to
cannam@49 80 // be implemented via destructors, so KJ's use of _Exit() shouldn't make a difference here.
cannam@49 81 //
cannam@49 82 // * Servers: A good server is fault-tolerant, prepared for the possibility that at any time
cannam@49 83 // it could crash, the OS could decide to kill it off, or the machine it is running on could
cannam@49 84 // just die. So, using _Exit() should be no problem. In fact, servers generally never even
cannam@49 85 // call exit anyway; they are killed externally.
cannam@49 86 //
cannam@49 87 // * Batch jobs: A long-running batch job is something between a command and a server. It
cannam@49 88 // probably knows exactly what needs to be flushed before exiting, and it probably should be
cannam@49 89 // fault-tolerant.
cannam@49 90 //
cannam@49 91 // Meanwhile, regardless of program type, if you are adhering to KJ style, then the use of
cannam@49 92 // _Exit() shouldn't be a problem anyway:
cannam@49 93 //
cannam@49 94 // * KJ style forbids global mutable state (singletons) in general and global constructors and
cannam@49 95 // destructors in particular. Therefore, everything that could possibly need cleanup either
cannam@49 96 // lives on the stack or is transitively owned by something living on the stack.
cannam@49 97 //
cannam@49 98 // * Calling exit() simply means "Don't clean up anything older than this stack frame.". If you
cannam@49 99 // have resources that require cleanup before exit, make sure they are owned by stack frames
cannam@49 100 // beyond the one that eventually calls exit(). To be as safe as possible, don't place any
cannam@49 101 // state in your program's main class, and don't call exit() yourself. Then, runMainAndExit()
cannam@49 102 // will do it, and the only thing on the stack at that time will be your main class, which
cannam@49 103 // has no state anyway.
cannam@49 104 //
cannam@49 105 // TODO(someday): Perhaps we should use the new std::quick_exit(), so that at_quick_exit() is
cannam@49 106 // available for those who really think they need it. Unfortunately, it is not yet available
cannam@49 107 // on many platforms.
cannam@49 108
cannam@49 109 virtual void warning(StringPtr message) = 0;
cannam@49 110 // Print the given message to standard error. A newline is printed after the message if it
cannam@49 111 // doesn't already have one.
cannam@49 112
cannam@49 113 virtual void error(StringPtr message) = 0;
cannam@49 114 // Like `warning()`, but also sets a flag indicating that the process has failed, and that when
cannam@49 115 // it eventually exits it should indicate an error status.
cannam@49 116
cannam@49 117 KJ_NORETURN(virtual void exitError(StringPtr message)) = 0;
cannam@49 118 // Equivalent to `error(message)` followed by `exit()`.
cannam@49 119
cannam@49 120 KJ_NORETURN(virtual void exitInfo(StringPtr message)) = 0;
cannam@49 121 // Displays the given non-error message to the user and then calls `exit()`. This is used to
cannam@49 122 // implement things like --help.
cannam@49 123
cannam@49 124 virtual void increaseLoggingVerbosity() = 0;
cannam@49 125 // Increase the level of detail produced by the debug logging system. `MainBuilder` invokes
cannam@49 126 // this if the caller uses the -v flag.
cannam@49 127
cannam@49 128 // TODO(someday): Add interfaces representing standard OS resources like the filesystem, so that
cannam@49 129 // these things can be mocked out.
cannam@49 130 };
cannam@49 131
cannam@49 132 class TopLevelProcessContext final: public ProcessContext {
cannam@49 133 // A ProcessContext implementation appropriate for use at the actual entry point of a process
cannam@49 134 // (as opposed to when you are trying to call a program's main function from within some other
cannam@49 135 // program). This implementation writes errors to stderr, and its `exit()` method actually
cannam@49 136 // calls the C `quick_exit()` function.
cannam@49 137
cannam@49 138 public:
cannam@49 139 explicit TopLevelProcessContext(StringPtr programName);
cannam@49 140
cannam@49 141 struct CleanShutdownException { int exitCode; };
cannam@49 142 // If the environment variable KJ_CLEAN_SHUTDOWN is set, then exit() will actually throw this
cannam@49 143 // exception rather than exiting. `kj::runMain()` catches this exception and returns normally.
cannam@49 144 // This is useful primarily for testing purposes, to assist tools like memory leak checkers that
cannam@49 145 // are easily confused by quick_exit().
cannam@49 146
cannam@49 147 StringPtr getProgramName() override;
cannam@49 148 KJ_NORETURN(void exit() override);
cannam@49 149 void warning(StringPtr message) override;
cannam@49 150 void error(StringPtr message) override;
cannam@49 151 KJ_NORETURN(void exitError(StringPtr message) override);
cannam@49 152 KJ_NORETURN(void exitInfo(StringPtr message) override);
cannam@49 153 void increaseLoggingVerbosity() override;
cannam@49 154
cannam@49 155 private:
cannam@49 156 StringPtr programName;
cannam@49 157 bool cleanShutdown;
cannam@49 158 bool hadErrors = false;
cannam@49 159 };
cannam@49 160
cannam@49 161 typedef Function<void(StringPtr programName, ArrayPtr<const StringPtr> params)> MainFunc;
cannam@49 162
cannam@49 163 int runMainAndExit(ProcessContext& context, MainFunc&& func, int argc, char* argv[]);
cannam@49 164 // Runs the given main function and then exits using the given context. If an exception is thrown,
cannam@49 165 // this will catch it, report it via the context and exit with an error code.
cannam@49 166 //
cannam@49 167 // Normally this function does not return, because returning would probably lead to wasting time
cannam@49 168 // on cleanup when the process is just going to exit anyway. However, to facilitate memory leak
cannam@49 169 // checkers and other tools that require a clean shutdown to do their job, if the environment
cannam@49 170 // variable KJ_CLEAN_SHUTDOWN is set, the function will in fact return an exit code, which should
cannam@49 171 // then be returned from main().
cannam@49 172 //
cannam@49 173 // Most users will use the KJ_MAIN() macro rather than call this function directly.
cannam@49 174
cannam@49 175 #define KJ_MAIN(MainClass) \
cannam@49 176 int main(int argc, char* argv[]) { \
cannam@49 177 ::kj::TopLevelProcessContext context(argv[0]); \
cannam@49 178 MainClass mainObject(context); \
cannam@49 179 return ::kj::runMainAndExit(context, mainObject.getMain(), argc, argv); \
cannam@49 180 }
cannam@49 181 // Convenience macro for declaring a main function based on the given class. The class must have
cannam@49 182 // a constructor that accepts a ProcessContext& and a method getMain() which returns
cannam@49 183 // kj::MainFunc (probably building it using a MainBuilder).
cannam@49 184
cannam@49 185 class MainBuilder {
cannam@49 186 // Builds a main() function with nice argument parsing. As options and arguments are parsed,
cannam@49 187 // corresponding callbacks are called, so that you never have to write a massive switch()
cannam@49 188 // statement to interpret arguments. Additionally, this approach encourages you to write
cannam@49 189 // main classes that have a reasonable API that can be used as an alternative to their
cannam@49 190 // command-line interface.
cannam@49 191 //
cannam@49 192 // All StringPtrs passed to MainBuilder must remain valid until option parsing completes. The
cannam@49 193 // assumption is that these strings will all be literals, making this an easy requirement. If
cannam@49 194 // not, consider allocating them in an Arena.
cannam@49 195 //
cannam@49 196 // Some flags are automatically recognized by the main functions built by this class:
cannam@49 197 // --help: Prints help text and exits. The help text is constructed based on the
cannam@49 198 // information you provide to the builder as you define each flag.
cannam@49 199 // --verbose: Increase logging verbosity.
cannam@49 200 // --version: Print version information and exit.
cannam@49 201 //
cannam@49 202 // Example usage:
cannam@49 203 //
cannam@49 204 // class FooMain {
cannam@49 205 // public:
cannam@49 206 // FooMain(kj::ProcessContext& context): context(context) {}
cannam@49 207 //
cannam@49 208 // bool setAll() { all = true; return true; }
cannam@49 209 // // Enable the --all flag.
cannam@49 210 //
cannam@49 211 // kj::MainBuilder::Validity setOutput(kj::StringPtr name) {
cannam@49 212 // // Set the output file.
cannam@49 213 //
cannam@49 214 // if (name.endsWith(".foo")) {
cannam@49 215 // outputFile = name;
cannam@49 216 // return true;
cannam@49 217 // } else {
cannam@49 218 // return "Output file must have extension .foo.";
cannam@49 219 // }
cannam@49 220 // }
cannam@49 221 //
cannam@49 222 // kj::MainBuilder::Validity processInput(kj::StringPtr name) {
cannam@49 223 // // Process an input file.
cannam@49 224 //
cannam@49 225 // if (!exists(name)) {
cannam@49 226 // return kj::str(name, ": file not found");
cannam@49 227 // }
cannam@49 228 // // ... process the input file ...
cannam@49 229 // return true;
cannam@49 230 // }
cannam@49 231 //
cannam@49 232 // kj::MainFunc getMain() {
cannam@49 233 // return MainBuilder(context, "Foo Builder v1.5", "Reads <source>s and builds a Foo.")
cannam@49 234 // .addOption({'a', "all"}, KJ_BIND_METHOD(*this, setAll),
cannam@49 235 // "Frob all the widgets. Otherwise, only some widgets are frobbed.")
cannam@49 236 // .addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setOutput),
cannam@49 237 // "<filename>", "Output to <filename>. Must be a .foo file.")
cannam@49 238 // .expectOneOrMoreArgs("<source>", KJ_BIND_METHOD(*this, processInput))
cannam@49 239 // .build();
cannam@49 240 // }
cannam@49 241 //
cannam@49 242 // private:
cannam@49 243 // bool all = false;
cannam@49 244 // kj::StringPtr outputFile;
cannam@49 245 // kj::ProcessContext& context;
cannam@49 246 // };
cannam@49 247
cannam@49 248 public:
cannam@49 249 MainBuilder(ProcessContext& context, StringPtr version,
cannam@49 250 StringPtr briefDescription, StringPtr extendedDescription = nullptr);
cannam@49 251 ~MainBuilder() noexcept(false);
cannam@49 252
cannam@49 253 class OptionName {
cannam@49 254 public:
cannam@49 255 OptionName() = default;
cannam@49 256 inline OptionName(char shortName): isLong(false), shortName(shortName) {}
cannam@49 257 inline OptionName(const char* longName): isLong(true), longName(longName) {}
cannam@49 258
cannam@49 259 private:
cannam@49 260 bool isLong;
cannam@49 261 union {
cannam@49 262 char shortName;
cannam@49 263 const char* longName;
cannam@49 264 };
cannam@49 265 friend class MainBuilder;
cannam@49 266 };
cannam@49 267
cannam@49 268 class Validity {
cannam@49 269 public:
cannam@49 270 inline Validity(bool valid) {
cannam@49 271 if (!valid) errorMessage = heapString("invalid argument");
cannam@49 272 }
cannam@49 273 inline Validity(const char* errorMessage)
cannam@49 274 : errorMessage(heapString(errorMessage)) {}
cannam@49 275 inline Validity(String&& errorMessage)
cannam@49 276 : errorMessage(kj::mv(errorMessage)) {}
cannam@49 277
cannam@49 278 inline const Maybe<String>& getError() const { return errorMessage; }
cannam@49 279 inline Maybe<String> releaseError() { return kj::mv(errorMessage); }
cannam@49 280
cannam@49 281 private:
cannam@49 282 Maybe<String> errorMessage;
cannam@49 283 friend class MainBuilder;
cannam@49 284 };
cannam@49 285
cannam@49 286 MainBuilder& addOption(std::initializer_list<OptionName> names, Function<Validity()> callback,
cannam@49 287 StringPtr helpText);
cannam@49 288 // Defines a new option (flag). `names` is a list of characters and strings that can be used to
cannam@49 289 // specify the option on the command line. Single-character names are used with "-" while string
cannam@49 290 // names are used with "--". `helpText` is a natural-language description of the flag.
cannam@49 291 //
cannam@49 292 // `callback` is called when the option is seen. Its return value indicates whether the option
cannam@49 293 // was accepted. If not, further option processing stops, and error is written, and the process
cannam@49 294 // exits.
cannam@49 295 //
cannam@49 296 // Example:
cannam@49 297 //
cannam@49 298 // builder.addOption({'a', "all"}, KJ_BIND_METHOD(*this, showAll), "Show all files.");
cannam@49 299 //
cannam@49 300 // This option could be specified in the following ways:
cannam@49 301 //
cannam@49 302 // -a
cannam@49 303 // --all
cannam@49 304 //
cannam@49 305 // Note that single-character option names can be combined into a single argument. For example,
cannam@49 306 // `-abcd` is equivalent to `-a -b -c -d`.
cannam@49 307 //
cannam@49 308 // The help text for this option would look like:
cannam@49 309 //
cannam@49 310 // -a, --all
cannam@49 311 // Show all files.
cannam@49 312 //
cannam@49 313 // Note that help text is automatically word-wrapped.
cannam@49 314
cannam@49 315 MainBuilder& addOptionWithArg(std::initializer_list<OptionName> names,
cannam@49 316 Function<Validity(StringPtr)> callback,
cannam@49 317 StringPtr argumentTitle, StringPtr helpText);
cannam@49 318 // Like `addOption()`, but adds an option which accepts an argument. `argumentTitle` is used in
cannam@49 319 // the help text. The argument text is passed to the callback.
cannam@49 320 //
cannam@49 321 // Example:
cannam@49 322 //
cannam@49 323 // builder.addOptionWithArg({'o', "output"}, KJ_BIND_METHOD(*this, setOutput),
cannam@49 324 // "<filename>", "Output to <filename>.");
cannam@49 325 //
cannam@49 326 // This option could be specified with an argument of "foo" in the following ways:
cannam@49 327 //
cannam@49 328 // -ofoo
cannam@49 329 // -o foo
cannam@49 330 // --output=foo
cannam@49 331 // --output foo
cannam@49 332 //
cannam@49 333 // Note that single-character option names can be combined, but only the last option can have an
cannam@49 334 // argument, since the characters after the option letter are interpreted as the argument. E.g.
cannam@49 335 // `-abofoo` would be equivalent to `-a -b -o foo`.
cannam@49 336 //
cannam@49 337 // The help text for this option would look like:
cannam@49 338 //
cannam@49 339 // -o FILENAME, --output=FILENAME
cannam@49 340 // Output to FILENAME.
cannam@49 341
cannam@49 342 MainBuilder& addSubCommand(StringPtr name, Function<MainFunc()> getSubParser,
cannam@49 343 StringPtr briefHelpText);
cannam@49 344 // If exactly the given name is seen as an argument, invoke getSubParser() and then pass all
cannam@49 345 // remaining arguments to the parser it returns. This is useful for implementing commands which
cannam@49 346 // have lots of sub-commands, like "git" (which has sub-commands "checkout", "branch", "pull",
cannam@49 347 // etc.).
cannam@49 348 //
cannam@49 349 // `getSubParser` is only called if the command is seen. This avoids building main functions
cannam@49 350 // for commands that aren't used.
cannam@49 351 //
cannam@49 352 // `briefHelpText` should be brief enough to show immediately after the command name on a single
cannam@49 353 // line. It will not be wrapped. Users can use the built-in "help" command to get extended
cannam@49 354 // help on a particular command.
cannam@49 355
cannam@49 356 MainBuilder& expectArg(StringPtr title, Function<Validity(StringPtr)> callback);
cannam@49 357 MainBuilder& expectOptionalArg(StringPtr title, Function<Validity(StringPtr)> callback);
cannam@49 358 MainBuilder& expectZeroOrMoreArgs(StringPtr title, Function<Validity(StringPtr)> callback);
cannam@49 359 MainBuilder& expectOneOrMoreArgs(StringPtr title, Function<Validity(StringPtr)> callback);
cannam@49 360 // Set callbacks to handle arguments. `expectArg()` and `expectOptionalArg()` specify positional
cannam@49 361 // arguments with special handling, while `expect{Zero,One}OrMoreArgs()` specifies a handler for
cannam@49 362 // an argument list (the handler is called once for each argument in the list). `title`
cannam@49 363 // specifies how the argument should be represented in the usage text.
cannam@49 364 //
cannam@49 365 // All options callbacks are called before argument callbacks, regardless of their ordering on
cannam@49 366 // the command line. This matches GNU getopt's behavior of permuting non-flag arguments to the
cannam@49 367 // end of the argument list. Also matching getopt, the special option "--" indicates that the
cannam@49 368 // rest of the command line is all arguments, not options, even if they start with '-'.
cannam@49 369 //
cannam@49 370 // The interpretation of positional arguments is fairly flexible. The non-optional arguments can
cannam@49 371 // be expected at the beginning, end, or in the middle. If more arguments are specified than
cannam@49 372 // the number of non-optional args, they are assigned to the optional argument handlers in the
cannam@49 373 // order of registration.
cannam@49 374 //
cannam@49 375 // For example, say you called:
cannam@49 376 // builder.expectArg("<foo>", ...);
cannam@49 377 // builder.expectOptionalArg("<bar>", ...);
cannam@49 378 // builder.expectArg("<baz>", ...);
cannam@49 379 // builder.expectZeroOrMoreArgs("<qux>", ...);
cannam@49 380 // builder.expectArg("<corge>", ...);
cannam@49 381 //
cannam@49 382 // This command requires at least three arguments: foo, baz, and corge. If four arguments are
cannam@49 383 // given, the second is assigned to bar. If five or more arguments are specified, then the
cannam@49 384 // arguments between the third and last are assigned to qux. Note that it never makes sense
cannam@49 385 // to call `expect*OrMoreArgs()` more than once since only the first call would ever be used.
cannam@49 386 //
cannam@49 387 // In practice, you probably shouldn't create such complicated commands as in the above example.
cannam@49 388 // But, this flexibility seems necessary to support commands where the first argument is special
cannam@49 389 // as well as commands (like `cp`) where the last argument is special.
cannam@49 390
cannam@49 391 MainBuilder& callAfterParsing(Function<Validity()> callback);
cannam@49 392 // Call the given function after all arguments have been parsed.
cannam@49 393
cannam@49 394 MainFunc build();
cannam@49 395 // Build the "main" function, which simply parses the arguments. Once this returns, the
cannam@49 396 // `MainBuilder` is no longer valid.
cannam@49 397
cannam@49 398 private:
cannam@49 399 struct Impl;
cannam@49 400 Own<Impl> impl;
cannam@49 401
cannam@49 402 class MainImpl;
cannam@49 403 };
cannam@49 404
cannam@49 405 } // namespace kj
cannam@49 406
cannam@49 407 #endif // KJ_MAIN_H_