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