Ejemplo n.º 1
0
stk_array *
array_promote(stk_array *arr)
{
    stk_array *new2;
    int i;
    array_iter idx;

    if (!arr) {
        return NULL;
    }
    if (arr->type != ARRAY_PACKED) {
        return NULL;
    }

    new2 = new_array_dictionary();

    idx.type = PROG_INTEGER;
    for (i = 0; i < arr->items; i++) {
        idx.data.number = i;
        array_setitem(&new2, &idx, array_getitem(arr, &idx));
    }
    array_free(arr);

    return new2;
}
Ejemplo n.º 2
0
void
prim_event_send(PRIM_PROTOTYPE)
{
    struct frame *destfr;
    stk_array *arr;
    struct inst temp1;

    CHECKOP(3);
    oper3 = POP();		/* any: data to pass */
    oper2 = POP();		/* string: event id */
    oper1 = POP();		/* int: process id to send to */

    if (mlev < 3)
	abort_interp("Requires Mucker level 3 or better.");
    if (oper1->type != PROG_INTEGER)
	abort_interp("Expected an integer process id. (1)");
    if (oper2->type != PROG_STRING)
	abort_interp("Expected a string event id. (2)");

    if (oper1->data.number == fr->pid)
	destfr = fr;
    else
	destfr = timequeue_pid_frame(oper1->data.number);

    if (destfr) {
        stk_array_active_list = &destfr->array_active_list;
        struct inst data_copy;
        deep_copyinst(oper3, &data_copy, destfr->pinning);
	arr = new_array_dictionary(destfr->pinning);
	array_set_strkey(&arr, "data", &data_copy);
	array_set_strkey_intval(&arr, "caller_pid", fr->pid);
	array_set_strkey_intval(&arr, "descr", fr->descr);
	array_set_strkey_refval(&arr, "caller_prog", program);
	array_set_strkey_refval(&arr, "trigger", fr->trig);
	array_set_strkey_refval(&arr, "prog_uid", ProgUID);
	array_set_strkey_refval(&arr, "player", player);

	temp1.type = PROG_ARRAY;
	temp1.data.array = arr;

	snprintf(buf, sizeof(buf), "USER.%.32s", DoNullInd(oper2->data.string));
	muf_event_add(destfr, buf, &temp1, 0);

        stk_array_active_list = &fr->array_active_list;

	CLEAR(&temp1);
        CLEAR(&data_copy);
    }

    CLEAR(oper1);
    CLEAR(oper2);
    CLEAR(oper3);
}
Ejemplo n.º 3
0
void
prim_event_send(PRIM_PROTOTYPE)
{
      struct frame *destfr;
      stk_array *arr;
      struct inst temp1;

	CHECKOP(3);
	oper3 = POP();				/* any: data to pass */
	oper2 = POP();				/* string: event id */
	oper1 = POP();				/* int: process id to send to */

	if (mlev < 3)
		abort_interp("Requires Mucker level 3 or better.");
	if (oper1->type != PROG_INTEGER)
		abort_interp("Expected an integer process id. (1)");
	if (oper2->type != PROG_STRING)
		abort_interp("Expected a string event id. (2)");

      destfr = (struct frame*) timequeue_pid_frame(oper1->data.number);
	if (destfr) {
		arr = new_array_dictionary();
		array_set_strkey(&arr, "data", oper3);
		array_set_strkey_intval(&arr, "caller_pid", fr->pid);
		array_set_strkey_refval(&arr, "caller_prog", program);

		temp1.type = PROG_ARRAY;
		temp1.data.array = arr; 

		sprintf(buf, "USER.%.32s", DoNullInd(oper2->data.string));
		muf_event_add(destfr, buf, oper3);
	}

      CLEAR(oper1);
	CLEAR(oper2);
	CLEAR(oper3);
}
Ejemplo n.º 4
0
struct inst *
interp_loop(dbref player, dbref program, struct frame *fr, int rettyp)
{
	register struct inst *pc;
	register int atop;
	register struct inst *arg;
	register struct inst *temp1;
	register struct inst *temp2;
	register struct stack_addr *sys;
	register int instr_count;
	register int stop;
	int i = 0, tmp, writeonly, mlev;
	static struct inst retval;
	char dbuf[BUFFER_LEN];
	int instno_debug_line = get_primitive("debug_line");


	fr->level = ++interp_depth;	/* increment interp level */

	/* load everything into local stuff */
	pc = fr->pc;
	atop = fr->argument.top;
	stop = fr->system.top;
	arg = fr->argument.st;
	sys = fr->system.st;
	writeonly = fr->writeonly;
	already_created = 0;
	fr->brkpt.isread = 0;

	if (!pc) {
		struct line *tmpline;

		tmpline = PROGRAM_FIRST(program);
		PROGRAM_SET_FIRST(program, (struct line *) read_program(program));
		do_compile(-1, OWNER(program), program, 0);
		free_prog_text(PROGRAM_FIRST(program));
		PROGRAM_SET_FIRST(program, tmpline);
		pc = fr->pc = PROGRAM_START(program);
		if (!pc) {
			abort_loop_hard("Program not compilable. Cannot run.", NULL, NULL);
		}
		PROGRAM_INC_PROF_USES(program);
		PROGRAM_INC_INSTANCES(program);
	}
	ts_useobject(program);
	err = 0;

	instr_count = 0;
	mlev = ProgMLevel(program);
	gettimeofday(&fr->proftime, NULL);

	/* This is the 'natural' way to exit a function */
	while (stop) {

		/* Abort program if player/thing running it is recycled */
		if ((player < 0) || (player >= db_top) || ((Typeof(player) != TYPE_PLAYER) && (Typeof(player) != TYPE_THING)))
		{
			reload(fr, atop, stop);
			prog_clean(fr);
			interp_depth--;
			calc_profile_timing(program,fr);

			return NULL;
		}

		fr->instcnt++;
		instr_count++;

		if ((fr->multitask == PREEMPT) || (FLAGS(program) & BUILDER)) {
			if (mlev == 4) {
				if (tp_max_ml4_preempt_count)
				{
					if (instr_count >= tp_max_ml4_preempt_count)
						abort_loop_hard("Maximum preempt instruction count exceeded", NULL, NULL);
				}
				else
					instr_count = 0;
			} else {
				/* else make sure that the program doesn't run too long */
				if (instr_count >= tp_max_instr_count)
					abort_loop_hard("Maximum preempt instruction count exceeded", NULL, NULL);
			}
		} else {
			/* if in FOREGROUND or BACKGROUND mode, '0 sleep' every so often. */
			if ((fr->instcnt > tp_instr_slice * 4) && (instr_count >= tp_instr_slice)) {
				fr->pc = pc;
				reload(fr, atop, stop);
				PLAYER_SET_BLOCK(player, (!fr->been_background));
				add_muf_delay_event(0, fr->descr, player, NOTHING, NOTHING, program, fr,
									(fr->multitask ==
									 FOREGROUND) ? "FOREGROUND" : "BACKGROUND");
				interp_depth--;
				calc_profile_timing(program,fr);
				return NULL;
			}
		}
		if (((FLAGS(program) & ZOMBIE) || fr->brkpt.force_debugging) &&
				!fr->been_background &&
				controls(player, program)
		) {
			fr->brkpt.debugging = 1;
		} else {
			fr->brkpt.debugging = 0;
		}
		if (FLAGS(program) & DARK ||
			(fr->brkpt.debugging && fr->brkpt.showstack && !fr->brkpt.bypass)) {

			if ((pc->type != PROG_PRIMITIVE) || (pc->data.number != instno_debug_line))
			{
				char *m = debug_inst(fr, 0, pc, fr->pid, arg, dbuf, sizeof(dbuf), atop, program);

				notify_nolisten(player, m, 1);
			}
		}
		if (fr->brkpt.debugging) {
			short breakflag = 0;
			if (stop == 1 &&
					!fr->brkpt.bypass &&
					pc->type == PROG_PRIMITIVE &&
					pc->data.number == IN_RET
			) {
				/* Program is about to EXIT */
				notify_nolisten(player, "Program is about to EXIT.", 1);
				breakflag = 1;
			} else if (fr->brkpt.count) {
				for (i = 0; i < fr->brkpt.count; i++) {
					if ((!fr->brkpt.pc[i] || pc == fr->brkpt.pc[i]) &&
						/* pc matches */
						(fr->brkpt.line[i] == -1 ||
						 (fr->brkpt.lastline != pc->line &&
						  fr->brkpt.line[i] == pc->line)) &&
						/* line matches */
						(fr->brkpt.level[i] == -1 ||
						 stop <= fr->brkpt.level[i]) &&
						/* level matches */
						(fr->brkpt.prog[i] == NOTHING ||
						 fr->brkpt.prog[i] == program) &&
						/* program matches */
						(fr->brkpt.linecount[i] == -2 ||
						 (fr->brkpt.lastline != pc->line &&
						  fr->brkpt.linecount[i]-- <= 0)) &&
						/* line count matches */
						(fr->brkpt.pccount[i] == -2 ||
						 (fr->brkpt.lastpc != pc &&
						  fr->brkpt.pccount[i]-- <= 0))
						/* pc count matches */
					) {
						if (fr->brkpt.bypass) {
							if (fr->brkpt.pccount[i] == -1)
								fr->brkpt.pccount[i] = 0;
							if (fr->brkpt.linecount[i] == -1)
								fr->brkpt.linecount[i] = 0;
						} else {
							breakflag = 1;
							break;
						}
					}
				}
			}
			if (breakflag) {
				char *m;
				char buf[BUFFER_LEN];

				if (fr->brkpt.dosyspop) {
					program = sys[--stop].progref;
					pc = sys[stop].offset;
				}
				add_muf_read_event(fr->descr, player, program, fr);
				reload(fr, atop, stop);
				fr->pc = pc;
				fr->brkpt.isread = 0;
				fr->brkpt.breaknum = i;
				fr->brkpt.lastlisted = 0;
				fr->brkpt.bypass = 0;
				fr->brkpt.dosyspop = 0;
				PLAYER_SET_CURR_PROG(player, program);
				PLAYER_SET_BLOCK(player, 0);
				interp_depth--;
				if (!fr->brkpt.showstack) {
					m = debug_inst(fr, 0, pc, fr->pid, arg, dbuf, sizeof(dbuf), atop, program);
					notify_nolisten(player, m, 1);
				}
				if (pc <= PROGRAM_CODE(program) || (pc - 1)->line != pc->line) {
					list_proglines(player, program, fr, pc->line, 0);
				} else {
					m = show_line_prims(fr, program, pc, 15, 1);
					snprintf(buf, sizeof(buf), "     %s", m);
					notify_nolisten(player, buf, 1);
				}
				calc_profile_timing(program,fr);
				return NULL;
			}
			fr->brkpt.lastline = pc->line;
			fr->brkpt.lastpc = pc;
			fr->brkpt.bypass = 0;
		}
		if (mlev < 3) {
			if (fr->instcnt > (tp_max_instr_count * ((mlev == 2) ? 4 : 1)))
				abort_loop_hard("Maximum total instruction count exceeded.", NULL, NULL);
		}
		switch (pc->type) {
		case PROG_INTEGER:
		case PROG_FLOAT:
		case PROG_ADD:
		case PROG_OBJECT:
		case PROG_VAR:
		case PROG_LVAR:
		case PROG_SVAR:
		case PROG_STRING:
		case PROG_LOCK:
		case PROG_MARK:
		case PROG_ARRAY:
			if (atop >= STACK_SIZE)
				abort_loop("Stack overflow.", NULL, NULL);
			copyinst(pc, arg + atop);
			pc++;
			atop++;
			break;

		case PROG_LVAR_AT:
		case PROG_LVAR_AT_CLEAR:
			{
				struct inst *tmp;
				struct localvars *lv;

				if (atop >= STACK_SIZE)
					abort_loop("Stack overflow.", NULL, NULL);

				if (pc->data.number >= MAX_VAR || pc->data.number < 0)
					abort_loop("Scoped variable number out of range.", NULL, NULL);

				lv = localvars_get(fr, program);
				tmp = &(lv->lvars[pc->data.number]);

				copyinst(tmp, arg + atop);

				if (pc->type == PROG_LVAR_AT_CLEAR) {
					CLEAR(tmp);
					tmp->type			= PROG_INTEGER;
					tmp->data.number	= 0;
				}

				pc++;
				atop++;
			}
			break;

		case PROG_LVAR_BANG:
			{
				struct inst *the_var;
				struct localvars *lv;
				if (atop < 1)
					abort_loop("Stack Underflow.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);

				if (pc->data.number >= MAX_VAR || pc->data.number < 0)
					abort_loop("Scoped variable number out of range.", NULL, NULL);

				lv = localvars_get(fr, program);
				the_var = &(lv->lvars[pc->data.number]);

				CLEAR(the_var);
				temp1 = arg + --atop;
				*the_var = *temp1;
				pc++;
			}
			break;

		case PROG_SVAR_AT:
		case PROG_SVAR_AT_CLEAR:
			{
				struct inst *tmp;

				if (atop >= STACK_SIZE)
					abort_loop("Stack overflow.", NULL, NULL);

				tmp = scopedvar_get(fr, 0, pc->data.number);
				if (!tmp)
					abort_loop("Scoped variable number out of range.", NULL, NULL);

				copyinst(tmp, arg + atop);

				if (pc->type == PROG_SVAR_AT_CLEAR) {
					CLEAR(tmp);

					tmp->type			= PROG_INTEGER;
					tmp->data.number	= 0;
				}

				pc++;
				atop++;
			}
			break;

		case PROG_SVAR_BANG:
			{
				struct inst *the_var;
				if (atop < 1)
					abort_loop("Stack Underflow.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);

				the_var = scopedvar_get(fr, 0, pc->data.number);
				if (!the_var)
					abort_loop("Scoped variable number out of range.", NULL, NULL);

				CLEAR(the_var);
				temp1 = arg + --atop;
				*the_var = *temp1;
				pc++;
			}
			break;

		case PROG_FUNCTION:
			{
				int i = pc->data.mufproc->args;
				if (atop < i)
					abort_loop("Stack Underflow.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < i)
					abort_loop("Stack protection fault.", NULL, NULL);
				if (fr->skip_declare)
					fr->skip_declare = 0;
				else
					scopedvar_addlevel(fr, pc, pc->data.mufproc->vars);
				while (i-->0)
				{
					struct inst *tmp;
					temp1 = arg + --atop;
					tmp = scopedvar_get(fr, 0, i);
					if (!tmp)
						abort_loop_hard("Internal error: Scoped variable number out of range in FUNCTION init.", temp1, NULL);
					CLEAR(tmp);
					copyinst(temp1, tmp);
					CLEAR(temp1);
				}
				pc++;
			}
			break;

		case PROG_IF:
			if (atop < 1)
				abort_loop("Stack Underflow.", NULL, NULL);
			if (fr->trys.top && atop - fr->trys.st->depth < 1)
				abort_loop("Stack protection fault.", NULL, NULL);
			temp1 = arg + --atop;
			if (false_inst(temp1))
				pc = pc->data.call;
			else
				pc++;
			CLEAR(temp1);
			break;

		case PROG_EXEC:
			if (stop >= STACK_SIZE)
				abort_loop("System Stack Overflow", NULL, NULL);
			sys[stop].progref = program;
			sys[stop++].offset = pc + 1;
			pc = pc->data.call;
			fr->skip_declare = 0;  /* Make sure we DON'T skip var decls */
			break;

		case PROG_JMP:
			/* Don't need to worry about skipping scoped var decls here. */
			/* JMP to a function header can only happen in IN_JMP */
			pc = pc->data.call;
			break;

		case PROG_TRY:
			if (atop < 1)
				abort_loop("Stack Underflow.", NULL, NULL);
			if (fr->trys.top && atop - fr->trys.st->depth < 1)
				abort_loop("Stack protection fault.", NULL, NULL);
			temp1 = arg + --atop;
			if (temp1->type != PROG_INTEGER || temp1->data.number < 0)
				abort_loop("Argument is not a positive integer.", temp1, NULL);
			if (fr->trys.top && atop - fr->trys.st->depth < temp1->data.number)
				abort_loop("Stack protection fault.", NULL, NULL);
			if (temp1->data.number > atop)
				abort_loop("Stack Underflow.", temp1, NULL);

			fr->trys.top++;
			fr->trys.st = push_try(fr->trys.st);
			fr->trys.st->depth = atop - temp1->data.number;
			fr->trys.st->call_level = stop;
			fr->trys.st->for_count = 0;
			fr->trys.st->addr = pc->data.call;

			pc++;
			CLEAR(temp1);
			break;

		case PROG_PRIMITIVE:
			/*
			 * All pc modifiers and stuff like that should stay here,
			 * everything else call with an independent dispatcher.
			 */
			switch (pc->data.number) {
			case IN_JMP:
				if (atop < 1)
					abort_loop("Stack underflow.  Missing address.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);
				temp1 = arg + --atop;
				if (temp1->type != PROG_ADD)
					abort_loop("Argument is not an address.", temp1, NULL);
				if (temp1->data.addr->progref >= db_top ||
					temp1->data.addr->progref < 0 ||
					(Typeof(temp1->data.addr->progref) != TYPE_PROGRAM))
							abort_loop_hard("Internal error.  Invalid address.", temp1, NULL);
				if (program != temp1->data.addr->progref) {
					abort_loop("Destination outside current program.", temp1, NULL);
				}
				if (temp1->data.addr->data->type == PROG_FUNCTION) {
					fr->skip_declare = 1;
				}
				pc = temp1->data.addr->data;
				CLEAR(temp1);
				break;

			case IN_EXECUTE:
				if (atop < 1)
					abort_loop("Stack Underflow. Missing address.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);
				temp1 = arg + --atop;
				if (temp1->type != PROG_ADD)
					abort_loop("Argument is not an address.", temp1, NULL);
				if (temp1->data.addr->progref >= db_top ||
					temp1->data.addr->progref < 0 ||
					(Typeof(temp1->data.addr->progref) != TYPE_PROGRAM))
							abort_loop_hard("Internal error.  Invalid address.", temp1, NULL);
				if (stop >= STACK_SIZE)
					abort_loop("System Stack Overflow", temp1, NULL);
				sys[stop].progref = program;
				sys[stop++].offset = pc + 1;
				if (program != temp1->data.addr->progref) {
					program = temp1->data.addr->progref;
					fr->caller.st[++fr->caller.top] = program;
					mlev = ProgMLevel(program);
					PROGRAM_INC_INSTANCES(program);
				}
				pc = temp1->data.addr->data;
				CLEAR(temp1);
				break;

			case IN_CALL:
				if (atop < 1)
					abort_loop("Stack Underflow. Missing dbref argument.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);
				temp1 = arg + --atop;
				temp2 = 0;
				if (temp1->type != PROG_OBJECT) {
					temp2 = temp1;
					if (atop < 1)
						abort_loop("Stack Underflow. Missing dbref of func.", temp1, NULL);
					if (fr->trys.top && atop - fr->trys.st->depth < 1)
						abort_loop("Stack protection fault.", NULL, NULL);
					temp1 = arg + --atop;
					if (temp2->type != PROG_STRING)
						abort_loop("Public Func. name string required. (2)", temp1, temp2);
					if (!temp2->data.string)
						abort_loop("Null string not allowed. (2)", temp1, temp2);
				}
				if (temp1->type != PROG_OBJECT)
					abort_loop("Dbref required. (1)", temp1, temp2);
				if (!valid_object(temp1)
					|| Typeof(temp1->data.objref) != TYPE_PROGRAM)
					abort_loop("Invalid object.", temp1, temp2);
				if (!(PROGRAM_CODE(temp1->data.objref))) {
					struct line *tmpline;

					tmpline = PROGRAM_FIRST(temp1->data.objref);
					PROGRAM_SET_FIRST(temp1->data.objref,
									  (struct line *) read_program(temp1->data.objref));
					do_compile(-1, OWNER(temp1->data.objref), temp1->data.objref, 0);
					free_prog_text(PROGRAM_FIRST(temp1->data.objref));
					PROGRAM_SET_FIRST(temp1->data.objref, tmpline);
					if (!(PROGRAM_CODE(temp1->data.objref)))
						abort_loop("Program not compilable.", temp1, temp2);
				}
				if (ProgMLevel(temp1->data.objref) == 0)
					abort_loop("Permission denied", temp1, temp2);
				if (mlev < 4 && OWNER(temp1->data.objref) != ProgUID
					&& !Linkable(temp1->data.objref))
							abort_loop("Permission denied", temp1, temp2);
				if (stop >= STACK_SIZE)
					abort_loop("System Stack Overflow", temp1, temp2);
				sys[stop].progref = program;
				sys[stop].offset = pc + 1;
				if (!temp2) {
					pc = PROGRAM_START(temp1->data.objref);
				} else {
					struct publics *pbs;
					int tmpint;

					pbs = PROGRAM_PUBS(temp1->data.objref);
					while (pbs) {
						tmpint = string_compare(temp2->data.string->data, pbs->subname);
						if (!tmpint)
							break;
						pbs = pbs->next;
					}
					if (!pbs)
						abort_loop("PUBLIC or WIZCALL function not found. (2)", temp2, temp2);
					if (mlev < pbs->mlev)
						abort_loop("Insufficient permissions to call WIZCALL function. (2)",
								   temp2, temp2);
					pc = pbs->addr.ptr;
				}
				stop++;
				if (temp1->data.objref != program) {
					calc_profile_timing(program,fr);
					gettimeofday(&fr->proftime, NULL);
					program = temp1->data.objref;
					fr->caller.st[++fr->caller.top] = program;
					PROGRAM_INC_INSTANCES(program);
					mlev = ProgMLevel(program);
				}
				PROGRAM_INC_PROF_USES(program);
				ts_useobject(program);
				CLEAR(temp1);
				if (temp2)
					CLEAR(temp2);
				break;

			case IN_RET:
				if (stop > 1 && program != sys[stop - 1].progref) {
					if (sys[stop - 1].progref >= db_top ||
						sys[stop - 1].progref < 0 ||
						(Typeof(sys[stop - 1].progref) != TYPE_PROGRAM))
								abort_loop_hard("Internal error.  Invalid address.", NULL, NULL);
					calc_profile_timing(program,fr);
					gettimeofday(&fr->proftime, NULL);
					PROGRAM_DEC_INSTANCES(program);
					program = sys[stop - 1].progref;
					mlev = ProgMLevel(program);
					fr->caller.top--;
				}
				scopedvar_poplevel(fr);
				pc = sys[--stop].offset;
				break;

			case IN_CATCH:
			case IN_CATCH_DETAILED:
				{
					int depth;

					if (!(fr->trys.top))
						abort_loop_hard("Internal error.  TRY stack underflow.", NULL, NULL);

					depth = fr->trys.st->depth;
					while (atop > depth) {
						temp1 = arg + --atop;
						CLEAR(temp1);
					}

					while (fr->trys.st->for_count-->0) {
						CLEAR(&fr->fors.st->cur);
						CLEAR(&fr->fors.st->end);
						fr->fors.top--;
						fr->fors.st = pop_for(fr->fors.st);
					}

					fr->trys.top--;
					fr->trys.st = pop_try(fr->trys.st);

					if (pc->data.number == IN_CATCH) {
						/* IN_CATCH */
						if (fr->errorstr) {
							arg[atop].type = PROG_STRING;
							arg[atop++].data.string = alloc_prog_string(fr->errorstr);
							free(fr->errorstr);
							fr->errorstr = NULL;
						} else {
							arg[atop].type = PROG_STRING;
							arg[atop++].data.string = NULL;
						}
						if (fr->errorinst) {
							free(fr->errorinst);
							fr->errorinst = NULL;
						}
					} else {
						/* IN_CATCH_DETAILED */
						stk_array *nu = new_array_dictionary();
						if (fr->errorstr) {
							array_set_strkey_strval(&nu, "error", fr->errorstr);
							free(fr->errorstr);
							fr->errorstr = NULL;
						}
						if (fr->errorinst) {
							array_set_strkey_strval(&nu, "instr", fr->errorinst);
							free(fr->errorinst);
							fr->errorinst = NULL;
						}
						array_set_strkey_intval(&nu, "line", fr->errorline);
						array_set_strkey_refval(&nu, "program", fr->errorprog);
						arg[atop].type = PROG_ARRAY;
						arg[atop++].data.array = nu;
					}
					reload(fr, atop, stop);
				}
				pc++;
				break;

			case IN_EVENT_WAITFOR:
				if (atop < 1)
					abort_loop("Stack Underflow. Missing eventID list array argument.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);
				temp1 = arg + --atop;
				if (temp1->type != PROG_ARRAY)
					abort_loop("EventID string list array expected.", temp1, NULL);
				if (temp1->data.array && temp1->data.array->type != ARRAY_PACKED)
					abort_loop("Argument must be a list array of eventid strings.", temp1, NULL);
				if (!array_is_homogenous(temp1->data.array, PROG_STRING))
					abort_loop("Argument must be a list array of eventid strings.", temp1, NULL);
				fr->pc = pc + 1;
				reload(fr, atop, stop);

				{
					int i, outcount;
					int count = array_count(temp1->data.array);
					char** events = (char**)malloc(count * sizeof(char**));
					for (outcount = i = 0; i < count; i++) {
						char *val = array_get_intkey_strval(temp1->data.array, i);
						if (val != NULL) {
							int found = 0;
							int j;
							for (j = 0; j < outcount; j++) {
								if (!strcmp(events[j], val)) {
									found = 1;
									break;
								}
							}
							if (!found) {
								events[outcount++] = val;
							}
						}
					}
					muf_event_register_specific(player, program, fr, outcount, events);
					free(events);
				}

				PLAYER_SET_BLOCK(player, (!fr->been_background));
				CLEAR(temp1);
				interp_depth--;
				calc_profile_timing(program,fr);
				return NULL;
				/* NOTREACHED */
				break;

			case IN_READ:
				if (writeonly)
					abort_loop("Program is write-only.", NULL, NULL);
				if (fr->multitask == BACKGROUND)
					abort_loop("BACKGROUND programs are write only.", NULL, NULL);
				reload(fr, atop, stop);
				fr->brkpt.isread = 1;
				fr->pc = pc + 1;
				PLAYER_SET_CURR_PROG(player, program);
				PLAYER_SET_BLOCK(player, 0);
				add_muf_read_event(fr->descr, player, program, fr);
				interp_depth--;
				calc_profile_timing(program,fr);
				return NULL;
				/* NOTREACHED */
				break;

			case IN_SLEEP:
				if (atop < 1)
					abort_loop("Stack Underflow.", NULL, NULL);
				if (fr->trys.top && atop - fr->trys.st->depth < 1)
					abort_loop("Stack protection fault.", NULL, NULL);
				temp1 = arg + --atop;
				if (temp1->type != PROG_INTEGER)
					abort_loop("Invalid argument type.", temp1, NULL);
				fr->pc = pc + 1;
				reload(fr, atop, stop);
				if (temp1->data.number < 0)
					abort_loop("Timetravel beyond scope of muf.", temp1, NULL);
				add_muf_delay_event(temp1->data.number, fr->descr, player,
									NOTHING, NOTHING, program, fr, "SLEEPING");
				PLAYER_SET_BLOCK(player, (!fr->been_background));
				interp_depth--;
				calc_profile_timing(program,fr);
				return NULL;
				/* NOTREACHED */
				break;

			default:
				nargs = 0;
				reload(fr, atop, stop);
				tmp = atop;
				prim_func[pc->data.number - 1] (player, program, mlev, pc, arg, &tmp, fr);
				atop = tmp;
				pc++;
				break;
			}					/* switch */
			break;
		case PROG_CLEARED:
			log_status("WARNING: attempt to execute instruction cleared by %s:%hd in program %d",
					   (char*)pc->data.addr, pc->line, program);
			pc = NULL;
			abort_loop_hard("Program internal error. Program erroneously freed from memory.",
							NULL, NULL);
		default:
			pc = NULL;
			abort_loop_hard("Program internal error. Unknown instruction type.",
							NULL, NULL);
		}						/* switch */
		if (err) {
			if (err != ERROR_DIE_NOW && fr->trys.top) {
				while (fr->trys.st->call_level < stop) {
					if (stop > 1 && program != sys[stop - 1].progref) {
						if (sys[stop - 1].progref >= db_top ||
							sys[stop - 1].progref < 0 ||
							(Typeof(sys[stop - 1].progref) != TYPE_PROGRAM))
									abort_loop_hard("Internal error.  Invalid address.", NULL, NULL);
						calc_profile_timing(program,fr);
						gettimeofday(&fr->proftime, NULL);
						PROGRAM_DEC_INSTANCES(program);
						program = sys[stop - 1].progref;
						mlev = ProgMLevel(program);
						fr->caller.top--;
					}
					scopedvar_poplevel(fr);
					stop--;
				}

				pc = fr->trys.st->addr;
				err = 0;
			} else {
				reload(fr, atop, stop);
				prog_clean(fr);
				PLAYER_SET_BLOCK(player, 0);
				interp_depth--;
				calc_profile_timing(program,fr);
				return NULL;
			}
		}
	}							/* while */

	PLAYER_SET_BLOCK(player, 0);
	if (atop) {
		struct inst *rv;

		if (rettyp) {
			copyinst(arg + atop - 1, &retval);
			rv = &retval;
		} else {
			if (!false_inst(arg + atop - 1)) {
				rv = (struct inst *) 1;
			} else {
				rv = NULL;
			}
		}
		reload(fr, atop, stop);
		prog_clean(fr);
		interp_depth--;
		calc_profile_timing(program,fr);
		return rv;
	}
	reload(fr, atop, stop);
	prog_clean(fr);
	interp_depth--;
	calc_profile_timing(program,fr);
	return NULL;
}
Ejemplo n.º 5
0
void
prim_array_regmatchval(PRIM_PROTOTYPE)
{
    struct inst *in;
    stk_array *arr;
    stk_array *nw;
    muf_re* re;
    char* text;
    int flags;
    int matchcnt = 0;
    const char* errstr = NULL;

    CHECKOP(3);
    oper3 = POP();              /* int  pcreflags */
    oper2 = POP();              /* str  pattern */
    oper1 = POP();              /* arr  Array */
    if (oper1->type != PROG_ARRAY)
        abort_interp("Argument not an array. (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Argument not a string pattern. (2)");
    if (oper3->type != PROG_INTEGER)
        abort_interp("Non-integer argument (3)");

    flags = PCRE_NO_AUTO_CAPTURE;

    if (oper3->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper3->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    re = regmatch_re_get(oper2->data.string, flags, &errstr);
    if (errstr)
        abort_interp(errstr)

    nw = new_array_dictionary();
    arr = oper1->data.array;

    if (re && !re->extra && array_count(arr) > 2) {
        /* This pattern is getting used 3 or more times, let's study it. A null
         * return is okay, that just means there's nothing to optimize. */
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    if (array_first(arr, &temp1)) {
        do {
            in = array_getitem(arr, &temp1);
            if (in->type == PROG_STRING) {
                text    = (char *)DoNullInd(in->data.string);
                if ((matchcnt = regmatch_exec(re, text)) < 0) {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    array_setitem(&nw, &temp1, in);
                }
            } else if (in->type == PROG_OBJECT) {
                text    = (char *) NAME(in->data.objref);
                if ((matchcnt = regmatch_exec(re, text)) < 0) {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    array_setitem(&nw, &temp1, in);
                }
            }
        } while (array_next(arr, &temp1));
    }


    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushArrayRaw(nw);
}
Ejemplo n.º 6
0
void
prim_array_regsub(PRIM_PROTOTYPE)
{
    struct inst *in;
    stk_array *arr;
    stk_array *nw;
    int         matches[MATCH_ARR_SIZE];
    int         flags       = 0;
    char*       write_ptr   = buf;
    int         write_left  = BUFFER_LEN - 1;
    muf_re*     re;
    char*       text;
    char*       textstart;
    const char* errstr;
    int         matchcnt, len;

    CHECKOP(4);

    oper4 = POP(); /* int:Flags */
    oper3 = POP(); /* str:Replace */
    oper2 = POP(); /* str:Pattern */
    oper1 = POP(); /* str:Text */

    if (oper1->type != PROG_ARRAY)
        abort_interp("Argument not an array of strings. (1)");
    if (!array_is_homogenous(oper1->data.array, PROG_STRING))
        abort_interp("Argument not an array of strings. (1)");
    if (oper2->type != PROG_STRING)
        abort_interp("Non-string argument (2)");
    if (oper3->type != PROG_STRING)
        abort_interp("Non-string argument (3)");
    if (oper4->type != PROG_INTEGER)
        abort_interp("Non-integer argument (4)");
    if (!oper2->data.string)
        abort_interp("Empty string argument (2)");

    if (oper4->data.number & MUF_RE_ICASE)
        flags |= PCRE_CASELESS;
    if (oper4->data.number & MUF_RE_EXTENDED)
        flags |= PCRE_EXTENDED;

    if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL)
        abort_interp(errstr);



    nw = new_array_dictionary();
    arr = oper1->data.array;

    if (!re->extra
        && ((oper4->data.number & MUF_RE_ALL ) || array_count(arr) > 2)) {
        /* Study the pattern if the user requested recursive substitution, or
         * if the input array contains at least three items. */
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    if (array_first(arr, &temp1)) {
        do {
            write_ptr = buf;
            write_left = BUFFER_LEN - 1;

            in = array_getitem(arr, &temp1);
            textstart = text = (char *)DoNullInd(in->data.string);
            len = strlen(textstart);

            while((*text != '\0') && (write_left > 0))
            {
                if ((matchcnt = pcre_exec(re->re, re->extra, textstart, len,
                                          text-textstart, 0, matches,
                                          MATCH_ARR_SIZE)) < 0)
                {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                    {
                        abort_interp(muf_re_error(matchcnt));
                    }

                    while((write_left > 0) && (*text != '\0'))
                    {
                        *write_ptr++ = *text++;
                        write_left--;
                    }

                    break;
                }
                else
                {
                    int         allstart    = matches[0];
                    int         allend      = matches[1];
                    int         substart    = -1;
                    int         subend      = -1;
                    char*       read_ptr    = (char *)DoNullInd(oper3->data.string);
                    int         count;

                    for(count = allstart-(text-textstart);
                                (write_left > 0) && (*text != '\0') && (count > 0);
                                count--)
                    {
                        *write_ptr++ = *text++;
                        write_left--;
                    }

                    while((write_left > 0) && (*read_ptr != '\0'))
                    {
                        if (*read_ptr == '\\')
                        {
                            if (!isdigit(*(++read_ptr)))
                            {
                                *write_ptr++ = *read_ptr++;
                                write_left--;
                            }
                            else
                            {
                                int idx = (*read_ptr++) - '0';

                                if ((idx < 0) || (idx >= matchcnt))
                                {
                                    abort_interp("Invalid \\subexp in substitution string. (3)");
                                }

                                substart = matches[idx*2];
                                subend = matches[idx*2+1];

                                if ((substart >= 0) && (subend >= 0) && (substart < len))
                                {
                                    char* ptr = &textstart[substart];

                                    count = subend - substart;

                                    if (count > write_left)
                                    {
                                        abort_interp("Operation would result in overflow");
                                    }

                                    for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--)
                                    {
                                        *write_ptr++ = *ptr++;
                                        write_left--;
                                    }
                                }
                            }
                        }
                        else
                        {
                            *write_ptr++ = *read_ptr++;
                            write_left--;
                        }
                    }

                    for(count = allend - allstart; (*text != '\0') && (count > 0); count--)
                        text++;

                    if (allstart == allend && *text) {
                        *write_ptr++ = *text++;
                        write_left--;
                    }
                }

                if ((oper4->data.number & MUF_RE_ALL) == 0)
                {
                    while((write_left > 0) && (*text != '\0'))
                    {
                        *write_ptr++ = *text++;
                        write_left--;
                    }

                    break;
                }
            }

            if (*text != '\0')
                abort_interp("Operation would result in overflow");

            *write_ptr = '\0';

            temp2.type = PROG_STRING;
            temp2.data.string = alloc_prog_string(buf);

            array_setitem(&nw, &temp1, &temp2);
            CLEAR(&temp2);
        } while (array_next(arr, &temp1));
    }

    CLEAR(oper4);
    CLEAR(oper3);
    CLEAR(oper2);
    CLEAR(oper1);

    PushArrayRaw(nw);
}
Ejemplo n.º 7
0
stk_array *
array_getrange(stk_array *arr, array_iter *start, array_iter *end)
{
    stk_array *new2;
    array_data *tmp;
    int sidx, eidx;

    if (!arr) {
        return NULL;
    }
    switch (arr->type) {
        case ARRAY_PACKED:{
            array_iter idx;
            array_iter didx;

            if (start->type != PROG_INTEGER) {
                return NULL;
            }
            if (end->type != PROG_INTEGER) {
                return NULL;
            }
            sidx = start->data.number;
            eidx = end->data.number;
            if (sidx < 0) {
                sidx = 0;
            } else if (sidx > arr->items) {
                return NULL;
            }
            if (eidx >= arr->items) {
                eidx = arr->items - 1;
            } else if (eidx < 0) {
                return NULL;
            }
            if (sidx > eidx) {
                return NULL;
            }
            idx.type = PROG_INTEGER;
            idx.data.number = sidx;
            didx.type = PROG_INTEGER;
            didx.data.number = 0;
            new2 = new_array_packed(eidx - sidx + 1);
            while (idx.data.number <= eidx) {
                tmp = array_getitem(arr, &idx);
                if (!tmp)
                    break;
                array_setitem(&new2, &didx, tmp);
                didx.data.number++;
                idx.data.number++;
            }
            return new2;
            break;
        }

        case ARRAY_DICTIONARY:{
            stk_array *new2;
            array_tree *s;
            array_tree *e;

            new2 = new_array_dictionary();
            s = array_tree_find(arr->data.dict, start);
            if (!s) {
                s = array_tree_next_node(arr->data.dict, start);
                if (!s) {
                    return new2;
                }
            }
            e = array_tree_find(arr->data.dict, end);
            if (!e) {
                e = array_tree_prev_node(arr->data.dict, end);
                if (!e) {
                    return new2;
                }
            }
            if (array_tree_compare(&s->key, &e->key, 0, 0, 0) > 0) {
                return new2;
            }
            while (s) {
                array_setitem(&new2, &s->key, &s->data);
                if (s == e)
                    break;
                s = array_tree_next_node(arr->data.dict, &s->key);
            }
            return new2;
            break;
        }

        default:
            break;
    }
    return NULL;
}
Ejemplo n.º 8
0
stk_array *
tune_parms_array(const char *pattern, int mlev)
{
    struct tune_str_entry *tstr = tune_str_list;
    struct tune_time_entry *ttim = tune_time_list;
    struct tune_val_entry *tval = tune_val_list;
    struct tune_ref_entry *tref = tune_ref_list;
    struct tune_bool_entry *tbool = tune_bool_list;
    stk_array *nu = new_array_packed(0);
    struct inst temp1;
    char pat[BUFFER_LEN];
    char buf[BUFFER_LEN];
    int i = 0;

    strcpy(pat, pattern);
    while (tbool->name) {
        if (tbool->readmlev <= mlev) {
            strcpy(buf, tbool->name);
            if (!*pattern || equalstr(pat, buf)) {
                stk_array *item = new_array_dictionary();

                array_set_strkey_strval(&item, "type", "boolean");
                array_set_strkey_strval(&item, "group", tbool->group);
                array_set_strkey_strval(&item, "name", tbool->name);
                array_set_strkey_intval(&item, "value", *tbool->boolv ? 1 : 0);
                array_set_strkey_intval(&item, "readmlev", tbool->readmlev);
                array_set_strkey_intval(&item, "writemlev", tbool->writemlev);
                temp1.type = PROG_ARRAY;
                temp1.data.array = item;
                array_set_intkey(&nu, i++, &temp1);
                CLEAR(&temp1);
            }
        }
        tbool++;
    }

    while (ttim->name) {
        if (ttim->readmlev <= mlev) {
            strcpy(buf, ttim->name);
            if (!*pattern || equalstr(pat, buf)) {
                stk_array *item = new_array_dictionary();

                array_set_strkey_strval(&item, "type", "timespan");
                array_set_strkey_strval(&item, "group", ttim->group);
                array_set_strkey_strval(&item, "name", ttim->name);
                array_set_strkey_intval(&item, "value", *ttim->tim);
                array_set_strkey_intval(&item, "readmlev", ttim->readmlev);
                array_set_strkey_intval(&item, "writemlev", ttim->writemlev);
                temp1.type = PROG_ARRAY;
                temp1.data.array = item;
                array_set_intkey(&nu, i++, &temp1);
                CLEAR(&temp1);
            }
        }
        ttim++;
    }

    while (tval->name) {
        if (tval->readmlev <= mlev) {
            strcpy(buf, tval->name);
            if (!*pattern || equalstr(pat, buf)) {
                stk_array *item = new_array_dictionary();

                array_set_strkey_strval(&item, "type", "integer");
                array_set_strkey_strval(&item, "group", tval->group);
                array_set_strkey_strval(&item, "name", tval->name);
                array_set_strkey_intval(&item, "value", *tval->val);
                array_set_strkey_intval(&item, "readmlev", tval->readmlev);
                array_set_strkey_intval(&item, "writemlev", tval->writemlev);
                temp1.type = PROG_ARRAY;
                temp1.data.array = item;
                array_set_intkey(&nu, i++, &temp1);
                CLEAR(&temp1);
            }
        }
        tval++;
    }

    while (tref->name) {
        if (tref->readmlev <= mlev) {
            strcpy(buf, tref->name);
            if (!*pattern || equalstr(pat, buf)) {
                stk_array *item = new_array_dictionary();

                array_set_strkey_strval(&item, "type", "dbref");
                array_set_strkey_strval(&item, "group", tref->group);
                array_set_strkey_strval(&item, "name", tref->name);
                array_set_strkey_refval(&item, "value", *tref->ref);
                array_set_strkey_intval(&item, "readmlev", tref->readmlev);
                array_set_strkey_intval(&item, "writemlev", tref->writemlev);
                switch (tref->typ) {
                case NOTYPE:
                    array_set_strkey_strval(&item, "objtype", "any");
                    break;
                case TYPE_PLAYER:
                    array_set_strkey_strval(&item, "objtype", "player");
                    break;
                case TYPE_THING:
                    array_set_strkey_strval(&item, "objtype", "thing");
                    break;
                case TYPE_ROOM:
                    array_set_strkey_strval(&item, "objtype", "room");
                    break;
                case TYPE_EXIT:
                    array_set_strkey_strval(&item, "objtype", "exit");
                    break;
                case TYPE_PROGRAM:
                    array_set_strkey_strval(&item, "objtype", "program");
                    break;
                case TYPE_GARBAGE:
                    array_set_strkey_strval(&item, "objtype", "garbage");
                    break;
                default:
                    array_set_strkey_strval(&item, "objtype", "unknown");
                    break;
                }
                temp1.type = PROG_ARRAY;
                temp1.data.array = item;
                array_set_intkey(&nu, i++, &temp1);
                CLEAR(&temp1);
            }
        }
        tref++;
    }

    while (tstr->name) {
        if (tstr->readmlev <= mlev) {
            strcpy(buf, tstr->name);
            if (!*pattern || equalstr(pat, buf)) {
                stk_array *item = new_array_dictionary();

                array_set_strkey_strval(&item, "type", "string");
                array_set_strkey_strval(&item, "group", tstr->group);
                array_set_strkey_strval(&item, "name", tstr->name);
                array_set_strkey_strval(&item, "value", *tstr->str);
                array_set_strkey_intval(&item, "readmlev", tstr->readmlev);
                array_set_strkey_intval(&item, "writemlev", tstr->writemlev);
                temp1.type = PROG_ARRAY;
                temp1.data.array = item;
                array_set_intkey(&nu, i++, &temp1);
                CLEAR(&temp1);
            }
        }
        tstr++;
    }
    return nu;
}
Ejemplo n.º 9
0
stk_array *
get_pidinfo(int pid)
{
	struct inst temp1, temp2;
	stk_array  *nw;
	time_t      rtime = time(NULL);
	time_t      etime = 0;
	double      pcnt  = 0.0;

	timequeue ptr = tqhead;
	nw = new_array_dictionary();
	while (ptr) {
		if (ptr->eventnum == pid) {
			if (ptr->typ != TQ_MUF_TYP || ptr->subtyp != TQ_MUF_TIMER) {
				break;
			}
		}
		ptr = ptr->next;
	}
	if (ptr && (ptr->eventnum == pid) &&
			(ptr->typ != TQ_MUF_TYP || ptr->subtyp != TQ_MUF_TIMER)) {
		if (ptr->fr) {
			etime = rtime - ptr->fr->started;
			if (etime > 0) {
				pcnt = ptr->fr->totaltime.tv_sec;
				pcnt += ptr->fr->totaltime.tv_usec / 1000000;
				pcnt = pcnt * 100 / etime;
				if (pcnt > 100.0) {
					pcnt = 100.0;
				}
			} else {
				pcnt = 0.0;
			}
		}
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("PID");
		temp2.type = PROG_INTEGER;
		temp2.data.number = ptr->eventnum;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("CALLED_PROG");
		temp2.type = PROG_OBJECT;
		temp2.data.objref = ptr->called_prog;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("TRIG");
		temp2.type = PROG_OBJECT;
		temp2.data.objref = ptr->trig;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("PLAYER");
		temp2.type = PROG_OBJECT;
		temp2.data.objref = ptr->uid;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("CALLED_DATA");
		temp2.type = PROG_STRING;
		temp2.data.string = alloc_prog_string(ptr->called_data);
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("INSTCNT");
		temp2.type = PROG_INTEGER;
		temp2.data.number = ptr->fr ? ptr->fr->instcnt : 0;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("DESCR");
		temp2.type = PROG_INTEGER;
		temp2.data.number = ptr->descr;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("CPU");
		temp2.type = PROG_FLOAT;
		temp2.data.fnumber = pcnt;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("NEXTRUN");
		temp2.type = PROG_INTEGER;
		temp2.data.number = (int) ptr->when;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("STARTED");
		temp2.type = PROG_INTEGER;
		temp2.data.number = (int) (ptr->fr ? ptr->fr->started : 0);
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("TYPE");
		temp2.type = PROG_STRING;
		temp2.data.string = 	(ptr->typ == TQ_MUF_TYP) ? alloc_prog_string("MUF") :
						(ptr->typ == TQ_MPI_TYP) ? alloc_prog_string("MPI") : alloc_prog_string("UNK") ;
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
		temp1.type = PROG_STRING;
		temp1.data.string = alloc_prog_string("SUBTYPE");
		temp2.type = PROG_STRING;
		if (ptr->typ == TQ_MUF_TYP) {
			temp2.data.string = (ptr->subtyp == TQ_MUF_READ) ? alloc_prog_string("READ") :
							(ptr->subtyp == TQ_MUF_TREAD) ? alloc_prog_string("TREAD") :
							(ptr->subtyp == TQ_MUF_QUEUE) ? alloc_prog_string("QUEUE") :
							(ptr->subtyp == TQ_MUF_LISTEN) ? alloc_prog_string("LISTEN") :
							(ptr->subtyp == TQ_MUF_TIMER) ? alloc_prog_string("TIMER") :
							(ptr->subtyp == TQ_MUF_DELAY) ? alloc_prog_string("DELAY") :
							alloc_prog_string("");
		} else if (ptr->typ == TQ_MPI_TYP) {
			int subtyp = (ptr->subtyp & TQ_MPI_SUBMASK);
			temp2.data.string = (subtyp == TQ_MPI_QUEUE) ? alloc_prog_string("QUEUE") :
							(subtyp == TQ_MPI_DELAY) ? alloc_prog_string("DELAY") :
							alloc_prog_string("");
		} else {
			temp2.data.string = alloc_prog_string("");
		}
		array_setitem(&nw, &temp1, &temp2);
		CLEAR(&temp1);
		CLEAR(&temp2);
	} else {
		nw = get_mufevent_pidinfo(nw, pid);
	}
	return nw;
}