bool gmCodeGenPrivate::GenDeclVariable(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode) { GM_ASSERT(a_node->m_type == CTNT_DECLARATION && a_node->m_subType == CTNDT_VARIABLE); GM_ASSERT(m_currentFunction); m_currentFunction->SetVariableType(a_node->m_children[0]->m_data.m_string, (gmCodeTreeVariableType) a_node->m_subTypeType); return true; }
void gmGCColorSet::DestructAll() { int count = 0; DestructPersistantObjects(); // Black and Gray gmGCObjBase* curGrayOrBlack = m_gray->GetNext(); while(curGrayOrBlack != m_free) { gmGCObjBase* objToRecycle = curGrayOrBlack; curGrayOrBlack = curGrayOrBlack->GetNext(); #if GM_GC_KEEP_PERSISTANT_SEPARATE GM_ASSERT(!objToRecycle->GetPersist()); #endif //GM_GC_KEEP_PERSISTANT_SEPARATE objToRecycle->Destruct(m_gc->GetVM()); #if GM_GC_STATS --m_numAllocated; #endif //GM_GC_STATS ++count; } // Whites gmGCObjBase* curWhite = m_white->GetNext(); while(curWhite != m_tail) { gmGCObjBase* objToRecycle = curWhite; curWhite = curWhite->GetNext(); #if GM_GC_KEEP_PERSISTANT_SEPARATE GM_ASSERT(!objToRecycle->GetPersist()); #endif //GM_GC_KEEP_PERSISTANT_SEPARATE objToRecycle->Destruct(m_gc->GetVM()); #if GM_GC_STATS --m_numAllocated; #endif //GM_GC_STATS ++count; } // Free list gmGCObjBase* curFree = m_free; while(curFree != m_white) { gmGCObjBase* objToRecycle = curFree; curFree = curFree->GetNext(); { #if GM_GC_KEEP_PERSISTANT_SEPARATE GM_ASSERT(!objToRecycle->GetPersist()); #endif //GM_GC_KEEP_PERSISTANT_SEPARATE objToRecycle->Destruct(m_gc->GetVM()); #if GM_GC_STATS --m_numAllocated; #endif //GM_GC_STATS ++count; } } Init(m_gc); }
void ScriptSys::SetTableGameObj(const char* a_memberName, GameObj* a_gameObj, gmTableObject* a_table) { GM_ASSERT(a_table); GM_ASSERT(a_gameObj); gmTableObject* table = a_table; gmVariable newVar; newVar.SetUser(a_gameObj->GetScriptObj()->GetUserObject()); table->Set(m_machine, a_memberName, newVar); }
int gmGCColorSet::DestructSomeFreeObjects(int a_maxToDestruct) { int numDestructed = 0; // Go through the free list (perhaps over multiple installments in future) and call Destruct() on them. if(m_free != m_white) { gmGCObjBase* beforeFree = m_free->GetPrev(); // Save previous node so we can relink after removing some bool fixScan = false; if(m_scan == m_free) // Will need to fix the scan ptr later if this is so. { fixScan = true; } while(m_free != m_white) { gmGCObjBase* objToRecycle = m_free; m_free = m_free->GetNext(); #if GM_GC_DEBUG //GM_ASSERT(objToRecycle->m_curPosColor == GM_GC_DEBUG_COL_WHITE); GM_ASSERT(objToRecycle->m_curPosColor == GM_GC_DEBUG_COL_FREE); objToRecycle->m_curPosColor = GM_GC_DEBUG_COL_INVALID; #endif //GM_GC_DEBUG #if GM_GC_KEEP_PERSISTANT_SEPARATE GM_ASSERT(!objToRecycle->GetPersist()); #endif //GM_GC_KEEP_PERSISTANT_SEPARATE #if GM_GC_STATS --m_numAllocated; #endif //GM_GC_STATS objToRecycle->Destruct(m_gc->GetVM()); ++numDestructed; --a_maxToDestruct; if(a_maxToDestruct <= 0) { // Relink since we removed elements beforeFree->SetNext(m_free); m_free->SetPrev(beforeFree); if(fixScan) { m_scan = m_free; } return numDestructed; // Work is done for now. } } // Relink since we removed elements beforeFree->SetNext(m_free); m_free->SetPrev(beforeFree); if(fixScan) { m_scan = m_free; } } return numDestructed; }
static void GM_CDECL gmFileInfoOpGetDot(gmThread * a_thread, gmVariable * a_operands) { gmUserObject * user = (gmUserObject *) GM_OBJECT(a_operands->m_value.m_ref); if(user && user->m_user) { gmFileInfoUser * fileInfo = (gmFileInfoUser *) user->m_user; gmStringObject * member = (gmStringObject *) GM_OBJECT(a_operands[1].m_value.m_ref); GM_ASSERT(sizeof(fileInfo->m_creationTime) <= sizeof(gmint)); // NOTE: Not valid or tested for 64bit target if(strcmp(member->GetString(), "creationTime") == 0) a_operands->SetInt((gmint) fileInfo->m_creationTime); else if(strcmp(member->GetString(), "accessedTime") == 0) a_operands->SetInt((gmint) fileInfo->m_accessedTime); else if(strcmp(member->GetString(), "modifiedTime") == 0) a_operands->SetInt((gmint) fileInfo->m_modifiedTime); else if(strcmp(member->GetString(), "size") == 0) a_operands->SetInt((gmint) fileInfo->m_size); else { a_operands->Nullify(); return; } return; } a_operands->Nullify(); }
static int GM_CDECL gmfTime(gmThread * a_thread) { #ifdef IS64BIT // Compatible with 64bit OS __time32_t t; _time32(&t); GM_ASSERT(sizeof(t) <= sizeof(gmint)); a_thread->PushInt(t); return GM_OK; #else time_t t; time(&t); GM_ASSERT(sizeof(time_t) <= sizeof(gmptr)); a_thread->PushInt(t); return GM_OK; #endif }
static int GM_CDECL gmfSystem(gmThread * a_thread) { const int bufferSize = 256; int len = 0, size = 0, i, ret = -1; char * str = NULL, buffer[bufferSize]; // build the string for(i = 0; i < a_thread->GetNumParams(); ++i) { gmConcat(a_thread->GetMachine(), str, len, size, a_thread->Param(i).AsString(a_thread->GetMachine(), buffer, bufferSize), 64); if(str) { GM_ASSERT(len < size); str[len++] = ' '; str[len] = '\0'; } } // print the string if(str) { ret = system(str); a_thread->GetMachine()->Sys_Free(str); } a_thread->PushInt(ret); return GM_OK; }
static int GM_CDECL gmfFileSeek(gmThread * a_thread) // return false on error { gmUserObject * fileObject = a_thread->ThisUserObject(); GM_ASSERT(fileObject->m_userType == s_gmFileType); GM_CHECK_NUM_PARAMS(2); GM_CHECK_INT_PARAM(offset, 0); GM_CHECK_INT_PARAM(origin, 1); if( origin != SEEK_CUR && origin != SEEK_END && origin != SEEK_SET ) { return GM_EXCEPTION; } int result = fseek((FILE*)fileObject->m_user, offset, origin); if(result != 0) { a_thread->PushInt(false); } a_thread->PushInt(true); return GM_OK; }
static int GM_CDECL gmfFileIsOpen(gmThread * a_thread) // return 1 if open, else 0 { gmUserObject * fileObject = a_thread->ThisUserObject(); GM_ASSERT(fileObject->m_userType == s_gmFileType); a_thread->PushInt((fileObject->m_user) ? 1 : 0); return GM_OK; }
bool ScriptSys::ExecuteFile(const char* a_fileName) { FILE* scriptFile = NULL; char* fileString = NULL; int fileSize = 0; GM_ASSERT(m_machine); if( !(scriptFile = fopen(a_fileName, "rb")) ) { return false; } fseek(scriptFile, 0, SEEK_END); fileSize = ftell(scriptFile); fseek(scriptFile, 0, SEEK_SET); fileString = new char [fileSize+1]; fread(fileString, fileSize, 1, scriptFile); fileString[fileSize] = 0; // Terminating null fclose(scriptFile); int threadId = GM_INVALID_THREAD; int errors = m_machine->ExecuteString(fileString, &threadId, true, a_fileName); if(errors) { LogAnyMachineErrorMessages(); } delete [] fileString; return true; }
static int GM_CDECL gmfStringSpanExcluding(gmThread * a_thread) { GM_CHECK_NUM_PARAMS(1); if(a_thread->ParamType(0) == GM_STRING) { const gmVariable * var = a_thread->GetThis(); GM_ASSERT(var->m_type == GM_STRING); gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref); const char * thisStr = (const char *) *strObj; const char * otherStr = a_thread->ParamString(0); int offset = strcspn(thisStr, otherStr); char * buffer = (char *) alloca(offset + 1); memcpy(buffer, thisStr, offset); buffer[offset] = 0; a_thread->PushNewString(buffer, offset); return GM_OK; } return GM_EXCEPTION; }
static int GM_CDECL gmStringTrimRight(gmThread * a_thread) { GM_STRING_PARAM(trim, 0, GM_WHITE_SPACE); const gmVariable * var = a_thread->GetThis(); GM_ASSERT(var->m_type == GM_STRING); gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref); const char * str = (const char *) *strObj; int strLength = strObj->GetLength(); if(strLength > 0) { char * buffer = (char *) alloca(strLength + 1); memcpy(buffer, str, strLength + 1); //Copy old string // Find beginning of trailing matches by starting at end char *lpsz = buffer + strLength; while (--lpsz >= buffer && strchr(trim, *lpsz) != NULL) {} ++lpsz; *lpsz = '\0'; a_thread->PushNewString(buffer); } else { a_thread->PushString(strObj); } return GM_OK; }
bool gmThread::Touch(int a_extra) { // Grow stack if necessary. NOTE: Use better growth metric if needed. bool reAlloc = false; while((m_top + a_extra + GMTHREAD_SLACKSPACE) >= m_size) { if(sizeof(gmVariable) * m_size > GMTHREAD_MAXBYTESIZE) { GM_ASSERT(!"GMTHREAD_MAXBYTESIZE exceeded"); return false; } m_size *= 2; reAlloc = true; } if(reAlloc) { gmVariable * stack = new gmVariable[m_size]; //memset(stack, 0, sizeof(gmVariable) * m_size); memcpy(stack, m_stack, m_top * sizeof(gmVariable)); if(m_stack) delete[] m_stack; m_stack = stack; } return true; }
bool gmCodeGenPrivate::GenStmtIf(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode) { GM_ASSERT(a_node->m_type == CTNT_STATEMENT && a_node->m_subType == CTNST_IF); unsigned int loc1, loc2, loc3; if(a_node->m_children[2]) // Is this an if-else, or just an if { if(!Generate(a_node->m_children[0], a_byteCode)) return false; loc1 = a_byteCode->Skip(SIZEOF_BC_BRA); if(!Generate(a_node->m_children[1], a_byteCode)) return false; loc2 = a_byteCode->Skip(SIZEOF_BC_BRA); if(!Generate(a_node->m_children[2], a_byteCode)) return false; loc3 = a_byteCode->Seek(loc1); a_byteCode->EmitPtr(BC_BRZ, loc2+SIZEOF_BC_BRA); a_byteCode->Seek(loc2); a_byteCode->EmitPtr(BC_BRA, loc3); a_byteCode->Seek(loc3); } else { if(!Generate(a_node->m_children[0], a_byteCode)) return false; loc1 = a_byteCode->Skip(SIZEOF_BC_BRA); if(!Generate(a_node->m_children[1], a_byteCode)) return false; loc2 = a_byteCode->Seek(loc1); m_currentFunction->m_currentLine = a_node->m_lineNumber; a_byteCode->EmitPtr(BC_BRZ, loc2); a_byteCode->Seek(loc2); } return true; }
void gmGCColorSet::Allocate(gmGCObjBase* a_obj) { #if GM_GC_STATS ++m_numAllocated; #endif //GM_GC_STATS a_obj->SetPersist(false); a_obj->SetColor(m_gc->GetCurShadeColor()); #if GM_GC_DEBUG GM_ASSERT(a_obj->m_curPosColor == GM_GC_DEBUG_COL_INVALID); a_obj->m_curPosColor = GM_GC_DEBUG_COL_BLACK; #endif //GM_GC_DEBUG //Insert at the end of black list a_obj->SetNext(m_free); //Next is first Free a_obj->SetPrev(m_free->GetPrev()); //Prev is last Black m_free->GetPrev()->SetNext(a_obj); //Last Black next is now this m_free->SetPrev(a_obj); //Free prev is now this //If there were no blacks, move scan forward to prevent scanning this new black if(m_scan == m_free) { m_scan = a_obj; } }
bool gmGCColorSet::BlackenNextGray(int& a_workDone, int a_workLeftToGo) { if(m_gc->GetTraceState().m_done == true) { if(m_scan->GetPrev() == m_gray) // No grays to blacken. { a_workDone = 0; return false; } else { m_scan = m_scan->GetPrev(); m_gc->GetTraceState().m_object = m_scan; #if GM_GC_DEBUG GM_ASSERT(m_scan->m_curPosColor == GM_GC_DEBUG_COL_GRAY); m_scan->m_curPosColor = GM_GC_DEBUG_COL_BLACK; #endif //GM_GC_DEBUG a_workDone = FollowPointers(a_workLeftToGo); return true; // Gray was blackened } } else { // Resume previously interrupted scanning of an object a_workDone = FollowPointers(a_workLeftToGo); return true; } }
static int GM_CDECL gmStringGetPath(gmThread * a_thread) { GM_INT_PARAM(keepSlash, 0, 0); const gmVariable * var = a_thread->GetThis(); GM_ASSERT(var->m_type == GM_STRING); gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref); const char * str = (const char *) *strObj; int strLength = strObj->GetLength(); char * buffer = (char *) alloca(strLength + 1); memcpy(buffer, str, strLength + 1); //Copy old string char *lpsz = buffer + strLength; while (--lpsz >= buffer && *lpsz != '\\' && *lpsz != '/') {} if(*lpsz == '\\' || *lpsz == '/') { if(keepSlash) lpsz[1] = 0; else lpsz[0] = 0; a_thread->PushNewString(buffer); } else { a_thread->PushNewString(""); } return GM_OK; }
static int GM_CDECL gmStringGetExtension(gmThread * a_thread) { GM_INT_PARAM(keepDot, 0, 0); const gmVariable * var = a_thread->GetThis(); GM_ASSERT(var->m_type == GM_STRING); gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref); const char * str = (const char *) *strObj; int strLength = strObj->GetLength(); const char *lpsz = str + strLength; while (--lpsz >= str && *lpsz != '.') {} if(*lpsz == '.') { if(!keepDot) { ++lpsz; } a_thread->PushNewString(lpsz); } else { a_thread->PushNewString(""); } return GM_OK; }
bool gmGCColorSet::VerifyIntegrity() { // Scan through list make sure all pointers are in valid positions and all objects are colored correctly gmGCObjBase* curObj = m_gray->GetNext(); int curCol = GM_GC_DEBUG_COL_GRAY; while(curObj != m_tail) { if(curObj == m_scan) { curCol = GM_GC_DEBUG_COL_BLACK; } if(curObj == m_free) { curCol = GM_GC_DEBUG_COL_FREE; } if(curObj == m_white) { curCol = GM_GC_DEBUG_COL_WHITE; } if(curObj != &m_separatorObject) { GM_ASSERT(curObj->m_curPosColor == curCol); } curObj = curObj->GetNext(); } return true; }
// string string.SetAt(int a_index, int a_char); // Returns string with modified character at offset, or original string if index out of range. static int GM_CDECL gmStringSetAt(gmThread * a_thread) { GM_CHECK_NUM_PARAMS(1); GM_CHECK_INT_PARAM(index, 0); GM_CHECK_INT_PARAM(newChar, 1); const gmVariable * var = a_thread->GetThis(); GM_ASSERT(var->m_type == GM_STRING); gmStringObject * strObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref); const char * str = (const char *) *strObj; int strLength = strObj->GetLength(); if(index < 0 || index >= strLength) { a_thread->PushString(strObj); //Return original string if index out of range return GM_OK; } char * buffer = (char *) alloca(strLength + 1); memcpy(buffer, str, strLength + 1); //Copy old string buffer[index] = (char)newChar; //Set character in string a_thread->PushNewString(buffer, strLength); return GM_OK; }
bool gmCodeGenPrivate::GenStmtFork(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode) { GM_ASSERT(a_node->m_type == CTNT_STATEMENT && a_node->m_subType == CTNST_FORK ); gmuint32 loc1,loc2; // create the var for the thread id const char * valname = 0; gmuint32 valref = 0; if ( a_node->m_children[1]) { valname = a_node->m_children[1]->m_data.m_string; valref = m_currentFunction->SetVariableType( valname, CTVT_LOCAL ); } loc1 = a_byteCode->Skip( SIZEOF_BC_BRA ); if (!valname) a_byteCode->Emit( BC_POP ); // if not specified then just pop else a_byteCode->Emit( BC_SETLOCAL, valref ); // store the thread id if (!Generate(a_node->m_children[0], a_byteCode )) return false; a_byteCode->Emit( BC_RET ); loc2 = a_byteCode->Seek( loc1 ); a_byteCode->Emit( BC_FORK, loc2 ); a_byteCode->Seek( loc2 ); if (!valname) a_byteCode->Emit( BC_POP ); // if not specified then just pop else a_byteCode->Emit( BC_SETLOCAL, valref ); // store the thread id return true; }
// int string.ReverseFind(char/string a_charOrStringToFind); // Find the last instance of a specific character in a string. // Returns character offset or -1 if not found. static int GM_CDECL gmStringReverseFind(gmThread * a_thread) { GM_CHECK_NUM_PARAMS(1); const char* retCharPtr = NULL; const gmVariable * var = a_thread->GetThis(); GM_ASSERT(var->m_type == GM_STRING); gmStringObject * thisStrObj = (gmStringObject *) GM_OBJECT(var->m_value.m_ref); const char* thisStr = (const char *) *thisStrObj; if(a_thread->ParamType(0) == GM_INT) { const char otherChar = (char)a_thread->ParamInt(0); //Find character retCharPtr = strrchr(thisStr, otherChar); } else if(a_thread->ParamType(0) == GM_STRING) { gmStringObject * otherStrObj = a_thread->ParamStringObject(0); const char* otherStr = a_thread->ParamString(0); //Find string const char* lastFoundPtr = NULL; const char* newTestPtr = NULL; const char* curTestPtr = thisStr; const char* endThisStr = thisStr + thisStrObj->GetLength(); int searchStrLength = otherStrObj->GetLength(); //Search through string for last occurence //Not very efficient, but very rarely used. for(;;) { newTestPtr = strstr(curTestPtr, otherStr); if(!newTestPtr) { break; } lastFoundPtr = newTestPtr; curTestPtr = newTestPtr + searchStrLength; if(curTestPtr > endThisStr) { break; } }; retCharPtr = lastFoundPtr; } else { return GM_EXCEPTION; } // return -1 for not found, distance from beginning otherwise int retOffset = (retCharPtr == NULL) ? -1 : (int)(retCharPtr - thisStr); a_thread->PushInt(retOffset); return GM_OK; }
void ScriptSys::SetTableNull(const char* a_memberName, gmTableObject* a_table) { GM_ASSERT(a_table); gmTableObject* table = a_table; gmVariable newVar; newVar.Nullify(); table->Set(m_machine, a_memberName, newVar); }
void ScriptSys::SetTableString(const char* a_memberName, const char* a_string, int a_strLength, gmTableObject* a_table) { GM_ASSERT(a_table); gmTableObject* table = a_table; gmVariable newVar; newVar.SetString(m_machine->AllocStringObject(a_string, a_strLength)); table->Set(m_machine, a_memberName, newVar); }
void ScriptSys::SetTableFloat(const char* a_memberName, float a_float, gmTableObject* a_table) { GM_ASSERT(a_table); gmTableObject* table = a_table; gmVariable newVar; newVar.SetFloat(a_float); table->Set(m_machine, a_memberName, newVar); }
static void Cross(const gmVector3& a_vec1, const gmVector3& a_vec2, gmVector3& a_result) { GM_ASSERT( (&a_result != &a_vec1) && (&a_result != &a_vec2) ); a_result.m_x = (a_vec1.m_y * a_vec2.m_z) - (a_vec1.m_z * a_vec2.m_y); a_result.m_y = (a_vec1.m_z * a_vec2.m_x) - (a_vec1.m_x * a_vec2.m_z); a_result.m_z = (a_vec1.m_x * a_vec2.m_y) - (a_vec1.m_y * a_vec2.m_x); }
static int GM_CDECL gmfFileClose(gmThread * a_thread) { gmUserObject * fileObject = a_thread->ThisUserObject(); GM_ASSERT(fileObject->m_userType == s_gmFileType); if(fileObject->m_user) fclose((FILE *) fileObject->m_user); fileObject->m_user = NULL; return GM_OK; }
void gmGCColorSet::GrayThisObject(gmGCObjBase* a_obj) { gmGCObjBase* objPrev = a_obj->GetPrev(); gmGCObjBase* objNext = a_obj->GetNext(); // This routine should never get called with a shaded object GM_ASSERT(!m_gc->IsShaded(a_obj)); #if GM_GC_DEBUG GM_ASSERT(a_obj->m_curPosColor == GM_GC_DEBUG_COL_WHITE); a_obj->m_curPosColor = GM_GC_DEBUG_COL_GRAY; #endif //GM_GC_DEBUG // Set object`s color to shaded first. a_obj->SetColor(m_gc->GetCurShadeColor()); // The object must be shaded GM_ASSERT(m_gc->IsShaded(a_obj)); // Splice the object out of the white list // This can be done unconditionally as no set pointers can point to any object in this set. objPrev->SetNext(objNext); objNext->SetPrev(objPrev); // Put the object into the correct place in the gray list #if DEPTH_FIRST // Put the gray object at the head of the gray list. a_obj->SetPrev(m_scan->GetPrev()); a_obj->SetNext(m_scan); m_scan->GetPrev()->SetNext(a_obj); m_scan->SetPrev(a_obj); #else // BREADTH_FIRST // Put the gray object at the tail of the gray list. a_obj->SetPrev(m_gray); a_obj->SetNext(m_gray->GetNext()); m_gray->GetNext()->SetPrev(a_obj); m_gray->SetNext(a_obj); #endif // BREADTH_FIRST #if GM_GC_DEBUG // Slow, paranoid check VerifyIntegrity(); #endif //GM_GC_DEBUG }
bool gmCodeGenPrivate::GenExprOpArrayIndex(const gmCodeTreeNode * a_node, gmByteCodeGen * a_byteCode) { GM_ASSERT(a_node->m_type == CTNT_EXPRESSION && a_node->m_subType == CTNET_OPERATION && a_node->m_subTypeType == CTNOT_ARRAY_INDEX); if(!Generate(a_node->m_children[0], a_byteCode)) return false; if(!Generate(a_node->m_children[1], a_byteCode)) return false; return a_byteCode->Emit(BC_GETIND); }
void gmGCRootManager::Init() { GM_ASSERT( !s_staticInstance ); if( !s_staticInstance ) { s_staticInstance = new gmGCRootManager; } }