/** dropt.h * * A deliberately rudimentary command-line option parser. * * Version 2.0.0 * * Copyright (C) 2006-2018 James D. Lin * * The latest version of this file can be downloaded from: * * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * * 3. This notice may not be removed or altered from any source distribution. */ #ifndef DROPT_H #define DROPT_H #include #include #if __STDC_VERSION__ >= 199901L #include typedef uintptr_t dropt_uintptr; #else typedef size_t dropt_uintptr; #endif #ifdef __cplusplus extern "C" { #endif #ifndef DROPT_USE_WCHAR #if defined _UNICODE && (defined _MSC_VER || defined DROPT_NO_STRING_BUFFERS) #define DROPT_USE_WCHAR 1 #endif #endif #ifdef DROPT_USE_WCHAR /* This may be used for both char and string literals. */ #define DROPT_TEXT_LITERAL(s) L ## s typedef wchar_t dropt_char; #else #define DROPT_TEXT_LITERAL(s) s typedef char dropt_char; #endif enum { /* Errors in the range [0x00, 0x7F] are reserved for dropt. */ dropt_error_none, dropt_error_unknown, dropt_error_bad_configuration, dropt_error_insufficient_memory, dropt_error_invalid_option, dropt_error_insufficient_arguments, dropt_error_mismatch, dropt_error_overflow, dropt_error_underflow, /* Errors in the range [0x80, 0xFFFF] are free for clients to use. */ dropt_error_custom_start = 0x80, dropt_error_custom_last = 0xFFFF }; typedef unsigned int dropt_error; typedef unsigned char dropt_bool; /* Opaque. */ typedef struct dropt_context dropt_context; /* Forward declarations. */ typedef struct dropt_option dropt_option; /** `dropt_option_handler_func` callbacks are responsible for parsing * individual options and storing the parsed value. * * `dropt_option_handler_decl` may be used for declaring the callback * functions (see the stock option handlers below for examples). * `dropt_option_handler_func` is the actual function pointer type. * * `option` points to the `dropt_option` entry that matched the option * supplied by the user. This will never be `NULL` when dropt invokes the * handler. * * `optionArgument` will be `NULL` if no argument is specified for an option. * It will be the empty string if the user explicitly passed an empty string * as the argument (e.g. `--option=""`). * * An option that doesn't expect an argument still can receive a non-null * value for `optionArgument` if the user explicitly specified one (e.g. * `--option=arg`). * * If the option's argument is optional, the handler might be called twice: * once with a candidate argument, and if that argument is rejected by the * handler, again with no argument. Handlers should be aware of this if they * have side-effects. * * `dest` is the client-specified pointer to a variable for the handler to * modify. */ typedef dropt_error dropt_option_handler_decl(dropt_context* context, const dropt_option* option, const dropt_char* optionArgument, void* dest); typedef dropt_option_handler_decl* dropt_option_handler_func; /** `dropt_error_handler_func` callbacks are responsible for generating error * messages. The returned string must be allocated on the heap and must be * freeable with `free()`. */ typedef dropt_char* (*dropt_error_handler_func)(dropt_error error, const dropt_char* optionName, const dropt_char* optionArgument, void* handlerData); /** `dropt_strncmp_func` callbacks allow callers to provide their own (possibly * case-insensitive) string comparison function. */ typedef int (*dropt_strncmp_func)(const dropt_char* s, const dropt_char* t, size_t n); /** Properties defining each option: * * short_name: * The option's short name (e.g. the 'h' in `-h`). * Use '\0' if the option has no short name. * * long_name: * The option's long name (e.g. "help" in `--help`). * Use `NULL` if the option has no long name. * * description: * The description shown when generating help. * May be `NULL` for undocumented options. * * arg_description: * The description for the option's argument (e.g. `--option=argument` or * `--option argument`), printed when generating help. * Use `NULL` if the option does not take an argument. * * handler: * The handler callback and data invoked in response to encountering the * option. * * dest: * The address of a variable for the handler to modify, if necessary. * * attr: * Miscellaneous attributes. See below. * * extra_data: * Additional callback data for the handler. */ struct dropt_option { dropt_char short_name; const dropt_char* long_name; const dropt_char* description; const dropt_char* arg_description; dropt_option_handler_func handler; void* dest; unsigned int attr; dropt_uintptr extra_data; }; /** Bitwise flags for option attributes: * * dropt_attr_halt: * Stop processing when this option is encountered. * * dropt_attr_hidden: * Don't list the option when generating help. Use this for undocumented * options. * * dropt_attr_optional_val: * The option's argument is optional. If an option has this attribute, * the handler callback may be invoked twice (once with a potential * argument, and if that fails, again with a `NULL` argument). */ enum { dropt_attr_halt = (1 << 0), dropt_attr_hidden = (1 << 1), dropt_attr_optional_val = (1 << 2) }; typedef struct dropt_help_params { unsigned int indent; unsigned int description_start_column; dropt_bool blank_lines_between_options; } dropt_help_params; dropt_context* dropt_new_context(const dropt_option* options); void dropt_free_context(dropt_context* context); const dropt_option* dropt_get_options(const dropt_context* context); void dropt_set_error_handler(dropt_context* context, dropt_error_handler_func handler, void* handlerData); void dropt_set_strncmp(dropt_context* context, dropt_strncmp_func cmp); /* Use this only for backward compatibility purposes. */ void dropt_allow_concatenated_arguments(dropt_context* context, dropt_bool allow); dropt_char** dropt_parse(dropt_context* context, int argc, dropt_char** argv); dropt_error dropt_get_error(const dropt_context* context); void dropt_get_error_details(const dropt_context* context, dropt_char** optionName, dropt_char** optionArgument); const dropt_char* dropt_get_error_message(dropt_context* context); void dropt_clear_error(dropt_context* context); #ifndef DROPT_NO_STRING_BUFFERS dropt_char* dropt_default_error_handler(dropt_error error, const dropt_char* optionName, const dropt_char* optionArgument); void dropt_init_help_params(dropt_help_params* helpParams); dropt_char* dropt_get_help(const dropt_context* context, const dropt_help_params* helpParams); void dropt_print_help(FILE* f, const dropt_context* context, const dropt_help_params* helpParams); #endif /* Stock option handlers for common types. */ dropt_option_handler_decl dropt_handle_bool; dropt_option_handler_decl dropt_handle_verbose_bool; dropt_option_handler_decl dropt_handle_int; dropt_option_handler_decl dropt_handle_uint; dropt_option_handler_decl dropt_handle_double; dropt_option_handler_decl dropt_handle_string; dropt_option_handler_decl dropt_handle_const; #define DROPT_MISUSE(message) dropt_misuse(message, __FILE__, __LINE__) void dropt_misuse(const char* message, const char* filename, int line); #ifdef __cplusplus } /* extern "C" */ #endif #endif /* DROPT_H */