super hacky macro hacks for parsing arguments in C
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

kyaa.h 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /* kyaa.h - macro hacks for handling main() arguments
  2. This is free and unencumbered software released into the public domain.
  3. For more information, please refer to <http://unlicense.org>
  4. */
  5. #ifndef KYAA_ONCE
  6. #define KYAA_ONCE
  7. /* set some sane defaults. */
  8. #ifndef KYAA_OKAY
  9. #define KYAA_OKAY 0
  10. #endif
  11. #ifndef KYAA_FAIL
  12. #define KYAA_FAIL 1
  13. #endif
  14. #ifndef KYAA_OUT
  15. #define KYAA_OUT(...) printf(__VA_ARGS__)
  16. #endif
  17. #ifndef KYAA_ERR
  18. #define KYAA_ERR(...) fprintf(stderr, __VA_ARGS__)
  19. #endif
  20. #define KYAA_IS_LONG(arg, name) \
  21. (strncmp(arg, "--" name, strlen("--" name)) == 0 && \
  22. (arg[strlen("--" name)] == '\0' || arg[strlen("--" name)] == '='))
  23. #define KYAA_SETUP \
  24. if (argc <= 0 || argv == NULL || argv[0] == NULL) { \
  25. KYAA_ERR("malformed argc/argv\n"); \
  26. return KYAA_FAIL; \
  27. } \
  28. const char *kyaa_name = argv[0]; \
  29. bool kyaa_read_stdin = false; \
  30. char kyaa_char = '\0'; \
  31. bool kyaa_parsing = true; \
  32. bool kyaa_skip = false; \
  33. #define KYAA_LOOP \
  34. KYAA_SETUP \
  35. for (int kyaa_iter = 1; kyaa_iter < argc; kyaa_iter++) \
  36. #define KYAA_BEGIN \
  37. const char *kyaa_arg = argv[kyaa_iter]; \
  38. if (kyaa_parsing && (kyaa_skip || kyaa_arg[0] == '-')) { \
  39. if (!kyaa_skip && kyaa_arg[1] == '-' && kyaa_arg[2] == '\0') { \
  40. kyaa_parsing = false; \
  41. continue; \
  42. } \
  43. if (!kyaa_skip && kyaa_arg[1] == '\0') kyaa_read_stdin = true; \
  44. else { \
  45. /* case: kyaa_skip: kyaa_arg is at least 1 char long. */ \
  46. /* case: !kyaa_skip: kyaa_arg is at least 3 chars long. */ \
  47. const char *kyaa_etc = kyaa_skip ? kyaa_arg : kyaa_arg + 2; \
  48. const char *kyaa_equals = kyaa_skip ? NULL : strchr(kyaa_etc, '='); \
  49. bool kyaa_helping = false; \
  50. bool kyaa_any = false; \
  51. if (!kyaa_skip) { \
  52. if (kyaa_arg[1] != '-') { \
  53. kyaa_char = kyaa_arg[1]; \
  54. if (kyaa_arg[2] == '\0') kyaa_etc = NULL; \
  55. } else if (kyaa_equals == NULL) kyaa_etc = NULL; \
  56. else kyaa_etc = kyaa_equals + 1; \
  57. if (strcmp(kyaa_arg, "--help") == 0) kyaa_char = 'h'; \
  58. if (kyaa_char == 'h') { \
  59. KYAA_OUT("usage:\n"); \
  60. kyaa_helping = true; \
  61. } \
  62. } \
  63. if (0) { \
  64. #define KYAA_END \
  65. } \
  66. if (!kyaa_any && !kyaa_helping) { \
  67. if (kyaa_char) KYAA_ERR("unknown flag: -%c\n", kyaa_char); \
  68. else KYAA_ERR("unknown flag: %s\n", kyaa_arg); \
  69. return KYAA_FAIL; \
  70. } \
  71. if (kyaa_helping) { \
  72. return KYAA_OKAY; \
  73. } \
  74. kyaa_skip = false; \
  75. kyaa_char = '\0'; \
  76. continue; \
  77. } \
  78. } \
  79. #define KYAA_DESCRIBE(c, name, description) \
  80. KYAA_OUT(" -%c --%s\n%s\n", c, name, description) \
  81. #define KYAA_FLAG(c, name, description) \
  82. } \
  83. if (kyaa_helping) KYAA_DESCRIBE(c, name, description); \
  84. else if (kyaa_char == c || KYAA_IS_LONG(kyaa_arg, name)) { \
  85. kyaa_char = c; \
  86. kyaa_any = true; \
  87. #define KYAA_FLAG_ARG(c, name, description) \
  88. } \
  89. if (kyaa_helping) KYAA_DESCRIBE(c, name, description); \
  90. else if (kyaa_char == c || KYAA_IS_LONG(kyaa_arg, name)) { \
  91. if (kyaa_etc == NULL) { \
  92. kyaa_skip = true; \
  93. if (kyaa_iter + 1 == argc || argv[kyaa_iter + 1] == NULL) { \
  94. KYAA_ERR("expected an argument for --%s (-%c)\n", name, c); \
  95. return KYAA_FAIL; \
  96. } \
  97. kyaa_char = c; \
  98. continue; \
  99. } \
  100. kyaa_char = c; \
  101. kyaa_any = true; \
  102. #define KYAA_HELP(description) \
  103. } \
  104. if (kyaa_helping) { \
  105. if (description != NULL) KYAA_OUT("%s\n", description); \
  106. #endif /* KYAA_ONCE */