/*JSON{ "type" : "staticmethod", "class" : "ESP8266WiFi", "name" : "logDebug", "generate" : "jswrap_ESP8266WiFi_logDebug", "params" : [ ["enable", "JsVar", "Enable or disable the debug logging."] ] } * Enable or disable the logging of debug information. A value of `true` enables * debug logging while a value of `false` disables debug logging. Debug output is sent * to UART1. */ void jswrap_ESP8266WiFi_logDebug( JsVar *jsDebug ) { uint8 enable = (uint8)jsvGetBool(jsDebug); os_printf("> jswrap_ESP8266WiFi_logDebug, enable=%d\n", enable); system_set_os_print((uint8)jsvGetBool(jsDebug)); os_printf("< jswrap_ESP8266WiFi_logDebug\n"); }
bool run_test(const char *filename) { printf("----------------------------------\r\n"); printf("----------------------------- TEST %s \r\n", filename); char *buffer = read_file(filename); if (!buffer) exit(1); jshInit(); jsvInit(); jsiInit(false /* do not autoload!!! */); addNativeFunction("quit", nativeQuit); addNativeFunction("interrupt", nativeInterrupt); jsvUnLock(jspEvaluate(buffer, true)); isRunning = true; bool isBusy = true; while (isRunning && (jsiHasTimers() || isBusy)) isBusy = jsiLoop(); JsVar *result = jsvObjectGetChild(execInfo.root, "result", 0/*no create*/); bool pass = jsvGetBool(result); jsvUnLock(result); if (pass) printf("----------------------------- PASS %s\r\n", filename); else { printf("----------------------------------\r\n"); printf("----------------------------- FAIL %s <-------\r\n", filename); jsvTrace(execInfo.root, 0); printf("----------------------------- FAIL %s <-------\r\n", filename); printf("----------------------------------\r\n"); } printf("BEFORE: %d Memory Records Used\r\n", jsvGetMemoryUsage()); // jsvTrace(execInfo.root, 0); jsiKill(); printf("AFTER: %d Memory Records Used\r\n", jsvGetMemoryUsage()); jsvGarbageCollect(); unsigned int unfreed = jsvGetMemoryUsage(); printf("AFTER GC: %d Memory Records Used (should be 0!)\r\n", unfreed); jsvShowAllocated(); jsvKill(); jshKill(); if (unfreed) { printf("FAIL because of unfreed memory.\r\n"); pass = false; } //jsvDottyOutput(); printf("\r\n"); free(buffer); return pass; }
/*JSON{ "type" : "staticmethod", "class" : "ESP8266WiFi", "name" : "setAutoConnect", "generate" : "jswrap_ESP8266WiFi_setAutoConnect", "params" : [ ["autoconnect","JsVar","True if we wish to auto connect."] ] }*/ void jswrap_ESP8266WiFi_setAutoConnect( JsVar *autoconnect //!< True if we wish to auto connect. ) { os_printf("Auto connect is: %d\n", (int)autoconnect); // Check that we have been passed a boolean ... if not, nothing to do here. if (!jsvIsBoolean(autoconnect)) { return; } uint8 newValue = jsvGetBool(autoconnect); os_printf("New value: %d\n", newValue); wifi_station_set_auto_connect(newValue); os_printf("Autoconnect changed\n"); }
static bool handlePipe(JsVar *arr, JsvObjectIterator *it, JsVar* pipe) { bool paused = jsvGetBoolAndUnLock(jsvObjectGetChild(pipe,"drainWait",0)); if (paused) return false; JsVar *position = jsvObjectGetChild(pipe,"position",0); JsVar *chunkSize = jsvObjectGetChild(pipe,"chunkSize",0); JsVar *source = jsvObjectGetChild(pipe,"source",0); JsVar *destination = jsvObjectGetChild(pipe,"destination",0); bool dataTransferred = false; if(source && destination && chunkSize && position) { JsVar *readFunc = jspGetNamedField(source, "read", false); JsVar *writeFunc = jspGetNamedField(destination, "write", false); if (jsvIsFunction(readFunc) && jsvIsFunction(writeFunc)) { // do the objects have the necessary methods on them? JsVar *buffer = jspExecuteFunction(readFunc, source, 1, &chunkSize); if(buffer) { JsVarInt bufferSize = jsvGetLength(buffer); if (bufferSize>0) { JsVar *response = jspExecuteFunction(writeFunc, destination, 1, &buffer); if (jsvIsBoolean(response) && jsvGetBool(response)==false) { // If boolean false was returned, wait for drain event (http://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback) jsvUnLock(jsvObjectSetChild(pipe,"drainWait",jsvNewFromBool(true))); } jsvUnLock(response); jsvSetInteger(position, jsvGetInteger(position) + bufferSize); } jsvUnLock(buffer); dataTransferred = true; // so we don't close the pipe if we get an empty string } } else { if(!jsvIsFunction(readFunc)) jsExceptionHere(JSET_ERROR, "Source Stream does not implement the required read(length) method."); if(!jsvIsFunction(writeFunc)) jsExceptionHere(JSET_ERROR, "Destination Stream does not implement the required write(buffer) method."); } jsvUnLock(readFunc); jsvUnLock(writeFunc); } if(!dataTransferred) { // when no more chunks are possible, execute the callback handlePipeClose(arr, it, pipe); } jsvUnLock(source); jsvUnLock(destination); jsvUnLock(chunkSize); jsvUnLock(position); return dataTransferred; }
bool run_test(const char *filename) { printf("----------------------------------\r\n"); printf("----------------------------- TEST %s \r\n", filename); char *buffer = (char *)read_file(filename); if (!buffer) return (false); jshInit(); jsiInit(false /* do not autoload!!! */); jspAddNativeFunction(jsiGetParser(), "function quit()", nativeQuit); jspAddNativeFunction(jsiGetParser(), "function interrupt()", nativeInterrupt); jsvUnLock(jspEvaluate(jsiGetParser(), buffer )); isRunning = true; while (isRunning && jsiHasTimers()) jsiLoop(); JsVar *result = jsvObjectGetChild(jsiGetParser()->root, "result", 0/*no create*/); bool pass = jsvGetBool(result); jsvUnLock(result); if (pass) printf("----------------------------- PASS %s\r\n", filename); else { printf("----------------------------------\r\n"); printf("----------------------------- FAIL %s <-------\r\n", filename); jsvTrace(jsvGetRef(jsiGetParser()->root), 0); printf("----------------------------- FAIL %s <-------\r\n", filename); printf("----------------------------------\r\n"); } printf("BEFORE: %d Memory Records Used\r\n", jsvGetMemoryUsage()); // jsvTrace(jsiGetParser()->root, 0); jsiKill(); printf("AFTER: %d Memory Records Used\r\n", jsvGetMemoryUsage()); jsvGarbageCollect(); printf("AFTER GC: %d Memory Records Used (should be 0!)\r\n", jsvGetMemoryUsage()); jsvShowAllocated(); jshKill(); //jsvDottyOutput(); printf("\r\n"); free(buffer); return pass; }
int jswrap_E_flashFatFS(JsVar* options) { uint32_t addr = FS_FLASH_BASE; uint16_t sectors = FS_SECTOR_COUNT; uint8_t format = 0; if (jsvIsObject(options)) { JsVar *a = jsvObjectGetChild(options, "addr", false); if (a) { if (jsvIsNumeric(a) && jsvGetInteger(a)>0x100000) addr = (uint32_t)jsvGetInteger(a); } JsVar *s = jsvObjectGetChild(options, "sectors", false); if (s) { if (jsvIsNumeric(s) && jsvGetInteger(s)>0) sectors = (uint16_t)jsvGetInteger(s); } JsVar *f = jsvObjectGetChild(options, "format", false); if (f) { if (jsvIsBoolean(f)) format = jsvGetBool(f); } } else if (!jsvIsUndefined(options)) { jsExceptionHere(JSET_TYPEERROR, "'options' must be an object, or undefined"); } uint8_t init=flashFatFsInit(addr, sectors); if (init) { if ( format ) { uint8_t res = f_mount(&jsfsFAT, "", 0); jsDebug("Formatting Flash"); res = f_mkfs("", 1, 0); // Super Floppy format, using all space (not partition table) if (res != FR_OK) { jsExceptionHere(JSET_INTERNALERROR, "Flash Formatting error:",res); return false; } } } jsfsInit(); return true; }
/*JSON{ "type" : "constructor", "class" : "Boolean", "name" : "Boolean", "generate" : "jswrap_boolean_constructor", "params" : [ ["value","JsVar","A single value to be converted to a number"] ], "return" : ["bool","A Boolean object"] } Creates a number */ bool jswrap_boolean_constructor(JsVar *value) { return jsvGetBool(value); }
JsVar *_jswrap_array_iterate_with_callback(const char *name, JsVar *parent, JsVar *funcVar, JsVar *thisVar, bool wantArray, bool isBoolCallback, bool expectedValue) { if (!jsvIsIterable(parent)) { jsExceptionHere(JSET_ERROR, "Array.%s can only be called on something iterable", name); return 0; } if (!jsvIsFunction(funcVar)) { jsExceptionHere(JSET_ERROR, "Array.%s's first argument should be a function", name); return 0; } if (!jsvIsUndefined(thisVar) && !jsvIsObject(thisVar)) { jsExceptionHere(JSET_ERROR, "Array.%s's second argument should be undefined, or an object", name); return 0; } JsVar *result = 0; if (wantArray) result = jsvNewEmptyArray(); bool isDone = false; if (result || !wantArray) { JsvIterator it; jsvIteratorNew(&it, parent); while (jsvIteratorHasElement(&it) && !isDone) { JsVar *index = jsvIteratorGetKey(&it); if (jsvIsInt(index)) { JsVarInt idxValue = jsvGetInteger(index); JsVar *args[3], *cb_result; args[0] = jsvIteratorGetValue(&it); args[1] = jsvNewFromInteger(idxValue); // child is a variable name, create a new variable for the index args[2] = parent; cb_result = jspeFunctionCall(funcVar, 0, thisVar, false, 3, args); jsvUnLockMany(2,args); if (cb_result) { bool matched; if (isBoolCallback) matched = (jsvGetBool(cb_result) == expectedValue); if (wantArray) { if (isBoolCallback) { // filter if (matched) { jsvArrayPushAndUnLock(result, jsvIteratorGetValue(&it)); } } else { // map JsVar *name = jsvNewFromInteger(idxValue); if (name) { // out of memory? jsvMakeIntoVariableName(name, cb_result); jsvAddName(result, name); jsvUnLock(name); } } } else { // break the loop early if expecting a particular value and didn't get it if (isBoolCallback && !matched) isDone = true; } jsvUnLock(cb_result); } } jsvUnLock(index); jsvIteratorNext(&it); } jsvIteratorFree(&it); } /* boolean result depends on whether the loop terminated early for 'some' or completed for 'every' */ if (!wantArray && isBoolCallback) { result = jsvNewFromBool(isDone != expectedValue); } return result; }
/** Call a function with the given argument specifiers */ JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar *thisParam, JsVar **paramData, int paramCount) { JsnArgumentType returnType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK); JsVar *argsArray = 0; // if JSWAT_ARGUMENT_ARRAY is ever used (note it'll only ever be used once) int paramNumber = 0; // how many parameters we have int argCount = 0; size_t argData[MAX_ARGS]; #ifndef ARM // cdecl on x86 puts FP args elsewhere! int doubleCount = 0; JsVarFloat doubleData[MAX_ARGS]; #endif // prepend the 'this' link if we need one if (argumentSpecifier&JSWAT_THIS_ARG) argData[argCount++] = (size_t)thisParam; argumentSpecifier = (argumentSpecifier & JSWAT_ARGUMENTS_MASK) >> JSWAT_BITS; // run through all arguments while (argumentSpecifier & JSWAT_MASK) { // Get the parameter data JsVar *param = (paramNumber<paramCount) ? paramData[paramNumber] : (JsVar *)0; paramNumber++; // try and pack it: JsnArgumentType argType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK); #ifdef ARM if (JSWAT_IS_64BIT(argType)) argCount = (argCount+1)&~1; #endif if (argCount > MAX_ARGS - (JSWAT_IS_64BIT(argType)?2:1)) { jsError("INTERNAL: too many arguments for jsnCallFunction"); } switch (argType) { case JSWAT_JSVAR: { // standard variable argData[argCount++] = (size_t)param; break; } case JSWAT_ARGUMENT_ARRAY: { // a JsVar array containing all subsequent arguments argsArray = jsvNewWithFlags(JSV_ARRAY); if (argsArray) { // push everything into the array while (paramNumber<=paramCount) { jsvArrayPush(argsArray, param); param = (paramNumber<paramCount) ? paramData[paramNumber] : 0; paramNumber++; } } // push the array argData[argCount++] = (size_t)argsArray; break; } case JSWAT_BOOL: // boolean argData[argCount++] = jsvGetBool(param); break; case JSWAT_INT32: // 32 bit int argData[argCount++] = (uint32_t)jsvGetInteger(param); break; case JSWAT_PIN: // 16 bit int argData[argCount++] = (uint32_t)jshGetPinFromVar(param); break; case JSWAT_JSVARFLOAT: { // 64 bit float JsVarFloat f = jsvGetFloat(param); #ifdef ARM uint64_t i = *(uint64_t*)&f; #if __WORDSIZE == 64 argData[argCount++] = (size_t)i; #else argData[argCount++] = (size_t)((i) & 0xFFFFFFFF); argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF); #endif #else // jsiConsolePrintf("doubleData, %d, %d\n", doubleCount, (int)f); doubleData[doubleCount++] = f; #endif break; } default: assert(0); break; } // on to next! argumentSpecifier >>= JSWAT_BITS; } uint64_t result; // When args<=4 on ARM, everything is passed in registers (so we try and do this case first) if (argCount<=4) { #ifndef ARM assert(doubleCount<=4); if (doubleCount) { if (returnType==JSWAT_JSVARFLOAT) { // On x86, doubles are returned in a floating point unit register JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]); result = *(uint64_t*)&f; } else { // HERE // jsiConsolePrintf("callFunction: %d, %d, %d\n", JSWAT_IS_64BIT(returnType), function == jswrap_interface_setInterval, (int)doubleData[0]); // if (function == jswrap_interface_setInterval) { // result = (uint32_t)jswrap_interface_setInterval((JsVar *)argData[0], doubleData[0]); // } // else if (JSWAT_IS_64BIT(returnType)) result = ((uint64_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]); else // HERE if (argCount<=2) // ESP8266 fix result = ((uint32_t (*)(size_t,size_t,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],doubleData[0],doubleData[1]); else result = ((uint32_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]); } } else if (returnType==JSWAT_JSVARFLOAT) { // On x86, doubles are returned in a floating point unit register JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]); result = *(uint64_t*)&f; } else #endif { if (JSWAT_IS_64BIT(returnType)) result = ((uint64_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]); else result = ((uint32_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]); } } else { // else it gets tricky... #ifndef ARM assert(doubleCount==0); if (returnType==JSWAT_JSVARFLOAT) { // On x86, doubles are returned in a floating point unit register JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]); result = *(uint64_t*)&f; } else #endif { if (JSWAT_IS_64BIT(returnType)) result = ((uint64_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]); else result = ((uint32_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]); } } jsvUnLock(argsArray); switch (returnType) { case JSWAT_VOID: return 0; case JSWAT_JSVAR: // standard variable case JSWAT_ARGUMENT_ARRAY: // a JsVar array containing all subsequent arguments return (JsVar*)(size_t)result; case JSWAT_BOOL: // boolean return jsvNewFromBool(result!=0); case JSWAT_PIN: return jsvNewFromPin((Pin)result); case JSWAT_INT32: // 32 bit int return jsvNewFromInteger((JsVarInt)result); case JSWAT_JSVARFLOAT: // 64 bit float return jsvNewFromFloat(*(JsVarFloat*)&result); default: assert(0); return 0; } }
/** Call a function with the given argument specifiers */ JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar *thisParam, JsVar **paramData, int paramCount) { /*if(paramCount == 3) { jsiConsolePrintf("param[1] = %d\n",jsvGetInteger(paramData[1])); jsiConsolePrintf("param[2] = %d\n",jsvGetInteger(paramData[2])); jsiConsolePrintf("argType = %d\n",argumentSpecifier); }*/ JsnArgumentType returnType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK); JsVar *argsArray = 0; // if JSWAT_ARGUMENT_ARRAY is ever used (note it'll only ever be used once) int paramNumber = 0; // how many parameters we have int argCount = 0; size_t argData[MAX_ARGS]; #ifndef ARM // cdecl on x86 puts FP args elsewhere! int doubleCount = 0; JsVarFloat doubleData[MAX_ARGS]; #endif // prepend the 'this' link if we need one if (argumentSpecifier&JSWAT_THIS_ARG){ //jsiConsolePrintf("this var\n"); argData[argCount++] = (size_t)thisParam; } argumentSpecifier = (argumentSpecifier & JSWAT_ARGUMENTS_MASK) >> JSWAT_BITS; //jsiConsolePrintf("out while : %d\n",argCount); // run through all arguments while (argumentSpecifier & JSWAT_MASK) { // Get the parameter data JsVar *param = (paramNumber<paramCount) ? paramData[paramNumber] : (JsVar *)0; paramNumber++; // try and pack it: JsnArgumentType argType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK); #ifdef ARM if (JSWAT_IS_64BIT(argType)){ //jsiConsolePrintf("64 bit\n"); argCount = (argCount+1)&~1; } #endif if (argCount > MAX_ARGS - (JSWAT_IS_64BIT(argType)?2:1)) { jsError("INTERNAL: too many arguments for jsnCallFunction"); } //jsiConsolePrintf("in while : %d\n",argCount); switch (argType) { case JSWAT_JSVAR: { // standard variable argData[argCount++] = (size_t)param; //jsiConsolePrintf("111 : %d\n",argCount - 1); break; } case JSWAT_ARGUMENT_ARRAY: { // a JsVar array containing all subsequent arguments argsArray = jsvNewWithFlags(JSV_ARRAY); if (argsArray) { // push everything into the array while (paramNumber<=paramCount) { jsvArrayPush(argsArray, param); param = (paramNumber<paramCount) ? paramData[paramNumber] : 0; paramNumber++; } } // push the array argData[argCount++] = (size_t)argsArray; //jsiConsolePrintf("222 : %d\n",argCount - 1); break; } case JSWAT_BOOL:{ // boolean argData[argCount++] = jsvGetBool(param); //jsiConsolePrintf("666 : %d\n",argCount - 1); break; } case JSWAT_INT32:{ // 32 bit int argData[argCount++] = (uint32_t)jsvGetInteger(param); //jsiConsolePrintf("333 : %d\n",argCount - 1); break; } case JSWAT_PIN:{ // 16 bit int argData[argCount++] = (uint32_t)jshGetPinFromVar(param); //jsiConsolePrintf("444 : %d\n",argCount - 1); break; } case JSWAT_JSVARFLOAT: { // 64 bit float //jsiConsolePrintf("555\n"); JsVarFloat f = jsvGetFloat(param); //jsiConsolePrintf("params[%d] = %f\n",argCount - 1,f); #ifdef ARM uint64_t i = *(uint64_t*)&f; //jsiConsolePrintf("define ARM\n"); #if __WORDSIZE == 64 argData[argCount++] = (size_t)i; //jsiConsolePrintf("1 - params[%d] = %f\n",argCount - 1,argData[argCount - 1]); #else argData[argCount++] = (size_t)((i) & 0xFFFFFFFF); //jsiConsolePrintf("2 - params[%d] = %d\n",argCount - 1,argData[argCount - 1]); argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF); //jsiConsolePrintf("3 - params[%d] = %d\n",argCount - 1,argData[argCount - 1]); #endif #else doubleData[doubleCount++] = f; #endif break; } default: assert(0); break; } // on to next! argumentSpecifier >>= JSWAT_BITS; } //end for while (argumentSpecifier & JSWAT_MASK) //jsiConsolePrintf("native Count = %d\n",argCount - 1); /*for(int i = 0 ; i < argCount; i ++ ){ jsiConsolePrintf("argData[%d] = %d\n",i,argData[i]); }*/ uint64_t result; //jsiConsolePrintf(); // When args<=4 on ARM, everything is passed in registers (so we try and do this case first) if (argCount<=4) { #ifndef ARM assert(doubleCount<=4); if (doubleCount) { if (returnType==JSWAT_JSVARFLOAT) { // On x86, doubles are returned in a floating point unit register //jsiConsolePrintf("111\n"); JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]); result = *(uint64_t*)&f; } else { //jsiConsolePrintf("222\n"); if (JSWAT_IS_64BIT(returnType)){ result = ((uint64_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]); //jsiConsolePrintf("333\n"); } else result = ((uint32_t (*)(size_t,size_t,size_t,size_t,JsVarFloat,JsVarFloat,JsVarFloat,JsVarFloat))function)(argData[0],argData[1],argData[2],argData[3],doubleData[0],doubleData[1],doubleData[2],doubleData[3]); } } else if (returnType==JSWAT_JSVARFLOAT) { // On x86, doubles are returned in a floating point unit register JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]); result = *(uint64_t*)&f; } else #endif { if (JSWAT_IS_64BIT(returnType)) result = ((uint64_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]); else{ //jsiConsolePrintf("real exec!!!\n"); result = ((uint32_t (*)(size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3]); } } } else { // else it gets tricky... #ifndef ARM assert(doubleCount==0); if (returnType==JSWAT_JSVARFLOAT) { // On x86, doubles are returned in a floating point unit register JsVarFloat f = ((JsVarFloat (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]); result = *(uint64_t*)&f; } else #endif { if (JSWAT_IS_64BIT(returnType)) result = ((uint64_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]); else result = ((uint32_t (*)(size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t,size_t))function)(argData[0],argData[1],argData[2],argData[3],argData[4],argData[5],argData[6],argData[7],argData[8],argData[9],argData[10],argData[11]); } } jsvUnLock(argsArray); //jsiConsolePrint("okok\n"); switch (returnType) { case JSWAT_VOID: return 0; case JSWAT_JSVAR: // standard variable case JSWAT_ARGUMENT_ARRAY: // a JsVar array containing all subsequent arguments return (JsVar*)(size_t)result; case JSWAT_BOOL: // boolean return jsvNewFromBool(result!=0); case JSWAT_PIN: return jsvNewFromPin((Pin)result); case JSWAT_INT32: // 32 bit int return jsvNewFromInteger((JsVarInt)result); case JSWAT_JSVARFLOAT: // 64 bit float return jsvNewFromFloat(*(JsVarFloat*)&result); default: assert(0); return 0; } }
/** Call a function with the given argument specifiers */ JsVar *jsnCallFunction(void *function, JsnArgumentType argumentSpecifier, JsVar *thisParam, JsVar **paramData, int paramCount) { #ifndef SAVE_ON_FLASH // Handle common call types quickly: // ------- void(void) if (argumentSpecifier==JSWAT_VOID) { ((void (*)())function)(); return 0; } // ------- JsVar*(void) if (argumentSpecifier==JSWAT_JSVAR) { return ((JsVar *(*)())function)(); } // ------- void('this') if (argumentSpecifier==(JSWAT_VOID | JSWAT_THIS_ARG)) { ((void (*)(JsVar *))function)(thisParam); return 0; } #endif // Now do it the hard way... JsnArgumentType returnType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK); JsVar *argsArray = 0; // if JSWAT_ARGUMENT_ARRAY is ever used (note it'll only ever be used once) int paramNumber = 0; // how many parameters we have int argCount = 0; size_t argData[MAX_ARGS]; #ifdef USE_SEPARATE_DOUBLES int doubleCount = 0; JsVarFloat doubleData[MAX_ARGS]; #endif // prepend the 'this' link if we need one if (argumentSpecifier&JSWAT_THIS_ARG) argData[argCount++] = (size_t)thisParam; argumentSpecifier = (argumentSpecifier & JSWAT_ARGUMENTS_MASK) >> JSWAT_BITS; #ifdef USE_ARG_REORDERING size_t alignedLongsAfter = 0; #endif // run through all arguments while (argumentSpecifier & JSWAT_MASK) { // Get the parameter data JsVar *param = (paramNumber<paramCount) ? paramData[paramNumber] : (JsVar *)0; paramNumber++; // try and pack it: JsnArgumentType argType = (JsnArgumentType)(argumentSpecifier&JSWAT_MASK); #ifdef USE_ARG_REORDERING if (!JSWAT_IS_64BIT(argType) && !(argCount&1)) { argCount += alignedLongsAfter*2; alignedLongsAfter = 0; } #endif if (argCount > MAX_ARGS - (JSWAT_IS_64BIT(argType)?2:1)) { // TODO: can we ever hit this because of JsnArgumentType's restrictions? jsError("INTERNAL: too many arguments for jsnCallFunction"); } switch (argType) { case JSWAT_JSVAR: { // standard variable argData[argCount++] = (size_t)param; break; } case JSWAT_ARGUMENT_ARRAY: { // a JsVar array containing all subsequent arguments argsArray = jsvNewEmptyArray(); if (argsArray) { // push everything into the array while (paramNumber<=paramCount) { jsvArrayPush(argsArray, param); param = (paramNumber<paramCount) ? paramData[paramNumber] : 0; paramNumber++; } } // push the array argData[argCount++] = (size_t)argsArray; break; } case JSWAT_BOOL: // boolean argData[argCount++] = jsvGetBool(param); break; case JSWAT_INT32: // 32 bit int argData[argCount++] = (uint32_t)jsvGetInteger(param); break; case JSWAT_PIN: // 16 bit int argData[argCount++] = (uint32_t)jshGetPinFromVar(param); break; case JSWAT_JSVARFLOAT: { // 64 bit float JsVarFloat f = jsvGetFloat(param); #ifdef USE_SEPARATE_DOUBLES doubleData[doubleCount++] = f; #else uint64_t i = *(uint64_t*)&f; #if USE_64BIT argData[argCount++] = (size_t)i; #else // 32 bit... #ifdef USE_ARG_REORDERING if (argCount&1) { size_t argC = argCount+1; argData[argC++] = (size_t)((i) & 0xFFFFFFFF); argData[argC++] = (size_t)((i>>32) & 0xFFFFFFFF); alignedLongsAfter++; } else { argData[argCount++] = (size_t)((i) & 0xFFFFFFFF); argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF); } #else // no reordering if (argCount&1) argCount++; argData[argCount++] = (size_t)((i) & 0xFFFFFFFF); argData[argCount++] = (size_t)((i>>32) & 0xFFFFFFFF); #endif #endif #endif break; } default: assert(0); break; }