/*
 *				f l e x . c
 */

/*)LIBRARY
*/

#ifdef	DOCUMENTATION

title	flex	Create a New Flex
index		Create a new flex

synopsis

	 #ifdef	vms
	 #include "c:flex.h"
	 #else
	 #include <flex.h>
	 #endif

	 FLEX *
	 flex(dim,isz,ext)
	 unsigned dim;		/* Initial size, items	*/
	 unsigned isz;		/* Item size, bytes	*/
	 unsigned ext;		/* Items to extend by	*/

description

	Flexes are dynamically expandable arrays.  If an attempt is made to
	add an item to a flex that is already full, the flex's core area is
	re-allocated to make more room.

	All the items in a flex must be the same size; all references are by
	item numbers, which, like array indices, run from 0 to (# items in the
	flex minus 1).  When a flex must expand, it expands some whole number
	of items; the particular number to expand by is stored in the flex's
	header.  If this number is zero, the flex cannot expand.

	If a flex cannot expand, either because its header sets a growth size
	of 0 or because there is insufficient core, but a request is made to
	add an item while it is full, the flex is marked damaged.  The core it
	used for its data is lost (realloc() free's it) and any further
	attempts to use the flex are ignored.  In general, any time a flex
	becomes damaged, or a damaged flex is passed to one of the flex
	handling routines, the routine returns NULL.  (Usually, they just
	return the flex passed.)

	A flex actually consists of a header, which contains information
	describing it, and a separate block of data.  The first item in the
	header is a pointer to the data.  While the header never moves, the
	data may move any time items are added to or removed from the flex.

	It is occassionally necessary to recover the information in a damaged
	flex (in most cases, there is no reasonable way to continue once the
	program runs out of memory).  This can be done by making use of
	realloc()'s ability to reallocate the most recently freed block of
	core.  Before making the potentially damaging call, save the current
	values of the fxdata and fxused elements of the flex.  Should the
	flex become damaged, the fxdata value can be passed to realloc()
	safely.  Note that this recovers the data, but not the flex's header;
	you still cannot apply any of the flex-handling functions to it.

	The various flex handling functions in the Utility Library all have
	names beginning "fx".  They form a fairly complete set of primitives.
	You may wish to restrict yourself to doing all accesses through these
	routines since this would, in principle, allow you to replace them
	with a set of routines that, for example, page items to disk if a flex
	gets too large.

	The file flex.h contains some definitions that are useful when dealing
	with flexes.

	The function flex(dim,isz,ext) creates a new flex.  The data area of
	the flex will initially contain sufficient space for dim items, each
	isz bytes in length.  If the flex fills, it will be extended in units
	of ext items.

bugs

author

	Jerry Leichter

#endif

/*
 * )EDITLEVEL=10
 * Edit history
 * 0.0  4-May-81 JSL	Invention
 * 0.1  5-May-81 JSL	Cleanup; add fxneed
 * 0.2  7-May-81 JSL	Split flex.c into separate files; this is one
 * 0.3 23-Jun-81 JSL	Conversion to new documentation convention
 */

#ifdef	vms
#include "c:flex.h"
#else
#include <flex.h>
#endif
#define NULL 0

extern char *malloc();

FLEX *
flex(dim,isz,ext)
unsigned dim;		/* initial size, in items */
unsigned isz;		/* size of an item in bytes */
unsigned ext;		/* number of items to extend by; 0 means no extends */
{	register FLEX *fx;
	if ((fx = (FLEX *)malloc(sizeof(FLEX))) == NULL)
		return(NULL);
	if ((fx->fxdata = malloc(dim*isz)) == NULL)
	{	free(fx);
		return(NULL);
	}
	fx->fxdim = dim;
	fx->fxisz = isz;
	fx->fxext = ext;
	fx->fxused = 0;
	return(fx);
}	
