apply new hurd patch to my tree
[debian/pax] / fgetln.c
1 /* fgetline:  Read one line of input and return a pointer to
2    that line.  Necessary space is obtained from malloc.
3    (char *) NULL is returned on EOF.
4
5     Andy Dougherty              doughera@lafcol.lafayette.edu
6     Dept. of Physics
7     Lafayette College, Easton PA 18042
8
9     Successive calls to fgetline() overwrite the original buffer.
10     If you want to preserve the data, you must do something like
11     the following (the +1's are for '\0' characters):
12
13         tmp = fgetline(fp);
14         ntmp = Ealloc(strlen(tmp)+1, sizeof(char));  
15         strncpy(ntmp, tmp, strlen(tmp)+1);
16
17     A line is defined as all characters up to (and including) the next
18     newline character or end of file.
19     The string is terminated by a NULL character.
20
21  * Version 1.1   A. Dougherty  2/7/94
22    Don't call realloc() just to save a few bytes.
23    Check return value from realloc().  (NULL is allowed under POSIX,
24    though I've never hit it.)
25
26  * Version 1.0  A. Dougherty  2/27/91
27
28  This fgetline implementation was written by Andrew Dougherty
29  <doughera@lafayette.edu>.  I hearby place it in the public domain.
30  As a courtesy, please leave my name attached to the source.
31
32  This code comes with no warranty whatsoever, and I take no
33  responsibility for any consequences of its use.
34 */
35
36 /* Algorithm:  A local static buffer "buf" is maintained.  The current
37    length (space available) is in the static variable "avail".  
38    Read in characters into this buffer.  If need more space, call
39    malloc().
40
41    Aside:  We have computed strlen(buf) in this function.  It
42    seems a shame to throw it away.
43 */
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <sys/types.h>
48
49 #define LINELEN 128 /* A decent guess that should only rarely be
50                         overwritten.
51                     */
52 #define OK_TO_WASTE 512 /* Don't bother trying to realloc() back to
53                            a smaller buffer if you'd only end up
54                            wasting OK_TO_WASTE bytes.
55                         */
56
57 void *Emalloc(size_t len) /* David */
58 {
59         char *p;
60
61         p=malloc(len);
62         if (p == NULL) {
63                 perror("out of memory (Emalloc)");
64                 exit(2);
65
66         }
67         return p;
68 }
69
70 void *Erealloc(char *p, size_t len) /* David */
71 {
72         p=realloc(p, len);
73         if (p == NULL) {
74                 perror("out of memory (Erealloc)");
75                 exit(2);
76
77         }
78         return p;
79 }
80
81 char *
82 fgetln(FILE *fp, size_t *length)
83   {
84     static char *buf = NULL;
85     static size_t avail = 0;
86     int c;
87     char *p; /* Temporary used for reducing length. */
88     int len;
89
90     if (avail == 0)
91       {
92         buf = (char *) Emalloc(LINELEN * sizeof(char));
93         avail = LINELEN;
94       }
95
96     len = 0; /* Current length */
97
98     while ((c=getc(fp)) != EOF)
99       {
100         if (len >= avail) /* Need to ask for space */
101           {
102             avail += LINELEN;  /* Maybe avail *= 2 would be better */
103             buf = (char *) Erealloc((void *) buf, avail * sizeof(char));
104           }
105         buf[len] = c;
106         len++;
107         if (c == '\n')
108             break;
109       }
110
111     if (c == EOF && len == 0)
112         return (char *) NULL;
113
114     /* Add terminating '\0' character */
115     if (len >= avail)  /* Need 1 more space */
116         buf = (char *) Erealloc((void *) buf, (len+1) * sizeof(char));
117     buf[len] = '\0';
118
119     /* Should we bother to try reclaiming memory?  (Otherwise, this
120        function will hold onto enough memory to hold the longest
121        line for the entire duration of the program.)
122     */
123     if (avail - len  > OK_TO_WASTE)
124       {
125         p = (char *) Erealloc((void *) buf, (len+1) * sizeof(char));
126         if (p != NULL)
127           {
128             buf = p;
129             avail = len + 1;
130           }
131       }
132     *length=len-1;
133     return buf;
134   }