/* Parse command line, set up command arguments Unix-style, and call function.
 * Note: argument is modified (delimiters are overwritten with nulls)
 * Improved error handling by Brian Boesch of Stanford University
 */
#include <stdio.h>
#include "global.h"
#include "cmdparse.h"

int
cmdparse(cmds,line)
struct cmds cmds[];
register char *line;
{
	struct cmds *cmdp;
	char *argv[NARG],*cp;
	int argc,qflag;
	int rslt;

	/* Remove cr/lf */
	rip(line);

	for(argc = 0;argc < NARG;argc++)
		argv[argc] = NULLCHAR;

	for(argc = 0;argc < NARG;){
		qflag = 0;
		/* Skip leading white space */
		while(*line == ' ' || *line == '\t')
			line++;
		if(*line == '\0')
			break;
		/* Check for quoted token */
		if(*line == '"'){
			line++;	/* Suppress quote */
			qflag = 1;
		}
		argv[argc++] = line;	/* Beginning of token */
		/* Find terminating delimiter */
		if(qflag){
			/* Find quote, it must be present */
			if((line = index(line,'"')) == NULLCHAR){
				return -1;
			}
			*line++ = '\0';
		} else {
			/* Find space or tab. If not present,
			 * then we've already found the last
			 * token.
			 */
			if((cp = index(line,' ')) == NULLCHAR
			 && (cp = index(line,'\t')) == NULLCHAR){
				break;
			}
			*cp++ = '\0';
			line = cp;
		}
	}
	if (argc < 1) {		/* empty command line */
		argc = 1;
		argv[0] = "";
	}
	/* Lines beginning with "#" are comments */
	if(argv[0] == NULLCHAR || argv[0][0] == '#')
		return 0;

	/* Look up command in table; prefix matches are OK */
	for(cmdp = cmds;cmdp->name != NULLCHAR;cmdp++){
		if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0)
			break;
	}
	if(cmdp->name == NULLCHAR) {
		if(cmdp->argc_errmsg != NULLCHAR) 
			printf("%s\n",cmdp->argc_errmsg);
		return -1;
	} else {
		if(argc < cmdp->argcmin) {
			/* Insufficient arguments */
			printf("Usage: %s\n",cmdp->argc_errmsg);
			return -1;
		} else {
			rslt = (*cmdp->func)(argc,argv);
			if ((rslt < 0) && (cmdp->exec_errmsg != NULLCHAR))
				printf("%s\n",cmdp->exec_errmsg);
			return(rslt);
		}
	}
}

/* Call a subcommand based on the first token in an already-parsed line */
int
subcmd(tab,argc,argv)
struct cmds tab[];
int argc;
char *argv[];
{
	int rslt;
	register struct cmds *cmdp;

	/* Strip off first token and pass rest of line to subcommand */
	if (argc < 2) {
		if (argc < 1)
			printf("SUBCMD - Don't know what to do?\n");
		else
			printf("\"%s\" - takes at least one argument\n",argv[0]);
		return -1;
	}
	argc--;
	argv++;
	for(cmdp = tab;cmdp->name != NULLCHAR;cmdp++){
		if(strncmp(argv[0],cmdp->name,strlen(argv[0])) == 0){
			if(argc < cmdp->argcmin) {
				if (cmdp->argc_errmsg != NULLCHAR)
					printf("Usage: %s\n",cmdp->argc_errmsg);
				return -1;
			} else {
				rslt = (*cmdp->func)(argc,argv);
				if ((rslt < 0) && (cmdp->exec_errmsg != NULLCHAR))
					printf("%s\n",cmdp->exec_errmsg);
				return(rslt);
			}
		}
	}
	if (cmdp->argc_errmsg != NULLCHAR) 
		printf("%s\n",cmdp->argc_errmsg);
	return -1;
}
