Download
67 lines 2.6 KiBCModified 2026-01-25 raw
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef streq
#define streq(str, target) (strcmp(str, target) == 0)
#endif

#ifndef startswith
#define startswith(str, target) (strncmp(str, target, strlen(target)) == 0)
#endif

#define USAGE_ERROR(program_name, usage, ...)                                                                          \
    ({                                                                                                                 \
        printf("%s: ", program_name);                                                                                  \
        printf(__VA_ARGS__);                                                                                           \
        printf("\n\n%s", usage);                                                                                       \
        exit(1);                                                                                                       \
    })

static const char *pop_str_arg(const char *program_name, const char *usage, const char *flag, char shortflag, int *i,
                               int argc, char *argv[]) {
    if (startswith(argv[*i], flag)) {
        if (argv[*i][strlen(flag)] == '\0') {
            if (*i + 1 >= argc) USAGE_ERROR(program_name, usage, "No argument provided for %s", flag);
            const char *ret = argv[*i + 1];
            *i += 2;
            return ret;
        } else if (argv[*i][strlen(flag)] == '=') {
            const char *ret = &argv[*i][strlen(flag) + 1];
            *i += 1;
            return ret;
        }
    } else if (argv[*i][0] == '-' && argv[*i][1] == shortflag) {
        if (argv[*i][2] == '=') {
            const char *ret = &argv[*i][3];
            *i += 1;
            return ret;
        } else if (argv[*i][2] == '\0') {
            if (*i + 1 >= argc) USAGE_ERROR(program_name, usage, "No argument provided for -%c", shortflag);
            const char *ret = argv[*i + 1];
            *i += 2;
            return ret;
        }
    }
    return NULL;
}

static bool pop_bool_arg(const char *flag, char shortflag, int *i, int argc, char *argv[]) {
    if (streq(argv[*i], flag)) {
        memmove(&argv[*i], &argv[*i + 1], sizeof(char * [argc - *i - 1]));
        *i += 1;
        return true;
    } else if (argv[*i][0] == '-' && argv[*i][1] != '-') {
        if (argv[*i][1] == shortflag && argv[*i][2] == '\0') {
            *i += 1;
            return true;
        }
        char *c = strchr(argv[*i], shortflag);
        if (c) {
            memmove(c, c + 1, strlen(c));
            return true;
        }
    }
    return false;
}