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;
+}