/*****************************************************************************
** FILE IDENTIFICATION
**
-** POL - Problem Oriented Language
+** POL - Problem Oriented Language
**
** This is part of the CTSim program
-** Copyright (c) 1983-2001 Kevin Rosenberg
-**
-** $Id$
+** Copyright (c) 1983-2009 Kevin Rosenberg
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License (version 2) as
const struct POL::KeywordCodeList POL::cmdlist[] = {
- { "eoc", PC_EOC,},
- { "str", PC_STR,},
- { "com", PC_COM,},
- { "cmd", PC_CMD,},
- { "prg", PC_PRG,},
- { "con", PC_CON,},
- { "out", PC_OUT,},
- { "ter", PC_TER,},
- { "inb", PC_INB,},
-
- { "nl_eoc",PC_NL_EOC,},
- { "nl_neoc", PC_NL_NEOC,},
- { "tron", PC_TRON,},
- { "troff", PC_TROFF,},
- { "file", PC_FILE,},
- { "dump", PC_DUMP,},
+ { "eoc", PC_EOC,},
+ { "str", PC_STR,},
+ { "com", PC_COM,},
+ { "cmd", PC_CMD,},
+ { "prg", PC_PRG,},
+ { "con", PC_CON,},
+ { "out", PC_OUT,},
+ { "ter", PC_TER,},
+ { "inb", PC_INB,},
+
+ { "nl_eoc",PC_NL_EOC,},
+ { "nl_neoc", PC_NL_NEOC,},
+ { "tron", PC_TRON,},
+ { "troff", PC_TROFF,},
+ { "file", PC_FILE,},
+ { "dump", PC_DUMP,},
};
const unsigned int POL::NUMCMD = (sizeof(POL::cmdlist) / sizeof (struct POL::KeywordCodeList));
{
}
-void
+void
POL::init ()
{
meta.eoc = SEMICOL;
meta.out = DOLLAR;
meta.ter = PERCENT;
meta.inb = LBRACK;
-
+
m_bNewlineIsEOC = true;
m_szSkipChars[0] = EOS;
-
-
+
+
for (unsigned int i = 0; i < NUMCMD; i++)
cmdtable.installKeywordCode (cmdlist[i].keyword, cmdlist[i].code);
-
- token.ready = false; // no token read yet
+
+ token.ready = false; // no token read yet
}
* char *w - word for pol to ignore and skip over in input
*
* tok() compares all tokens to words given to this routine. If it finds it,
-* it will immediately read another token.
+* it will immediately read another token.
*/
-void
+void
POL::addSkipWord (const char* const w)
{
skiptable.installKeywordCode (w, 0);
*
* skip all characters that appear in string s
*/
-void
+void
POL::addSkipChar (int c)
{
int n = strlen (m_szSkipChars);
/* get_word - matches tokens on a letter by letter basis
*
* char *search - string to search for
-* int nlet - maximum number of chars to search for match
+* int nlet - maximum number of chars to search for match
*/
-bool
-POL::readWord (char *search, int nlet)
+bool
+POL::readWord (const char *search, int nlet)
{
tok (&token);
if (m_bTrace)
sys_error (ERR_TRACE, "POL matching current token %s against word %s\n", token.tokstr, search);
-
+
if (strncasecmp (search, token.tokstr, nlet) == 0) {
dumptok (&token);
return (true);
}
/* usertok (str,code)
-* see if current token is a user defined token set with install()
+* see if current token is a user defined token set with install()
*
* char *str - token string as read from input
* int *code - returned code for user defined symbol
* return value - true if current token has been user defined
-* false if current token is not user defined
+* false if current token is not user defined
*/
bool
POL::readUserToken (char *str, int *code)
{
tok (&token);
-
+
if (m_bTrace)
sys_error (ERR_TRACE, "POL checking if current token '%s' is user defined\n", token.tokstr);
-
+
if (token.type == TT_USERTOK) {
*code = token.code;
strcpy (str, token.tokstr);
POL::readString (char *str)
{
tok (&token);
-
+
if (token.type == TT_STRING) {
strcpy (str, token.tokstr);
dumptok (&token);
/* integer - test for an integer
*
-* int *n: returned integer value
+* int *n: returned integer value
* int typecode = TT_INT if accept only integer values
-* = TT_REAL if accept both real and integer values
+* = TT_REAL if accept both real and integer values
* int boundcode= true if force to lie between boundries
-* = false can take any value it likes
-* int bb1: lower bound
-* int bb2: upper bound
+* = false can take any value it likes
+* int bb1: lower bound
+* int bb2: upper bound
*/
-bool
+bool
POL::readInteger (int *n, int typecode, bool boundcode, int bb1, int bb2)
{
tok (&token);
-
+
if (m_bTrace)
sys_error (ERR_TRACE, "POL checking if current token %s is an integer\n", token.tokstr);
-
+
if (token.type == TT_INT || token.type == TT_REAL) {
- if (boundcode) {
+ if (boundcode) {
if (token.inum < bb1)
*n = bb1;
else if (token.inum > bb2)
*n = bb2;
else
*n = token.inum;
- } else
+ } else
*n = token.inum;
dumptok (&token);
return (true);
POL::readFloat (double *n, double typecode, bool boundcode, double bb1, double bb2)
{
tok (&token);
-
+
if (m_bTrace)
sys_error (ERR_TRACE, "POL checking if current token %s is an floating point number\n", token.tokstr);
-
+
if (token.type == TT_INT || token.type == TT_REAL) {
- if (boundcode) {
+ if (boundcode) {
if (token.fnum < bb1)
*n = bb1;
else if (token.fnum > bb2)
*n = bb2;
else
*n = token.fnum;
- } else
+ } else
*n = token.fnum;
dumptok (&token);
return (true);
}
/*----------------------------------------------------------------------*/
-/* skip() - skip over any token except for end of command sequence */
-/* */
-/* returns true if succesful skip */
-/* returns false if already at end of command or EOF */
+/* skip() - skip over any token except for end of command sequence */
+/* */
+/* returns true if succesful skip */
+/* returns false if already at end of command or EOF */
/*----------------------------------------------------------------------*/
-bool
+bool
POL::skipTokens()
{
- char term[5]; /* string of characters not to skip */
-
+ char term[5]; /* string of characters not to skip */
+
term[0] = meta.eoc;
if (m_bNewlineIsEOC) {
term[1] = NEWLINE;
term[2] = EOS;
} else
term[1] = EOS;
-
+
return (skipSingleToken (term));
}
-void
+void
POL::reader()
{
while (skipTokens())
;
-
- dumptok (&token); /* skip end of command token */
+
+ dumptok (&token); /* skip end of command token */
}
/* skiptok (term) - skip a token unless the first character of a token is
-* in the string of terminators, term.
+* in the string of terminators, term.
* char *term - string of termination characters, don't skip these characters
-* skiptok() also does NOT skip TT_EOF
+* skiptok() also does NOT skip TT_EOF
* returns (true) if succesful skip of a token
* returns (false) if didn't skip, read termination character or TT_EOF
*/
-bool
+bool
POL::skipSingleToken (char term[])
{
tok (&token);
-
+
if (token.type == TT_EOF
|| (token.type == TT_SPECLCHAR && strchr(term, token.tokstr[0]) != NULL))
return (false);
}
}
-int
+int
POL::tok (struct token_st *token)
{
if (token->ready == false)
return (token->type);
}
-void
+void
POL::dumptok (struct token_st *token)
{
if (token->ready == false)
token->ready = false;
}
-int
+int
POL::getpol_tok (struct token_st *token)
{
KeywordCodeEntry* sym;
-
+
token->ready = false;
nexttok:
gettok (token);
-
+
if (token->type == TT_BLANK)
goto nexttok;
if (token->type == TT_SPECLCHAR) {
getcmd();
goto nexttok;
}
- if (token->tokstr[0] == meta.com) { /* skip comment */
+ if (token->tokstr[0] == meta.com) { /* skip comment */
eatline ();
goto nexttok;
}
fputs (token->tokstr, stderr);
goto nexttok;
}
- if (token->tokstr[0] == meta.con) { /* continuation across NEWLINE */
+ if (token->tokstr[0] == meta.con) { /* continuation across NEWLINE */
while (lookchar() == BLANK || lookchar() == TAB)
inchar();
if (lookchar() == NEWLINE)
inchar();
}
- if (token->tokstr[0] == meta.ter) { /* get input from terminal */
+ if (token->tokstr[0] == meta.ter) { /* get input from terminal */
usefile (P_USE_FILE, "");
tok (token);
closefile();
return (token->type);
}
}
-
+
/* look for filler words */
-
- if (skiptable.lookup (token->tokstr) != NULL) /* ignore words in skip table */
+
+ if (skiptable.lookup (token->tokstr) != NULL) /* ignore words in skip table */
goto nexttok;
-
+
/* look for user defined symbols */
-
+
if ((sym = usertable.lookup (token->tokstr)) != NULL) {
token->type = TT_USERTOK;
token->code = sym->getCode();
} else
token->code = 0;
-
+
if (m_bTrace)
sys_error (ERR_TRACE, "POL read token '%s', type = %d\n", token->tokstr, token->type);
-
+
return (token->type);
}
-int
+int
POL::getcmd()
{
int tt, found;
char str[MAXTOK+1];
KeywordCodeEntry *cmd;
TOKEN tok;
-
+
tt = getalpha (str, MAXTOK);
if (tt == TT_ERROR) {
sys_error (ERR_WARNING, "Error in POL parameter command");
found = false;
switch (cmd->getCode()) {
case PC_TRON:
- m_bTrace = true;
+ m_bTrace = true;
found = true;
break;
case PC_TROFF:
- m_bTrace = false;
+ m_bTrace = false;
found = true;
break;
case PC_FILE:
- found = true;
+ found = true;
tt = gettok (&tok);
usefile (P_USE_FILE, tok.tokstr);
break;
case PC_NL_EOC:
- found = true;
+ found = true;
m_bNewlineIsEOC = true;
break;
case PC_NL_NEOC:
- found = true;
+ found = true;
m_bNewlineIsEOC = false;
break;
case PC_DUMP:
- found = true;
+ found = true;
printf("eoc = %c str = %c com = %c cmd = %c prg = %c\n",
meta.eoc, meta.str, meta.com, meta.cmd, meta.prg);
printf("con = %c out = %c ter = %c inb = %c\n",
meta.con, meta.out, meta.ter, meta.inb);
- break;
+ break;
}
if (found == false) {
tt = gettok (&tok);
return (false);
}
switch(cmd->getCode()) {
- case PC_EOC:
+ case PC_EOC:
meta.eoc = tok.tokstr[0];
break;
case PC_STR:
default:
printf("command not implemented\n");
break;
- } /* switch (tok->type) */
- } /* if (found == false) */
- reader(); /* clean up command */
- } /* if legal command */
-
+ } /* switch (tok->type) */
+ } /* if (found == false) */
+ reader(); /* clean up command */
+ } /* if legal command */
+
return (true);
}
-int
+int
POL::gettok (TOKEN *tok)
{
int c, toktype;
int inum;
double fnum;
- int toksiz = MAXTOK; /* maximum length of token string */
-
+ int toksiz = MAXTOK; /* maximum length of token string */
+
while ((c = inchar()) == BLANK || c == TAB)
;
ungetch (c);
-
+
c = lookchar();
toktype = type(c);
-
+
fnum = 0.0;
inum = 0;
-
- if (c == BLANK || c == TAB) { /* skip white space */
+
+ if (c == BLANK || c == TAB) { /* skip white space */
getblank(tok->tokstr, toksiz);
toktype = TT_BLANK;
} else if (toktype == LETTER) {
toktype = getalpha (tok->tokstr, toksiz);
- } else if (c == meta.str) { /* quoted string */
+ } else if (c == meta.str) { /* quoted string */
getquote (tok->tokstr, toksiz);
toktype = TT_STRING;
} else if (type(c) == DIGIT || c == PLUS || c == HYPHEN || c == PERIOD) {
tok->tokstr[1] = EOS;
toktype = TT_SPECLCHAR;
}
-
+
tok->type = toktype;
tok->ready = true;
if (tok->type == TT_REAL || tok->type == TT_INT) {
tok->fnum = 0.0;
tok->inum = 0;
}
-
+
return (toktype);
}
-void
+void
POL::getblank (char *s, int toksiz)
{
int c;
-
+
while ((c = inchar()) == BLANK || c == TAB)
;
ungetch(c);
-
+
s[0] = BLANK;
s[1] = EOS;
}
-int
+int
POL::getalpha (char *s, int toksiz)
{
int i, chartype, alphatype;
-
+
if (type(lookchar()) != LETTER) {
s[0] = EOS;
return (TT_ERROR);
}
-
+
alphatype = TT_ALPHA;
- for (i = 0; i < toksiz; i++) { /* get alphanumeric token */
+ for (i = 0; i < toksiz; i++) { /* get alphanumeric token */
s[i] = inchar();
chartype = type (s[i]);
if (chartype != LETTER && chartype != DIGIT)
alphatype = TT_ALPNUM;
}
ungetch(s[i]);
-
+
if (i >= toksiz)
sys_error (ERR_SEVERE, "POL token too long.");
-
- s[i] = EOS; /* terminate token */
+
+ s[i] = EOS; /* terminate token */
return (alphatype);
}
/* getquote - get quoted string from file */
/* have already gotten delimiter in qs[0] */
-void
+void
POL::getquote (char *qs, int toksiz)
{
int delim;
-
- delim = inchar(); /* char = delimiter */
+
+ delim = inchar(); /* char = delimiter */
getescape(qs, delim, toksiz);
}
-void
-POL::getescape ( /* reads up to delim */
+void
+POL::getescape ( /* reads up to delim */
char *s,
int delim,
int toksiz
)
{
int i, c;
-
+
for (i = 0; (c = inchar()) != delim; i++) {
if (c == NEWLINE) {
sys_error (ERR_WARNING, "Missing closing delimiter.");
ungetch(c);
sys_error (ERR_SEVERE, "end of file inside quotation");
break;
- } else if (c == BSLASH) { /* escape character */
+ } else if (c == BSLASH) { /* escape character */
s[i++] = c;
- c = inchar(); /* get escaped character */
+ c = inchar(); /* get escaped character */
}
s[i] = c;
}
}
-bool
+bool
POL::readText (char *str, int lim)
{
int c;
str[0] = 0;
return false;
}
-
+
int i;
for (i = 0; i < lim && (c = inchar()) != EOF && c != NEWLINE; i++)
str[i] = c;
ungetch (c);
str[i] = 0;
-
+
return true;
}
//----------------------------------------------
-// Get a number for gettok()
+// Get a number for gettok()
//----------------------------------------------
-int
-POL::getnumber
+int
+POL::getnumber
(
- char str[], /* string to return token in */
- int strsize, /* maximum length of token string */
- double *fnum, /* floating point value of number read */
- int *inum /* integer value of number read */
+ char str[], /* string to return token in */
+ int strsize, /* maximum length of token string */
+ double *fnum, /* floating point value of number read */
+ int *inum /* integer value of number read */
)
{
int sp = 0;
double sign = 1.0;
- bool isSigned = false; /* true if number prefixed by '+' or '-' */
+ bool isSigned = false; /* true if number prefixed by '+' or '-' */
*fnum = 0.0;
*inum = 0;
str[0] = EOS;
-
+
int c = inchar();
if (c == HYPHEN) {
str[sp++] = c;
return (TT_ERROR);
} else
ungetch (c);
-
+
if (isSigned) {
c = lookchar();
if (c == PERIOD) {
- inchar(); /* get period */
- c = lookchar(); /* look at character past period */
- ungetch (PERIOD); /* put back period */
+ inchar(); /* get period */
+ c = lookchar(); /* look at character past period */
+ ungetch (PERIOD); /* put back period */
if (type(c) != DIGIT) {
str[sp] = EOS;
return (TT_SPECLCHAR);
return (TT_SPECLCHAR);
}
}
-
+
double whole = 0.0;
while (type(c = inchar()) == DIGIT) {
if (sp < strsize)
str[sp++] = c;
whole = 10.0 * whole + (c - '0');
}
- ungetch (c); /* put back non-numeric character */
-
+ ungetch (c); /* put back non-numeric character */
+
if (c != PERIOD && tolower(c) != 'e') {
str[sp] = EOS;
*fnum = whole * sign;
*inum = (int) *fnum;
return (TT_INT);
}
-
+
if (lookchar() == PERIOD) {
inchar();
if (sp < strsize)
str[sp++] = PERIOD;
}
-
+
double frac = 0.0;
double powerof10 = 10.0;
-
+
while (type(c = inchar()) == DIGIT) {
if (sp < strsize)
str[sp++] = c;
powerof10 *= 10.0;
}
ungetch (c);
-
+
double exp = 0.0;
double expsign = 1.0;
c = inchar();
str[sp++] = c;
expsign = -1.0;
} else if (type(c) != DIGIT) {
- --sp; /* erase 'e' */
+ --sp; /* erase 'e' */
ungetch (c);
ungetch ('e');
goto getnumexit;
} else
ungetch(c);
-
+
exp = 0;
while (type(c = inchar()) == DIGIT) {
if (sp < strsize)
}
ungetch (c);
}
-
+
getnumexit:
str[sp] = EOS;
*fnum = sign * (whole + frac) * pow (10.0, expsign * exp);
return (TT_REAL);
}
-void
+void
POL::eatline ()
{
char term [2];
-
+
term[0] = NEWLINE;
term[1] = EOS;
skipSingleToken (term);
}
-// return type of ASCII character
-int
+// return type of ASCII character
+int
POL::type (int c)
{
if (isalpha(c) || c == UNDERLIN)
//----------------------------------------------------------------------
-// POL INPUT
+// POL INPUT
//----------------------------------------------------------------------
/* usefile - set source of POL input
*
* int source - source of input
-* P_USE_STR - have POL use strings as input
-* P_USE_FILE - use file. filename is in str
+* P_USE_STR - have POL use strings as input
+* P_USE_FILE - use file. filename is in str
*
*/
-void
-POL::usefile (int source, char *fn)
+void
+POL::usefile (int source, const char *fn)
{
FILE *fp;
-
+
++currentf;
if (currentf >= MAXFILE) {
--currentf;
sys_error (ERR_SEVERE, "files nested too deeply");
return;
}
-
+
while (! m_stackPushBackInput.empty())
m_stackPushBackInput.pop();
}
}
-void
+void
POL::closefile()
{
if (currentf >= 0) {
/*-----------------------------*/
-int
+int
POL::lookchar()
{
int c;
-
+
c = inchar();
ungetch (c);
return (c);
}
-int
+int
POL::inchar()
{
int c = 0;
-
+
if (currentf < 0)
return (EOF);
-
+
while (currentf >= 0 && (c = getch(filep[currentf])) == EOF && filep[currentf] != NULL) {
closefile ();
}
-
+
return (c);
}
/*--------------------------------------------------------------*/
-/* getch - get a (possibly pushed back) character */
-/* if fp == NULL, then get character from inputline */
+/* getch - get a (possibly pushed back) character */
+/* if fp == NULL, then get character from inputline */
/*--------------------------------------------------------------*/
-int
+int
POL::getch (FILE *fp)
{
int c;
}
} else
c = fgetc(fp);
-
+
return (c);
}
-// push character back on input
-void
+// push character back on input
+void
POL::ungetch (int c)
{
m_stackPushBackInput.push (c);
}
-int
+int
POL::get_inputline (FILE *fp)
{
while (! m_stackPushBackInput.empty())
return (OK);
}
-void
+void
POL::set_inputline (const char* const line)
{
while (! m_stackPushBackInput.empty())