wraith-lang/lib/dropt/dropt.h

273 lines
8.8 KiB
C
Raw Permalink Normal View History

2021-04-28 22:21:51 +00:00
/** dropt.h
*
* A deliberately rudimentary command-line option parser.
*
* Version 2.0.0
*
* Copyright (C) 2006-2018 James D. Lin <jamesdlin@berkeley.edu>
*
* The latest version of this file can be downloaded from:
* <http://www.taenarum.com/software/dropt/>
*
* 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 <stdio.h>
#include <wchar.h>
#if __STDC_VERSION__ >= 199901L
#include <stdint.h>
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 */