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

📄 xcscrpt.c

📁 支持X/YModem和cis_b+协议的串口通讯程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	{"bind_function",	bind_function},	{"bind_script",	bind_script},	{"bind_string",	bind_string},	{"capture",		k_capture},	{"debug",		k_debug},	{"dial",		k_dial},	{"hangup",		hangup},	{"linked",		k_linked},	{"pause",		k_pause},	{"quit",		(int(*)())s_exit},	{"redial",		redial},	{"seen",		k_seen},	{"xmitbrk",		xmitbrk},	{"transmit",		k_transmit},	{"tty",			k_tty},	{"type",		k_type},	{"waitfor",		k_waitfor},	{NIL(char),			0}};/*	end of primitives *//*	token types */typedef enum {	NULLTOK,	/* terminating '\0' in script buffer */	ACTION,		/* an action (primitive or script cmd) */	AFFIRM,		/* script 'affirm' */	BACKQUOT,	/* script command substitution */	SBREAK,		/* script 'break' */	CALL,		/* script 'call' */	COMMENT,	/* comment */	SCONTNUE,	/* script 'continue' */	DECR,		/* script 'decr' */	DO,			/* script 'do' */	DONE,		/* script 'done' */	ECHOS,		/* script 'echo' */	EFLAG,		/* '-n' switch for script 'echo' cmd */	ELSE,		/* script 'else' */	ENDIF,		/* script 'endif' */	ENDTRAP,	/* script 'endtrap' */	EQ,			/* operator "equals" */	EXIT,		/* script 'exit' */	SFILE,		/* script 'file' */	SFALSE,		/* script 'false' */	IF,			/* script 'if' */	INCR,		/* script 'incr' */	LESSTHAN,	/* operator "less than" */	LITERAL,	/* a literal string (e.g. "abcde") */	MORETHAN,	/* operator "greater than" */	NEGATE,		/* negation operator for comparisons */	NEQ,		/* operator "not equal to" */	NUMBER,		/* a numeric constant (e.g. 12345) */	PIPE,		/* script 'pipe' */	READ,		/* script 'read' */	SHELL,		/* script 'shell' */	SET,		/* script 'assign' */	STRAP,		/* script 'trap' */	TERMINAT,	/* statement terminators (';' and '\n') */	THEN,		/* script 'then' */	STRUE,		/* script 'true' */	UNSET,		/* script 'unset' */	UNTRAP,		/* script 'untrap' */	XCSET,		/* xc 'set' command */	VARNAME,	/* a variable name */	WHILE,		/* script 'while' */	TTERROR,	/* unrecognizable token */	TIMEOUT		/* script 'timeout' */} TOK_TYPE;/*	token table */static struct {	char *name;	TOK_TYPE token;} s_toktab[] = {	{"NULLTOK",		NULLTOK},	{"ACTION",		ACTION},	{"affirm",		AFFIRM},	{"BACKQUOT",	BACKQUOT},	{"break",		SBREAK},	{"call",		CALL},	{"COMMENT",		COMMENT},	{"continue",	SCONTNUE},	{"decr",		DECR},	{"do",			DO},	{"done",		DONE},	{"echo",		ECHOS},	{"-n",			EFLAG},	{"else",		ELSE},	{"endif",		ENDIF},	{"fi",			ENDIF},	{"ENDTRAP",		ENDTRAP},	{"eq",			EQ},	{"exit",		EXIT},	{"false",		SFALSE},	{"file",		SFILE},	{"if",			IF},	{"incr",		INCR},	{"lessthan",	LESSTHAN},	{"LITERAL",		LITERAL},	{"morethan",	MORETHAN},	{"!",			NEGATE},	{"neq",			NEQ},	{"NUMBER",		NUMBER},	{"pipe",		PIPE},	{"read",		READ},	{"assign",		SET},	{"shell",		SHELL},	{"TRAP",		STRAP},		/* 'trap' keyword left for later dev't */	{"TERMINAT",	TERMINAT},	{"then",		THEN},	{"timeout",		TIMEOUT},	{"true",		STRUE},	{"unassign",	UNSET},	{"UNTRAP",		UNTRAP},	{"set",			XCSET},	{"VARNAME",		VARNAME},	{"while",		WHILE},	{"\0",			TTERROR}};/*	end token types *//*	tok_value is set by lexan() in the following instances:	 TOK_TYPE NUMBER:	 (long) value of number	 TOK_TYPE LITERAL:	 pointer to beginning of quoted string	 TOK_TYPE ACTION:	 function pointer to appropriate vector	 TOK_TYPE VARNAME:	 pointer to VAR struct	 TOK_TYPE TTERROR:	 pointer to strange construction in script	All other values of TOK_TYPE don't require further information.*/static union {	long numval;		/* numbers */	char *strptr;		/* for literal strings (points to initial '"') */	int (*funcptr)();	/* vector for primitives */	VAR *varptr;		/* for variables */} tok_value;/*	lexan() is the lexical analyzer, which translates words	into token types and sets tok_value appropriately. It's	called repeatedly by the language parser, S_parse().*/static TOK_TYPElexan(pcptr)char **pcptr;			/* address of script program counter */{	long nvalue, negpos = 1;	VAR *varptr;	FILE *bqpipe;	int i, c;				/* really a char, but 'int' to spot EOF */	static char *cptr, *lasttok,				latoken[VNAMELEN+1], temp[VMAXSIZE+1], bqcmd[VMAXSIZE+1];	extern FILE *popen();	/* if in debug mode, echo script line to tfp */	if (debugflag && *pcptr>lasttok){		cptr = *pcptr - 1;		while (*cptr==' ' || *cptr=='\t') --cptr;		if (*cptr=='\n'){			fputs("+ ",tfp);			++cptr;			while (*cptr!='\n' && *cptr)				fputc(*(cptr++),tfp);			fputc('\r',tfp),			fputc('\n',tfp);		}	}	/* skip to beginning of next token */	while (**pcptr==' ' || **pcptr=='\t') ++(*pcptr);	tok_value.strptr = cptr = lasttok = *pcptr;				/* save place */									/* negation operator for comparisons */	if (*cptr=='!' && (*(cptr+1)==' ' || *(cptr+1)=='\t')){		++cptr;		*pcptr = cptr;		return NEGATE;	}									/* comment in script */	if (*cptr=='#'){		while (*cptr && *cptr!='\n') ++cptr;		*pcptr = cptr;		return TERMINAT;	}									/* statement terminator */	if (*cptr==';' || *cptr=='\n'){		++cptr;		*pcptr = cptr;		return TERMINAT;	}									/* end of script */	if (*cptr=='\0')		return NULLTOK;									/* quoted literal string */	if (*cptr=='"'){		++cptr;		while (*cptr && *cptr!='\n' && !(*cptr=='"' && *(cptr-1)!='\\'))			++cptr;		if (*cptr=='"'){			++cptr;			*pcptr = cptr;			return LITERAL;		}		sprintf(Msg,"Unmatched quote");		S_abort();	}							/* environment variable (treat as a literal) */	if (*cptr=='$'){		++cptr;		for (i=0; i<VMAXSIZE; ++i){			if (!*cptr || *cptr==' ' || *cptr=='\t' || *cptr=='\n'				|| *cptr=='\r' || *cptr==';')					break;			temp[i] = *(cptr++);		}		temp[i] = '\0';		tok_value.strptr = getenv(temp);		if (!tok_value.strptr)			tok_value.strptr = temp,			sprintf(Msg,"%s: no such environment variable",temp),			S2(Msg),			tok_value.strptr = "";		*pcptr = cptr;		return LITERAL;	}						/* back-quoted shell command (treat like env var) */	if (*cptr=='`'){		++cptr;		i = 0;		while (*cptr && *cptr!='\n' && *cptr!='`' && (++i)<VMAXSIZE)			++cptr;		if (*cptr=='`'){			for (i=0; i<VMAXSIZE; ++i){			/* tok_value ptr points */				bqcmd[i] = tok_value.strptr[i+1];	/* to leading '`' */				if (bqcmd[i]=='`'){					bqcmd[i] = '\0';					break;				}			}			bqcmd[i] = '\0';			signal(SIGCHLD,SIG_DFL);			if (!(bqpipe=popen(bqcmd,"r"))){				sprintf(Msg,"%s: cannot create pipe",bqcmd);				S_abort();			}			else {				temp[0] = '\0';				i = 0;				while (i<=VMAXSIZE && (c=fgetc(bqpipe))!=EOF && c!='\n')					temp[i++] = c;				fflush(bqpipe);				pclose(bqpipe);				temp[i] = '\0';				tok_value.strptr = temp;				*pcptr = cptr + 1;				return LITERAL;			}		}		else {			sprintf(Msg,"Unmatched back-quote:");			S_abort();		}	}								/* dialout port name */	if (!strncmp(cptr,"portname",8)){		tok_value.strptr =mport(NIL(char));		*pcptr += 8;		return LITERAL;	}								/* leading hyphen, maybe a negative number? */	if (*cptr=='-')		negpos = (-1),		++cptr;								/* string beginning with a digit */	if (isdigit(*cptr)){		nvalue = (*cptr - '0') * negpos;		while (*(++cptr)){			if (isdigit(*cptr)){				nvalue *= 10;				nvalue += (*cptr - '0');				if (nvalue>0) nvalue *= negpos;				continue;			}			else if (strchr(" \t\n;",*cptr)){				tok_value.numval = nvalue;				*pcptr = cptr;				return NUMBER;			}			sprintf(Msg,"Variable name cannot begin with a digit: ");			S_abort();		}		tok_value.numval = nvalue;		*pcptr = cptr;		return NUMBER;	}					/* check for '-n' switch for echo (type EFLAG) */	if (negpos<0){		if (*cptr=='N' || *cptr=='n'){			while (*cptr && !strchr(" \t\n;",*cptr)) ++cptr;			*pcptr = cptr;			return EFLAG;		}		sprintf(Msg,"Bad option to ECHO command");		S_abort();	}							/* impermissible initial character */	if (!isalpha(*cptr)){		sprintf(Msg,"bad initial character: %c", *cptr);		S_abort();	}		/* remember that tok_value.strptr points to start of token */	for (i=1; i<(VNAMELEN+1); ++i){		/* jump to next field separator */		++cptr;		if (*cptr=='\0' || strchr(" \t\n;",*cptr))			break;	}	if (i>VNAMELEN){						/* word too long */		sprintf(Msg,"Variable name too long");		S_abort();	}	strncpy(latoken,tok_value.strptr,i);	/* copy word to array 'latoken' */	latoken[i] = '\0';	lc_word(latoken);						/* cvt to lowercase */											/* script keywords */					/* scan table for keyword match */	for (i=0; *(s_toktab[i].name) && strcmp(latoken,s_toktab[i].name); ++i)		;	if (*s_toktab[i].name)	{				/* lc keyword recognized */		if (s_toktab[i].token==STRUE)			tok_value.numval = TRUE;		if (s_toktab[i].token==SFALSE)			tok_value.numval = FALSE;		*pcptr = cptr;		return s_toktab[i].token;	}									/* system primitive (ACTION) */									/* scan table for keyword match */	for (i=0;s_acttab[i].name && strcmp(latoken,s_acttab[i].name);++i)		;	if (s_acttab[i].name){			/* primitive recognized */		tok_value.funcptr = s_acttab[i].funcptr;		*pcptr = cptr;		return ACTION;	}									/* user variable name */	if ((varptr=findvar(latoken))){	/* existing user variable */		tok_value.varptr = varptr;		*pcptr = cptr;		return VARNAME;	}				/* could this be the name of a new variable? */	tok_value.strptr = latoken;	/* just in case this is 'on', 'off', etc. */	if (!setvar(latoken,VCHAR,"",0))	/* can't create it */		return TTERROR;	if (!(varptr=findvar(latoken)))	/* can't retrieve it */		return TTERROR;	else {							/* got it */		tok_value.varptr = varptr;		*pcptr = cptr;		return VARNAME;	}}/*		utility routines called by S_parse() *//*	S_affirm is a placeholder. It's the function to get a yes or no	response from the user.*/static intS_affirm(){	char c, junk;	c = getchar();	fputc(c,tfp);	while ((junk=getchar()) !='\n' && junk !='\r')		fputc(junk,tfp);	fputc('\r',tfp),	fputc('\n',tfp);	return(c=='y' || c=='Y');}/*	S_addsub increments or decrements a numeric variable.	It assumes that since the INCR or DECR directives call	lexan() for the variable just before coming here, the	tok_value structure contains a pointer to the variable	whose value is to be changed.*/static intS_addsub(direction)int direction;{	long oldval = tok_value.varptr->u.num;	oldval += direction;	if (!setvar(tok_value.varptr->name,VNUM,"",&oldval)){		sprintf(Msg,"Error setting variable '%s'", tok_value.varptr->name);		S_abort();	}	return(tok_value.varptr->u.num ? SUCCESS : FAILURE);}/*	S_qstrip returns a pointer to a (static) string with leading and	trailing double-quote marks removed. If the string happens to	lack a leading or trailing double-quote mark, then the string	will be returned with its beginning unchanged, and its length	equal to VMAXSIZE or the length of the string, whichever is	shorter. Double-quote marks escaped with a backslash are included	in the returned string and the backslash is excised.*/static char *S_qstrip(strptr)char *strptr;{	int i;	static char strbuf[VMAXSIZE+2];	if (*strptr=='"')		++strptr;	for (i=0; i<VMAXSIZE+1; ++i){		if (*strptr=='\\' && *(strptr+1)=='"' && *(strptr-1)!='\\')			++strptr;		if ((*strptr=='"' && *(strptr-1)!='\\') || !*strptr || *strptr=='\n')			break;		strbuf[i] = *strptr;		++strptr;	}	strbuf[i] = '\0';	return strbuf;}/*	S_read does the parsing grunts for the script 'read' directive.	On	entry, the 'read' token has been parsed, but that's all.*/static intS_read(pcptr)char **pcptr;{	int i;	VAR *varptr1;	static char strbuf[VMAXSIZE+2];	if (lexan(pcptr)!=VARNAME)		S_abort();	varptr1 = tok_value.varptr;	strbuf[0] = '\0';	for (i=0; i<VMAXSIZE; ++i){		strbuf[i] = getchar();		if (strbuf[i]==BS){			if (i>0)				fputs("\b \b",tfp),				i -= 2;			else				i = -1;			continue;		}		fputc(strbuf[i],tfp);		if (strbuf[i]=='\n' || strbuf[i]=='\r'){			strbuf[i] = '\0';			break;		}	}	strbuf[VMAXSIZE] = '\0';	fputc('\r',tfp),	fputc('\n',tfp);	return(setvar(varptr1->name,VCHAR,strbuf,0));}/*	S_perform invokes a system primitive and returns SUCCESS if the	primitive succeeds, FAILURE if it fails. On entry, only the ACTION	token has been parsed.*/static intS_perform(pcptr)char **pcptr;{	int (*fptr)();	char *cptr;	VAR *varptr1;	long n = -1;	fptr = tok_value.funcptr;	cptr = NIL(char);	while (TRUE){		switch (lexan(pcptr)){			case TERMINAT:				break;			case NUMBER:				if (n != -1)					S_abort();				n = tok_value.numval;				continue;			case LITERAL:			case TTERROR:				cptr = S_qstrip(tok_value.strptr);				continue;			case VARNAME:				varptr1 = tok_value.varptr;				if (varptr1->type==VCHAR){						cptr = varptr1->u.str;						break;				}				if (n != -1)					S_abort();				n = varptr1->u.num;				continue;			default:				S_abort();		}		break;	}	return (*fptr)(n,cptr);}/*	S_set does the parsing grunts for the script 'assign' directive. It's	a separate function mostly to keep from cluttering up S_parse()	too much.	On entry, only the 'set' token has been received from	the directive containing it.*/static intS_set(pcptr)char **pcptr;				/* S_parse()'s program counter (p_pc) */{	TOK_TYPE nexttype;	VAR *varptr1, *varptr2;	char *setstr;	if ((nexttype=lexan(pcptr))!=VARNAME)		S_abort();	varptr1 = tok_value.varptr;	if ((nexttype=lexan(pcptr))!=EQ)		S_abort();	switch (nexttype = lexan(pcptr)){		case LITERAL:			setstr = S_qstrip(tok_value.strptr);			return(setvar(varptr1->name,VCHAR,setstr,0));		case ACTION:		case AFFIRM:			if (nexttype==ACTION)				tok_value.numval = (long) S_perform(pcptr);			else				tok_value.numval = (long) S_affirm();		case NUMBER:		case STRUE:		case SFALSE:			return(setvar(varptr1->name,VNUM,"",&tok_value.numval));		case VARNAME:			varptr2 = tok_value.varptr;			switch (varptr2->type){				case VCHAR:					return(setvar(varptr1->name,VCHAR,varptr2->u.str,0));				default:					return(setvar(varptr1->name,VNUM,"",&(varptr2->u.num)));			}		default:			S_abort();	}	return S_abort() ; /* not reached */ }/*	S_varcmp() compares a variable's value with a string or numeric	literal, or with the value of a second variable. Once again,	this function does parsing grunts for S_parse().*/static intS_varcmp(varptr1, pcptr)VAR *varptr1;char **pcptr;{	TOK_TYPE compmode;	long testnum = 0L ;	static char strbuf[VMAXSIZE+1];	char *cmpstr = NULL ;	int status, numvar;	VAR *varptr2;	numvar = (varptr1->type!=VCHAR);	compmode = lexan(pcptr);	switch (compmode){		case EQ:		case NEQ:		case MORETHAN:		case LESSTHAN:			break;		case TERMINAT:			if (numvar)				return(varptr1->u.num ? TRUE : FALSE);			else				return(*varptr1->u.str ? TRUE : FALSE);		default:			S_abort();	}	switch (lexan(pcptr)){		case LITERAL:			if (numvar){				sprintf(Msg,"Error: %s is a numeric variable",varptr1->name);				S_abort();			}			++tok_value.strptr;			strncpy(strbuf,tok_value.strptr,VMAXSIZE);			*(strchr(strbuf,'"')) = '\0';			cmpstr = strbuf;			break;		case NUMBER:		case STRUE:		case SFALSE:			if (!numvar){				sprintf(Msg,"Error: %s is a string variable",varptr1->name);				S_abort();			}			testnum = tok_value.numval;			break;		case VARNAME:			varptr2 = tok_value.varptr;			if (numvar && varptr2->type==VCHAR){				sprintf(Msg,"Error: %s and %s are of different types",					varptr1->name, varptr2->name);				S_abort();			}			if (numvar)				testnum = varptr2->u.num;			else				cmpstr = varptr2->u.str;			break;		default:			S_abort();	}	if (numvar){		status = (varptr1->u.num==testnum);		if (compmode==EQ)			return status;		if (compmode==NEQ)			return !status;		status = (varptr1->u.num > testnum);		if (compmode==MORETHAN)			return status;		else			return !status;	}	status = strcmp(varptr1->u.str,cmpstr);	if (compmode==EQ)		return(status==0);	if (compmode==NEQ)		return status;	if (compmode==MORETHAN)		return(status>0);	else		return(status<0);}static char *S_construct(pcptr)char **pcptr;{	char *cptr;	static char newstring[VMAXSIZE+10];	TOK_TYPE nexttype;	newstring[0] = '\0';	cptr = newstring;	while ((nexttype=lexan(pcptr))!=NULLTOK){		if (strlen(newstring)>VMAXSIZE){			newstring[VMAXSIZE] = '\0';			break;		}		switch (nexttype){			case TERMINAT:				break;			case NUMBER:				sprintf(cptr,"%ld",tok_value.numval);				cptr += strlen(cptr);				continue;			case LITERAL:				sprintf(cptr,"%s",S_qstrip(tok_value.strptr));				cptr += strlen(cptr);

⌨️ 快捷键说明

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