tmuck2.4/
tmuck2.4/admin/scripts/
tmuck2.4/docs/
tmuck2.4/minimal-db/
tmuck2.4/minimal-db/data/
tmuck2.4/minimal-db/logs/
tmuck2.4/minimal-db/muf/
tmuck2.4/old/
tmuck2.4/src/
tmuck2.4/src/compile/
tmuck2.4/src/editor/
tmuck2.4/src/game/
tmuck2.4/src/interface/
tmuck2.4/src/scripts/
tmuck2.4/src/utilprogs/
/* Copyright (c) 1992 by David Moore.  All rights reserved. */
/* string_prims.c,v 2.5 1997/08/29 21:02:08 dmoore Exp */
#include "config.h"

#include <string.h>

#include "db.h"
#include "code.h"
#include "prim_offsets.h"
#include "buffer.h"
#include "externs.h"


/* Use this to get shared strings in a nice format. */
#define SSText(x)	((x)->un.string ? (x)->un.string->data : "")
#define SSLen(x)	((x)->un.string ? (x)->un.string->length : 0)

/* All of your basic string primitives (including notifies):
   pronoun_sub, explode, subst, instr, rinstr, number, stringcmp,
   strcmp, strncmp, strcut, strlen, strcat, atoi, intostr
   notify, notify_except */

static Buffer buf;		/* Global buffer for all routines to use. */


MUF_PRIM(prim_pronoun)
{
    inst format;
    inst who;
    inst result;

    pop_stack(curr_data_st, &format);
    pop_stack(curr_data_st, &who);

    Bufsprint(&buf, "%p", who.un.object, SSText(&format));

    result.type = INST_STRING;
    result.un.string = make_shared_string(Buftext(&buf), Buflen(&buf));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_explode)
{
    inst str1, str2;
    inst temp;
    const char *pat;
    char *orig;
    int origlen, patlen;
    int pos;
    int count;

    pop_stack(curr_data_st, &str2);
    pop_stack(curr_data_st, &str1);

    count = 0;
    temp.type = INST_STRING;

    Bufcpy(&buf, SSText(&str1));
    orig = Buftext(&buf);
    origlen = Buflen(&buf);
    pat = SSText(&str2);
    patlen = SSLen(&str2);

    while ((pos = muck_rinstr(orig, origlen, pat, patlen))) {
	pos--;

	temp.un.string = make_shared_string(orig + pos + patlen,
					    origlen - pos - patlen);
	
	orig[pos] = '\0';
	origlen = pos;

	safe_push_data_st(curr_frame, curr_data_st, &temp, PRIM_explode);
	if (curr_frame->error) return;

	count++;
    }

    temp.un.string = make_shared_string(orig, origlen);
	    
    safe_push_data_st(curr_frame, curr_data_st, &temp, PRIM_explode);
    if (curr_frame->error) return;
	    
    count++;

    temp.type = INST_INTEGER;
    temp.un.integer = count;
    
    safe_push_data_st(curr_frame, curr_data_st, &temp, PRIM_explode);
}



MUF_PRIM(prim_subst)
{
    inst str, orig, repl;
    inst result;
    const char *subbed;
    int len;

    pop_stack(curr_data_st, &orig);
    pop_stack(curr_data_st, &repl);
    pop_stack(curr_data_st, &str);

    subbed = muck_subst(SSText(&str), SSText(&orig), SSLen(&orig),
			SSText(&repl), &len);

    result.type = INST_STRING;
    result.un.string = make_shared_string(subbed, len);

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_instr)
{
    inst str, pattern;
    inst result;

    pop_stack(curr_data_st, &pattern);
    pop_stack(curr_data_st, &str);
   
    result.type = INST_INTEGER;
    result.un.integer = muck_instr(SSText(&str), SSLen(&str),
				   SSText(&pattern), SSLen(&pattern));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_rinstr)
{
    inst str, pattern;
    inst result;

    pop_stack(curr_data_st, &pattern);
    pop_stack(curr_data_st, &str);

    result.type = INST_INTEGER;
    result.un.integer = muck_rinstr(SSText(&str), SSLen(&str),
				    SSText(&pattern), SSLen(&pattern));
   
    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_numberp)
{
    inst str;
    inst result;

    pop_stack(curr_data_st, &str);

    result.type = INST_INTEGER;
    result.un.integer = number(SSText(&str));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_stringcmp)
{
    inst arg1, arg2;
    inst result;

    pop_stack(curr_data_st, &arg2);
    pop_stack(curr_data_st, &arg1);

    result.type = INST_INTEGER;
    result.un.integer = muck_stricmp(SSText(&arg1), SSText(&arg2));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_strcmp)
{
    inst arg1, arg2;
    inst result;

    pop_stack(curr_data_st, &arg2);
    pop_stack(curr_data_st, &arg1);

    result.type = INST_INTEGER;
    result.un.integer = strcmp(SSText(&arg1), SSText(&arg2));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_strncmp)
{
    inst str1, str2, size;
    inst result;

    pop_stack(curr_data_st, &size);
    pop_stack(curr_data_st, &str2);
    pop_stack(curr_data_st, &str1);

    result.type = INST_INTEGER;
    result.un.integer = strncmp(SSText(&str1), SSText(&str2), size.un.integer);

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_stringncmp)
{
    inst str1, str2, size;
    inst result;

    pop_stack(curr_data_st, &size);
    pop_stack(curr_data_st, &str2);
    pop_stack(curr_data_st, &str1);

    result.type = INST_INTEGER;
    result.un.integer = muck_strnicmp(SSText(&str1), SSText(&str2),
				      size.un.integer);

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_strcut)
{
    inst str, n;
    inst result1, result2;

    pop_stack(curr_data_st, &n);
    pop_stack(curr_data_st, &str);

    if (n.un.integer < 0) {
	interp_error(curr_frame, PRIM_strcut, "Non-negative arg needed");
	return;
    }

    result1.type = INST_STRING;
    result2.type = INST_STRING;

    if (!str.un.string) {
	result1.un.string = NULL;
	result2.un.string = NULL;
    } else if (n.un.integer > SSLen(&str)) {
	result1.un.string = dup_shared_string(str.un.string);
	result2.un.string = NULL;
    } else {
	Bufncpy(&buf, SSText(&str), n.un.integer);
	result1.un.string = make_shared_string(Buftext(&buf), Buflen(&buf));
	
	result2.un.string = make_shared_string(SSText(&str) + n.un.integer,
					       SSLen(&str) - n.un.integer);
    }

    push_stack(curr_data_st, &result1);
    push_stack(curr_data_st, &result2);
}


MUF_PRIM(prim_strlen)
{
    inst str;
    inst result;

    pop_stack(curr_data_st, &str);

    result.type = INST_INTEGER;
    result.un.integer = SSLen(&str);

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_strcat)
{
    inst str1, str2;
    inst result;

    pop_stack(curr_data_st, &str2);
    pop_stack(curr_data_st, &str1);
    

    result.type = INST_STRING;
    if (!str1.un.string) {
	result.un.string = dup_shared_string(str2.un.string);
    } else if (!str2.un.string) {
	result.un.string = dup_shared_string(str1.un.string);
    } else {
	result.un.string = make2_shared_string(SSText(&str1), SSLen(&str1),
					       SSText(&str2), SSLen(&str2));
    }

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_atoi)
{
    inst str;
    inst result;

    pop_stack(curr_data_st, &str);

    result.type = INST_INTEGER;
    result.un.integer = atoi(SSText(&str));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_intostr)
{
    inst arg, result;
    Buffer buf;

    pop_stack(curr_data_st, &arg);

    switch (arg.type) {
    case INST_INTEGER:
	Bufsprint(&buf, "%i", arg.un.integer);
	break;
    case INST_OBJECT:
	Bufsprint(&buf, "%d", arg.un.object);
	break;
    default:
	interp_error(curr_frame, PRIM_intostr, "Requires integer or object");
	return;
	break;
    }

    result.type = INST_STRING;
    result.un.string = make_shared_string(Buftext(&buf), Buflen(&buf));

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_strftime)
{
    inst when, format;
    inst result;

    pop_stack(curr_data_st, &format);
    pop_stack(curr_data_st, &when);

    result.type = INST_STRING;
    if (format.un.string) {
	Bufsprint(&buf, "%t", SSText(&format), when.un.integer);
	result.un.string = make_shared_string(Buftext(&buf), Buflen(&buf));
    } else {
	result.un.string = NULL;
    }

    push_stack(curr_data_st, &result);
}


MUF_PRIM(prim_notify)
{
    inst who, message;

    /* Pops are guaranteed safe before calling.  And types checked. */
    pop_stack(curr_data_st, &message);
    pop_stack(curr_data_st, &who);

    if (message.un.string) {
	notify(who.un.object, "%s", message.un.string->data);
    }
}


MUF_PRIM(prim_notify_except)
{
    inst loc;
    inst who_not;
    inst message;

    pop_stack(curr_data_st, &message);
    pop_stack(curr_data_st, &who_not);
    pop_stack(curr_data_st, &loc);

    if (message.un.string) {
	notify_except(loc.un.object, who_not.un.object, "%s",
		      message.un.string->data);
    }
}