Elimate compiler warnings
[ctsim.git] / libctgraphics / pol.cpp
1 /*****************************************************************************
2 ** FILE IDENTIFICATION
3 **
4 **   POL - Problem Oriented Language
5 **
6 **  This is part of the CTSim program
7 **  Copyright (c) 1983-2009 Kevin Rosenberg
8 **
9 **  This program is free software; you can redistribute it and/or modify
10 **  it under the terms of the GNU General Public License (version 2) as
11 **  published by the Free Software Foundation.
12 **
13 **  This program is distributed in the hope that it will be useful,
14 **  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 **  GNU General Public License for more details.
17 **
18 **  You should have received a copy of the GNU General Public License
19 **  along with this program; if not, write to the Free Software
20 **  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 ******************************************************************************/
22
23 #include "ct.h"
24 #include <math.h>
25 #include <stdio.h>
26 #include <ctype.h>
27 #include "ctsupport.h"
28 #include "pol.h"
29
30
31 const struct POL::KeywordCodeList POL::cmdlist[] = {
32   {     "eoc",  PC_EOC,},
33   {     "str",  PC_STR,},
34   {     "com",  PC_COM,},
35   {     "cmd",  PC_CMD,},
36   {     "prg",  PC_PRG,},
37   {     "con",  PC_CON,},
38   {     "out",  PC_OUT,},
39   {     "ter",  PC_TER,},
40   {     "inb",  PC_INB,},
41
42   {     "nl_eoc",PC_NL_EOC,},
43   {     "nl_neoc", PC_NL_NEOC,},
44   {     "tron",  PC_TRON,},
45   {     "troff", PC_TROFF,},
46   {     "file",  PC_FILE,},
47   {     "dump",  PC_DUMP,},
48 };
49
50 const unsigned int POL::NUMCMD = (sizeof(POL::cmdlist) / sizeof (struct POL::KeywordCodeList));
51
52
53 POL::POL()
54 {
55   currentf = -1;
56   m_bTrace = false;
57   init();
58 }
59
60 POL::~POL()
61 {
62 }
63
64 void
65 POL::init ()
66 {
67   meta.eoc    = SEMICOL;
68   meta.str    = DQUOTE;
69   meta.com    = SHARP;
70   meta.cmd    = EXCLAM;
71   meta.prg    = ATSIGN;
72   meta.con    = AMPERSAND;
73   meta.out    = DOLLAR;
74   meta.ter    = PERCENT;
75   meta.inb    = LBRACK;
76
77   m_bNewlineIsEOC = true;
78   m_szSkipChars[0] = EOS;
79
80
81   for (unsigned int i = 0; i < NUMCMD; i++)
82     cmdtable.installKeywordCode (cmdlist[i].keyword, cmdlist[i].code);
83
84   token.ready = false;          // no token read yet
85 }
86
87
88 /* addSkipWord (w)
89 *
90 * char *w - word for pol to ignore and skip over in input
91 *
92 * tok() compares all tokens to words given to this routine. If it finds it,
93 * it will immediately read another token.
94 */
95
96 void
97 POL::addSkipWord (const char* const w)
98 {
99   skiptable.installKeywordCode (w, 0);
100 }
101
102 /* skpchar (s)
103 *
104 * skip all characters that appear in string s
105 */
106 void
107 POL::addSkipChar (int c)
108 {
109   int n = strlen (m_szSkipChars);
110   if (n < MAXSKIPCHAR) {
111     m_szSkipChars[n] = c;
112     m_szSkipChars[n+1] = 0;
113   }
114 }
115
116 // installKeyword (str, code)
117 //
118 // char *str - token string to install
119 // int code  - code to return for token
120 //
121 // tok() looks for these user defined tokens.  If it finds one,
122 // it stores the tokens code in the token structure and returns TT_USERTOK
123 void
124 POL::addKeyword (const char* const str, int code)
125 {
126   usertable.installKeywordCode (str, code);
127 }
128
129 /* get_word - matches tokens on a letter by letter basis
130 *
131 * char *search - string to search for
132 * int  nlet     - maximum number of chars to search for match
133 */
134
135 bool
136 POL::readWord (const char *search, int nlet)
137 {
138   tok (&token);
139   if (m_bTrace)
140     sys_error (ERR_TRACE, "POL matching current token %s against word %s\n", token.tokstr, search);
141
142   if (strncasecmp (search, token.tokstr, nlet) == 0) {
143     dumptok (&token);
144     return (true);
145   } else
146     return (false);
147 }
148
149 /* usertok (str,code)
150 *       see if current token is a user defined token set with install()
151 *
152 *    char *str - token string as read from input
153 *    int *code - returned code for user defined symbol
154 *    return value - true if current token has been user defined
155 *                    false if current token is not user defined
156 */
157 bool
158 POL::readUserToken (char *str, int *code)
159 {
160   tok (&token);
161
162   if (m_bTrace)
163     sys_error (ERR_TRACE, "POL checking if current token '%s' is user defined\n", token.tokstr);
164
165   if (token.type == TT_USERTOK) {
166     *code = token.code;
167     strcpy (str, token.tokstr);
168     dumptok (&token);
169     return (true);
170   } else {
171     *code = 0;
172     return (false);
173   }
174 }
175
176 /* isstring (s) - returns true if current token is a string
177 *
178 * char *s - pointer to place to store token string
179 */
180
181 bool
182 POL::readString (char *str)
183 {
184   tok (&token);
185
186   if (token.type == TT_STRING) {
187     strcpy (str, token.tokstr);
188     dumptok (&token);
189     return (true);
190   } else
191     return (false);
192 }
193
194 /* integer - test for an integer
195 *
196 * int *n:       returned integer value
197 * int typecode = TT_INT if accept only integer values
198 *               = TT_REAL if accept both real and integer values
199 * int boundcode= true if force to lie between boundries
200 *               = false can take any value it likes
201 * int bb1:      lower bound
202 * int bb2:      upper bound
203 */
204 bool
205 POL::readInteger (int *n, int typecode, bool boundcode, int bb1, int bb2)
206 {
207   tok (&token);
208
209   if (m_bTrace)
210     sys_error (ERR_TRACE, "POL checking if current token %s is an integer\n", token.tokstr);
211
212   if (token.type == TT_INT || token.type == TT_REAL) {
213            if (boundcode) {
214        if (token.inum < bb1)
215          *n = bb1;
216        else if (token.inum > bb2)
217          *n = bb2;
218        else
219          *n = token.inum;
220             } else
221         *n = token.inum;
222       dumptok (&token);
223       return (true);
224   }
225   *n = 0;
226   return (false);
227 }
228
229 bool
230 POL::readFloat (double *n, double typecode, bool boundcode, double bb1, double bb2)
231 {
232   tok (&token);
233
234   if (m_bTrace)
235     sys_error (ERR_TRACE, "POL checking if current token %s is an floating point number\n", token.tokstr);
236
237   if (token.type == TT_INT || token.type == TT_REAL) {
238            if (boundcode) {
239        if (token.fnum < bb1)
240          *n = bb1;
241        else if (token.fnum > bb2)
242          *n = bb2;
243        else
244          *n = token.fnum;
245             } else
246         *n = token.fnum;
247       dumptok (&token);
248       return (true);
249   }
250   *n = 0.0;
251   return (false);
252 }
253
254 /*----------------------------------------------------------------------*/
255 /* skip() - skip over any token except for end of command sequence      */
256 /*                                                                      */
257 /*              returns true if succesful skip                          */
258 /*              returns false if already at end of command or EOF       */
259 /*----------------------------------------------------------------------*/
260
261 bool
262 POL::skipTokens()
263 {
264   char term[5];         /* string of characters not to skip */
265
266   term[0] = meta.eoc;
267   if (m_bNewlineIsEOC) {
268     term[1] = NEWLINE;
269     term[2] = EOS;
270   } else
271     term[1] = EOS;
272
273   return (skipSingleToken (term));
274 }
275
276 void
277 POL::reader()
278 {
279   while (skipTokens())
280     ;
281
282   dumptok (&token);             /* skip end of command token */
283 }
284
285 /* skiptok (term) - skip a token unless the first character of a token is
286 *                   in the string of terminators, term.
287 * char *term - string of termination characters, don't skip these characters
288 *               skiptok() also does NOT skip TT_EOF
289 * returns (true) if succesful skip of a token
290 * returns (false) if didn't skip, read termination character or TT_EOF
291 */
292
293 bool
294 POL::skipSingleToken (char term[])
295 {
296   tok (&token);
297
298   if (token.type == TT_EOF
299     || (token.type == TT_SPECLCHAR && strchr(term, token.tokstr[0]) != NULL))
300     return (false);
301   else {
302     dumptok (&token);
303     return (true);
304   }
305 }
306
307 int
308 POL::tok (struct token_st *token)
309 {
310   if (token->ready == false)
311     getpol_tok(token);
312   else {
313     if (token->type == TT_EOF && lookchar() != EOF)
314       getpol_tok(token);
315   }
316   return (token->type);
317 }
318
319 void
320 POL::dumptok (struct token_st *token)
321 {
322   if (token->ready == false)
323     getpol_tok(token);
324   token->ready = false;
325 }
326
327 int
328 POL::getpol_tok (struct token_st *token)
329 {
330   KeywordCodeEntry* sym;
331
332   token->ready = false;
333 nexttok:
334   gettok (token);
335
336   if (token->type == TT_BLANK)
337     goto nexttok;
338   if (token->type == TT_SPECLCHAR) {
339     if (strchr(m_szSkipChars, token->tokstr[0]) != NULL)
340       goto nexttok;
341     if (token->tokstr[0] == NEWLINE)
342       goto nexttok;
343     if (token->tokstr[0] == meta.cmd) {
344       getcmd();
345       goto nexttok;
346     }
347     if (token->tokstr[0] == meta.com) {         /* skip comment */
348       eatline ();
349       goto nexttok;
350     }
351     if (token->tokstr[0] == meta.out) {
352       getescape(token->tokstr, meta.out, MAXTOK);
353       fputs (token->tokstr, stderr);
354       goto nexttok;
355     }
356     if (token->tokstr[0] == meta.con) {         /* continuation across NEWLINE */
357       while (lookchar() == BLANK || lookchar() == TAB)
358         inchar();
359       if (lookchar() == NEWLINE)
360         inchar();
361     }
362     if (token->tokstr[0] == meta.ter) {         /* get input from terminal */
363       usefile (P_USE_FILE, "");
364       tok (token);
365       closefile();
366       return (token->type);
367     }
368   }
369
370   /* look for filler words */
371
372   if (skiptable.lookup (token->tokstr) != NULL) /* ignore words in skip table */
373     goto nexttok;
374
375   /* look for user defined symbols */
376
377   if ((sym = usertable.lookup (token->tokstr)) != NULL) {
378     token->type = TT_USERTOK;
379     token->code = sym->getCode();
380   } else
381     token->code = 0;
382
383   if (m_bTrace)
384     sys_error (ERR_TRACE, "POL read token '%s', type = %d\n", token->tokstr, token->type);
385
386   return (token->type);
387 }
388
389
390 int
391 POL::getcmd()
392 {
393   int tt, found;
394   char str[MAXTOK+1];
395   KeywordCodeEntry *cmd;
396   TOKEN tok;
397
398   tt = getalpha (str, MAXTOK);
399   if (tt == TT_ERROR) {
400     sys_error (ERR_WARNING, "Error in POL parameter command");
401     reader();
402     return(false);
403   }
404   if ((cmd = cmdtable.lookup (str)) == NULL) {
405     sys_error  (ERR_WARNING, "POL: Unrecognized command %s", cmd);
406     reader();
407     return (false);
408   } else {
409     found = false;
410     switch (cmd->getCode()) {
411     case PC_TRON:
412                     m_bTrace = true;
413         found = true;
414         break;
415     case PC_TROFF:
416                     m_bTrace = false;
417         found = true;
418         break;
419     case PC_FILE:
420                     found = true;
421         tt = gettok (&tok);
422         usefile (P_USE_FILE, tok.tokstr);
423         break;
424     case PC_NL_EOC:
425                     found = true;
426         m_bNewlineIsEOC = true;
427         break;
428     case PC_NL_NEOC:
429                     found = true;
430         m_bNewlineIsEOC = false;
431         break;
432     case PC_DUMP:
433                     found = true;
434         printf("eoc = %c  str = %c  com = %c  cmd = %c  prg = %c\n",
435           meta.eoc, meta.str, meta.com, meta.cmd, meta.prg);
436         printf("con = %c  out = %c  ter = %c  inb = %c\n",
437           meta.con, meta.out, meta.ter, meta.inb);
438         break;
439     }
440     if (found == false) {
441       tt = gettok (&tok);
442       if (tt != TT_SPECLCHAR) {
443         sys_error (ERR_SEVERE, "POL: Illegal command character");
444         return (false);
445       }
446       switch(cmd->getCode()) {
447                     case PC_EOC:
448           meta.eoc = tok.tokstr[0];
449           break;
450         case PC_STR:
451           meta.str = tok.tokstr[0];
452           break;
453         case PC_COM:
454           meta.com = tok.tokstr[0];
455           break;
456         case PC_CMD:
457           meta.cmd = tok.tokstr[0];
458           break;
459         case PC_PRG:
460           meta.prg = tok.tokstr[0];
461           break;
462         case PC_CON:
463           meta.con = tok.tokstr[0];
464           break;
465         case PC_OUT:
466           meta.out = tok.tokstr[0];
467           break;
468         case PC_TER:
469           meta.ter = tok.tokstr[0];
470           break;
471         case PC_INB:
472           meta.inb = tok.tokstr[0];
473           break;
474         default:
475           printf("command not implemented\n");
476           break;
477       }                         /* switch (tok->type) */
478     }                                   /* if (found == false) */
479     reader();                   /* clean up command */
480   }                                     /* if legal command */
481
482   return (true);
483 }
484
485
486 int
487 POL::gettok (TOKEN *tok)
488 {
489   int c, toktype;
490   int inum;
491   double fnum;
492   int toksiz = MAXTOK;          /* maximum length of token string */
493
494   while ((c = inchar()) == BLANK || c == TAB)
495     ;
496   ungetch (c);
497
498   c = lookchar();
499   toktype = type(c);
500
501   fnum = 0.0;
502   inum = 0;
503
504   if (c == BLANK || c == TAB) {                 /* skip white space */
505     getblank(tok->tokstr, toksiz);
506     toktype = TT_BLANK;
507   } else if (toktype == LETTER) {
508     toktype = getalpha (tok->tokstr, toksiz);
509   } else if (c == meta.str) {                   /* quoted string */
510     getquote (tok->tokstr, toksiz);
511     toktype = TT_STRING;
512   } else if (type(c) == DIGIT || c == PLUS || c == HYPHEN || c == PERIOD) {
513     toktype = getnumber (tok->tokstr, toksiz, &fnum, &inum);
514   } else if (c == EOF) {
515     tok->tokstr[0] = EOS;
516     toktype = TT_EOF;
517   } else {
518     c = inchar();
519     tok->tokstr[0] = c;
520     tok->tokstr[1] = EOS;
521     toktype = TT_SPECLCHAR;
522   }
523
524   tok->type = toktype;
525   tok->ready = true;
526   if (tok->type == TT_REAL || tok->type == TT_INT) {
527     tok->fnum = fnum;
528     tok->inum = inum;
529   } else {
530     tok->fnum = 0.0;
531     tok->inum = 0;
532   }
533
534   return (toktype);
535 }
536
537
538 void
539 POL::getblank (char *s, int toksiz)
540 {
541   int c;
542
543   while ((c = inchar()) == BLANK || c == TAB)
544     ;
545   ungetch(c);
546
547   s[0] = BLANK;
548   s[1] = EOS;
549 }
550
551
552 int
553 POL::getalpha (char *s, int toksiz)
554 {
555   int i, chartype, alphatype;
556
557   if (type(lookchar()) != LETTER) {
558     s[0] = EOS;
559     return (TT_ERROR);
560   }
561
562   alphatype = TT_ALPHA;
563   for (i = 0; i < toksiz; i++) {                /* get alphanumeric token */
564     s[i] = inchar();
565     chartype = type (s[i]);
566     if (chartype != LETTER && chartype != DIGIT)
567       break;
568     if (chartype == DIGIT)
569       alphatype = TT_ALPNUM;
570   }
571   ungetch(s[i]);
572
573   if (i >= toksiz)
574     sys_error (ERR_SEVERE, "POL token too long.");
575
576   s[i] = EOS;                   /* terminate token */
577   return (alphatype);
578 }
579
580
581 /* getquote - get quoted string from file */
582 /* have already gotten delimiter in qs[0] */
583 void
584 POL::getquote (char *qs, int toksiz)
585 {
586   int delim;
587
588   delim = inchar();                     /* char = delimiter */
589   getescape(qs, delim, toksiz);
590 }
591
592
593 void
594 POL::getescape (        /* reads up to delim */
595                 char *s,
596                 int delim,
597                 int toksiz
598                 )
599 {
600   int i, c;
601
602   for (i = 0; (c = inchar()) != delim; i++) {
603     if (c == NEWLINE) {
604       sys_error (ERR_WARNING, "Missing closing delimiter.");
605       break;
606     }
607     if (i >= toksiz) {
608       sys_error (ERR_SEVERE, "string too long.");
609       break;
610     }
611     if (c == EOF) {
612       ungetch(c);
613       sys_error (ERR_SEVERE, "end of file inside quotation");
614       break;
615     } else if (c == BSLASH) {   /* escape character */
616       s[i++] = c;
617       c = inchar();             /* get escaped character */
618     }
619     s[i] = c;
620   }
621   s[i] = EOS;
622 }
623
624
625 bool
626 POL::readText (char *str, int lim)
627 {
628   int c;
629   while ((c = inchar()) == BLANK || c == TAB)
630     ;
631   ungetch (c);
632   if (c == EOF) {
633     str[0] = 0;
634     return false;
635   }
636
637   int i;
638   for (i = 0; i < lim && (c = inchar()) != EOF && c != NEWLINE; i++)
639     str[i] = c;
640   ungetch (c);
641   str[i] = 0;
642
643   return true;
644 }
645
646 //----------------------------------------------
647 // Get a number for gettok()
648 //----------------------------------------------
649
650 int
651 POL::getnumber
652 (
653  char str[],                            /* string to return token in */
654  int strsize,                           /* maximum length of token string */
655  double *fnum,                          /* floating point value of number read */
656  int *inum                              /* integer value of number read */
657  )
658 {
659   int sp = 0;
660   double sign = 1.0;
661   bool isSigned = false;                /* true if number prefixed by '+' or '-' */
662   *fnum = 0.0;
663   *inum = 0;
664   str[0] = EOS;
665
666   int c = inchar();
667   if (c == HYPHEN) {
668     str[sp++] = c;
669     isSigned = true;
670     sign = -1.0;
671   } else if (c == PLUS) {
672     str[sp++] = c;
673     isSigned = true;
674     sign = 1.0;
675   } else if (c == PERIOD) {
676     if (type(lookchar()) != DIGIT) {
677       str[0] = PERIOD;
678       str[1] = EOS;
679       return (TT_SPECLCHAR);
680     } else
681       ungetch (PERIOD);
682   } else if (type(c) != DIGIT) {
683     ungetch (c);
684     return (TT_ERROR);
685   } else
686     ungetch (c);
687
688   if (isSigned) {
689     c = lookchar();
690     if (c == PERIOD) {
691       inchar();         /* get period */
692       c = lookchar();           /* look at character past period */
693       ungetch (PERIOD); /* put back period */
694       if (type(c) != DIGIT) {
695         str[sp] = EOS;
696         return (TT_SPECLCHAR);
697       }
698     } else if (type (c) != DIGIT) {
699       str[sp] = EOS;
700       return (TT_SPECLCHAR);
701     }
702   }
703
704   double whole = 0.0;
705   while (type(c = inchar()) == DIGIT) {
706     if (sp < strsize)
707       str[sp++] = c;
708     whole = 10.0 * whole + (c - '0');
709   }
710   ungetch (c);          /* put back non-numeric character */
711
712   if (c != PERIOD && tolower(c) != 'e') {
713     str[sp] = EOS;
714     *fnum = whole * sign;
715     if (*fnum < MIN_INT)
716       *inum = MIN_INT;
717     else if (*fnum > MAX_INT)
718       *inum = MAX_INT;
719     else
720       *inum = (int) *fnum;
721     return (TT_INT);
722   }
723
724   if (lookchar() == PERIOD) {
725     inchar();
726     if (sp < strsize)
727       str[sp++] = PERIOD;
728   }
729
730   double frac = 0.0;
731   double powerof10 = 10.0;
732
733   while (type(c = inchar()) == DIGIT) {
734     if (sp < strsize)
735       str[sp++] = c;
736     frac += (double) (c - '0') / powerof10;
737     powerof10 *= 10.0;
738   }
739   ungetch (c);
740
741   double exp = 0.0;
742   double expsign = 1.0;
743   c = inchar();
744   if (tolower(c) != 'e')
745     ungetch (c);
746   else {
747     if (sp < strsize)
748       str[sp++] = c;
749     if ((c = inchar()) == PLUS) {
750       if (sp < strsize)
751         str[sp++] = c;
752       expsign = 1.0;
753     } else if (c == HYPHEN) {
754       if (sp < strsize)
755         str[sp++] = c;
756       expsign = -1.0;
757     } else if (type(c) != DIGIT) {
758       --sp;                             /* erase 'e' */
759       ungetch (c);
760       ungetch ('e');
761       goto getnumexit;
762     } else
763       ungetch(c);
764
765     exp = 0;
766     while (type(c = inchar()) == DIGIT) {
767       if (sp < strsize)
768         str[sp++] = c;
769       exp = 10 * exp + (c - '0');
770     }
771     ungetch (c);
772   }
773
774 getnumexit:
775   str[sp] = EOS;
776   *fnum = sign * (whole + frac) * pow (10.0, expsign * exp);
777   if (*fnum < MIN_INT)
778     *inum = MIN_INT;
779   else if (*fnum > MAX_INT)
780     *inum = MAX_INT;
781   else
782     *inum = (int) *fnum;
783   return (TT_REAL);
784 }
785
786 void
787 POL::eatline ()
788 {
789   char term [2];
790
791   term[0] = NEWLINE;
792   term[1] = EOS;
793   skipSingleToken (term);
794 }
795
796 // return type of ASCII character
797 int
798 POL::type (int c)
799 {
800   if (isalpha(c) || c == UNDERLIN)
801     return (LETTER);
802   else if (isdigit(c))
803     return (DIGIT);
804   else
805     return (c);
806 }
807
808
809 //----------------------------------------------------------------------
810 //                              POL INPUT
811 //----------------------------------------------------------------------
812
813
814 /* usefile - set source of POL input
815 *
816 *    int source - source of input
817 *                  P_USE_STR  - have POL use strings as input
818 *                  P_USE_FILE - use file.  filename is in str
819 *
820 */
821
822 void
823 POL::usefile (int source, const char *fn)
824 {
825   FILE *fp;
826
827   ++currentf;
828   if (currentf >= MAXFILE) {
829     --currentf;
830     sys_error (ERR_SEVERE, "files nested too deeply");
831     return;
832   }
833
834   while (! m_stackPushBackInput.empty())
835     m_stackPushBackInput.pop();
836
837   if (source == P_USE_STR) {
838     filep[currentf] = NULL;
839   } else if (source == P_USE_FILE) {
840     if (fn == NULL || strlen(fn) == 0) {
841       fp = stdin;
842     } else if ((fp = fopen(fn, "r")) == NULL) {
843       --currentf;
844       sys_error (ERR_SEVERE, "can't open file");
845       return;
846     }
847     filep[currentf] = fp;
848     fname[currentf] = strdup (fn);
849   }
850 }
851
852 void
853 POL::closefile()
854 {
855   if (currentf >= 0) {
856     if (filep[currentf] != NULL)
857       fclose (filep[currentf]);
858     --currentf;
859   }
860 }
861
862 /*-----------------------------*/
863 /* Lowest Level Input Routines */
864 /*-----------------------------*/
865
866
867 int
868 POL::lookchar()
869 {
870   int c;
871
872   c = inchar();
873   ungetch (c);
874   return (c);
875 }
876
877 int
878 POL::inchar()
879 {
880   int c = 0;
881
882   if (currentf < 0)
883     return (EOF);
884
885   while (currentf >= 0 && (c = getch(filep[currentf])) == EOF && filep[currentf] != NULL) {
886     closefile ();
887   }
888
889   return (c);
890 }
891
892 /*--------------------------------------------------------------*/
893 /* getch - get a (possibly pushed back) character               */
894 /*         if fp == NULL, then get character from inputline     */
895 /*--------------------------------------------------------------*/
896
897 int
898 POL::getch (FILE *fp)
899 {
900   int c;
901   if (m_stackPushBackInput.size() > 0) {
902     c = m_stackPushBackInput.top();
903     m_stackPushBackInput.pop();
904     return c;
905   }
906
907   if (fp == NULL) {
908     if ((c = inputline[lineptr]) == EOS)
909       return (EOF);
910     else {
911       ++lineptr;
912       return (c);
913     }
914   } else
915     c = fgetc(fp);
916
917   return (c);
918 }
919
920 // push character back on input
921 void
922 POL::ungetch (int c)
923 {
924   m_stackPushBackInput.push (c);
925 }
926
927
928 int
929 POL::get_inputline (FILE *fp)
930 {
931   while (! m_stackPushBackInput.empty())
932     m_stackPushBackInput.pop();
933
934   lineptr = 0;
935   if (fgets (inputline, MAXLINE, fp) == NULL)
936     return (EOF);
937   else
938     return (OK);
939 }
940
941 void
942 POL::set_inputline (const char* const line)
943 {
944   while (! m_stackPushBackInput.empty())
945     m_stackPushBackInput.pop();
946
947   strncpy (inputline, line, MAXLINE);
948   lineptr = 0;
949 }