1/*	$NetBSD: expand.h,v 1.4 2001/07/26 15:05:07 wiz Exp $	*/
2
3/*
4 * Expanding strings
5 */
6/* $Id: expand.h,v 1.4 2001/07/26 15:05:07 wiz Exp $ */
7
8#define X_EXTRA		8	/* this many extra bytes in X string */
9
10#if 0				/* Usage */
11	XString xs;
12	char *xp;
13
14	Xinit(xs, xp, 128, ATEMP); /* allocate initial string */
15	while ((c = generate()) {
16		Xcheck(xs, xp);	/* expand string if necessary */
17		Xput(xs, xp, c); /* add character */
18	}
19	return Xclose(xs, xp);	/* resize string */
20/*
21 * NOTE:
22 *     The Xcheck and Xinit macros have a magic + X_EXTRA in the lengths.
23 *     This is so that you can put up to X_EXTRA characters in a XString
24 *     before calling Xcheck. (See yylex in lex.c)
25 */
26#endif /* 0 */
27
28typedef struct XString {
29	char   *end, *beg;	/* end, begin of string */
30	size_t	len;		/* length */
31	Area	*areap;		/* area to allocate/free from */
32} XString;
33
34typedef char * XStringP;
35
36/* initialize expandable string */
37#define	Xinit(xs, xp, length, area) do { \
38			(xs).len = length; \
39			(xs).areap = (area); \
40			(xs).beg = alloc((xs).len + X_EXTRA, (xs).areap); \
41			(xs).end = (xs).beg + (xs).len; \
42			xp = (xs).beg; \
43		} while (0)
44
45/* stuff char into string */
46#define	Xput(xs, xp, c)	(*xp++ = (c))
47
48/* check if there are at least n bytes left */
49#define	XcheckN(xs, xp, n) do { \
50		    int more = ((xp) + (n)) - (xs).end; \
51		    if (more > 0) \
52			xp = Xcheck_grow_(&xs, xp, more); \
53		} while (0)
54
55/* check for overflow, expand string */
56#define Xcheck(xs, xp)	XcheckN(xs, xp, 1)
57
58/* free string */
59#define	Xfree(xs, xp)	afree((void*) (xs).beg, (xs).areap)
60
61/* close, return string */
62#define	Xclose(xs, xp)	(char*) aresize((void*)(xs).beg, \
63					(size_t)((xp) - (xs).beg), (xs).areap)
64/* begin of string */
65#define	Xstring(xs, xp)	((xs).beg)
66
67#define Xnleft(xs, xp) ((xs).end - (xp))	/* may be less than 0 */
68#define	Xlength(xs, xp) ((xp) - (xs).beg)
69#define Xsize(xs, xp) ((xs).end - (xs).beg)
70#define	Xsavepos(xs, xp) ((xp) - (xs).beg)
71#define	Xrestpos(xs, xp, n) ((xs).beg + (n))
72
73char *	Xcheck_grow_	ARGS((XString *xsp, char *xp, int more));
74
75/*
76 * expandable vector of generic pointers
77 */
78
79typedef struct XPtrV {
80	void  **cur;		/* next avail pointer */
81	void  **beg, **end;	/* begin, end of vector */
82} XPtrV;
83
84#define	XPinit(x, n) do { \
85			register void **vp__; \
86			vp__ = (void**) alloc(sizeofN(void*, n), ATEMP); \
87			(x).cur = (x).beg = vp__; \
88			(x).end = vp__ + n; \
89		    } while (0)
90
91#define	XPput(x, p) do { \
92			if ((x).cur >= (x).end) { \
93				int n = XPsize(x); \
94				(x).beg = (void**) aresize((void*) (x).beg, \
95						   sizeofN(void*, n*2), ATEMP); \
96				(x).cur = (x).beg + n; \
97				(x).end = (x).cur + n; \
98			} \
99			*(x).cur++ = (p); \
100		} while (0)
101
102#define	XPptrv(x)	((x).beg)
103#define	XPsize(x)	((x).cur - (x).beg)
104
105#define	XPclose(x)	(void**) aresize((void*)(x).beg, \
106					 sizeofN(void*, XPsize(x)), ATEMP)
107
108#define	XPfree(x)	afree((void*) (x).beg, ATEMP)
109