#include #include #include #include #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; }