// native Array:ArrayClone(Array:which); static cell AMX_NATIVE_CALL ArrayClone(AMX* amx, cell* params) { CellArray* vec = HandleToVector(amx, params[1]); if (vec == NULL) { return 0; } CellArray *clonevec = vec->clone(); // Scan through the vector list to see if any are NULL. // NULL means the vector was previously destroyed. for (unsigned int i = 0; i < VectorHolder.length(); ++i) { if (VectorHolder[i] == NULL) { VectorHolder[i] = clonevec; return i + 1; } } VectorHolder.append(clonevec); return VectorHolder.length(); }
pstruct_t* pstructs_add(const char *name) { auto p = ke::MakeUnique<pstruct_t>(name); sStructs.append(ke::Move(p)); return sStructs.back().get(); }
void popstacklist(bool codegen) { if (codegen) modstk_for_scope(sStackScopes.back()); sStackScopes.pop(); }
//Makes a new menu handle (-1 for failure) //native csdm_makemenu(title[]); static cell AMX_NATIVE_CALL menu_create(AMX *amx, cell *params) { int len; char *title = get_amxstring(amx, params[1], 0, len); validate_menu_text(title); char *handler = get_amxstring(amx, params[2], 1, len); int func = registerSPForwardByName(amx, handler, FP_CELL, FP_CELL, FP_CELL, FP_DONE); if (func == -1) { LogError(amx, AMX_ERR_NOTFOUND, "Invalid function \"%s\"", handler); return 0; } Menu *pMenu = new Menu(title, amx, func); if (g_MenuFreeStack.empty()) { g_NewMenus.append(pMenu); pMenu->thisId = (int)g_NewMenus.length() - 1; } else { int pos = g_MenuFreeStack.front(); g_MenuFreeStack.pop(); g_NewMenus[pos] = pMenu; pMenu->thisId = pos; } return pMenu->thisId; }
void popheaplist(bool codegen) { if (codegen) modheap_for_scope(sHeapScopes.back()); sHeapScopes.pop(); }
static void EnterMemoryScope(ke::Vector<MemoryScope>& frame) { if (frame.empty()) frame.append(MemoryScope{0}); else frame.append(MemoryScope{frame.back().scope_id + 1}); }
void ClearPluginLibraries() { ClearLibraries(LibSource_Plugin); for (size_t i=0; i<g_RegNatives.length(); i++) { delete [] g_RegNatives[i]->pfn; delete g_RegNatives[i]; } g_RegNatives.clear(); }
funcenum_t *funcenums_add(const char *name) { auto e = ke::MakeUnique<funcenum_t>(); strcpy(e->name, name); e->tag = gTypes.defineFunction(name, e.get())->tagid(); sFuncEnums.append(ke::Move(e)); return sFuncEnums.back().get(); }
void genheapfree(int stop_id) { for (size_t i = sHeapScopes.length() - 1; i < sHeapScopes.length(); i--) { const MemoryScope& scope = sHeapScopes[i]; if (scope.scope_id <= stop_id) break; modheap_for_scope(scope); } }
void genstackfree(int stop_id) { for (size_t i = sStackScopes.length() - 1; i < sStackScopes.length(); i--) { const MemoryScope& scope = sStackScopes[i]; if (scope.scope_id <= stop_id) break; modstk_for_scope(scope); } }
// Sums up array usage in the current heap tracer and convert it into a dynamic array. // This is used for the ternary operator, which needs to convert its array usage into // something dynamically managed. // !Note: // This might break if expressions can ever return dynamic arrays. // Thus, we assert() if something is non-static here. // Right now, this poses no problem because this type of expression is impossible: // (a() ? return_array() : return_array()) ? return_array() : return_array() cell_t pop_static_heaplist() { cell_t total = 0; for (const auto& use : sHeapScopes.back().usage) { assert(use.type == MEMUSE_STATIC); total += use.size; } sHeapScopes.pop(); return total; }
void ClearMenus() { for (size_t i = 0; i < g_NewMenus.length(); i++) { delete g_NewMenus[i]; } g_NewMenus.clear(); while (!g_MenuFreeStack.empty()) { g_MenuFreeStack.pop(); } }
int GetPEL() { for (int i=0; i<(int)PEL.length(); i++) { if (PEL[i]->isFree()) return i; } RegEx *x = new RegEx(); PEL.append(x); return (int)PEL.length() - 1; }
void OnAmxxDetach() { for (int i = 0; i<(int)PEL.length(); i++) { if (PEL[i]) { delete PEL[i]; PEL[i] = 0; } } PEL.clear(); }
void OnAmxxDetach() { while (!g_FreeTRs.empty()) { delete g_FreeTRs.front(); g_FreeTRs.pop(); } while (!g_KVDWs.empty()) delete g_KVDWs.popCopy(); while (!g_FreeKVDWs.empty()) delete g_FreeKVDWs.popCopy(); }
//register_native(const name[], const handler[]) static cell AMX_NATIVE_CALL register_native(AMX *amx, cell *params) { if (!g_Initialized) amxx_DynaInit((void *)(amxx_DynaCallback)); g_Initialized = true; int len; char *name = get_amxstring(amx, params[1], 0, len); char *func = get_amxstring(amx, params[2], 1, len); int idx, err; if ( (err=amx_FindPublic(amx, func, &idx)) != AMX_ERR_NONE) { LogError(amx, err, "Function \"%s\" was not found", func); return 0; } regnative *pNative = new regnative; pNative->amx = amx; pNative->func = idx; //we'll apply a safety buffer too //make our function int size = amxx_DynaCodesize(); #if defined(_WIN32) DWORD temp; pNative->pfn = new char[size + 10]; VirtualProtect(pNative->pfn, size+10, PAGE_EXECUTE_READWRITE, &temp); #elif defined(__GNUC__) # if defined(__APPLE__) pNative->pfn = (char *)valloc(size+10); # else pNative->pfn = (char *)memalign(sysconf(_SC_PAGESIZE), size+10); # endif mprotect((void *)pNative->pfn, size+10, PROT_READ|PROT_WRITE|PROT_EXEC); #endif int id = (int)g_RegNatives.length(); amxx_DynaMake(pNative->pfn, id); pNative->func = idx; pNative->style = params[3]; g_RegNatives.append(pNative); pNative->name = name; return 1; }
Menu *get_menu_by_id(int id) { if (id < 0 || size_t(id) >= g_NewMenus.length() || !g_NewMenus[id]) return NULL; return g_NewMenus[id]; }
// native regex_substr(Regex:id, str_id, buffer[], maxLen); static cell AMX_NATIVE_CALL regex_substr(AMX *amx, cell *params) { int id = params[1]-1; if (id >= (int)PEL.length() || id < 0 || PEL[id]->isFree()) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid regex handle %d", id); return 0; } RegEx *x = PEL[id]; static char buffer[16384]; // Same as AMXX buffer. size_t length; size_t maxLength = ke::Min<size_t>(params[4], sizeof(buffer) - 1); const char *ret = x->GetSubstring(params[2], buffer, maxLength, &length); if (ret == NULL) { return 0; } if (length >= maxLength && ret[length - 1] & 1 << 7) { maxLength -= UTIL_CheckValidChar((char *)ret + length - 1); } MF_SetAmxString(amx, params[3], ret, maxLength); return 1; }
//native regex_replace(Regex:pattern, string[], maxLen, const replace[], flags = REGEX_FORMAT_DEFAULT, &errcode = 0); static cell AMX_NATIVE_CALL regex_replace(AMX *amx, cell *params) { int id = params[1] - 1; if (id >= (int)PEL.length() || id < 0 || PEL[id]->isFree()) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid regex handle %d", id); return 0; } int textLen, replaceLen; char *text = MF_GetAmxString(amx, params[2], 0, &textLen); const char *replace = MF_GetAmxString(amx, params[4], 1, &replaceLen); cell *erroCode = MF_GetAmxAddr(amx, params[6]); RegEx *x = PEL[id]; int e = x->Replace(text, params[3] + 1, replace, replaceLen, params[5]); if (e == -1) { *erroCode = x->mErrorOffset; x->ClearMatch(); return -2; } else if (e == 0) { *erroCode = 0; x->ClearMatch(); return 0; } MF_SetAmxString(amx, params[2], text, params[3]); return e; }
void OnAmxxDetach() { ConfigManager->CloseGameConfigFile(CommonConfig); ConfigManager->CloseGameConfigFile(GamerulesConfig); while (!g_FreeTRs.empty()) { delete g_FreeTRs.front(); g_FreeTRs.pop(); } while (!g_KVDWs.empty()) delete g_KVDWs.popCopy(); while (!g_FreeKVDWs.empty()) delete g_FreeKVDWs.popCopy(); }
void CLangMngr::CLang::MergeDefinitions(ke::Vector<sKeyDef> &vec) { ke::AutoString *pDef; int key = -1; while (!vec.empty()) { auto keydef = vec.popCopy(); key = keydef.key; pDef = keydef.definition; AddEntry(key, pDef->ptr()); delete pDef; } }
void pfnTouch(edict_t *pToucher, edict_t *pTouched) { unsigned int i = 0; int retVal = 0; const char *ptrClass = STRING(pToucher->v.classname); const char *ptdClass = STRING(pTouched->v.classname); int ptrIndex = ENTINDEX(pToucher); int ptdIndex = ENTINDEX(pTouched); META_RES res=MRES_IGNORED; for (i=0; i<Touches.length(); i++) { if (Touches[i]->Toucher.isVoid()) { if (Touches[i]->Touched.isVoid()) { retVal = MF_ExecuteForward(Touches[i]->Forward, (cell)ptrIndex, (cell)ptdIndex); if (retVal & 2/*PLUGIN_HANDLED_MAIN*/) RETURN_META(MRES_SUPERCEDE); else if (retVal) res=MRES_SUPERCEDE; } else if (Touches[i]->Touched.compare(ptdClass)==0) { retVal = MF_ExecuteForward(Touches[i]->Forward, (cell)ptrIndex, (cell)ptdIndex); if (retVal & 2/*PLUGIN_HANDLED_MAIN*/) RETURN_META(MRES_SUPERCEDE); else if (retVal) res=MRES_SUPERCEDE; } } else if (Touches[i]->Toucher.compare(ptrClass)==0) { if (Touches[i]->Touched.isVoid()) { retVal = MF_ExecuteForward(Touches[i]->Forward, (cell)ptrIndex, (cell)ptdIndex); if (retVal & 2/*PLUGIN_HANDLED_MAIN*/) RETURN_META(MRES_SUPERCEDE); else if (retVal) res=MRES_SUPERCEDE; } else if (Touches[i]->Touched.compare(ptdClass)==0) { retVal = MF_ExecuteForward(Touches[i]->Forward, (cell)ptrIndex, (cell)ptdIndex); if (retVal & 2/*PLUGIN_HANDLED_MAIN*/) RETURN_META(MRES_SUPERCEDE); else if (retVal) res=MRES_SUPERCEDE; } } } /* Execute pfnTouch forwards */ if (pfnTouchForward != -1) { retVal = MF_ExecuteForward(pfnTouchForward, (cell)ptrIndex, (cell)ptdIndex); if (retVal) RETURN_META(MRES_SUPERCEDE); } if (VexdTouchForward != -1) { retVal = MF_ExecuteForward(VexdTouchForward, (cell)ptrIndex, (cell)ptdIndex); if (retVal) RETURN_META(MRES_SUPERCEDE); } RETURN_META(res); }
static cell AMX_NATIVE_CALL free_kvd(AMX *amx, cell *params) { if (params[1] == 0) { return 0; } KVD_Wrapper *kvdw = reinterpret_cast<KVD_Wrapper *>(params[1]); for (size_t i = 0; i < g_KVDWs.length(); ++i) { if (g_KVDWs[i] == kvdw) { g_KVDWs.remove(i); g_FreeKVDWs.append(kvdw); return 1; } } return 0; }
methodmap_t* methodmap_add(methodmap_t* parent, LayoutSpec spec, const char* name) { auto map = ke::MakeUnique<methodmap_t>(parent, spec, name); if (spec == Layout_MethodMap && parent) { if (parent->nullable) map->nullable = parent->nullable; if (parent->keyword_nullable) map->keyword_nullable = parent->keyword_nullable; } if (spec == Layout_MethodMap) map->tag = gTypes.defineMethodmap(name, map.get())->tagid(); else map->tag = gTypes.defineObject(name)->tagid(); sMethodmaps.append(ke::Move(map)); return sMethodmaps.back().get(); }
static cell AMX_NATIVE_CALL create_kvd(AMX *amx, cell *params) { KVD_Wrapper *kvdw; if (g_FreeKVDWs.empty()) { kvdw = new KVD_Wrapper; } else { kvdw = g_FreeKVDWs.popCopy(); } kvdw->cls = ""; kvdw->kvd.szClassName = const_cast<char*>(kvdw->cls.chars()); kvdw->key = ""; kvdw->kvd.szKeyName = const_cast<char*>(kvdw->key.chars()); kvdw->val = ""; kvdw->kvd.szValue = const_cast<char*>(kvdw->val.chars()); kvdw->kvd.fHandled = 0; g_KVDWs.append(kvdw); return reinterpret_cast<cell>(kvdw); }
// Array:ArrayCreate(cellsize=1, reserved=32); static cell AMX_NATIVE_CALL ArrayCreate(AMX* amx, cell* params) { // params[1] (cellsize) is how big in cells each element is. // this MUST be greater than 0! int cellsize = params[1]; // params[2] (reserved) is how many elements to allocate // immediately when the list is created. int reserved = params[2]; if (cellsize <= 0) { LogError(amx, AMX_ERR_NATIVE, "Invalid array size (%d)", cellsize); return -1; } if (reserved < 0) { reserved = 0; } // Scan through the vector list to see if any are NULL. // NULL means the vector was previously destroyed. for (unsigned int i=0; i < VectorHolder.length(); ++i) { if (VectorHolder[i]==NULL) { VectorHolder[i] = new CellArray(cellsize, reserved); return i + 1; } } // None are NULL, create a new vector CellArray* NewVector = new CellArray(cellsize, reserved); VectorHolder.append(NewVector); return VectorHolder.length(); }
AMX_NATIVE_INFO *BuildNativeTable() { if (g_RegNatives.length() < 1) { return NULL; } AMX_NATIVE_INFO *pNatives = new AMX_NATIVE_INFO[g_RegNatives.length() + 1]; AMX_NATIVE_INFO info; regnative *pNative; for (size_t i=0; i<g_RegNatives.length(); i++) { pNative = g_RegNatives[i]; info.name = pNative->name.chars(); info.func = (AMX_NATIVE)((void *)(pNative->pfn)); pNatives[i] = info; } pNatives[g_RegNatives.length()].name = NULL; pNatives[g_RegNatives.length()].func = NULL; //this needs to be deleted return pNatives; }
cell match_c(AMX *amx, cell *params, bool all) { int id = params[2] - 1; if (id >= (int)PEL.length() || id < 0 || PEL[id]->isFree()) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid regex handle %d", id); return 0; } int len; const char *str = MF_GetAmxString(amx, params[1], 0, &len); cell *errorCode = MF_GetAmxAddr(amx, params[3]); RegEx *x = PEL[id]; int e; if (all) e = x->MatchAll(str); else e = x->Match(str); if (e == -1) { /* there was a match error. move on. */ *errorCode = x->mErrorOffset; /* only clear the match results, since the regex object may still be referenced later */ x->ClearMatch(); return -2; } else if (e == 0) { *errorCode = 0; /* only clear the match results, since the regex object may still be referenced later */ x->ClearMatch(); return 0; } else { *errorCode = x->Count(); return x->Count(); } }
static cell AMX_NATIVE_CALL regex_free(AMX *amx, cell *params) { cell *c = MF_GetAmxAddr(amx, params[1]); int id = *c; *c = 0; id -= 1; if (id >= (int)PEL.length() || id < 0 || PEL[id]->isFree()) { MF_LogError(amx, AMX_ERR_NATIVE, "Invalid regex handle %d", id); return 0; } RegEx *x = PEL[id]; x->Clear(); return 1; }
void CmdStart(const edict_t *player, const struct usercmd_s *_cmd, unsigned int random_seed) { unsigned int i = 0; int retVal = 0; edict_t *pEntity = (edict_t *)player; g_cmd = (struct usercmd_s *)_cmd; int origImpulse = g_cmd->impulse; // incase a plugin alters it for (i=0; i<Impulses.length(); i++) { if (Impulses[i]->Check == g_cmd->impulse) { retVal = MF_ExecuteForward(Impulses[i]->Forward, (cell)ENTINDEX(pEntity), (cell)origImpulse); // don't return SUPERCEDE in any way here, // we don't want to break client_impulse forward and access to cmd with [g/s]et_usercmd if (retVal) g_cmd->impulse = 0; } } // client_impulse if (ClientImpulseForward != -1 && origImpulse != 0) { retVal = MF_ExecuteForward(ClientImpulseForward, (cell)ENTINDEX(pEntity), (cell)origImpulse); if (retVal) g_cmd->impulse = 0; } // client_CmdStart if (CmdStartForward != -1) { incmd = true; retVal = MF_ExecuteForward(CmdStartForward, (cell)ENTINDEX(pEntity)); incmd = false; if (retVal) RETURN_META(MRES_SUPERCEDE); } RETURN_META(MRES_IGNORED); }