Merge branch 'topic/sync-to-go-2'
[s-roff.git] / src / pre-html / pushback.cpp
blobcf608a8e4f19517f9e6779d88e5b5578b200fc42
1 /*@
2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 2000, 2001, 2003 - 2005 Free Software Foundation, Inc.
5 * Written by Gaius Mulley (gaius@glam.ac.uk).
7 * This 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 2, or (at your option) any later
10 * version.
12 * This 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
15 * for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with groff; see the file COPYING. If not, write to the Free Software
19 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "config.h"
23 #include "html-config.h"
25 #include <sys/types.h>
27 #include <assert.h>
28 #include <ctype.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include <stdlib.h>
33 #include "errarg.h"
34 #include "error.h"
35 #include "lib.h"
36 #include "nonposix.h"
37 #include "posix.h"
38 #include "stringclass.h"
40 #include "pushback.h"
41 #include "pre-html.h"
43 #define ERROR(X) \
44 (void)(fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) &&\
45 (fflush(stderr)) && localexit(1))
47 pushBackBuffer::pushBackBuffer (char *filename)
49 charStack = (char *)malloc(MAXPUSHBACKSTACK);
50 if (charStack == 0) {
51 sys_fatal("malloc");
53 stackPtr = 0; /* index to push back stack */
54 debug = 0;
55 verbose = 0;
56 eofFound = false;
57 lineNo = 1;
58 if (strcmp(filename, "") != 0) {
59 if ((stdIn = dup(0)) == -1)
60 sys_fatal("cannot dup(2)licate standard input");
61 close(0);
62 if (open(filename, O_RDONLY) != 0) {
63 sys_fatal("when trying to open file");
64 } else {
65 fileName = filename;
70 pushBackBuffer::~pushBackBuffer ()
72 if (charStack != 0) {
73 free(charStack);
75 close(0);
76 /* restore stdin in file descriptor 0 */
77 if (dup(stdIn) == -1) /* FIXME use dup2() if possible, not close(0)+dup(2)! */
78 sys_fatal("cannot restore dup(2)licated standard input");
79 close(stdIn);
83 * localexit - wraps exit with a return code to aid the ERROR macro.
86 int localexit (int i)
88 exit(i);
89 return( 1 );
93 * getPB - returns a character, possibly a pushed back character.
96 char pushBackBuffer::getPB (void)
98 if (stackPtr>0) {
99 stackPtr--;
100 return( charStack[stackPtr] );
101 } else {
102 char ch;
104 if (read(0, &ch, 1) == 1) {
105 if (verbose) {
106 printf("%c", ch);
108 if (ch == '\n') {
109 lineNo++;
111 return( ch );
112 } else {
113 eofFound = true;
114 return( eof );
120 * putPB - pushes a character onto the push back stack.
121 * The same character is returned.
124 char pushBackBuffer::putPB (char ch)
126 if (stackPtr<MAXPUSHBACKSTACK) {
127 charStack[stackPtr] = ch ;
128 stackPtr++;
129 } else {
130 ERROR("max push back stack exceeded, increase MAXPUSHBACKSTACK constant");
132 return( ch );
136 * isWhite - returns true if a white character is found. This character is NOT consumed.
139 static int isWhite (char ch)
141 return( (ch==' ') || (ch == '\t') || (ch == '\n') );
145 * skipToNewline - skips characters until a newline is seen.
148 void pushBackBuffer::skipToNewline (void)
150 while ((putPB(getPB()) != '\n') && (! eofFound)) {
151 getPB();
156 * skipUntilToken - skips until a token is seen
159 void pushBackBuffer::skipUntilToken (void)
161 char ch;
163 while ((isWhite(putPB(getPB())) || (putPB(getPB()) == '#')) && (! eofFound)) {
164 ch = getPB();
165 if (ch == '#') {
166 skipToNewline();
172 * isString - returns true if the string, s, matches the pushed back string.
173 * if true is returned then this string is consumed, otherwise it is
174 * left alone.
177 int pushBackBuffer::isString (const char *s)
179 int length=strlen(s);
180 int i=0;
182 while ((i<length) && (putPB(getPB())==s[i])) {
183 if (getPB() != s[i]) {
184 ERROR("assert failed");
186 i++;
188 if (i==length) {
189 return true;
190 } else {
191 i--;
192 while (i>=0) {
193 if (putPB(s[i]) != s[i]) {
194 ERROR("assert failed");
196 i--;
199 return false;
203 * isDigit - returns true if the character, ch, is a digit.
206 static int isDigit (char ch)
208 return( ((ch>='0') && (ch<='9')) );
212 * isHexDigit - returns true if the character, ch, is a hex digit.
215 #if 0
216 static int isHexDigit (char ch)
218 return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) );
220 #endif
223 * readInt - returns an integer from the input stream.
226 int pushBackBuffer::readInt (void)
228 int c =0;
229 int i =0;
230 int s =1;
231 char ch=getPB();
233 while (isWhite(ch)) {
234 ch=getPB();
236 // now read integer
238 if (ch == '-') {
239 s = -1;
240 ch = getPB();
242 while (isDigit(ch)) {
243 i *= 10;
244 if ((ch>='0') && (ch<='9')) {
245 i += (int)(ch-'0');
247 ch = getPB();
248 c++;
250 if (ch != putPB(ch)) {
251 ERROR("assert failed");
253 return( i*s );
257 * convertToFloat - converts integers, a and b into a.b
260 static double convertToFloat (int a, int b)
262 int c=10;
263 double f;
265 while (b>c) {
266 c *= 10;
268 f = ((double)a) + (((double)b)/((double)c));
269 return( f );
273 * readNumber - returns a float representing the word just read.
276 double pushBackBuffer::readNumber (void)
278 int i;
279 char ch;
281 i = readInt();
282 if ((ch = getPB()) == '.') {
283 return convertToFloat(i, readInt());
285 putPB(ch);
286 return (double)i;
290 * readString - reads a string terminated by white space
291 * and returns a malloced area of memory containing
292 * a copy of the characters.
295 char *pushBackBuffer::readString (void)
297 char buffer[MAXPUSHBACKSTACK];
298 char *str = 0;
299 int i=0;
300 char ch=getPB();
302 while (isWhite(ch)) {
303 ch=getPB();
305 while ((i < MAXPUSHBACKSTACK) && (! isWhite(ch)) && (! eofFound)) {
306 buffer[i] = ch;
307 i++;
308 ch = getPB();
310 if (i < MAXPUSHBACKSTACK) {
311 buffer[i] = (char)0;
312 str = (char *)malloc(strlen(buffer)+1);
313 strcpy(str, buffer);
315 return( str );
318 // s-it2-mode