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 | ++++++++ |
A | Makefile | | | 11 | +++++++++++ |
A | args.hpp | | | 73 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | demo.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;
+}