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