/**
 * Add a string to the end of the current string in a string-builder-object.
 * The internal buffer is reallocated as needed.
 * If reallocation fails, the program halts.
 *
 * @param strbuilder The object to initialze. Must be initialized with
 *      dc_strbuilder_init().
 * @param text Null-terminated string to add to the end of the string-builder-string.
 * @return Returns a pointer to the copy of the given text.
 *     The returned pointer is a pointer inside dc_strbuilder_t::buf and MUST NOT
 *     be freed.  If the string-builder was empty before, the returned
 *     pointer is equal to dc_strbuilder_t::buf.
 *     If the given text is NULL, NULL is returned and the string-builder-object is not modified.
 */
char* dc_strbuilder_cat(dc_strbuilder_t* strbuilder, const char* text)
{
	// this function MUST NOT call logging functions as it is used to output the log
	if (strbuilder==NULL || text==NULL) {
		return NULL;
	}

	int len = strlen(text);

	if (len > strbuilder->free) {
		int add_bytes  = DC_MAX(len, strbuilder->allocated);
		int old_offset = (int)(strbuilder->eos - strbuilder->buf);

		strbuilder->allocated = strbuilder->allocated + add_bytes;
		strbuilder->buf       = realloc(strbuilder->buf, strbuilder->allocated+add_bytes);

        if (strbuilder->buf==NULL) {
			exit(39);
		}

		strbuilder->free      = strbuilder->free + add_bytes;
		strbuilder->eos       = strbuilder->buf + old_offset;
	}

	char* ret = strbuilder->eos;

	strcpy(strbuilder->eos, text);
	strbuilder->eos += len;
	strbuilder->free -= len;

	return ret;
}
/* the six output registers %o0-%o5 are always loaded, thus we need to ensure the argument buffer has space for at least 24 bytes. */
static DCCallVM* dc_callvm_new_sparc(DCCallVM_vt* vt, DCsize size)
{
  size=DC_MAX(size,sizeof(void*)*(6+1));
  DCCallVM_sparc* self = (DCCallVM_sparc*) dcAllocMem(sizeof(DCCallVM_sparc)+size);
  dc_callvm_base_init(&self->mInterface, vt);
  dcVecInit(&self->mVecHead,size);
  return (DCCallVM*)self;
}
void dc_callvm_call_mips_n64(DCCallVM* in_self, DCpointer target)
{
  DCCallVM_mips_n64* self = (DCCallVM_mips_n64*)in_self;
  /* at minimum provide 16-bytes
     which hold the first four integer register as spill area 
     and are automatically loaded to $4-$7
   */
  size_t size = DC_MAX(16, ( ( (unsigned) dcVecSize(&self->mVecHead) ) +7UL ) & (-8UL) );
  dcCall_mips_n64(target, &self->mRegData, size, dcVecData(&self->mVecHead));
}
void dc_callvm_call_ppc32_darwin(DCCallVM* in_self, DCpointer target)
{
    DCCallVM_ppc32* self = (DCCallVM_ppc32*)in_self;
    dcCall_ppc32_darwin(
        target,
        &self->mRegData,
        DC_MAX(dcVecSize(&self->mVecHead), 8*4),
        dcVecData(&self->mVecHead)
    );
}
/**
 * Init a string-builder-object.
 * A string-builder-object is placed typically on the stack and contains a string-buffer
 * which is initially empty.
 *
 * You can add data to the string-buffer using eg. dc_strbuilder_cat() or
 * dc_strbuilder_catf() - the buffer is reallocated as needed.
 *
 * When you're done with string building, the ready-to-use, null-terminates
 * string can be found at dc_strbuilder_t::buf, you can do whatever you like
 * with this buffer, however, never forget to call free() when done.
 *
 * @param strbuilder The object to initialze.
 * @param init_bytes The number of bytes to reserve for the string. If you have an
 *     idea about how long the resulting string will be, you can give this as a hint here;
 *     this avoids some reallocations; if the string gets longer, reallocation is done.
 *     If you do not know how larget the string will be, give 0 here.
 * @return None.
 */
void dc_strbuilder_init(dc_strbuilder_t* strbuilder, int init_bytes)
{
	if (strbuilder==NULL) {
		return;
	}

	strbuilder->allocated    = DC_MAX(init_bytes, 128); /* use a small default minimum, we may use _many_ of these objects at the same time */
	strbuilder->buf          = malloc(strbuilder->allocated);

    if (strbuilder->buf==NULL) {
		exit(38);
	}

	strbuilder->buf[0]       = 0;
	strbuilder->free         = strbuilder->allocated - 1 /*the nullbyte! */;
	strbuilder->eos          = strbuilder->buf;
}