File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / bin / cdb / tk.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
Power 6/32 Unix version 1.2b

static char sccsid[] = "@(#)tk.c	2.6";

#include <ctype.h>
#include "cdb.h"

#define	chTab	'\t'
#define	chSpace	' '
#define chUnder	'_'
#define chDollar '$'
#define	chBackSlash '\\'

export int	vcbTok, vcbPeek;
export TKE	vtk, vtkPeek;
export char	vsbTok[100], vsbTokPeek[100];
export LCE	vlc;	/* the current language which has precedence */

#define icmdMax 20
int	vicmdMac;
char	*vrgCmd[icmdMax];	/* where we push command pointers */

typedef struct {	/* keyword */
	char	*sbKey;
	short	tk;
} 
KWR, *pKWR;
#define cbKWR	sizeof(KWR)
#define kwNil ((pKWR)0)

KWR vrgKwCdb[] = {
	"$in",	tkInside,
};
#define ikwCdbMax (sizeof(vrgKwCdb)/cbKWR)

KWR vrgKwC[] = {
	"sizeof",	tkSizeof,
};
#define ikwCMax (sizeof(vrgKwC)/cbKWR)

KWR vrgKwFor[] = {
	".NE.",	tkNotEqual,
	".EQ.",	tkEqual,
	".LT.",	tkLT,
	".LE.",	tkLE,
	".GT.",	tkGT,
	".GE.",	tkGE,
};
#define ikwForMax (sizeof(vrgKwFor)/cbKWR)

KWR vrgKwPas[] = {
	"and",	tkLAND,
	"or",	tkLOR,
	"not",	tkBang,
	"div",	tkDiv,
	"mod",	tkModulo,
};
#define ikwPasMax (sizeof(vrgKwPas)/cbKWR)

#define isodigit(ch) (isdigit(ch) && (ch!='8') && (ch!='9'))


/* T K   F   K W */

export void TkFKw(ptk, sbKey, rgKw, ikwMax)
TKE	*ptk;
char	*sbKey;
pKWR	rgKw;
int	ikwMax;
{
	int		i;
	for (i=0; i < ikwMax; i++) {
		if (FSbCmp(sbKey, rgKw[i].sbKey)) {
			*ptk = rgKw[i].tk;
			return;
		}
	}
} /* TkFKw */


/* C H   F   E S C A P E */

local char ChFEscape(psbIn)
char	**psbIn;
{
	int		i, val;
	char	ch;

	ch = **psbIn;
	(*psbIn)++;
	if (ch != chBackSlash)
		return(ch);	/* vanilla flavored char */
	ch = **psbIn;
	(*psbIn)++;
	switch (ch) {
	case 'b':	
		return('\b');
	case 'f':	
		return('\f');
	case 'n':	
		return('\n');
	case 'r':	
		return('\r');
	case 't':	
		return('\t');
	case '\\':	
		return('\\');
	case '\'':	
		return('\'');
	case '0': 
	case '1': 
	case '2': 
	case '3':
	case '4': 
	case '5': 
	case '6': 
	case '7':
		/* it is an arbitrary 1-3 octal digit thingie */
		val = 0;
		for (i=0; i<3; i++) {
			val = (val * 8) + (ch - '0');
			ch = **psbIn;	/* look at NEXT character */
			if (!isodigit(ch))
				break;
			(*psbIn)++;	/* is good digit, advance str pointer */
		} /* for */
		return(val);
	} /* switch */
	return(ch);	/* by default we just ignore the backslash */
} /* ChFEscape */


/* T K   F   S T R */

export TKE TkFStr(psbCmd, sbTok, pcb)
char	**psbCmd, *sbTok;
int	*pcb;
{
	int		i;
	char	ch, *sbCmd, *sbStart, sbT[10];
	TKE		tk;

	/* given a string, copy first token to safe place and advance string */

	sbCmd = *psbCmd;
	if (sbCmd == sbNil)
		return(tkNil);

	while (*sbCmd != chNull AND *sbCmd == chTab OR *sbCmd == chSpace)
		sbCmd++;	/* eat leading tabs and spaces */
	if (*sbCmd == chNull) {
		*pcb = 0;
		sbTok[0] = chNull;
		return(tkNil);
	} /* if */

	sbStart = sbCmd; /* remember where we started */

	tk = tkNil;
	ch = *sbCmd++;
	if (isalpha(ch)
	    OR (ch == chUnder)
	    OR (ch == chDollar)) {  /* string (var|command) token */
		tk = tkStr;
		while (isalnum(*sbCmd)
		    OR *sbCmd == chUnder) 
			sbCmd++;
	} 
	else if (isdigit(ch)) {	/* number */
		tk = tkNumber;
		if ((ch == '0') AND (*sbCmd == 'x')) {
			sbCmd++; /* it's a hex number */
			while (isxdigit(*sbCmd))
				sbCmd++;
		} 
		else {
			while (isdigit(*sbCmd))
				sbCmd++;
		} /* if */
	} 
	else if (ispunct(ch)) {
		/* hopefully an interesting operator or something */
		switch (ch) {
		case '[':	
			tk = tkLSB;	
			break;
		case ']':	
			tk = tkRSB;	
			break;
		case '(':	
			tk = tkLP;	
			break;
		case ')':	
			tk = tkRP;	
			break;
		case '{':	
			tk = tkLCB;	
			break;
		case '}':	
			tk = tkRCB;	
			break;
		case '?':	
			tk = tkQuest;	
			break;
		case '@':	
			tk = tkAt;	
			break;
		case '$':	
			tk = tkDollar;	
			break;
		case '#':	
			tk = tkHash;	
			break;
		case ';':	
			tk = tkSemi;	
			break;
		case ',':	
			tk = tkComma;	
			break;
		case '_':	
			tk = tkUnderScore; 
			break;
		case '\\':	
			tk = tkBackSlash; 
			break;
		case '\'':	
			tk = tkCharConstant;
			sbTok[0] = ChFEscape(&sbCmd);
			if (*sbCmd != '\'')
				UError("Character constant is missing ending '");
			sbCmd++;
			*pcb = 1;
			goto special;
		case '"':	
			tk = tkStrConstant;
			i = 0;
			while ((*sbCmd != chNull) AND (*sbCmd != '"')) {
				sbTok[i] = ChFEscape(&sbCmd);
				i++;
			} /* while */
			if (*sbCmd != '"')
				UError("String constant is missing ending \"");
			sbCmd++;
			*pcb = i;
			goto special;
		case '.':	
			tk = tkDot;
			if (vlc != lcFortran)
				break;
			if (sbCmd[2] == '.') {
				/* we have '.XX.' - might be a relop */
				strncpy(sbT, sbCmd-1, 4); /* get the whole thing */
				TkFKw(&tk, sbT, vrgKwFor, ikwForMax);
				if (tk != tkDot) {
					/* we have a hit */
					sbCmd += 3;
				}
			}
			break;
		case ':':	
			tk = tkColon;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssign;
			} /* if */
			break;
		case '+':	
			tk = tkPlus;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssPlus;
			} /* if */
			break;
		case '-':	
			tk = tkMinus;
			if (*sbCmd == '>') {
				sbCmd++;
				tk = tkPtr;
			} 
			else if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssMinus;
			} /* if */
			break;
		case '*':	
			tk = tkStar;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssMult;
			} /* if */
			break;
		case '/':	
			tk = tkSlash;
			if (*sbCmd == '/') {
				sbCmd++;
				tk = tkDiv;
				if (*sbCmd == '=') {
					sbCmd++;
					tk = tkAssDiv;
				} /* if */
			} /* if */
			break;
		case '%':	
			tk = tkModulo;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssMod;
			} /* if */
			break;
		case '&':	
			tk = tkBitAnd;
			if (*sbCmd == '&') {
				sbCmd++;
				tk = tkLAND;
			} 
			else if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssBAND;
			} /* if */
			break;
		case '|':	
			tk = tkBitOr;
			if (*sbCmd == '|') {
				sbCmd++;
				tk = tkLOR;
			} 
			else if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssBOR;
			} /* if */
			break;
		case '^':	
			tk = tkXOR;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkAssXOR;
			} 
			else if (*sbCmd == '.') {
				if (vlc == lcPascal) {
					sbCmd++;
					tk = tkPtr;
				}
			} /* if */
			break;
		case '~':	
			tk = tkTilda;
			break;
		case '!':	
			tk = tkBang;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkNotEqual;
			} /* if */
			break;
		case '=':	
			if (vlc == lcPascal) {
				tk = tkEqual;
			} 
			else {
				tk = tkAssign;
				if (*sbCmd == '=') {
					sbCmd++;
					tk = tkEqual;
				} /* if */
			}
			break;
		case '<':	
			tk = tkLT;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkLE;
			} 
			else if (*sbCmd =='<') {
				sbCmd++;
				tk = tkLShift;
				if (*sbCmd == '=') {
					sbCmd++;
					tk = tkAssLeft;
				} /* if */
			} 
			else if (*sbCmd == '>') {
				sbCmd++;
				tk = tkNotEqual;
			} /* if */
			break;
		case '>':	
			tk = tkGT;
			if (*sbCmd == '=') {
				sbCmd++;
				tk = tkGE;
			} 
			else if (*sbCmd =='>') {
				sbCmd++;
				tk = tkRShift;
				if (*sbCmd == '=') {
					sbCmd++;
					tk = tkAssRight;
				} /* if */
			} /* if */
			break;
		} /* switch */
	} 
	else { /* it's  <something else> !! */
		tk = tkOther;
	} /* if */

	*pcb = sbCmd - sbStart;
	strncpy(sbTok, sbStart, *pcb);

special:	/* used by character and string constant routines */
	sbTok[*pcb] = chNull;
	*psbCmd = sbCmd;

	if (tk == tkStr) {
		TkFKw(&tk, sbTok, vrgKwCdb, ikwCdbMax);
		switch (vlc) {
		case lcC:		
			TkFKw(&tk, sbTok, vrgKwC, ikwCMax); 
			break;
		case lcPascal:	
			TkFKw(&tk, sbTok, vrgKwPas, ikwPasMax); 
			break;
		case lcFortran:	
			TkFKw(&tk, sbTok, vrgKwFor, ikwForMax); 
			break;
		} /* switch */
	}

	return(tk);
} /* TkFStr */


/* P O P   C M D */

export char * PopCmd()
{
	if (vicmdMac == 0)
		return(sbNil);
	return(vrgCmd[--vicmdMac]);
} /* PopCmd */


/* P U S H   C M D */

export void PushCmd(sbCmd)
char	*sbCmd;
{
	if (sbCmd == sbNil OR *sbCmd == chNull)
		return;
	if (vicmdMac >= icmdMax) {
		vicmdMac = 0;
		Panic("Too much command nesting - flushing everything");
	} /* if */
	vrgCmd[vicmdMac++] = sbCmd;
} /* PushCmd */


/* T K   P E E K */

export TKE TkPeek()
{
	char	*sbCmd;
	/* used to peek at next token in global command line */
	sbCmd = vsbCmd;
	vtkPeek = TkFStr(&sbCmd, vsbTokPeek, &vcbPeek);
	return(vtkPeek);
} /* TkPeek */


/* T K   N E X T */

export TKE TkNext()
{
	/* used by most routines to eat next token in the global command line */
	while ((vtk = TkFStr(&vsbCmd, vsbTok, &vcbTok)) == tkNil) {
		if (vicmdMac == 0)
			return(tkNil);
		vsbCmd = PopCmd();
	} /* while */
	return(vtk);
} /* TkNext */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.