#include "arg.h" #include "dbg.h" #include #include #include struct arg { const char *s; int (*f)(struct args *, const char *); enum { NOVAL, SPACEVAL = 1, EQVAL = 1 << 1, JOINVAL = 1 << 2 } v; }; static int debug(struct args *a, const char *arg) { dbgen = 1; return 0; } static int inc(struct args *a, const char *arg) { struct arg_input *i = &a->incs; size_t n = i->n + 1; const char **v = realloc(i->v, n * sizeof *v); if (!v) { perror("realloc(3)"); return -1; } v[i->n++] = arg; i->v = v; return 0; } static int opt(struct args *args, const struct arg *a, const char *arg) { const struct arg *prev = args->arg; const char *v = arg + strlen(a->s); if (prev && prev->v) { fprintf(stderr, "%s: option '%s' requires a value\n", args->name, prev->s); return -1; } else if (*v) { if (!(a->v & JOINVAL)) { fprintf(stderr, "%s: unrecognized command-line option '%s'\n", args->name, arg); return -1; } } else if (a->v & SPACEVAL) { args->arg = a; return 0; } else v = NULL; return a->f(args, v); } int arg(struct args *a, const char *value) { static const struct arg args[] = { {"-d", debug}, {"-I", inc, SPACEVAL | JOINVAL} }; const struct arg *prev = a->arg; for (size_t i = 0; i < sizeof args / sizeof *args; i++) { const struct arg *arg = &args[i]; if (!strncmp(value, arg->s, strlen(arg->s))) return opt(a, arg, value); } if (prev) { if (*value != '-' && prev->f(a, value)) return -1; a->arg = NULL; } else if (a->src) { fprintf(stderr, "%s: only one source file allowed\n", a->name); return -1; } else a->src = value; return 0; } void arg_defaults(struct args *a) { } static void free_input(struct arg_input *i) { free(i->v); } void arg_free(struct args *a) { free_input(&a->incs); }