poafloc

Parser 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 36fd7278d9c884f92d36fa9a886e0c420dc36551
parent 660f946bfbd9e8aa1aae6eca0d235385ef89ed45
author Dimitrije Dobrota < mail@dimitrijedobrota.com >
date Wed, 5 Jun 2024 21:15:12 +0200

Recognize long and short options

Diffstat:
M args.hpp | +++++++++++++++++++++++++++++++ ---------------
M demo.cpp | ++++++++++++++++ ----------------------------

2 files changed, 47 insertions(+), 43 deletions(-)


diff --git a/ args.hpp b/ args.hpp

@@ -9,7 +9,7 @@ class Parser {

public:
struct option_t {
const char *name;
char key;
const char key;
const char *arg;
};

@@ -20,25 +20,44 @@ class Parser {

const parse_f parser;
};

static int parse(const argp_t *argp, int argc, const char *argv[], void *input) {

static int parse(argp_t *argp, int argc, char *argv[], void *input) {
for (int i = 1; i < argc; i++) {
bool opt_short = false, opt_long = false;

if (argv[i][0] != '-') {
argp->parser(-1, argv[i], input);
continue;
}

if (argv[i][1] != '-') opt_short = true;
else opt_long = true;

const char *opt = argv[i] + opt_long + 1;

bool found = false;
for (int j = 0; argp->options[j].name; j++) {
for (int j = 0; argp->options[j].key; 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 (opt_short && opt[0] != option.key) continue;

if (argv[i][n] == '=') {
if (!option.arg) {
std::cerr << "option doesn't require a value\n";
exit(1);
if (opt_long) {
if(!option.name) continue;

const auto n = std::strlen(option.name);
if (std::strncmp(argv[i] + 2, option.name, n)) continue;

if (opt[n] == '=') {
if (!option.arg) {
std::cerr << "option doesn't require a value\n";
exit(1);
}

arg = opt + n + 1;
}
}

arg = argv[i] + n + 1;
} else if (option.arg) {
if (option.arg && !arg) {
if (i == argc) {
std::cerr << "option missing a value\n";
exit(1);

@@ -59,8 +78,6 @@ class Parser {

std::cerr << std::format("unknown option {}\n", argv[i]);
return 1;
}

argp->parser(-1, argv[i], input);
}

return 0;

@@ -70,4 +87,3 @@ class Parser {

};

#endif

diff --git a/ demo.cpp b/ demo.cpp

@@ -1,7 +1,6 @@

#include "args.hpp"

#include <cstdint>
#include <unordered_map>
#include <vector>

void error(const std::string &message) {

@@ -10,14 +9,13 @@ void error(const std::string &message) {

}

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;

std::vector<const char *> args;
};

int parse_opt(int key, const char *arg, void *input) {

@@ -34,18 +32,6 @@ int parse_opt(int key, const char *arg, void *input) {

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);
}

@@ -54,16 +40,15 @@ int parse_opt(int key, const char *arg, void *input) {


// clang-format off
static const Parser::option_t options[] = {
{ "--debug", 'd', 0},
{ "--hex", 'h', 0},
{"--relocatable", 'r', 0},
{ "-o", 'o', "file"},
{ "--place", 'p', "address"},
{ 0, 'o', "file"},
{ "debug", 'd', 0},
{ "hex", 'h', 0},
{"relocatable", 'r', 0},
{0},
};
// clang-format on

int main(int argc, const char *argv[]) {
int main(int argc, char *argv[]) {
Parser::argp_t argp = {options, parse_opt};
arguments_t arguments;

@@ -71,13 +56,16 @@ int main(int argc, const char *argv[]) {

error("There was an error while parsing arguments");
}

if (arguments.args.size() == 0) {
error("please provide at least one input file");
}
std::cout << "Command line options: " << std::endl;

if (!arguments.hex && !arguments.relocatable) {
error("please provide hex or relocatable flags");
}
std::cout << "\t output: " << arguments.output_file << std::endl;
std::cout << "\t hex: " << arguments.hex << std::endl;
std::cout << "\t debug: " << arguments.debug << std::endl;
std::cout << "\t relocatable: " << arguments.relocatable << std::endl;

std::cout << "\t args: ";
for (const auto &arg : arguments.args) std::cout << arg << " ";
std::cout << std::endl;

return 0;
}