From 95e076c55f4edec07636f903f87e92440a5f61bf Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 15 Dec 2020 12:07:01 -0500 Subject: [PATCH] implemented basic parsing of long options --- inc/liba.h | 2 +- lib/a/gc.c | 2 +- lib/a/options.c | 3 ++ lib/a/opts_parse.c | 110 ++++++++++++++++++++++++++++++++++++++++- lib/a/opts_printhelp.c | 5 ++ tools/build.c | 9 ++-- 6 files changed, 121 insertions(+), 10 deletions(-) create mode 100644 lib/a/options.c diff --git a/inc/liba.h b/inc/liba.h index 52e3867..68d4039 100644 --- a/inc/liba.h +++ b/inc/liba.h @@ -35,7 +35,7 @@ */ /* rename user's main routine so GC is auto-initialized and options parsed */ -extern int usermain(int, char**); +extern int usermain(int argc, char** argv); #define main usermain /* diff --git a/lib/a/gc.c b/lib/a/gc.c index b60578d..5c0699d 100644 --- a/lib/a/gc.c +++ b/lib/a/gc.c @@ -87,7 +87,7 @@ void gc_delref(void* p) int main(int argc, char** argv) { - (void)argc, (void)argv; + opts_parse(argc, argv); Stack_Bot = &(intptr_t){0}; Log.index = 0; hash_init(&ZCT,0); diff --git a/lib/a/options.c b/lib/a/options.c new file mode 100644 index 0000000..edc18c8 --- /dev/null +++ b/lib/a/options.c @@ -0,0 +1,3 @@ +#include + +Option_T Options[] = { {0,0} }; \ No newline at end of file diff --git a/lib/a/opts_parse.c b/lib/a/opts_parse.c index b446747..1e18855 100644 --- a/lib/a/opts_parse.c +++ b/lib/a/opts_parse.c @@ -1,7 +1,113 @@ #include +static OptionDescriptor_T* lookup_opt(int optc, OptionDescriptor_T* optv, char* flag) +{ + OptionDescriptor_T* opt = NULL; + + for (int i = 0; i < optc; i++) + { + int match = ( + (flag[1] && !strcmp(optv[i].lname, flag)) + || (!flag[1] && flag[0] == optv[i].sname) + ); + if (match) + { + opt = &optv[i]; + break; + } + } + + return opt; +} + +static void parse_longopt(int optc, OptionDescriptor_T* optv, int* currp, char** argv) +{ + /* get the option and the arg if there is one */ + char* flag = argv[*currp] + 2; + char* split = strchr(flag, '='); + char* arg = NULL; + if (split) + { + *split = '\0'; + arg = split+1; + } + + OptionDescriptor_T* od = lookup_opt(optc, optv, flag); + if (!od) + { + fatal("unknown option: '%s'", flag); + } + else if (arg && !od->hasarg) + { + fatal("unexpected argument to option: --%s=%s", flag, arg); + } + else + { + if (od->hasarg && !arg) + { + *currp += 1; + arg = argv[*currp]; + if (!arg) + { + fatal("expected argument for option: '%s'", flag); + } + } + printf("handled option: '--%s=%s'\n", flag, arg); + } + + /* now repair the split if we made one */ + if (split && *split) + { + *split = '='; + } + *currp += 1; +} + +static void parse_shortopt(int optc, OptionDescriptor_T* optv, int* currp, char** argv) +{ + (void)optc, (void)optv; + printf("short: %s\n", argv[*currp]); + *currp += 1; +} + void opts_parse(int argc, char** argv) { - (void)argc; - (void)argv; + /* parse the option descriptors for easy usage during parsing */ + int capacity = 32; + int optc = 1; + OptionDescriptor_T* optv = malloc(capacity * sizeof(OptionDescriptor_T)); + opts_parsespec("h,help", optv); + for (Option_T* curr = Options; curr->name; curr++) + { + if (optc == capacity) + { + capacity <<= 1; + optv = realloc(optv, capacity * sizeof(OptionDescriptor_T)); + } + opts_parsespec(curr->name, &optv[optc]); + optc++; + } + + /* Record the program name */ + ARGV0 = argv[0]; + + /* now parse the arguments */ + for (int i = 1; i < argc;) + { + if (argv[i][0] == '-' && argv[i][1] == '-') + { + parse_longopt(optc, optv, &i, argv); + } + else if (argv[i][0] == '-') + { + parse_shortopt(optc, optv, &i, argv); + } + else + { + printf("posarg: %s\n", argv[i]); + i++; + } + } + + free(optv); } diff --git a/lib/a/opts_printhelp.c b/lib/a/opts_printhelp.c index 5b8096a..20f1d89 100644 --- a/lib/a/opts_printhelp.c +++ b/lib/a/opts_printhelp.c @@ -1,5 +1,10 @@ #include +/* + TODO: + * Print -h, --help in the help output +*/ + void opts_printhelp(void) { Option_T* opts = Options; diff --git a/tools/build.c b/tools/build.c index cdb0721..54927f3 100644 --- a/tools/build.c +++ b/tools/build.c @@ -27,7 +27,7 @@ char* CCCMD[] = { "-I/usr/X11/include/", "-I/usr/X11/include/freetype2", "-I/usr/include/freetype2/", - "-c", "-o", + "-g", "-c", "-o", /* output */ /* inputs */ NULL @@ -42,7 +42,7 @@ char* LDCMD[] = { "cc", "-L./build/lib", "-L/usr/X11/lib/", - "-o", + "-g", "-o", /* output */ /* inputs */ /* LIBS */ @@ -219,7 +219,6 @@ int should_rebuild(char** outputs, char** inputs) void object(Target* tgt) { - printf("Object %s\n", tgt->outputs[0]); char** cmd = make_cmd((char**[]){ CCCMD, tgt->outputs, tgt->inputs, NULL }); print_cmd(cmd); make_dirs(tgt->outputs); @@ -228,7 +227,6 @@ void object(Target* tgt) void library(Target* tgt) { - printf("Library %s\n", tgt->outputs[0]); char** cmd = make_cmd((char**[]){ ARCMD, tgt->outputs, tgt->inputs, NULL }); print_cmd(cmd); exit(execvp(cmd[0], cmd)); @@ -236,7 +234,6 @@ void library(Target* tgt) void binary(Target* tgt) { - printf("Binary %s\n", tgt->outputs[0]); char** cmd = make_cmd((char**[]){ LDCMD, tgt->outputs, tgt->inputs, LIBS, NULL }); print_cmd(cmd); @@ -327,7 +324,7 @@ void build_targets(Target* targets) int pid = fork(); if (pid == 0) { - if (should_rebuild(targets->outputs, targets->inputs)) + if (targets->build == binary || should_rebuild(targets->outputs, targets->inputs)) { targets->build(targets); } -- 2.52.0