Ejemplo n.º 1
0
void SC_HID_APIManager::handleElement( int joy_idx, struct hid_device_element * ele, std::atomic<bool> const & shouldBeRunning ){
	int status = lockLanguageOrQuit(shouldBeRunning);
	if (status == EINTR)
		return;
	if (status) {
		postfl("error when locking language (%d)\n", status);
		return;
	}

	if (compiledOK) {
		VMGlobals* g = gMainVMGlobals;
		g->canCallOS = false;
		++g->sp; SetObject(g->sp, s_hidapi->u.classobj ); // set the class HID_API
		++g->sp; SetInt(g->sp, joy_idx );
		++g->sp; SetInt(g->sp, ele->index );
		++g->sp; SetInt(g->sp, ele->usage_page );
		++g->sp; SetInt(g->sp, ele->usage );
		++g->sp; SetInt(g->sp, ele->value );
		++g->sp; SetFloat(g->sp, hid_element_map_logical( ele ) );
		++g->sp; SetFloat(g->sp, hid_element_map_physical( ele ) );
		++g->sp; SetInt(g->sp, ele->array_value );
		runInterpreter(g, s_hidElementData, 9 );
		g->canCallOS = false;
	}
	gLangMutex.unlock();
}
Ejemplo n.º 2
0
void PerformOSCBundle(int inSize, char* inData, PyrObject *replyObj, int inPortNum)
{
	// convert all data to arrays

	int64 oscTime = OSCtime(inData + 8);
	double seconds = OSCToElapsedTime(oscTime);

	VMGlobals *g = gMainVMGlobals;
	char *data = inData + 16;
	char* dataEnd = inData + inSize;
	while (data < dataEnd) {
		int32 msgSize = OSCint(data);
		data += sizeof(int32);
		if (IsBundle(data))
		{
			PerformOSCBundle(msgSize, data, replyObj, inPortNum);
		}
		else // is a message
		{
			++g->sp; SetObject(g->sp, g->process);
			++g->sp; SetFloat(g->sp, seconds);
			++g->sp; SetObject(g->sp, replyObj);
			++g->sp; SetInt(g->sp, inPortNum);

			PyrObject *arrayObj = ConvertOSCMessage(msgSize, data);
			++g->sp; SetObject(g->sp, arrayObj);
			runInterpreter(g, s_recvoscmsg, 5);
		}
		data += msgSize;
	}
}
Ejemplo n.º 3
0
void interpretCmdLine(const char *textbuf, int textlen, char *methodname)
{
	PyrString *string;

	if (compiledOK) {
		PyrSlot slot;

		string = newPyrStringN(gMainVMGlobals->gc, textlen, 0, false);
		memcpy(string->s, textbuf, textlen);
		SetObject(&slotRawInterpreter(&gMainVMGlobals->process->interpreter)->cmdLine, string);
		gMainVMGlobals->gc->GCWrite(slotRawObject(&gMainVMGlobals->process->interpreter), string);
		SetObject(&slot, gMainVMGlobals->process);
//#if __profile__
//		ProfilerInit(collectSummary, microsecondsTimeBase, 500, 100);
//#endif
		slotCopy((++gMainVMGlobals->sp), &slot);
		runInterpreter(gMainVMGlobals, getsym(methodname), 1);
//#if __profile__
//		ProfilerDump("\pErase2.prof");
//		ProfilerTerm();
//#endif
	} else {
		postfl("Library has not been compiled successfully.\n");
	}
}
Ejemplo n.º 4
0
// pass the remaining command-line arguments to the world
void passArguments(int argumentCount, char ** arguments) {
	mainContext = createMainContext();
	exceptionHandlerContext = createExceptionHandlerContext();
	
	// pass all remaining arguments to the script;
	// place them all directly to the old space since they will live forever
	OP argumentArray = instantiateClassInOldSpace(ARRAY_OP, argumentCount, 0);
	
	for(int index = 0; index < argumentCount; ++index) {
		int argLength = strlen(arguments[index]);
		
		OP argumentString = instantiateClassInOldSpace(STRING_OP, argLength, 0);
		
		for(int charIndex = 0; charIndex < argLength; ++charIndex) {
			storeIndexablePointer(argumentString, charIndex, characterObjectOf(arguments[index][charIndex]));
		}
		
		storeIndexablePointer(argumentArray, index, argumentString);
	}
	
	switchActiveContext(exceptionHandlerContext);
	activeContextStackPush(argumentArray);
	sendSelector(OBJECT_ARGUMENTS_SELECTOR_OP, SCRIPTRUNNER_OP, 1);
	runInterpreter();
	
	mainContext = OBJECT_NIL_OP;
	exceptionHandlerContext = OBJECT_NIL_OP;
}
Ejemplo n.º 5
0
void PerformOSCBundle(int inSize, char* inData, PyrObject *replyObj)
{
    // convert all data to arrays

    int64 oscTime = OSCtime(inData + 8);
    double seconds = OSCToElapsedTime(oscTime);

    VMGlobals *g = gMainVMGlobals;
    ++g->sp; SetObject(g->sp, g->process);
    ++g->sp; SetFloat(g->sp, seconds);
    ++g->sp; SetObject(g->sp, replyObj);

    PyrSlot *stackBase = g->sp;
    char *data = inData + 16;
    char* dataEnd = inData + inSize;
    while (data < dataEnd) {
        int32 msgSize = OSCint(data);
        data += sizeof(int32);
        PyrObject *arrayObj = ConvertOSCMessage(msgSize, data);
        ++g->sp; SetObject(g->sp, arrayObj);
        data += msgSize;
    }

	int numMsgs = g->sp - stackBase;

    runInterpreter(g, s_recvoscbndl, 3+numMsgs);
}
Ejemplo n.º 6
0
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QFont f("unexistent");
    f.setStyleHint(QFont::Monospace);
    ui->ui_inputPlainTextEdit->setFont(f);
    ui->ui_outputPlainTextEdit->setFont(f);

    setCurrentPath(QString());
    setModified(false);

    connect(ui->ui_sourceEditTableWidget, SIGNAL(cursorPositionChanged(int,int)), this, SLOT(cursorPositionChanged(int,int)));
    connect(ui->ui_sourceEditTableWidget, SIGNAL(textChanged()), this, SLOT(textChanged()));
    connect(ui->ui_newFileAction, SIGNAL(triggered()), this, SLOT(newFile()));
    connect(ui->ui_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
    connect(ui->ui_saveFileAction, SIGNAL(triggered()), this, SLOT(saveFile()));
    connect(ui->ui_saveAsAction, SIGNAL(triggered()), this, SLOT(saveFileAs()));
    connect(ui->ui_quitAction, SIGNAL(triggered()), this, SLOT(close()));

    connect(ui->ui_setInterpreterAction, SIGNAL(triggered()), this, SLOT(setInterpreter()));
    connect(ui->ui_runInterpreterAction, SIGNAL(triggered()), this, SLOT(runInterpreter()));
}
Ejemplo n.º 7
0
SC_DLLEXPORT_C void runLibrary(PyrSymbol* selector)
{
        VMGlobals *g = gMainVMGlobals;
        g->canCallOS = true;
	try {
		if (compiledOK) {
                        ++g->sp; SetObject(g->sp, g->process);
			runInterpreter(g, selector, 1);
		} else {
			postfl("Library has not been compiled successfully.\n");
		}
	} catch (std::exception &ex) {
		PyrMethod *meth = g->method;
		if (meth) {
			int ip = slotRawInt8Array(&meth->code) ? g->ip - slotRawInt8Array(&meth->code)->b : -1;
			post("caught exception in runLibrary %s:%s %3d\n",
				slotRawSymbol(&slotRawClass(&meth->ownerclass)->name)->name, slotRawSymbol(&meth->name)->name, ip
			);
			dumpByteCodes(meth);
		} else {
			post("caught exception in runLibrary\n");
		}
		error(ex.what());
	} catch (...) {
		postfl("DANGER: OUT of MEMORY. Operation failed.\n");
	}
        g->canCallOS = false;
}
Ejemplo n.º 8
0
void PushQueueEvents_CalibratedValue (){

	IOHIDEventStruct event;
	pRecDevice  pCurrentHIDDevice = HIDGetFirstDevice ();

	int numdevs = gNumberOfHIDDevices;
	unsigned char result;
	for(int i=0; i< numdevs; i++){

		result = HIDGetEvent(pCurrentHIDDevice, (void*) &event);
		if(result && compiledOK) {
			SInt32 value = event.value;
			int vendorID = pCurrentHIDDevice->vendorID;
			int productID = pCurrentHIDDevice->productID;
			int locID = pCurrentHIDDevice->locID;
			IOHIDElementCookie cookie = (IOHIDElementCookie) event.elementCookie;
			pRecElement pCurrentHIDElement =  HIDGetFirstDeviceElement (pCurrentHIDDevice, kHIDElementTypeAll);
	// use gElementCookie to find current element
			while (pCurrentHIDElement && ( (pCurrentHIDElement->cookie) != cookie))
			pCurrentHIDElement = HIDGetNextDeviceElement (pCurrentHIDElement, kHIDElementTypeAll);

			if (pCurrentHIDElement)
			{
			value = HIDCalibrateValue(value, pCurrentHIDElement);
			//find element to calibrate
			VMGlobals *g = gMainVMGlobals;
			pthread_mutex_lock (&gLangMutex);
			g->canCallOS = false; // cannot call the OS
			++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService
			//set arguments:
			++g->sp;SetInt(g->sp, vendorID);
			++g->sp;SetInt(g->sp, productID);
			++g->sp;SetInt(g->sp, locID);
			++g->sp;SetInt(g->sp, (int) cookie);
			++g->sp;SetInt(g->sp, value);
			runInterpreter(g, s_hidAction, 6);
			g->canCallOS = false; // cannot call the OS
			pthread_mutex_unlock (&gLangMutex);
			}
		}
	/* FIXME: this does not seem to be working!
		if ( !HIDIsValidDevice(pCurrentHIDDevice) )
		{ // readError
		 post("HID: read Error\n");
			int locID = pCurrentHIDDevice->locID;
			VMGlobals *g = gMainVMGlobals;
			pthread_mutex_lock (&gLangMutex);
			g->canCallOS = false; // cannot call the OS
			++g->sp; SetObject(g->sp, s_hid->u.classobj); // Set the class HIDService
			++g->sp;SetInt(g->sp, locID);
			runInterpreter(g, s_readError, 2);
			g->canCallOS = false; // cannot call the OS
			pthread_mutex_unlock (&gLangMutex);
		}*/
	pCurrentHIDDevice = HIDGetNextDevice(pCurrentHIDDevice);
	}
}
Ejemplo n.º 9
0
// create a context that catches unhandled exceptions and prints them
OP createExceptionHandlerContext() {
	switchActiveContext(mainContext);
	sendSelector(OBJECT_DEFAULT_EXCEPTION_HANDLER_CONTEXT_SELECTOR_OP, SCRIPTRUNNER_OP, 0);
	
	runInterpreter();
	
	exceptionHandlerContext = stackPop(mainContext);
	decrementNamedSmallInteger(exceptionHandlerContext, METHODCONTEXT_PROGRAM_COUNTER);
	
	return exceptionHandlerContext;
}
Ejemplo n.º 10
0
void SC_LID::readError()
{
	pthread_mutex_lock(&gLangMutex);
	if (compiledOK) {
		VMGlobals* g = gMainVMGlobals;
		g->canCallOS = false;
 		++g->sp; SetObject(g->sp, m_obj);
		runInterpreter(g, s_readError, 1);
		g->canCallOS = false;
	}
	pthread_mutex_unlock(&gLangMutex);
}
Ejemplo n.º 11
0
pascal void OurWordCallBackProc ( SpeechChannel inSpeechChannel, long inRefCon, long inWordPos, short inWordLen) {
    //post("word done");
	pthread_mutex_lock (&gLangMutex);
	VMGlobals *g = gMainVMGlobals;
	g->canCallOS = true;
	++g->sp; SetObject(g->sp, s_speech->u.classobj);
    //set arguments:
	++g->sp; SetInt(g->sp, (int) inRefCon); //src
	runInterpreter(g, s_speechwordAction, 2);

    g->canCallOS = false;
	pthread_mutex_unlock (&gLangMutex);
}
Ejemplo n.º 12
0
static void scCallSysexAction(PyrSymbol* action, int recoverFromUID) {
	VMGlobals *g = gMainVMGlobals;
	if(recoverFromUID) { // rebuild the VM so sc won't crash with two following calls
		++g->sp; SetObject(g->sp, s_midiin->u.classobj); // Set the class MIDIIn
		++g->sp; SetInt(g->sp,  recoverFromUID); //src
		++g->sp;
	}
	PyrInt8Array* sysexArray = newPyrInt8Array(g->gc, (int)gSysexData.size(), 0, true);
	sysexArray->size = (int)gSysexData.size();
	std::copy(gSysexData.begin(), gSysexData.end(), sysexArray->b);
	SetObject(g->sp, (PyrObject*) sysexArray);			// chan argument unneeded as there
	runInterpreter(g, action, 3 );			// special sysex action in the lang
}
Ejemplo n.º 13
0
void netAddrTcpClientNotifyFunc(void *clientData)
{
	extern bool compiledOK;

	pthread_mutex_lock(&gLangMutex);
	if (compiledOK) {
		PyrObject* netAddrObj = (PyrObject*)clientData;
		VMGlobals* g = gMainVMGlobals;
		g->canCallOS = false;
		++g->sp; SetObject(g->sp, netAddrObj);
		runInterpreter(g, getsym("prConnectionClosed"), 1);
		g->canCallOS = false;
	}
	pthread_mutex_unlock(&gLangMutex);
}
Ejemplo n.º 14
0
void PerformOSCMessage(int inSize, char *inData, PyrObject *replyObj, int inPortNum)
{

	PyrObject *arrayObj = ConvertOSCMessage(inSize, inData);

	// call virtual machine to handle message
	VMGlobals *g = gMainVMGlobals;
	++g->sp; SetObject(g->sp, g->process);
	++g->sp; SetFloat(g->sp, elapsedTime());	// time
	++g->sp; SetObject(g->sp, replyObj);
	++g->sp; SetInt(g->sp, inPortNum);
	++g->sp; SetObject(g->sp, arrayObj);

	runInterpreter(g, s_recvoscmsg, 5);
}
Ejemplo n.º 15
0
void SC_LID::handleEvent(struct input_event& evt)
{
	if (evt.type != EV_SYN) {
		pthread_mutex_lock(&gLangMutex);
		if (compiledOK) {
			VMGlobals* g = gMainVMGlobals;
			g->canCallOS = false;
			++g->sp; SetObject(g->sp, m_obj);
			++g->sp; SetInt(g->sp, evt.type);
			++g->sp; SetInt(g->sp, evt.code);
			++g->sp; SetInt(g->sp, evt.value);
			runInterpreter(g, s_handleEvent, 4);
			g->canCallOS = false;
		}
		pthread_mutex_unlock(&gLangMutex);
	}
}
Ejemplo n.º 16
0
pascal void OurSpeechDoneCallBackProc ( SpeechChannel inSpeechChannel, long inRefCon )
{
    //call action here;
    // post("text done");
    pthread_mutex_lock (&gLangMutex);
	VMGlobals *g = gMainVMGlobals;
	g->canCallOS = true;
	++g->sp; SetObject(g->sp, s_speech->u.classobj); // Set the class
        //set arguments:
	++g->sp;SetInt(g->sp, (int) inRefCon); //src
	runInterpreter(g, s_speechdoneAction, 2);
	if(speechStrings[(int) inRefCon] != NULL){
		free(speechStrings[(int) inRefCon]);
		speechStrings[(int) inRefCon] = NULL;
	}
    g->canCallOS = false;
	pthread_mutex_unlock (&gLangMutex);
}
Ejemplo n.º 17
0
static void runShutdown()
{
	//printf("->aboutToCompileLibrary\n");
	gLangMutex.lock();
	if (compiledOK) {
		VMGlobals *g = gMainVMGlobals;

		g->canCallOS = true;

		++g->sp;
		SetObject(g->sp, g->process);
		runInterpreter(g, s_shutdown, 1);

		g->canCallOS = false;
	}
	gLangMutex.unlock();
	//printf("<-aboutToCompileLibrary\n");
}
Ejemplo n.º 18
0
void aboutToCompileLibrary()
{
	//printf("->aboutToCompileLibrary\n");
	pthread_mutex_lock (&gLangMutex);
	if (compiledOK) {
		VMGlobals *g = gMainVMGlobals;

		g->canCallOS = true;

		++g->sp;
		SetObject(g->sp, g->process);
		runInterpreter(g, s_shutdown, 1);

		g->canCallOS = false;
	}
	pthread_mutex_unlock (&gLangMutex);
	//printf("<-aboutToCompileLibrary\n");
}
Ejemplo n.º 19
0
void SC_HID_APIManager::deviceClosed( int joy_idx, struct hid_dev_desc * dd, std::atomic<bool> const & shouldBeRunning ){
	int status = lockLanguageOrQuit(shouldBeRunning);
	if (status == EINTR)
		return;
	if (status) {
		trace("error when locking language (%d)\n", status);
		return;
	}
	if (compiledOK) {
		VMGlobals* g = gMainVMGlobals;
		g->canCallOS = false;
		++g->sp; SetObject(g->sp, s_hidapi->u.classobj ); // set the class HID_API
		++g->sp; SetInt(g->sp, joy_idx );
		runInterpreter(g, s_hidClosed, 2);
		g->canCallOS = false;
	}
	gLangMutex.unlock();
}
Ejemplo n.º 20
0
void SerialPort::doneAction()
{
	int status = lockLanguageOrQuit(m_dodone);
	if (status == EINTR)
		return;
	if (status) {
		postfl("error when locking language (%d)\n", status);
		return;
	}

	PyrSymbol *method = s_doneAction;
	if (m_obj) {
		VMGlobals *g = gMainVMGlobals;
		g->canCallOS = true;
		++g->sp; SetObject(g->sp, m_obj);
		runInterpreter(g, method, 1);
		g->canCallOS = false;
	}
	gLangMutex.unlock();
}
Ejemplo n.º 21
0
void SC_HID_APIManager::handleDevice( int joy_idx, struct hid_dev_desc * devd, std::atomic<bool> const & shouldBeRunning ){
	int status = lockLanguageOrQuit(shouldBeRunning);
	if (status == EINTR)
		return;
	if (status) {
		postfl("error when locking language (%d)\n", status);
		return;
	}

	if (compiledOK) {
		VMGlobals* g = gMainVMGlobals;
		g->canCallOS = false;
		++g->sp; SetObject(g->sp, s_hidapi->u.classobj ); // set the class HID_API
		++g->sp; SetInt(g->sp, joy_idx );
		++g->sp; SetInt(g->sp, devd->device_collection->num_elements );
		runInterpreter(g, s_hidDeviceData, 3);
		g->canCallOS = false;
	}
	gLangMutex.unlock();
}
Ejemplo n.º 22
0
void SerialPort::dataAvailable()
{
	int status = lockLanguageOrQuit(m_running);
	if (status == EINTR)
		return;
	if (status) {
		postfl("error when locking language (%d)\n", status);
		return;
	}

	PyrSymbol *method = s_dataAvailable;
	if (m_obj) {
		VMGlobals *g = gMainVMGlobals;
		g->canCallOS = true;
		++g->sp; SetObject(g->sp, m_obj);
		runInterpreter(g, method, 1);
		g->canCallOS = false;
	}
	pthread_mutex_unlock (&gLangMutex);
}
Ejemplo n.º 23
0
void compileSucceeded()
{
	compiledOK = !(parseFailed || compileErrors);
	if (compiledOK) {
		compiledOK = true;

		compiledOK = initRuntime(gMainVMGlobals, 128*1024, pyr_pool_runtime);

		if (compiledOK) {
			VMGlobals *g = gMainVMGlobals;

			g->canCallOS = true;
			//++g->sp; SetObject(g->sp, g->process);
			//runInterpreter(g, s_hardwaresetup, 1);

			++g->sp; SetObject(g->sp, g->process);
			runInterpreter(g, s_startup, 1);
                        g->canCallOS = false;

			schedRun();
		}
		flushPostBuf();
	}
}
Ejemplo n.º 24
0
void* string_popen_thread_func(void *data)
{
	struct sc_process *process = (struct sc_process *)data;
	FILE *stream = process->stream;
	pid_t pid = process->pid;
	char buf[1024];

	while (process->postOutput) {
		char *string = fgets(buf, 1024, stream);
		if (!string) break;
		postText(string, strlen(string));
	}

	int res;
	res = sc_pclose(stream, pid);
	res = WEXITSTATUS(res);

	if(process->postOutput)
		post("RESULT = %d\n", res);

	free(process);

    pthread_mutex_lock (&gLangMutex);
    if(compiledOK) {
		VMGlobals *g = gMainVMGlobals;
		g->canCallOS = true;
		++g->sp;  SetObject(g->sp, class_string);
		++g->sp; SetInt(g->sp, res);
		++g->sp; SetInt(g->sp, pid);
		runInterpreter(g, s_unixCmdAction, 3);
		g->canCallOS = false;
	}
    pthread_mutex_unlock (&gLangMutex);

	return 0;
}
Ejemplo n.º 25
0
// The main bytecode interpreter loop. This is where the magic happens. It is
// also, as you can imagine, highly performance critical. Returns `true` if the
// fiber completed without error.
static bool runInterpreter(WrenVM* vm)
{
  // Hoist these into local variables. They are accessed frequently in the loop
  // but assigned less frequently. Keeping them in locals and updating them when
  // a call frame has been pushed or popped gives a large speed boost.
  register ObjFiber* fiber = vm->fiber;
  register CallFrame* frame;
  register Value* stackStart;
  register uint8_t* ip;
  register ObjFn* fn;

  // These macros are designed to only be invoked within this function.
  #define PUSH(value)  (*fiber->stackTop++ = value)
  #define POP()        (*(--fiber->stackTop))
  #define DROP()       (fiber->stackTop--)
  #define PEEK()       (*(fiber->stackTop - 1))
  #define PEEK2()      (*(fiber->stackTop - 2))
  #define READ_BYTE()  (*ip++)
  #define READ_SHORT() (ip += 2, (ip[-2] << 8) | ip[-1])

  // Use this before a CallFrame is pushed to store the local variables back
  // into the current one.
  #define STORE_FRAME() frame->ip = ip

  // Use this after a CallFrame has been pushed or popped to refresh the local
  // variables.
  #define LOAD_FRAME()                                 \
      frame = &fiber->frames[fiber->numFrames - 1];    \
      stackStart = frame->stackStart;                  \
      ip = frame->ip;                                  \
      if (frame->fn->type == OBJ_FN)                   \
      {                                                \
        fn = (ObjFn*)frame->fn;                        \
      }                                                \
      else                                             \
      {                                                \
        fn = ((ObjClosure*)frame->fn)->fn;             \
      }

  // Terminates the current fiber with error string [error]. If another calling
  // fiber is willing to catch the error, transfers control to it, otherwise
  // exits the interpreter.
  #define RUNTIME_ERROR(error)                         \
      do {                                             \
        STORE_FRAME();                                 \
        fiber = runtimeError(vm, fiber, error);        \
        if (fiber == NULL) return false;               \
        LOAD_FRAME();                                  \
        DISPATCH();                                    \
      }                                                \
      while (false)

  #if WREN_COMPUTED_GOTO

  // Note that the order of instructions here must exacly match the Code enum
  // in wren_vm.h or horrendously bad things happen.
  static void* dispatchTable[] = {
    &&code_CONSTANT,
    &&code_NULL,
    &&code_FALSE,
    &&code_TRUE,
    &&code_LOAD_LOCAL_0,
    &&code_LOAD_LOCAL_1,
    &&code_LOAD_LOCAL_2,
    &&code_LOAD_LOCAL_3,
    &&code_LOAD_LOCAL_4,
    &&code_LOAD_LOCAL_5,
    &&code_LOAD_LOCAL_6,
    &&code_LOAD_LOCAL_7,
    &&code_LOAD_LOCAL_8,
    &&code_LOAD_LOCAL,
    &&code_STORE_LOCAL,
    &&code_LOAD_UPVALUE,
    &&code_STORE_UPVALUE,
    &&code_LOAD_GLOBAL,
    &&code_STORE_GLOBAL,
    &&code_LOAD_FIELD_THIS,
    &&code_STORE_FIELD_THIS,
    &&code_LOAD_FIELD,
    &&code_STORE_FIELD,
    &&code_POP,
    &&code_CALL_0,
    &&code_CALL_1,
    &&code_CALL_2,
    &&code_CALL_3,
    &&code_CALL_4,
    &&code_CALL_5,
    &&code_CALL_6,
    &&code_CALL_7,
    &&code_CALL_8,
    &&code_CALL_9,
    &&code_CALL_10,
    &&code_CALL_11,
    &&code_CALL_12,
    &&code_CALL_13,
    &&code_CALL_14,
    &&code_CALL_15,
    &&code_CALL_16,
    &&code_SUPER_0,
    &&code_SUPER_1,
    &&code_SUPER_2,
    &&code_SUPER_3,
    &&code_SUPER_4,
    &&code_SUPER_5,
    &&code_SUPER_6,
    &&code_SUPER_7,
    &&code_SUPER_8,
    &&code_SUPER_9,
    &&code_SUPER_10,
    &&code_SUPER_11,
    &&code_SUPER_12,
    &&code_SUPER_13,
    &&code_SUPER_14,
    &&code_SUPER_15,
    &&code_SUPER_16,
    &&code_JUMP,
    &&code_LOOP,
    &&code_JUMP_IF,
    &&code_AND,
    &&code_OR,
    &&code_IS,
    &&code_CLOSE_UPVALUE,
    &&code_RETURN,
    &&code_LIST,
    &&code_CLOSURE,
    &&code_CLASS,
    &&code_METHOD_INSTANCE,
    &&code_METHOD_STATIC,
    &&code_END
  };

  #define INTERPRET_LOOP    DISPATCH();
  #define CASE_CODE(name)   code_##name

  #if WREN_DEBUG_TRACE_INSTRUCTIONS
    // Prints the stack and instruction before each instruction is executed.
    #define DISPATCH() \
        { \
          wrenDebugPrintStack(fiber); \
          wrenDebugPrintInstruction(vm, fn, (int)(ip - fn->bytecode)); \
          instruction = *ip++; \
          goto *dispatchTable[instruction]; \
        }
  #else

    #define DISPATCH()      goto *dispatchTable[instruction = READ_BYTE()];

  #endif

  #else

  #define INTERPRET_LOOP    for (;;) switch (instruction = READ_BYTE())
  #define CASE_CODE(name)   case CODE_##name
  #define DISPATCH()        break

  #endif

  LOAD_FRAME();

  Code instruction;
  INTERPRET_LOOP
  {
    CASE_CODE(LOAD_LOCAL_0):
    CASE_CODE(LOAD_LOCAL_1):
    CASE_CODE(LOAD_LOCAL_2):
    CASE_CODE(LOAD_LOCAL_3):
    CASE_CODE(LOAD_LOCAL_4):
    CASE_CODE(LOAD_LOCAL_5):
    CASE_CODE(LOAD_LOCAL_6):
    CASE_CODE(LOAD_LOCAL_7):
    CASE_CODE(LOAD_LOCAL_8):
      PUSH(stackStart[instruction - CODE_LOAD_LOCAL_0]);
      DISPATCH();

    CASE_CODE(LOAD_LOCAL):
      PUSH(stackStart[READ_BYTE()]);
      DISPATCH();

    CASE_CODE(LOAD_FIELD_THIS):
    {
      int field = READ_BYTE();
      Value receiver = stackStart[0];
      ASSERT(IS_INSTANCE(receiver), "Receiver should be instance.");
      ObjInstance* instance = AS_INSTANCE(receiver);
      ASSERT(field < instance->obj.classObj->numFields, "Out of bounds field.");
      PUSH(instance->fields[field]);
      DISPATCH();
    }

    CASE_CODE(POP):   DROP(); DISPATCH();
    CASE_CODE(NULL):  PUSH(NULL_VAL); DISPATCH();
    CASE_CODE(FALSE): PUSH(FALSE_VAL); DISPATCH();
    CASE_CODE(TRUE):  PUSH(TRUE_VAL); DISPATCH();

    CASE_CODE(CALL_0):
    CASE_CODE(CALL_1):
    CASE_CODE(CALL_2):
    CASE_CODE(CALL_3):
    CASE_CODE(CALL_4):
    CASE_CODE(CALL_5):
    CASE_CODE(CALL_6):
    CASE_CODE(CALL_7):
    CASE_CODE(CALL_8):
    CASE_CODE(CALL_9):
    CASE_CODE(CALL_10):
    CASE_CODE(CALL_11):
    CASE_CODE(CALL_12):
    CASE_CODE(CALL_13):
    CASE_CODE(CALL_14):
    CASE_CODE(CALL_15):
    CASE_CODE(CALL_16):
    {
      // Add one for the implicit receiver argument.
      int numArgs = instruction - CODE_CALL_0 + 1;
      int symbol = READ_SHORT();

      Value receiver = *(fiber->stackTop - numArgs);
      ObjClass* classObj = wrenGetClassInline(vm, receiver);

      // If the class's method table doesn't include the symbol, bail.
      if (symbol >= classObj->methods.count)
      {
        RUNTIME_ERROR(methodNotFound(vm, classObj, symbol));
      }

      Method* method = &classObj->methods.data[symbol];
      switch (method->type)
      {
        case METHOD_PRIMITIVE:
        {
          Value* args = fiber->stackTop - numArgs;

          // After calling this, the result will be in the first arg slot.
          switch (method->fn.primitive(vm, fiber, args))
          {
            case PRIM_VALUE:
              // The result is now in the first arg slot. Discard the other
              // stack slots.
              fiber->stackTop -= numArgs - 1;
              break;

            case PRIM_ERROR:
              RUNTIME_ERROR(AS_STRING(args[0]));

            case PRIM_CALL:
              STORE_FRAME();
              callFunction(fiber, AS_OBJ(args[0]), numArgs);
              LOAD_FRAME();
              break;

            case PRIM_RUN_FIBER:
              STORE_FRAME();
              fiber = AS_FIBER(args[0]);
              LOAD_FRAME();
              break;
          }
          break;
        }

        case METHOD_FOREIGN:
          callForeign(vm, fiber, method->fn.foreign, numArgs);
          break;

        case METHOD_BLOCK:
          STORE_FRAME();
          callFunction(fiber, method->fn.obj, numArgs);
          LOAD_FRAME();
          break;

        case METHOD_NONE:
          RUNTIME_ERROR(methodNotFound(vm, classObj, symbol));
          break;
      }
      DISPATCH();
    }

    CASE_CODE(STORE_LOCAL):
      stackStart[READ_BYTE()] = PEEK();
      DISPATCH();

    CASE_CODE(CONSTANT):
      PUSH(fn->constants[READ_SHORT()]);
      DISPATCH();

    CASE_CODE(SUPER_0):
    CASE_CODE(SUPER_1):
    CASE_CODE(SUPER_2):
    CASE_CODE(SUPER_3):
    CASE_CODE(SUPER_4):
    CASE_CODE(SUPER_5):
    CASE_CODE(SUPER_6):
    CASE_CODE(SUPER_7):
    CASE_CODE(SUPER_8):
    CASE_CODE(SUPER_9):
    CASE_CODE(SUPER_10):
    CASE_CODE(SUPER_11):
    CASE_CODE(SUPER_12):
    CASE_CODE(SUPER_13):
    CASE_CODE(SUPER_14):
    CASE_CODE(SUPER_15):
    CASE_CODE(SUPER_16):
    {
      // TODO: Almost completely copied from CALL. Unify somehow.

      // Add one for the implicit receiver argument.
      int numArgs = instruction - CODE_SUPER_0 + 1;
      int symbol = READ_SHORT();

      Value receiver = *(fiber->stackTop - numArgs);
      ObjClass* classObj = wrenGetClassInline(vm, receiver);

      // Ignore methods defined on the receiver's immediate class.
      classObj = classObj->superclass;

      // If the class's method table doesn't include the symbol, bail.
      if (symbol >= classObj->methods.count)
      {
        RUNTIME_ERROR(methodNotFound(vm, classObj, symbol));
      }

      Method* method = &classObj->methods.data[symbol];
      switch (method->type)
      {
        case METHOD_PRIMITIVE:
        {
          Value* args = fiber->stackTop - numArgs;

          // After calling this, the result will be in the first arg slot.
          switch (method->fn.primitive(vm, fiber, args))
          {
            case PRIM_VALUE:
              // The result is now in the first arg slot. Discard the other
              // stack slots.
              fiber->stackTop -= numArgs - 1;
              break;

            case PRIM_ERROR:
              RUNTIME_ERROR(AS_STRING(args[0]));

            case PRIM_CALL:
              STORE_FRAME();
              callFunction(fiber, AS_OBJ(args[0]), numArgs);
              LOAD_FRAME();
              break;

            case PRIM_RUN_FIBER:
              STORE_FRAME();
              fiber = AS_FIBER(args[0]);
              LOAD_FRAME();
              break;
          }
          break;
        }

        case METHOD_FOREIGN:
          callForeign(vm, fiber, method->fn.foreign, numArgs);
          break;

        case METHOD_BLOCK:
          STORE_FRAME();
          callFunction(fiber, method->fn.obj, numArgs);
          LOAD_FRAME();
          break;

        case METHOD_NONE:
          RUNTIME_ERROR(methodNotFound(vm, classObj, symbol));
          break;
      }
      DISPATCH();
    }

    CASE_CODE(LOAD_UPVALUE):
    {
      Upvalue** upvalues = ((ObjClosure*)frame->fn)->upvalues;
      PUSH(*upvalues[READ_BYTE()]->value);
      DISPATCH();
    }

    CASE_CODE(STORE_UPVALUE):
    {
      Upvalue** upvalues = ((ObjClosure*)frame->fn)->upvalues;
      *upvalues[READ_BYTE()]->value = PEEK();
      DISPATCH();
    }

    CASE_CODE(LOAD_GLOBAL):
      PUSH(vm->globals.data[READ_SHORT()]);
      DISPATCH();

    CASE_CODE(STORE_GLOBAL):
      vm->globals.data[READ_SHORT()] = PEEK();
      DISPATCH();

    CASE_CODE(STORE_FIELD_THIS):
    {
      int field = READ_BYTE();
      Value receiver = stackStart[0];
      ASSERT(IS_INSTANCE(receiver), "Receiver should be instance.");
      ObjInstance* instance = AS_INSTANCE(receiver);
      ASSERT(field < instance->obj.classObj->numFields, "Out of bounds field.");
      instance->fields[field] = PEEK();
      DISPATCH();
    }

    CASE_CODE(LOAD_FIELD):
    {
      int field = READ_BYTE();
      Value receiver = POP();
      ASSERT(IS_INSTANCE(receiver), "Receiver should be instance.");
      ObjInstance* instance = AS_INSTANCE(receiver);
      ASSERT(field < instance->obj.classObj->numFields, "Out of bounds field.");
      PUSH(instance->fields[field]);
      DISPATCH();
    }

    CASE_CODE(STORE_FIELD):
    {
      int field = READ_BYTE();
      Value receiver = POP();
      ASSERT(IS_INSTANCE(receiver), "Receiver should be instance.");
      ObjInstance* instance = AS_INSTANCE(receiver);
      ASSERT(field < instance->obj.classObj->numFields, "Out of bounds field.");
      instance->fields[field] = PEEK();
      DISPATCH();
    }

    CASE_CODE(JUMP):
    {
      int offset = READ_SHORT();
      ip += offset;
      DISPATCH();
    }

    CASE_CODE(LOOP):
    {
      // Jump back to the top of the loop.
      int offset = READ_SHORT();
      ip -= offset;
      DISPATCH();
    }

    CASE_CODE(JUMP_IF):
    {
      int offset = READ_SHORT();
      Value condition = POP();

      if (IS_FALSE(condition) || IS_NULL(condition)) ip += offset;
      DISPATCH();
    }

    CASE_CODE(AND):
    {
      int offset = READ_SHORT();
      Value condition = PEEK();

      if (IS_FALSE(condition) || IS_NULL(condition))
      {
        // Short-circuit the right hand side.
        ip += offset;
      }
      else
      {
        // Discard the condition and evaluate the right hand side.
        DROP();
      }
      DISPATCH();
    }

    CASE_CODE(OR):
    {
      int offset = READ_SHORT();
      Value condition = PEEK();

      if (IS_FALSE(condition) || IS_NULL(condition))
      {
        // Discard the condition and evaluate the right hand side.
        DROP();
      }
      else
      {
        // Short-circuit the right hand side.
        ip += offset;
      }
      DISPATCH();
    }

    CASE_CODE(IS):
    {
      Value expected = POP();
      if (!IS_CLASS(expected))
      {
        const char* message = "Right operand must be a class.";
        RUNTIME_ERROR(AS_STRING(wrenNewString(vm, message, strlen(message))));
      }

      ObjClass* actual = wrenGetClass(vm, POP());
      bool isInstance = false;

      // Walk the superclass chain looking for the class.
      while (actual != NULL)
      {
        if (actual == AS_CLASS(expected))
        {
          isInstance = true;
          break;
        }
        actual = actual->superclass;
      }
      PUSH(BOOL_VAL(isInstance));
      DISPATCH();
    }

    CASE_CODE(CLOSE_UPVALUE):
      closeUpvalue(fiber);
      DROP();
      DISPATCH();

    CASE_CODE(RETURN):
    {
      Value result = POP();
      fiber->numFrames--;

      // Close any upvalues still in scope.
      Value* firstValue = stackStart;
      while (fiber->openUpvalues != NULL &&
             fiber->openUpvalues->value >= firstValue)
      {
        closeUpvalue(fiber);
      }

      // If the fiber is complete, end it.
      if (fiber->numFrames == 0)
      {
        // If this is the main fiber, we're done.
        if (fiber->caller == NULL) return true;

        // We have a calling fiber to resume.
        fiber = fiber->caller;

        // Store the result in the resuming fiber.
        *(fiber->stackTop - 1) = result;
      }
      else
      {
        // Store the result of the block in the first slot, which is where the
        // caller expects it.
        stackStart[0] = result;

        // Discard the stack slots for the call frame (leaving one slot for the
        // result).
        fiber->stackTop = frame->stackStart + 1;
      }

      LOAD_FRAME();
      DISPATCH();
    }

    CASE_CODE(LIST):
    {
      int numElements = READ_BYTE();
      ObjList* list = wrenNewList(vm, numElements);
      // TODO: Do a straight memcopy.
      for (int i = 0; i < numElements; i++)
      {
        list->elements[i] = *(fiber->stackTop - numElements + i);
      }

      // Discard the elements.
      fiber->stackTop -= numElements;

      PUSH(OBJ_VAL(list));
      DISPATCH();
    }

    CASE_CODE(CLOSURE):
    {
      ObjFn* prototype = AS_FN(fn->constants[READ_SHORT()]);

      ASSERT(prototype->numUpvalues > 0,
             "Should not create closure for functions that don't need it.");

      // Create the closure and push it on the stack before creating upvalues
      // so that it doesn't get collected.
      ObjClosure* closure = wrenNewClosure(vm, prototype);
      PUSH(OBJ_VAL(closure));

      // Capture upvalues.
      for (int i = 0; i < prototype->numUpvalues; i++)
      {
        bool isLocal = READ_BYTE();
        int index = READ_BYTE();
        if (isLocal)
        {
          // Make an new upvalue to close over the parent's local variable.
          closure->upvalues[i] = captureUpvalue(vm, fiber,
                                                frame->stackStart + index);
        }
        else
        {
          // Use the same upvalue as the current call frame.
          closure->upvalues[i] = ((ObjClosure*)frame->fn)->upvalues[index];
        }
      }

      DISPATCH();
    }

    CASE_CODE(CLASS):
    {
      ObjString* name = AS_STRING(PEEK2());

      ObjClass* superclass;
      if (IS_NULL(PEEK()))
      {
        // Implicit Object superclass.
        superclass = vm->objectClass;
      }
      else
      {
        // TODO: Handle the superclass not being a class object!
        superclass = AS_CLASS(PEEK());
      }

      int numFields = READ_BYTE();

      ObjClass* classObj = wrenNewClass(vm, superclass, numFields, name);

      // Don't pop the superclass and name off the stack until the subclass is
      // done being created, to make sure it doesn't get collected.
      DROP();
      DROP();

      // Now that we know the total number of fields, make sure we don't
      // overflow.
      if (superclass->numFields + numFields > MAX_FIELDS)
      {
        char message[70 + MAX_VARIABLE_NAME];
        snprintf(message, 70 + MAX_VARIABLE_NAME,
            "Class '%s' may not have more than %d fields, including inherited "
            "ones.", name->value, MAX_FIELDS);

        RUNTIME_ERROR(AS_STRING(wrenNewString(vm, message, strlen(message))));
      }

      PUSH(OBJ_VAL(classObj));
      DISPATCH();
    }

    CASE_CODE(METHOD_INSTANCE):
    CASE_CODE(METHOD_STATIC):
    {
      int type = instruction;
      int symbol = READ_SHORT();
      ObjClass* classObj = AS_CLASS(PEEK());
      Value method = PEEK2();
      bindMethod(vm, type, symbol, classObj, method);
      DROP();
      DROP();
      DISPATCH();
    }

    CASE_CODE(END):
      // A CODE_END should always be preceded by a CODE_RETURN. If we get here,
      // the compiler generated wrong code.
      UNREACHABLE();
  }

  // We should only exit this function from an explicit return from CODE_RETURN
  // or a runtime error.
  UNREACHABLE();
  return false;
}

WrenInterpretResult wrenInterpret(WrenVM* vm, const char* sourcePath,
                                  const char* source)
{
  // TODO: Check for freed VM.
  ObjFn* fn = wrenCompile(vm, sourcePath, source);
  if (fn == NULL) return WREN_RESULT_COMPILE_ERROR;

  WREN_PIN(vm, fn);
  vm->fiber = wrenNewFiber(vm, (Obj*)fn);
  WREN_UNPIN(vm);

  if (runInterpreter(vm))
  {
    return WREN_RESULT_SUCCESS;
  }
  else
  {
    return WREN_RESULT_RUNTIME_ERROR;
  }
}
Ejemplo n.º 26
0
/* timer "interrupt" for processing midi data */
static void PMProcessMidi(PtTimestamp timestamp, void *userData)
{
	ScopeMutexLock mulo(&gPmStreamMutex);
	PmError result;
	PmEvent buffer; /* just one message at a time */

	for( int i = 0 ; i < gNumMIDIInPorts; ++i )
	{
		int pmdid = gMidiInputIndexToPmDevIndex[i];
		PmStream* midi_in = gMIDIInStreams[i];
		if( midi_in )
		{
			while(result = Pm_Poll(midi_in))
			{
				long Tstatus, data1, data2;
				if (Pm_Read(midi_in, &buffer, 1) == pmBufferOverflow) 
				continue;
				// unless there was overflow, we should have a message now 

				Tstatus = Pm_MessageStatus(buffer.message);
				data1 = Pm_MessageData1(buffer.message);
				data2 = Pm_MessageData2(buffer.message);

				// +---------------------------------------------+
				// | Lock the interp. mutex and dispatch message |
				// +---------------------------------------------+
				pthread_mutex_lock (&gLangMutex); // it is needed  -jamesmcc
				if (compiledOK) 
				{
					VMGlobals *g = gMainVMGlobals;
					uint8 status = static_cast<uint8>(Tstatus & 0xF0);			
					uint8 chan = static_cast<uint8>(Tstatus & 0x0F);

					g->canCallOS = false; // cannot call the OS

					++g->sp; SetObject(g->sp, s_midiin->u.classobj); // Set the class MIDIIn
					//set arguments: 

					++g->sp; SetInt(g->sp,  pmdid); //src
					// ++g->sp;  SetInt(g->sp, status); //status
					++g->sp;  SetInt(g->sp, chan); //chan

					//if(status & 0x80) // set the running status for voice messages
						//gRunningStatus = ((status >> 4) == 0xF) ? 0 : pkt->data[i]; // keep also additional info
					switch (status) 
					{
					case 0x80 : //noteOff
						++g->sp; SetInt(g->sp, data1);
						++g->sp; SetInt(g->sp, data2);
						runInterpreter(g, s_midiNoteOffAction, 5);
						break;
					case 0x90 : //noteOn 
						++g->sp; SetInt(g->sp, data1);
						++g->sp; SetInt(g->sp, data2);
						runInterpreter(g, data2 ? s_midiNoteOnAction : s_midiNoteOffAction, 5);
						break;
					case 0xA0 : //polytouch
						++g->sp; SetInt(g->sp, data1);
						++g->sp; SetInt(g->sp, data2);
						runInterpreter(g, s_midiPolyTouchAction, 5);
						break;
					case 0xB0 : //control
						++g->sp; SetInt(g->sp, data1);
						++g->sp; SetInt(g->sp, data2);
						runInterpreter(g, s_midiControlAction, 5);
						break;
					case 0xC0 : //program
						++g->sp; SetInt(g->sp, data1);
						runInterpreter(g, s_midiProgramAction, 4);
						break;
					case 0xD0 : //touch
						++g->sp; SetInt(g->sp, data1);
						runInterpreter(g, s_midiTouchAction, 4);
						break;
					case 0xE0 : //bend	
						++g->sp; SetInt(g->sp, (data2 << 7) | data1);
						runInterpreter(g, s_midiBendAction, 4);
						break;
					/*case 0xF0 :
						// only the first Pm_Event will carry the 0xF0 byte
						// sysex message will be terminated by the EOX status byte 0xF7
						midiProcessSystemPacket(data1, data2, chan);
						break;
					default :	// data byte => continuing sysex message
						if(gRunningStatus && !gSysexFlag) { // handle running status
							status = gRunningStatus & 0xF0; // accept running status only inside a packet beginning
							chan = gRunningStatus & 0x0F;	// with a valid status byte 
							SetInt(g->sp, chan);			
							--i;
							//goto L; // parse again with running status set // mv - get next byte
						}
						chan = 0;
						i += midiProcessSystemPacket(pkt, chan); // process sysex packet
						break; */
					}
					g->canCallOS = false;
				} 
				pthread_mutex_unlock (&gLangMutex); 
			}
		} // if (midi_in)
	} // for loop until numMIDIInPorts
}
Ejemplo n.º 27
0
static int midiProcessSystemPacket(MIDIPacket *pkt, int chan) {
	int index, data;
	VMGlobals *g = gMainVMGlobals;
	switch (chan) {
	case 7: // added cp: Sysex EOX must be taken into account if first on data packet
	case 0:
		{
		int last_uid = 0;
		int m = pkt->length;
		Byte* p_pkt = pkt->data;
		Byte pktval;

		while(m--) {
			pktval = *p_pkt++;
			if(pktval & 0x80) { // status byte
				if(pktval == 0xF7) { // end packet
					gSysexData.push_back(pktval); // add EOX
					if(gSysexFlag)
						sysexEnd(last_uid); // if last_uid != 0 rebuild the VM.
					else
						sysexEndInvalid(); // invalid 1 byte with only EOX can happen
					break;
				}
				else if(pktval == 0xF0) { // new packet
					if(gSysexFlag) {// invalid new one/should not happen -- but handle in case
						// store the last uid value previous to invalid data to rebuild VM after sysexEndInvalid call
						// since it may call sysexEnd() just after it !
						if(slotIntVal(g->sp-1, &last_uid)) {
							post("error: failed retrieving uid value !");
							last_uid = -1;
						}
						sysexEndInvalid();
					}
					sysexBegin(); // new sysex in
					gSysexData.push_back(pktval); // add SOX
				}
				else {// abnormal data in middle of sysex packet
					gSysexData.push_back(pktval); // add it as an abort message
					sysexEndInvalid(); // flush invalid
					m = 0; // discard all packet
					break;
				}
			}
			else if(gSysexFlag)
				gSysexData.push_back(pktval); // add Byte
			else // garbage - handle in case - discard it
				break;
		}
		return (pkt->length-m);
		}
	break;

	case 1 :
		index = pkt->data[1] >> 4;
		data  = pkt->data[1] & 0xf;
		switch (index) { case 1: case 3: case 5: case 7: { data = data << 4; } }
		SetInt(g->sp,  index);		 						// chan unneeded
		++g->sp; SetInt(g->sp, data);						// special smpte action in the lang
		runInterpreter(g, s_midiSMPTEAction, 4 );
		return 2;

	case 2 : 	//songptr
		++g->sp; SetInt(g->sp,  (pkt->data[2] << 7) | pkt->data[1]); //val1
		runInterpreter(g, s_midiSysrtAction, 4);
		return 3;

	case 3 :	// song select
		++g->sp; SetInt(g->sp,  pkt->data[1]); //val1
		runInterpreter(g, s_midiSysrtAction, 4);
		return 2;

	case 8 :	//clock
	case 10:	//start
	case 11:	//continue
	case 12: 	//stop
	case 15:	//reset
		gRunningStatus = 0; // clear running status
		runInterpreter(g, s_midiSysrtAction, 3);
		return 1;

	default:
		g->sp -= 3; // nevermind
		break;
	}

	return (1);
}
Ejemplo n.º 28
0
static void midiProcessPacket(MIDIPacket *pkt, size_t uid)
{
//jt
	if(pkt) {
	pthread_mutex_lock (&gLangMutex); //dont know if this is really needed/seems to be more stable..
		// it is needed  -jamesmcc
	if (compiledOK) {
			VMGlobals *g = gMainVMGlobals;

			int i = 0; //cp : changed uint8 to int if packet->length >= 256 bug:(infinite loop)
			while (i < pkt->length) {
				uint8 status = pkt->data[i] & 0xF0;
				uint8 chan = pkt->data[i] & 0x0F;
				g->canCallOS = false; // cannot call the OS

				++g->sp; SetObject(g->sp, s_midiin->u.classobj); // Set the class MIDIIn
				//set arguments:
				++g->sp; SetInt(g->sp, (int)uid); //src
					// ++g->sp;  SetInt(g->sp, status); //status
				++g->sp; SetInt(g->sp, chan); //chan

				if(status & 0x80) // set the running status for voice messages
					gRunningStatus = ((status >> 4) == 0xF) ? 0 : pkt->data[i]; // keep also additional info
			L:
				switch (status) {
				case 0x80 : //noteOff
					++g->sp; SetInt(g->sp, pkt->data[i+1]); //val1
					++g->sp; SetInt(g->sp, pkt->data[i+2]); //val2
					runInterpreter(g, s_midiNoteOffAction, 5);
					i += 3;
					break;
				case 0x90 : //noteOn
					++g->sp; SetInt(g->sp, pkt->data[i+1]); //val1
					++g->sp; SetInt(g->sp, pkt->data[i+2]); //val2
					runInterpreter(g, pkt->data[i+2] ? s_midiNoteOnAction : s_midiNoteOffAction, 5);
					i += 3;
					break;
				case 0xA0 : //polytouch
					++g->sp; SetInt(g->sp, pkt->data[i+1]); //val1
					++g->sp; SetInt(g->sp, pkt->data[i+2]); //val2
					runInterpreter(g, s_midiPolyTouchAction, 5);
					i += 3;
					break;
				case 0xB0 : //control
					++g->sp; SetInt(g->sp, pkt->data[i+1]); //val1
					++g->sp; SetInt(g->sp, pkt->data[i+2]); //val2
					runInterpreter(g, s_midiControlAction, 5);
					i += 3;
					break;
				case 0xC0 : //program
					++g->sp; SetInt(g->sp, pkt->data[i+1]); //val1
					runInterpreter(g, s_midiProgramAction, 4);
					i += 2;
					break;
				case 0xD0 : //touch
					++g->sp; SetInt(g->sp,  pkt->data[i+1]); //val1
					runInterpreter(g, s_midiTouchAction, 4);
					i += 2;
					break;
				case 0xE0 : //bend
					++g->sp; SetInt(g->sp,  (pkt->data[i+2] << 7) | pkt->data[i+1]); //val1
					runInterpreter(g, s_midiBendAction, 4);
					i += 3;
					break;
				case 0xF0 :
					i += midiProcessSystemPacket(pkt, chan);
					break;
				default :	// data byte => continuing sysex message
					if(gRunningStatus && !gSysexFlag) { // modified cp: handling running status. may be we should here
						status = gRunningStatus & 0xF0; // accept running status only inside a packet beginning
						chan = gRunningStatus & 0x0F;	// with a valid status byte ?
						SetInt(g->sp, chan);
						--i;
						goto L; // parse again with running status set
					}
					chan = 0;
					i += midiProcessSystemPacket(pkt, chan);
					break;
			}
		}
		g->canCallOS = false;
	}
	pthread_mutex_unlock (&gLangMutex);
	}
}