Compare commits
2 Commits
880627f66c
...
refactor
| Author | SHA1 | Date | |
|---|---|---|---|
| a7008d3a1e | |||
| 4dc995b9a6 |
88
argparser.c
88
argparser.c
@@ -8,8 +8,16 @@
|
|||||||
|
|
||||||
#define INITIAL_SIZE 30
|
#define INITIAL_SIZE 30
|
||||||
|
|
||||||
|
void print_usage(argparser_t *parser);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
arg_type_t type;
|
||||||
|
const char *identifier;
|
||||||
|
const char *short_name;
|
||||||
|
} parser_arg_t;
|
||||||
|
|
||||||
struct argparser {
|
struct argparser {
|
||||||
arg_t *args;
|
parser_arg_t *args;
|
||||||
u64 size;
|
u64 size;
|
||||||
u64 args_count;
|
u64 args_count;
|
||||||
u64 positional_count;
|
u64 positional_count;
|
||||||
@@ -17,14 +25,16 @@ struct argparser {
|
|||||||
u64 flag_count;
|
u64 flag_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
argparser_t *create_parser(void) {
|
INTERNAL parser_arg_t help_arg = {ARG_TYPE_FLAG, "help", "h"};
|
||||||
|
|
||||||
|
argparser_t *create_parser(parse_func_t parse_func) {
|
||||||
argparser_t *parser = (argparser_t *)malloc(sizeof(argparser_t));
|
argparser_t *parser = (argparser_t *)malloc(sizeof(argparser_t));
|
||||||
|
|
||||||
if (!parser) {
|
if (!parser) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->args = (arg_t *)malloc(INITIAL_SIZE * sizeof(arg_t));
|
parser->args = (parser_arg_t *)malloc(INITIAL_SIZE * sizeof(parser_arg_t));
|
||||||
if (!(parser->args)) {
|
if (!(parser->args)) {
|
||||||
free(parser);
|
free(parser);
|
||||||
|
|
||||||
@@ -35,7 +45,7 @@ argparser_t *create_parser(void) {
|
|||||||
parser->args_count = parser->positional_count = parser->named_count =
|
parser->args_count = parser->positional_count = parser->named_count =
|
||||||
parser->flag_count = 0;
|
parser->flag_count = 0;
|
||||||
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "h", "help"});
|
add_argument(parser, help_arg);
|
||||||
|
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
@@ -69,19 +79,19 @@ void add_argument(argparser_t *parser, arg_t arg) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser->args_count + 1 == parser->size) {
|
if (parser->args_count == parser->size) {
|
||||||
arg_t *new_args =
|
parser->size += INITIAL_SIZE;
|
||||||
(arg_t *)malloc((parser->size + INITIAL_SIZE) * sizeof(arg_t));
|
|
||||||
|
|
||||||
if (!new_args) {
|
// clang-format off
|
||||||
|
parser->args = (arg_t *)realloc(
|
||||||
|
(void *)(parser->args),
|
||||||
|
parser->size * sizeof(arg_t)
|
||||||
|
);
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
if (!(parser->args)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(new_args, parser->args, parser->args_count);
|
|
||||||
|
|
||||||
free(parser->args);
|
|
||||||
|
|
||||||
parser->args = new_args;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
parser->args[(parser->args_count)++] = arg;
|
parser->args[(parser->args_count)++] = arg;
|
||||||
@@ -101,21 +111,41 @@ void add_argument(argparser_t *parser, arg_t arg) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_args(argparser_t *parser, i32 argc, char *argv[]) {
|
||||||
|
for (u32 i = 0; i < argc; ++i) {
|
||||||
|
const char *short_name = &(argv[i][1]);
|
||||||
|
const char *long_name = &(argv[i][2]);
|
||||||
|
|
||||||
|
if (strcmp(short_name, help_arg.short_name) == 0 ||
|
||||||
|
strcmp(long_name, help_arg.identifier) == 0) {
|
||||||
|
print_usage(parser);
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc - 1 < parser->positional_count) {
|
||||||
|
print_usage(parser);
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void print_usage(argparser_t *parser) {
|
void print_usage(argparser_t *parser) {
|
||||||
arg_t positional[parser->positional_count];
|
parser_arg_t positional[parser->positional_count];
|
||||||
memset(positional, 0, parser->positional_count);
|
memset(positional, 0, parser->positional_count);
|
||||||
u64 positional_index = 0;
|
u64 positional_index = 0;
|
||||||
|
|
||||||
arg_t named[parser->named_count];
|
parser_arg_t named[parser->named_count];
|
||||||
memset(named, 0, parser->named_count);
|
memset(named, 0, parser->named_count);
|
||||||
u64 named_index = 0;
|
u64 named_index = 0;
|
||||||
|
|
||||||
arg_t flag[parser->flag_count];
|
parser_arg_t flag[parser->flag_count];
|
||||||
memset(flag, 0, parser->flag_count);
|
memset(flag, 0, parser->flag_count);
|
||||||
u64 flag_index = 0;
|
u64 flag_index = 0;
|
||||||
|
|
||||||
for (u64 i = 0; i < parser->args_count; ++i) {
|
for (u64 i = 0; i < parser->args_count; ++i) {
|
||||||
const arg_t *arg = &(parser->args[i]);
|
const parser_arg_t *arg = &(parser->args[i]);
|
||||||
|
|
||||||
switch (arg->type) {
|
switch (arg->type) {
|
||||||
case ARG_TYPE_POSITIONAL:
|
case ARG_TYPE_POSITIONAL:
|
||||||
@@ -152,7 +182,7 @@ void print_usage(argparser_t *parser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < flag_index; ++i) {
|
for (u64 i = 0; i < flag_index; ++i) {
|
||||||
const arg_t *arg = &(flag[i]);
|
const parser_arg_t *arg = &(flag[i]);
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "[");
|
sprintf(&(usage_line[strlen(usage_line)]), "[");
|
||||||
sprintf(&(flag_args[strlen(flag_args)]), "\t");
|
sprintf(&(flag_args[strlen(flag_args)]), "\t");
|
||||||
@@ -162,12 +192,12 @@ void print_usage(argparser_t *parser) {
|
|||||||
sprintf(&(flag_args[strlen(flag_args)]), "-%s, ", arg->short_name);
|
sprintf(&(flag_args[strlen(flag_args)]), "-%s, ", arg->short_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "--%s] ", arg->long_name);
|
sprintf(&(usage_line[strlen(usage_line)]), "--%s] ", arg->identifier);
|
||||||
sprintf(&(flag_args[strlen(flag_args)]), "--%s\n", arg->long_name);
|
sprintf(&(flag_args[strlen(flag_args)]), "--%s\n", arg->identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < named_index; ++i) {
|
for (u64 i = 0; i < named_index; ++i) {
|
||||||
const arg_t *arg = &(named[i]);
|
const parser_arg_t *arg = &(named[i]);
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "[");
|
sprintf(&(usage_line[strlen(usage_line)]), "[");
|
||||||
sprintf(&(named_args[strlen(named_args)]), "\t");
|
sprintf(&(named_args[strlen(named_args)]), "\t");
|
||||||
@@ -177,33 +207,33 @@ void print_usage(argparser_t *parser) {
|
|||||||
sprintf(&(named_args[strlen(named_args)]), "-%s, ", arg->short_name);
|
sprintf(&(named_args[strlen(named_args)]), "-%s, ", arg->short_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 name_length = strlen(arg->long_name);
|
u64 name_length = strlen(arg->identifier);
|
||||||
|
|
||||||
char capitalised[name_length];
|
char capitalised[name_length];
|
||||||
memset(capitalised, 0, name_length);
|
memset(capitalised, 0, name_length);
|
||||||
|
|
||||||
strcpy(capitalised, arg->long_name);
|
strcpy(capitalised, arg->identifier);
|
||||||
|
|
||||||
for (u64 i = 0; i < name_length; ++i) {
|
for (u64 i = 0; i < name_length; ++i) {
|
||||||
capitalised[i] = toupper(capitalised[i]);
|
capitalised[i] = toupper(capitalised[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "--%s %s] ", arg->long_name,
|
sprintf(&(usage_line[strlen(usage_line)]), "--%s %s] ", arg->identifier,
|
||||||
capitalised);
|
capitalised);
|
||||||
sprintf(&(named_args[strlen(named_args)]), "--%s\n", arg->long_name);
|
sprintf(&(named_args[strlen(named_args)]), "--%s\n", arg->identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u64 i = 0; i < positional_index; ++i) {
|
for (u64 i = 0; i < positional_index; ++i) {
|
||||||
const arg_t *arg = &(named[i]);
|
const parser_arg_t *arg = &(named[i]);
|
||||||
|
|
||||||
sprintf(&(positional_args[strlen(positional_args)]), "\t");
|
sprintf(&(positional_args[strlen(positional_args)]), "\t");
|
||||||
|
|
||||||
u64 name_length = strlen(arg->long_name);
|
u64 name_length = strlen(arg->identifier);
|
||||||
|
|
||||||
char capitalised[name_length];
|
char capitalised[name_length];
|
||||||
memset(capitalised, 0, name_length);
|
memset(capitalised, 0, name_length);
|
||||||
|
|
||||||
strcpy(capitalised, arg->long_name);
|
strcpy(capitalised, arg->identifier);
|
||||||
|
|
||||||
for (u64 i = 0; i < name_length; ++i) {
|
for (u64 i = 0; i < name_length; ++i) {
|
||||||
capitalised[i] = toupper(capitalised[i]);
|
capitalised[i] = toupper(capitalised[i]);
|
||||||
|
|||||||
19
argparser.h
19
argparser.h
@@ -2,9 +2,18 @@
|
|||||||
#define ARGPARSER_H
|
#define ARGPARSER_H
|
||||||
|
|
||||||
#include "aliases.h"
|
#include "aliases.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct argparser argparser_t;
|
typedef struct argparser argparser_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *identifier;
|
||||||
|
union {
|
||||||
|
const char *value;
|
||||||
|
bool flag;
|
||||||
|
};
|
||||||
|
} arg_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ARG_TYPE_POSITIONAL,
|
ARG_TYPE_POSITIONAL,
|
||||||
ARG_TYPE_NAMED,
|
ARG_TYPE_NAMED,
|
||||||
@@ -13,15 +22,11 @@ typedef enum {
|
|||||||
COUNT_ARG_TYPE,
|
COUNT_ARG_TYPE,
|
||||||
} arg_type_t;
|
} arg_type_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef void (*parse_func_t)(arg_t arg, void *user_data);
|
||||||
arg_type_t type;
|
|
||||||
const char *short_name;
|
|
||||||
const char *long_name;
|
|
||||||
} arg_t;
|
|
||||||
|
|
||||||
argparser_t *create_parser(void);
|
argparser_t *create_parser(parse_func_t parse_func);
|
||||||
void destroy_parser(argparser_t **parser);
|
void destroy_parser(argparser_t **parser);
|
||||||
void add_argument(argparser_t *parser, arg_t arg);
|
void add_argument(argparser_t *parser, arg_t arg);
|
||||||
void print_usage(argparser_t *parser);
|
void parse_args(argparser_t *parser, i32 argc, char *argv[]);
|
||||||
|
|
||||||
#endif // !ARGPARSER_H
|
#endif // !ARGPARSER_H
|
||||||
|
|||||||
2
build
2
build
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
|
|
||||||
CC=clang
|
CC=clang
|
||||||
CFLAGS="-g -Wall -Werror -pedantic"
|
CFLAGS="-g -Wall -Werror -Wpedantic"
|
||||||
SRC=*.c
|
SRC=*.c
|
||||||
OUT=main
|
OUT=main
|
||||||
|
|
||||||
|
|||||||
9
main.c
9
main.c
@@ -1,8 +1,11 @@
|
|||||||
#include "argparser.h"
|
#include "argparser.h"
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void parse_func(arg_t arg, void *user_data);
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
argparser_t *parser = create_parser();
|
argparser_t *parser = create_parser(parse_func);
|
||||||
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_POSITIONAL, "c", "count"});
|
add_argument(parser, (arg_t){ARG_TYPE_POSITIONAL, "c", "count"});
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_POSITIONAL, "g", "group"});
|
add_argument(parser, (arg_t){ARG_TYPE_POSITIONAL, "g", "group"});
|
||||||
@@ -12,9 +15,11 @@ int main(int argc, char *argv[]) {
|
|||||||
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "u", "undo"});
|
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "u", "undo"});
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "d", "delete"});
|
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "d", "delete"});
|
||||||
|
|
||||||
print_usage(parser);
|
parse_args(parser, argc, argv);
|
||||||
|
|
||||||
destroy_parser(&parser);
|
destroy_parser(&parser);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_func(arg_t arg, void *user_data) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user