xref: /netbsd-src/external/gpl2/groff/dist/src/preproc/html/pushback.cpp (revision 89a07cf815a29524268025a1139fac4c5190f765)
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