
#include "V_M_UC.h"
#include "str.h"
#include "mem.h"

/*
* Append a string to a String.  Note that we may be passed the  length  as  an
* arg,  or the caller may pass -1 for len, in which case we call strlen to get
* the length.  If the caller knows the length, it is of course more  efficient
* to pass it to us than to re-compute it here.
*/
Str * str_appscm(dst,src,len,msg)
	Str   *dst;		/* Output string */
	char  *src;		/* Input string */
	int    len;		/* Length of src string, or -1 for strlen(src) */
	char  *msg;		/* For error messages */
{	int    m, n;
	char  *p;
	Fenter("str_appscm");
	if (!msg) msg = (CP)unknown;
	if (!dst) {			/* If there's no dst, alloc one */
		V7M "Get new Str ..." D;
		if (!(dst = (Str*)GetChunk(sizeof(Str),msg)))
			Fail;
		dst->l = dst->m = 0;
		dst->v = dst->p = 0;
		V8M "dst: l=%d m=%d v=%06X=\"%s\"",
			dst->l,dst->m,dst->v,NulC(dst->v) D;
	}
	if (src) {					/* Is src nonnull? */
		if (len < 0)			/* Shall we determine its length? */
			len = strlen(src);
		n = dst->l + len + 1;	/* Min size needed, including terminator */
		m = MEMUNIT(n);			/* Amount of space to grab */
		if (Igt(m,dst->m)) {		/* Is there room in current value? */
			if (!(p = (CP)GetChunk(m,msg)))
				Fail;			/* Get new space for it */
			if (dst->l)		/* Copy old value to new */
				Bcopy(dst->v,p,dst->l);
			if (dst->m && dst->v)	/* Discard old value */
				RelChunk(dst->v,msg);
			dst->p = (dst->p) ? (p + (dst->p - dst->v)) : 0;
			dst->v = p;		/* Plug in new value */
			dst->m = m;		/* New allocated size */
			V7M str_needmsg,m,msg,len D;
		}
		Bcopy(src,dst->v+dst->l,len);	/* Append the data */
		dst->v[dst->l += len] = 0;		/* Null terminator for debugging */
		V8M "dst: l=%d m=%d v=%06X=\"%s\"",
			dst->l,dst->m,dst->v,NulC(dst->v) D;
	} else {		/* The src string is null */
		V8M m_null D;
	}
	if (Vlvl>2 && ChkStrM(dst,msg))
		V2M str_badstmsg D;
fail:
	V8M "dst: l=%d m=%d v=%06X=\"%s\"",
		dst->l,dst->m,dst->v,NulC(dst->v) D;
	Fexit;
	return dst;
}
