|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.