/*
 *  hap -- a mail notification program
 * 
 *  copyright 1995 by Eric Fischer, etaoin@uchicago.edu
 * 
 *  copies of hap may be redistributed under the terms of the
 *  GNU public license, copies of which are available from
 *  the Free Software Foundation, 59 Temple Place, Boston, MA
 *  02111 USA.
 *
 */

#include <stdio.h>
#include <stdlib.h>

#include "fgetl.h"

#define INITBUFSIZE 100  /* line length we start with */
#define BUFSIZEINCR 100  /* amount to incr each time it gets too big */

/* malloc, but die if it fails. only use to allocate char[] */

static char *
fgmalloc (size)
	int size;
{
	char *foo;

	foo = malloc (size * sizeof (char));
	if (foo == 0) {
		fprintf (stderr, "fgetl: memory allocation failure\n");
		exit (1);
	}

	return foo;
}

/* realloc, but die if it fails.  again, char[] only */

static char *
fgrealloc (what, size)
	char *what;
	int size;
{
	what = realloc (what, size * sizeof (char));
	if (what == 0) {
		fprintf (stderr, "fgetl: memory allocation failure\n");
		exit (1);
	}

	return what;
}

/* get a line of text from the FILE pointed to by which, and return
   a pointer to it.  This is quite similar to the Berkeley 4.4
   fgetln(), except that since they're inside stdio they get to use
   internal buffers while we have to make our own.  Anyway, the
   memory allocated is *not* to be freed by the calling function;
   this would be one of those "returns a pointer to static data
   which is overwritten with each call" except that since our buffer
   grows as needed it's not quite static.
*/

char *
fgetl (which)
	FILE *which;
{
	static char *line = 0;
	static int len = 0;  /* longest line[] has ever been */

	int c;      /* char we read */
	int l = 0;  /* where we are in the string now */

	if (line == 0) {
		line = fgmalloc (INITBUFSIZE);
		len = INITBUFSIZE;
	}

	while ((c = getc (which)) != EOF) {

		/* make sure there's room for the new char */

		if (l >= len) {
			len += BUFSIZEINCR;
			line = fgrealloc (line, len);
		}

		line[l] = c;
		l++;

		/* if we added a newline, stop */

		if (c == '\n') break;
	}

	/* if we've read all the chars and l is still 0, we must be
	   at EOF, so return 0
	*/

	if (l == 0) {
		return 0;
	}

	/* make sure there's room for the \0 on the end */

	if (l >= len) {
		len += BUFSIZEINCR;
		line = fgrealloc (line, len);
	}

	/* put it there, return the string */

	line[l] = 0;
	return line;
}

