shithub: mc

Download patch

ref: 87b4515f7e065029ec88eca6f6133f53223def8a
parent: a8359030735219db18bc48b4e481c67ad6e48484
author: Ori Bernstein <[email protected]>
date: Sun Oct 5 11:24:10 EDT 2014

Write my own option parsing.

    getopt() isn't really portable: it has different and annoying
    behaviors on OSX, and doesn't actually exist on plan9.

--- a/6/main.c
+++ b/6/main.c
@@ -120,14 +120,16 @@
 
 int main(int argc, char **argv)
 {
-    int opt;
-    int i;
-    Stab *globls;
     char buf[1024];
-    while ((opt = getopt(argc, argv, "d:hSo:I:")) != -1) {
-        switch (opt) {
+    Stab *globls;
+    Optctx ctx;
+    size_t i;
+
+    optinit(&ctx, "d:hSo:I:", argv, argc);
+    while (!optdone(&ctx)) {
+        switch (optnext(&ctx)) {
             case 'o':
-                outfile = optarg;
+                outfile = ctx.optarg;
                 break;
             case 'S':
                 writeasm = 1;
@@ -137,14 +139,11 @@
                 exit(0);
                 break;
             case 'd':
-                while (optarg && *optarg) {
-                    if (*optarg == 'y')
-                        yydebug = 1;
-                    debugopt[*optarg++ & 0x7f]++;
-                }
+                while (ctx.optarg && *ctx.optarg)
+                    debugopt[*ctx.optarg++ & 0x7f]++;
                 break;
             case 'I':
-                lappend(&incpaths, &nincpaths, optarg);
+                lappend(&incpaths, &nincpaths, ctx.optarg);
                 break;
             default:
                 usage(argv[0]);
@@ -154,11 +153,11 @@
     }
 
     lappend(&incpaths, &nincpaths, Instroot "/lib/myr");
-    for (i = optind; i < argc; i++) {
+    for (i = 0; i < ctx.nargs; i++) {
         globls = mkstab();
         tyinit(globls);
-        tokinit(argv[i]);
-        file = mkfile(argv[i]);
+        tokinit(ctx.args[i]);
+        file = mkfile(ctx.args[i]);
         file->file.exports = mkstab();
         file->file.globls = globls;
         yyparse();
@@ -173,13 +172,13 @@
             dump(file, stdout);
 
         if (writeasm) {
-            swapsuffix(buf, sizeof buf, argv[i], ".myr", ".s");
+            swapsuffix(buf, sizeof buf, ctx.args[i], ".myr", ".s");
         } else {
-            gentemp(buf, sizeof buf, argv[i], ".s");
+            gentemp(buf, sizeof buf, ctx.args[i], ".s");
         }
         gen(file, buf);
-        assem(buf, argv[i]);
-        genuse(argv[i]);
+        assem(buf, ctx.args[i]);
+        genuse(ctx.args[i]);
     }
 
     return 0;
--- a/muse/muse.c
+++ b/muse/muse.c
@@ -86,12 +86,13 @@
 
 int main(int argc, char **argv)
 {
+    Optctx ctx;
+    size_t i;
     FILE *f;
-    int opt;
-    int i;
 
-    while ((opt = getopt(argc, argv, "d::hmo:I:")) != -1) {
-        switch (opt) {
+    optinit(&ctx, "d:hmo:I:", argv, argc);
+    while (!optdone(&ctx)) {
+        switch (optnext(&ctx)) {
             case 'h':
                 usage(argv[0]);
                 exit(0);
@@ -100,15 +101,15 @@
                 merge = 1;
                 break;
             case 'o':
-                outfile = optarg;
+                outfile = ctx.optarg;
                 break;
             case 'd':
                 debug = 1;
-                while (optarg && *optarg)
-                    debugopt[*optarg++ & 0x7f] = 1;
+                while (ctx.optarg && *ctx.optarg)
+                    debugopt[*ctx.optarg++ & 0x7f] = 1;
                 break;
             case 'I':
-                lappend(&incpaths, &nincpaths, optarg);
+                lappend(&incpaths, &nincpaths, ctx.optarg);
                 break;
             default:
                 usage(argv[0]);
@@ -129,8 +130,8 @@
         file->file.globls = mkstab();
         updatens(file->file.exports, outfile);
         tyinit(file->file.globls);
-        for (i = optind; i < argc; i++)
-            mergeuse(argv[i]);
+        for (i = 0; i < ctx.nargs; i++)
+            mergeuse(ctx.args[i]);
         infer(file);
         tagexports(file->file.exports, 1);
         f = fopen(outfile, "w");
@@ -137,14 +138,14 @@
         writeuse(f, file);
         fclose(f);
     } else {
-        for (i = optind; i < argc; i++) {
-            file = mkfile(argv[i]);
+        for (i = 0; i < ctx.nargs; i++) {
+            file = mkfile(ctx.args[i]);
             file->file.exports = mkstab();
             file->file.globls = mkstab();
             if (debugopt['s'])
-                dumpuse(argv[i]);
+                dumpuse(ctx.args[i]);
             else
-                genuse(argv[i]);
+                genuse(ctx.args[i]);
         }
     }
 
--- a/myrbuild/myrbuild.c
+++ b/myrbuild/myrbuild.c
@@ -485,33 +485,35 @@
 
 int main(int argc, char **argv)
 {
-    int opt;
-    int i;
     struct utsname name;
     char **stack;
     size_t nstack;
+    Optctx ctx;
+    size_t i;
 
     if (uname(&name) == 0)
         sysname = strdup(name.sysname);
-    while ((opt = getopt(argc, argv, "hb:l:s:r:SI:C:A:M:L:R:")) != -1) {
-        switch (opt) {
-            case 'b': binname = optarg; break;
-            case 'l': libname = optarg; break;
-            case 's': ldscript = optarg; break;
+    
+    optinit(&ctx, "hb:l:s:r:SI:C:A:M:L:R:", argv, argc);
+    while (!optdone(&ctx)) {
+        switch (optnext(&ctx)) {
+            case 'b': binname = ctx.optarg; break;
+            case 'l': libname = ctx.optarg; break;
+            case 's': ldscript = ctx.optarg; break;
             case 'S': genasm = 1; break;
-            case 'C': mc = optarg; break;
-            case 'A': as = optarg; break;
-            case 'M': muse = optarg; break;
-            case 'L': ld = optarg; break;
-            case 'R': ar = optarg; break;
+            case 'C': mc = ctx.optarg; break;
+            case 'A': as = ctx.optarg; break;
+            case 'M': muse = ctx.optarg; break;
+            case 'L': ld = ctx.optarg; break;
+            case 'R': ar = ctx.optarg; break;
             case 'r':
-                      if (!strcmp(optarg, "none"))
+                      if (!strcmp(ctx.optarg, "none"))
                           runtime = NULL;
                       else
-                          runtime = strdup(optarg);
+                          runtime = strdup(ctx.optarg);
                       break;
             case 'I':
-                lappend(&incpaths, &nincpaths, strdup(optarg));
+                lappend(&incpaths, &nincpaths, strdup(ctx.optarg));
                 break;
             case 'h':
                 usage(argv[0]);
@@ -532,16 +534,16 @@
     libgraph = mkht(strhash, streq);
     compiled = mkht(strhash, streq);
     loopdetect = mkht(strhash, streq);
-    for (i = optind; i < argc; i++) {
-        lappend(&stack, &nstack, argv[i]);
-        compile(argv[i], &stack, &nstack);
+    for (i = 0; i < ctx.nargs; i++) {
+        lappend(&stack, &nstack, ctx.args[i]);
+        compile(ctx.args[i], &stack, &nstack);
         lpop(&stack, &nstack);
     }
     if (libname) {
-        mergeuse(&argv[optind], argc - optind);
-        archive(&argv[optind], argc - optind);
+        mergeuse(ctx.args, ctx.nargs);
+        archive(ctx.args, ctx.nargs);
     } else {
-        linkobj(&argv[optind], argc - optind);
+        linkobj(ctx.args, ctx.nargs);
     }
 
     return 0;
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -12,6 +12,7 @@
 
 typedef struct Bitset Bitset;
 typedef struct Htab Htab;
+typedef struct Optctx Optctx;
 
 typedef struct Tok Tok;
 typedef struct Node Node;
@@ -314,6 +315,22 @@
     };
 };
 
+struct Optctx {
+    /* public exports */
+    char *optarg;
+    char **args;
+    size_t nargs;
+
+    /* internal state */
+    char *optstr;
+    char **optargs;
+    size_t noptargs;
+    size_t argidx;
+    int optdone;    /* seen -- */
+    int finished;
+    char *curarg;
+};
+
 /* globals */
 extern char *filename;
 extern Tok *curtok;     /* the last token we tokenized */
@@ -520,6 +537,11 @@
 char *litstr(Littype lt);
 char *tidstr(Ty tid);
 
+/* option parsing */
+void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs);
+int optnext(Optctx *c);
+int optdone(Optctx *c);
+
 /* convenience funcs */
 void lappend(void *l, size_t *len, void *n); /* hack; nl is void* b/c void*** is incompatible with T*** */
 void linsert(void *l, size_t *len, size_t idx, void *n);
@@ -562,9 +584,10 @@
 void vfindentf(FILE *fd, int depth, char *fmt, va_list ap); 
 
 /* Options to control the compilation */
-extern int yydebug;
 extern char debugopt[128];
 extern int asmonly;
 extern char *outfile;
 extern char **incpaths;
 extern size_t nincpaths;
+
+
--- a/parse/util.c
+++ b/parse/util.c
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 #include <stdio.h>
-#include <inttypes.h>
+#include <stdint.h>
 #include <stdarg.h>
 #include <ctype.h>
 #include <string.h>
@@ -40,7 +40,7 @@
 
     p = xrealloc(mem, sz);
     if (sz > oldsz)
-        memset(&p[oldsz], 0, sz - oldsz);
+        bzero(&p[oldsz], sz - oldsz);
     return p;
 }
 
@@ -210,13 +210,11 @@
     return v;
 }
 
-void wrbuf(FILE *fd, void *ptr, size_t sz)
+void wrbuf(FILE *fd, void *buf, size_t sz)
 {
     size_t n;
-    char *buf;
 
     n = 0;
-    buf = ptr;
     while (n < sz) {
 	n += fwrite(buf + n, 1, sz - n, fd);
 	if (feof(fd))
@@ -410,3 +408,95 @@
     vfprintf(fd, fmt, ap);
 }
 
+static int optinfo(Optctx *ctx, char arg, int *take, int *mand)
+{
+    char *s;
+
+    for (s = ctx->optstr; *s != '\0'; s++) {
+        if (*s == arg) {
+            s++;
+            if (*s == ':') {
+                *take = 1;
+                *mand = 1;
+                return 1;
+            } else if (*s == '?') {
+                *take = 1;
+                *mand = 0;
+                return 1;
+            } else {
+                *take = 0;
+                *mand = 0;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+static int findnextopt(Optctx *ctx)
+{
+    size_t i;
+
+    for (i = ctx->argidx + 1; i < ctx->noptargs; i++) {
+        if (ctx->optargs[i][0] == '-')
+            goto foundopt;
+        else
+            lappend(&ctx->args, &ctx->nargs, ctx->optargs[i]);
+    }
+    ctx->finished = 1;
+    return 0;
+foundopt:
+    ctx->argidx = i;
+    ctx->curarg = ctx->optargs[i] + 1; /* skip initial '-' */
+    return 1;
+}
+
+void optinit(Optctx *ctx, char *optstr, char **optargs, size_t noptargs)
+{
+    ctx->args = NULL;
+    ctx->nargs = 0;
+
+    ctx->optstr = optstr;
+    ctx->optargs = optargs;
+    ctx->noptargs = noptargs;
+    ctx->optdone = 0;
+    ctx->finished = 0;
+    ctx->argidx = 0;
+    ctx->curarg = "";
+    findnextopt(ctx);
+}
+
+int optnext(Optctx *ctx)
+{
+    int take, mand;
+    int c;
+
+    c = *ctx->curarg;
+    ctx->curarg++;
+    if (!optinfo(ctx, c, &take, &mand)) {
+        printf("Unexpected argument %c\n", *ctx->curarg);
+    }
+
+    ctx->optarg = NULL;
+    if (take) {
+        if (*ctx->curarg) {
+            ctx->optarg = ctx->curarg;
+            ctx->curarg += strlen(ctx->optarg);
+        } else if (ctx->argidx < ctx->noptargs - 1) {
+            ctx->optarg = ctx->optargs[ctx->argidx + 1];
+            ctx->argidx++;
+        } else if (mand) {
+            fprintf(stderr, "expected argument for %c\n", *ctx->curarg);
+        }
+        findnextopt(ctx);
+    } else {
+        if (*ctx->optarg == '\0')
+            findnextopt(ctx);
+    }
+    return c;
+}
+
+int optdone(Optctx *ctx)
+{
+    return *ctx->curarg == '\0' && ctx->finished;
+}