/*
#ident "@(#)smail/src:RELEASE-3_2_0_121:dys.h,v 1.30 2005/11/15 01:15:16 woods Exp"
*/
/*
* Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
* Copyright (C) 1992 Ronald S. Karr
*
* See the file COPYING, distributed with smail, for restriction
* and warranty information.
*/
/*
* dys.h:
* macros for dynamic string region functions.
*
* The macros in this file provide a simple method of building strings in
* an environment where the final length requirements are not known.
* Thus, these macros automatically support growing of strings with
* xrealloc() when the current allocation is deemed insufficient.
*
* The 'str' structure has three values: a character pointer, an index,
* and an allocation size. The index is an offset from the character
* pointer to the current location being copied into and the allocation
* size is the current limit for the index, beyond which a call to
* xrealloc() is required.
*/
/*
* STR - access the string in question directly
*
* Note that 'struct str' arrays are not necessarily NUL-terminated unless
* they've explicitly been made so.
*/
#define STR(sp) ((sp)->p)
/*
* STR_LEN - since we have the value handy and pre-calculated
*/
#define STR_LEN(sp) ((sp)->i) /* remember, not i-1, zero offset! */
/*
* STR_GET - access the character at index 'pos' in a dynamic string
*
* This makes it easy to use one of the main benefits of this dynamic string
* implementation without having to directly know anything about the data
* structure's internal fields, namely access the character at the end of the
* string without having to search down the whole array for a terminator.
*/
#define STR_GET(sp, pos) ((sp)->p[(pos)])
/* STR_CHECK - call X_CHECK (from alloc.h) for a string */
#define STR_CHECK(sp) (void) ((sp) ? X_CHECK((sp)->p) : \
(write_log(WRITE_LOG_PANIC, \
"STR_CHECK(NULL), line=%d, file=%s", \
__LINE__, __FILE__), \
x_dont_panic ? \
FAIL : \
(abort(), 0)))
/* STR_ALLOCSZ - access the allocated size of the string buffer */
#define STR_ALLOCSZ(sp) ((sp)->a)
/* STR_BUMP - the basic quantum of allocation space */
#define STR_BUMP 64
/*
* STR_INIT - initialize the variables for a dynamic string region
* this macro should be called with the variables to be passed to
* other macros in this package before those other macros are used
*/
#define STR_INIT(sp) \
(((sp)->i = 0), \
((sp)->p = xmalloc((size_t) STR_BUMP)), \
((sp)->a = STR_BUMP))
/*
* STR_CLEAR - prepare to re-use a dynamic string
*/
#define STR_CLEAR(sp) ((sp)->i = 0)
/*
* STR_ZAP - give up a dynamic string after passing the pointer elsewhere
*
* XXX consistent use of STR_ZAP() everywhere might allow us to get rid of all
* the static "is it init'ed" variables and just rely on whether 'p' is nil or
* not to tell us whether to call STR_INIT().
*/
#define STR_ZAP(sp) \
(((sp)->a = 0), \
((sp)->i = 0), \
((sp)->p = NULL))
/*
* STR_NEXT - write to the next character in a dynamic string region, growing
* the region if no successor character currently is allocated. This can be
* used in the form:
*
* STR_NEXT(p, character expression);
*
* to load successive characters into the string.
*
* Increase allocated storage if 'c' would be written into the last available
* position of the currently allocated storage.
*/
#define STR_NEXT(sp, c) \
{ \
if ((sp)->i >= (sp)->a) { \
(sp)->a += STR_BUMP; \
(sp)->p = xrealloc((sp)->p, (sp)->a); \
} \
(sp)->p[(sp)->i++] = (c); \
}
/*
* STR_PREV - remove the previous character from a dynamic string
*/
#define STR_PREV(sp) ((sp)->i--)
/*
* STR_TRIM - trim a dynamic string to length 'len'
*
* If the string would grow bigger than the available allocated storage then
* make sure new storage is made available, and that the newly "used" portion
* of the new storage is also filled with NUL bytes.
*/
#define STR_TRIM(sp, len) \
{ \
if ((size_t) (len) >= (sp)->a) { \
write_log(WRITE_LOG_PANIC, \
"STR_TRIM(%p, %lu): at %s:%d, extending allocation from %lu", \
(POINTER_TYPE) (sp), (unsigned long) (len), \
__FILE__, __LINE__, \
(unsigned long) ((sp)->a)); \
(sp)->a += (((len) / STR_BUMP) + 1) * STR_BUMP; \
(sp)->p = xrealloc((sp)->p, (sp)->a); \
} \
if ((size_t) (len) > (sp)->i) { \
write_log(WRITE_LOG_PANIC, \
"STR_TRIM(%p, %lu): at %s:%d, extending length from %lu", \
(POINTER_TYPE) (sp), (unsigned long) (len), \
__FILE__, __LINE__, \
(unsigned long) ((sp)->i)); \
memset((sp)->p + (sp)->i, '\0', (len) - (sp)->i); \
} \
(sp)->i = (len); \
}
/*
* STR_CAT - concatenate a C string onto the end of a dynamic string region
* (thus NUL-terminating it), growing the storage region as necessary, but
* leave the NUL un-accounted for in the dynamic string's current length so
* that futher str_cat(), str_ncat(), or STR_NEXT(), etc. operations simply
* overwrite it.
*
* STR_NCAT - concatenate an array of characters of a given length onto the end
* of a dynamic string region, growing the storage region as necessary.
*
* These are now implemented as functions in string.c.
*/
#define STR_CAT(sp, cs) str_cat((sp), (cs))
#define STR_NCAT(sp, cs, len) str_ncat((sp), (cs), (len))
/*
* STR_DONE - finish building a dynamic string region. This is not
* required, though it will xrealloc a region to minimum length, which
* may be useful if xmalloc and xrealloc call something besides the
* stock malloc and realloc functions.
*/
#define STR_DONE(sp) ((sp)->p = xrealloc((char *) ((sp)->p), \
((sp)->i + 1)), \
(sp)->a = (sp)->i + 1)
/*
* STR_FREE - free a region, returning its storage to the free pool
*/
#define STR_FREE(sp) ((sp)->p ? (void) xfree((sp)->p) : (void) ((sp)->p = NULL, (sp)->i = 0))
/*
* STR_ALIGN - if region index is not aligned add bytes to align it.
*/
#define STR_ALIGN(sp) { while ((sp)->i % BYTES_PER_ALIGN) STR_NEXT((sp), 0); }
/*
* COPY_STRING - copy a C-style string to a new xmalloc'd region
*/
#define COPY_STRING(sp) (strcpy(xmalloc((size_t) (strlen((sp)) + 1)), (sp)))
/*
* Local Variables:
* c-file-style: "smail"
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1