From: Simon Wilkinson Date: Tue, 19 Apr 2011 18:37:37 +0000 (+0100) Subject: cmd: Add support for params with optional values X-Git-Tag: openafs-devel-1_7_1~538 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=d0d8b391b0c634f44cb019fd73fddf6ee523cfaa cmd: Add support for params with optional values Add the CMD_SINGLE_OR_FLAG option which permits a parameter to either have a single value, or no value at all. If it has no value, then it behaves in the same way as the current 'flag' implementation. Change-Id: I49cf313f1d3b9c369f87b1ff66bfcc038b8aa08a Reviewed-on: http://gerrit.openafs.org/4545 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/cmd/cmd.c b/src/cmd/cmd.c index d8d2107..76061f6 100644 --- a/src/cmd/cmd.c +++ b/src/cmd/cmd.c @@ -601,6 +601,10 @@ ResetSyntax(struct cmd_syndesc *as) tp = as->parms; for (i = 0; i < CMD_MAXPARMS; i++, tp++) { switch (tp->type) { + case CMD_SINGLE_OR_FLAG: + if (tp->items == &dummy) + break; + /* Deliberately fall through here */ case CMD_SINGLE: case CMD_LIST: /* free whole list in both cases, just for fun */ @@ -908,7 +912,8 @@ cmd_Parse(int argc, char **argv, struct cmd_syndesc **outsyntax) continue; } - if (tparm->type == CMD_SINGLE) { + if (tparm->type == CMD_SINGLE || + tparm->type == CMD_SINGLE_OR_FLAG) { if (tparm->items) { fprintf(stderr, "%sToo many values after switch %s\n", NName(pname, ": "), tparm->name); @@ -946,10 +951,14 @@ cmd_Parse(int argc, char **argv, struct cmd_syndesc **outsyntax) if (tparm->type == 0) continue; /* Skipped parm slot */ if ((tparm->flags & CMD_PROCESSED) && tparm->items == 0) { - fprintf(stderr, "%s The field '%s' isn't completed properly\n", + if (tparm->type == CMD_SINGLE_OR_FLAG) { + tparm->items = &dummy; + } else { + fprintf(stderr, "%s The field '%s' isn't completed properly\n", NName(pname, ": "), tparm->name); - code = CMD_TOOFEW; - goto out; + code = CMD_TOOFEW; + goto out; + } } if (!(tparm->flags & CMD_OPTIONAL) && tparm->items == 0) { fprintf(stderr, "%sMissing required parameter '%s'\n", @@ -1164,6 +1173,9 @@ cmd_OptionAsInt(struct cmd_syndesc *syn, int pos, int *value) if (syn->parms[pos].items == NULL || syn->parms[pos].items->data == NULL) return CMD_MISSING; + if (syn->parms[pos].items == &dummy) + return 0; + *value = strtol(syn->parms[pos].items->data, NULL, 10); return 0; @@ -1176,9 +1188,12 @@ cmd_OptionAsString(struct cmd_syndesc *syn, int pos, char **value) return CMD_EXCESSPARMS; if (syn->parms[pos].items == NULL || syn->parms[pos].items->data == NULL) return CMD_MISSING; + if (syn->parms[pos].items == &dummy) + return 0; if (*value) free(*value); + *value = strdup(syn->parms[pos].items->data); return 0; diff --git a/src/cmd/cmd.p.h b/src/cmd/cmd.p.h index ac5cff1..8280614 100644 --- a/src/cmd/cmd.p.h +++ b/src/cmd/cmd.p.h @@ -14,6 +14,7 @@ #define CMD_FLAG 1 /* no parms */ #define CMD_SINGLE 2 /* one parm */ #define CMD_LIST 3 /* two parms */ +#define CMD_SINGLE_OR_FLAG 4 /* one parm or flag */ /* syndesc flags */ #define CMD_ALIAS 1 /* this is an alias */ diff --git a/tests/cmd/command-t.c b/tests/cmd/command-t.c index b2ea160..aec9c8a 100644 --- a/tests/cmd/command-t.c +++ b/tests/cmd/command-t.c @@ -59,7 +59,7 @@ main(int argc, char **argv) int retval; char *retstring; - plan(62); + plan(70); initialize_CMD_error_table(); @@ -230,6 +230,37 @@ main(int argc, char **argv) cmd_FreeOptions(&retopts); cmd_FreeArgv(tv); + /* Add something that can be a flag or a value, and put something after + * it so we can check for parse problems*/ + cmd_AddParm(opts, "-perhaps", CMD_SINGLE_OR_FLAG, CMD_OPTIONAL, + "what am I"); + cmd_AddParm(opts, "-sanity", CMD_SINGLE, CMD_OPTIONAL, "sanity check"); + + /* Try using as an option */ + + code = cmd_ParseLine("-first 1 -perhaps 2 -sanity 3", tv, &tc, 100); + is_int(0, code, "cmd_ParseLine succeeds"); + code = cmd_Parse(tc, tv, &retopts); + is_int(0, code, "cmd_Parse succeeds for option-as-flag as opt"); + code = cmd_OptionAsInt(retopts, 6, &retval); + is_int(0, code, "cmd_OptionAsInt succeeds"); + is_int(2, retval, " ... and we have the correct value"); + cmd_FreeOptions(&retopts); + cmd_FreeArgv(tv); + + /* And now, as a flag */ + + code = cmd_ParseLine("-first 1 -perhaps -sanity 3", tv, &tc, 100); + is_int(0, code, "cmd_ParseLine succeeds"); + code = cmd_Parse(tc, tv, &retopts); + is_int(0, code, "cmd_Parse succeeds for option-as-flag as flag"); + code = cmd_OptionAsInt(retopts, 6, &retval); + is_int(CMD_MISSING, code, " ... pulling out a value fails as expected"); + cmd_OptionAsFlag(retopts, 6, &retval); + ok(retval, " ... but parsing as a flag works"); + cmd_FreeOptions(&retopts); + cmd_FreeArgv(tv); + return 0; }