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 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 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 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 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 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 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 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 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 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 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 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 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 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 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