diff --git a/amxmodx/CLibrarySys.cpp b/amxmodx/CLibrarySys.cpp index 03b2892d..689b789d 100644 --- a/amxmodx/CLibrarySys.cpp +++ b/amxmodx/CLibrarySys.cpp @@ -61,28 +61,16 @@ CDirectory::~CDirectory() } } -void CDirectory::NextEntry(cell* offset) +DirHandle CDirectory::GetHandle() +{ + return m_dir; +} + +void CDirectory::NextEntry() { #if defined PLATFORM_WINDOWS - if (offset) - { - // Should be declared after loop so entry starts to '.' and not '..' - // But old code did that, so keep this for compatibility. - ++*offset; - - for (cell i = 0; i < *offset; ++i) - { - if (FindNextFile(m_dir, &m_fd) == 0) - { - *offset = 0; - FindClose(m_dir); - m_dir = INVALID_HANDLE_VALUE; - return; - } - } - } - else if (FindNextFile(m_dir, &m_fd) == 0) + if (FindNextFile(m_dir, &m_fd) == 0) { FindClose(m_dir); m_dir = INVALID_HANDLE_VALUE; @@ -90,22 +78,7 @@ void CDirectory::NextEntry(cell* offset) #elif defined PLATFORM_POSIX - if (offset) - { - seekdir(m_dir, *offset); - - if (!(m_ep = readdir(m_dir))) - { - *offset = 0; - closedir(m_dir); - m_dir = nullptr; - } - else - { - *offset = telldir(m_dir); - } - } - else if (!(m_ep = readdir(m_dir))) + if (!(m_ep = readdir(m_dir))) { closedir(m_dir); m_dir = nullptr; diff --git a/amxmodx/CLibrarySys.h b/amxmodx/CLibrarySys.h index 1ce8f37b..d57063b4 100644 --- a/amxmodx/CLibrarySys.h +++ b/amxmodx/CLibrarySys.h @@ -58,9 +58,15 @@ #define PLATFORM_MAX_PATH 260 #if defined PLATFORM_WINDOWS + typedef HMODULE LibraryHandle; + typedef HANDLE DirHandle; + #elif defined PLATFORM_POSIX + typedef void* LibraryHandle; + typedef DIR* DirHandle; + #endif enum FileTimeType @@ -80,7 +86,7 @@ class CDirectory public: bool MoreFiles(); - void NextEntry(cell* offset = nullptr); + void NextEntry(); const char* GetEntryName(); bool IsEntryDirectory(); bool IsEntryFile(); @@ -89,6 +95,7 @@ class CDirectory public: bool IsValid(); + DirHandle GetHandle(); private: diff --git a/amxmodx/CPlugin.cpp b/amxmodx/CPlugin.cpp index 5db24c52..04ad342f 100755 --- a/amxmodx/CPlugin.cpp +++ b/amxmodx/CPlugin.cpp @@ -152,6 +152,11 @@ int CPluginMngr::loadPluginsFromFile(const char* filename, bool warn) { *get_amxaddr(plugin->getAMX(), addr) = gpGlobals->maxClients; } + + if (amx_FindPubVar(plugin->getAMX(), "NULL_STRING", &addr) != AMX_ERR_NOTFOUND) + { + plugin->m_pNullStringOfs = get_amxaddr(plugin->getAMX(), addr); + } } } @@ -256,7 +261,7 @@ const char* CPluginMngr::CPlugin::getStatus() const return "error"; } -CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d) : name(n), title(n) +CPluginMngr::CPlugin::CPlugin(int i, const char* p, const char* n, char* e, int d) : name(n), title(n), m_pNullStringOfs(nullptr) { const char* unk = "unknown"; diff --git a/amxmodx/CPlugin.h b/amxmodx/CPlugin.h index a52ffd37..ced01d6b 100755 --- a/amxmodx/CPlugin.h +++ b/amxmodx/CPlugin.h @@ -61,6 +61,7 @@ public: ~CPlugin(); bool m_Debug; + cell* m_pNullStringOfs; public: inline const char* getName() { return name.c_str();} inline const char* getVersion() { return version.c_str();} @@ -90,6 +91,7 @@ public: const char* getStatus() const; inline bool isDebug() const { return m_Debug; } + inline cell* getNullStringOfs() const { return m_pNullStringOfs; } }; private: diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 321a991f..50ee79ff 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -29,7 +29,7 @@ static cell AMX_NATIVE_CALL get_xvar_id(AMX *amx, cell *params) char* sName = get_amxstring(amx, params[1], 0, len); cell ptr; - if (!strcmp(sName, "MaxClients")) + if (!strcmp(sName, "MaxClients") || !strcmp(sName, "NULL_STRING")) { return -1; } diff --git a/amxmodx/amxmodx.h b/amxmodx/amxmodx.h index 4b216480..4bf6b85e 100755 --- a/amxmodx/amxmodx.h +++ b/amxmodx/amxmodx.h @@ -276,6 +276,7 @@ char* format_amxstring(AMX *amx, cell *params, int parm, int& len); AMX* get_amxscript(int, void**, const char**); const char* get_amxscriptname(AMX* amx); char* get_amxstring(AMX *amx, cell amx_addr, int id, int& len); +char *get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len); extern "C" size_t get_amxstring_r(AMX *amx, cell amx_addr, char *destination, int maxlen); int amxstring_len(cell* cstr); diff --git a/amxmodx/file.cpp b/amxmodx/file.cpp index 008b9dd3..a5e1981e 100755 --- a/amxmodx/file.cpp +++ b/amxmodx/file.cpp @@ -29,7 +29,30 @@ static cell AMX_NATIVE_CALL read_dir(AMX *amx, cell *params) cell offset = Max(0, params[2]); - dir->NextEntry(&offset); + if (offset >= 0) + { +#if defined PLATFORM_WINDOWS + // Should be declared after so entry starts to '.' and not '..' + // But old code did that, so keep this for compatibility. + ++offset; + + for (cell i = 0; i < offset && dir->MoreFiles(); ++i) + { + dir->NextEntry(); + } + +#elif defined PLATFORM_POSIX + + seekdir(dir->GetHandle(), offset); + + dir->NextEntry(); + + if (dir->IsValid()) + { + offset = telldir(dir->GetHandle()); + } +#endif + } if (!dir->IsValid()) { @@ -190,12 +213,7 @@ static cell AMX_NATIVE_CALL delete_file(AMX *amx, cell *params) if (*params / sizeof(cell) >= 2 && params[2] > 0) { - const char* pathID = get_amxstring(amx, params[3], 1, length); - - if (!strcmp(pathID, "ALL")) - { - pathID = nullptr; - } + const char* pathID = get_amxstring_null(amx, params[3], 1, length); return ValveFile::Delete(file, pathID); } @@ -240,7 +258,7 @@ static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params) { int length; const char* path = get_amxstring(amx, params[1], 0, length); - int flag = params[2]; + int flag = FSOPT_BYTES_COUNT; AutoPtr fp; @@ -248,12 +266,7 @@ static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params) if (numParams >= 3 && params[3] > 0) { - const char* pathID = get_amxstring(amx, params[4], 1, length); - - if (!strcmp(pathID, "ALL")) - { - pathID = nullptr; - } + const char* pathID = get_amxstring_null(amx, params[4], 1, length); fp = ValveFile::Open(path, "r", pathID); } @@ -267,9 +280,13 @@ static cell AMX_NATIVE_CALL file_size(AMX *amx, cell *params) return -1; } + if (numParams >= 2) + { + flag = params[2]; + } + switch (flag) { - default: case FSOPT_BYTES_COUNT: { fp->Seek(0, SEEK_END); @@ -314,12 +331,7 @@ static cell AMX_NATIVE_CALL amx_fopen(AMX *amx, cell *params) if (*params / sizeof(cell) >= 3 && params[3] > 0) { - const char* pathID = get_amxstring(amx, params[4], 2, length); - - if (!strcmp(pathID, "ALL")) - { - pathID = nullptr; - } + const char* pathID = get_amxstring_null(amx, params[4], 2, length); fp = ValveFile::Open(file, flags, pathID); } @@ -388,16 +400,14 @@ static cell AMX_NATIVE_CALL amx_fwrite_blocks(AMX *amx, cell *params) } break; } - default: - { - if (size != BLOCK_INT) - { - size = BLOCK_INT; - } - } case BLOCK_INT: { read = fp->Write(data, sizeof(cell) * blocks); + break; + } + default: + { + return 0; } } @@ -429,7 +439,6 @@ static cell AMX_NATIVE_CALL amx_fwrite(AMX *amx, cell *params) short value = static_cast(data); return fp->Write(&value, sizeof(value)); } - default: case BLOCK_INT: { int value = static_cast(data); @@ -499,7 +508,6 @@ static cell AMX_NATIVE_CALL amx_fread(AMX *amx, cell *params) return res; } case BLOCK_INT: - default: { int value; size_t res = fp->Read(&value, sizeof(value)); @@ -561,18 +569,15 @@ static cell AMX_NATIVE_CALL amx_fread_blocks(AMX *amx, cell *params) } break; } - default: - { - if (size != BLOCK_INT) - { - size = BLOCK_INT; - } - } case BLOCK_INT: { read = fp->Read(data, sizeof(cell) * blocks); break; } + default: + { + return 0; + } } return read / size; @@ -764,12 +769,7 @@ static cell AMX_NATIVE_CALL amx_open_dir(AMX *amx, cell *params) if (numParams >= 4 && params[5] > 0) { const char* wildcardedPath = g_LibSys.PathFormat("%s%s*", path, (path[length - 1] != '/' && path[length - 1] != '\\') ? "/" : ""); - const char* pathID = get_amxstring(amx, params[6], 1, length); - - if (!strcmp(pathID, "ALL")) - { - pathID = nullptr; - } + const char* pathID = get_amxstring_null(amx, params[6], 1, length); static FileFindHandle_t handle; const char* pFirst = g_FileSystem->FindFirst(wildcardedPath, &handle, pathID); @@ -976,18 +976,13 @@ static cell AMX_NATIVE_CALL amx_mkdir(AMX *amx, cell *params) if (numParams >= 3 && params[3] > 0) { - const char* pathID = get_amxstring(amx, params[4], 1, length); + const char* pathID = get_amxstring_null(amx, params[4], 1, length); if (g_FileSystem->IsDirectory(path)) { return -1; } - if (!strcmp(pathID, "ALL")) - { - pathID = nullptr; - } - g_FileSystem->CreateDirHierarchy(path, pathID); if (g_FileSystem->IsDirectory(path)) diff --git a/amxmodx/string.cpp b/amxmodx/string.cpp index e9ca20f7..492c1d7a 100755 --- a/amxmodx/string.cpp +++ b/amxmodx/string.cpp @@ -176,6 +176,16 @@ char *get_amxstring(AMX *amx, cell amx_addr, int id, int& len) return buffer[id]; } +char *get_amxstring_null(AMX *amx, cell amx_addr, int id, int& len) +{ + if (get_amxaddr(amx, amx_addr) == g_plugins.findPluginFast(amx)->getNullStringOfs()) + { + return nullptr; + } + + return get_amxstring(amx, amx_addr, id, len); +} + void copy_amxmemory(cell* dest, cell* src, int len) { while (len--) diff --git a/compiler/libpc300/sc1.c b/compiler/libpc300/sc1.c index cb071acd..8230118c 100755 --- a/compiler/libpc300/sc1.c +++ b/compiler/libpc300/sc1.c @@ -1895,8 +1895,10 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst if (size > INT_MAX) error(105); /* overflow, exceeding capacity */ #endif +#if 0 /* We don't actually care */ if (ispublic) error(56,name); /* arrays cannot be public */ +#endif dim[numdim++]=(int)size; } /* while */ /* if this variable is never used (which can be detected only in the @@ -1936,7 +1938,7 @@ static void declglb(char *firstname,int firsttag,int fpublic,int fstatic,int fst sym->usage|=uDEFINE; } /* if */ if (ispublic) - sym->usage|=uPUBLIC; + sym->usage|=uPUBLIC|uREAD; if (fconst) sym->usage|=uCONST; if (fstock) diff --git a/compiler/libpc300/sc6.c b/compiler/libpc300/sc6.c index af5762ca..bd617926 100755 --- a/compiler/libpc300/sc6.c +++ b/compiler/libpc300/sc6.c @@ -619,7 +619,7 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) assert(sym->vclass==sGLOBAL); mainaddr=sym->addr; } /* if */ - } else if (sym->ident==iVARIABLE) { + } else if (sym->ident==iVARIABLE || sym->ident == iARRAY || sym->ident == iREFARRAY) { if ((sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) match=++numpubvars; } /* if */ @@ -794,7 +794,8 @@ SC_FUNC int assemble(FILE *fout,FILE *fin) /* write the public variables table */ count=0; for (sym=glbtab.next; sym!=NULL; sym=sym->next) { - if (sym->ident==iVARIABLE && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) { + if ((sym->ident==iVARIABLE || sym->ident==iARRAY || sym->ident==iREFARRAY) + && (sym->usage & uPUBLIC)!=0 && (sym->usage & (uREAD | uWRITTEN))!=0) { assert((sym->usage & uDEFINE)!=0); assert(sym->vclass==sGLOBAL); func.address=sym->addr; diff --git a/plugins/include/amxconst.inc b/plugins/include/amxconst.inc index 23d9b05a..d2b4f681 100755 --- a/plugins/include/amxconst.inc +++ b/plugins/include/amxconst.inc @@ -39,7 +39,15 @@ */ #define MAX_PLAYERS 32 /* Maximum number of players AMX Mod X supports */ -public stock const MaxClients; /* Maximum number of players the server supports */ +/** + * Maximum number of players the server supports + */ +public stock const MaxClients; + +/** + * Pass this into certain functions to act as a C++ NULL + */ +public stock const NULL_STRING[1]; /** * The maximum buffer size required to store a clients name. diff --git a/plugins/include/file.inc b/plugins/include/file.inc index 2ac10e3e..c675bffc 100755 --- a/plugins/include/file.inc +++ b/plugins/include/file.inc @@ -149,7 +149,7 @@ native write_file(const file[], const text[], line = -1); * This can be used to delete files existing in the Valve * search path, rather than solely files existing directly * in the gamedir. - * @param valve_path_id If use_valve_fs, a search path from gameinfo or "ALL" for all search paths. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * * @return 1 on success, 0 on failure or if file not immediately removed. */ @@ -204,7 +204,7 @@ native dir_exists(const dir[], bool:use_valve_fs = false); * the Valve search paths, rather than solely files * existing directly in the gamedir. * If used, flag option is ignored. - * @param valve_path_id If use_valve_fs, a search path from gameinfo or "ALL" for all search paths + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths * * @return If flag is FSOPT_BYTES_COUNT or use_valve_fs to true, the file size in bytes * If flag is FSOPT_LINES_COUNT, the number of lines in the file @@ -258,7 +258,7 @@ native file_size(const file[], flag = FSOPT_BYTES_COUNT, bool:use_valve_fs = fal * This can be used to finred files existing in valve * search paths, rather than solely files existing directly * in the gamedir. - * @param valve_path_id If use_valve_fs, a search path from gameinfo or "ALL" for all search paths + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths * * @return A file handle, or null if the file could not be opened. */ @@ -481,7 +481,7 @@ native rmdir(const path[]); * @param use_valve_fs If true, the Valve file system will be used instead * This can be used to create folders in the game's * Valve search paths, rather than directly in the gamedir. - * @param valve_path_id If use_valve_fs, a search path from gameinfo or "ALL" for default + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for default * In this case, mode is ignored * * @return 0 on success, -1 otherwise @@ -496,7 +496,7 @@ native mkdir(const dirname[], mode = FPERM_DIR_DEFAULT, bool:use_valve_fs = fals * This can be used to delete files existing in the Valve * search path, rather than solely files existing directly * in the gamedir. - * @param valve_path_id If use_valve_fs, a search path from gameinfo or "ALL" for all search paths + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths * * @return 1 on success, 0 on failure or if file not immediately removed */ @@ -515,7 +515,7 @@ native unlink(const filename[], bool:use_valve_fs = false, const valve_path_id[] * This can be used to find files existing in any of * the Valve search paths, rather than solely files * existing directly in the gamedir. - * @param valve_path_id If use_valve_fs, a search path from gameinfo or "ALL" for all search paths. + * @param valve_path_id If use_valve_fs, a search path from gameinfo or NULL_STRING for all search paths. * * @return Handle to the directory, 0 otherwise */