/* * v s t r i n g . c */ /*)LIBRARY */ #ifdef DOCUMENTATION title vstring Functions to Manipulate Vstrings index Create a new vstring index Add a character to a vstring index Add a string to a vstring index Free a vstring synopsis #ifdef vms #include "c:vstrin.h" #else #include #endif VSTRING * vstring(dim,ext) unsigned dim; unsigned ext; VSTRING * vsaddc(pv,c) VSTRING *pv; char c; VSTRING * vsadds(pv,s) VSTRING *pv; char *s; vsfree(pv) VSTRING *pv; description Vstrings are dynamically expandable strings. They have room for some fixed number of characters, but can grow, obtaining memory through malloc(), if necessary. vstring(dim,ext) returns a pointer to a new vstring, or NULL if there is no space for one. The vstring initially has room for dim bytes, and will grow by ext bytes if it fills. vsaddc() adds a character to a vstring. vsadds() adds a string to a vstring. It merely calls vsaddc() in a loop. The trailing EOS is NOT added. Both vsaddc() and vsadds() return NULL if the vstring would have had to grow but couldn't due to lack of memory or a zero growth quantum. In this case, the data in the vstring is lost and the vstring itself is marked damaged and cannot be used again; further attempts always return NULL. If all went well, the vstring's address as passed is returned. It is occassionally necessary to recover the information in a damaged vstring (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 vsdata and vsused elements of the vstring. Should the vstring become damaged, the vsdata value can be passed to realloc() safely. Note that this recovers the data, but not the vstring's header; you still cannot apply any of the vstring-handling functions to it. vsfree() frees a vstring. Attempting to free something that was not created with vstring() will cause trouble. However, NULL or a vstring that was filled and marked damaged may be safely passed. bugs A vstring is a special case of a flex which always has an item size of 1 byte. It is convenient to maintain it as a separate data type because the kinds of operations done on the two differ. For example, fxadd() takes the address of the item to add; vsaddc() takes the character itself, which is often more convenient. The basic set of functions provided for vstrings is more limited; perhaps more purely string-oriented functions that work on vstrings will be defined later. author Jerry Leichter #endif /* *)EDITLEVEL=10 * Edit history * 0.0 28-Apr-81 JSL Invention * 0.1 4-May-81 JSL Better error handling * 0.2 12-May-81 JSL Decided to keep blocks around after all; changed the * name of balloc() to block() to match flex(). * 0.3 23-Jun-81 JSL Conversion to the new documentation conventions. * 1.0 26-Jun-81 JSL Changed block to vstring, which makes more sense. * 1.1 29-Jun-81 JSL More name changes; get consistent with flexes. */ #ifdef vms #include "c:vstrin.h" #else #include #endif #define NULL 0 extern char *malloc(), *realloc(); VSTRING * vstring(dim,ext) unsigned dim; /* initial size for this vstring */ unsigned ext; /* growth quantum */ { register VSTRING *pv; if ((pv = (VSTRING *)malloc(sizeof(VSTRING))) == NULL) return(NULL); if ((pv->vsdata = malloc(dim)) == NULL) { free(pv); return(NULL); } pv->vsdim = dim; pv->vsext = ext; pv->vslen = 0; return(pv); } VSTRING * vsaddc(pv,c) register VSTRING *pv; char c; { if (pv != NULL) { if (pv->vsdim <= pv->vslen) { pv->vsdim += pv->vsext; if (pv->vsdim <= pv->vslen || pv->vsdata == NULL || (pv->vsdata = realloc(pv->vsdata,pv->vsdim)) == NULL) { pv->vsdim = 0; return(pv->vsdata = NULL); } } (pv->vsdata)[pv->vslen++] = c; } return(pv); } VSTRING * vsadds(pv,s) register VSTRING *pv; register char *s; { while (*s) pv = vsaddc(pv,*s++); return(pv); } vsfree(pv) register VSTRING *pv; { if (pv != NULL) { if (pv->vsdata != NULL) free(pv->vsdata); free(pv); } }