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

📄 vc.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic	char	*sccsid = "@(#)vc.c	4.1	(ULTRIX)	7/17/90";#endif lint# include	"stdio.h"# include	"sys/types.h"# include	"macros.h"# include	"fatal.h"/* * The symbol table size is set to a limit of forty keywords per input * file.  Should this limit be changed it should also be changed in the * Help file. */# define SYMSIZE 40# define PARMSIZE 10# define NSLOTS 32# define USD  1# define DCL 2# define ASG 4# define EQ '='# define NEQ '!'# define GT '>'# define LT '<'# define DELIM " \t"# define TRUE 1# define FALSE 0char Error[128];char	Ctlchar = ':';struct	symtab	{	int	usage;	char	name[PARMSIZE];	char	*value;	int	lenval;};struct	symtab	Sym[SYMSIZE];int	Skiptabs;int	Repall;/* * Delflag is used to indicate when text is to be skipped.  It is decre- * mented whenever an if condition is false, or when an if occurs * within a false if/end statement.  It is decremented whenever an end is * encountered and the Delflag is greater than zero.  Whenever Delflag * is greater than zero text is skipped. */int	Delflag;/* * Ifcount keeps track of the number of ifs and ends.  Each time * an if is encountered Ifcount is incremented and each time an end is * encountered it is decremented. */int	Ifcount;int	Lineno;char	*Repflag;char	*Linend;int	Silent;char	*getid(), *replace();char	*findch(), *ecopy(), *findstr();char	*fmalloc();/* * The main program reads a line of text and sends it to be processed * if it is a version control statement. If it is a line of text and * the Delflag is equal to zero, it is written to the standard output. */main(argc, argv)int argc;char *argv[];{	register  char *lineptr, *p;	register int i;	char line[512];	extern int Fflags;	Fflags = FTLCLN | FTLMSG | FTLEXIT;	setsig();	for(i = 1; i< argc; i++) {		p = argv[i];		if (p[0] == '-')			switch (p[1]) {			case 's':				Silent = 1;				break;			case 't':				Skiptabs = 1;				break;			case 'a':				Repall = 1;				break;			case 'c':				Ctlchar = p[2];				break;			}		else {			p[size(p) - 1] = '\n';			asgfunc(p);		}	}	while (fgets(line,sizeof(line),stdin) != NULL) {		lineptr = line;		Lineno++;		if (Repflag != 0) {			ffree(Repflag);			Repflag = 0;		}		if (Skiptabs) {			for (p = lineptr; *p; p++)				if (*p == '\t')					break;			if (*p++ == '\t')				lineptr = p;		}		if (lineptr[0] != Ctlchar) {			if (lineptr[0] == '\\' && lineptr[1] == Ctlchar)				for (p = &lineptr[1]; *lineptr++ = *p++; )					;			if(Delflag == 0) {				if (Repall)					repfunc(line);				else					fputs(line,stdout);			}			continue;		}		lineptr++;		if (imatch("if ", lineptr))			iffunc(&lineptr[3]);		else if (imatch("end", lineptr))			endfunc();		else if (Delflag == 0) {			if (imatch("asg ", lineptr))				asgfunc(&lineptr[4]);			else if (imatch("dcl ", lineptr))				dclfunc(&lineptr[4]);			else if (imatch("err", lineptr))				errfunc(&lineptr[3]);			else if (imatch("msg", lineptr))				msgfunc(&lineptr[3]);			else if (lineptr[0] == Ctlchar)				repfunc(&lineptr[1]);			else if (imatch("on", lineptr))				Repall = 1;			else if (imatch("off", lineptr))				Repall = 0;			else if (imatch("ctl ", lineptr))				Ctlchar = lineptr[4];			else {				sprintf(Error,"unknown command on line %d (vc1)",					Lineno);				fatal(Error);			}		}	}	for(i = 0; Sym[i].usage != 0 && i<SYMSIZE; i++) {		if ((Sym[i].usage&USD) == 0 && !Silent)			fprintf(stderr,"`%s' never used (vc2)\n",Sym[i].name);		if ((Sym[i].usage&DCL) == 0 && !Silent)			fprintf(stderr,"`%s' never declared (vc3)\n",				Sym[i].name);		if ((Sym[i].usage&ASG) == 0 && !Silent)			fprintf(stderr,"`%s' never assigned a value (vc20)\n",				Sym[i].name);	}	if (Ifcount > 0)		fatal("`if' with no matching `end' (vc4)");	exit(0);}/* * Asgfunc accepts a pointer to a line picks up a keyword name, an * equal sign and a value and calls putin to place it in the symbol table. */asgfunc(aptr)register char *aptr;{	register char *end, *aname;	char *avalue;	aptr = replace(aptr);	NONBLANK(aptr);	aname = aptr;	end = Linend;	aptr = findstr(aptr,"= \t");	if (*aptr == ' ' || *aptr == '\t') {		*aptr++ = '\0';		aptr = findch(aptr,'=');	}	if (aptr == end) {		sprintf(Error,"syntax on line %d (vc17)",Lineno);		fatal(Error);	}	*aptr++ = '\0';	avalue = getid(aptr);	chksize(aname);	putin(aname, avalue);}/* * Dclfunc accepts a pointer to a line and picks up keywords * separated by commas.  It calls putin to put each keyword in the * symbol table.  It returns when it sees a newline. */dclfunc(dptr)register char *dptr;{	register char *end, *dname;	int i;	dptr = replace(dptr);	end = Linend;	NONBLANK(dptr);	while (dptr < end) {		dname = dptr;		dptr = findch(dptr,',');		*dptr++ = '\0';		chksize(dname);		if (Sym[i = lookup(dname)].usage&DCL) {			sprintf(Error,"`%s' declared twice on line %d (vc5)", 				dname, Lineno);			fatal(Error);		}		else			Sym[i].usage |= DCL;		NONBLANK(dptr);	}}/* * Errfunc calls fatal which stops the process. */errfunc(eptr)char *eptr;{	if (!Silent)		fprintf(stderr,"ERROR:%s\n",replace(eptr));	sprintf(Error,"err statement on line %d (vc15)", Lineno);	fatal(Error);}/* * Endfunc indicates an end has been found by decrementing the if count * flag.  If because of a previous if statement, text was being skipped, * Delflag is also decremented. */endfunc(){	if (--Ifcount < 0) {		sprintf(Error,"`end' without matching `if' on line %d (vc10)",			Lineno);		fatal(Error);	}	if (Delflag > 0)		Delflag--;	return;}/* * Msgfunc accepts a pointer to a line and prints that line on the  * diagnostic output. */msgfunc(mptr)char *mptr;{	if (!Silent)		fprintf(stderr,"Message(%d):%s\n", Lineno, replace(mptr));}repfunc(s)char *s;{	fprintf(stdout,"%s\n",replace(s));}/* * Iffunc and the three functions following it, door, doand, and exp * are responsible for parsing and interperting the condition in the * if statement.  The BNF used is as follows: *	<iffunc> ::=   [ "not" ] <door> EOL *	<door> ::=     <doand> | <doand> "|" <door> *	<doand>::=     <exp> | <exp> "&" <doand> *	<exp>::=       "(" <door> ")" | <value> <operator> <value> *	<operator>::=  "=" | "!=" | "<" | ">" * And has precedence over or.  If the condition is false the Delflag * is bumped to indicate that lines are to be skipped. * An external variable, sptr is used for processing the line in * iffunc, door, doand, exp, getid. * Iffunc accepts a pointer to a line and sets sptr to that line.  The * rest of iffunc, door, and doand follow the BNF exactly. */char *sptr;iffunc(iptr)char *iptr;{	register int value, not;	Ifcount++;	if (Delflag > 0)		Delflag++;	else {		sptr = replace(iptr);		NONBLANK(sptr);		if (imatch("not ", sptr)) {			not = FALSE;			sptr += 4;		}		else not = TRUE;		value = door();		if( *sptr != 0) {			sprintf(Error,"syntax on line %d (vc18)",Lineno);			fatal(Error);		}		if (value != not)			Delflag++;	}	return;}door(){	int value;	value = doand();	NONBLANK(sptr);	while (*sptr=='|') {		sptr++;		value |= doand();		NONBLANK(sptr);	}	return(value);}doand(){	int value;	value = exp();	NONBLANK(sptr);	while (*sptr=='&') {		sptr++;		value &= exp();		NONBLANK(sptr);	}	return(value);}/* * After exp checks for parentheses, it picks up a value by calling getid, * picks up an operator and calls getid to pick up the second value. * Then based on the operator it calls either numcomp or equal to see * if the exp is true or false and returns the correct value. */exp(){	register char op, save;	register int value;	char *id1, *id2, next;	NONBLANK(sptr);	if(*sptr == '(') {		sptr++;		value = door();		NONBLANK(sptr);		if (*sptr == ')') {			sptr++;			return(value);		}		else {			sprintf(Error,"parenthesis error on line %d (vc11)",				Lineno);		}	}	id1 = getid(sptr);	if (op = *sptr)		*sptr++ = '\0';	if (op == NEQ && (next = *sptr++) == '\0')		--sptr;	id2 = getid(sptr);	save = *sptr;	*sptr = '\0';	if(op ==LT || op == GT) {		value = numcomp(id1, id2);		if ((op == GT && value == 1) || (op == LT && value == -1))			value = TRUE;		else value = FALSE;	}	else if (op==EQ || (op==NEQ && next==EQ)) {		value = equal(id1, id2);		if ( op == NEQ)			value = !value;	}	else {		sprintf(Error,"invalid operator on line %d (vc12)", Lineno);		fatal(Error);	}	*sptr = save;	return(value);}/* * Getid picks up a value off a line and returns a pointer to the value. */char *getid(gptr)register char *gptr;{	register char *id;	NONBLANK(gptr);	id = gptr;	gptr = findstr(gptr,DELIM);	if (*gptr)		*gptr++ = '\0';	NONBLANK(gptr);	sptr = gptr;	return(id);}/* * Numcomp accepts two pointers to strings of digits and calls numck * to see if the strings contain only digits.  It returns -1 if * the first is less than the second, 1 if the first is greater than the * second and 0 if the two are equal. */numcomp(id1, id2)register char *id1, *id2;{	int k1, k2;	numck(id1);	numck(id2);	while (*id1 == '0')		id1++;	while (*id2 == '0')		id2++;	if ((k1 = size(id1)) > (k2 = size(id2)))		return(1);	else if (k1 < k2)		return(-1);	else while(*id1 != '\0') {		if(*id1 > *id2)			return(1);		else if(*id1 < *id2)			return(-1);		id1++;		id2++;	}	return(0);}/* * Numck accepts a pointer to a string and checks to see if they are * all digits.  If they're not it calls fatal, otherwise it returns. */numck(nptr)register char *nptr;{	for (; *nptr != '\0'; nptr++)		if (!numeric(*nptr)) {			sprintf(Error,"non-numerical value on line %d (vc14)",				Lineno);			fatal(Error);		}	return;}/* * Replace accepts a pointer to a line and scans the line for a keyword * enclosed in control characters.  If it doesn't find one it returns * a pointer to the begining of the line.  Otherwise, it calls * lookup to find the keyword. * It rewrites the line substituting the value for the * keyword enclosed in control characters.  It then continues scanning * the line until no control characters are found and returns a pointer to * the begining of the new line. */# define INCR(int) if (++int==NSLOTS) { \		sprintf(Error,"out of space [line %d] (vc16)",Lineno); \		fatal(Error); }char *replace(ptr)char *ptr;{	char *slots[NSLOTS];	int i,j,newlen;	register char *s, *t, *p;	for (s=ptr; *s++!='\n';);	*(--s) = '\0';	Linend = s;	i = -1;	for (p=ptr; *(s=findch(p,Ctlchar)); p=t) {		*s++ = '\0';		INCR(i);		slots[i] = p;		if (*(t=findch(s,Ctlchar))==0) {			sprintf(Error,"unmatched `%c' on line %d (vc7)",				Ctlchar,Lineno);			fatal(Error);		}		*t++ = '\0';		INCR(i);		slots[i] = Sym[j = lookup(s)].value;		Sym[j].usage |= USD;	}	INCR(i);	slots[i] = p;	if (i==0) return(ptr);	newlen = 0;	for (j=0; j<=i; j++)		newlen += (size(slots[j])-1);	t = Repflag = fmalloc(++newlen);	for (j=0; j<=i; j++)		t = ecopy(slots[j],t);	Linend = t;	return(Repflag);}/* * Lookup accepts a pointer to a keyword name and searches the symbol * table for the keyword.  It returns its index in the table if its there, * otherwise it puts the keyword in the table. */lookup(lname)char *lname;{	register int i;	register char *t;	register struct symtab *s;	t = lname;	while ((i = *t++) &&		((i>='A' && i<='Z') || (i>='a' && i<='z') ||			(i!= *lname && i>='0' && i<='9')));	if (i) {		sprintf(Error,"invalid keyword name on line %d (vc9)",Lineno);		fatal(Error);	}	for(i =0; Sym[i].usage != 0 && i<SYMSIZE; i++)		if (equal(lname, Sym[i].name)) return(i);	s = &Sym[i];	if (s->usage == 0) {		copy(lname,s->name);		copy("",(s->value = fmalloc(s->lenval = 1)));		return(i);	}	fatal("out of space (vc6)");}/* * Putin accepts a pointer to a keyword name, and a pointer to a value. * It puts this information in the symbol table by calling lookup. * It returns the index of the name in the table. */putin(pname, pvalue)char *pname;char *pvalue;{	register int i;	register struct symtab *s;	s = &Sym[i = lookup(pname)];	ffree(s->value);	s->lenval = size(pvalue);	copy(pvalue, (s->value = fmalloc(s->lenval)));	s->usage |= ASG;	return(i);}chksize(s)char *s;{	if (size(s) > PARMSIZE) {		sprintf(Error,"keyword name too long on line %d (vc8)",Lineno);		fatal(Error);	}}char *findch(astr,match)char *astr, match;{	register char *s, *t, c;	char *temp;	for (s=astr; (c = *s) && c!=match; s++)		if (c=='\\') {			if (s[1]==0) {				sprintf(Error,"syntax on line %d (vc19)",Lineno);				fatal(Error);			}			else {				for (t = (temp=s) + 1; *s++ = *t++;);				s = temp;			}		}	return(s);}char *ecopy(s1,s2)char *s1, *s2;{	register char *r1, *r2;	r1 = s1;	r2 = s2;	while (*r2++ = *r1++);	return(--r2);}char *findstr(astr,pat)char *astr, *pat;{	register char *s, *t, c;	char *temp;	for (s=astr; (c = *s) && any(c,pat)==0; s++)		if (c=='\\') {			if (s[1]==0) {				sprintf(Error,"syntax on line %d (vc19)",Lineno);				fatal(Error);			}			else {				for (t = (temp=s) + 1; *s++ = *t++;);				s = temp;			}		}	return(s);}

⌨️ 快捷键说明

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