void allocLocal(TypePtr typePtr) { if(typePtr == IntegerTypePtr) pushInteger(0); else if(typePtr == RealTypePtr) pushReal((float)0.0); else if(typePtr == BooleanTypePtr) pushByte(0); else if(typePtr == CharTypePtr) pushByte(0); else switch(typePtr->form) { case FRM_ENUM: pushInteger(0); break; // NOTE: We currently are not supporting sub ranges, until // we really want 'em... // case FRM_SUBRANGE: // allocLocal(typePtr->info.subrange.rangeTypePtr); // break; case FRM_ARRAY: PSTR ptr = (PSTR)ABLStackMallocCallback(typePtr->size); if(!ptr) ABL_Fatal(0, " ABL: Unable to AblStackHeap->malloc local array "); pushAddress((Address)ptr); break; } }
primitiveAioSuspend(void) { sqInt exceptionWatch; sqInt fd; sqInt flags; sqInt readWatch; sqInt writeWatch; if ((nilObject()) == (stackValue(3))) { return primitiveFail(); } fd = stackIntegerValue(3); if (fd < 0) { return primitiveFail(); } exceptionWatch = stackObjectValue(2); readWatch = stackObjectValue(1); writeWatch = stackObjectValue(0); flags = 0; if (exceptionWatch == (trueObject())) { flags = flags | (AIO_X); } if (readWatch == (trueObject())) { flags = flags | (AIO_R); } if (writeWatch == (trueObject())) { flags = flags | (AIO_W); } aioSuspend(fd, flags); pop(5); pushInteger(flags); return 0; }
primitiveAioEnable(void) { static int eventSemaphoreIndices[FD_SETSIZE]; sqInt externalObject; sqInt fd; sqInt flags; sqInt semaIndex; if ((nilObject()) == (stackValue(2))) { return primitiveFail(); } fd = stackIntegerValue(2); if (fd < 0) { return primitiveFail(); } semaIndex = stackIntegerValue(1); eventSemaphoreIndices[semaIndex] = semaIndex; externalObject = stackObjectValue(0); if (externalObject == (trueObject())) { flags = AIO_EXT; } else { flags = 0; } aioEnable(fd, &(eventSemaphoreIndices[semaIndex]), flags); pop(4); pushInteger(semaIndex); return 0; }
primitiveCreateRenderer(void) { // B3DAcceleratorPlugin>>#primitiveCreateRenderer sqInt allowHardware; sqInt allowSoftware; sqInt h; sqInt result; sqInt w; sqInt x; sqInt y; if (!((methodArgumentCount()) == 6)) { return primitiveFail(); } h = stackIntegerValue(0); w = stackIntegerValue(1); y = stackIntegerValue(2); x = stackIntegerValue(3); allowHardware = booleanValueOf(stackValue(4)); allowSoftware = booleanValueOf(stackValue(5)); if (failed()) { return null; } result = b3dxCreateRenderer(allowSoftware, allowHardware, x, y, w, h); if (result < 0) { return primitiveFail(); } pop(7); return pushInteger(result); }
primitiveCreateRendererFlags(void) { // B3DAcceleratorPlugin>>#primitiveCreateRendererFlags sqInt flags; sqInt h; sqInt result; sqInt w; sqInt x; sqInt y; if (!((methodArgumentCount()) == 5)) { return primitiveFail(); } h = stackIntegerValue(0); w = stackIntegerValue(1); y = stackIntegerValue(2); x = stackIntegerValue(3); flags = stackIntegerValue(4); if (failed()) { return null; } result = b3dxCreateRendererFlags(x, y, w, h, flags); if (result < 0) { return primitiveFail(); } pop(6); return pushInteger(result); }
primitiveOSFileHandle(void) { sqInt fileNo; sqInt sqFileOop; sqFileOop = stackValue(0); if (!((((isBytes(sqFileOop)) && ((byteSizeOf(sqFileOop)) == (sizeof(SQFile)))) && ((getThisSessionID()) == (sessionIdentifierFromSqFile(arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { return primitiveFail(); } /* begin fileDescriptorFrom: */ if (!((((isBytes(sqFileOop)) && ((byteSizeOf(sqFileOop)) == (sizeof(SQFile)))) && ((getThisSessionID()) == (sessionIdentifierFromSqFile(arrayValueOf(sqFileOop))))) && (isNonNullSQFile(sqFileOop)))) { fileNo = -1; goto l1; } fileNo = fileno(fileHandleFrom(sqFileOop)); l1: /* end fileDescriptorFrom: */; pop(2); pushInteger(fileNo); return 0; }
primitiveAllocateTexture(void) { // B3DAcceleratorPlugin>>#primitiveAllocateTexture sqInt d; sqInt h; sqInt renderer; sqInt result; sqInt w; if (!((methodArgumentCount()) == 4)) { return primitiveFail(); } h = stackIntegerValue(0); w = stackIntegerValue(1); d = stackIntegerValue(2); renderer = stackIntegerValue(3); if (failed()) { return null; } result = b3dxAllocateTexture(renderer, w, h, d); if (result == -1) { return primitiveFail(); } pop(5); return pushInteger(result); }
TypePtr execConstant(SymTableNodePtr idPtr) { TypePtr typePtr = idPtr->typePtr; if ((typePtr == IntegerTypePtr) || (typePtr->form == FRM_ENUM)) pushInteger(idPtr->defn.info.constant.value.integer); else if (typePtr == RealTypePtr) pushReal(idPtr->defn.info.constant.value.real); else if (typePtr == CharTypePtr) pushInteger(idPtr->defn.info.constant.value.character); else if (typePtr->form == FRM_ARRAY) pushAddress(idPtr->defn.info.constant.value.stringPtr); if (debugger) debugger->traceDataFetch(idPtr, typePtr, tos); getCodeToken(); return (typePtr); }
primitiveHashArray(void) { // FloatArrayPlugin>>#primitiveHashArray sqInt i; sqInt length; sqInt rcvr; int *rcvrPtr; sqInt result; rcvr = stackObjectValue(0); if (failed()) { return null; } success(isWords(rcvr)); if (failed()) { return null; } length = stSizeOf(rcvr); rcvrPtr = ((int *) (firstIndexableField(rcvr))); result = 0; for (i = 0; i <= (length - 1); i += 1) { result += rcvrPtr[i]; } pop(1); return pushInteger(result & 536870911); }
primPCREExec(void) { sqInt extraObj; sqInt length; int *matchSpacePtr; sqInt matchSpaceSize; sqInt result; char *searchBuffer; sqInt searchObject; /* Load Parameters */ searchObject = stackObjectValue(0); searchBuffer = arrayValueOf(searchObject); length = byteSizeOf(searchObject); /* begin loadRcvrFromStackAt: */ rcvr = stackObjectValue(1); pcrePtr = ((sqInt) (fetchArrayofObject(2, rcvr))); /* begin rcvrExtraPtr */ extraObj = fetchPointerofObject(3, rcvr); extraPtr = ((sqInt) ((!(extraObj == (nilObject())) ? arrayValueOf(extraObj) : 0))); matchFlags = fetchIntegerofObject(6, rcvr); matchSpacePtr = ((int *) (fetchArrayofObject(7, rcvr))); matchSpaceSize = (byteSizeOf(fetchPointerofObject(7, rcvr))) / 4; if (failed()) { return null; } result = pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, 0, matchFlags, matchSpacePtr, matchSpaceSize); pop(2); pushInteger(result); return 0; }
primitiveRendererVersion(void) { // B3DAcceleratorPlugin>>#primitiveRendererVersion if (!((methodArgumentCount()) == 0)) { return primitiveFail(); } pop(1); return pushInteger(1); }
primPCRENumSubPatterns(void) { sqInt ncap; /* begin loadRcvrFromStackAt: */ rcvr = stackObjectValue(0); pcrePtr = ((sqInt) (fetchArrayofObject(2, rcvr))); pcre_fullinfo((const pcre *)pcrePtr, NULL, PCRE_INFO_CAPTURECOUNT, &ncap); pop(1); pushInteger(ncap); return 0; }
primitiveSetVerboseLevel(void) { // B3DAcceleratorPlugin>>#primitiveSetVerboseLevel sqInt level; sqInt result; if (!((methodArgumentCount()) == 1)) { return primitiveFail(); } level = stackIntegerValue(0); result = b3dxSetVerboseLevel(level); pop(2); return pushInteger(result); }
primPCREExecfromto(void) { sqInt extraObj; sqInt fromInteger; sqInt length; int *matchSpacePtr; sqInt matchSpaceSize; sqInt result; char *searchBuffer; sqInt searchObject; sqInt toInteger; /* Load Parameters */ toInteger = stackIntegerValue(0); fromInteger = stackIntegerValue(1); searchObject = stackObjectValue(2); searchBuffer = arrayValueOf(searchObject); length = byteSizeOf(searchObject); /* begin loadRcvrFromStackAt: */ rcvr = stackObjectValue(3); success(1 <= fromInteger); success(toInteger <= length); /* Smalltalk offsets are 1-based */ fromInteger -= 1; success(fromInteger <= toInteger); length = toInteger - fromInteger; /* Load Instance Variables */ searchBuffer += fromInteger; pcrePtr = ((sqInt) (fetchArrayofObject(2, rcvr))); /* begin rcvrExtraPtr */ extraObj = fetchPointerofObject(3, rcvr); extraPtr = ((sqInt) ((!(extraObj == (nilObject())) ? arrayValueOf(extraObj) : 0))); matchFlags = fetchIntegerofObject(6, rcvr); matchSpacePtr = ((int *) (fetchArrayofObject(7, rcvr))); matchSpaceSize = (byteSizeOf(fetchPointerofObject(7, rcvr))) / 4; if (failed()) { return null; } result = pcre_exec((pcre *)pcrePtr, (pcre_extra *)extraPtr, searchBuffer, length, 0, matchFlags, matchSpacePtr, matchSpaceSize); pop(4); pushInteger(result); return 0; }
std::string LuaInterface::traceback(const std::string& errorMessage, int level) { // gets debug.traceback getGlobal("debug"); getField("traceback"); remove(-2); // remove debug // calls debug.traceback(errorMessage, level) pushString(errorMessage); pushInteger(level); call(2,1); // returns the traceback message return popString(); }
primitiveCreate(void) { sqInt handle; if (!((methodArgumentCount()) == 0)) { return primitiveFail(); } handle = sqCreateSSL(); if (handle == 0) { return primitiveFail(); } pop((methodArgumentCount()) + 1); pushInteger(handle); return 0; }
primitiveAioDisable(void) { sqInt fd; if ((nilObject()) == (stackValue(0))) { return primitiveFail(); } fd = stackIntegerValue(0); if (fd < 0) { return primitiveFail(); } aioDisable(fd); pop(2); pushInteger(fd); return 0; }
primitiveGetIntProperty(void) { // B3DAcceleratorPlugin>>#primitiveGetIntProperty sqInt handle; sqInt prop; sqInt result; if (!((methodArgumentCount()) == 2)) { return primitiveFail(); } prop = stackIntegerValue(0); handle = stackIntegerValue(1); result = b3dxGetIntProperty(handle, prop); pop(3); return pushInteger(result); }
//*************************************************************************** void pushStackFrameHeader(int32_t oldLevel, int32_t newLevel) { //----------------------------------- // Make space for the return value... pushInteger(0); StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr; //---------------------------------------------------------------------- // STATIC LINK // Currently, let's not allow functions defined within functions. Assume // the old scope level equals the new scope level, for now. if(newLevel == -1) { //-------------------------------------------------------------------- // Calling a library function, so push a nullptr static link since // it's scope is in a different module than the calling function. // Note that global variables in libraries should be STATIC, otherwise // they're never in scope! Weird "feature" which we may want // to fix later... pushAddress(nullptr); } else if(newLevel == oldLevel + 1) { //---------------------------------------------------------------- // Calling a routine nested within the caller, so push the pointer // to the caller's stack frame. In ABL, as currently defined // (2/22/96), this should only be when a module's code section is // calling a function... pushAddress((Address)headerPtr); } else if(newLevel == oldLevel) { //--------------------------------------------------------------- // Calling a function at the same scope level. We like that! Push // pointer to stack frame of their common parent... pushAddress(headerPtr->staticLink.address); } else { //------------------------------------------------------- // Oops. We don't want nested functions, for now, in ABL. runtimeError(ABL_ERR_RUNTIME_NESTED_FUNCTION_CALL); } pushAddress((Address)stackFrameBasePtr); //--------------------------- // Push the return address... pushAddress(0); }
primitiveOSSocketHandle(void) { int fileNo; sqInt sqSocketOop; sqSocketOop = stackValue(0); if (!(((isBytes(sqSocketOop)) && ((byteSizeOf(sqSocketOop)) == (sizeof(SQSocket)))) && (!(isNullSQSocket(sqSocketOop))))) { return primitiveFail(); } fileNo = socketDescriptorFrom(sqSocketOop); if (fileNo < 0) { return primitiveFail(); } pop(2); pushInteger(fileNo); return 0; }
primitiveEncrypt(void) { sqInt dstLen; sqInt dstOop; char *dstPtr; sqInt handle; sqInt result; sqInt srcLen; sqInt srcOop; char *srcPtr; sqInt start; if (!((methodArgumentCount()) == 5)) { return primitiveFail(); } dstOop = stackObjectValue(0); srcLen = stackIntegerValue(1); start = stackIntegerValue(2); srcOop = stackObjectValue(3); handle = stackIntegerValue(4); if (failed()) { return null; } if (!(((start > 0) && (srcLen >= 0)) && ((isBytes(srcOop)) && ((isBytes(dstOop)) && ((byteSizeOf(srcOop)) >= ((start + srcLen) - 1)))))) { return primitiveFail(); } srcPtr = firstIndexableField(srcOop); dstPtr = firstIndexableField(dstOop); srcPtr = (srcPtr + start) - 1; dstLen = byteSizeOf(dstOop); result = sqEncryptSSL(handle, srcPtr, srcLen, dstPtr, dstLen); if (failed()) { return null; } pop((methodArgumentCount()) + 1); pushInteger(result); return 0; }
primitiveGetRendererSurfaceWidth(void) { // B3DAcceleratorPlugin>>#primitiveGetRendererSurfaceWidth sqInt handle; sqInt result; if (!((methodArgumentCount()) == 1)) { return primitiveFail(); } handle = stackIntegerValue(0); if (failed()) { return null; } result = b3dxGetRendererSurfaceWidth(handle); if (result < 0) { return primitiveFail(); } pop(2); return pushInteger(result); }
primitiveHashArray(void) { sqInt i; sqInt length; sqInt rcvr; int *rcvrPtr; sqInt result; rcvr = stackValue(0); if (!(isWords(rcvr))) { return primitiveFail(); } length = stSizeOf(rcvr); rcvrPtr = ((int *) (firstIndexableField(rcvr))); result = 0; for (i = 0; i < length; i += 1) { result += rcvrPtr[i]; } pop(1); return pushInteger(result & 0x1FFFFFFF); }
primitiveTextureSurfaceHandle(void) { // B3DAcceleratorPlugin>>#primitiveTextureSurfaceHandle sqInt handle; sqInt renderer; sqInt result; if (!((methodArgumentCount()) == 2)) { return primitiveFail(); } handle = stackIntegerValue(0); renderer = stackIntegerValue(1); if (failed()) { return null; } result = b3dxTextureSurfaceHandle(renderer, handle); if (result < 0) { return primitiveFail(); } pop(3); return pushInteger(result); }
primLastAlloc(void) { pop(1); pushInteger(lastAlloc); return 0; }
TypePtr execDeclaredRoutineCall(SymTableNodePtr routineIdPtr, bool skipOrder) { if(skipOrder) { StackItemPtr curStackFrameBase = tos; //---------------------------------------- // Push parameter values onto the stack... getCodeToken(); if(codeToken == TKN_LPAREN) { execActualParams(routineIdPtr); getCodeToken(); } getCodeToken(); tos = curStackFrameBase; pushInteger(1); return((TypePtr)(routineIdPtr->typePtr)); } int32_t oldLevel = level; // level of caller int32_t newLevel = routineIdPtr->level + 1; // level of callee CallStackLevel++; //------------------------------------------- // First, set up the stack frame of callee... StackItemPtr newStackFrameBasePtr = tos + 1; bool isLibraryCall = (routineIdPtr->library && (routineIdPtr->library != CurRoutineIdPtr->library)); if(isLibraryCall) pushStackFrameHeader(-1, -1); else pushStackFrameHeader(oldLevel, newLevel); //---------------------------------------- // Push parameter values onto the stack... getCodeToken(); if(codeToken == TKN_LPAREN) { execActualParams(routineIdPtr); getCodeToken(); } //------------------------------------------------- // Set the return address in the new stack frame... level = newLevel; stackFrameBasePtr = newStackFrameBasePtr; StackFrameHeaderPtr headerPtr = (StackFrameHeaderPtr)stackFrameBasePtr; headerPtr->returnAddress.address = codeSegmentPtr - 1; //--------------------------------------------------------- // If we're calling a library function, we need to set some // module-specific info... ABLModulePtr PrevModule = nullptr; if(isLibraryCall) { PrevModule = CurModule; CurModule = routineIdPtr->library; CurModuleHandle = CurModule->getHandle(); if(debugger) debugger->setModule(CurModule); StaticDataPtr = CurModule->getStaticData(); CallModuleInit = !CurModule->getInitCalled(); CurModule->setInitCalled(true); // routineEntry(ModuleRegistry[CurModule->getHandle()].moduleIdPtr); } if(ProfileLog) { int32_t functionStartTime = ABLGetTimeCallback(); execute(routineIdPtr); int32_t functionExecTime = ABLGetTimeCallback() - functionStartTime; if(functionExecTime > ProfileLogFunctionTimeLimit) { char s[512]; sprintf_s(s, _countof(s), "[%08d] ", NumExecutions); for(size_t i = 0; i < CallStackLevel; i++) strcat(s, " "); char s1[512]; sprintf_s(s1, _countof(s1), "%s (%d)\n", routineIdPtr->name, functionExecTime); strcat(s, s1); ABL_AddToProfileLog(s); } } else execute(routineIdPtr); //---------------------------------------------------------------- // If we're calling a library function, reset some module-specific // info... if(isLibraryCall) { // routineExit(ModuleRegistry[CurModule->getHandle()].moduleIdPtr); CurModule = PrevModule; CurModuleHandle = CurModule->getHandle(); if(debugger) debugger->setModule(CurModule); StaticDataPtr = CurModule->getStaticData(); } //------------------------------------------------------- // Return from the callee, and grab the first token after // the return... level = oldLevel; getCodeToken(); CallStackLevel--; return((TypePtr)(routineIdPtr->typePtr)); }
int32_t ABLModule::execute(ABLParamPtr moduleParamList, SymTableNodePtr functionIdPtr) { CurModule = this; if(debugger) debugger->setModule(this); //-------------------------- // Execute the ABL module... SymTableNodePtr moduleIdPtr = ModuleRegistry[handle].moduleIdPtr; if(moduleIdPtr->defn.info.routine.flags & ROUTINE_FLAG_FSM) CurFSM = this; else CurFSM = nullptr; NumStateTransitions = 0; //-------------------------------------------- // Point to this module's static data space... StaticDataPtr = staticData; OrderCompletionFlags = orderCallFlags; //--------------------------------- // Init some important variables... CurModuleIdPtr = nullptr; CurRoutineIdPtr = nullptr; FileNumber = -1; errorCount = 0; execStatementCount = 0; NumExecutions++; NewStateSet = false; //------------------ // Init the stack... stackFrameBasePtr = tos = (stack + eternalOffset); //--------------------------------------- // Initialize the module's stack frame... level = 1; CallStackLevel = 0; stackFrameBasePtr = tos + 1; //------------------------- // Function return value... pushInteger(0); //--------------- // Static Link... pushAddress(nullptr); //---------------- // Dynamic Link... pushAddress(nullptr); //------------------ // Return Address... pushAddress(nullptr); //initDebugger(); //---------- // Run it... if(moduleParamList) { //------------------------------------------------------------------------------ // NOTE: Currently, parameter passing of arrays is not functioning. This MUST be // done... int32_t curParam = 0; for(SymTableNodePtr formalIdPtr = (SymTableNodePtr)(moduleIdPtr->defn.info.routine.params); formalIdPtr != nullptr; formalIdPtr = formalIdPtr->next) { TypePtr formalTypePtr = (TypePtr)(formalIdPtr->typePtr); if(formalIdPtr->defn.key == DFN_VALPARAM) { if(formalTypePtr == RealTypePtr) { if(moduleParamList[curParam].type == ABL_PARAM_INTEGER) { //--------------------------------------------- // Real formal parameter, but integer actual... pushReal((float)(moduleParamList[curParam].integer)); } else if(moduleParamList[curParam].type == ABL_PARAM_REAL) pushReal(moduleParamList[curParam].real); } else if(formalTypePtr == IntegerTypePtr) { if(moduleParamList[curParam].type == ABL_PARAM_INTEGER) pushInteger(moduleParamList[curParam].integer); else return(0); } //---------------------------------------------------------- // Formal parameter is an array or record, so make a copy... if((formalTypePtr->form == FRM_ARRAY)/* || (formalTypePtr->form == FRM_RECORD)*/) { //------------------------------------------------------------------------------ // The following is a little inefficient, but is kept this way to keep it clear. // Once it's verified to work, optimize... int32_t size = formalTypePtr->size; PSTR dest = (PSTR)ABLStackMallocCallback((size_t)size); if(!dest) { char err[255]; sprintf(err, "ABL: Unable to AblStackHeap->malloc array parameter [Module %d]", id); ABL_Fatal(0, err); } PSTR src = tos->address; PSTR savePtr = dest; memcpy(dest, src, size); tos->address = savePtr; } } else { //------------------------------- // pass by reference parameter... if(formalTypePtr == RealTypePtr) pushAddress((Address) & (moduleParamList[curParam].real)); else if(formalTypePtr == IntegerTypePtr) pushAddress((Address) & (moduleParamList[curParam].integer)); else return(0); } curParam++; } } CurModuleHandle = handle; CallModuleInit = !initCalled; initCalled = true; ::executeChild(moduleIdPtr, functionIdPtr); memcpy(&returnVal, &returnValue, sizeof(StackItem)); //----------- // Summary... return(execStatementCount); }
primNetMemory(void) { pop(1); pushInteger(netMemory); return 0; }
primNumAllocs(void) { pop(1); pushInteger(numAllocs); return 0; }
primNumFrees(void) { pop(1); pushInteger(numFrees); return 0; }