/* vi: set tabstop=4 shiftwidth=4 */
/*
* $Id: fgetline.c,v 2.2 2005/08/07 17:20:16 schweikh Exp $
*/
/*@ignore@*/
#ifndef _POSIX_SOURCE
# define _POSIX_SOURCE 1
#endif
/*@end@*/
/*@+charintliteral@*/
#include <stdlib.h> /* malloc */
#include "error.h"
#include "fgetline.h"
/*
* fgetline: reads a stream up to the next eol character and
* returns the pointer to that line. The eol char is replaced
* by a \0. Returns NULL on EOF or error. To distinguish
* between EOF and error use feof(fp) which is nonzero
* on EOF. Memory is allocated using malloc(). The caller
* is responsible for freeing.
*/
/*
* M_START is the initial size of the allocated memory. It must be
* even and is doubled every time the line fills up the memory.
*/
#define M_START 16
#if M_START % 2 == 1
#error M_START must be even
#endif
char *
fgetline (FILE *fp, int eol)
{
char *mem, *write_to; /* mem is const, write_to changes */
int input;
size_t mem_size = M_START;
input = fgetc (fp);
if (input == EOF) {
return NULL; /* feof(fp) now is nonzero */
}
check (ungetc (input, fp) != 0);
/* okay, there is at least one character to read */
mem = NULL;
while (mem = xrealloc (mem, mem_size), 1) {
/*
* On the first iteration, make write_to = mem, otherwise
* let write_to point to the newly allocated memory.
*/
write_to = (mem_size == M_START ? mem : mem + mem_size/2);
/*@i@*/ while (write_to != mem + mem_size) { /* while we have space to write */
input = fgetc (fp);
if (input == eol || input == EOF) {
*write_to = '\0';
return mem;
}
*write_to++ = (char) input;
}
/*
* We have written mem+mem_size-write_to chars into mem[], it's full.
* But there might be more to read or an EOF coming. Even if EOF is
* next, we have to realloc to have space for the terminating \0.
*/
mem_size *= 2;
}
}
syntax highlighted by Code2HTML, v. 0.9.1