Compare commits
No commits in common. "880627f66c12ba86255bb7bba65a018f41df24ec" and "6afd2ad97b30d6cc969d314e8fe4031c37365422" have entirely different histories.
880627f66c
...
6afd2ad97b
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
main
|
|
15
.vscode/launch.json
vendored
15
.vscode/launch.json
vendored
@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Debug main",
|
|
||||||
"type": "cppdbg",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${workspaceRoot}/main",
|
|
||||||
"cwd": "${workspaceRoot}"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
26
aliases.h
26
aliases.h
@ -1,26 +0,0 @@
|
|||||||
#ifndef ALIASES_H
|
|
||||||
#define ALIASES_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#define u8 uint8_t
|
|
||||||
#define u16 uint16_t
|
|
||||||
#define u32 uint32_t
|
|
||||||
#define u64 uint64_t
|
|
||||||
|
|
||||||
#define i8 int8_t
|
|
||||||
#define i16 int16_t
|
|
||||||
#define i32 int32_t
|
|
||||||
#define i64 int64_t
|
|
||||||
|
|
||||||
#define f32 float
|
|
||||||
#define f64 double
|
|
||||||
|
|
||||||
#define INTERNAL static
|
|
||||||
#define PERSISTENT static
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define CLASS_MEMBER static
|
|
||||||
#endif // __cplusplus
|
|
||||||
|
|
||||||
#endif // !ALIASES_H
|
|
229
argparser.c
229
argparser.c
@ -1,229 +0,0 @@
|
|||||||
#include "argparser.h"
|
|
||||||
#include "aliases.h"
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#define INITIAL_SIZE 30
|
|
||||||
|
|
||||||
struct argparser {
|
|
||||||
arg_t *args;
|
|
||||||
u64 size;
|
|
||||||
u64 args_count;
|
|
||||||
u64 positional_count;
|
|
||||||
u64 named_count;
|
|
||||||
u64 flag_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
argparser_t *create_parser(void) {
|
|
||||||
argparser_t *parser = (argparser_t *)malloc(sizeof(argparser_t));
|
|
||||||
|
|
||||||
if (!parser) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->args = (arg_t *)malloc(INITIAL_SIZE * sizeof(arg_t));
|
|
||||||
if (!(parser->args)) {
|
|
||||||
free(parser);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->size = INITIAL_SIZE;
|
|
||||||
parser->args_count = parser->positional_count = parser->named_count =
|
|
||||||
parser->flag_count = 0;
|
|
||||||
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "h", "help"});
|
|
||||||
|
|
||||||
return parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroy_parser(argparser_t **parser) {
|
|
||||||
if (*parser) {
|
|
||||||
if ((*parser)->args) {
|
|
||||||
free((*parser)->args);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(*parser);
|
|
||||||
|
|
||||||
*parser = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_argument(argparser_t *parser, arg_t arg) {
|
|
||||||
bool valid_arg_type = false;
|
|
||||||
|
|
||||||
switch (arg.type) {
|
|
||||||
case ARG_TYPE_POSITIONAL:
|
|
||||||
case ARG_TYPE_NAMED:
|
|
||||||
case ARG_TYPE_FLAG:
|
|
||||||
valid_arg_type = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
valid_arg_type = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid_arg_type) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser->args_count + 1 == parser->size) {
|
|
||||||
arg_t *new_args =
|
|
||||||
(arg_t *)malloc((parser->size + INITIAL_SIZE) * sizeof(arg_t));
|
|
||||||
|
|
||||||
if (!new_args) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(new_args, parser->args, parser->args_count);
|
|
||||||
|
|
||||||
free(parser->args);
|
|
||||||
|
|
||||||
parser->args = new_args;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser->args[(parser->args_count)++] = arg;
|
|
||||||
|
|
||||||
switch (arg.type) {
|
|
||||||
case ARG_TYPE_POSITIONAL:
|
|
||||||
++(parser->positional_count);
|
|
||||||
break;
|
|
||||||
case ARG_TYPE_NAMED:
|
|
||||||
++(parser->named_count);
|
|
||||||
break;
|
|
||||||
case ARG_TYPE_FLAG:
|
|
||||||
++(parser->flag_count);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_usage(argparser_t *parser) {
|
|
||||||
arg_t positional[parser->positional_count];
|
|
||||||
memset(positional, 0, parser->positional_count);
|
|
||||||
u64 positional_index = 0;
|
|
||||||
|
|
||||||
arg_t named[parser->named_count];
|
|
||||||
memset(named, 0, parser->named_count);
|
|
||||||
u64 named_index = 0;
|
|
||||||
|
|
||||||
arg_t flag[parser->flag_count];
|
|
||||||
memset(flag, 0, parser->flag_count);
|
|
||||||
u64 flag_index = 0;
|
|
||||||
|
|
||||||
for (u64 i = 0; i < parser->args_count; ++i) {
|
|
||||||
const arg_t *arg = &(parser->args[i]);
|
|
||||||
|
|
||||||
switch (arg->type) {
|
|
||||||
case ARG_TYPE_POSITIONAL:
|
|
||||||
positional[positional_index++] = *arg;
|
|
||||||
break;
|
|
||||||
case ARG_TYPE_NAMED:
|
|
||||||
named[named_index++] = *arg;
|
|
||||||
break;
|
|
||||||
case ARG_TYPE_FLAG:
|
|
||||||
flag[flag_index++] = *arg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char usage_line[2048] = {0};
|
|
||||||
char positional_args[2048] = {0};
|
|
||||||
char named_args[2048] = {0};
|
|
||||||
char flag_args[2048] = {0};
|
|
||||||
|
|
||||||
sprintf(usage_line, "Usage: program ");
|
|
||||||
|
|
||||||
if (positional_index > 0) {
|
|
||||||
sprintf(positional_args, "Positional arguments:\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (named_index > 0) {
|
|
||||||
sprintf(named_args, "Named arguments:\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag_index > 0) {
|
|
||||||
sprintf(flag_args, "Flag arguments:\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < flag_index; ++i) {
|
|
||||||
const arg_t *arg = &(flag[i]);
|
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "[");
|
|
||||||
sprintf(&(flag_args[strlen(flag_args)]), "\t");
|
|
||||||
|
|
||||||
if (strlen(arg->short_name) > 0) {
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "-%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(&(flag_args[strlen(flag_args)]), "--%s\n", arg->long_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < named_index; ++i) {
|
|
||||||
const arg_t *arg = &(named[i]);
|
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "[");
|
|
||||||
sprintf(&(named_args[strlen(named_args)]), "\t");
|
|
||||||
|
|
||||||
if (strlen(arg->short_name) > 0) {
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "-%s | ", arg->short_name);
|
|
||||||
sprintf(&(named_args[strlen(named_args)]), "-%s, ", arg->short_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 name_length = strlen(arg->long_name);
|
|
||||||
|
|
||||||
char capitalised[name_length];
|
|
||||||
memset(capitalised, 0, name_length);
|
|
||||||
|
|
||||||
strcpy(capitalised, arg->long_name);
|
|
||||||
|
|
||||||
for (u64 i = 0; i < name_length; ++i) {
|
|
||||||
capitalised[i] = toupper(capitalised[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "--%s %s] ", arg->long_name,
|
|
||||||
capitalised);
|
|
||||||
sprintf(&(named_args[strlen(named_args)]), "--%s\n", arg->long_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u64 i = 0; i < positional_index; ++i) {
|
|
||||||
const arg_t *arg = &(named[i]);
|
|
||||||
|
|
||||||
sprintf(&(positional_args[strlen(positional_args)]), "\t");
|
|
||||||
|
|
||||||
u64 name_length = strlen(arg->long_name);
|
|
||||||
|
|
||||||
char capitalised[name_length];
|
|
||||||
memset(capitalised, 0, name_length);
|
|
||||||
|
|
||||||
strcpy(capitalised, arg->long_name);
|
|
||||||
|
|
||||||
for (u64 i = 0; i < name_length; ++i) {
|
|
||||||
capitalised[i] = toupper(capitalised[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
sprintf(&(usage_line[strlen(usage_line)]), "%s ", capitalised);
|
|
||||||
sprintf(&(positional_args[strlen(positional_args)]), "%s\n", capitalised);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("%s\n\n", usage_line);
|
|
||||||
|
|
||||||
if (strlen(positional_args) > 0) {
|
|
||||||
printf("%s\n", positional_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(named_args) > 0) {
|
|
||||||
printf("%s\n", named_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strlen(flag_args) > 0) {
|
|
||||||
printf("%s\n", flag_args);
|
|
||||||
}
|
|
||||||
}
|
|
27
argparser.h
27
argparser.h
@ -1,27 +0,0 @@
|
|||||||
#ifndef ARGPARSER_H
|
|
||||||
#define ARGPARSER_H
|
|
||||||
|
|
||||||
#include "aliases.h"
|
|
||||||
|
|
||||||
typedef struct argparser argparser_t;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
ARG_TYPE_POSITIONAL,
|
|
||||||
ARG_TYPE_NAMED,
|
|
||||||
ARG_TYPE_FLAG,
|
|
||||||
|
|
||||||
COUNT_ARG_TYPE,
|
|
||||||
} arg_type_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
arg_type_t type;
|
|
||||||
const char *short_name;
|
|
||||||
const char *long_name;
|
|
||||||
} arg_t;
|
|
||||||
|
|
||||||
argparser_t *create_parser(void);
|
|
||||||
void destroy_parser(argparser_t **parser);
|
|
||||||
void add_argument(argparser_t *parser, arg_t arg);
|
|
||||||
void print_usage(argparser_t *parser);
|
|
||||||
|
|
||||||
#endif // !ARGPARSER_H
|
|
4
build
4
build
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
|
|
||||||
CC=clang
|
CC=clang++
|
||||||
CFLAGS="-g -Wall -Werror -pedantic"
|
CFLAGS="-g -Wall -Werror -pedantic"
|
||||||
SRC=*.c
|
SRC=*.cpp
|
||||||
OUT=main
|
OUT=main
|
||||||
|
|
||||||
set -x
|
set -x
|
||||||
|
20
main.c
20
main.c
@ -1,20 +0,0 @@
|
|||||||
#include "argparser.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
argparser_t *parser = create_parser();
|
|
||||||
|
|
||||||
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_NAMED, "t", "test"});
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_NAMED, "f", "fault"});
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_NAMED, "e", "emblem"});
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "u", "undo"});
|
|
||||||
add_argument(parser, (arg_t){ARG_TYPE_FLAG, "d", "delete"});
|
|
||||||
|
|
||||||
print_usage(parser);
|
|
||||||
|
|
||||||
destroy_parser(&parser);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user