Merge from vendor branch OPENSSH:
[dragonfly.git] / contrib / gperf / src / read-line.cc
1 /* Correctly reads an arbitrarily size string.
2
3    Copyright (C) 1989-1998 Free Software Foundation, Inc.
4    written by Douglas C. Schmidt (schmidt@ics.uci.edu)
5
6 This file is part of GNU GPERF.
7
8 GNU GPERF is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
11 any later version.
12
13 GNU GPERF is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU GPERF; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111, USA.  */
21
22 #include "read-line.h"
23
24 #include <stdlib.h>
25 #include <string.h> /* declares memcpy() */
26 #include "options.h"
27 #include "trace.h"
28
29 /* Recursively fills up the buffer. */
30
31 #define CHUNK_SIZE 4096
32
33 /* CHUNKS is the number of chunks (each of size CHUNK_SIZE) which have
34    already been read and which are temporarily stored on the stack.
35    This function reads the remainder of the line, allocates a buffer
36    for the entire line, fills the part beyond &buffer[chunks*CHUNK_SIZE],
37    and returns &buffer[chunks*CHUNK_SIZE].  */
38
39 char *
40 Read_Line::readln_aux (int chunks)
41 {
42   T (Trace t ("Read_Line::readln_aux");)
43 #if LARGE_STACK
44   char buf[CHUNK_SIZE];
45 #else
46   // Note: we don't use new, because that invokes a custom operator new.
47   char *buf = (char*)malloc(CHUNK_SIZE);
48   if (buf == NULL)
49     abort ();
50 #endif
51   char *bufptr = buf;
52   char *ptr;
53   int c;
54
55   while (c = getc (fp), c != EOF && c != '\n') /* fill the current buffer */
56     {
57       *bufptr++ = c;
58       if (bufptr - buf == CHUNK_SIZE)
59         {
60           if ((ptr = readln_aux (chunks + 1)) != NULL)
61
62             /* prepend remainder to ptr buffer */
63             {
64               ptr -= CHUNK_SIZE;
65               memcpy (ptr, buf, CHUNK_SIZE);
66             }
67
68           goto done;
69         }
70     }
71   if (c == EOF && bufptr == buf && chunks == 0)
72     ptr = NULL;
73   else
74     {
75       size_t s1 = chunks * CHUNK_SIZE;
76       size_t s2 = bufptr - buf;
77
78       ptr = new char[s1+s2+1];
79       ptr += s1;
80       ptr[s2] = '\0';
81       memcpy (ptr, buf, s2);
82     }
83  done:
84 #if !LARGE_STACK
85   free (buf);
86 #endif
87
88   return ptr;
89 }
90
91 #ifndef __OPTIMIZE__
92
93 #define INLINE /* not inline */
94 #include "read-line.icc"
95 #undef INLINE
96
97 #endif /* not defined __OPTIMIZE__ */