/* we're only targeting unixes */
#include <unistd.h>
-/* This variable contains the value of argv[0] so that it can be referenced
- * again once the option parsing is done. This variable must be defined by the
- * program. */
-extern char* ARGV0;
-
-/* Option Parsing
- *******************************************************************************
- * This following macros implement a simple POSIX-style option parsing strategy.
- * They are heavily influenced and inspired by the arg.h file from suckless.org
- * (http://git.suckless.org/libsl/tree/arg.h). That file is in turn inspired by
- * the corresponding macros defined in plan9 libc.h.
- *
- * The interface assumes that the main function will have the following
- * prototype:
- *
- * int main(int argc, char** argv);
- *
- * An example usage of the interface would look something like the follwoing:
- *
- * char* ARGV0;
- * int main(int argc, char** argv) {
- * OPTBEGIN {
- * case 'a': printf("Simple option\n"); break;
- * case 'b': printf("Option with arg: %s\n", OPTARG()); break;
- * default: printf("Unknown option!\n");
- * } OPTEND;
- * return 0;
- * }
- */
-
-/* This is a helper function used by the following macros to parse the next
- * option from the command line. */
-static inline char* _getopt_(int* p_argc, char*** p_argv) {
- if (!(*p_argv)[0][1] && !(*p_argv)[1]) {
- return (char*)0;
- } else if ((*p_argv)[0][1]) {
- return &(*p_argv)[0][1];
- } else {
- *p_argv = *p_argv + 1;
- *p_argc = *p_argc - 1;
- return (*p_argv)[0];
- }
-}
-
-/* This macro is almost identical to the ARGBEGIN macro from suckless.org. If
- * it ain't broke, don't fix it. */
-#define OPTBEGIN \
- for ( \
- ARGV0 = *argv, argc--, argv++; \
- argv[0] && argv[0][1] && argv[0][0] == '-'; \
- argc--, argv++ \
- ) { \
- int brk_; char argc_ , **argv_, *optarg_; \
- if (argv[0][1] == '-' && !argv[0][2]) { \
- argv++, argc--; break; \
- } \
- for (brk_=0, argv[0]++, argv_=argv; argv[0][0] && !brk_; argv[0]++) { \
- if (argv_ != argv) break; \
- argc_ = argv[0][0]; \
- switch (argc_)
-
-/* Terminate the option parsing. */
-#define OPTEND }}
-
-/* Get the current option character */
-#define OPTC() (argc_)
-
-/* Get an argument from the command line and return it as a string. If no
- * argument is available, this macro returns NULL */
-#define OPTARG() \
- (optarg_ = _getopt_(&argc,&argv), brk_ = (optarg_!=0), optarg_)
-
-/* Get an argument from the command line and return it as a string. If no
- * argument is available, this macro executes the provided code. If that code
- * returns, then abort is called. */
-#define EOPTARG(code) \
- (optarg_ = _getopt_(&argc,&argv), \
- (!optarg_ ? ((code), abort(), (char*)0) : (brk_ = 1, optarg_)))
-
-/* Helper macro to recognize number options */
-#define OPTNUM \
- case '0': \
- case '1': \
- case '2': \
- case '3': \
- case '4': \
- case '5': \
- case '6': \
- case '7': \
- case '8': \
- case '9'
-
-/* Helper macro to recognize "long" options ala GNU style. */
-#define OPTLONG \
- case '-'
-
/* Miscellaneous Macros
******************************************************************************/
#ifndef nelem
(type*)((uintptr_t)obj - offsetof(type, member))
#endif
-#define concat(a,b) \
- a##b
-
-#define ident(a) \
- concat(id, a)
-
-#define unique_id \
- ident(__LINE__)
-
-#ifndef static_assert
- #define static_assert(expr) \
- typedef char unique_id[( expr )?1:-1]
-#endif
-
+/*
+ Basic Runtime Facilities
+*/
/* rename user's main routine so GC is auto-initialized */
extern int usermain(int, char**);
#define main usermain
+/* This variable contains the value of argv[0] so that it can be referenced
+ * again once the option parsing is done. This variable must be defined by the
+ * program. */
+extern char* ARGV0;
+
void* gc_alloc(size_t sz);
void gc_addref(void* p);
void gc_delref(void* p);
+typedef struct {
+ char* name;
+ char* desc;
+} Option_T;
+
+/*
+ { .name = "v" } // Error
+ { .name = "v," }
+ { .name = ",foo" }
+ { .name = "b,bar" }
+ { .name = ":b,bar" }
+ { .name = ":,bar" }
+ { .name = ":b," }
+*/
+
+extern Option_T Options[];
+
+void opts_parse(int argc, char** argv);
+
+/*
+ Standard Library Helpers
+*/
void fatal(const char* fmt, ...);
void warn(const char* fmt, ...);
void esignal(int sig, void (*func)(int));