From b455ac4f4eba749a629e70a4c0aae9b569c4726b Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 6 Apr 2008 06:56:45 +0000 Subject: [PATCH] merged changes back from 1.0.1 --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401992 --- core/AdminCache.cpp | 351 ++++++++++++++++++++++++++++- core/AdminCache.h | 7 + core/sm_stringutil.cpp | 67 ++++++ core/sm_trie.cpp | 29 +++ core/sm_trie.h | 7 + editor/crimson/spec/sourcepawn.key | 2 +- editor/crimson/tools/compile.cmd | Bin 0 -> 553 bytes gamedata/sdktools.games.txt | 65 ++++++ plugins/include/tf2.inc | 10 - public/sm_trie_tpl.h | 111 +++++++++ sourcepawn/compiler/sc1.c | 17 +- 11 files changed, 648 insertions(+), 18 deletions(-) create mode 100644 editor/crimson/tools/compile.cmd diff --git a/core/AdminCache.cpp b/core/AdminCache.cpp index e469cdbcb..154f88a4b 100644 --- a/core/AdminCache.cpp +++ b/core/AdminCache.cpp @@ -41,12 +41,14 @@ #include "sourcemod.h" #include "sm_stringutil.h" #include "sourcemm_api.h" +#include "sm_srvcmds.h" #define LEVEL_STATE_NONE 0 #define LEVEL_STATE_LEVELS 1 #define LEVEL_STATE_FLAGS 2 AdminCache g_Admins; +char g_ReverseFlags[26]; AdminFlag g_FlagLetters[26]; bool g_FlagSet[26]; @@ -299,8 +301,23 @@ void AdminCache::OnSourceModAllInitialized() void AdminCache::OnSourceModLevelChange(const char *mapName) { + int i; + AdminFlag flag; + /* For now, we only read these once per level. */ s_FlagReader.LoadLevels(); + + for (i = 0; i < 26; i++) + { + if (FindFlag('a' + i, &flag)) + { + g_ReverseFlags[flag] = 'a' + i; + } + else + { + g_ReverseFlags[flag] = '?'; + } + } } void AdminCache::OnSourceModShutdown() @@ -434,7 +451,9 @@ AdminId AdminCache::CreateAdmin(const char *name) assert(pUser->magic == USR_MAGIC_UNSET); id = m_FreeUserList; m_FreeUserList = pUser->next_user; - } else { + } + else + { id = m_pMemory->CreateMem(sizeof(AdminUser), (void **)&pUser); pUser->grp_size = 0; pUser->grp_table = -1; @@ -454,19 +473,28 @@ AdminId AdminCache::CreateAdmin(const char *name) { m_FirstUser = id; m_LastUser = id; - } else { + } + else + { AdminUser *pPrev = (AdminUser *)m_pMemory->GetAddress(m_LastUser); pPrev->next_user = id; pUser->prev_user = m_LastUser; m_LastUser = id; } + /* Since we always append to the tail, we should invalidate their next */ + pUser->next_user = -1; + if (name && name[0] != '\0') { int nameidx = m_pStrings->AddString(name); pUser = (AdminUser *)m_pMemory->GetAddress(id); pUser->nameidx = nameidx; } + else + { + pUser->nameidx = -1; + } return id; } @@ -1587,7 +1615,9 @@ bool AdminCache::CanAdminTarget(AdminId id, AdminId target) bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag) { - if (c < 'a' || c > 'z') + if (c < 'a' + || c > 'z' + || !g_FlagSet[(unsigned)c - (unsigned)'a']) { return false; } @@ -1600,6 +1630,21 @@ bool AdminCache::FindFlag(char c, AdminFlag *pAdmFlag) return true; } +bool AdminCache::FindFlagChar(AdminFlag flag, char *c) +{ + if (!g_FlagSet[flag]) + { + return false; + } + + if (c) + { + *c = g_ReverseFlags[flag]; + } + + return true; +} + FlagBits AdminCache::ReadFlagString(const char *flags, const char **end) { FlagBits bits = 0; @@ -1730,3 +1775,303 @@ bool AdminCache::CheckAccess(int client, const char *cmd, FlagBits flags, bool o return g_ConCmds.CheckCommandAccess(client, cmd, bits) ? 1 : 0; } + +void iterator_glob_basic_override(Trie *pTrie, const char *key, void **value, void *data) +{ + FILE *fp; + int flags; + char flagstr[64]; + + fp = (FILE *)data; + flags = (int)*value; + g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t\"%s\"\t\t\"%s\"\n", key, flagstr); +} + +void iterator_glob_grp_override(Trie *pTrie, const char *key, void **value, void *data) +{ + FILE *fp; + int flags; + char flagstr[64]; + + fp = (FILE *)data; + flags = (int)*value; + g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t\"@%s\"\t\t\"%s\"\n", key, flagstr); +} + +void iterator_group_basic_override(Trie *pTrie, const char *key, void **value, void *data) +{ + FILE *fp; + int flags; + char flagstr[64]; + + fp = (FILE *)data; + flags = (int)*value; + g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t\t\t\"%s\"\t\t\"%s\"\n", key, flagstr); +} + +void iterator_group_grp_override(Trie *pTrie, const char *key, void **value, void *data) +{ + FILE *fp; + int flags; + char flagstr[64]; + + fp = (FILE *)data; + flags = (int)*value; + g_Admins.FillFlagString(flags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t\t\t\"@%s\"\t\t\"%s\"\n", key, flagstr); +} + +void AdminCache::DumpCache(FILE *fp) +{ + int *itable; + AdminId aid; + GroupId gid; + char flagstr[64]; + unsigned int num; + AdminUser *pAdmin; + AdminGroup *pGroup; + char name_buffer[512]; + + fprintf(fp, "\"Groups\"\n{\n"); + + num = 0; + gid = m_FirstGroup; + while (gid != INVALID_GROUP_ID + && (pGroup = GetGroup(gid)) != NULL) + { + num++; + FillFlagString(pGroup->addflags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t/* num = %d, gid = 0x%X */\n", num, gid); + fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pGroup->nameidx)); + fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr); + fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pGroup->immunity_level); + + if (pGroup->immune_table != -1 + && (itable = (int *)m_pMemory->GetAddress(pGroup->immune_table)) != NULL) + { + AdminGroup *pAltGroup; + const char *gname, *mod; + + for (int i = 1; i <= itable[0]; i++) + { + if ((pAltGroup = GetGroup(itable[i])) == NULL) + { + /* Assume the rest of the table is corrupt */ + break; + } + gname = GetString(pAltGroup->nameidx); + if (atoi(gname) != 0) + { + mod = "@"; + } + else + { + mod = ""; + } + fprintf(fp, "\t\t\"immunity\"\t\t\"%s%s\"\n", mod, gname); + } + } + + fprintf(fp, "\n\t\t\"Overrides\"\n\t\t{\n"); + if (pGroup->pCmdGrpTable != NULL) + { + sm_trie_bad_iterator(pGroup->pCmdGrpTable, + name_buffer, + sizeof(name_buffer), + iterator_group_grp_override, + fp); + } + if (pGroup->pCmdTable != NULL) + { + sm_trie_bad_iterator(pGroup->pCmdTable, + name_buffer, + sizeof(name_buffer), + iterator_group_basic_override, + fp); + } + fprintf(fp, "\t\t}\n"); + + fprintf(fp, "\t}\n"); + + if ((gid = pGroup->next_grp) != INVALID_GROUP_ID) + { + fprintf(fp, "\n"); + } + } + + fprintf(fp, "}\n\n"); + fprintf(fp, "\"Admins\"\n{\n"); + + num = 0; + aid = m_FirstUser; + while (aid != INVALID_ADMIN_ID + && (pAdmin = GetUser(aid)) != NULL) + { + num++; + FillFlagString(pAdmin->flags, flagstr, sizeof(flagstr)); + + fprintf(fp, "\t/* num = %d, aid = 0x%X, serialno = 0x%X*/\n", num, aid, pAdmin->serialchange); + + if (pAdmin->nameidx != -1) + { + fprintf(fp, "\t\"%s\"\n\t{\n", GetString(pAdmin->nameidx)); + } + else + { + fprintf(fp, "\t\"\"\n\t{\n"); + } + + if (pAdmin->auth.identidx != -1) + { + fprintf(fp, "\t\t\"auth\"\t\t\t\"%s\"\n", GetMethodName(pAdmin->auth.index)); + fprintf(fp, "\t\t\"identity\"\t\t\"%s\"\n", GetString(pAdmin->auth.identidx)); + } + if (pAdmin->password != -1) + { + fprintf(fp, "\t\t\"password\"\t\t\"%s\"\n", GetString(pAdmin->password)); + } + fprintf(fp, "\t\t\"flags\"\t\t\t\"%s\"\n", flagstr); + fprintf(fp, "\t\t\"immunity\"\t\t\"%d\"\n", pAdmin->immunity_level); + + if (pAdmin->grp_count != 0 + && pAdmin->grp_table != -1 + && (itable = (int *)m_pMemory->GetAddress(pAdmin->grp_table)) != NULL) + { + unsigned int i; + + for (i = 0; i < pAdmin->grp_count; i++) + { + if ((pGroup = GetGroup(itable[i])) == NULL) + { + /* Assume the rest of the table is corrupt */ + break; + } + fprintf(fp, "\t\t\"group\"\t\t\t\"%s\"\n", GetString(pGroup->nameidx)); + } + } + + fprintf(fp, "\t}\n"); + + if ((aid = pAdmin->next_user) != INVALID_ADMIN_ID) + { + fprintf(fp, "\n"); + } + } + + fprintf(fp, "}\n\n"); + + fprintf(fp, "\"Overrides\"\n{\n"); + if (m_pCmdGrpOverrides != NULL) + { + sm_trie_bad_iterator(m_pCmdGrpOverrides, + name_buffer, + sizeof(name_buffer), + iterator_glob_grp_override, + fp); + } + if (m_pCmdOverrides != NULL) + { + sm_trie_bad_iterator(m_pCmdOverrides, + name_buffer, + sizeof(name_buffer), + iterator_glob_basic_override, + fp); + } + fprintf(fp, "}\n"); +} + +AdminGroup *AdminCache::GetGroup(GroupId gid) +{ + AdminGroup *pGroup; + + pGroup = (AdminGroup *)m_pMemory->GetAddress(gid); + if (!pGroup || pGroup->magic != GRP_MAGIC_SET) + { + return NULL; + } + + return pGroup; +} + +AdminUser *AdminCache::GetUser(AdminId aid) +{ + AdminUser *pAdmin; + + pAdmin = (AdminUser *)m_pMemory->GetAddress(aid); + if (!pAdmin || pAdmin->magic != USR_MAGIC_SET) + { + return NULL; + } + + return pAdmin; +} + +const char *AdminCache::GetMethodName(unsigned int index) +{ + List::iterator iter; + for (iter=m_AuthMethods.begin(); + iter!=m_AuthMethods.end(); + iter++) + { + if (index-- == 0) + { + return (*iter).name.c_str(); + } + } + + return NULL; +} + +const char *AdminCache::GetString(int idx) +{ + return m_pStrings->GetString(idx); +} + +size_t AdminCache::FillFlagString(FlagBits bits, char *buffer, size_t maxlen) +{ + size_t pos; + unsigned int i, num_flags; + AdminFlag flags[AdminFlags_TOTAL]; + + num_flags = FlagBitsToArray(bits, flags, AdminFlags_TOTAL); + + pos = 0; + for (i = 0; pos < maxlen && i < num_flags; i++) + { + if (FindFlagChar(flags[i], &buffer[pos])) + { + pos++; + } + } + buffer[pos] = '\0'; + + return pos; +} + +CON_COMMAND(sm_dump_admcache, "Dumps the admin cache for debugging") +{ + FILE *fp; + char buffer[PLATFORM_MAX_PATH]; + + g_SourceMod.BuildPath(Path_SM, buffer, sizeof(buffer), "data/admin_cache_dump.txt"); + + if ((fp = fopen(buffer, "wt")) == NULL) + { + g_RootMenu.ConsolePrint("Could not open file for writing: %s", buffer); + return; + } + + g_Admins.DumpCache(fp); + + g_RootMenu.ConsolePrint("Admin cache dumped to: %s", buffer); + + fclose(fp); +} diff --git a/core/AdminCache.h b/core/AdminCache.h index ab0b74616..c7d21da1a 100644 --- a/core/AdminCache.h +++ b/core/AdminCache.h @@ -153,6 +153,7 @@ public: //IAdminSystem bool FindFlag(const char *str, AdminFlag *pFlag); bool FindFlag(char c, AdminFlag *pAdmFlag); FlagBits ReadFlagString(const char *flags, const char **end); + size_t FillFlagString(FlagBits bits, char *buffer, size_t maxlen); unsigned int GetAdminSerialChange(AdminId id); bool CanAdminUseCommand(int client, const char *cmd); const char *GetGroupName(GroupId gid); @@ -164,8 +165,13 @@ public: //IAdminSystem const char *cmd, FlagBits flags, bool override_only); + bool FindFlagChar(AdminFlag flag, char *c); public: bool IsValidAdmin(AdminId id); + void DumpCache(FILE *fp); + AdminGroup *GetGroup(GroupId gid); + AdminUser *GetUser(AdminId id); + const char *GetString(int idx); private: void _UnsetCommandOverride(const char *cmd); void _UnsetCommandGroupOverride(const char *group); @@ -174,6 +180,7 @@ private: void DumpCommandOverrideCache(OverrideType type); Trie *GetMethodByIndex(unsigned int index); bool GetMethodIndex(const char *name, unsigned int *_index); + const char *GetMethodName(unsigned int index); void NameFlag(const char *str, AdminFlag flag); public: BaseStringTable *m_pStrings; diff --git a/core/sm_stringutil.cpp b/core/sm_stringutil.cpp index de344f035..f12bba8b3 100644 --- a/core/sm_stringutil.cpp +++ b/core/sm_stringutil.cpp @@ -357,6 +357,57 @@ void AddFloat(char **buf_p, size_t &maxlen, double fval, int width, int prec, in *buf_p = buf; } +void AddBinary(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags) +{ + char text[32]; + int digits; + char *buf; + + digits = 0; + do + { + if (val & 1) + { + text[digits++] = '1'; + } + else + { + text[digits++] = '0'; + } + val >>= 1; + } while (val); + + buf = *buf_p; + + if (!(flags & LADJUST)) + { + while (digits < width && maxlen) + { + *buf++ = (flags & ZEROPAD) ? '0' : ' '; + width--; + maxlen--; + } + } + + while (digits-- && maxlen) + { + *buf++ = text[digits]; + width--; + maxlen--; + } + + if (flags & LADJUST) + { + while (width-- && maxlen) + { + *buf++ = (flags & ZEROPAD) ? '0' : ' '; + maxlen--; + } + } + + *buf_p = buf; +} + void AddUInt(char **buf_p, size_t &maxlen, unsigned int val, int width, int flags) { char text[32]; @@ -623,6 +674,13 @@ reswitch: arg++; break; } + case 'b': + { + int *value = (int *)args[arg]; + AddBinary(&buf_p, llen, *value, width, flags); + arg++; + break; + } case 'd': case 'i': { @@ -809,6 +867,15 @@ reswitch: arg++; break; } + case 'b': + { + CHECK_ARGS(0); + cell_t *value; + pCtx->LocalToPhysAddr(params[arg], &value); + AddBinary(&buf_p, llen, *value, width, flags); + arg++; + break; + } case 'd': case 'i': { diff --git a/core/sm_trie.cpp b/core/sm_trie.cpp index 3c518f20b..ac267de70 100644 --- a/core/sm_trie.cpp +++ b/core/sm_trie.cpp @@ -90,3 +90,32 @@ size_t sm_trie_mem_usage(Trie *trie) { return trie->k.mem_usage(); } + +struct trie_iter_data +{ + SM_TRIE_BAD_ITERATOR iter; + void *ptr; + Trie *pTrie; +}; + +void our_trie_iterator(KTrie *pTrie, const char *name, void *& obj, void *data) +{ + trie_iter_data *our_iter; + + our_iter = (trie_iter_data *)data; + our_iter->iter(our_iter->pTrie, name, &obj, our_iter->ptr); +} + +void sm_trie_bad_iterator(Trie *trie, + char *buffer, + size_t maxlength, + SM_TRIE_BAD_ITERATOR iter, + void *data) +{ + trie_iter_data our_iter; + + our_iter.iter = iter; + our_iter.ptr = data; + our_iter.pTrie = trie; + trie->k.bad_iterator(buffer, maxlength, &our_iter, our_trie_iterator); +} diff --git a/core/sm_trie.h b/core/sm_trie.h index ca224d536..8306fd553 100644 --- a/core/sm_trie.h +++ b/core/sm_trie.h @@ -34,6 +34,8 @@ struct Trie; +typedef void (*SM_TRIE_BAD_ITERATOR)(Trie *pTrie, const char *key, void **value, void *data); + Trie *sm_trie_create(); void sm_trie_destroy(Trie *trie); bool sm_trie_insert(Trie *trie, const char *key, void *value); @@ -42,5 +44,10 @@ bool sm_trie_retrieve(Trie *trie, const char *key, void **value); bool sm_trie_delete(Trie *trie, const char *key); void sm_trie_clear(Trie *trie); size_t sm_trie_mem_usage(Trie *trie); +void sm_trie_bad_iterator(Trie *trie, + char *buffer, + size_t maxlength, + SM_TRIE_BAD_ITERATOR iter, + void *data); #endif //_INCLUDE_SOURCEMOD_SIMPLE_TRIE_H_ diff --git a/editor/crimson/spec/sourcepawn.key b/editor/crimson/spec/sourcepawn.key index 861553202..1868916c3 100644 --- a/editor/crimson/spec/sourcepawn.key +++ b/editor/crimson/spec/sourcepawn.key @@ -15,7 +15,7 @@ cellsof chars sizeof tagof # Predefined constants false true cellbits cellmax cellmin charbits charmax charmin myinfo INVALID_HANDLE -__version +__version NULL_VECTOR NULL_STRING # Predefined tag names bool Float Handle String diff --git a/editor/crimson/tools/compile.cmd b/editor/crimson/tools/compile.cmd new file mode 100644 index 0000000000000000000000000000000000000000..4c9e9064ce52e4f7a8abe3cd4f5630afcde82cf4 GIT binary patch literal 553 zcmWG7PAyV!&d<$F%u7)))-y3+zycVN#9(Y8pjdEzX;E^jZ+;5Mgo4bR)FM@&XpvP+ zF<2ruKP9H5s5CD-rXZ&@Ju|O3rnn#(s8BDpBGntHP({NHsK+lcH&s(XHy^Gor8p+J zxTGjEJ2fUTB_$uE4Q?FFAc)qG%#xf`O}*mW3NE;DE}2D|FgJo|7#qk$0m$OWY-B~q K;>hfgs0ILzG&@)T literal 0 HcmV?d00001 diff --git a/gamedata/sdktools.games.txt b/gamedata/sdktools.games.txt index 7a5e99de8..04c53078f 100644 --- a/gamedata/sdktools.games.txt +++ b/gamedata/sdktools.games.txt @@ -415,6 +415,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "217" + "linux" "218" + } } } @@ -493,6 +498,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "217" + "linux" "218" + } } } @@ -572,6 +582,11 @@ "windows" "30" "linux" "31" } + "WeaponEquip" + { + "windows" "211" + "linux" "212" + } /* Temp Entities */ "TE_GetServerClass" @@ -675,6 +690,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "220" + "linux" "221" + } /* Offset into CBaseTempEntity constructor. * On Windows Dsytopia is heavily inlined; we use the function @@ -767,6 +787,11 @@ "windows" "24" "linux" "25" } + "WeaponEquip" + { + "windows" "215" + "linux" "216" + } } } @@ -846,6 +871,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "217" + "linux" "218" + } } } @@ -1020,6 +1050,11 @@ "windows" "27" "linux" "28" } + "WeaponEquip" + { + "windows" "227" + "linux" "228" + } } "Signatures" @@ -1187,6 +1222,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "221" + "linux" "222" + } /* Offset into LevelShutdown for CGlobalEntList */ "gEntList" @@ -1281,6 +1321,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "217" + "linux" "218" + } } } @@ -1360,6 +1405,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "217" + "linux" "218" + } } } @@ -1440,6 +1490,11 @@ "windows" "0" "linux" "0" } + "WeaponEquip" + { + "windows" "198" + "linux" "199" + } } "Signatures" @@ -1537,6 +1592,11 @@ { "windows" "7" } + "WeaponEquip" + { + "windows" "198" + "linux" "199" + } } "Signatures" @@ -1656,6 +1716,11 @@ "windows" "25" "linux" "26" } + "WeaponEquip" + { + "windows" "219" + "linux" "220" + } } "Signatures" { diff --git a/plugins/include/tf2.inc b/plugins/include/tf2.inc index 8838c72ab..1cab534d8 100644 --- a/plugins/include/tf2.inc +++ b/plugins/include/tf2.inc @@ -67,16 +67,6 @@ enum TFTeam */ native TF2_SetPlayerInvuln(client, bool:enabled); - -/** - * Sets a client on fire for 10 seconds. - * - * @param client Player's index. - * @noreturn - * @error Invalid client index, client not in game, or no mod support. - */ -native TF2_IgnitePlayer(client, target); - /** * Respawns a client * diff --git a/public/sm_trie_tpl.h b/public/sm_trie_tpl.h index dce77f46d..61b8f1e50 100644 --- a/public/sm_trie_tpl.h +++ b/public/sm_trie_tpl.h @@ -648,6 +648,117 @@ public: return false; } + + /** + * @brief Iterates over the trie returning all known values. + * + * Note: This function is for debugging. Do not use it as a + * production iterator since it's inefficient. Iteration is + * guaranteed to be sorted ascendingly. + * + * The callback function takes: + * (KTrie) - Pointer to this Trie + * (const char *) - String containing key name. + * (K &) - By-reference object at the key. + * (data) - User pointer. + * + * @param buffer Buffer to use as a key name cache. + * @param maxlength Maximum length of the key name buffer. + * @param data User pointer for passing to the iterator. + * @param func Iterator callback function. + */ + void bad_iterator(char *buffer, + size_t maxlength, + void *data, + void (*func)(KTrie *, const char *, K & obj, void *data)) + { + bad_iterator_r(buffer, maxlength, 0, data, func, 1); + } + +private: + void bad_iterator_r(char *buffer, + size_t maxlength, + size_t buf_pos, + void *data, + void (*func)(KTrie *, const char *, K & obj, void *data), + unsigned int root) + { + char *term; + unsigned int idx, limit, start; + + limit = 255; + start = m_base[root].idx; + + /* Bound our limits */ + if (start + limit > m_baseSize) + { + limit = m_baseSize - start; + } + + /* Search for strings */ + for (unsigned int i = 1; i <= limit; i++) + { + idx = start + i; + if (m_base[idx].mode == Node_Unused + || m_base[idx].parent != root) + { + continue; + } + + if (m_base[idx].mode == Node_Arc) + { + if (buf_pos < maxlength - 1) + { + buffer[buf_pos++] = (char)i; + } + + if (m_base[idx].valset) + { + buffer[buf_pos] = '\0'; + func(this, buffer, m_base[idx].value, data); + } + + bad_iterator_r(buffer, + maxlength, + buf_pos, + data, + func, + idx); + + buf_pos--; + } + else if (m_base[idx].mode == Node_Term + && m_base[idx].valset == true) + { + size_t save_buf_pos; + + save_buf_pos = buf_pos; + if (buf_pos < maxlength - 1) + { + buffer[buf_pos++] = (char)i; + } + if (buf_pos < maxlength - 1) + { + size_t destlen, j; + + term = &m_stringtab[m_base[idx].idx]; + destlen = strlen(term); + for (j = 0; + j < destlen && j + buf_pos < maxlength - 1; + j++) + { + buffer[buf_pos + j] = term[j]; + } + buf_pos += j; + } + buffer[buf_pos] = '\0'; + + func(this, buffer, m_base[idx].value, data); + + buf_pos = save_buf_pos; + } + } + } public: KTrie() { diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.c index f6e5bb261..db5399582 100644 --- a/sourcepawn/compiler/sc1.c +++ b/sourcepawn/compiler/sc1.c @@ -2777,15 +2777,21 @@ static cell initarray(int ident,int tag,int dim[],int numdim,int cur, constvalue *enumroot,int *errorfound) { cell dsize,totalsize; - int idx,abortparse; + int idx,abortparse,needbrace; assert(cur>=0 && cur=0); assert(cur+2<=numdim);/* there must be 2 dimensions or more to do */ assert(errorfound!=NULL && *errorfound==FALSE); totalsize=0; + needbrace=1; needtoken('{'); for (idx=0,abortparse=FALSE; !abortparse; idx++) { + if (matchtoken('}')) + { + needbrace=0; + break; + } /* In case the major dimension is zero, we need to store the offset * to the newly detected sub-array into the indirection table; i.e. * this table needs to be expanded and updated. @@ -2815,7 +2821,10 @@ static cell initarray(int ident,int tag,int dim[],int numdim,int cur, if (*errorfound || !matchtoken(',')) abortparse=TRUE; } /* for */ - needtoken('}'); + if (needbrace) + { + needtoken('}'); + } assert(counteddim!=NULL); if (counteddim[cur]>0) { if (idx(int)size) { /* e.g. "myvar[3]={1,2,3,4};" */ - error(18); /* initialisation data exceeds declared size */ + error(18); /* initialization data exceeds declared size */ litidx=(int)size+curlit; /* avoid overflow in memory moves */ } /* if */ return size;