Parse command-line arguments
This commit is contained in:
1 parent
05dfa4f977
commit
cc041168a1
4 files changed
+196
-2
No files matched your search
+173
-1
@@ -1,5 +1,177 @@
|
|||||||
#include <fart/Cli.h>
|
#include <fart/Cli.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
Cli::Cli()
|
#define FLAGS \
|
||||||
|
FLAG(height, "h", true) \
|
||||||
|
FLAG(height_l, "height", true) \
|
||||||
|
FLAG(help, "help", false) \
|
||||||
|
FLAG(output, "o", true) \
|
||||||
|
FLAG(output_l, "output", true) \
|
||||||
|
FLAG(version, "version", false) \
|
||||||
|
FLAG(width, "w", true) \
|
||||||
|
FLAG(width_l, "width", true) \
|
||||||
|
|
||||||
|
#define FLAG(name, flag, arg) flag_##name,
|
||||||
|
typedef enum
|
||||||
{
|
{
|
||||||
|
FLAGS
|
||||||
|
flag__count
|
||||||
|
} flag_id_t;
|
||||||
|
#undef FLAG
|
||||||
|
|
||||||
|
#define FLAG(name, flag, arg) static const char flag_##name##_str[] = flag;
|
||||||
|
FLAGS
|
||||||
|
#undef FLAG
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char * flag;
|
||||||
|
size_t flag_length;
|
||||||
|
bool arg;
|
||||||
|
} flag_def_t;
|
||||||
|
|
||||||
|
#define FLAG(name, flag, arg) { \
|
||||||
|
flag_##name##_str, \
|
||||||
|
sizeof(flag_##name##_str) - 1u, \
|
||||||
|
arg},
|
||||||
|
static const flag_def_t flag_defs[] = {
|
||||||
|
FLAGS
|
||||||
|
};
|
||||||
|
#undef FLAG
|
||||||
|
|
||||||
|
int Cli::run(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
for (size_t i = 1; i < argc; i++)
|
||||||
|
{
|
||||||
|
size_t dashes = 0u;
|
||||||
|
if (strncmp(argv[i], "--", 2) == 0)
|
||||||
|
{
|
||||||
|
dashes = 2u;
|
||||||
|
}
|
||||||
|
else if (strncmp(argv[i], "-", 1) == 0)
|
||||||
|
{
|
||||||
|
dashes = 1u;
|
||||||
|
}
|
||||||
|
if (dashes > 0u)
|
||||||
|
{
|
||||||
|
const char * flag = &argv[i][dashes];
|
||||||
|
size_t flag_idx;
|
||||||
|
for (flag_idx = 0u; flag_idx < flag__count; flag_idx++)
|
||||||
|
{
|
||||||
|
size_t flag_length = flag_defs[flag_idx].flag_length;
|
||||||
|
size_t flag_dashes = flag_length == 1u ? 1u : 2u;
|
||||||
|
if (flag_dashes != dashes)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strncmp(flag, flag_defs[flag_idx].flag, flag_length) != 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (dashes == 2 && flag[flag_length] != '\0' && flag[flag_length] != '=')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool arg = flag_defs[flag_idx].arg;
|
||||||
|
const char * arg_value = nullptr;
|
||||||
|
if (arg)
|
||||||
|
{
|
||||||
|
if (flag[flag_length] == '\0')
|
||||||
|
{
|
||||||
|
if (i >= (argc - 1))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: option %s requires an argument\n", flag_defs[flag_idx].flag);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
arg_value = argv[i];
|
||||||
|
}
|
||||||
|
else if (dashes == 1u)
|
||||||
|
{
|
||||||
|
arg_value = &flag[flag_length];
|
||||||
|
}
|
||||||
|
else if (flag[flag_length + 1] != '\0')
|
||||||
|
{
|
||||||
|
arg_value = &flag[flag_length + 1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: option %s requires an argument\n", flag_defs[flag_idx].flag);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dashes == 2u && flag[flag_length] == '=')
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error: option %s does not take an argument\n", flag_defs[flag_idx].flag);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* TODO: support combining short flags, e.g. -cofoo */
|
||||||
|
}
|
||||||
|
int r = handle_option(flag_idx, arg_value);
|
||||||
|
if (r != 0)
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (flag_idx == flag__count)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unknown flag: %s\n", flag);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (this->options.input_file != "")
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Extraneous argument: %s\n", argv[i]);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
this->options.input_file = argv[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Cli::handle_option(size_t flag_idx, const char * arg_value)
|
||||||
|
{
|
||||||
|
switch (flag_idx)
|
||||||
|
{
|
||||||
|
case flag_height:
|
||||||
|
case flag_height_l:
|
||||||
|
this->options.height = atoi(arg_value);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case flag_help:
|
||||||
|
printf("Usage: fart [options] input-file\n");
|
||||||
|
printf("\n");
|
||||||
|
printf(" Options:\n");
|
||||||
|
printf("\n");
|
||||||
|
printf(" -h, --height H Set render height to H\n");
|
||||||
|
printf(" --help Show this help and exit\n");
|
||||||
|
printf(" -o, --output F Write rendered image to file F\n");
|
||||||
|
printf(" -w, --width W Set render width to W\n");
|
||||||
|
printf(" --version Show fart version and exit\n");
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case flag_output:
|
||||||
|
case flag_output_l:
|
||||||
|
this->options.output_file = arg_value;
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case flag_width:
|
||||||
|
case flag_width_l:
|
||||||
|
this->options.width = atoi(arg_value);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case flag_version:
|
||||||
|
printf("fart, version 0.0.0.0.0.1\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fprintf(stderr, "Internal error: unhandled flag_idx=%zu\n", flag_idx);
|
||||||
|
return 2;
|
||||||
}
|
}
|
||||||
+8
-1
@@ -1,7 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <fart/Options.h>
|
||||||
|
|
||||||
class Cli
|
class Cli
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Cli();
|
Options options;
|
||||||
|
|
||||||
|
int run(int argc, char * argv[]);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int handle_option(size_t option_idx, const char * arg_value);
|
||||||
};
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
struct Options
|
||||||
|
{
|
||||||
|
std::string input_file;
|
||||||
|
std::string output_file;
|
||||||
|
size_t width = 0u;
|
||||||
|
size_t height = 0u;
|
||||||
|
};
|
||||||
@@ -5,6 +5,11 @@
|
|||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
Cli cli;
|
Cli cli;
|
||||||
|
int rc = cli.run(argc, argv);
|
||||||
|
if (rc > 0)
|
||||||
|
{
|
||||||
|
return rc - 1;
|
||||||
|
}
|
||||||
Engine engine;
|
Engine engine;
|
||||||
printf("Hello\n");
|
printf("Hello\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in new issue
Block a user