summaryrefslogtreecommitdiff
path: root/src/args.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/args.c')
-rw-r--r--src/args.c342
1 files changed, 244 insertions, 98 deletions
diff --git a/src/args.c b/src/args.c
index 1b756d5..f995903 100644
--- a/src/args.c
+++ b/src/args.c
@@ -1,129 +1,275 @@
#include "../inc/args.h"
-#include "../inc/commands.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
-void parsecmdstr(cmdinput *cmd, char *cmdstr)
+typedef struct parg
{
- switch (cmd->settype)
+ argtype type;
+ char *flag;
+ char *full;
+ int numopt;
+ char *desc[2];
+ void (*runarg)(struct arg *);
+} parg;
+
+int argerr = 0;
+char *errflag = NULL;
+
+char *inf = NULL;
+char *usg = NULL;
+
+int PARGC = 0;
+int pargscap = 2;
+parg *PARGS = NULL;
+
+int ARGC = 0;
+int argscap = 2;
+arg *ARGS;
+
+void setinfo(char *info)
+{
+ inf = info;
+}
+
+void setusage(char *usage)
+{
+ usg = usage;
+}
+
+int addparg(argtype type, char *flag, char *full, int numopt, char *desc1, char *desc2, void (*runarg)(struct arg *))
+{
+ if (!PARGS)
+ PARGS = (parg *)malloc(pargscap * sizeof(parg));
+ else
{
- case 'i':
- if (sscanf(cmdstr, "%i:%23[^\n]", &cmd->id, cmd->to) != 2)
- {
- fprintf(stderr, "ERROR: Failed to parse argument '%s' to type 'ID:RESULT'\n", cmdstr);
- exit(EXIT_FAILURE);
- }
- break;
- case 'n':
- if (sscanf(cmdstr, "%23[^:]:%23[^\n]", cmd->from, cmd->to) != 2)
- {
- fprintf(stderr, "ERROR: Failed to parse argument '%s' to type 'NAME:RESULT'\n", cmdstr);
- exit(EXIT_FAILURE);
- }
- break;
- case '\0':
- fprintf(stderr, "ERROR: Found no flag modifier\n");
- exit(EXIT_FAILURE);
- break;
- default:
- fprintf(stderr, "ERROR: Failed to parse flag with '%c' modifier\n", cmd->settype);
- exit(EXIT_FAILURE);
- break;
+ pargscap *= 2;
+ PARGS = (parg *)realloc(PARGS, pargscap * sizeof(parg));
}
+ PARGS[PARGC].type = type;
+ PARGS[PARGC].flag = flag;
+ PARGS[PARGC].full = full;
+ PARGS[PARGC].numopt = numopt;
+ PARGS[PARGC].desc[0] = desc1;
+ PARGS[PARGC].desc[1] = desc2;
+ PARGS[PARGC].runarg = runarg;
+ PARGC++;
+
+ return 1;
}
-void parseargs(input *in, int argc, char *argv[])
+int addarg(char *value, char *desc, void (*runarg)(struct arg *))
{
- in->demopath = NULL;
- in->mappath = NULL;
- in->outpath = NULL;
- in->print = 0;
- in->extractmap = 0;
+ if (!value || !desc)
+ return 0;
+ addparg(ARGUMENT, NULL, NULL, 0, value, desc, runarg);
+ return 1;
+}
+
+int addopt(char *flag, char *full, int numopt, char *value, char *desc, void (*runarg)(struct arg *))
+{
+ if (!flag || !desc)
+ return 0;
+ addparg(OPTION, flag, full, numopt, value, desc, runarg);
+ return 1;
+}
+
+int checkarg(char *str, parg *par)
+{
+ if (par->flag && strcmp(str, par->flag) == 0)
+ return 1;
+
+ if (par->full && strcmp(str, par->full) == 0)
+ return 1;
+
+ return 0;
+}
+
+int parseargs(int argc, char *args[])
+{
+ ARGS = (arg *)malloc(argscap * sizeof(arg));
- in->numcmds = 0;
+ char inctype[] = {0, 0, 0};
+ for (int i = 0; i < PARGC; i++)
+ inctype[PARGS[i].type]++;
- int argi;
- for (argi = 1; argi < argc; argi++)
+ int argumentc = 0;
+
+ for (int i = 1; i < argc; i++)
{
- if (argv[argi][0] == '-')
+ char *a = args[i];
+ char isopt = 0;
+ for (int y = 0; y < PARGC; y++)
{
- cmdinput *cmd = &in->commands[in->numcmds];
- switch (argv[argi][1])
+ parg *pa = &PARGS[y];
+ if (checkarg(a, pa))
{
- case 'n':
- if (argi + 1 >= argc)
- {
- fprintf(stderr, "ERROR: Flag 'n' requires additional argument\n");
- exit(EXIT_FAILURE);
- }
- cmd->cmdtype = argv[argi][1];
- cmd->settype = argv[argi][2];
- parsecmdstr(cmd, argv[argi + 1]);
- in->numcmds++;
- argi++;
- break;
- case 's':
- if (argi + 1 >= argc)
+ if (i + pa->numopt >= argc)
{
- fprintf(stderr, "ERROR: Flag 's' requires additional argument\n");
- exit(EXIT_FAILURE);
+ argerr = 1;
+ errflag = pa->flag;
+ return 0;
}
- cmd->cmdtype = argv[argi][1];
- cmd->settype = argv[argi][2];
- parsecmdstr(cmd, argv[argi + 1]);
- in->numcmds++;
- argi++;
- break;
- case 'o':
- if (argi + 1 >= argc)
+ isopt = 1;
+ if (argscap >= ARGC)
{
- fprintf(stderr, "ERROR: Flag 'o' requires additional argument\n");
- exit(EXIT_FAILURE);
+ argscap *= 2;
+ ARGS = (arg *)realloc(ARGS, argscap * sizeof(arg));
}
- in->outpath = argv[argi + 1];
- argi++;
- break;
- case 'p':
- in->print = 1;
- break;
- case 'e':
- if (argi + 1 >= argc)
- {
- fprintf(stderr, "ERROR: Flag 'e' requires additional argument\n");
- exit(EXIT_FAILURE);
- }
- in->extractmap = argv[argi + 1];
- argi++;
- break;
- case 'm':
- if (argi + 1 >= argc)
+ ARGS[ARGC].type = pa->type;
+ ARGS[ARGC].flag = a;
+ ARGS[ARGC].numopt = pa->numopt;
+ ARGS[ARGC].runarg = pa->runarg;
+ ARGS[ARGC].opts = (char **)malloc(pa->numopt * sizeof(char *));
+
+ for (int j = 0; j < pa->numopt; j++)
+ ARGS[ARGC].opts[j] = args[i + j + 1];
+
+ i += pa->numopt;
+ ARGC++;
+ }
+ }
+ if (isopt)
+ continue;
+
+ if (argumentc < inctype[ARGUMENT])
+ {
+ ARGS[ARGC].type = ARGUMENT;
+ for (int y = 0, x = argumentc; y < PARGC; y++)
+ {
+ if (PARGS[y].type == ARGUMENT)
{
- fprintf(stderr, "ERROR: Flag 'm' requires additional argument\n");
- exit(EXIT_FAILURE);
+ if (x != 0)
+ x--;
+ else
+ {
+ ARGS[ARGC].numopt = 1;
+ ARGS[ARGC].flag = "NONE";
+ ARGS[ARGC].runarg = PARGS[y].runarg;
+ ARGS[ARGC].opts = (char **)malloc(sizeof(char *));
+ ARGS[ARGC].opts[0] = a;
+ argumentc++;
+ ARGC++;
+ }
}
- in->mappath = argv[argi + 1];
- argi++;
- break;
- default:
- fprintf(stderr, "ERROR: Unknown flag '%c'\n", argv[argi][1]);
- exit(EXIT_FAILURE);
- break;
}
}
else
{
- if (in->demopath)
- {
- fprintf(stderr, "ERROR: Found two non-flag arguments\n");
- exit(EXIT_FAILURE);
- }
- in->demopath = argv[argi];
+ argerr = 2;
+ errflag = NULL;
+ return 0;
}
}
- if (!in->demopath)
+ return 1;
+}
+
+void runargs()
+{
+ for (int i = 0; i < ARGC; i++)
+ {
+ if (ARGS[i].runarg)
+ ARGS[i].runarg(&ARGS[i]);
+ }
+}
+
+arg *getarg(int pos)
+{
+ for (int i = 0; i < ARGC; i++)
+ if (ARGS[i].type == ARGUMENT)
+ {
+ if (pos == 0)
+ return &ARGS[i];
+ pos--;
+ }
+ return NULL;
+}
+
+arg *getopt(char *flag, int pos)
+{
+ for (int i = 0; i < ARGC; i++)
+ if (ARGS[i].type == OPTION && strcmp(flag, ARGS[i].flag) == 0)
+ {
+ if (pos == 0)
+ return &ARGS[i];
+ pos--;
+ }
+ return NULL;
+}
+void printhelp()
+{
+ char inctype[ARGTYPELEN] = {0, 0, 0};
+ int maxflag[ARGTYPELEN] = {0, 0, 0};
+ int maxfull[ARGTYPELEN] = {0, 0, 0};
+ int maxdesc0[ARGTYPELEN] = {0, 0, 0};
+ int maxdesc1[ARGTYPELEN] = {0, 0, 0};
+
+ for (int i = 0; i < PARGC; i++)
{
- fprintf(stderr, "ERROR: Found no demo input\n");
- exit(EXIT_FAILURE);
+ parg *pa = &PARGS[i];
+ int type = pa->type;
+
+ inctype[type]++;
+ if (pa->flag)
+ maxflag[type] = (maxflag[type] > strlen(pa->flag) ? maxflag[type] : strlen(pa->flag));
+ if (pa->full)
+ maxfull[type] = (maxfull[type] > strlen(pa->full) ? maxfull[type] : strlen(pa->full));
+ if (pa->desc[0])
+ maxdesc0[type] = (maxdesc0[type] > strlen(pa->desc[0]) ? maxdesc0[type] : strlen(pa->desc[0]));
+ if (pa->desc[1])
+ maxdesc1[type] = (maxdesc1[type] > strlen(pa->desc[1]) ? maxdesc1[type] : strlen(pa->desc[1]));
+ }
+ if (inf)
+ printf("%s\n\n", inf);
+
+ if (usg)
+ printf("\e[4mUsage:\e[0m %s\n", usg);
+
+ if (inctype[ARGUMENT])
+ {
+ printf("\n\e[4mArgument%c:\e[0m\n", (inctype[ARGUMENT] < 2) ? '\0' : 's');
+ for (int i = 0; i < PARGC; i++)
+ {
+ parg *pa = &PARGS[i];
+ if (pa->type == ARGUMENT)
+ printf(" %s %s\n", pa->desc[0], pa->desc[1]);
+ }
+ }
+
+ if (inctype[OPTION])
+ {
+ printf("\n\e[4mOption%c:\e[0m\n", (inctype[OPTION] < 2) ? '\0' : 's');
+ for (int i = 0; i < PARGC; i++)
+ {
+ parg *pa = &PARGS[i];
+ if (pa->type == OPTION)
+ printf(" %*s, %-*s %-*s %s\n", maxflag[OPTION], pa->flag, maxfull[OPTION], pa->full, maxdesc0[OPTION],
+ (pa->desc[0]) ? pa->desc[0] : "", pa->desc[1]);
+ }
+ }
+}
+
+void paerror(char *str)
+{
+ char *errstr;
+ switch (argerr)
+ {
+ case 0:
+ errstr = "No error";
+ break;
+ case 1:
+ errstr = "Missing input for option flag";
+ break;
+ case 2:
+ errstr = "Too many positional arguments";
+ break;
+ default:
+ errstr = "Unknown error";
+ break;
}
+ if (errflag)
+ fprintf(stderr, "%s %s '%s'\n", str, errstr, errflag);
+ else
+ fprintf(stderr, "%s %s\n", str, errstr);
}