2 /* Copyright (C) 2000-2018 Free Software Foundation, Inc.
3 Written by Gaius Mulley (gaius@glam.ac.uk).
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
29 #include "stringclass.h"
34 #include <sys/types.h>
50 # define ERROR(X) (void)(fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) && \
51 (fflush(stderr)) && localexit(1))
54 #define MAXPUSHBACKSTACK 4096 /* maximum number of character that can be pushed back */
58 * constructor for pushBackBuffer
61 pushBackBuffer::pushBackBuffer (char *filename)
63 charStack = (char *)malloc(MAXPUSHBACKSTACK);
67 stackPtr = 0; /* index to push back stack */
72 if (strcmp(filename, "") != 0) {
75 sys_fatal("dup stdin");
78 if (open(filename, O_RDONLY) != 0) {
79 sys_fatal("when trying to open file");
86 pushBackBuffer::~pushBackBuffer ()
92 /* restore stdin in file descriptor 0 */
94 sys_fatal("restore stdin");
100 * localexit - wraps exit with a return code to aid the ERROR macro.
103 int localexit (int i)
110 * getPB - returns a character, possibly a pushed back character.
113 char pushBackBuffer::getPB (void)
117 return( charStack[stackPtr] );
121 if (read(0, &ch, 1) == 1) {
137 * putPB - pushes a character onto the push back stack.
138 * The same character is returned.
141 char pushBackBuffer::putPB (char ch)
143 if (stackPtr<MAXPUSHBACKSTACK) {
144 charStack[stackPtr] = ch ;
147 ERROR("max push back stack exceeded, increase MAXPUSHBACKSTACK constant");
153 * isWhite - returns TRUE if a white character is found. This character is NOT consumed.
156 static int isWhite (char ch)
158 return( (ch==' ') || (ch == '\t') || (ch == '\n') );
162 * skipToNewline - skips characters until a newline is seen.
165 void pushBackBuffer::skipToNewline (void)
167 while ((putPB(getPB()) != '\n') && (! eofFound)) {
173 * skipUntilToken - skips until a token is seen
176 void pushBackBuffer::skipUntilToken (void)
180 while ((isWhite(putPB(getPB())) || (putPB(getPB()) == '#')) && (! eofFound)) {
189 * isString - returns TRUE if the string, s, matches the pushed back string.
190 * if TRUE is returned then this string is consumed, otherwise it is
194 int pushBackBuffer::isString (const char *s)
196 int length=strlen(s);
199 while ((i<length) && (putPB(getPB())==s[i])) {
200 if (getPB() != s[i]) {
201 ERROR("assert failed");
210 if (putPB(s[i]) != s[i]) {
211 ERROR("assert failed");
220 * isDigit - returns TRUE if the character, ch, is a digit.
223 static int isDigit (char ch)
225 return( ((ch>='0') && (ch<='9')) );
229 * isHexDigit - returns TRUE if the character, ch, is a hex digit.
233 static int isHexDigit (char ch)
235 return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) );
240 * readInt - returns an integer from the input stream.
243 int pushBackBuffer::readInt (void)
250 while (isWhite(ch)) {
259 while (isDigit(ch)) {
261 if ((ch>='0') && (ch<='9')) {
267 if (ch != putPB(ch)) {
268 ERROR("assert failed");
274 * convertToFloat - converts integers, a and b into a.b
277 static double convertToFloat (int a, int b)
285 f = ((double)a) + (((double)b)/((double)c));
290 * readNumber - returns a float representing the word just read.
293 double pushBackBuffer::readNumber (void)
299 if ((ch = getPB()) == '.') {
300 return convertToFloat(i, readInt());
307 * readString - reads a string terminated by white space
308 * and returns a malloced area of memory containing
309 * a copy of the characters.
312 char *pushBackBuffer::readString (void)
314 char buffer[MAXPUSHBACKSTACK];
319 while (isWhite(ch)) {
322 while ((i < MAXPUSHBACKSTACK) && (! isWhite(ch)) && (! eofFound)) {
327 if (i < MAXPUSHBACKSTACK) {
329 str = (char *)malloc(strlen(buffer)+1);