Beispiel #1
0
Object* PushDict(VM* vm)
{
	Object* obj = NewObject(vm, OBJ_DICT);
	InitDict(&obj->dict);
	PushObject(vm, obj);
	return obj;
}
Beispiel #2
0
void
prim_prog(PRIM_PROTOTYPE)
{
    CHECKOP(0);
    ref = (dbref) program;
    CHECKOFLOW(1);
    PushObject(ref);
}
Beispiel #3
0
void PushString(VM* vm, const char* string)
{
	Object* obj = NewObject(vm, OBJ_STRING);
	
	obj->string.raw = estrdup(string);
	
	PushObject(vm, obj);
}
Beispiel #4
0
void
prim_caller(PRIM_PROTOTYPE)
{
    CHECKOP(0);
    ref = (dbref) fr->caller.st[fr->caller.top - 1];
    CHECKOFLOW(1);
    PushObject(ref);
}
Beispiel #5
0
void
prim_trig(PRIM_PROTOTYPE)
{
    CHECKOP(0);
    ref = (dbref) fr->trig;
    CHECKOFLOW(1);
    PushObject(ref);
}
Beispiel #6
0
void
prim_dbtop(PRIM_PROTOTYPE)
{
    CHECKOP(0);
    ref = (dbref) db_top;
    CHECKOFLOW(1);
    PushObject(ref);
}
Beispiel #7
0
void PushNative(VM* vm, void* value, void (*onFree)(void*), void (*onMark)())
{
	Object* obj = NewObject(vm, OBJ_NATIVE);
	obj->native.value = value;
	obj->native.onFree = onFree;
	obj->native.onMark = onMark;
	PushObject(vm, obj);
}
Beispiel #8
0
static JSBool
OpenObject(JSContext *cx, JSONParser *jp)
{
    JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL);
    if (!obj)
        return JS_FALSE;
 
    return PushObject(cx, jp, obj);
}
Beispiel #9
0
static JSBool
OpenArray(JSContext *cx, JSONParser *jp)
{
    // Add an array to an existing array or object
    JSObject *arr = JS_NewArrayObject(cx, 0, NULL);
    if (!arr)
        return JS_FALSE;
 
    return PushObject(cx, jp, arr);
}
Beispiel #10
0
Object* PushFunc(VM* vm, int id, Word hasEllipsis, Word isExtern, Word numArgs)
{
	Object* obj = NewObject(vm, OBJ_FUNC);
	
	obj->func.index = id;
	obj->func.isExtern = isExtern;
	obj->func.hasEllipsis = hasEllipsis;
	obj->func.numArgs = numArgs;
	
	PushObject(vm, obj);
	
	return obj;
}
Beispiel #11
0
void
prim_forcedby(PRIM_PROTOTYPE)
{
    CHECKOFLOW(1);
    if (mlev < 4)
	abort_interp("Wizbit only primitive.");

    if (forcelist) {
	ref = forcelist->data;
    } else {
	ref = NOTHING;
    }
    PushObject(ref);
}
Beispiel #12
0
void Std_Fopen(VM* vm)
{
	const char* filename = PopString(vm);
	const char* mode = PopString(vm);
	
	FILE* file = fopen(filename, mode);
	if(!file)
	{	
		PushObject(vm, &NullObject);
		return;
	}
	
	PushNative(vm, file, Std_Fclose, NULL);
}
Beispiel #13
0
void 
prim_online(PRIM_PROTOTYPE)
{
    CHECKOP(0);
    if (mlev < (tp_compatible_muf ? LM3 : LM2))
	abort_interp(tp_compatible_muf ? "M3 prim" : "M2 prim");
    result = pcount();
    CHECKOFLOW(result + 1);
    while (result) {
	ref = pdbref(result--);
	PushObject(ref);
    }
    result = pcount();
    PushInt(result);
}
Beispiel #14
0
Object* PushArray(VM* vm, int length)
{
	Object* obj = NewObject(vm, OBJ_ARRAY);
	
	if(length == 0)
		obj->array.capacity = 2;
	else
		obj->array.capacity = length;
	
	obj->array.members = emalloc(sizeof(Object*) * obj->array.capacity);
	obj->array.length = length;
	
	memset(obj->array.members, (int)(&NullObject), sizeof(Object*) * obj->array.capacity); 
	
	PushObject(vm, obj);
	return obj;
}
Beispiel #15
0
void 
prim_condbref(PRIM_PROTOTYPE)
{
    /* int -- dbref */
    CHECKOP(1);
    oper1 = POP();
    if (mlev < (tp_compatible_muf ? LM3 : LM2))
	abort_interp(tp_compatible_muf ? "M3 prim" : "M2 prim");
    if (oper1->type != PROG_INTEGER)
	abort_interp("Argument not an integer (1)");
    result = oper1->data.number;
    if ((result < 1) || (result > pcount()))
	abort_interp("Invalid connection number (1)");
    result = pdbref(result);
    CHECKOFLOW(1);
    CLEAR(oper1);
    PushObject(result);
}
    int TextureViewParser::GetDefaultView( lua_State *L )
    {
        INIT_LUA_STACK_TRACKING( L );

        // Texture should be the first argument
        auto *pTexture = *GetUserData<ITexture**>( L, 1, m_TextureLibMetatableName.c_str() );
        
        // View type should be the second argument
        TEXTURE_VIEW_TYPE ViewType;
        m_ViewTypeParser.SetValue( L, 2, &ViewType );

        auto pView = pTexture->GetDefaultView( ViewType );
        if( !pView )
            SCRIPT_PARSING_ERROR( L, "Failed to get default texture view of type ", GetTexViewTypeLiteralName( ViewType ) );

        // Push existing object
        PushObject(L, pView);

        CHECK_LUA_STACK_HEIGHT( +1 );

        // Returning one value to Lua
        return 1;
    }
Beispiel #17
0
void
prim_regfindnext(PRIM_PROTOTYPE)
{
    struct flgchkdat check;
    dbref who, item, ref, i;
    const char *name;
    muf_re* re;
    char* text;
    int flags;
    int matchcnt = 0;
    const char* errstr = NULL;

    CHECKOP(5);
    oper5 = POP();              /* int:pcreflags */
    oper4 = POP();              /* str:objflags */
    oper3 = POP();              /* str:namepattern */
    oper2 = POP();              /* ref:owner */
    oper1 = POP();              /* ref:currobj */

    if (oper5->type != PROG_INTEGER)
        abort_interp("Non-integer argument (5)");
    if (oper4->type != PROG_STRING)
        abort_interp("Expected string argument. (4)");
    if (oper3->type != PROG_STRING)
        abort_interp("Expected string argument. (3)");
    if (oper2->type != PROG_OBJECT)
        abort_interp("Expected dbref argument. (2)");
    if (oper2->data.objref < NOTHING || oper2->data.objref >= db_top)
        abort_interp("Bad object. (2)");
    if (oper1->type != PROG_OBJECT)
        abort_interp("Expected dbref argument. (1)");
    if (oper1->data.objref < NOTHING || oper1->data.objref >= db_top)
        abort_interp("Bad object. (1)");
    if (oper2->data.objref != NOTHING &&
        Typeof(oper2->data.objref) == TYPE_GARBAGE)
        abort_interp("Owner dbref is garbage. (2)");

    item = oper1->data.objref;
    who = oper2->data.objref;
    name = DoNullInd(oper3->data.string);

    if (mlev < 2)
        abort_interp("Permission denied.  Requires at least Mucker Level 2.");

    if (mlev < 3) {
        if (who == NOTHING) {
            abort_interp
                ("Permission denied.  Owner inspecific searches require Mucker Level 3.");
        } else if (who != ProgUID) {
            abort_interp
                ("Permission denied.  Searching for other people's stuff requires Mucker Level 3.");
        }
    }

    flags = PCRE_NO_AUTO_CAPTURE;

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

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

    /* We're scanning a chunk of the DB, so studying should pay off.
     * A null return is fine, it just means we can't optimize further. */
    if (re && !re->extra) {
        re->extra = pcre_study(re->re, 0, &errstr);
        if (errstr)
            abort_interp(errstr);
    }

    if (item == NOTHING) {
        item = 0;
    } else {
        item++;
    }

    ref = NOTHING;
    init_checkflags(PSafe, DoNullInd(oper4->data.string), &check);
    for (i = item; i < db_top; i++) {
        if ((who == NOTHING || OWNER(i) == who) &&
            checkflags(i, check) && NAME(i)) {
            if (!*name) {
                ref = i;
                break;
            } else {
                text = (char *) NAME(i);
                if ((matchcnt = regmatch_exec(re, text)) < 0) {
                    if (matchcnt != PCRE_ERROR_NOMATCH)
                        abort_interp(muf_re_error(matchcnt));
                } else {
                    ref = i;
                    break;
                }
            }
        }
    }


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

    PushObject(ref);
}
Beispiel #18
0
void
prim_envprop(PRIM_PROTOTYPE)
{
	double fresult;

	CHECKOP(2);
	oper1 = POP();
	oper2 = POP();
	if (oper1->type != PROG_STRING)
		abort_interp("Non-string argument (2)");
	if (!oper1->data.string)
		abort_interp("Empty string argument (2)");
	if (!valid_object(oper2))
		abort_interp("Non-object argument (1)");
	CHECKREMOTE(oper2->data.objref);
	{
		char tname[BUFFER_LEN];
		dbref what;
		PropPtr ptr;
		int len = oper1->data.string->length;

		strcpyn(tname, sizeof(tname), oper1->data.string->data);
		while (len-- > 0 && tname[len] == PROPDIR_DELIMITER) {
			tname[len] = '\0';
		}

		what = oper2->data.objref;
		ptr = envprop(&what, tname, 0);
		if (what != NOTHING) {
			if (!prop_read_perms(ProgUID, what, oper1->data.string->data, mlev))
				abort_interp("Permission denied.");
		}
		CLEAR(oper1);
		CLEAR(oper2);
		PushObject(what);

		if (!ptr) {
			result = 0;
			PushInt(result);
		} else {
#ifdef DISKBASE
			propfetch(what, ptr);
#endif
			switch (PropType(ptr)) {
			case PROP_STRTYP:
				PushString(PropDataStr(ptr));
				break;
			case PROP_INTTYP:
				result = PropDataVal(ptr);
				PushInt(result);
				break;
			case PROP_FLTTYP:
				fresult = PropDataFVal(ptr);
				PushFloat(fresult);
				break;
			case PROP_REFTYP:
				ref = PropDataRef(ptr);
				PushObject(ref);
				break;
			case PROP_LOKTYP:
				if (PropFlags(ptr) & PROP_ISUNLOADED) {
					PushLock(TRUE_BOOLEXP);
				} else {
					PushLock(PropDataLok(ptr));
				}
				break;
			default:
				result = 0;
				PushInt(result);
				break;
			}
		}
	}
}
Beispiel #19
0
void
prim_envpropstr(PRIM_PROTOTYPE)
{
	CHECKOP(2);
	oper1 = POP();
	oper2 = POP();
	if (oper1->type != PROG_STRING)
		abort_interp("Non-string argument (2)");
	if (!oper1->data.string)
		abort_interp("Empty string argument (2)");
	if (!valid_object(oper2))
		abort_interp("Non-object argument (1)");
	CHECKREMOTE(oper2->data.objref);
	{
		char tname[BUFFER_LEN];
		dbref what;
		PropPtr ptr;
		const char *temp;
		int len = oper1->data.string->length;

		strcpyn(tname, sizeof(tname), oper1->data.string->data);
		while (len-- > 0 && tname[len] == PROPDIR_DELIMITER) {
			tname[len] = '\0';
		}

		what = oper2->data.objref;
		ptr = envprop(&what, tname, 0);
		if (!ptr) {
			temp = "";
		} else {
#ifdef DISKBASE
			propfetch(what, ptr);
#endif
			switch (PropType(ptr)) {
			case PROP_STRTYP:
				temp = PropDataStr(ptr);
				break;
				/*
				 *case PROP_INTTYP:
				 *    snprintf(buf, sizeof(buf), "%d", PropDataVal(ptr));
				 *    temp = buf;
				 *    break;
				 */
			case PROP_REFTYP:
				snprintf(buf, sizeof(buf), "#%d", PropDataRef(ptr));
				temp = buf;
				break;
			case PROP_LOKTYP:
				if (PropFlags(ptr) & PROP_ISUNLOADED) {
					temp = "*UNLOCKED*";
				} else {
					temp = unparse_boolexp(ProgUID, PropDataLok(ptr), 1);
				}
				break;
			default:
				temp = "";
				break;
			}
		}

#ifdef LOG_PROPS
		log2file("props.log", "#%d (%d) ENVPROPSTR: o=%d so=%d n=\"%s\" s=\"%s\"",
				 program, pc->line, what, oper2->data.objref, tname, temp);
#endif

		if (what != NOTHING) {
			if (!prop_read_perms(ProgUID, what, oper1->data.string->data, mlev))
				abort_interp("Permission denied.");
			/* if (Typeof(what) != TYPE_PLAYER)
			 *     ts_lastuseobject(what); */
		}
		CLEAR(oper1);
		CLEAR(oper2);
		PushObject(what);
		PushString(temp);
	}
}
Beispiel #20
0
void ExecuteCycle(VM* vm)
{
	if(vm->pc == -1) return;
	if(vm->debug)
		printf("pc %i: ", vm->pc);
	
	if(vm->stackSize < vm->numGlobals)
		printf("Global(s) were removed from the stack!\n");
	
	switch(vm->program[vm->pc])
	{
		case OP_PUSH_NULL:
		{
			if(vm->debug)
				printf("push_null\n");
			++vm->pc;
			PushObject(vm, &NullObject);
		} break;
		
		case OP_PUSH_NUMBER:
		{
			if(vm->debug)
				printf("push_number\n");
			++vm->pc;
			int index = ReadInteger(vm);
			PushNumber(vm, vm->numberConstants[index]);
		} break;
		
		case OP_PUSH_STRING:
		{
			if(vm->debug)
				printf("push_string\n");
			++vm->pc;
			int index = ReadInteger(vm);
			PushString(vm, vm->stringConstants[index]);
		} break;
		
		case OP_PUSH_FUNC:
		{
			if(vm->debug)
				printf("push_func\n");
			Word hasEllipsis = vm->program[++vm->pc];
			Word isExtern = vm->program[++vm->pc];
			Word numArgs = vm->program[++vm->pc];
			++vm->pc;
			int index = ReadInteger(vm);
			
			PushFunc(vm, index, hasEllipsis, isExtern, numArgs);
		} break;
		
		case OP_PUSH_DICT:
		{
			if(vm->debug)
				printf("push_dict\n");
			++vm->pc;
			PushDict(vm);
		} break;

		case OP_CREATE_DICT_BLOCK:
		{
			if(vm->debug)
				printf("create_dict_block\n");
			++vm->pc;
			int length = ReadInteger(vm);
			Object* obj = PushDict(vm);
			if(length > 0)
			{
				// stack (before dict) is filled with key-value pairs (backwards, key is higher on stack)
				for(int i = 0; i < length * 2; i += 2)
					DictPut(&obj->dict, vm->stack[vm->stackSize - i - 2]->string.raw, vm->stack[vm->stackSize - i - 3]);
				vm->stackSize -= length * 2;
				vm->stack[vm->stackSize - 1] = obj;
			}
		} break;

		case OP_CREATE_ARRAY:
		{
			if(vm->debug)
				printf("create_array\n");
			++vm->pc;
			int length = (int)PopNumber(vm);
			PushArray(vm, length);
		} break;
		
		case OP_CREATE_ARRAY_BLOCK:
		{
			if(vm->debug)
				printf("create_array_block\n");
			++vm->pc;
			int length = ReadInteger(vm);
			Object* obj = PushArray(vm, length);
			if(length > 0)
			{
				for(int i = 0; i < length; ++i)
					obj->array.members[length - i - 1] = vm->stack[vm->stackSize - 2 - i];
				vm->stackSize -= length;
				vm->stack[vm->stackSize - 1] = obj;
			}
		} break;

		case OP_LENGTH:
		{
			if(vm->debug)
				printf("length\n");
			++vm->pc;
			Object* obj = PopObject(vm);
			if(obj->type == OBJ_STRING)
				PushNumber(vm, strlen(obj->string.raw));
			else if(obj->type == OBJ_ARRAY)
				PushNumber(vm, obj->array.length);
			else
			{
				fprintf(stderr, "Attempted to get length of %s\n", ObjectTypeNames[obj->type]);
				exit(1);
			}
		} break;
		
		case OP_ARRAY_PUSH:
		{
			if(vm->debug)
				printf("array_push\n");
			++vm->pc;
			
			Object* obj = PopArrayObject(vm);
			Object* value = PopObject(vm);

			while(obj->array.length + 1 >= obj->array.capacity)
			{
				obj->array.capacity *= 2;
				obj->array.members = erealloc(obj->array.members, obj->array.capacity * sizeof(Object*));
			}
			
			obj->array.members[obj->array.length++] = value;
		} break;
		
		case OP_ARRAY_POP:
		{
			if(vm->debug)
				printf("array_pop\n");
			++vm->pc;
			Object* obj = PopArrayObject(vm);
			if(obj->array.length <= 0)
			{
				fprintf(stderr, "Cannot pop from empty array\n");
				exit(1);
			}
			
			PushObject(vm, obj->array.members[--obj->array.length]);
		} break;
		
		case OP_ARRAY_CLEAR:
		{
			if(vm->debug)
				printf("array_clear\n");
			++vm->pc;
			Object* obj = PopArrayObject(vm);
			obj->array.length = 0;
		} break;

		case OP_DICT_SET:
		{
			if(vm->debug)
				printf("dict_set\n");
			++vm->pc;
			Object* obj = PopDict(vm);
			const char* key = PopString(vm);
			Object* value = PopObject(vm);
			
			DictPut(&obj->dict, key, value);
		} break;
		
		case OP_DICT_GET:
		{
			if(vm->debug)
				printf("dict_get\n");
			++vm->pc;
			Object* obj = PopDict(vm);
			const char* key = PopString(vm);
			
			Object* value = DictGet(&obj->dict, key);
			if(value)
				PushObject(vm, value);
			else
				PushObject(vm, &NullObject);
		} break;

		case OP_DICT_PAIRS:
		{
			if(vm->debug)
				printf("dict_pairs\n");
			++vm->pc;
			Object* obj = PopDict(vm);
			Object* aobj = PushArray(vm, obj->dict.numEntries);
			
			int len = 0;
			for(int i = 0; i <= obj->dict.capacity; ++i)
			{
				DictNode* node = obj->dict.buckets[i];
				while(node)
				{
					Object* pair = PushArray(vm, 2);
					
					Object* key = NewObject(vm, OBJ_STRING);
					key->string.raw = estrdup(node->key);
					
					pair->array.members[0] = key;
					pair->array.members[1] = node->value;
					
					aobj->array.members[len++] = PopObject(vm);
					
					node = node->next;
				}
			}
		} break;
		
		#define BIN_OP_TYPE(op, operator, type) case OP_##op: { if(vm->debug) printf("%s\n", #op); Object* val2 = PopObject(vm); Object* val1 = PopObject(vm); PushNumber(vm, (type)val1->number operator (type)val2->number); ++vm->pc; } break;
		#define BIN_OP(op, operator) BIN_OP_TYPE(op, operator, double)
		
		BIN_OP(ADD, +)
		BIN_OP(SUB, -)
		BIN_OP(MUL, *)
		BIN_OP(DIV, /)
		BIN_OP_TYPE(MOD, %, int)
		BIN_OP_TYPE(OR, |, int)
		BIN_OP_TYPE(AND, &, int)
		BIN_OP(LT, <)
		BIN_OP(LTE, <=)
		BIN_OP(GT, >)
		BIN_OP(GTE, >=)
		BIN_OP_TYPE(LOGICAL_AND, &&, int)
		BIN_OP_TYPE(LOGICAL_OR, ||, int)
		
		#define CBIN_OP(op, operator) case OP_##op: { ++vm->pc; if(vm->debug) printf("%s\n", #op); Object* b = PopObject(vm); Object* a = PopObject(vm); a->number operator b->number; } break;
		
		CBIN_OP(CADD, +=)
		CBIN_OP(CSUB, -=)
		CBIN_OP(CMUL, *=)
		CBIN_OP(CDIV, /=)
		
		case OP_EQU:
		{
			++vm->pc;
			Object* o2 = PopObject(vm);
			Object* o1 = PopObject(vm);
			
			if(o1->type != o2->type) PushNumber(vm, 0);
			else
			{
				if(o1->type == OBJ_STRING) { PushNumber(vm, strcmp(o1->string.raw, o2->string.raw) == 0); }
				else if(o1->type == OBJ_NUMBER) { PushNumber(vm, o1->number == o2->number); }
				else PushNumber(vm, o1 == o2);
			}
		} break;
		
		case OP_NEQU:
		{
			++vm->pc;
			Object* o2 = PopObject(vm);
			Object* o1 = PopObject(vm);
			
			if(o1->type != o2->type) PushNumber(vm, 1);
			else
			{
				if(o1->type == OBJ_STRING) { PushNumber(vm, strcmp(o1->string.raw, o2->string.raw) != 0); }
				else if(o1->type == OBJ_NUMBER) { PushNumber(vm, o1->number != o2->number); }
				else PushNumber(vm, o1 != o2);
			}
		} break;
		
		case OP_NEG:
		{
			if(vm->debug)
				printf("neg\n");
			
			++vm->pc;
			Object* obj = PopObject(vm);
			PushNumber(vm, -obj->number);
		} break;
		
		case OP_LOGICAL_NOT:
		{
			if(vm->debug)
				printf("not\n");
			
			++vm->pc;
			Object* obj = PopObject(vm);
			PushNumber(vm, !obj->number);
		} break;
		
		case OP_SETINDEX:
		{
			++vm->pc;

			Object* obj = PopObject(vm);
			Object* indexObj = PopObject(vm);
			Object* value = PopObject(vm);
			if(vm->debug)
				printf("setindex\n");
			
			if(obj->type == OBJ_ARRAY)
			{
				if(indexObj->type != OBJ_NUMBER)
				{
					fprintf(stderr, "Attempted to index array with a %s (expected number)\n", ObjectTypeNames[indexObj->type]);
					exit(1);
				}
				
				int index = (int)indexObj->number;
				
				int arrayLength = obj->array.length;
				Object** members = obj->array.members;
				
				if(index >= 0 && index < arrayLength)
					members[index] = value;
				else
				{
					fprintf(stderr, "Invalid array index %i\n", index);
					exit(1);
				}
			}
			else if(obj->type == OBJ_STRING)
			{				
				if(indexObj->type != OBJ_NUMBER)
				{
					fprintf(stderr, "Attempted to index string with a %s (expected number)\n", ObjectTypeNames[indexObj->type]);
					exit(1);
				}
				
				if(value->type != OBJ_NUMBER)
				{
					fprintf(stderr, "Attempted to assign a %s to an index of a string '%s' (expected number/character)\n", ObjectTypeNames[value->type], obj->string.raw);
					exit(1);
				}
				
				obj->string.raw[(int)indexObj->number] = (char)value->number;
			}
			else if(obj->type == OBJ_DICT)
			{
				if(indexObj->type != OBJ_STRING)
				{
					fprintf(stderr, "Attempted to index dict with a %s (expected string)\n", ObjectTypeNames[indexObj->type]);
					exit(1);
				}
				
				DictPut(&obj->dict, indexObj->string.raw, value);
			}
			else
			{
				fprintf(stderr, "Attempted to index a %s\n", ObjectTypeNames[obj->type]);
				exit(1);
			}
		} break;

		case OP_GETINDEX:
		{
			++vm->pc;

			Object* obj = PopObject(vm);
			Object* indexObj = PopObject(vm);

			if(obj->type == OBJ_ARRAY)
			{
				if(indexObj->type != OBJ_NUMBER)
				{
					fprintf(stderr, "Attempted to index array with a %s (expected number)\n", ObjectTypeNames[indexObj->type]);
					exit(1);
				}
				
				int index = (int)indexObj->number;
				
				int arrayLength = obj->array.length;
				Object** members = obj->array.members;
				
				if(index >= 0 && index < arrayLength)
				{
					if(members[index])
						PushObject(vm, members[index]);
					else
					{
						fprintf(stderr, "attempted to index non-existent value in array\n");
						exit(1);
					}
					if(vm->debug)
						printf("getindex %i\n", index);
				}
				else
				{
					fprintf(stderr, "Invalid array index %i\n", index);
					exit(1);
				}
			}
			else if(obj->type == OBJ_STRING)
			{
				if(indexObj->type != OBJ_NUMBER)
				{
					fprintf(stderr, "Attempted to index string with a %s (expected number)\n", ObjectTypeNames[indexObj->type]);
					exit(1);
				}
				
				PushNumber(vm, obj->string.raw[(int)indexObj->number]);
			}
			else if(obj->type == OBJ_DICT)
			{
				if(indexObj->type != OBJ_STRING)
				{
					fprintf(stderr, "Attempted to index dict with a %s (expected string)\n", ObjectTypeNames[indexObj->type]);
					exit(1);
				}
				
				Object* val = (Object*)DictGet(&obj->dict, indexObj->string.raw);
				if(val)
					PushObject(vm, val);
				else
					PushObject(vm, &NullObject);
			}
			else 
			{
				fprintf(stderr, "Attempted to index a %s\n", ObjectTypeNames[obj->type]);
				exit(1);
			}
		} break;

		case OP_SET:
		{
			++vm->pc;
			int index = ReadInteger(vm);
			
			Object* top = PopObject(vm);
			vm->stack[index] = top;
			
			if(vm->debug)
			{
				if(top->type == OBJ_NUMBER) printf("set %i to %g\n", index, top->number);
				else if(top->type == OBJ_STRING) printf("set %i to %s\n", index, top->string);	
			}
		} break;
		
		case OP_GET:
		{
			++vm->pc;
			int index = ReadInteger(vm);
			if(vm->stack[index])
				PushObject(vm, (vm->stack[index]));
			else
				PushObject(vm, &NullObject);
				
			if(vm->debug)
				printf("get %i\n", index);
		} break;
		
		case OP_WRITE:
		{
			if(vm->debug)
				printf("write\n");
			Object* top = PopObject(vm);
			WriteObject(vm, top);
			printf("\n");
			++vm->pc;
		} break;
		
		case OP_READ:
		{
			if(vm->debug)
				printf("read\n");
			char* string = ReadStringFromStdin();
			PushString(vm, string);
			free(string);
			++vm->pc;
		} break;
		
		case OP_GOTO:
		{
			++vm->pc;
			int pc = ReadInteger(vm);
			vm->pc = pc;
		
			if(vm->debug)
				printf("goto %i\n", vm->pc);
		} break;
		
		case OP_GOTOZ:
		{
			++vm->pc;
			int pc = ReadInteger(vm);
			
			Object* top = PopObject(vm);
			if(top->number == 0)
			{
				vm->pc = pc;
				if(vm->debug)
					printf("gotoz %i\n", vm->pc);
			}
		} break;
		
		case OP_CALL:
		{
			Word nargs = vm->program[++vm->pc];
			++vm->pc;
			int index = ReadInteger(vm);

			if(vm->debug)
				printf("call %s\n", vm->functionNames[index]);

			PushIndir(vm, nargs);

			vm->pc = vm->functionPcs[index];
		} break;
		
		case OP_CALLP:
		{
			Word hasEllipsis, isExtern, numArgs;
			Word nargs = vm->program[++vm->pc];
			++vm->pc;
			int id = PopFunc(vm, &hasEllipsis, &isExtern, &numArgs);
			
			if(vm->debug)
				printf("callp %s%s\n", isExtern ? "extern " : "", isExtern ? vm->externNames[id] : vm->functionNames[id]);
			
			if(isExtern)
				vm->externs[id](vm);
			else
			{
				if(!hasEllipsis)
				{
					if(nargs != numArgs)
					{
						fprintf(stderr, "Function '%s' expected %i args but recieved %i args\n", vm->functionNames[id], numArgs, nargs);
						exit(1);
					}
				}
				else
				{
					if(nargs < numArgs)
					{
						fprintf(stderr, "Function '%s' expected at least %i args but recieved %i args\n", vm->functionNames[id], numArgs, nargs);
						exit(1);
					}
				}
				
				if(!hasEllipsis) PushIndir(vm, nargs);
				else
				{
					// runtime collapsing of arguments:
					// the concrete arguments (known during compilation) are on the top of
					// the stack. We create an array (by pushing it and then decrementing the
					// stack pointer) and fill it up with the ellipsed arguments (behind the
					// concrete arguments). We then place this array just before the concrete
					// arguments in the stack so that it can be accessed as an argument "args".
					// The indirection info is pushed onto the indirection stack (the concrete and
					// non-concrete [aside from the one that the 'args' array replaces] are still 
					// present on the stack, so all of the arguments are to be removed)
					
					/*printf("args:\n");
					for(int i = 0; i < nargs; ++i)
					{
						WriteObject(vm, vm->stack[vm->stackSize - i - 1]);
						printf("\n");
					}
					printf("end\n");*/
					
					//printf("members:\n");
					Object* obj = PushArray(vm, nargs - numArgs);
					vm->stackSize -= 1;
					for(int i = 0; i < obj->array.length; ++i)
					{
						obj->array.members[i] = vm->stack[vm->stackSize - numArgs - 1 - i];
						/*WriteObject(vm, obj->array.members[i]);
						printf("\n");*/
					}
					//printf("end\n");
					
					vm->stack[vm->stackSize - numArgs - 1] = obj;
					
					/*printf("final args:\n");
					for(int i = 0; i < numArgs + 1; ++i)
					{
						WriteObject(vm, vm->stack[vm->stackSize - i - 1]);
						printf("\n");
					}
					printf("end\n");*/
					
					PushIndir(vm, nargs);
				}
				
				vm->pc = vm->functionPcs[id];
			}
		} break;
		
		case OP_RETURN:
		{
			if(vm->debug)
				printf("ret\n");
			PopIndir(vm);
		} break;
		
		case OP_RETURN_VALUE:
		{
			if(vm->debug)
				printf("retval\n");
			Object* returnValue = PopObject(vm);
			PopIndir(vm);
			PushObject(vm, returnValue);
		} break;
		
		case OP_CALLF:
		{
			++vm->pc;
			int index = ReadInteger(vm);
			if(vm->debug)
				printf("callf %s\n", vm->externNames[index]);
			vm->externs[index](vm);
		} break;

		case OP_GETLOCAL:
		{
			++vm->pc;
			int index = ReadInteger(vm);
			PushObject(vm, GetLocal(vm, index));
			if(vm->debug)
				printf("getlocal %i (fp: %i, stack size: %i)\n", index, vm->fp, vm->stackSize);
		} break;
		
		case OP_SETLOCAL:
		{
			if(vm->debug)
				printf("setlocal\n");
			++vm->pc;
			int index = ReadInteger(vm);
			SetLocal(vm, index, PopObject(vm));
		} break;
		
		case OP_HALT:
		{
			if(vm->debug)
				printf("halt\n");
			vm->pc = -1;
		} break;
		
		default:
			printf("Invalid instruction %i\n", vm->program[vm->pc]);
			break;
	}
}
Beispiel #21
0
void PushNumber(VM* vm, double value)
{
	Object* obj = NewObject(vm, OBJ_NUMBER);
	obj->number = value;
	PushObject(vm, obj);
}
Beispiel #22
0
void
prim_getprop(PRIM_PROTOTYPE)
{
	const char *temp;
	PropPtr prptr;
	dbref obj2;

	CHECKOP(2);
	oper1 = POP();
	oper2 = POP();
	if (oper1->type != PROG_STRING)
		abort_interp("Non-string argument (2)");
	if (!oper1->data.string)
		abort_interp("Empty string argument (2)");
	if (!valid_object(oper2))
		abort_interp("Non-object argument (1)");
	CHECKREMOTE(oper2->data.objref);
	{
		char type[BUFFER_LEN];
		int len = oper1->data.string->length;

		if (!prop_read_perms(ProgUID, oper2->data.objref, oper1->data.string->data, mlev))
			abort_interp("Permission denied.");

		strcpyn(type, sizeof(type), oper1->data.string->data);
		while (len-- > 0 && type[len] == PROPDIR_DELIMITER) {
			type[len] = '\0';
		}

		obj2 = oper2->data.objref;
		prptr = get_property(obj2, type);

#ifdef LOG_PROPS
		log2file("props.log", "#%d (%d) GETPROP: o=%d n=\"%s\"",
				 program, pc->line, oper2->data.objref, type);
#endif

		CLEAR(oper1);
		CLEAR(oper2);
		if (prptr) {
#ifdef DISKBASE
			propfetch(obj2, prptr);
#endif
			switch (PropType(prptr)) {
			case PROP_STRTYP:
				temp = PropDataStr(prptr);
				PushString(temp);
				break;
			case PROP_LOKTYP:
				if (PropFlags(prptr) & PROP_ISUNLOADED) {
					PushLock(TRUE_BOOLEXP);
				} else {
					PushLock(PropDataLok(prptr));
				}
				break;
			case PROP_REFTYP:
				PushObject(PropDataRef(prptr));
				break;
			case PROP_INTTYP:
				PushInt(PropDataVal(prptr));
				break;
			case PROP_FLTTYP:
				PushFloat(PropDataFVal(prptr));
				break;
			default:
				result = 0;
				PushInt(result);
				break;
			}
		} else {
			result = 0;
			PushInt(result);
		}

		/* if (Typeof(oper2->data.objref) != TYPE_PLAYER)
		   ts_lastuseobject(oper2->data.objref); */
	}
}