aboutsummaryrefslogtreecommitdiff
path: root/src/prc1/arg.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi92@disroot.org>2026-09-26 23:30:40 +0200
committerXavier Del Campo Romero <xavi92@disroot.org>2026-09-27 23:57:29 +0200
commit204f6f332318056a9b950e71e4a958da0c10ea72 (patch)
tree5d7938d9ed44dbe9455d2a88b2ef93a4beef4397 /src/prc1/arg.c
parent88d1bca43a8412b285ea2dd54dfa98d08ecc7849 (diff)
downloadprc-204f6f332318056a9b950e71e4a958da0c10ea72.tar.gz
prc1: Rework arg handling + dbg
Diffstat (limited to 'src/prc1/arg.c')
-rw-r--r--src/prc1/arg.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/prc1/arg.c b/src/prc1/arg.c
new file mode 100644
index 0000000..f61bca7
--- /dev/null
+++ b/src/prc1/arg.c
@@ -0,0 +1,123 @@
+#include "arg.h"
+#include "dbg.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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);
+}