1 /*****************************************************************************
4 ** POL - Problem Oriented Language
6 ** This is part of the CTSim program
7 ** Copyright (C) 1983-2000 Kevin Rosenberg
9 ** $Id: pol.cpp,v 1.7 2000/12/27 20:09:19 kevin Exp $
11 ** This program is free software; you can redistribute it and/or modify
12 ** it under the terms of the GNU General Public License (version 2) as
13 ** published by the Free Software Foundation.
15 ** This program is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU General Public License for more details.
20 ** You should have received a copy of the GNU General Public License
21 ** along with this program; if not, write to the Free Software
22 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 ******************************************************************************/
29 #include "ctsupport.h"
33 const struct POL::KeywordCodeList POL::cmdlist[] = {
44 { "nl_eoc",PC_NL_EOC,},
45 { "nl_neoc", PC_NL_NEOC,},
47 { "troff", PC_TROFF,},
52 const unsigned int POL::NUMCMD = (sizeof(POL::cmdlist) / sizeof (struct POL::KeywordCodeList));
80 m_bNewlineIsEOC = true;
\r
81 m_szSkipChars[0] = EOS;
84 for (unsigned int i = 0; i < NUMCMD; i++)
85 cmdtable.installKeywordCode (cmdlist[i].keyword, cmdlist[i].code);
87 token.ready = false; // no token read yet
93 * char *w - word for pol to ignore and skip over in input
95 * tok() compares all tokens to words given to this routine. If it finds it,
96 * it will immediately read another token.
100 POL::addSkipWord (const char* const w)
102 skiptable.installKeywordCode (w, 0);
107 * skip all characters that appear in string s
110 POL::addSkipChar (int c)
112 int n = strlen (m_szSkipChars);
\r
113 if (n < MAXSKIPCHAR) {
\r
114 m_szSkipChars[n] = c;
\r
115 m_szSkipChars[n+1] = 0;
\r
119 // installKeyword (str, code)
121 // char *str - token string to install
122 // int code - code to return for token
124 // tok() looks for these user defined tokens. If it finds one,
125 // it stores the tokens code in the token structure and returns TT_USERTOK
127 POL::addKeyword (const char* const str, int code)
129 usertable.installKeywordCode (str, code);
132 /* get_word - matches tokens on a letter by letter basis
134 * char *search - string to search for
135 * int nlet - maximum number of chars to search for match
139 POL::readWord (char *search, int nlet)
143 sys_error (ERR_TRACE, "POL matching current token %s against word %s\n", token.tokstr, search);
145 if (strncasecmp (search, token.tokstr, nlet) == 0) {
152 /* usertok (str,code)
153 * see if current token is a user defined token set with install()
155 * char *str - token string as read from input
156 * int *code - returned code for user defined symbol
157 * return value - true if current token has been user defined
158 * false if current token is not user defined
161 POL::readUserToken (char *str, int *code)
166 sys_error (ERR_TRACE, "POL checking if current token '%s' is user defined\n", token.tokstr);
168 if (token.type == TT_USERTOK) {
170 strcpy (str, token.tokstr);
179 /* isstring (s) - returns true if current token is a string
181 * char *s - pointer to place to store token string
185 POL::readString (char *str)
189 if (token.type == TT_STRING) {
190 strcpy (str, token.tokstr);
197 /* integer - test for an integer
199 * int *n: returned integer value
200 * int typecode = TT_INT if accept only integer values
201 * = TT_REAL if accept both real and integer values
202 * int boundcode= true if force to lie between boundries
203 * = false can take any value it likes
204 * int bb1: lower bound
205 * int bb2: upper bound
208 POL::readInteger (int *n, int typecode, bool boundcode, int bb1, int bb2)
213 sys_error (ERR_TRACE, "POL checking if current token %s is an integer\n", token.tokstr);
215 if (token.type == TT_INT || token.type == TT_REAL) {
217 if (token.inum < bb1)
219 else if (token.inum > bb2)
233 POL::readFloat (double *n, double typecode, bool boundcode, double bb1, double bb2)
238 sys_error (ERR_TRACE, "POL checking if current token %s is an floating point number\n", token.tokstr);
240 if (token.type == TT_INT || token.type == TT_REAL) {
242 if (token.fnum < bb1)
244 else if (token.fnum > bb2)
257 /*----------------------------------------------------------------------*/
258 /* skip() - skip over any token except for end of command sequence */
260 /* returns true if succesful skip */
261 /* returns false if already at end of command or EOF */
262 /*----------------------------------------------------------------------*/
267 char term[5]; /* string of characters not to skip */
270 if (m_bNewlineIsEOC) {
276 return (skipSingleToken (term));
285 dumptok (&token); /* skip end of command token */
288 /* skiptok (term) - skip a token unless the first character of a token is
289 * in the string of terminators, term.
290 * char *term - string of termination characters, don't skip these characters
291 * skiptok() also does NOT skip TT_EOF
292 * returns (true) if succesful skip of a token
293 * returns (false) if didn't skip, read termination character or TT_EOF
297 POL::skipSingleToken (char term[])
301 if (token.type == TT_EOF
302 || (token.type == TT_SPECLCHAR && strchr(term, token.tokstr[0]) != NULL))
311 POL::tok (struct token_st *token)
313 if (token->ready == false)
316 if (token->type == TT_EOF && lookchar() != EOF)
318 return (token->type);
322 POL::dumptok (struct token_st *token)
324 if (token->ready == false)
326 token->ready = false;
330 POL::getpol_tok (struct token_st *token)
332 KeywordCodeEntry* sym;
334 token->ready = false;
338 if (token->type == TT_BLANK)
340 if (token->type == TT_SPECLCHAR) {
341 if (strchr(m_szSkipChars, token->tokstr[0]) != NULL)
343 if (token->tokstr[0] == NEWLINE)
345 if (token->tokstr[0] == meta.cmd) {
349 if (token->tokstr[0] == meta.com) { /* skip comment */
353 if (token->tokstr[0] == meta.out) {
354 getescape(token->tokstr, meta.out, MAXTOK);
355 fputs (token->tokstr, stderr);
358 if (token->tokstr[0] == meta.con) { /* continuation across NEWLINE */
359 while (lookchar() == BLANK || lookchar() == TAB)
361 if (lookchar() == NEWLINE)
364 if (token->tokstr[0] == meta.ter) { /* get input from terminal */
365 usefile (P_USE_FILE, "");
368 return (token->type);
372 /* look for filler words */
374 if (skiptable.lookup (token->tokstr) != NULL) /* ignore words in skip table */
377 /* look for user defined symbols */
379 if ((sym = usertable.lookup (token->tokstr)) != NULL) {
380 token->type = TT_USERTOK;
381 token->code = sym->getCode();
386 sys_error (ERR_TRACE, "POL read token '%s', type = %d\n", token->tokstr, token->type);
388 return (token->type);
397 KeywordCodeEntry *cmd;
400 tt = getalpha (str, MAXTOK);
401 if (tt == TT_ERROR) {
402 sys_error (ERR_WARNING, "Error in POL parameter command");
406 if ((cmd = cmdtable.lookup (str)) == NULL) {
407 sys_error (ERR_WARNING, "POL: Unrecognized command %s", cmd);
412 switch (cmd->getCode()) {
424 usefile (P_USE_FILE, tok.tokstr);
428 m_bNewlineIsEOC = true;
432 m_bNewlineIsEOC = false;
436 printf("eoc = %c str = %c com = %c cmd = %c prg = %c\n",
437 meta.eoc, meta.str, meta.com, meta.cmd, meta.prg);
438 printf("con = %c out = %c ter = %c inb = %c\n",
439 meta.con, meta.out, meta.ter, meta.inb);
442 if (found == false) {
444 if (tt != TT_SPECLCHAR) {
445 sys_error (ERR_SEVERE, "POL: Illegal command character");
448 switch(cmd->getCode()) {
450 meta.eoc = tok.tokstr[0];
453 meta.str = tok.tokstr[0];
456 meta.com = tok.tokstr[0];
459 meta.cmd = tok.tokstr[0];
462 meta.prg = tok.tokstr[0];
465 meta.con = tok.tokstr[0];
468 meta.out = tok.tokstr[0];
471 meta.ter = tok.tokstr[0];
474 meta.inb = tok.tokstr[0];
477 printf("command not implemented\n");
479 } /* switch (tok->type) */
480 } /* if (found == false) */
481 reader(); /* clean up command */
482 } /* if legal command */
489 POL::gettok (TOKEN *tok)
494 int toksiz = MAXTOK; /* maximum length of token string */
496 while ((c = inchar()) == BLANK || c == TAB)
506 if (c == BLANK || c == TAB) { /* skip white space */
507 getblank(tok->tokstr, toksiz);
509 } else if (toktype == LETTER) {
510 toktype = getalpha (tok->tokstr, toksiz);
511 } else if (c == meta.str) { /* quoted string */
512 getquote (tok->tokstr, toksiz);
514 } else if (type(c) == DIGIT || c == PLUS || c == HYPHEN || c == PERIOD) {
515 toktype = getnumber (tok->tokstr, toksiz, &fnum, &inum);
516 } else if (c == EOF) {
517 tok->tokstr[0] = EOS;
522 tok->tokstr[1] = EOS;
523 toktype = TT_SPECLCHAR;
528 if (tok->type == TT_REAL || tok->type == TT_INT) {
541 POL::getblank (char *s, int toksiz)
545 while ((c = inchar()) == BLANK || c == TAB)
555 POL::getalpha (char *s, int toksiz)
557 int i, chartype, alphatype;
559 if (type(lookchar()) != LETTER) {
564 alphatype = TT_ALPHA;
565 for (i = 0; i < toksiz; i++) { /* get alphanumeric token */
567 chartype = type (s[i]);
568 if (chartype != LETTER && chartype != DIGIT)
570 if (chartype == DIGIT)
571 alphatype = TT_ALPNUM;
576 sys_error (ERR_SEVERE, "POL token too long.");
578 s[i] = EOS; /* terminate token */
583 /* getquote - get quoted string from file */
584 /* have already gotten delimiter in qs[0] */
586 POL::getquote (char *qs, int toksiz)
590 delim = inchar(); /* char = delimiter */
591 getescape(qs, delim, toksiz);
596 POL::getescape ( /* reads up to delim */
604 for (i = 0; (c = inchar()) != delim; i++) {
606 sys_error (ERR_WARNING, "Missing closing delimiter.");
610 sys_error (ERR_SEVERE, "string too long.");
615 sys_error (ERR_SEVERE, "end of file inside quotation");
617 } else if (c == BSLASH) { /* escape character */
619 c = inchar(); /* get escaped character */
628 POL::readText (char *str, int lim)
631 while ((c = inchar()) == BLANK || c == TAB)
640 for (i = 0; i < lim && (c = inchar()) != EOF && c != NEWLINE; i++)
648 //----------------------------------------------
649 // Get a number for gettok()
650 //----------------------------------------------
655 char str[], /* string to return token in */
656 int strsize, /* maximum length of token string */
657 double *fnum, /* floating point value of number read */
658 int *inum /* integer value of number read */
663 bool isSigned = false; /* true if number prefixed by '+' or '-' */
673 } else if (c == PLUS) {
677 } else if (c == PERIOD) {
678 if (type(lookchar()) != DIGIT) {
681 return (TT_SPECLCHAR);
684 } else if (type(c) != DIGIT) {
693 inchar(); /* get period */
694 c = lookchar(); /* look at character past period */
695 ungetch (PERIOD); /* put back period */
696 if (type(c) != DIGIT) {
698 return (TT_SPECLCHAR);
700 } else if (type (c) != DIGIT) {
702 return (TT_SPECLCHAR);
707 while (type(c = inchar()) == DIGIT) {
710 whole = 10.0 * whole + (c - '0');
712 ungetch (c); /* put back non-numeric character */
714 if (c != PERIOD && tolower(c) != 'e') {
716 *fnum = whole * sign;
719 else if (*fnum > MAX_INT)
726 if (lookchar() == PERIOD) {
733 double powerof10 = 10.0;
735 while (type(c = inchar()) == DIGIT) {
738 frac += (double) (c - '0') / powerof10;
744 double expsign = 1.0;
746 if (tolower(c) != 'e')
751 if ((c = inchar()) == PLUS) {
755 } else if (c == HYPHEN) {
759 } else if (type(c) != DIGIT) {
760 --sp; /* erase 'e' */
768 while (type(c = inchar()) == DIGIT) {
771 exp = 10 * exp + (c - '0');
778 *fnum = sign * (whole + frac) * pow (10.0, expsign * exp);
781 else if (*fnum > MAX_INT)
795 skipSingleToken (term);
798 // return type of ASCII character
802 if (isalpha(c) || c == UNDERLIN)
811 //----------------------------------------------------------------------
813 //----------------------------------------------------------------------
816 /* usefile - set source of POL input
818 * int source - source of input
819 * P_USE_STR - have POL use strings as input
820 * P_USE_FILE - use file. filename is in str
825 POL::usefile (int source, char *fn)
830 if (currentf >= MAXFILE) {
832 sys_error (ERR_SEVERE, "files nested too deeply");
836 bp = 0; /* clear any pushed back input */
838 if (source == P_USE_STR) {
839 filep[currentf] = NULL;
840 } else if (source == P_USE_FILE) {
841 if (fn == NULL || strlen(fn) == 0) {
843 } else if ((fp = fopen(fn, "r")) == NULL) {
845 sys_error (ERR_SEVERE, "can't open file");
848 filep[currentf] = fp;
849 fname[currentf] = strdup (fn);
857 if (filep[currentf] != NULL)
858 fclose (filep[currentf]);
863 /*-----------------------------*/
864 /* Lowest Level Input Routines */
865 /*-----------------------------*/
886 while (currentf >= 0 && (c = getch(filep[currentf])) == EOF && filep[currentf] != NULL) {
893 /*--------------------------------------------------------------*/
894 /* getch - get a (possibly pushed back) character */
895 /* if fp == NULL, then get character from inputline */
896 /*--------------------------------------------------------------*/
899 POL::getch (FILE *fp)
907 if ((c = inputline[lineptr]) == EOS)
919 /* push character back on input */
924 sys_error (ERR_SEVERE, "too many characters pushed back [ungetch]");
931 POL::get_inputline (FILE *fp)
935 if (fgets (inputline, MAXLINE, fp) == NULL)
942 POL::set_inputline (const char* const line)
946 strncpy (inputline, line, MAXLINE);