return 1;
}
+/* Add help, apropos commands once */
+static void
+initSyntax(void)
+{
+ struct cmd_syndesc *ts;
+
+ if (!noOpcodes) {
+ ts = cmd_CreateSyntax("help", HelpProc, NULL,
+ "get help on commands");
+ cmd_AddParm(ts, "-topic", CMD_LIST, CMD_OPTIONAL, "help string");
+ cmd_AddParm(ts, "-admin", CMD_FLAG, CMD_OPTIONAL, NULL);
+
+ ts = cmd_CreateSyntax("apropos", AproposProc, NULL,
+ "search by help text");
+ cmd_AddParm(ts, "-topic", CMD_SINGLE, CMD_REQUIRED, "help string");
+ ts = cmd_CreateSyntax("version", VersionProc, NULL,
+ (char *)CMD_HIDDEN);
+ ts = cmd_CreateSyntax("-version", VersionProc, NULL,
+ (char *)CMD_HIDDEN);
+ ts = cmd_CreateSyntax("-help", HelpProc, NULL,
+ (char *)CMD_HIDDEN);
+ ts = cmd_CreateSyntax("--version", VersionProc, NULL,
+ (char *)CMD_HIDDEN);
+ ts = cmd_CreateSyntax("--help", HelpProc, NULL,
+ (char *)CMD_HIDDEN);
+ }
+}
+
/* Call the appropriate function, or return syntax error code. Note: if
* no opcode is specified, an initialization routine exists, and it has
* NOT been called before, we invoke the special initialization opcode
*/
int
-cmd_Dispatch(int argc, char **argv)
+cmd_Parse(int argc, char **argv, struct cmd_syndesc **outsyntax)
{
char *pname;
- struct cmd_syndesc *ts;
+ struct cmd_syndesc *ts = NULL;
struct cmd_parmdesc *tparm;
afs_int32 i, j;
int curType;
int positional;
int ambig;
+ int code = 0;
static int initd = 0; /*Is this the first time this routine has been called? */
static int initcmdpossible = 1; /*Should be consider parsing the initial command? */
+ *outsyntax = NULL;
+
if (!initd) {
initd = 1;
- /* Add help, apropos commands once */
- if (!noOpcodes) {
- ts = cmd_CreateSyntax("help", HelpProc, NULL,
- "get help on commands");
- cmd_AddParm(ts, "-topic", CMD_LIST, CMD_OPTIONAL, "help string");
- cmd_AddParm(ts, "-admin", CMD_FLAG, CMD_OPTIONAL, NULL);
-
- ts = cmd_CreateSyntax("apropos", AproposProc, NULL,
- "search by help text");
- cmd_AddParm(ts, "-topic", CMD_SINGLE, CMD_REQUIRED,
- "help string");
- ts = cmd_CreateSyntax("version", VersionProc, NULL,
- (char *)CMD_HIDDEN);
- ts = cmd_CreateSyntax("-version", VersionProc, NULL,
- (char *)CMD_HIDDEN);
- ts = cmd_CreateSyntax("-help", HelpProc, NULL,
- (char *)CMD_HIDDEN);
- ts = cmd_CreateSyntax("--version", VersionProc, NULL,
- (char *)CMD_HIDDEN);
- ts = cmd_CreateSyntax("--help", HelpProc, NULL,
- (char *)CMD_HIDDEN);
- }
+ initSyntax();
}
/*Remember the program name */
if (argc == 1) {
if (!NoParmsOK(allSyntax)) {
printf("%s: Type '%s -help' for help\n", pname, pname);
- return (CMD_USAGE);
+ code = CMD_USAGE;
+ goto out;
}
}
} else {
if (argc < 2) {
/* if there is an initcmd, don't print an error message, just
* setup to use the initcmd below. */
- if (!(initcmdpossible && FindSyntax(initcmd_opcode, (int *)0))) {
+ if (!(initcmdpossible && FindSyntax(initcmd_opcode, NULL))) {
printf("%s: Type '%s help' or '%s help <topic>' for help\n",
pname, pname, pname);
- return (CMD_USAGE);
+ code = CMD_USAGE;
+ goto out;
}
}
}
* see if there is a descriptor for the initialization opcode.
* Only try this once. */
initcmdpossible = 0;
- ts = FindSyntax(initcmd_opcode, (int *)0);
+ ts = FindSyntax(initcmd_opcode, NULL);
if (!ts) {
/*There is no initialization opcode available, so we declare
* an error */
"Unrecognized operation '%s'; type '%shelp' for list\n",
argv[1], NName(pname, " "));
}
- return (CMD_UNKNOWNCMD);
+ code = CMD_UNKNOWNCMD;
+ goto out;
} else {
/*Found syntax structure for an initialization opcode. Fix
* up argv and argc to relect what the user
fprintf(stderr,
"%sCan't insert implicit init opcode into command line\n",
NName(pname, ": "));
- return (CMD_INTERNALERROR);
+ code = CMD_INTERNALERROR;
+ goto out;
}
}
} /*Initial opcode not yet attempted */
"Unrecognized operation '%s'; type '%shelp' for list\n",
argv[1], NName(pname, " "));
}
- return CMD_UNKNOWNCMD;
+ code = CMD_UNKNOWNCMD;
+ goto out;
}
} /*Argv[1] is not a valid opcode */
} /*Opcodes are defined */
else
fprintf(stderr, "'%shelp %s' for detailed help\n",
NName(argv[0], " "), ts->name);
- ResetSyntax(ts);
- return (CMD_UNKNOWNSWITCH);
+ code = CMD_UNKNOWNSWITCH;
+ goto out;
}
if (j >= CMD_MAXPARMS) {
fprintf(stderr, "%sInternal parsing error\n",
NName(pname, ": "));
- ResetSyntax(ts);
- return (CMD_INTERNALERROR);
+ code = CMD_INTERNALERROR;
+ goto out;
}
if (ts->parms[j].type == CMD_FLAG) {
ts->parms[j].items = &dummy;
/* Try to fit in this descr */
if (curType >= CMD_MAXPARMS) {
fprintf(stderr, "%sToo many arguments\n", NName(pname, ": "));
- ResetSyntax(ts);
- return (CMD_TOOMANY);
+ code = CMD_TOOMANY;
+ goto out;
}
tparm = &ts->parms[curType];
if (tparm->items) {
fprintf(stderr, "%sToo many values after switch %s\n",
NName(pname, ": "), tparm->name);
- ResetSyntax(ts);
- return (CMD_NOTLIST);
+ code = CMD_NOTLIST;
+ goto out;
}
AddItem(tparm, argv[i]); /* Add to end of list */
} else if (tparm->type == CMD_LIST) {
/* Display full help syntax if we don't have subcommands */
if (noOpcodes)
PrintFlagHelp(ts);
- ResetSyntax(ts);
- return 0;
+ code = CMD_USAGE;
+ goto out;
}
/* Parsing done, see if we have all of our required parameters */
if ((tparm->flags & CMD_PROCESSED) && tparm->items == 0) {
fprintf(stderr, "%s The field '%s' isn't completed properly\n",
NName(pname, ": "), tparm->name);
- ResetSyntax(ts);
- tparm->flags &= ~CMD_PROCESSED;
- return (CMD_TOOFEW);
+ code = CMD_TOOFEW;
+ goto out;
}
if (!(tparm->flags & CMD_OPTIONAL) && tparm->items == 0) {
fprintf(stderr, "%sMissing required parameter '%s'\n",
NName(pname, ": "), tparm->name);
- ResetSyntax(ts);
- tparm->flags &= ~CMD_PROCESSED;
- return (CMD_TOOFEW);
+ code = CMD_TOOFEW;
+ goto out;
}
tparm->flags &= ~CMD_PROCESSED;
}
+ *outsyntax = ts;
+
+out:
+ if (code && ts != NULL)
+ ResetSyntax(ts);
+
+ return code;
+}
+
+int
+cmd_Dispatch(int argc, char **argv)
+{
+ struct cmd_syndesc *ts = NULL;
+ int code;
+
+ code = cmd_Parse(argc, argv, &ts);
+ if (code)
+ return code;
/*
* Before calling the beforeProc and afterProc and all the implications
* now.
*/
if ((ts->proc == HelpProc) || (ts->proc == AproposProc)) {
- i = (*ts->proc) (ts, ts->rock);
- ResetSyntax(ts);
- return (i);
+ code = (*ts->proc) (ts, ts->rock);
+ goto out;
}
/* Now, we just call the procedure and return */
if (beforeProc)
- i = (*beforeProc) (ts, beforeRock);
- else
- i = 0;
- if (i) {
- ResetSyntax(ts);
- return (i);
- }
- i = (*ts->proc) (ts, ts->rock);
+ code = (*beforeProc) (ts, beforeRock);
+
+ if (code)
+ goto out;
+
+ code = (*ts->proc) (ts, ts->rock);
+
if (afterProc)
(*afterProc) (ts, afterRock);
- ResetSyntax(ts); /* Reset and free things */
- return (i);
+out:
+ cmd_FreeOptions(&ts);
+ return code;
+}
+
+void
+cmd_FreeOptions(struct cmd_syndesc **ts)
+{
+ if (*ts != NULL) {
+ ResetSyntax(*ts);
+ *ts = NULL;
+ }
}
/* free token list returned by parseLine */
{
char *tv[100];
struct cmd_syndesc *opts;
+ struct cmd_syndesc *retopts;
int code;
int tc;
- plan(29);
+ plan(47);
initialize_CMD_error_table();
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(0, code, "dispatching simple comamnd line succeeds");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(0, code, "parsing simple command line succeeds");
+ is_string("foo", retopts->parms[0].items->data, " ... 1st option matches");
+ is_string("bar", retopts->parms[1].items->data, " ... 2nd option matches");
+ ok(retopts->parms[2].items != NULL, " ... 3rd option matches");
+ cmd_FreeOptions(&retopts);
cmd_FreeArgv(tv);
/* unknown switch */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(CMD_UNKNOWNSWITCH, code, "invalid options fail as expected");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_UNKNOWNSWITCH, code, "and still fail with cmd_Parse");
cmd_FreeArgv(tv);
/* missing parameter */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(CMD_TOOFEW, code, "missing parameters fail as expected");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_TOOFEW, code, "and still fail with cmd_Parse");
cmd_FreeArgv(tv);
/* missing option */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(CMD_UNKNOWNSWITCH, code, "missing options fail as expected");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_UNKNOWNSWITCH, code, "and still fail with cmd_Parse");
cmd_FreeArgv(tv);
code = cmd_ParseLine("-first foo baz -second bar -third -flag", tv, &tc, 100);
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(CMD_NOTLIST, code, "too many parameters fails as expected");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_NOTLIST, code, "and still fail with cmd_Parse");
cmd_FreeArgv(tv);
/* Positional parameters */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(0, code, "dispatching positional parameters succeeds");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(0, code, "and works with cmd_Parse");
+ cmd_FreeOptions(&retopts);
cmd_FreeArgv(tv);
/* Abbreviations */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(0, code, "dispatching abbreviations succeeds");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(0, code, "and works with cmd_Parse");
+ cmd_FreeOptions(&retopts);
+
cmd_FreeArgv(tv);
/* Ambiguous */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(CMD_UNKNOWNSWITCH, code, "ambiguous abbreviations correctly fail");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_UNKNOWNSWITCH, code, "and fail with cmd_Parse too");
cmd_FreeArgv(tv);
/* Disable positional commands */
code = cmd_ParseLine("foo bar -flag", tv, &tc, 100);
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
- is_int(3359746, code, "positional parameters can be disabled");
+ is_int(CMD_NOTLIST, code, "positional parameters can be disabled");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_NOTLIST, code, "and fail with cmd_Parse too");
cmd_FreeArgv(tv);
/* Disable abbreviations */
is_int(0, code, "cmd_ParseLine succeeds");
code = cmd_Dispatch(tc, tv);
is_int(CMD_UNKNOWNSWITCH, code, "dispatching abbreviations succeeds");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(CMD_UNKNOWNSWITCH, code, "and fail with cmd_Parse too");
+
+ cmd_FreeArgv(tv);
+
+ /* Try the new cmd_Parse function with something different*/
+ code = cmd_ParseLine("-first one -second two -flag", tv, &tc, 100);
+ is_int(0, code, "cmd_ParseLine succeeds");
+ code = cmd_Parse(tc, tv, &retopts);
+ is_int(0, code, "Parsing with cmd_Parse works");
+ is_string("one", retopts->parms[0].items->data, " ... 1st option matches");
+ is_string("two", retopts->parms[1].items->data, " ... 2nd option matches");
+ ok(retopts->parms[2].items != NULL, " ... 3rd option matches");
+
+ cmd_FreeOptions(&retopts);
cmd_FreeArgv(tv);
return 0;