/* * 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 #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 #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); }