From: Mark Wooding Date: Mon, 1 Jan 2007 12:52:32 +0000 (+0000) Subject: admin: Option parser macros. X-Git-Tag: 1.0.0pre8~94^3~8 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/tripe/commitdiff_plain/e7a4d919c7949baff584b17fe604f1a9973cf00f admin: Option parser macros. There's too much clone and hack in options parsing. Cover up the repeated code with macros. Also, sneak in a little fix: complain if there are too many arguments to a PING or EPING command. --- diff --git a/server/admin.c b/server/admin.c index 44a0fdc6..1660106c 100644 --- a/server/admin.c +++ b/server/admin.c @@ -862,6 +862,44 @@ fail: xfree(r); } +/*----- Option parsing ----------------------------------------------------*/ + +#define OPTIONS(argc, argv, guts) do { \ + char **o_av = argv; \ + for (;; o_av++) { \ + if (!*o_av) \ + break; \ + if (mystrieq(*o_av, "--")) { \ + o_av++; \ + break; \ + } \ + guts \ + if (**o_av == '-') \ + goto bad_syntax; \ + break; \ + } \ + argc -= o_av - argv; \ + argv = o_av; \ +} while (0) + +#define OPT(name, guts) if (mystrieq(*o_av, name)) { guts continue; } + +#define OPTARG(name, arg, guts) OPT(name, { \ + const char *arg; \ + arg = *++o_av; \ + if (!arg) goto bad_syntax; \ + guts \ +}) + +#define OPTTIME(name, arg, guts) OPTARG(name, o_arg, { \ + long arg; \ + if ((arg = a_parsetime(o_arg)) < 0) { \ + a_fail(a, "bad-time-spec", "%s", o_arg, A_END); \ + goto fail; \ + } \ + guts \ +}) + /*----- Adding peers ------------------------------------------------------*/ /* --- @a_doadd@ --- * @@ -907,7 +945,6 @@ static void a_doadd(admin_resop *r, int rc) static void acmd_add(admin *a, unsigned ac, char *av[]) { - unsigned i, j; const char *tag = 0; admin_addop *add; @@ -920,54 +957,38 @@ static void acmd_add(admin *a, unsigned ac, char *av[]) /* --- Parse options --- */ - i = 0; - for (;;) { - if (!av[i]) - goto bad_syntax; - if (mystrieq(av[i], "-background")) { - if (!av[++i]) goto bad_syntax; - tag = av[i]; - } else if (mystrieq(av[i], "-tunnel")) { - if (!av[++i]) goto bad_syntax; - for (j = 0;; j++) { - if (!tunnels[j]) { - a_fail(a, "unknown-tunnel", "%s", av[i], A_END); + OPTIONS(ac, av, { + OPTARG("-background", arg, { tag = arg; }) + OPTARG("-tunnel", arg, { + unsigned i; + for (i = 0;; i++) { + if (!tunnels[i]) { + a_fail(a, "unknown-tunnel", "%s", arg, A_END); goto fail; } - if (mystrieq(av[i], tunnels[j]->name)) { - add->peer.tops = tunnels[j]; + if (mystrieq(arg, tunnels[i]->name)) { + add->peer.tops = tunnels[i]; break; } } - } else if (mystrieq(av[i], "-keepalive")) { - long t; - if (!av[++i]) goto bad_syntax; - if ((t = a_parsetime(av[i])) < 0) { - a_fail(a, "bad-time-spec", "%s", av[i], A_END); - goto fail; - } - add->peer.t_ka = t; - } else if (mystrieq(av[i], "--")) { - i++; - break; - } else - break; - i++; - } + }) + OPTTIME("-keepalive", t, { add->peer.t_ka = t; }) + }); /* --- Make sure someone's not got there already --- */ - if (!av[i]) + if (!*av) goto bad_syntax; - if (p_find(av[i])) { - a_fail(a, "peer-exists", "%s", av[i], A_END); + if (p_find(*av)) { + a_fail(a, "peer-exists", "%s", *av, A_END); goto fail; } - add->peer.name = xstrdup(av[i++]); + add->peer.name = xstrdup(*av++); + ac--; /* --- Crank up the resolver --- */ - a_resolve(a, &add->r, tag, a_doadd, ac - i, av + i); + a_resolve(a, &add->r, tag, a_doadd, ac, av); return; /* --- Clearing up --- */ @@ -1052,34 +1073,16 @@ static void a_ping(admin *a, unsigned ac, char *av[], const char *cmd, unsigned msg) { long t = T_PING; - int i; peer *p; admin_pingop *pg = 0; const char *tag = 0; - i = 0; - for (;;) { - if (!av[i]) - goto bad_syntax; - if (mystrieq(av[i], "-background")) { - if (!av[++i]) goto bad_syntax; - tag = av[i]; - } else if (mystrieq(av[i], "-timeout")) { - if (!av[++i]) goto bad_syntax; - if ((t = a_parsetime(av[i])) < 0) { - a_fail(a, "bad-time-spec", "%s", av[i], A_END); - return; - } - } else if (mystrieq(av[i], "--")) { - i++; - break; - } else - break; - i++; - } - - if (!av[i]) goto bad_syntax; - if ((p = a_findpeer(a, av[i])) == 0) + OPTIONS(ac, av, { + OPTARG("-background", arg, { tag = arg; }) + OPTTIME("-timeout", arg, { t = arg; }) + }); + if (!*av || av[1]) goto bad_syntax; + if ((p = a_findpeer(a, *av)) == 0) return; pg = xmalloc(sizeof(*pg)); gettimeofday(&pg->pingtime, 0); @@ -1094,6 +1097,7 @@ static void a_ping(admin *a, unsigned ac, char *av[], bad_syntax: a_fail(a, "bad-syntax", "%s", cmd, "[OPTIONS] PEER", cmd, A_END); +fail: return; }