commit 31ee3b7c839842a6969085a8c52d9a83f225457b
parent 08b98eba297b9146c8a8aecacb5a50833df2d4bf
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Fri, 14 Jun 2024 19:23:08 +0200
Rebrand to poafloc
Diffstat:
16 files changed, 572 insertions(+), 573 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.25.2)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project(
- args
- VERSION 0.0.9
- DESCRIPTION "Command Line Argument Parser"
+ poafloc
+ VERSION 1.0.0
+ DESCRIPTION "Parser Of Arguments For Lines Of Commands"
LANGUAGES CXX C
)
@@ -49,9 +49,9 @@ add_subdirectory(demo)
install(
TARGETS
- args
+ poafloc
EXPORT
- argsTargets
+ poaflocTargets
ARCHIVE
DESTINATION ${INSTALL_LIBDIR}
COMPONENT lib
@@ -62,15 +62,15 @@ install(
DESTINATION ${INSTALL_LIBDIR}
COMPONENT lib
PUBLIC_HEADER
- DESTINATION ${INSTALL_INCLUDEDIR}/args
+ DESTINATION ${INSTALL_INCLUDEDIR}/poafloc
COMPONENT dev
)
install(
EXPORT
- argsTargets
+ poaflocTargets
NAMESPACE
- "args::"
+ "poafloc::"
DESTINATION
${INSTALL_CMAKEDIR}
COMPONENT
@@ -80,21 +80,21 @@ install(
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
- ${CMAKE_CURRENT_BINARY_DIR}/argsConfigVersion.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/poaflocConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)
configure_package_config_file(
- ${PROJECT_SOURCE_DIR}/argsConfig.cmake.in
- ${CMAKE_CURRENT_BINARY_DIR}/argsConfig.cmake
+ ${PROJECT_SOURCE_DIR}/poaflocConfig.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/poaflocConfig.cmake
INSTALL_DESTINATION ${INSTALL_CMAKEDIR}
)
install(
FILES
- ${CMAKE_CURRENT_BINARY_DIR}/argsConfig.cmake
- ${CMAKE_CURRENT_BINARY_DIR}/argsConfigVersion.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/poaflocConfig.cmake
+ ${CMAKE_CURRENT_BINARY_DIR}/poaflocConfigVersion.cmake
DESTINATION
${INSTALL_CMAKEDIR}
)
diff --git a/argsConfig.cmake.in b/argsConfig.cmake.in
@@ -1,6 +0,0 @@
-@PACKAGE_INIT@
-include("${CMAKE_CURRENT_LIST_DIR}/argsTargets.cmake")
-
-check_required_components(
- "args"
-)
diff --git a/demo/CMakeLists.txt b/demo/CMakeLists.txt
@@ -1,5 +1,5 @@
add_executable(demo main.cpp)
-target_link_libraries(demo PRIVATE args)
+target_link_libraries(demo PRIVATE poafloc)
target_include_directories(demo PRIVATE ../include)
set_target_properties(demo PROPERTIES LANGUAGE CXX)
set_target_properties(demo PROPERTIES
@@ -8,7 +8,7 @@ set_target_properties(demo PROPERTIES
)
add_executable(cdemo main.c)
-target_link_libraries(cdemo PRIVATE args)
+target_link_libraries(cdemo PRIVATE poafloc)
target_include_directories(cdemo PRIVATE ../include)
set_target_properties(cdemo PROPERTIES LANGUAGE C)
set_target_properties(cdemo PROPERTIES
diff --git a/demo/main.c b/demo/main.c
@@ -1,4 +1,4 @@
-#include "args.h"
+#include "poafloc.h"
#include <stdio.h>
@@ -13,8 +13,8 @@ typedef struct {
int relocatable;
} arguments_t;
-int parse_opt(int key, const char *arg, args_parser_t *parser) {
- arguments_t *arguments = (arguments_t *)args_parser_input(parser);
+int parse_opt(int key, const char *arg, poafloc_parser_t *parser) {
+ arguments_t *arguments = (arguments_t *)poafloc_parser_input(parser);
switch (key) {
case 777: arguments->debug = 1; break;
@@ -29,8 +29,8 @@ int parse_opt(int key, const char *arg, args_parser_t *parser) {
case 'o': arguments->output_file = arg ? arg : "stdout"; break;
case 'i': arguments->input_file = arg; break;
// case Parser::Key::ARG: arguments->args.push_back(arg); break;
- case ARGS_KEY_ERROR: fprintf(stderr, "handled error\n");
- case ARGS_KEY_INIT:
+ case POAFLOC_KEY_ERROR: fprintf(stderr, "handled error\n");
+ case POAFLOC_KEY_INIT:
arguments->input_file = "stdin";
arguments->output_file = "stdout";
}
@@ -39,22 +39,22 @@ int parse_opt(int key, const char *arg, args_parser_t *parser) {
}
// clang-format off
-static const args_option_t options[] = {
+static const poafloc_option_t options[] = {
{ 0, 'R', 0, 0, "random 0-group option"},
{ 0, 0, 0, 0, "Program mode", 1},
{"relocatable", 'r', 0, 0, "Output in relocatable format"},
{ "hex", 'h', 0, 0, "Output in hex format"},
- {"hexadecimal", 0, 0, ARGS_OPTION_ALIAS | ARGS_OPTION_HIDDEN},
+ {"hexadecimal", 0, 0, POAFLOC_OPTION_ALIAS | POAFLOC_OPTION_HIDDEN},
{ 0, 0, 0, 0, "For developers", 4},
{ "debug", 777, 0, 0, "Enable debugging mode"},
{ 0, 0, 0, 0, "Input/output", 3},
- { "output", 'o', "file", ARGS_OPTION_ARG_OPTIONAL, "Output file, default stdout"},
+ { "output", 'o', "file", POAFLOC_OPTION_ARG_OPTIONAL, "Output file, default stdout"},
{ 0, 'i', "file", 0, "Input file"},
{ 0, 0, 0, 0, "Informational Options", -1},
{0},
};
-static const args_argp_t argp = {
+static const poafloc_arg_t argp = {
options, parse_opt, "doc string\nother usage",
"First half of the message\vsecond half of the message"
};
@@ -63,7 +63,7 @@ static const args_argp_t argp = {
int main(int argc, char *argv[]) {
arguments_t arguments = {0};
- if (args_parse(&argp, argc, argv, 0, &arguments)) {
+ if (poafloc_parse(&argp, argc, argv, 0, &arguments)) {
error("There was an error while parsing arguments");
return 1;
}
diff --git a/demo/main.cpp b/demo/main.cpp
@@ -1,10 +1,10 @@
-#include "args.hpp"
+#include "poafloc.hpp"
#include <cstdint>
#include <iostream>
#include <vector>
-using namespace args;
+using namespace poafloc;
void error(const std::string &message) { std::cerr << message << std::endl; }
struct arguments_t {
@@ -56,7 +56,7 @@ static const option_t options[] = {
{0},
};
-static const argp_t argp = {
+static const arg_t argp = {
options, parse_opt, "doc string\nother usage",
"First half of the message\vsecond half of the message"
};
diff --git a/include/args.h b/include/args.h
@@ -1,122 +0,0 @@
-#ifndef ARGS_H
-#define ARGS_H
-
-#ifdef __cplusplus
-
-#include <cstdio>
-
-#define MANGLE_ENUM(enumn, name) name
-#define ENUM_OPTION Option
-#define ENUM_KEY Key
-#define ENUM_HELP Help
-#define ENUM_PARSE Parse
-
-extern "C" {
-namespace args {
-
-struct Parser;
-typedef Parser args_parser_t;
-
-#else
-
-#include <stdio.h>
-
-#define MANGLE_ENUM(enumn, name) ARGS_##enumn##_##name
-#define ENUM_OPTION args_option_e
-#define ENUM_KEY args_key_e
-#define ENUM_HELP args_help_e
-#define ENUM_PARSE args_parse_e
-
-struct __Parser;
-typedef struct __Parser args_parser_t;
-
-#endif
-
-typedef struct {
- char const *name;
- int key;
- char const *arg;
- int flags;
- char const *message;
- int group;
-} args_option_t;
-
-typedef int (*args_parse_f)(int key, const char *arg, args_parser_t *parser);
-
-typedef struct {
- args_option_t const *options;
- args_parse_f parse;
- char const *doc;
- char const *message;
-} args_argp_t;
-
-enum ENUM_OPTION {
- MANGLE_ENUM(OPTION, ARG_OPTIONAL) = 0x1,
- MANGLE_ENUM(OPTION, HIDDEN) = 0x2,
- MANGLE_ENUM(OPTION, ALIAS) = 0x4,
-};
-
-enum ENUM_KEY {
- MANGLE_ENUM(KEY, ARG) = 0,
- MANGLE_ENUM(KEY, END) = 0x1000001,
- MANGLE_ENUM(KEY, NO_ARGS) = 0x1000002,
- MANGLE_ENUM(KEY, INIT) = 0x1000003,
- MANGLE_ENUM(KEY, SUCCESS) = 0x1000004,
- MANGLE_ENUM(KEY, ERROR) = 0x1000005,
-};
-
-enum ENUM_HELP {
-
- MANGLE_ENUM(HELP, SHORT_USAGE) = 0x1,
- MANGLE_ENUM(HELP, USAGE) = 0x2,
- MANGLE_ENUM(HELP, SEE) = 0x4,
- MANGLE_ENUM(HELP, LONG) = 0x8,
-
- MANGLE_ENUM(HELP, EXIT_ERR) = 0x10,
- MANGLE_ENUM(HELP, EXIT_OK) = 0x20,
-
- MANGLE_ENUM(HELP, STD_ERR) = MANGLE_ENUM(HELP, SEE) |
- MANGLE_ENUM(HELP, EXIT_ERR),
-
- MANGLE_ENUM(HELP, STD_HELP) = MANGLE_ENUM(HELP, LONG) |
- MANGLE_ENUM(HELP, EXIT_OK),
-
- MANGLE_ENUM(HELP, STD_USAGE) = MANGLE_ENUM(HELP, USAGE) |
- MANGLE_ENUM(HELP, EXIT_ERR),
-};
-
-enum ENUM_PARSE {
- MANGLE_ENUM(PARSE, NO_ERRS) = 0x1,
- // MANGLE_ENUM(PARSE, NO_ARGS),
- MANGLE_ENUM(PARSE, NO_HELP) = 0x2,
- MANGLE_ENUM(PARSE, NO_EXIT) = 0x4,
- MANGLE_ENUM(PARSE, SILENT) = 0x8,
- MANGLE_ENUM(PARSE, IN_ORDER) = 0x10,
-};
-
-#if !defined __cplusplus || defined WITH_C_BINDINGS
-
-void *args_parser_input(args_parser_t *parser);
-
-void args_usage(args_parser_t *parser);
-
-void args_help(const args_parser_t *state, FILE *stream, unsigned flags);
-
-int args_parse(const args_argp_t *argp, int argc, char *argv[], unsigned flags,
- void *input);
-
-void args_failure(const args_parser_t *parser, int status, int errnum,
- const char *fmt, ...);
-
-#endif
-
-#undef MANGLE_ENUM
-#undef ENUM_OPTION
-#undef ENUM_KEY
-
-#ifdef __cplusplus
-} // namespace args
-} // extern "C"
-#endif
-
-#endif
diff --git a/include/args.hpp b/include/args.hpp
@@ -1,111 +0,0 @@
-#ifndef ARGS_HPP
-#define ARGS_HPP
-
-#include "args.h"
-
-#include <cstdarg>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-namespace args {
-
-using option_t = args_option_t;
-using argp_t = args_argp_t;
-
-int parse(const argp_t *argp, int argc, char *argv[], unsigned flags,
- void *input) noexcept;
-
-void usage(const Parser *parser);
-void help(const Parser *parser, FILE *stream, unsigned flags);
-
-void failure(const Parser *parser, int status, int errnum, const char *fmt,
- va_list args);
-
-void failure(const Parser *parser, int status, int errnum, const char *fmt,
- ...);
-
-class Parser {
- public:
- void *input() const { return m_input; }
- const char *name() const { return m_name; }
- unsigned flags() const { return m_flags; }
-
- private:
- friend int parse(const argp_t *, int, char **, unsigned, void *) noexcept;
- friend void help(const Parser *parser, FILE *stream, unsigned flags);
-
- Parser(const argp_t *argp, unsigned flags, void *input);
- Parser(const Parser &) = delete;
- Parser(Parser &&) = delete;
- Parser &operator=(const Parser &) = delete;
- Parser &operator=(Parser &&) = delete;
- ~Parser() noexcept = default;
-
- int parse(int argc, char *argv[]);
-
- int handle_unknown(bool shrt, const char *argv);
- int handle_missing(bool shrt, const char *argv);
- int handle_excess(const char *argv);
-
- void print_other_usages(FILE *stream) const;
- void help(FILE *stream) const;
- void usage(FILE *stream) const;
- void see(FILE *stream) const;
-
- static const char *basename(const char *name);
-
- struct help_entry_t {
- help_entry_t(const char *arg, const char *message, int group,
- bool opt = false)
- : arg(arg), message(message), group(group), opt(opt) {}
-
- void push(char sh) { opt_short.push_back(sh); }
- void push(const char *lg) { opt_long.push_back(lg); }
-
- bool operator<(const help_entry_t &rhs) const;
-
- const char *arg;
- const char *message;
- int group;
- bool opt;
-
- std::vector<const char *> opt_long;
- std::vector<char> opt_short;
- };
-
- class trie_t {
- public:
- trie_t() = default;
- trie_t(const trie_t &) = delete;
- trie_t(trie_t &&) = delete;
- trie_t &operator=(const trie_t &) = delete;
- trie_t &operator=(trie_t &&) = delete;
- ~trie_t() noexcept;
-
- bool insert(const char *option, int key);
- int get(const char *option) const;
-
- private:
- static bool is_valid(const char *option);
-
- trie_t *children[26] = {0};
- int count = 0;
- int key = 0;
- bool terminal = false;
- };
-
- const argp_t *argp;
- unsigned m_flags;
- void *m_input;
-
- const char *m_name;
-
- std::unordered_map<int, const option_t *> options;
- std::vector<help_entry_t> help_entries;
- trie_t trie;
-};
-
-} // namespace args
-
-#endif
diff --git a/include/poafloc.h b/include/poafloc.h
@@ -0,0 +1,121 @@
+#ifndef POAFLOC_POAFLOC_H
+#define POAFLOC_POAFLOC_H
+
+#ifdef __cplusplus
+
+#include <cstdio>
+
+#define MANGLE_ENUM(enumn, name) name
+#define ENUM_OPTION Option
+#define ENUM_KEY Key
+#define ENUM_HELP Help
+#define ENUM_PARSE Parse
+
+extern "C" {
+namespace poafloc {
+
+struct Parser;
+typedef Parser poafloc_parser_t;
+
+#else
+
+#include <stdio.h>
+
+#define MANGLE_ENUM(enumn, name) POAFLOC_##enumn##_##name
+#define ENUM_OPTION poafloc_option_e
+#define ENUM_KEY poafloc_key_e
+#define ENUM_HELP poafloc_help_e
+#define ENUM_PARSE poafloc_parse_e
+
+struct __Parser;
+typedef struct __Parser poafloc_parser_t;
+
+#endif
+
+typedef struct {
+ char const *name;
+ int key;
+ char const *arg;
+ int flags;
+ char const *message;
+ int group;
+} poafloc_option_t;
+
+typedef int (*poafloc_parse_f)(int key, const char *arg, poafloc_parser_t *parser);
+
+typedef struct {
+ poafloc_option_t const *options;
+ poafloc_parse_f parse;
+ char const *doc;
+ char const *message;
+} poafloc_arg_t;
+
+enum ENUM_OPTION {
+ MANGLE_ENUM(OPTION, ARG_OPTIONAL) = 0x1,
+ MANGLE_ENUM(OPTION, HIDDEN) = 0x2,
+ MANGLE_ENUM(OPTION, ALIAS) = 0x4,
+};
+
+enum ENUM_KEY {
+ MANGLE_ENUM(KEY, ARG) = 0,
+ MANGLE_ENUM(KEY, END) = 0x1000001,
+ MANGLE_ENUM(KEY, NO_ARGS) = 0x1000002,
+ MANGLE_ENUM(KEY, INIT) = 0x1000003,
+ MANGLE_ENUM(KEY, SUCCESS) = 0x1000004,
+ MANGLE_ENUM(KEY, ERROR) = 0x1000005,
+};
+
+enum ENUM_HELP {
+
+ MANGLE_ENUM(HELP, SHORT_USAGE) = 0x1,
+ MANGLE_ENUM(HELP, USAGE) = 0x2,
+ MANGLE_ENUM(HELP, SEE) = 0x4,
+ MANGLE_ENUM(HELP, LONG) = 0x8,
+
+ MANGLE_ENUM(HELP, EXIT_ERR) = 0x10,
+ MANGLE_ENUM(HELP, EXIT_OK) = 0x20,
+
+ MANGLE_ENUM(HELP, STD_ERR) = MANGLE_ENUM(HELP, SEE) |
+ MANGLE_ENUM(HELP, EXIT_ERR),
+
+ MANGLE_ENUM(HELP, STD_HELP) = MANGLE_ENUM(HELP, LONG) |
+ MANGLE_ENUM(HELP, EXIT_OK),
+
+ MANGLE_ENUM(HELP, STD_USAGE) = MANGLE_ENUM(HELP, USAGE) |
+ MANGLE_ENUM(HELP, EXIT_ERR),
+};
+
+enum ENUM_PARSE {
+ MANGLE_ENUM(PARSE, NO_ERRS) = 0x1,
+ MANGLE_ENUM(PARSE, NO_HELP) = 0x2,
+ MANGLE_ENUM(PARSE, NO_EXIT) = 0x4,
+ MANGLE_ENUM(PARSE, SILENT) = 0x8,
+ MANGLE_ENUM(PARSE, IN_ORDER) = 0x10,
+};
+
+#if !defined __cplusplus || defined WITH_C_BINDINGS
+
+void *poafloc_parser_input(poafloc_parser_t *parser);
+
+void poafloc_usage(poafloc_parser_t *parser);
+
+void poafloc_help(const poafloc_parser_t *state, FILE *stream, unsigned flags);
+
+int poafloc_parse(const poafloc_arg_t *argp, int argc, char *argv[], unsigned flags,
+ void *input);
+
+void poafloc_failure(const poafloc_parser_t *parser, int status, int errnum,
+ const char *fmt, ...);
+
+#endif
+
+#undef MANGLE_ENUM
+#undef ENUM_OPTION
+#undef ENUM_KEY
+
+#ifdef __cplusplus
+} // namespace poafloc
+} // extern "C"
+#endif
+
+#endif
diff --git a/include/poafloc.hpp b/include/poafloc.hpp
@@ -0,0 +1,111 @@
+#ifndef POAFLOC_POAFLOC_HPP
+#define POAFLOC_POAFLOC_HPP
+
+#include "poafloc.h"
+
+#include <cstdarg>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace poafloc {
+
+using option_t = poafloc_option_t;
+using arg_t = poafloc_arg_t;
+
+int parse(const arg_t *argp, int argc, char *argv[], unsigned flags,
+ void *input) noexcept;
+
+void usage(const Parser *parser);
+void help(const Parser *parser, FILE *stream, unsigned flags);
+
+void failure(const Parser *parser, int status, int errnum, const char *fmt,
+ va_list args);
+
+void failure(const Parser *parser, int status, int errnum, const char *fmt,
+ ...);
+
+class Parser {
+ public:
+ void *input() const { return m_input; }
+ const char *name() const { return m_name; }
+ unsigned flags() const { return m_flags; }
+
+ private:
+ friend int parse(const arg_t *, int, char **, unsigned, void *) noexcept;
+ friend void help(const Parser *parser, FILE *stream, unsigned flags);
+
+ Parser(const arg_t *argp, unsigned flags, void *input);
+ Parser(const Parser &) = delete;
+ Parser(Parser &&) = delete;
+ Parser &operator=(const Parser &) = delete;
+ Parser &operator=(Parser &&) = delete;
+ ~Parser() noexcept = default;
+
+ int parse(int argc, char *argv[]);
+
+ int handle_unknown(bool shrt, const char *argv);
+ int handle_missing(bool shrt, const char *argv);
+ int handle_excess(const char *argv);
+
+ void print_other_usages(FILE *stream) const;
+ void help(FILE *stream) const;
+ void usage(FILE *stream) const;
+ void see(FILE *stream) const;
+
+ static const char *basename(const char *name);
+
+ struct help_entry_t {
+ help_entry_t(const char *arg, const char *message, int group,
+ bool opt = false)
+ : arg(arg), message(message), group(group), opt(opt) {}
+
+ void push(char sh) { opt_short.push_back(sh); }
+ void push(const char *lg) { opt_long.push_back(lg); }
+
+ bool operator<(const help_entry_t &rhs) const;
+
+ const char *arg;
+ const char *message;
+ int group;
+ bool opt;
+
+ std::vector<const char *> opt_long;
+ std::vector<char> opt_short;
+ };
+
+ class trie_t {
+ public:
+ trie_t() = default;
+ trie_t(const trie_t &) = delete;
+ trie_t(trie_t &&) = delete;
+ trie_t &operator=(const trie_t &) = delete;
+ trie_t &operator=(trie_t &&) = delete;
+ ~trie_t() noexcept;
+
+ bool insert(const char *option, int key);
+ int get(const char *option) const;
+
+ private:
+ static bool is_valid(const char *option);
+
+ trie_t *children[26] = {0};
+ int count = 0;
+ int key = 0;
+ bool terminal = false;
+ };
+
+ const arg_t *argp;
+ unsigned m_flags;
+ void *m_input;
+
+ const char *m_name;
+
+ std::unordered_map<int, const option_t *> options;
+ std::vector<help_entry_t> help_entries;
+ trie_t trie;
+};
+
+} // namespace poafloc
+
+#endif
diff --git a/poaflocConfig.cmake.in b/poaflocConfig.cmake.in
@@ -0,0 +1,6 @@
+@PACKAGE_INIT@
+include("${CMAKE_CURRENT_LIST_DIR}/poaflocTargets.cmake")
+
+check_required_components(
+ "poafloc"
+)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
@@ -1,14 +1,14 @@
-add_library(args STATIC args.cpp help.cpp trie.cpp c_bindings.cpp)
-target_include_directories(args PRIVATE ../include)
-target_compile_definitions(args PRIVATE WITH_C_BINDINGS)
-set_target_properties(args PROPERTIES LINKER_LANGUAGE CXX)
+add_library(poafloc STATIC poafloc.cpp help.cpp trie.cpp c_bindings.cpp)
+target_include_directories(poafloc PRIVATE ../include)
+target_compile_definitions(poafloc PRIVATE WITH_C_BINDINGS)
+set_target_properties(poafloc PROPERTIES LINKER_LANGUAGE CXX)
-set_target_properties(args PROPERTIES
+set_target_properties(poafloc PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
- OUTPUT_NAME "args"
+ OUTPUT_NAME "poafloc"
DEBUG_POSTFIX "d"
- PUBLIC_HEADER "include/args.hpp;include/args.h"
+ PUBLIC_HEADER "include/poafloc.hpp;include/poafloc.h"
MACOSX_RPATH ON
WINDOWS_EXPORT_ALL_SYMBOLS ON
)
diff --git a/src/args.cpp b/src/args.cpp
@@ -1,287 +0,0 @@
-#include "args.hpp"
-
-#include <algorithm>
-#include <cstring>
-#include <format>
-#include <iostream>
-#include <sstream>
-
-namespace args {
-
-int parse(const argp_t *argp, int argc, char *argv[], unsigned flags,
- void *input) noexcept {
- Parser parser(argp, flags, input);
- return parser.parse(argc, argv);
-}
-
-void usage(const Parser *parser) { help(parser, stderr, Help::STD_USAGE); }
-void help(const Parser *parser, FILE *stream, unsigned flags) {
- if (!parser || !stream) return;
-
- if (flags & LONG) parser->help(stream);
- else if (flags & USAGE) parser->usage(stream);
- else if (flags & SEE) parser->see(stream);
-
- if (parser->flags() & NO_EXIT) return;
- if (flags & EXIT_ERR) exit(2);
- if (flags & EXIT_OK) exit(0);
-}
-
-void failure(const Parser *parser, int status, int errnum, const char *fmt,
- std::va_list args) {
- (void)errnum;
- std::fprintf(stderr, "%s: ", parser->name());
- std::vfprintf(stderr, fmt, args);
- std::putc('\n', stderr);
- if (status) exit(status);
-}
-
-void failure(const Parser *parser, int status, int errnum, const char *fmt,
- ...) {
- std::va_list args;
- va_start(args, fmt);
- failure(parser, status, errnum, fmt, args);
- va_end(args);
-}
-
-Parser::Parser(const argp_t *argp, unsigned flags, void *input)
- : argp(argp), m_flags(flags), m_input(input) {
- int group = 0, key_last = 0;
- bool hidden = false;
-
- for (int i = 0; true; i++) {
- const auto &opt = argp->options[i];
- if (!opt.name && !opt.key && !opt.message) break;
-
- if (!opt.name && !opt.key) {
- group = opt.group ? opt.group : group + 1;
- help_entries.emplace_back(nullptr, opt.message, group);
- continue;
- }
-
- if (!opt.key) {
- // non alias without a key, silently ignoring
- if (!(opt.flags & ALIAS)) continue;
-
- // nothing to alias, silently ignoring
- if (!key_last) continue;
-
- // option not valid, silently ignoring
- if (!trie.insert(opt.name, key_last)) continue;
-
- if (hidden) continue;
- if (opt.flags & Option::HIDDEN) continue;
-
- help_entries.back().push(opt.name);
- } else {
- // duplicate key, silently ignoring
- if (options.count(opt.key)) continue;
-
- if (opt.name) trie.insert(opt.name, opt.key);
- options[key_last = opt.key] = &opt;
-
- bool arg_opt = opt.flags & Option::ARG_OPTIONAL;
-
- if (!(opt.flags & ALIAS)) {
- if ((hidden = opt.flags & Option::HIDDEN)) continue;
-
- help_entries.emplace_back(opt.arg, opt.message, group,
- arg_opt);
-
- if (opt.name) help_entries.back().push(opt.name);
- if (std::isprint(opt.key)) help_entries.back().push(opt.key);
- } else {
- // nothing to alias, silently ignoring
- if (!key_last) continue;
-
- if (hidden) continue;
- if (opt.flags & Option::HIDDEN) continue;
-
- if (opt.name) help_entries.back().push(opt.name);
- if (std::isprint(opt.key)) help_entries.back().push(opt.key);
- }
- }
- }
-
- if (!(m_flags & NO_HELP)) {
- help_entries.emplace_back(nullptr, "Give this help list", -1);
- help_entries.back().push("help");
- help_entries.back().push('?');
-
- help_entries.emplace_back(nullptr, "Give a short usage message", -1);
- help_entries.back().push("usage");
- }
-
- std::sort(begin(help_entries), end(help_entries));
-}
-
-int Parser::parse(int argc, char *argv[]) {
- std::vector<const char *> args;
- int arg_cnt = 0, err_code = 0, i;
-
- const bool is_help = !(m_flags & NO_HELP);
- const bool is_error = !(m_flags & NO_ERRS);
-
- m_name = basename(argv[0]);
-
- argp->parse(Key::INIT, 0, this);
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] != '-') {
- if (m_flags & IN_ORDER) argp->parse(Key::ARG, argv[i], this);
- else args.push_back(argv[i]);
- arg_cnt++;
- continue;
- }
-
- // stop parsing options, rest are normal arguments
- if (!std::strcmp(argv[i], "--")) break;
-
- if (argv[i][1] != '-') { // short option
- const char *opt = argv[i] + 1;
-
- // loop over ganged options
- for (int j = 0; opt[j]; j++) {
- const char key = opt[j];
-
- if (is_help && key == '?') {
- if (is_error) ::args::help(this, stderr, STD_HELP);
- continue;
- }
-
- if (!options.count(key)) {
- err_code = handle_unknown(1, argv[i]);
- goto error;
- }
-
- const auto *option = options[key];
- bool is_opt = option->flags & ARG_OPTIONAL;
- if (!option->arg) argp->parse(key, nullptr, this);
- if (opt[j + 1] != 0) {
- argp->parse(key, opt + j + 1, this);
- break;
- } else if (is_opt) argp->parse(key, nullptr, this);
- else if (i + 1 != argc) {
- argp->parse(key, argv[++i], this);
- break;
- } else {
- err_code = handle_missing(1, argv[i]);
- goto error;
- }
- }
- } else { // long option
- const char *opt = argv[i] + 2;
- const auto is_eq = std::strchr(opt, '=');
-
- std::string opt_s = !is_eq ? opt : std::string(opt, is_eq - opt);
-
- if (is_help && opt_s == "help") {
- if (is_eq) {
- err_code = handle_excess(argv[i]);
- goto error;
- }
- if (is_error) ::args::help(this, stderr, STD_HELP);
- continue;
- }
-
- if (is_help && opt_s == "usage") {
- if (is_eq) {
- err_code = handle_excess(argv[i]);
- goto error;
- }
- if (is_error) ::args::help(this, stderr, STD_USAGE);
- continue;
- }
-
- const int key = trie.get(opt_s.data());
- if (!key) {
- err_code = handle_unknown(0, argv[i]);
- goto error;
- }
-
- const auto *option = options[key];
- if (!option->arg && is_eq) {
- err_code = handle_excess(argv[i]);
- goto error;
- }
-
- bool is_opt = option->flags & ARG_OPTIONAL;
- if (!option->arg) argp->parse(key, nullptr, this);
- else if (is_eq) argp->parse(key, is_eq + 1, this);
- else if (is_opt) argp->parse(key, nullptr, this);
- else if (i + 1 != argc) argp->parse(key, argv[++i], this);
- else {
- err_code = handle_missing(0, argv[i]);
- goto error;
- }
- }
- }
-
- // parse previous arguments if IN_ORDER is not set
- for (const auto arg : args) {
- argp->parse(Key::ARG, arg, this);
- }
-
- // parse rest argv as normal arguments
- for (i = i + 1; i < argc; i++) {
- argp->parse(Key::ARG, argv[i], this);
- arg_cnt++;
- }
-
- if (!arg_cnt) argp->parse(Key::NO_ARGS, 0, this);
-
- argp->parse(Key::END, 0, this);
- argp->parse(Key::SUCCESS, 0, this);
-
- return 0;
-
-error:
- return err_code;
-}
-
-int Parser::handle_unknown(bool shrt, const char *argv) {
- if (m_flags & NO_ERRS) return argp->parse(Key::ERROR, 0, this);
-
- static const char *const unknown_fmt[2] = {
- "unrecognized option '-%s'\n",
- "invalid option -- '%s'\n",
- };
-
- failure(this, 1, 0, unknown_fmt[shrt], argv + 1);
- see(stderr);
-
- if (m_flags & NO_EXIT) return 1;
- exit(1);
-}
-
-int Parser::handle_missing(bool shrt, const char *argv) {
- if (m_flags & NO_ERRS) return argp->parse(Key::ERROR, 0, this);
-
- static const char *const missing_fmt[2] = {
- "option '-%s' requires an argument\n",
- "option requires an argument -- '%s'\n",
- };
-
- failure(this, 2, 0, missing_fmt[shrt], argv + 1);
- see(stderr);
-
- if (m_flags & NO_EXIT) return 2;
- exit(2);
-}
-
-int Parser::handle_excess(const char *argv) {
- if (m_flags & NO_ERRS) return argp->parse(Key::ERROR, 0, this);
-
- failure(this, 3, 0, "option '%s' doesn't allow an argument\n", argv);
- see(stderr);
-
- if (m_flags & NO_EXIT) return 3;
- exit(3);
-}
-
-const char *Parser::basename(const char *name) {
- const char *name_sh = std::strrchr(name, '/');
- return name_sh ? name_sh + 1 : name;
-}
-
-} // namespace args
diff --git a/src/c_bindings.cpp b/src/c_bindings.cpp
@@ -1,24 +1,24 @@
-#include "args.h"
-#include "args.hpp"
+#include "poafloc.h"
+#include "poafloc.hpp"
#include <cstdarg>
-namespace args {
+namespace poafloc {
-int args_parse(const args_argp_t *argp, int argc, char *argv[], unsigned flags,
+int poafloc_parse(const poafloc_arg_t *argp, int argc, char *argv[], unsigned flags,
void *input) {
return parse(argp, argc, argv, flags, input);
}
-void *args_parser_input(args_parser_t *parser) { return parser->input(); }
+void *poafloc_parser_input(poafloc_parser_t *parser) { return parser->input(); }
-void args_usage(args_parser_t *parser) { return usage(parser); }
+void poafloc_usage(poafloc_parser_t *parser) { return usage(parser); }
-void args_help(const args_parser_t *parser, FILE *stream, unsigned flags) {
+void poafloc_help(const poafloc_parser_t *parser, FILE *stream, unsigned flags) {
help(parser, stream, flags);
}
-void args_failure(const args_parser_t *parser, int status, int errnum,
+void poafloc_failure(const poafloc_parser_t *parser, int status, int errnum,
const char *fmt, ...) {
std::va_list args;
va_start(args, fmt);
diff --git a/src/help.cpp b/src/help.cpp
@@ -1,10 +1,10 @@
-#include "args.hpp"
+#include "poafloc.hpp"
#include <cstring>
#include <format>
#include <sstream>
-namespace args {
+namespace poafloc {
bool Parser::help_entry_t::operator<(const help_entry_t &rhs) const {
if (group != rhs.group) {
diff --git a/src/poafloc.cpp b/src/poafloc.cpp
@@ -0,0 +1,287 @@
+#include "poafloc.hpp"
+
+#include <algorithm>
+#include <cstring>
+#include <format>
+#include <iostream>
+#include <sstream>
+
+namespace poafloc {
+
+int parse(const arg_t *argp, int argc, char *argv[], unsigned flags,
+ void *input) noexcept {
+ Parser parser(argp, flags, input);
+ return parser.parse(argc, argv);
+}
+
+void usage(const Parser *parser) { help(parser, stderr, Help::STD_USAGE); }
+void help(const Parser *parser, FILE *stream, unsigned flags) {
+ if (!parser || !stream) return;
+
+ if (flags & LONG) parser->help(stream);
+ else if (flags & USAGE) parser->usage(stream);
+ else if (flags & SEE) parser->see(stream);
+
+ if (parser->flags() & NO_EXIT) return;
+ if (flags & EXIT_ERR) exit(2);
+ if (flags & EXIT_OK) exit(0);
+}
+
+void failure(const Parser *parser, int status, int errnum, const char *fmt,
+ std::va_list args) {
+ (void)errnum;
+ std::fprintf(stderr, "%s: ", parser->name());
+ std::vfprintf(stderr, fmt, args);
+ std::putc('\n', stderr);
+ if (status) exit(status);
+}
+
+void failure(const Parser *parser, int status, int errnum, const char *fmt,
+ ...) {
+ std::va_list args;
+ va_start(args, fmt);
+ failure(parser, status, errnum, fmt, args);
+ va_end(args);
+}
+
+Parser::Parser(const arg_t *argp, unsigned flags, void *input)
+ : argp(argp), m_flags(flags), m_input(input) {
+ int group = 0, key_last = 0;
+ bool hidden = false;
+
+ for (int i = 0; true; i++) {
+ const auto &opt = argp->options[i];
+ if (!opt.name && !opt.key && !opt.message) break;
+
+ if (!opt.name && !opt.key) {
+ group = opt.group ? opt.group : group + 1;
+ help_entries.emplace_back(nullptr, opt.message, group);
+ continue;
+ }
+
+ if (!opt.key) {
+ // non alias without a key, silently ignoring
+ if (!(opt.flags & ALIAS)) continue;
+
+ // nothing to alias, silently ignoring
+ if (!key_last) continue;
+
+ // option not valid, silently ignoring
+ if (!trie.insert(opt.name, key_last)) continue;
+
+ if (hidden) continue;
+ if (opt.flags & Option::HIDDEN) continue;
+
+ help_entries.back().push(opt.name);
+ } else {
+ // duplicate key, silently ignoring
+ if (options.count(opt.key)) continue;
+
+ if (opt.name) trie.insert(opt.name, opt.key);
+ options[key_last = opt.key] = &opt;
+
+ bool arg_opt = opt.flags & Option::ARG_OPTIONAL;
+
+ if (!(opt.flags & ALIAS)) {
+ if ((hidden = opt.flags & Option::HIDDEN)) continue;
+
+ help_entries.emplace_back(opt.arg, opt.message, group,
+ arg_opt);
+
+ if (opt.name) help_entries.back().push(opt.name);
+ if (std::isprint(opt.key)) help_entries.back().push(opt.key);
+ } else {
+ // nothing to alias, silently ignoring
+ if (!key_last) continue;
+
+ if (hidden) continue;
+ if (opt.flags & Option::HIDDEN) continue;
+
+ if (opt.name) help_entries.back().push(opt.name);
+ if (std::isprint(opt.key)) help_entries.back().push(opt.key);
+ }
+ }
+ }
+
+ if (!(m_flags & NO_HELP)) {
+ help_entries.emplace_back(nullptr, "Give this help list", -1);
+ help_entries.back().push("help");
+ help_entries.back().push('?');
+
+ help_entries.emplace_back(nullptr, "Give a short usage message", -1);
+ help_entries.back().push("usage");
+ }
+
+ std::sort(begin(help_entries), end(help_entries));
+}
+
+int Parser::parse(int argc, char *argv[]) {
+ std::vector<const char *> args;
+ int arg_cnt = 0, err_code = 0, i;
+
+ const bool is_help = !(m_flags & NO_HELP);
+ const bool is_error = !(m_flags & NO_ERRS);
+
+ m_name = basename(argv[0]);
+
+ argp->parse(Key::INIT, 0, this);
+
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ if (m_flags & IN_ORDER) argp->parse(Key::ARG, argv[i], this);
+ else args.push_back(argv[i]);
+ arg_cnt++;
+ continue;
+ }
+
+ // stop parsing options, rest are normal arguments
+ if (!std::strcmp(argv[i], "--")) break;
+
+ if (argv[i][1] != '-') { // short option
+ const char *opt = argv[i] + 1;
+
+ // loop over ganged options
+ for (int j = 0; opt[j]; j++) {
+ const char key = opt[j];
+
+ if (is_help && key == '?') {
+ if (is_error) ::poafloc::help(this, stderr, STD_HELP);
+ continue;
+ }
+
+ if (!options.count(key)) {
+ err_code = handle_unknown(1, argv[i]);
+ goto error;
+ }
+
+ const auto *option = options[key];
+ bool is_opt = option->flags & ARG_OPTIONAL;
+ if (!option->arg) argp->parse(key, nullptr, this);
+ if (opt[j + 1] != 0) {
+ argp->parse(key, opt + j + 1, this);
+ break;
+ } else if (is_opt) argp->parse(key, nullptr, this);
+ else if (i + 1 != argc) {
+ argp->parse(key, argv[++i], this);
+ break;
+ } else {
+ err_code = handle_missing(1, argv[i]);
+ goto error;
+ }
+ }
+ } else { // long option
+ const char *opt = argv[i] + 2;
+ const auto is_eq = std::strchr(opt, '=');
+
+ std::string opt_s = !is_eq ? opt : std::string(opt, is_eq - opt);
+
+ if (is_help && opt_s == "help") {
+ if (is_eq) {
+ err_code = handle_excess(argv[i]);
+ goto error;
+ }
+ if (is_error) ::poafloc::help(this, stderr, STD_HELP);
+ continue;
+ }
+
+ if (is_help && opt_s == "usage") {
+ if (is_eq) {
+ err_code = handle_excess(argv[i]);
+ goto error;
+ }
+ if (is_error) ::poafloc::help(this, stderr, STD_USAGE);
+ continue;
+ }
+
+ const int key = trie.get(opt_s.data());
+ if (!key) {
+ err_code = handle_unknown(0, argv[i]);
+ goto error;
+ }
+
+ const auto *option = options[key];
+ if (!option->arg && is_eq) {
+ err_code = handle_excess(argv[i]);
+ goto error;
+ }
+
+ bool is_opt = option->flags & ARG_OPTIONAL;
+ if (!option->arg) argp->parse(key, nullptr, this);
+ else if (is_eq) argp->parse(key, is_eq + 1, this);
+ else if (is_opt) argp->parse(key, nullptr, this);
+ else if (i + 1 != argc) argp->parse(key, argv[++i], this);
+ else {
+ err_code = handle_missing(0, argv[i]);
+ goto error;
+ }
+ }
+ }
+
+ // parse previous arguments if IN_ORDER is not set
+ for (const auto arg : args) {
+ argp->parse(Key::ARG, arg, this);
+ }
+
+ // parse rest argv as normal arguments
+ for (i = i + 1; i < argc; i++) {
+ argp->parse(Key::ARG, argv[i], this);
+ arg_cnt++;
+ }
+
+ if (!arg_cnt) argp->parse(Key::NO_ARGS, 0, this);
+
+ argp->parse(Key::END, 0, this);
+ argp->parse(Key::SUCCESS, 0, this);
+
+ return 0;
+
+error:
+ return err_code;
+}
+
+int Parser::handle_unknown(bool shrt, const char *argv) {
+ if (m_flags & NO_ERRS) return argp->parse(Key::ERROR, 0, this);
+
+ static const char *const unknown_fmt[2] = {
+ "unrecognized option '-%s'\n",
+ "invalid option -- '%s'\n",
+ };
+
+ failure(this, 1, 0, unknown_fmt[shrt], argv + 1);
+ see(stderr);
+
+ if (m_flags & NO_EXIT) return 1;
+ exit(1);
+}
+
+int Parser::handle_missing(bool shrt, const char *argv) {
+ if (m_flags & NO_ERRS) return argp->parse(Key::ERROR, 0, this);
+
+ static const char *const missing_fmt[2] = {
+ "option '-%s' requires an argument\n",
+ "option requires an argument -- '%s'\n",
+ };
+
+ failure(this, 2, 0, missing_fmt[shrt], argv + 1);
+ see(stderr);
+
+ if (m_flags & NO_EXIT) return 2;
+ exit(2);
+}
+
+int Parser::handle_excess(const char *argv) {
+ if (m_flags & NO_ERRS) return argp->parse(Key::ERROR, 0, this);
+
+ failure(this, 3, 0, "option '%s' doesn't allow an argument\n", argv);
+ see(stderr);
+
+ if (m_flags & NO_EXIT) return 3;
+ exit(3);
+}
+
+const char *Parser::basename(const char *name) {
+ const char *name_sh = std::strrchr(name, '/');
+ return name_sh ? name_sh + 1 : name;
+}
+
+} // namespace args
diff --git a/src/trie.cpp b/src/trie.cpp
@@ -1,8 +1,8 @@
-#include "args.hpp"
+#include "poafloc.hpp"
#include <cstdint>
-namespace args {
+namespace poafloc {
Parser::trie_t::~trie_t() noexcept {
for (uint8_t i = 0; i < 26; i++) {