From: Michael D. Lowis Date: Wed, 15 Dec 2021 18:21:02 +0000 (-0500) Subject: reworked option parsing to get rid of malloc and work off of static array X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=eef6631aaeb1ae22c971b3d0663b2e8280be3b01;p=proto%2Faos.git reworked option parsing to get rid of malloc and work off of static array --- diff --git a/bin/dial.c b/bin/dial.c index 16d8430..21bd61b 100644 --- a/bin/dial.c +++ b/bin/dial.c @@ -2,6 +2,14 @@ #include #include +char* Usage = "dial [OPTIONS] DIALSTR [CMD [ARG...]]"; + +//void set_option(int sname, char* lname, char* arg) +//{ +// +//} + + int copy_data(int fromfd, int tofd, int events) { char buf[16384]; @@ -32,40 +40,42 @@ int copy_data(int fromfd, int tofd, int events) int main(int argc, char** argv) { - if (argc < 2) - { - fprintf(stderr, "usage: dial DIALSTR [CMD [ARG...]]\n"); - return 1; - } - - int running = 1; - int sockfd = netdial(argv[1]); - int cmdinfd = STDIN_FILENO; - int cmdoutfd = STDOUT_FILENO; - if (argc > 2) - { - cmdinfd = forkexec(&argv[2]); - cmdoutfd = cmdinfd; - if (cmdinfd < 0) - { - fatal("forkexec():"); - } - } + (void)argc, (void)argv; - while (running) - { - struct pollfd fds[] = { - { .fd = sockfd, .events = POLLIN }, - { .fd = cmdinfd, .events = POLLIN }, - }; - if (poll(fds, nelem(fds), -1) < 0) - { - fatal("poll():"); - } - running = running && copy_data(sockfd, cmdoutfd, fds[0].revents); - running = running && copy_data(cmdinfd, sockfd, fds[1].revents); - } - close(sockfd); +// if (argc < 2) +// { +// fprintf(stderr, "usage: dial DIALSTR [CMD [ARG...]]\n"); +// return 1; +// } +// +// int running = 1; +// int sockfd = netdial(argv[1]); +// int cmdinfd = STDIN_FILENO; +// int cmdoutfd = STDOUT_FILENO; +// if (argc > 2) +// { +// cmdinfd = forkexec(&argv[2]); +// cmdoutfd = cmdinfd; +// if (cmdinfd < 0) +// { +// fatal("forkexec():"); +// } +// } +// +// while (running) +// { +// struct pollfd fds[] = { +// { .fd = sockfd, .events = POLLIN }, +// { .fd = cmdinfd, .events = POLLIN }, +// }; +// if (poll(fds, nelem(fds), -1) < 0) +// { +// fatal("poll():"); +// } +// running = running && copy_data(sockfd, cmdoutfd, fds[0].revents); +// running = running && copy_data(cmdinfd, sockfd, fds[1].revents); +// } +// close(sockfd); return 0; } \ No newline at end of file diff --git a/bin/edit.c b/bin/edit.c index 3ea9348..3db827f 100644 --- a/bin/edit.c +++ b/bin/edit.c @@ -1,14 +1,16 @@ #include char* Usage = "edit [FLAGS...] [FILES...]"; + Option_T Options[] = { - { "v,verbose", "enable verbose mode" }, - { ":f,flag", "flag with an arg" }, - { "F,noflag", "flag without an arg" }, - { "a,noflag", "flag without an arg" }, - { "b,noflag", "flag without an arg" }, - { "c,noflag", "flag without an arg" }, - { 0, 0 } + { .s = 'h', .l = "help", .a = 0, .d = "print this help message" }, + { .s = 'v', .l = "verbose", .a = 0, .d = "enable verbose mode" }, + { .s = 'f', .l = "flag", .a = 1, .d = "flag with an arg" }, + { .s = 'F', .l = "noflag", .a = 0, .d = "flag without an arg" }, + { .s = 'a', .l = "noflag", .a = 0, .d = "flag without an arg" }, + { .s = 'b', .l = "noflag", .a = 0, .d = "flag without an arg" }, + { .s = 'c', .l = "noflag", .a = 0, .d = "flag without an arg" }, + {0} }; int main(int argc, char** argv) diff --git a/inc/liba.h b/inc/liba.h index f417a7c..3e9fbd1 100644 --- a/inc/liba.h +++ b/inc/liba.h @@ -41,20 +41,20 @@ void gc_delref(void* p); Option Parsing */ typedef struct { - char* name; - char* desc; + char* l; + char* d; + char s; + int a : 1; } Option_T; -typedef struct { - char* lname; - char sname; - int hasarg : 1; -} OptionDescriptor_T; - void opts_parse(int argc, char** argv); -void opts_parsespec(char* spec, OptionDescriptor_T* opt); +void opts_parsespec(char* spec, Option_T* opt); void opts_printhelp(void); +//void Options_Parse(int argc, char** argv); +//void Options_ParseSpec(char* spec, Option_T* opt); +//void Options_PrintHelp(void); + /* Standard Library Helpers */ diff --git a/lib/a/options.c b/lib/a/options.c index edc18c8..e23d738 100644 --- a/lib/a/options.c +++ b/lib/a/options.c @@ -1,3 +1,3 @@ #include -Option_T Options[] = { {0,0} }; \ No newline at end of file +Option_T Options[] = { {0} }; \ No newline at end of file diff --git a/lib/a/opts_parse.c b/lib/a/opts_parse.c index 71c2924..942ffa9 100644 --- a/lib/a/opts_parse.c +++ b/lib/a/opts_parse.c @@ -1,32 +1,32 @@ #include -static void handle_option(int sname, char* lname, char* arg) +static void handle_option(int s, char* l, char* arg) { - if (sname == 'h') + if (s == 'h') { opts_printhelp(); exit(1); } else { - printf(" --%s=%s\n", lname, arg); - set_option(sname, lname, arg); + printf(" --%s=%s\n", l, arg); + set_option(s, l, arg); } } -static OptionDescriptor_T* lookup_opt(int optc, OptionDescriptor_T* optv, char* flag) +static Option_T* lookup_opt(char* flag) { - OptionDescriptor_T* opt = NULL; + Option_T* opt = NULL; - for (int i = 0; i < optc; i++) + for (int i = 0; Options[i].s || Options[i].l; i++) { int match = ( - (flag[1] && !strcmp(optv[i].lname, flag)) - || (!flag[1] && flag[0] == optv[i].sname) + (flag[1] && !strcmp(Options[i].l, flag)) + || (!flag[1] && flag[0] == Options[i].s) ); if (match) { - opt = &optv[i]; + opt = &Options[i]; break; } } @@ -34,7 +34,7 @@ static OptionDescriptor_T* lookup_opt(int optc, OptionDescriptor_T* optv, char* return opt; } -static void parse_longopt(int optc, OptionDescriptor_T* optv, int* currp, char** argv) +static inline void parse_longopt(int* currp, char** argv) { /* get the option and the arg if there is one */ char* flag = argv[*currp] + 2; @@ -46,18 +46,18 @@ static void parse_longopt(int optc, OptionDescriptor_T* optv, int* currp, char** arg = split+1; } - OptionDescriptor_T* od = lookup_opt(optc, optv, flag); + Option_T* od = lookup_opt(flag); if (!od) { fatal("unknown option: '%s'", flag); } - else if (arg && !od->hasarg) + else if (arg && !od->a) { fatal("unexpected argument to option: --%s=%s", flag, arg); } else { - if (od->hasarg && !arg) + if (od->a && !arg) { *currp += 1; arg = argv[*currp]; @@ -67,7 +67,7 @@ static void parse_longopt(int optc, OptionDescriptor_T* optv, int* currp, char** } } printf("handled option: '--%s=%s'\n", flag, arg); - handle_option(od->sname, od->lname, arg); + handle_option(od->s, od->l, arg); } /* now repair the split if we made one */ @@ -78,7 +78,7 @@ static void parse_longopt(int optc, OptionDescriptor_T* optv, int* currp, char** *currp += 1; } -static void parse_shortopt(int optc, OptionDescriptor_T* optv, int* currp, char** argv) +static inline void parse_shortopt(int* currp, char** argv) { char* argstr = argv[*currp]+1; char flag[] = "\0\0"; @@ -86,18 +86,18 @@ static void parse_shortopt(int optc, OptionDescriptor_T* optv, int* currp, char* { /* get the flag and the possible argument */ flag[0] = *argstr; - OptionDescriptor_T* od = lookup_opt(optc, optv, flag); + Option_T* od = lookup_opt(flag); if (!od) { fatal("unknown option: '%s'", flag); } - else if (od->hasarg) + else if (od->a) { char* arg = argstr+1; if (*arg != '\0') { arg += (*arg == '=' ? 1 : 0); - handle_option(od->sname, od->lname, arg); + handle_option(od->s, od->l, arg); break; } else if (!*arg) @@ -107,7 +107,7 @@ static void parse_shortopt(int optc, OptionDescriptor_T* optv, int* currp, char* { fatal("expected argument for option: '%s'", flag); } - set_option(od->sname, od->lname, arg); + handle_option(od->s, od->l, arg); *currp += 1; break; } @@ -118,7 +118,7 @@ static void parse_shortopt(int optc, OptionDescriptor_T* optv, int* currp, char* } else { - set_option(od->sname, od->lname, NULL); + handle_option(od->s, od->l, NULL); } } *currp += 1; @@ -126,22 +126,6 @@ static void parse_shortopt(int optc, OptionDescriptor_T* optv, int* currp, char* void opts_parse(int argc, char** 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]; @@ -150,11 +134,11 @@ void opts_parse(int argc, char** argv) { if (argv[i][0] == '-' && argv[i][1] == '-') { - parse_longopt(optc, optv, &i, argv); + parse_longopt(&i, argv); } else if (argv[i][0] == '-') { - parse_shortopt(optc, optv, &i, argv); + parse_shortopt(&i, argv); } else { @@ -162,6 +146,54 @@ void opts_parse(int argc, char** argv) i++; } } +} - free(optv); +void opts_printhelp(void) +{ + /* calculate padding */ + size_t padding = 0; + for (int i = 0; Options[i].s || Options[i].l; i++) + { + size_t pad = 4; + if (Options[i].s) + { + pad += 2; + } + if (Options[i].l) + { + pad += (Options[i].s ? 2 : 0) + 2 + strlen(Options[i].l); + } + if (Options[i].a) + { + pad += 4; + } + if (pad > padding) + { + padding = pad; + } + } + + if (Usage) + { + printf("usage: %s\n\n", Usage); + } + + /* print option help messages */ + for (int i = 0; Options[i].s || Options[i].l; i++) + { + int remain = padding; + if (Options[i].s) + { + remain -= printf("-%c", Options[i].s); + } + if (Options[i].l) + { + remain -= printf("%s--%s", (Options[i].s ? ", " : ""), Options[i].l); + } + if (Options[i].a) + { + remain -= printf(" ARG"); + } + printf("%*c%s\n", remain, ' ', (Options[i].d ? Options[i].d : "")); + } } diff --git a/lib/a/opts_parsespec.c b/lib/a/opts_parsespec.c deleted file mode 100644 index 91c4d23..0000000 --- a/lib/a/opts_parsespec.c +++ /dev/null @@ -1,32 +0,0 @@ -#include - -void opts_parsespec(char* spec, OptionDescriptor_T* opt) -{ - char* fullspec = spec; - memset(opt, 0, sizeof(OptionDescriptor_T)); - - /* parse optional arg specifier */ - if (*spec == ':') - { - opt->hasarg = 1; - spec++; - } - - /* parse optional short name */ - if (*spec != ',') - { - opt->sname = *(spec++); - } - - /* we need a comma at a minimum and if no short name was parsed,a - long name must be provided. bail if we don't meet these constraints */ - if (*spec != ',' || (!opt->sname && spec[1] == '\0')) - { - fatal("opts_parsespec(): bad option specification '%s'", fullspec); - } - - if (*(++spec)) - { - opt->lname = spec; - } -} diff --git a/lib/a/opts_printhelp.c b/lib/a/opts_printhelp.c deleted file mode 100644 index ad03d5d..0000000 --- a/lib/a/opts_printhelp.c +++ /dev/null @@ -1,61 +0,0 @@ -#include - -/* - TODO: - * Print -h, --help in the help output -*/ - -void opts_printhelp(void) -{ - Option_T* opts = Options; - OptionDescriptor_T od = {0}; - size_t padding = 0; - - /* calculate padding */ - for (Option_T* curr = opts; curr->name; curr++) - { - size_t pad = 4; - opts_parsespec(curr->name, &od); - if (od.sname) - { - pad += 2; - } - if (od.lname) - { - pad += (od.sname ? 2 : 0) + 2 + strlen(od.lname); - } - if (od.hasarg) - { - pad += 4; - } - if (pad > padding) - { - padding = pad; - } - } - - if (Usage) - { - printf("usage: %s\n\n", Usage); - } - - /* print option help messages */ - for (Option_T* curr = opts; curr->name; curr++) - { - int remain = padding; - opts_parsespec(curr->name, &od); - if (od.sname) - { - remain -= printf("-%c", od.sname); - } - if (od.lname) - { - remain -= printf("%s--%s", (od.sname ? ", " : ""), od.lname); - } - if (od.hasarg) - { - remain -= printf(" ARG"); - } - printf("%*c%s\n", remain, ' ', (curr->desc ? curr->desc : "")); - } -}