Compare commits

..

2 Commits

Author SHA1 Message Date
a7008d3a1e Started refactoring the parser 2023-06-04 01:52:59 +01:00
4dc995b9a6 Add parse_func 2023-06-04 00:05:32 +01:00
4 changed files with 79 additions and 39 deletions

View File

@@ -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]);

View File

@@ -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
View File

@@ -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
View File

@@ -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) {}