1 /* $NetBSD: pushback.cpp,v 1.1.1.1 2016/01/13 18:41:49 christos Exp $ */
2
3 // -*- C++ -*-
4 /* Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
5 Written by Gaius Mulley (gaius@glam.ac.uk).
6
7 This file is part of groff.
8
9 groff is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 2, or (at your option) any later
12 version.
13
14 groff is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License along
20 with groff; see the file COPYING. If not, write to the Free Software
21 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #include "lib.h"
24
25 #include <signal.h>
26 #include <ctype.h>
27 #include <assert.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include "errarg.h"
31 #include "error.h"
32 #include "stringclass.h"
33 #include "posix.h"
34 #include "nonposix.h"
35
36 #include <errno.h>
37 #include <sys/types.h>
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #include "pushback.h"
43 #include "pre-html.h"
44
45 #if !defined(TRUE)
46 # define TRUE (1==1)
47 #endif
48
49 #if !defined(FALSE)
50 # define FALSE (1==0)
51 #endif
52
53 # define ERROR(X) (void)(fprintf(stderr, "%s:%d error %s\n", __FILE__, __LINE__, X) && \
54 (fflush(stderr)) && localexit(1))
55
56
57 #define MAXPUSHBACKSTACK 4096 /* maximum number of character that can be pushed back */
58
59
60 /*
61 * constructor for pushBackBuffer
62 */
63
pushBackBuffer(char * filename)64 pushBackBuffer::pushBackBuffer (char *filename)
65 {
66 charStack = (char *)malloc(MAXPUSHBACKSTACK);
67 if (charStack == 0) {
68 sys_fatal("malloc");
69 }
70 stackPtr = 0; /* index to push back stack */
71 debug = 0;
72 verbose = 0;
73 eofFound = FALSE;
74 lineNo = 1;
75 if (strcmp(filename, "") != 0) {
76 stdIn = dup(0);
77 close(0);
78 if (open(filename, O_RDONLY) != 0) {
79 sys_fatal("when trying to open file");
80 } else {
81 fileName = filename;
82 }
83 }
84 }
85
~pushBackBuffer()86 pushBackBuffer::~pushBackBuffer ()
87 {
88 if (charStack != 0) {
89 free(charStack);
90 }
91 close(0);
92 /* restore stdin in file descriptor 0 */
93 dup(stdIn);
94 close(stdIn);
95 }
96
97 /*
98 * localexit - wraps exit with a return code to aid the ERROR macro.
99 */
100
localexit(int i)101 int localexit (int i)
102 {
103 exit(i);
104 return( 1 );
105 }
106
107 /*
108 * getPB - returns a character, possibly a pushed back character.
109 */
110
getPB(void)111 char pushBackBuffer::getPB (void)
112 {
113 if (stackPtr>0) {
114 stackPtr--;
115 return( charStack[stackPtr] );
116 } else {
117 char ch;
118
119 if (read(0, &ch, 1) == 1) {
120 if (verbose) {
121 printf("%c", ch);
122 }
123 if (ch == '\n') {
124 lineNo++;
125 }
126 return( ch );
127 } else {
128 eofFound = TRUE;
129 return( eof );
130 }
131 }
132 }
133
134 /*
135 * putPB - pushes a character onto the push back stack.
136 * The same character is returned.
137 */
138
putPB(char ch)139 char pushBackBuffer::putPB (char ch)
140 {
141 if (stackPtr<MAXPUSHBACKSTACK) {
142 charStack[stackPtr] = ch ;
143 stackPtr++;
144 } else {
145 ERROR("max push back stack exceeded, increase MAXPUSHBACKSTACK constant");
146 }
147 return( ch );
148 }
149
150 /*
151 * isWhite - returns TRUE if a white character is found. This character is NOT consumed.
152 */
153
isWhite(char ch)154 static int isWhite (char ch)
155 {
156 return( (ch==' ') || (ch == '\t') || (ch == '\n') );
157 }
158
159 /*
160 * skipToNewline - skips characters until a newline is seen.
161 */
162
skipToNewline(void)163 void pushBackBuffer::skipToNewline (void)
164 {
165 while ((putPB(getPB()) != '\n') && (! eofFound)) {
166 getPB();
167 }
168 }
169
170 /*
171 * skipUntilToken - skips until a token is seen
172 */
173
skipUntilToken(void)174 void pushBackBuffer::skipUntilToken (void)
175 {
176 char ch;
177
178 while ((isWhite(putPB(getPB())) || (putPB(getPB()) == '#')) && (! eofFound)) {
179 ch = getPB();
180 if (ch == '#') {
181 skipToNewline();
182 }
183 }
184 }
185
186 /*
187 * isString - returns TRUE if the string, s, matches the pushed back string.
188 * if TRUE is returned then this string is consumed, otherwise it is
189 * left alone.
190 */
191
isString(const char * s)192 int pushBackBuffer::isString (const char *s)
193 {
194 int length=strlen(s);
195 int i=0;
196
197 while ((i<length) && (putPB(getPB())==s[i])) {
198 if (getPB() != s[i]) {
199 ERROR("assert failed");
200 }
201 i++;
202 }
203 if (i==length) {
204 return( TRUE );
205 } else {
206 i--;
207 while (i>=0) {
208 if (putPB(s[i]) != s[i]) {
209 ERROR("assert failed");
210 }
211 i--;
212 }
213 }
214 return( FALSE );
215 }
216
217 /*
218 * isDigit - returns TRUE if the character, ch, is a digit.
219 */
220
isDigit(char ch)221 static int isDigit (char ch)
222 {
223 return( ((ch>='0') && (ch<='9')) );
224 }
225
226 /*
227 * isHexDigit - returns TRUE if the character, ch, is a hex digit.
228 */
229
230 #if 0
231 static int isHexDigit (char ch)
232 {
233 return( (isDigit(ch)) || ((ch>='a') && (ch<='f')) );
234 }
235 #endif
236
237 /*
238 * readInt - returns an integer from the input stream.
239 */
240
readInt(void)241 int pushBackBuffer::readInt (void)
242 {
243 int c =0;
244 int i =0;
245 int s =1;
246 char ch=getPB();
247
248 while (isWhite(ch)) {
249 ch=getPB();
250 }
251 // now read integer
252
253 if (ch == '-') {
254 s = -1;
255 ch = getPB();
256 }
257 while (isDigit(ch)) {
258 i *= 10;
259 if ((ch>='0') && (ch<='9')) {
260 i += (int)(ch-'0');
261 }
262 ch = getPB();
263 c++;
264 }
265 if (ch != putPB(ch)) {
266 ERROR("assert failed");
267 }
268 return( i*s );
269 }
270
271 /*
272 * convertToFloat - converts integers, a and b into a.b
273 */
274
convertToFloat(int a,int b)275 static double convertToFloat (int a, int b)
276 {
277 int c=10;
278 double f;
279
280 while (b>c) {
281 c *= 10;
282 }
283 f = ((double)a) + (((double)b)/((double)c));
284 return( f );
285 }
286
287 /*
288 * readNumber - returns a float representing the word just read.
289 */
290
readNumber(void)291 double pushBackBuffer::readNumber (void)
292 {
293 int i;
294 char ch;
295
296 i = readInt();
297 if ((ch = getPB()) == '.') {
298 return convertToFloat(i, readInt());
299 }
300 putPB(ch);
301 return (double)i;
302 }
303
304 /*
305 * readString - reads a string terminated by white space
306 * and returns a malloced area of memory containing
307 * a copy of the characters.
308 */
309
readString(void)310 char *pushBackBuffer::readString (void)
311 {
312 char buffer[MAXPUSHBACKSTACK];
313 char *str = 0;
314 int i=0;
315 char ch=getPB();
316
317 while (isWhite(ch)) {
318 ch=getPB();
319 }
320 while ((i < MAXPUSHBACKSTACK) && (! isWhite(ch)) && (! eofFound)) {
321 buffer[i] = ch;
322 i++;
323 ch = getPB();
324 }
325 if (i < MAXPUSHBACKSTACK) {
326 buffer[i] = (char)0;
327 str = (char *)malloc(strlen(buffer)+1);
328 strcpy(str, buffer);
329 }
330 return( str );
331 }
332