poafloc

poafloc - Parser Of Arguments For Lines Of Commands
git clone git://git.dimitrijedobrota.com/poafloc.git
Log | Files | Refs | README | LICENSE

commit 0b04695a665b57bf1c7d14e9f3e8b534575705ac
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Wed,  5 Jun 2024 20:57:34 +0200

Proof of concept

Diffstat:
A.clang-format | 216+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.gitignore | 8++++++++
AMakefile | 11+++++++++++
Aargs.hpp | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ademo.cpp | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 391 insertions(+), 0 deletions(-)

diff --git a/.clang-format b/.clang-format @@ -0,0 +1,216 @@ +--- +Language: Cpp +# BasedOnStyle: Microsoft +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + PadOperators: false +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: true +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Always +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 79 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequiresClause: true +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertBraces: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +RequiresClausePosition: OwnLine +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + AfterRequiresInClause: false + AfterRequiresInExpression: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/.gitignore b/.gitignore @@ -0,0 +1,8 @@ +* + +!Makefile +!args.hpp +!demo.cpp +!.clang-format +!.gitignore + diff --git a/Makefile b/Makefile @@ -0,0 +1,11 @@ + +all: demo + +demo: demo.cpp args.hpp + g++ -o $@ $< -std=c++20 -Wall -Werror + +clean: + rm -rf demo + + +.PHONY: clean diff --git a/args.hpp b/args.hpp @@ -0,0 +1,73 @@ +#ifndef ARGS_HPP +#define ARGS_HPP + +#include <cstring> +#include <format> +#include <iostream> + +class Parser { + public: + struct option_t { + const char *name; + char key; + bool arg; + }; + + struct argp_t { + using parse_f = int (*)(int key, const char *arg, void *input); + + const option_t *options; + const parse_f parser; + }; + + static int parse(const argp_t *argp, int argc, const char *argv[], void *input) { + + for (int i = 1; i < argc; i++) { + bool found = false; + for (int j = 0; argp->options[j].name; j++) { + const auto &option = argp->options[j]; + const auto n = std::strlen(option.name); + const char *arg = 0; + + if (std::strncmp(argv[i], option.name, n)) continue; + + if (argv[i][n] == '=') { + if (!option.arg) { + std::cerr << "option doesn't require a value\n"; + exit(1); + } + + arg = argv[i] + n + 1; + } else if (option.arg) { + if (i == argc) { + std::cerr << "option missing a value\n"; + exit(1); + } + + arg = argv[++i]; + } + + argp->parser(option.key, arg, input); + + found = true; + break; + } + + if (found) continue; + + if (argv[i][0] == '-') { + std::cerr << std::format("unknown option {}\n", argv[i]); + return 1; + } + + argp->parser(-1, argv[i], input); + } + + return 0; + } + + private: +}; + +#endif + diff --git a/demo.cpp b/demo.cpp @@ -0,0 +1,83 @@ +#include "args.hpp" + +#include <cstdint> +#include <unordered_map> +#include <vector> + +void error(const std::string &message) { + std::cerr << message << std::endl; + exit(1); +} + +struct arguments_t { + std::vector<const char *> args; + std::unordered_map<std::string, uint32_t> places; + + const char *output_file = 0; + + bool debug = 0; + bool hex = 0; + bool relocatable = 0; +}; + +int parse_opt(int key, const char *arg, void *input) { + auto arguments = (arguments_t *)input; + + switch (key) { + case 'd': arguments->debug = true; break; + case 'h': + if (arguments->relocatable) error("cannot mix -hex and -relocatable"); + arguments->hex = true; + break; + case 'r': + if (arguments->hex) error("cannot mix -hex and -relocatable"); + arguments->relocatable = true; + break; + case 'o': arguments->output_file = arg; break; + case 'p': { + const std::string s = arg; + + const auto pos = s.find('@'); + if (pos == std::string::npos) error("Invalid argument for -place"); + + const auto value = stol(s.substr(pos + 1), 0, 16); + const auto [_, a] = arguments->places.emplace(s.substr(0, pos), value); + if (!a) error("duplicate place for the same section"); + + break; + } + default: arguments->args.push_back(arg); + } + + return 0; +} + +// clang-format off +static const Parser::option_t options[] = { + { "--debug", 'd', 0}, + { "--hex", 'h', 0}, + {"--relocatable", 'r', 0}, + { "-o", 'o', 1}, + { "--place", 'p', 1}, + {0}, +}; +// clang-format on + +int main(int argc, const char *argv[]) { + Parser::argp_t argp = {options, parse_opt}; + arguments_t arguments; + + if (Parser::parse(&argp, argc, argv, &arguments)) { + error("There was an error while parsing arguments"); + } + + if (arguments.args.size() == 0) { + error("please provide at least one input file"); + } + + if (!arguments.hex && !arguments.relocatable) { + error("please provide hex or relocatable flags"); + } + + return 0; +}