2019-01-21 15:00:04 +01:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
// GNU GPL OS/K //
|
|
|
|
// //
|
|
|
|
// Desc: Command line parsing utilities //
|
2019-02-16 23:36:33 +01:00
|
|
|
// //
|
|
|
|
// //
|
|
|
|
// Copyright © 2018-2019 The OS/K Team //
|
|
|
|
// //
|
|
|
|
// This file is part of OS/K. //
|
|
|
|
// //
|
|
|
|
// OS/K is free software: you can redistribute it and/or modify //
|
|
|
|
// it under the terms of the GNU General Public License as published by //
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or //
|
|
|
|
// any later version. //
|
|
|
|
// //
|
|
|
|
// OS/K is distributed in the hope that it will be useful, //
|
|
|
|
// but WITHOUT ANY WARRANTY//without even the implied warranty of //
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
|
|
|
// GNU General Public License for more details. //
|
|
|
|
// //
|
|
|
|
// You should have received a copy of the GNU General Public License //
|
|
|
|
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
2019-01-21 15:00:04 +01:00
|
|
|
//----------------------------------------------------------------------------//
|
|
|
|
|
2019-05-13 23:22:27 +02:00
|
|
|
#ifndef _LIBC_H
|
|
|
|
#include <libc.h>
|
2019-01-21 15:00:04 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef _KALEXTRAS_ARGV_H
|
|
|
|
#define _KALEXTRAS_ARGV_H
|
|
|
|
|
2019-02-16 23:36:33 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef enum CmdOptionFlag_t CmdOptionFlag_t;
|
|
|
|
typedef enum CmdParserFlags_t CmdParserFlags_t;
|
|
|
|
typedef enum CmdParserReturn_t CmdParserReturn_t;
|
|
|
|
|
|
|
|
typedef struct CmdOption_t CmdOption_t;
|
|
|
|
typedef struct CmdDocStrings_t CmdDocStrings_t;
|
2019-03-08 09:00:55 +01:00
|
|
|
typedef struct CmdParserState_t CmdParserState_t;
|
2019-02-16 23:36:33 +01:00
|
|
|
|
2019-01-21 15:00:04 +01:00
|
|
|
//------------------------------------------//
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Maximal total size of argv, including the pointers,
|
|
|
|
// the pointed-to strings and their null-terminators
|
|
|
|
// This is a 32-bit integer
|
|
|
|
//
|
2019-03-08 09:00:55 +01:00
|
|
|
#define ARG_MAX (1 << 16) // 64 KB
|
2019-02-06 14:07:38 +01:00
|
|
|
|
2019-01-21 15:00:04 +01:00
|
|
|
//------------------------------------------//
|
|
|
|
|
|
|
|
//
|
2019-02-06 14:07:38 +01:00
|
|
|
// Flags for options
|
|
|
|
//
|
2019-02-16 23:36:33 +01:00
|
|
|
enum CmdOptionFlag_t
|
|
|
|
{
|
2019-02-06 14:07:38 +01:00
|
|
|
// The option parameter is optional
|
|
|
|
KALOPT_OPTIONAL = (1 << 0),
|
|
|
|
|
|
|
|
// Do not show option in any help message
|
|
|
|
KALOPT_HIDDEN = (1 << 1),
|
|
|
|
|
|
|
|
// This option is an alias for the previous one
|
|
|
|
KALOPT_ALIAS = (1 << 2),
|
|
|
|
|
|
|
|
// This isn't an option but a docstring
|
|
|
|
KALOPT_DOCSTR = (1 << 3),
|
|
|
|
|
|
|
|
// Only show in long help messages
|
|
|
|
KALOPT_LONGDOC = (1 << 4),
|
|
|
|
|
2019-02-16 23:36:33 +01:00
|
|
|
};
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
//
|
2019-02-16 23:36:33 +01:00
|
|
|
// Flags for KalParse(CmdLine|ArgVec)
|
2019-02-06 14:07:38 +01:00
|
|
|
//
|
2019-02-16 23:36:33 +01:00
|
|
|
enum CmdParserFlags_t
|
|
|
|
{
|
2019-03-24 14:44:59 +01:00
|
|
|
// Don't exit on errors
|
2019-02-06 14:07:38 +01:00
|
|
|
KALOPT_NO_EXIT = (1 << 0),
|
|
|
|
|
|
|
|
// Don't react to --help
|
|
|
|
KALOPT_NO_HELP = (1 << 1),
|
|
|
|
|
|
|
|
// Don't react to --version
|
|
|
|
KALOPT_NO_VERSION = (1 << 2),
|
|
|
|
|
|
|
|
// Alias -h for --help and -V for --version
|
|
|
|
KALOPT_ALIASES = (1 << 3),
|
|
|
|
|
|
|
|
// Don't print any error message
|
|
|
|
// Implies KALOPT_NO_EXIT
|
|
|
|
KALOPT_NO_ERRORS = (1 << 4) | KALOPT_NO_EXIT,
|
|
|
|
|
|
|
|
// Use KalGetProgName() instead of argv[0]
|
|
|
|
// as program name
|
2019-03-08 09:00:55 +01:00
|
|
|
KALOPT_DONT_USE_ARGV0 = (1 << 5),
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
// Call argument parser for non-options
|
|
|
|
// Non-options arguments will be indicated by
|
|
|
|
// a key of 0, the argument passed as a parameter
|
|
|
|
KALOPT_PARSE_ALL = (1 << 6),
|
|
|
|
|
|
|
|
// Call argument parser with options and non-options in the
|
|
|
|
// order they were found, instead of parsing options first
|
|
|
|
KALOPT_IN_ORDER = (1 << 7) | KALOPT_PARSE_ALL,
|
|
|
|
|
|
|
|
// Stay silent all along
|
|
|
|
KALOPT_SILENT = KALOPT_NO_EXIT | KALOPT_NO_ERRORS
|
|
|
|
| KALOPT_NO_HELP | KALOPT_NO_VERSION,
|
2019-02-16 23:36:33 +01:00
|
|
|
};
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Return values for the command parser
|
|
|
|
// These flags can be combined and are applied in order
|
|
|
|
//
|
|
|
|
// "Continue" and "Break" actions do not prevent
|
|
|
|
// later actions from applying
|
2019-01-21 15:00:04 +01:00
|
|
|
//
|
2019-02-16 23:36:33 +01:00
|
|
|
enum CmdParserReturn_t
|
|
|
|
{
|
2019-02-06 14:07:38 +01:00
|
|
|
// Continue parsing new options
|
|
|
|
KALOPT_CONTINUE = 0,
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Stop parsing further options
|
|
|
|
KALOPT_BREAK = (1 << 0),
|
|
|
|
|
|
|
|
// Show help/version message (by default, continue parsing)
|
|
|
|
KALOPT_SHOWHELP = (1 << 1),
|
|
|
|
KALOPT_SHOWVERS = (1 << 2),
|
2019-02-16 23:36:33 +01:00
|
|
|
};
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
//------------------------------------------//
|
2019-01-21 15:00:04 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// An option for a command, e.g. "-o file" in "cc -o file"
|
|
|
|
//
|
2019-02-16 23:36:33 +01:00
|
|
|
struct CmdOption_t
|
|
|
|
{
|
2019-01-21 15:00:04 +01:00
|
|
|
// The option's name, e.g. "help" for "--help"
|
|
|
|
// May be 0, but only if letter is not zero
|
|
|
|
const char *longName;
|
|
|
|
|
|
|
|
// The option's letter, e.g. 'h' for '-h'
|
|
|
|
int letter;
|
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Address of the variable to put the parameter into
|
|
|
|
const char *param;
|
|
|
|
|
|
|
|
// Option flags, see above
|
|
|
|
CmdOptionFlag_t flags;
|
|
|
|
|
|
|
|
// The option's help text
|
|
|
|
// If this is 0, this option is hidden
|
|
|
|
const char *helpText;
|
|
|
|
|
2019-01-21 15:00:04 +01:00
|
|
|
// The option's group, for sorting during --help
|
|
|
|
// Must be positive and < 256, or option won't shop up
|
|
|
|
// during help texts
|
|
|
|
int group;
|
2019-02-16 23:36:33 +01:00
|
|
|
};
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
//
|
|
|
|
// Program help/documentation strings; any can be 0
|
|
|
|
//
|
|
|
|
// Help messages are printed in this format:
|
|
|
|
// (letting "this" be a CmdDocStrings_t* variable)
|
|
|
|
//
|
|
|
|
// Usage: (this->usage)
|
|
|
|
// (this->header)
|
|
|
|
//
|
|
|
|
// (this->groups[0])
|
|
|
|
// -o, --option-name option description
|
|
|
|
// ...
|
|
|
|
// ...
|
|
|
|
//
|
|
|
|
// (this->bottom)
|
|
|
|
//
|
|
|
|
// XXX progname/version
|
|
|
|
//
|
2019-02-16 23:36:33 +01:00
|
|
|
struct CmdDocStrings_t
|
|
|
|
{
|
2019-02-06 14:07:38 +01:00
|
|
|
const char *usage;
|
|
|
|
const char *header;
|
|
|
|
const char *bottom;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Groups documentation
|
|
|
|
// groups[n] should be either 0 or contain the
|
|
|
|
// description of the option group n
|
|
|
|
const char **groups;
|
2019-02-16 23:36:33 +01:00
|
|
|
};
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// The state variable passed to the parser containing useful infos
|
|
|
|
//
|
2019-03-08 09:00:55 +01:00
|
|
|
struct CmdParserState_t {
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
// Option we're currently parsing
|
|
|
|
const CmdOption_t *option;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Index (in argv) of the option we're parsing
|
|
|
|
int argvIndex;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Flags passed to KalParse(CmdLine|ArgV)
|
|
|
|
CmdParserFlags_t flags;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Has help/version messages been displayed already?
|
|
|
|
bool shownHelp;
|
|
|
|
bool shownVersion;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-03-08 09:00:55 +01:00
|
|
|
// Output streams (may be NULL)
|
|
|
|
/*FILE*/ void *outStream;
|
|
|
|
/*FILE*/ void *errStream;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
// Private, internal data; do not touch
|
|
|
|
void *priv;
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-03-08 09:00:55 +01:00
|
|
|
};
|
2019-01-21 15:00:04 +01:00
|
|
|
|
|
|
|
//
|
2019-02-06 14:07:38 +01:00
|
|
|
// The argument parser function
|
2019-01-21 15:00:04 +01:00
|
|
|
//
|
2019-02-06 14:07:38 +01:00
|
|
|
typedef CmdParserReturn_t (*CmdParser_t)(int key,
|
|
|
|
const char *param,
|
|
|
|
CmdParserState_t *state);
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
//------------------------------------------//
|
2019-01-21 15:00:04 +01:00
|
|
|
|
2019-02-06 14:07:38 +01:00
|
|
|
//
|
|
|
|
// Misc. simple functions
|
|
|
|
//
|
|
|
|
int KalComputeArgCount(const char **argv);
|
|
|
|
size_t KalComputeArgVecSize(const char **argv);
|
|
|
|
|
|
|
|
//
|
2019-03-08 09:00:55 +01:00
|
|
|
// Command line to argument vector
|
2019-02-06 14:07:38 +01:00
|
|
|
//
|
|
|
|
error_t KalCmdLineToArgVecEx(const char *cmdLine,
|
|
|
|
int *argcPtr,
|
2019-05-18 19:40:24 +02:00
|
|
|
char *bufptr,
|
2019-02-06 14:07:38 +01:00
|
|
|
bool doEscaping);
|
|
|
|
|
|
|
|
//
|
|
|
|
// KalCmdLineToArgVecEx but doEscaping = false
|
|
|
|
//
|
|
|
|
error_t KalCmdLineToArgVec(const char *cmdLine,
|
|
|
|
int *argcPtr,
|
2019-05-18 19:40:24 +02:00
|
|
|
char *bufptr);
|
2019-02-06 14:07:38 +01:00
|
|
|
|
|
|
|
//
|
2019-03-08 09:00:55 +01:00
|
|
|
// Argument vector to command line
|
2019-02-06 14:07:38 +01:00
|
|
|
//
|
|
|
|
error_t KalArgVecToCmdLineEx(char *cmdLine,
|
|
|
|
size_t lengthMax,
|
|
|
|
int argc,
|
|
|
|
const char **argv,
|
|
|
|
bool doUnEscaping);
|
|
|
|
|
|
|
|
//
|
|
|
|
// KalArgVecToCmdLineEx but doUnEscapign = false
|
|
|
|
//
|
|
|
|
error_t KalArgVecToCmdLine(char *cmdLine,
|
|
|
|
size_t lengthMax,
|
|
|
|
int argc,
|
|
|
|
const char **argv);
|
|
|
|
//
|
|
|
|
// Command line parser; only takes an argument vector
|
|
|
|
// The argv argument *will* be modified and all parsed
|
|
|
|
// options and arguments will be removed, except argv[0]
|
|
|
|
// which is guanranteed to be left
|
|
|
|
//
|
|
|
|
error_t KalParseArgVecEx(int argc,
|
|
|
|
char **argv,
|
|
|
|
const CmdOption_t *options,
|
|
|
|
const CmdDocStrings_t *docStrings,
|
|
|
|
CmdParserFlags_t *flags,
|
|
|
|
CmdParser_t *parser,
|
2019-03-08 09:00:55 +01:00
|
|
|
/*FILE*/ void *outStream,
|
|
|
|
/*FILE*/ void *errStream);
|
2019-02-06 14:07:38 +01:00
|
|
|
//
|
|
|
|
// KalParseArgVecEx(argc, argv, options, docString, stdin, stdout, parser, NULL)
|
|
|
|
//
|
|
|
|
error_t KalParseArgVec(int argc,
|
|
|
|
char **argv,
|
|
|
|
const CmdOption_t *options,
|
|
|
|
const CmdDocStrings_t *docStrings,
|
|
|
|
CmdParserFlags_t *flags,
|
|
|
|
CmdParser_t *parser);
|
|
|
|
|
2019-01-21 15:00:04 +01:00
|
|
|
//------------------------------------------//
|
|
|
|
|
2019-02-16 23:36:33 +01:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-01-21 15:00:04 +01:00
|
|
|
#endif
|