Imported Debian patch 1.5-15
[debian/pax] / fgetln.c
diff --git a/fgetln.c b/fgetln.c
new file mode 100644 (file)
index 0000000..03afbb0
--- /dev/null
+++ b/fgetln.c
@@ -0,0 +1,134 @@
+/* fgetline:  Read one line of input and return a pointer to
+   that line.  Necessary space is obtained from malloc.
+   (char *) NULL is returned on EOF.
+
+    Andy Dougherty             doughera@lafcol.lafayette.edu
+    Dept. of Physics
+    Lafayette College, Easton PA 18042
+
+    Successive calls to fgetline() overwrite the original buffer.
+    If you want to preserve the data, you must do something like
+    the following (the +1's are for '\0' characters):
+
+       tmp = fgetline(fp);
+       ntmp = Ealloc(strlen(tmp)+1, sizeof(char));  
+       strncpy(ntmp, tmp, strlen(tmp)+1);
+
+    A line is defined as all characters up to (and including) the next
+    newline character or end of file.
+    The string is terminated by a NULL character.
+
+ * Version 1.1   A. Dougherty  2/7/94
+   Don't call realloc() just to save a few bytes.
+   Check return value from realloc().  (NULL is allowed under POSIX,
+   though I've never hit it.)
+
+ * Version 1.0  A. Dougherty  2/27/91
+
+ This fgetline implementation was written by Andrew Dougherty
+ <doughera@lafayette.edu>.  I hearby place it in the public domain.
+ As a courtesy, please leave my name attached to the source.
+
+ This code comes with no warranty whatsoever, and I take no
+ responsibility for any consequences of its use.
+*/
+
+/* Algorithm:  A local static buffer "buf" is maintained.  The current
+   length (space available) is in the static variable "avail".  
+   Read in characters into this buffer.  If need more space, call
+   malloc().
+
+   Aside:  We have computed strlen(buf) in this function.  It
+   seems a shame to throw it away.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#define LINELEN 128 /* A decent guess that should only rarely be
+                       overwritten.
+                   */
+#define OK_TO_WASTE 512 /* Don't bother trying to realloc() back to
+                          a smaller buffer if you'd only end up
+                          wasting OK_TO_WASTE bytes.
+                       */
+
+void *Emalloc(size_t len) /* David */
+{
+       char *p;
+
+       p=malloc(len);
+       if (p == NULL) {
+               perror("out of memory (Emalloc)");
+               exit(2);
+
+       }
+       return p;
+}
+
+void *Erealloc(char *p, size_t len) /* David */
+{
+       p=realloc(p, len);
+       if (p == NULL) {
+               perror("out of memory (Erealloc)");
+               exit(2);
+
+       }
+       return p;
+}
+
+char *
+fgetln(FILE *fp, size_t *length)
+  {
+    static char *buf = NULL;
+    static size_t avail = 0;
+    int c;
+    char *p; /* Temporary used for reducing length. */
+    int len;
+
+    if (avail == 0)
+      {
+       buf = (char *) Emalloc(LINELEN * sizeof(char));
+       avail = LINELEN;
+      }
+
+    len = 0; /* Current length */
+
+    while ((c=getc(fp)) != EOF)
+      {
+       if (len >= avail) /* Need to ask for space */
+         {
+           avail += LINELEN;  /* Maybe avail *= 2 would be better */
+           buf = (char *) Erealloc((void *) buf, avail * sizeof(char));
+         }
+       buf[len] = c;
+       len++;
+       if (c == '\n')
+           break;
+      }
+
+    if (c == EOF && len == 0)
+       return (char *) NULL;
+
+    /* Add terminating '\0' character */
+    if (len >= avail)  /* Need 1 more space */
+       buf = (char *) Erealloc((void *) buf, (len+1) * sizeof(char));
+    buf[len] = '\0';
+
+    /* Should we bother to try reclaiming memory?  (Otherwise, this
+       function will hold onto enough memory to hold the longest
+       line for the entire duration of the program.)
+    */
+    if (avail - len  > OK_TO_WASTE)
+      {
+       p = (char *) Erealloc((void *) buf, (len+1) * sizeof(char));
+       if (p != NULL)
+         {
+           buf = p;
+           avail = len + 1;
+         }
+      }
+    *length=len-1;
+    return buf;
+  }