273 lines
8.8 KiB
C
273 lines
8.8 KiB
C
|
/** 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 */
|