dyngets.c

/*
 * dyngets.c (library)	  Matt Bishop     January 15, 1994
 *
 * Entry point:
 *	char *dyngets(char *buf, int n, FILE *fp)
 * 	Read the next line from the input and return a pointer to a buffer
 *	containing that line.  If buf is non-NULL on entry, this call is
 *	identical to fgets(3S); if buf is NULL, the second argument n is
 *	ignored, and the pointer returned points to an allocated buffer
 *	with all of the next line of the file in it, REGARDLESS of length.
 *
 * Modification history:
 *      1/10/94 Matt Bishop     original
 */
#include <stdio.h>
#include <malloc.h>

/*
 * macros
 */
#define INCREMENT	10		/* allocate this many chars, and */
					/* increase space by this many   */
					/* chars when necessary          */
#define NCHAR(n)	((n) * sizeof(char))	/* space for n chars */

/*
 * chins: insert a character into an array, increasing the size of
 *	  the array if necessary by INCREMENT characters
 *
 * arguments:   int c		character to be inserted
 *		int pos		position in the array to insert character
 *		char **space	points to pointer to array
 *		int *nspace	points to integer representing size of array
 *				already allocated
 *
 * return:      0	attempt to increase size of array failed, so
 *			the character could not be inserted
 *              1	character inserted successfully
 *
 * output:      none
 *
 * exceptions:  cannot allocate (reallocate) memory (no message, return 0)
 */
int chins(int c, int pos, char **space, int *nspace)
{
	char *r;		/* temp pointer to allocated space */

	/*
	 * see if we need more space
	 */
	if (pos >= *nspace){
		/* yes -- get size of the new allocation */
		*nspace += INCREMENT;
		/* do we allocate or make it grow? */
		if (*space == NULL){
			/* first time -- allocate */
			if ((r = malloc(NCHAR(*nspace))) == NULL)
				return(0);
		}
		else{
			/* not the first time -- reallocate */
			if ((r = realloc(*space, NCHAR(*nspace))) == NULL)
				return(0);
		}
		/* now update the reserved space parameter */
		*space = r;
	}
	/*
	 * we have enough space or
	 * we wouldn't be here -- add the char
	 */
	(*space)[pos] = c;
	return(1);
}

/*
 * dyngets: read a line from the given file, and return a pointer to
 *	    a character array holding it
 *
 * arguments:   char *buf	buffer to put input characters in; if NULL,
 *				dyngets will use (and allocate if necessary)
 *				its own buffer
 *		int n		size of array buf; ignored if buf is NULL
 *		FILE *fp	pointer to file to be read
 *
 * return:      char *	points to array holding input line:
 *			if buf is non-NULL, this is the same as buf,
 *			and one line (or n-1 chars from that line,
 *			whichever is less) is stored inbuf
 *			if buf is NULL, one line is stored in
 *			allocated space
 *              NULL	on EOF or error
 *
 * output:      dyngets: ran out of room
 *			could not allocate enough space to hold input line
 *
 * exceptions:  ran out of room (error message and return)
 */
char *dyngets(char *buf, int n, FILE *fp)
{
	static char *space = NULL;	/* internal buffer */
	static int nspace = 0;		/* size of internal buffer */
	int c;				/* input character */
	int i;				/* index of space to put char in */

	/*
	 * if we're told where to put the input
	 * let someone else do the work for us!
	 */
	if (buf != NULL)
		return(fgets(buf, n, fp));

	/*
	 * read up to the next newline or EOF,
	 * and append it to the current line
	 */
	for(i = 0; (c = getc(fp)) != '\n' && c != EOF; i++)
		if (chins(c, i, &space, &nspace) == 0){
			fprintf(stderr, "dyngets: ran out of room\n");
			return(NULL);
		}

	/*
	 * if EOF is the first character in the line,
	 * you're done; indicate this
	 */
	if (c == EOF && i == 0)
		return(NULL);

	/*
	 * tack on the newline, if present
	 */
	if (c == '\n' && chins('\n', i++, &space, &nspace) == 0){
		fprintf(stderr, "dyngets: ran out of room\n");
		return(NULL);
	}

	/*
	 * tack on the string terminator
	 */
	if (chins('\0', i, &space, &nspace) == 0){
		fprintf(stderr, "dyngets: ran out of room\n");
		return(NULL);
	}

	/*
	 * return pointer to internally allocated buffer
	 */
	return(space);
}


UC Davis sigil
Matt Bishop
Office: 2209 Watershed Sciences
Phone: +1 (530) 752-8060
Email: mabishop@ucdavis.edu
ECS 36A, Programming & Problem Solving
Version of April 2, 2024 at 12:13PM

You can get the raw source code here.

Valid HTML 4.01 Transitional Built with BBEdit Built on a Macintosh