poaflocParser Of Arguments For Lines Of Commands |
git clone git://git.dimitrijedobrota.com/poafloc.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 0b04695a665b57bf1c7d14e9f3e8b534575705ac |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 5 Jun 2024 18:57:34 +0200 |
Proof of concept
Diffstat:A | .clang-format | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | .gitignore | | | ++++++++ |
A | Makefile | | | +++++++++++ |
A | args.hpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | demo.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
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;
}