⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 docmd.c

📁 umon bootloader source code, support mips cpu.
💻 C
📖 第 1 页 / 共 2 页
字号:
/* docmd:
 *	This code supports the command line interface (CLI) portion of the
 *	monitor.  It is a table-driven CLI that uses the table in cmdtbl.c.
 *	A limited amount of "shell-like" capabilities are supported...
 *		shell variables, symbol-table lookup, command history,
 *		command line editiing, command output redirection, etc...
 *
 *	General notice:
 *	This code is part of a boot-monitor package developed as a generic base
 *	platform for embedded system designs.  As such, it is likely to be
 *	distributed to various projects beyond the control of the original
 *	author.  Please notify the author of any enhancements made or bugs found
 *	so that all may benefit from the changes.  In addition, notification back
 *	to the author will allow the new user to pick up changes that may have
 *	been made by other users after this version of the code was distributed.
 *
 *	Note1: the majority of this code was edited with 4-space tabs.
 *	Note2: as more and more contributions are accepted, the term "author"
 *		   is becoming a mis-representation of credit.
 *
 *	Original author:	Ed Sutter
 *	Email:				esutter@lucent.com
 *	Phone:				908-582-2351
 */
#include "config.h"
#include "genlib.h"
#include "tfs.h"
#include "tfsprivate.h"
#include "cli.h"

/* appCmdlist:
 * 	This is a pointer to a list of commands that can be added to the 
 * 	monitor's list by the application using addcommand().
 */
struct	monCommand *appCmdlist;
char	*appcmdUlvl;

extern	struct monCommand cmdlist[];
extern	char cmdUlvl[];

void
showusage(struct monCommand *cmdptr)
{
	char	*usage;

	usage = cmdptr->helptxt[1];
	printf("Usage: %s %s\n",
	    cmdptr->name,*usage ? usage : "(no args/opts)");
}

void
paramerr(struct monCommand *cmdptr)
{
	printf("Command parameter error...\n");
	showusage(cmdptr);
}

int
addcommand(struct monCommand *cmdlist, char *cmdlvl)
{
	appCmdlist = cmdlist;
	appcmdUlvl = cmdlvl;
	return(0);
}

#if INCLUDE_SHELLVARS

char *
shellsym_chk(char type, char *string,int *size,char *buf,int bufsize)
{
	char	*p1, *p2, varname[CMDLINESIZE], *val;

	p1 = string;
	p2 = varname;
	/* If incoming check is for a symbol, we apply a somewhat more
	 * flexible syntax check for the symbol name...
	 */
	if (type == '%') {
		while(*p1 && (*p1 != '}') && (*p1 != ' ') && (*p1 != '\t'))
			*p2++ = *p1++;
	}
	else {
		while(1) {
			if (((*p1 >= '0') && (*p1 <= '9')) ||
			    ((*p1 >= 'a') && (*p1 <= 'z')) ||
			    ((*p1 >= 'A') && (*p1 <= 'Z')) ||
			    (*p1 == '_')) {
				*p2++ = *p1++;
			}
			else
				break;
		}
	}
	*p2 = '\0';

	if (type == '%')
		val = getsym(varname,buf,bufsize);
	else
		val = getenv(varname);

	if ((val) && (size))
		*size = strlen(varname);

	return(val);
}

/* braceimbalance():
 *	Return non-zero (the index into the src string at the point of the 
 *	imbalance) if the incoming string does not have a balanced set
 *	of braces; else return 0.
 */
static int
braceimbalance(char *src, int *idx, int *ndp)
{
	int		bnest;
	char	*base;

	bnest = 0;
	base = src;
	while((*src) && (bnest >= 0)) {
		if (((*src == '$') || (*src == '%')) && (*(src+1) == '{')) {
			bnest++;
			src++;
		}
		else if (*src == '}')
			bnest--;
		else if (*src == '{') {
			*ndp += 1;	/* Indicate that there is a brace with no '$' prefix */
		}
		else if (*src == '\\') {
			if ((*(src+1) == '$') || (*(src+1) == '%') ||
			    (*(src+1) == '\\') ||
			    (*(src+1) == '{') || (*(src+1) == '}')) {
				src++;
			}
		}
		src++;
	}

	/* If there is a '{}' mismatch, bnest will be non-zero... */
	*idx = src - base - 1;
	return(bnest);
}

/* processprefixes():
 *	Process the '$' for shell variables and '%' for symbols.
 * 	Look for the last '$' (or '%') in the incoming string and attempt to
 *	make a shell variable (or symbol) substitution.  Return 0 if no '$'
 *	(or '%') is found.  Note that '$' and '%' are processed interchangeably
 *	to support symbols and shell variables in the same way.
 */
static int
processprefixes(char *src)
{
	int		namesize, srclen;
	char	*base, *varname, *value;
	char	buf[CMDLINESIZE], buf1[CMDLINESIZE];


	base = src;
	srclen = strlen(src);

	while(*src) {
		if (((*src == '$') || (*src == '%')) && (*(src-1) != '\\')) {
			varname = src+1;
			value = shellsym_chk(*src,varname,&namesize,buf1,sizeof(buf1));
			if (value) {
				if (((srclen - namesize) + strlen(value)) >= CMDLINESIZE) {
					printf("Cmd line expansion overflow\n");
					return(-1);
				}
				strcpy(buf,varname+namesize);
				sprintf(varname-1,"%s%s",value,buf);
				return(1);
			}
		}
		src++;
	}
	return(0);
}

/* processbraces():
 *	Look into the incoming string for the deepest set of braces and
 *	substitute that with the value stored in the corresponding shell
 *	variable.  Return 1 if a set of braces was processed; else 0 indicating
 *	that all braces have been processed.  Return -1 if there is some kind
 *	of processing error (buffer overflow).
 */
static int
processbraces(char *src)
{
	int		namesize, srclen, result;
	char	*base, *cp1, *cp2, *varname, *value, type;
	char	buf[CMDLINESIZE], buf1[CMDLINESIZE], buf2[CMDLINESIZE];

	type = 0;
	base = src;
	varname = src;
	srclen = strlen(src);

	while(*src) {
		if (((*src == '$') || (*src == '%')) && (*(src+1) == '{')) {
			type = *src;
			varname = src+2;
			src++;
		}
		else if (*src == '}') {
			cp1 = varname;
			cp2 = buf1;
			while(cp1 < src)
				*cp2++ = *cp1++;
			*cp2 = 0;
			while((result = processprefixes(buf1)) == 1);
			if (result == -1)
				return(-1);

			strcpy(buf,src);
			sprintf(varname,"%s%s",buf1,buf);
			value = shellsym_chk(type,varname,&namesize,buf2,sizeof(buf2));
			/* If the shellvar or symbol exists, replace it; else remove it. */
			if (value) {
				if (((srclen-(namesize+3))+strlen(value)+1) > CMDLINESIZE) {
					printf("Cmd line expansion overflow\n");
					return(-1);
				}
				strcpy(buf1,varname+namesize+1);
				sprintf(varname-2,"%s%s",value,buf1);
			}
			else {
				strcpy(varname-2,src+1);
			}
			return(1);
		}
		else if (*src == '\\') {
			if ((*(src+1) == '$') || (*(src+1) == '%') ||
				(*(src+1) == '\\') ||
			    (*(src+1) == '{') || (*(src+1) == '}')) {
				src++;
			}
		}
		src++;
	}
	return(0);
}

/* expandshellvars():
 *	Passed a string that is to be expanded with all shell variables converted.
 *	This function supports variables of type $VARNAME and ${VARNAME}.
 *	It also allows variables to be embedded within variables.  For example...
 *	${VAR${NAME}} will be a 2-pass expansion in which ${NAME} is evaluated
 *	and then ${VARXXX} (where XXX is whatever was in variable NAME) is
 *	processed.
 */
static int
expandshellvars(char *newstring)
{
	char	*cp;
	int		result, cno, ndp;

	/* Verify that there is a balanced set of braces in the incoming
	 * string...
	 */
	ndp = 0;
	if (braceimbalance(newstring,&cno,&ndp)) {
		printf("Brace imbalance @ %d%s.\n",
			cno,ndp ? " ({ missing $ or %)" : "");
		return(-1);
	}
		
	/* Process the variable names within braces... */
	while((result = processbraces(newstring)) == 1);
	if (result == -1)
		return(-1);

	/* Process dollar signs (left-most first)...	*/
	while((result = processprefixes(newstring)) == 1);
	if (result == -1)
		return(-1);

	/* Cleanup any remaining "\{", "\}" or "\$" strings... */
	cp = newstring+1; 
	while(*cp) {
		if (*cp == '{' || *cp == '}' || *cp == '$' || *cp == '%') {
			if (*(cp-1) == '\\') {
				strcpy(cp-1,cp);
				cp -= 2;
			}
		}
		cp++;
	}
	return(0);
}
#else
static int
expandshellvars(char *newstring)
{
	return(0);
}
#endif


/* tokenize():
 *	Take the incoming string and create an argv[] array from that.  The
 *	incoming string is assumed to be writeable.  The argv[] array is simple
 *	a set of pointers into that string, where the whitespace delimited
 *	character sets are each NULL terminated.
 */
int
tokenize(char *string,char *argv[])
{
	int	argc, done;

	/* Null out the incoming argv array. */
	for(argc=0;argc<ARGCNT;argc++)
		argv[argc] = (char *)0;

	argc = 0;
	while(1) {
		while ((*string == ' ') || (*string == '\t'))
			string++;
		if (*string == 0)
			break;
		argv[argc] = string;
		while ((*string != ' ') && (*string != '\t')) {
			if ((*string == '\\') && (*(string+1) == '"')) {
				strcpy(string,string+1);
			}
			else if (*string == '"') {
				strcpy(string,string+1);
				while(*string != '"') {
					if ((*string == '\\') && (*(string+1) == '"'))
						strcpy(string,string+1);
					if (*string == 0)
						return(-1);
					string++;
				}
				strcpy(string,string+1);
				continue;
			}
			if (*string == 0)
				break;
			string++;
		}
		if (*string == 0)
			done = 1;
		else {
			done = 0;
			*string++ = 0;
		}
		argc++;
		if (done)
			break;
		if (argc >= ARGCNT) {
			argc = -1;
			break;
		}
	}
	return(argc);
}

/* showhelp():
 *	Called by Help() when it is time to print out some verbosity level of
 *	a command's help text.
 *	if...
 *		verbose == 2, then print all the help text;
 *		verbose == 1, then print the command name and abstract;
 *		verbose == 0, then print only the command name;
 */
int
showhelp(struct monCommand *list,int index,int verbose)
{
	char **hp, *lvltbl;
	struct monCommand *cptr;

	cptr = &list[index];

	/* Get command list in sync with user-level table:
	 */
	if (list == cmdlist) 
		lvltbl = cmdUlvl;
	else if (list == appCmdlist)
		lvltbl = appcmdUlvl;
	else
		return(-1);
	
	/* Verify user level:
	 */
	if ((lvltbl[index] > getUsrLvl()))
		return(0);

	if (verbose == 2) {
		printf("%s\n", cptr->helptxt[0]);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -