aboutsummaryrefslogtreecommitdiffstats
path: root/libsimple-arg.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libsimple-arg.h164
1 files changed, 164 insertions, 0 deletions
diff --git a/libsimple-arg.h b/libsimple-arg.h
new file mode 100644
index 0000000..d63a7ec
--- /dev/null
+++ b/libsimple-arg.h
@@ -0,0 +1,164 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBSIMPLE_ARG_H
+#define LIBSIMPLE_ARG_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+
+extern char *argv0;
+
+
+struct longopt {
+ const char *long_flag;
+ char short_flag;
+ int with_arg;
+};
+
+
+#define ARGBEGIN ARGBEGIN3(1, argc, argv)
+#define SUBARGBEGIN ARGBEGIN3(0, argc, argv)
+
+#define ARGBEGIN3(WITH_ARGV0, argc, argv)\
+ do {\
+ char flag_, *lflag_, *arg_;\
+ int brk_ = 0, again_;\
+ size_t i_, n_;\
+ if (WITH_ARGV0) {\
+ argv0 = *argv;\
+ argv += !!argv0;\
+ argc -= !!argv0;\
+ }\
+ for (; argv[0] && argv[0][0] && argv[0][1]; argc--, argv++) {\
+ lflag_ = argv[0];\
+ if (argv[0][0] == '-') {\
+ if (argv[0][1] == '-' && !argv[0][2]) {\
+ argv++, argc--;\
+ break;\
+ }\
+ for (argv[0]++; argv[0][0]; argv[0]++) {\
+ flag_ = argv[0][0];\
+ if (flag_ == '-' && &argv[0][-1] != lflag_)\
+ usage();\
+ arg_ = argv[0][1] ? &argv[0][1] : argv[1];\
+ do {\
+ again_ = 0;\
+ switch (flag_) {
+
+#define ARGMAPLONG(LONGOPTS)\
+ for (i_ = 0; (LONGOPTS)[i_].long_flag; i_++) {\
+ if (TESTLONG((LONGOPTS)[i_].long_flag, (LONGOPTS)[i_].with_arg)) {\
+ flag_ = (LONGOPTS)[i_].short_flag;\
+ again_ = 1;\
+ break;\
+ }\
+ }\
+ if (again_)\
+ break
+
+#define ARGALT(SYMBOL)\
+ }\
+ } while (again_);\
+ if (brk_) {\
+ argc -= arg_ == argv[1];\
+ argv += arg_ == argv[1];\
+ brk_ = 0;\
+ break;\
+ }\
+ }\
+ } else if (argv[0][0] == SYMBOL) {\
+ if (argv[0][1] == SYMBOL && !argv[0][2])\
+ break;\
+ for (argv[0]++; argv[0][0]; argv[0]++) {\
+ flag_ = argv[0][0];\
+ if (flag_ == SYMBOL && &argv[0][-1] != lflag_)\
+ usage();\
+ arg_ = argv[0][1] ? &argv[0][1] : argv[1];\
+ do {\
+ again_ = 0;\
+ switch (flag_) {
+
+#define ARGEND\
+ }\
+ } while (again_);\
+ if (brk_) {\
+ argc -= arg_ == argv[1];\
+ argv += arg_ == argv[1];\
+ brk_ = 0;\
+ break;\
+ }\
+ }\
+ } else {\
+ break;\
+ }\
+ }\
+ } while (0)
+
+
+#define ARGNUM '0': case '1': case '2': case '3': case '4':\
+ case '5': case '6': case '7': case '8': case '9'
+
+#define FLAG() (flag_)
+#define LFLAG() (lflag_)
+#define ARG() (arg_ ? (brk_ = 1, arg_) : (usage(), (char *)0))
+#define ARGHERE() (brk_ = 1, argv[0])
+
+
+#define NOFLAGS(...)\
+ do {\
+ if (*argv)\
+ argv0 = *argv++, argc--;\
+ if (argv[0] && argv[0][0] == '-' && argv[0][1] == '-' && !argv[0][2])\
+ argv++, argc--;\
+ else if (argv[0] && argv[0][0] == '-')\
+ usage();\
+ if (__VA_ARGS__)\
+ usage();\
+ } while (0)
+
+
+#define TESTLONG(FLG, WARG)\
+ ((WARG)\
+ ? ((!strncmp(lflag_, (FLG), n_ = strlen(FLG)) && lflag_[n_] == '=')\
+ ? (lflag_[n_] = '\0',\
+ (arg_ = &lflag_[n_ + 1]),\
+ (brk_ = 1))\
+ : (!strcmp(lflag_, (FLG))\
+ ? (argv[1]\
+ ? ((arg_ = argv[1]),\
+ (brk_ = 1))\
+ : (usage(), 0))\
+ : 0))\
+ : (!strcmp(lflag_, (FLG))\
+ ? (brk_ = 1)\
+ : 0))
+
+
+#define USAGE(SYNOPSIS)\
+ NUSAGE(1, SYNOPSIS)
+
+#if defined(__GNUC__) || defined(__clang__)
+# define NUSAGE(STATUS, SYNOPSIS)\
+ __attribute__((noreturn))\
+ static void usage(void)\
+ {\
+ const char *syn = SYNOPSIS ? SYNOPSIS : "";\
+ fprintf(stderr, "usage: %s%s%s\n", argv0, *syn ? " " : "", syn);\
+ exit(STATUS);\
+ }\
+ char *argv0
+#else
+# define NUSAGE(STATUS, SYNOPSIS)\
+ static void usage(void)\
+ {\
+ const char *syn = SYNOPSIS ? SYNOPSIS : "";\
+ fprintf(stderr, "usage: %s%s%s\n", argv0, *syn ? " " : "", syn);\
+ exit(STATUS);\
+ }\
+ char *argv0
+#endif
+
+
+#endif