122 lines
3.8 KiB
C
122 lines
3.8 KiB
C
/* kyaa.h - macro hacks for handling main() arguments
|
|
license: public domain or whatever.
|
|
documentation is kept separate in kyaa.md
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#ifndef KYAA_OKAY
|
|
#define KYAA_OKAY 0
|
|
#endif
|
|
#ifndef KYAA_ERROR
|
|
#define KYAA_ERROR 1
|
|
#endif
|
|
#ifndef KYAA_ITER
|
|
#define KYAA_ITER i
|
|
#endif
|
|
|
|
#define KYAA_SETUP \
|
|
/* dumb sanity checks */ \
|
|
if (argc <= 0 || argv == NULL || argv[0] == NULL) { \
|
|
fprintf(stderr, "You've met with a terrible fate.\n"); \
|
|
return KYAA_ERROR; \
|
|
} \
|
|
char *kyaa_name = argv[0]; \
|
|
bool kyaa_read_stdin = false; \
|
|
char kyaa_flag = '\0'; \
|
|
bool kyaa_keep_parsing = true; \
|
|
bool kyaa_parse_next = false; \
|
|
|
|
#define KYAA_LOOP \
|
|
KYAA_SETUP \
|
|
for (int KYAA_ITER = 1; KYAA_ITER < argc; KYAA_ITER++) \
|
|
|
|
#define KYAA_BEGIN \
|
|
char *kyaa_arg = argv[KYAA_ITER]; \
|
|
if (kyaa_keep_parsing && (kyaa_parse_next || kyaa_arg[0] == '-')) { \
|
|
if (!kyaa_parse_next && kyaa_arg[1] == '-' && kyaa_arg[2] == '\0') { \
|
|
kyaa_keep_parsing = false; \
|
|
continue; \
|
|
} \
|
|
if (!kyaa_parse_next && kyaa_arg[1] == '\0') { \
|
|
kyaa_read_stdin = true; \
|
|
} else { \
|
|
/* case: kyaa_parse_next: arg is at least 1 char initialized. */ \
|
|
/* case: !kyaa_parse_next: arg is at least 3 chars initialized. */ \
|
|
char *kyaa_etc = kyaa_parse_next ? kyaa_arg : kyaa_arg + 2; \
|
|
bool kyaa_no_more = false; \
|
|
bool kyaa_helping = false; \
|
|
bool kyaa_any = false; \
|
|
if (!kyaa_parse_next && kyaa_arg[1] != '-') { \
|
|
kyaa_flag = kyaa_arg[1]; \
|
|
kyaa_no_more = kyaa_arg[2] == '\0'; \
|
|
} \
|
|
if (kyaa_flag == 'h' || !strcmp(kyaa_arg, "--help")) { \
|
|
printf("usage:\n"); \
|
|
kyaa_helping = true; \
|
|
} \
|
|
if (0) { \
|
|
|
|
#define KYAA_END \
|
|
} \
|
|
if (!kyaa_any && !kyaa_helping) { \
|
|
if (kyaa_flag) { \
|
|
fprintf(stderr, "unknown flag: -%c\n", kyaa_flag); \
|
|
} else { \
|
|
fprintf(stderr, "unknown flag: %s\n", kyaa_arg); \
|
|
} \
|
|
return KYAA_ERROR; \
|
|
} \
|
|
if (kyaa_helping) { \
|
|
return KYAA_OKAY; \
|
|
} \
|
|
kyaa_parse_next = false; \
|
|
kyaa_flag = '\0'; \
|
|
continue; \
|
|
} \
|
|
} \
|
|
|
|
#define KYAA_DESCRIBE(c, name, description) \
|
|
printf(" -%c --%s\n%s\n", c, name, description) \
|
|
|
|
#define KYAA_FLAG(c, name, description) \
|
|
} \
|
|
if (kyaa_helping) { \
|
|
KYAA_DESCRIBE(c, name, description); \
|
|
} else if (kyaa_flag == c || !strcmp(kyaa_arg, "--"name)) { \
|
|
kyaa_flag = c; \
|
|
kyaa_any = true; \
|
|
|
|
#define KYAA_FLAG_ARG(c, name, description) \
|
|
} \
|
|
if (kyaa_helping) { \
|
|
KYAA_DESCRIBE(c, name, description); \
|
|
} else if (kyaa_flag == c || !strcmp(kyaa_arg, "--"name)) { \
|
|
if (kyaa_no_more || kyaa_flag != c) { \
|
|
kyaa_parse_next = true; \
|
|
if (KYAA_ITER + 1 == argc || argv[KYAA_ITER + 1][0] == '\0') { \
|
|
fprintf(stderr, "expected an argument for --%s (-%c)\n", name, c); \
|
|
return KYAA_ERROR; \
|
|
} \
|
|
kyaa_flag = c; \
|
|
continue; \
|
|
} \
|
|
kyaa_flag = c; \
|
|
kyaa_any = true; \
|
|
|
|
#define KYAA_FLAG_LONG(c, name, description) \
|
|
KYAA_FLAG_ARG(c, name, description) \
|
|
errno = 0; \
|
|
long kyaa_flag_arg = strtol(kyaa_etc, NULL, 0); \
|
|
if (errno) { \
|
|
perror(NULL); \
|
|
return KYAA_ERROR; \
|
|
} \
|
|
|
|
#define KYAA_HELP(description) \
|
|
} \
|
|
if (kyaa_helping) { \
|
|
if (description != NULL) { \
|
|
printf("%s\n", description); \
|
|
} \
|
|
|