1.1 --- a/core/CTextParsers.cpp Sat Dec 09 03:18:48 2006 +0000
1.2 +++ b/core/CTextParsers.cpp Sun Dec 10 09:19:59 2006 +0000
1.3 @@ -587,6 +587,8 @@
1.4 *line = curline;
1.5 }
1.6
1.7 + smc->ReadSMC_ParseEnd(true, (err == SMCParse_Custom));
1.8 +
1.9 if (col)
1.10 {
1.11 *col = curtok;
2.1 --- a/core/msvc8/sourcemod_mm.vcproj Sat Dec 09 03:18:48 2006 +0000
2.2 +++ b/core/msvc8/sourcemod_mm.vcproj Sun Dec 10 09:19:59 2006 +0000
2.3 @@ -41,7 +41,7 @@
2.4 Name="VCCLCompilerTool"
2.5 Optimization="0"
2.6 AdditionalIncludeDirectories="..\interfaces;..\;..\systems;..\..\sourcepawn\include"
2.7 - PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMOD_MM_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
2.8 + PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMOD_MM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
2.9 MinimalRebuild="true"
2.10 BasicRuntimeChecks="3"
2.11 RuntimeLibrary="1"
2.12 @@ -118,7 +118,7 @@
2.13 <Tool
2.14 Name="VCCLCompilerTool"
2.15 AdditionalIncludeDirectories="..\interfaces;..\"
2.16 - PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMOD_MM_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
2.17 + PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMOD_MM_EXPORTS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE"
2.18 RuntimeLibrary="0"
2.19 UsePrecompiledHeader="0"
2.20 WarningLevel="3"
2.21 @@ -183,6 +183,10 @@
2.22 >
2.23 </File>
2.24 <File
2.25 + RelativePath="..\sm_memtable.cpp"
2.26 + >
2.27 + </File>
2.28 + <File
2.29 RelativePath="..\sourcemm_api.cpp"
2.30 >
2.31 </File>
2.32 @@ -205,6 +209,10 @@
2.33 >
2.34 </File>
2.35 <File
2.36 + RelativePath="..\sm_memtable.h"
2.37 + >
2.38 + </File>
2.39 + <File
2.40 RelativePath="..\sm_platform.h"
2.41 >
2.42 </File>
2.43 @@ -248,6 +256,10 @@
2.44 >
2.45 </File>
2.46 <File
2.47 + RelativePath="..\systems\PluginInfoDatabase.h"
2.48 + >
2.49 + </File>
2.50 + <File
2.51 RelativePath="..\systems\PluginSys.h"
2.52 >
2.53 </File>
2.54 @@ -268,6 +280,10 @@
2.55 >
2.56 </File>
2.57 <File
2.58 + RelativePath="..\systems\PluginInfoDatabase.cpp"
2.59 + >
2.60 + </File>
2.61 + <File
2.62 RelativePath="..\systems\PluginSys.cpp"
2.63 >
2.64 </File>
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/core/sm_memtable.cpp Sun Dec 10 09:19:59 2006 +0000
3.3 @@ -0,0 +1,85 @@
3.4 +#include <string.h>
3.5 +#include <malloc.h>
3.6 +#include "sm_memtable.h"
3.7 +
3.8 +BaseMemTable::BaseMemTable(unsigned int init_size)
3.9 +{
3.10 + membase = (unsigned char *)malloc(init_size);
3.11 + size = init_size;
3.12 +}
3.13 +
3.14 +BaseMemTable::~BaseMemTable()
3.15 +{
3.16 + free(membase);
3.17 + membase = NULL;
3.18 +}
3.19 +
3.20 +int BaseMemTable::CreateMem(unsigned int addsize, void **addr)
3.21 +{
3.22 + int idx = (int)tail;
3.23 +
3.24 + if (idx < 0)
3.25 + {
3.26 + return -1;
3.27 + }
3.28 +
3.29 + while (tail + addsize >= size)
3.30 + {
3.31 + size *= 2;
3.32 + membase = (unsigned char *)realloc(membase, size);
3.33 + }
3.34 +
3.35 + tail += addsize;
3.36 +
3.37 + if (addr)
3.38 + {
3.39 + *addr = (void *)&membase[idx];
3.40 + }
3.41 +
3.42 + return idx;
3.43 +}
3.44 +
3.45 +void *BaseMemTable::GetAddress(int index)
3.46 +{
3.47 + if (index < 0 || (unsigned int)index >= tail)
3.48 + {
3.49 + return NULL;
3.50 + }
3.51 +
3.52 + return &membase[index];
3.53 +}
3.54 +
3.55 +void BaseMemTable::Reset()
3.56 +{
3.57 + tail = 0;
3.58 +}
3.59 +
3.60 +BaseStringTable::BaseStringTable(unsigned int init_size) : m_table(init_size)
3.61 +{
3.62 +}
3.63 +
3.64 +BaseStringTable::~BaseStringTable()
3.65 +{
3.66 +}
3.67 +
3.68 +int BaseStringTable::AddString(const char *string)
3.69 +{
3.70 + size_t len = strlen(string) + 1;
3.71 + int idx;
3.72 + char *addr;
3.73 +
3.74 + idx = m_table.CreateMem(len, (void **)&addr);
3.75 + strcpy(addr, string);
3.76 +
3.77 + return idx;
3.78 +}
3.79 +
3.80 +const char *BaseStringTable::GetString(int str)
3.81 +{
3.82 + return (const char *)m_table.GetAddress(str);
3.83 +}
3.84 +
3.85 +void BaseStringTable::Reset()
3.86 +{
3.87 + m_table.Reset();
3.88 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/core/sm_memtable.h Sun Dec 10 09:19:59 2006 +0000
4.3 @@ -0,0 +1,69 @@
4.4 +#ifndef _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
4.5 +#define _INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
4.6 +
4.7 +class BaseMemTable
4.8 +{
4.9 +public:
4.10 + BaseMemTable(unsigned int init_size);
4.11 + ~BaseMemTable();
4.12 +public:
4.13 + /**
4.14 + * Allocates 'size' bytes of memory.
4.15 + * Optionally outputs the address through 'addr'.
4.16 + * Returns an index >= 0 on success, < 0 on failure.
4.17 + */
4.18 + int CreateMem(unsigned int size, void **addr);
4.19 +
4.20 + /**
4.21 + * Given an index into the memory table, returns its address.
4.22 + * Returns NULL if invalid.
4.23 + */
4.24 + void *GetAddress(int index);
4.25 +
4.26 + /**
4.27 + * Scraps the memory table. For caching purposes, the memory
4.28 + * is not freed, however subsequent calls to CreateMem() will
4.29 + * begin at the first index again.
4.30 + */
4.31 + void Reset();
4.32 +private:
4.33 + unsigned char *membase;
4.34 + unsigned int size;
4.35 + unsigned int tail;
4.36 +};
4.37 +
4.38 +class BaseStringTable
4.39 +{
4.40 +public:
4.41 + BaseStringTable(unsigned int init_size);
4.42 + ~BaseStringTable();
4.43 +public:
4.44 + /**
4.45 + * Adds a string to the string table and returns its index.
4.46 + */
4.47 + int AddString(const char *string);
4.48 +
4.49 + /**
4.50 + * Given an index into the string table, returns the associated string.
4.51 + */
4.52 + const char *GetString(int str);
4.53 +
4.54 + /**
4.55 + * Scraps the string table. For caching purposes, the memory
4.56 + * is not freed, however subsequent calls to AddString() will
4.57 + * begin at the first index again.
4.58 + */
4.59 + void Reset();
4.60 +
4.61 + /**
4.62 + * Returns the parent BaseMemTable that this string table uses.
4.63 + */
4.64 + inline BaseMemTable *GetMemTable()
4.65 + {
4.66 + return &m_table;
4.67 + }
4.68 +private:
4.69 + BaseMemTable m_table;
4.70 +};
4.71 +
4.72 +#endif //_INCLUDE_SOURCEMOD_CORE_STRINGTABLE_H_
5.1 --- a/core/sm_platform.h Sat Dec 09 03:18:48 2006 +0000
5.2 +++ b/core/sm_platform.h Sun Dec 10 09:19:59 2006 +0000
5.3 @@ -13,6 +13,7 @@
5.4 #if !defined snprintf
5.5 #define snprintf _snprintf
5.6 #endif
5.7 +#define strcasecmp strcmpi
5.8 #include <windows.h>
5.9 #include <direct.h>
5.10 #define PLATFORM_LIB_EXT "dll"
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/core/systems/PluginInfoDatabase.cpp Sun Dec 10 09:19:59 2006 +0000
6.3 @@ -0,0 +1,266 @@
6.4 +#include <stdarg.h>
6.5 +#include <string.h>
6.6 +#include "PluginInfoDatabase.h"
6.7 +#include "PluginSys.h"
6.8 +
6.9 +void PluginSettings::Init()
6.10 +{
6.11 + name = -1;
6.12 + pause_val = false;
6.13 + type_val = PluginType_MapUpdated;
6.14 + optarray = -1;
6.15 + opts_num = 0;
6.16 + opts_size = 0;
6.17 +}
6.18 +
6.19 +/**
6.20 + * :TODO: write the logger, make these errors log instead of being static
6.21 + * NOTE: once we do that, we will have to change some code to ignore sections
6.22 + */
6.23 +
6.24 +CPluginInfoDatabase::CPluginInfoDatabase()
6.25 +{
6.26 + m_strtab = NULL;
6.27 + m_infodb_count = 0;
6.28 + m_infodb_size = 0;
6.29 + m_infodb = -1;
6.30 +}
6.31 +
6.32 +CPluginInfoDatabase::~CPluginInfoDatabase()
6.33 +{
6.34 + delete m_strtab;
6.35 +}
6.36 +
6.37 +void CPluginInfoDatabase::ReadSMC_ParseStart()
6.38 +{
6.39 + /* Create or reset our string table */
6.40 + if (m_strtab)
6.41 + {
6.42 + m_strtab->Reset();
6.43 + } else {
6.44 + m_strtab = new BaseStringTable(1024);
6.45 + }
6.46 +
6.47 + /* Set our internal states to the beginning */
6.48 + in_plugins = false;
6.49 + cur_plugin = -1;
6.50 + in_options = false;
6.51 +}
6.52 +
6.53 +SMCParseResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
6.54 +{
6.55 + char buffer[512];
6.56 + va_list ap;
6.57 +
6.58 + va_start(ap, fmt);
6.59 + vsnprintf(buffer, sizeof(buffer), fmt, ap);
6.60 + va_end(ap);
6.61 +
6.62 + m_errmsg = m_strtab->AddString(buffer);
6.63 +
6.64 + return SMCParse_HaltFail;
6.65 +}
6.66 +
6.67 +unsigned int CPluginInfoDatabase::GetSettingsNum()
6.68 +{
6.69 + return m_infodb_count;
6.70 +}
6.71 +
6.72 +PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
6.73 +{
6.74 + BaseMemTable *memtab = m_strtab->GetMemTable();
6.75 + PluginSettings *table = (PluginSettings *)memtab->GetAddress(m_infodb);
6.76 +
6.77 + if (!table || index >= m_infodb_count)
6.78 + {
6.79 + return NULL;
6.80 + }
6.81 +
6.82 + const char *name = m_strtab->GetString(table[index].name);
6.83 +
6.84 + if (!name)
6.85 + {
6.86 + return NULL;
6.87 + }
6.88 +
6.89 + if (!g_PluginMngr.TestAliasMatch(name, filename))
6.90 + {
6.91 + return NULL;
6.92 + }
6.93 +
6.94 + return &table[index];
6.95 +}
6.96 +
6.97 +void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
6.98 +{
6.99 + PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
6.100 + if (!table)
6.101 + {
6.102 + *key = NULL;
6.103 + *val = NULL;
6.104 + return;
6.105 + }
6.106 +
6.107 + if (opt_num >= settings->opts_num)
6.108 + {
6.109 + *key = NULL;
6.110 + *val = NULL;
6.111 + return;
6.112 + }
6.113 +
6.114 + *key = m_strtab->GetString(table[opt_num].key);
6.115 + *val = m_strtab->GetString(table[opt_num].val);
6.116 +}
6.117 +
6.118 +SMCParseResult CPluginInfoDatabase::ReadSMC_KeyValue(const char *key,
6.119 + const char *value,
6.120 + bool key_quotes,
6.121 + bool value_quotes)
6.122 +{
6.123 + if (cur_plugin != -1)
6.124 + {
6.125 + PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
6.126 + if (!in_options)
6.127 + {
6.128 + if (strcmp(key, "pause") == 0)
6.129 + {
6.130 + if (strcasecmp(value, "yes") == 0)
6.131 + {
6.132 + plugin->pause_val = true;
6.133 + } else {
6.134 + plugin->pause_val = false;
6.135 + }
6.136 + } else if (strcmp(key, "lifetime") == 0) {
6.137 + if (strcasecmp(value, "private") == 0)
6.138 + {
6.139 + plugin->type_val = PluginType_Private;
6.140 + } else if (strcasecmp(value, "mapsync") == 0) {
6.141 + plugin->type_val = PluginType_MapUpdated;
6.142 + } else if (strcasecmp(value, "maponly") == 0) {
6.143 + plugin->type_val = PluginType_MapOnly;
6.144 + } else if (strcasecmp(value, "global") == 0) {
6.145 + plugin->type_val = PluginType_Global;
6.146 + } else {
6.147 + return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
6.148 + }
6.149 + } else {
6.150 + return MakeError("Unknown property key: \"%s\"", key);
6.151 + }
6.152 + } else {
6.153 + /* Cache every option, valid or not */
6.154 + int keyidx = m_strtab->AddString(key);
6.155 + int validx = m_strtab->AddString(value);
6.156 + PluginOpts *table;
6.157 + BaseMemTable *memtab = m_strtab->GetMemTable();
6.158 + if (plugin->opts_num + 1 > plugin->opts_size)
6.159 + {
6.160 + unsigned int oldsize = plugin->opts_size;
6.161 + if (oldsize == 0)
6.162 + {
6.163 + //right now we don't have many
6.164 + plugin->opts_size = 2;
6.165 + } else {
6.166 + plugin->opts_size *= 2;
6.167 + }
6.168 + int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
6.169 + if (plugin->optarray != -1)
6.170 + {
6.171 + void *oldtable = memtab->GetAddress(plugin->optarray);
6.172 + memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
6.173 + }
6.174 + plugin->optarray = newidx;
6.175 + } else {
6.176 + table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
6.177 + }
6.178 + PluginOpts *opt = &table[plugin->opts_num++];
6.179 + opt->key = keyidx;
6.180 + opt->val = validx;
6.181 + }
6.182 + } else if (in_plugins) {
6.183 + return MakeError("Unknown property key: \"%s\"", key);
6.184 + } else {
6.185 + /* Ignore anything we don't know about! */
6.186 + }
6.187 +
6.188 + return SMCParse_Continue;
6.189 +}
6.190 +
6.191 +SMCParseResult CPluginInfoDatabase::ReadSMC_LeavingSection()
6.192 +{
6.193 + if (in_plugins)
6.194 + {
6.195 + if (cur_plugin == -1)
6.196 + {
6.197 + if (in_options)
6.198 + {
6.199 + in_options = false;
6.200 + } else {
6.201 + /* If the plugin is ending, add it to the table */
6.202 + BaseMemTable *memtab = m_strtab->GetMemTable();
6.203 + int *table;
6.204 + if (m_infodb_count + 1 > m_infodb_size)
6.205 + {
6.206 + unsigned int oldsize = m_infodb_size;
6.207 + if (!m_infodb_size)
6.208 + {
6.209 + m_infodb_size = 8;
6.210 + } else {
6.211 + m_infodb_size *= 2;
6.212 + }
6.213 + int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
6.214 + if (m_infodb != -1)
6.215 + {
6.216 + void *oldtable = (int *)memtab->GetAddress(m_infodb);
6.217 + memcpy(table, oldtable, oldsize * sizeof(int));
6.218 + }
6.219 + m_infodb = newidx;
6.220 + } else {
6.221 + table = (int *)memtab->GetAddress(m_infodb);
6.222 + }
6.223 + /* Assign to table and scrap the current plugin */
6.224 + table[m_infodb_count++] = cur_plugin;
6.225 + cur_plugin = -1;
6.226 + }
6.227 + } else {
6.228 + in_plugins = false;
6.229 + }
6.230 + }
6.231 +
6.232 + return SMCParse_Continue;
6.233 +}
6.234 +
6.235 +SMCParseResult CPluginInfoDatabase::ReadSMC_NewSection(const char *name, bool opt_quotes)
6.236 +{
6.237 + if (!in_plugins)
6.238 + {
6.239 + /* If we're not in the main Plugins section, and we don't get it for the name, error out */
6.240 + if (strcmp(name, "Plugins") != 0)
6.241 + {
6.242 + return MakeError("Unknown root section: \"%s\"", name);
6.243 + } else {
6.244 + /* Otherwise set our states */
6.245 + in_plugins = true;
6.246 + cur_plugin = -1;
6.247 + in_options = false;
6.248 + }
6.249 + } else {
6.250 + if (cur_plugin == -1)
6.251 + {
6.252 + /* If we get a plugin node and we don't have a current plugin, create a new one */
6.253 + PluginSettings *plugin;
6.254 + cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
6.255 + plugin->Init();
6.256 + plugin->name = m_strtab->AddString(name);
6.257 + in_options = false;
6.258 + } else {
6.259 + if (!in_options && strcmp(name, "Options") == 0)
6.260 + {
6.261 + in_options = true;
6.262 + } else {
6.263 + return MakeError("Unknown plugin sub-section: \"%s\"", name);
6.264 + }
6.265 + }
6.266 + }
6.267 +
6.268 + return SMCParse_Continue;
6.269 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/core/systems/PluginInfoDatabase.h Sun Dec 10 09:19:59 2006 +0000
7.3 @@ -0,0 +1,74 @@
7.4 +#ifndef _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
7.5 +#define _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
7.6 +
7.7 +/**
7.8 + * This file parses plugin_settings.cfg and stores the information in cached memory.
7.9 + * It provides simplistic abstraction to retrieving the info.
7.10 + * :TODO: currently untested
7.11 + */
7.12 +
7.13 +#include "sm_memtable.h"
7.14 +#include "ITextParsers.h"
7.15 +#include "IPluginSys.h"
7.16 +#include "sm_globals.h"
7.17 +
7.18 +struct PluginOpts
7.19 +{
7.20 + int key;
7.21 + int val;
7.22 +};
7.23 +
7.24 +struct PluginSettings
7.25 +{
7.26 + void Init();
7.27 + int name;
7.28 + bool pause_val;
7.29 + PluginType type_val;
7.30 + int optarray;
7.31 + size_t opts_num;
7.32 + size_t opts_size;
7.33 +};
7.34 +
7.35 +class CPluginInfoDatabase : public ITextListener_SMC
7.36 +{
7.37 +public:
7.38 + CPluginInfoDatabase();
7.39 + ~CPluginInfoDatabase();
7.40 +public: //ITextListener_SMC
7.41 + void ReadSMC_ParseStart();
7.42 + SMCParseResult ReadSMC_NewSection(const char *name, bool opt_quotes);
7.43 + SMCParseResult ReadSMC_KeyValue(const char *key, const char *value, bool key_quotes, bool value_quotes);
7.44 + SMCParseResult ReadSMC_LeavingSection();
7.45 +public:
7.46 + /**
7.47 + * Returns the number of plugin settings available.
7.48 + */
7.49 + unsigned int GetSettingsNum();
7.50 +
7.51 + /**
7.52 + * Given an index, returns the plugin settings block if the filename matches.
7.53 + * Otherwise, returns NULL.
7.54 + */
7.55 + PluginSettings *GetSettingsIfMatch(unsigned int index, const char *filename);
7.56 +
7.57 + /**
7.58 + * Given a plugin settings struct and an index,
7.59 + * returns the given JIT key/value option pair at that index.
7.60 + * If the input is invalid, key and val will be set to NULL.
7.61 + */
7.62 + void GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val);
7.63 +private:
7.64 + SMCParseResult MakeError(const char *fmt, ...);
7.65 +private:
7.66 + BaseStringTable *m_strtab;
7.67 + int m_errmsg;
7.68 + bool in_plugins;
7.69 + bool in_options;
7.70 + unsigned int m_infodb;
7.71 + size_t m_infodb_count;
7.72 + size_t m_infodb_size;
7.73 + int cur_plugin;
7.74 +};
7.75 +
7.76 +
7.77 +#endif //_INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
8.1 --- a/core/systems/PluginSys.cpp Sat Dec 09 03:18:48 2006 +0000
8.2 +++ b/core/systems/PluginSys.cpp Sun Dec 10 09:19:59 2006 +0000
8.3 @@ -2,6 +2,7 @@
8.4 #include "PluginSys.h"
8.5 #include "LibrarySys.h"
8.6 #include "sourcemm_api.h"
8.7 +#include "CTextParsers.h"
8.8
8.9 CPluginManager g_PluginMngr;
8.10
8.11 @@ -288,9 +289,19 @@
8.12 * PLUGIN MANAGER *
8.13 ******************/
8.14
8.15 -void CPluginManager::RefreshOrLoadPlugins(const char *basedir)
8.16 +void CPluginManager::RefreshOrLoadPlugins(const char *config, const char *basedir)
8.17 {
8.18 - IDirectory *dir = g_LibSys.OpenDirectory(basedir);
8.19 + /* First read in the database of plugin settings */
8.20 + SMCParseError err;
8.21 + unsigned int line, col;
8.22 + if ((err=g_TextParse.ParseFile_SMC(config, &m_PluginInfo, &line, &col)) != SMCParse_Okay)
8.23 + {
8.24 + /* :TODO: log the error, don't bail out though */
8.25 + }
8.26 +
8.27 +
8.28 + //:TODO: move this to a separate recursive function and do stuff
8.29 + /*IDirectory *dir = g_LibSys.OpenDirectory(basedir);
8.30 while (dir->MoreFiles())
8.31 {
8.32 if (dir->IsEntryDirectory() && (strcmp(dir->GetEntryName(), "disabled") != 0))
8.33 @@ -300,7 +311,7 @@
8.34 RefreshOrLoadPlugins(basedir);
8.35 }
8.36 }
8.37 - g_LibSys.CloseDirectory(dir);
8.38 + g_LibSys.CloseDirectory(dir);*/
8.39 }
8.40
8.41 IPlugin *CPluginManager::LoadPlugin(const char *path, bool debug, PluginType type, char error[], size_t err_max)
8.42 @@ -446,6 +457,215 @@
8.43 }
8.44 }
8.45
8.46 +bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath)
8.47 +{
8.48 + /* As an optimization, we do not call strlen, but compute the length in the first pass */
8.49 + size_t alias_len = 0;
8.50 + size_t local_len = 0;
8.51 +
8.52 + const char *ptr = alias;
8.53 + unsigned int alias_explicit_paths = 0;
8.54 + unsigned int alias_path_end = 0;
8.55 + while (*ptr != '\0')
8.56 + {
8.57 + if (*ptr == '\\' || *ptr == '/')
8.58 + {
8.59 + alias_explicit_paths++;
8.60 + alias_path_end = alias_len;
8.61 + }
8.62 + alias_len++;
8.63 + ptr++;
8.64 + }
8.65 +
8.66 + if (alias_path_end == alias_len - 1)
8.67 + {
8.68 + /* Trailing slash is totally invalid here */
8.69 + return false;
8.70 + }
8.71 +
8.72 + ptr = localpath;
8.73 + unsigned int local_explicit_paths = 0;
8.74 + unsigned int local_path_end = 0;
8.75 + while (*ptr != '\0')
8.76 + {
8.77 + if (*ptr == '\\' || *ptr == '/')
8.78 + {
8.79 + local_explicit_paths++;
8.80 + local_path_end = local_len;
8.81 + }
8.82 + local_len++;
8.83 + ptr++;
8.84 + }
8.85 +
8.86 + /* If the alias has more explicit paths than the real path,
8.87 + * no match will be possible.
8.88 + */
8.89 + if (alias_explicit_paths > local_explicit_paths)
8.90 + {
8.91 + return false;
8.92 + }
8.93 +
8.94 + if (alias_explicit_paths)
8.95 + {
8.96 + /* We need to find if the paths match now. For example, these should all match:
8.97 + * csdm csdm
8.98 + * csdm optional/csdm
8.99 + * csdm/ban optional/crab/csdm/ban
8.100 + */
8.101 + const char *aliasptr = alias;
8.102 + const char *localptr = localpath;
8.103 + bool match = true;
8.104 + do
8.105 + {
8.106 + if (*aliasptr != *localptr)
8.107 + {
8.108 + /* We have to knock one path off */
8.109 + local_explicit_paths--;
8.110 + if (alias_explicit_paths > local_explicit_paths)
8.111 + {
8.112 + /* Skip out if we're gonna have an impossible match */
8.113 + return false;
8.114 + }
8.115 + /* Eat up localptr tokens until we get a result */
8.116 + while (((localptr - localpath) < (int)local_path_end)
8.117 + && *localptr != '/'
8.118 + && *localptr != '\\')
8.119 + {
8.120 + localptr++;
8.121 + }
8.122 + /* Check if we hit the end of our searchable area.
8.123 + * This probably isn't possible because of the path
8.124 + * count check, but it's a good idea anyway.
8.125 + */
8.126 + if ((localptr - localpath) >= (int)local_path_end)
8.127 + {
8.128 + return false;
8.129 + } else {
8.130 + /* Consume the slash token */
8.131 + localptr++;
8.132 + }
8.133 + /* Reset the alias pointer so we can continue consuming */
8.134 + aliasptr = alias;
8.135 + match = false;
8.136 + continue;
8.137 + }
8.138 + /* Note:
8.139 + * This is safe because if localptr terminates early, aliasptr will too
8.140 + */
8.141 + do
8.142 + {
8.143 + /* We should never reach the end of the string because of this check. */
8.144 + bool aliasend = (aliasptr - alias) > (int)alias_path_end;
8.145 + bool localend = (localptr - localpath) > (int)local_path_end;
8.146 + if (aliasend || localend)
8.147 + {
8.148 + if (aliasend && localend)
8.149 + {
8.150 + /* we matched, and we can break out now */
8.151 + match = true;
8.152 + break;
8.153 + }
8.154 + /* Otherwise, we've hit the end somehow and rest won't match up. Break out. */
8.155 + match = false;
8.156 + break;
8.157 + }
8.158 +
8.159 + /* If we got here, it's safe to compare the next two tokens */
8.160 + if (*localptr != *aliasptr)
8.161 + {
8.162 + match = false;
8.163 + break;
8.164 + }
8.165 + localptr++;
8.166 + aliasptr++;
8.167 + } while (true);
8.168 + } while (!match);
8.169 + }
8.170 +
8.171 + /* If we got here, it's time to compare filenames */
8.172 + const char *aliasptr = alias;
8.173 + const char *localptr = localpath;
8.174 +
8.175 + if (alias_explicit_paths)
8.176 + {
8.177 + aliasptr = &alias[alias_path_end + 1];
8.178 + }
8.179 +
8.180 + if (local_explicit_paths)
8.181 + {
8.182 + localptr = &localpath[local_path_end + 1];
8.183 + }
8.184 +
8.185 + while (true)
8.186 + {
8.187 + if (*aliasptr == '*')
8.188 + {
8.189 + /* First, see if this is the last character */
8.190 + if (aliasptr - alias == alias_len - 1)
8.191 + {
8.192 + /* If so, there's no need to match anything else */
8.193 + return true;
8.194 + }
8.195 + /* Otherwise, we need to search for an appropriate matching sequence in local.
8.196 + * Note that we only need to search up to the next asterisk.
8.197 + */
8.198 + aliasptr++;
8.199 + bool match = true;
8.200 + const char *local_orig = localptr;
8.201 + do
8.202 + {
8.203 + match = true;
8.204 + while (*aliasptr != '\0' && *aliasptr != '*')
8.205 + {
8.206 + /* Since aliasptr is never '\0', localptr hitting the end will fail */
8.207 + if (*aliasptr != *localptr)
8.208 + {
8.209 + match = false;
8.210 + break;
8.211 + }
8.212 + aliasptr++;
8.213 + localptr++;
8.214 + }
8.215 + if (!match)
8.216 + {
8.217 + /* If we didn't get a match, we need to advance the search stream.
8.218 + * This will let us skip tokens while still searching for another match.
8.219 + */
8.220 + localptr = ++local_orig;
8.221 + /* Make sure we don't go out of bounds */
8.222 + if (*localptr == '\0')
8.223 + {
8.224 + break;
8.225 + }
8.226 + }
8.227 + } while (!match);
8.228 +
8.229 + if (!match)
8.230 + {
8.231 + return false;
8.232 + } else {
8.233 + /* If we got a match, move on to the next token */
8.234 + continue;
8.235 + }
8.236 + } else if (*aliasptr == '\0') {
8.237 + if (*localptr == '\0'
8.238 + ||
8.239 + strcmp(localptr, ".smx") == 0)
8.240 + {
8.241 + return true;
8.242 + } else {
8.243 + return false;
8.244 + }
8.245 + } else if (*aliasptr != *localptr) {
8.246 + return false;
8.247 + }
8.248 + aliasptr++;
8.249 + localptr++;
8.250 + }
8.251 +
8.252 + return true;
8.253 +}
8.254 +
8.255 CPluginManager::~CPluginManager()
8.256 {
8.257 //:TODO: we need a good way to free what we're holding
9.1 --- a/core/systems/PluginSys.h Sat Dec 09 03:18:48 2006 +0000
9.2 +++ b/core/systems/PluginSys.h Sun Dec 10 09:19:59 2006 +0000
9.3 @@ -6,6 +6,7 @@
9.4 #include <sh_stack.h>
9.5 #include "sm_globals.h"
9.6 #include "CFunction.h"
9.7 +#include "PluginInfoDatabase.h"
9.8
9.9 using namespace SourceHook;
9.10
9.11 @@ -60,6 +61,13 @@
9.12 CFunction **m_pub_funcs;
9.13 };
9.14
9.15 +struct PluginDBInfo
9.16 +{
9.17 + bool pause;
9.18 + PluginType lifetime;
9.19 +
9.20 +};
9.21 +
9.22 class CPluginManager : public IPluginManager
9.23 {
9.24 friend class CPlugin;
9.25 @@ -67,6 +75,7 @@
9.26 CPluginManager();
9.27 ~CPluginManager();
9.28 public:
9.29 + /* Implements iterator class */
9.30 class CPluginIterator : public IPluginIterator
9.31 {
9.32 public:
9.33 @@ -83,7 +92,7 @@
9.34 List<IPlugin *>::iterator current;
9.35 };
9.36 friend class CPluginManager::CPluginIterator;
9.37 -public:
9.38 +public: //IPluginManager
9.39 virtual IPlugin *LoadPlugin(const char *path,
9.40 bool debug,
9.41 PluginType type,
9.42 @@ -96,7 +105,21 @@
9.43 virtual void AddPluginsListener(IPluginsListener *listener);
9.44 virtual void RemovePluginsListener(IPluginsListener *listener);
9.45 public:
9.46 - virtual void RefreshOrLoadPlugins(const char *basedir);
9.47 + /**
9.48 + * Refreshes and loads plugins, usually used on mapchange
9.49 + */
9.50 + virtual void RefreshOrLoadPlugins(const char *config, const char *basedir);
9.51 +
9.52 + /**
9.53 + * Tests a plugin file mask against a local folder.
9.54 + * The alias is searched backwards from localdir - i.e., given this input:
9.55 + * csdm/ban csdm/ban
9.56 + * ban csdm/ban
9.57 + * csdm/ban optional/csdm/ban
9.58 + * All of these will return true for an alias match.
9.59 + * Wildcards are allowed in the filename.
9.60 + */
9.61 + virtual bool TestAliasMatch(const char *alias, const char *localdir);
9.62 protected:
9.63 void ReleaseIterator(CPluginIterator *iter);
9.64 CFunction *GetFunctionFromPool(funcid_t f, CPlugin *plugin);
9.65 @@ -106,6 +129,7 @@
9.66 List<IPlugin *> m_plugins;
9.67 CStack<CPluginManager::CPluginIterator *> m_iters;
9.68 CStack<CFunction *> m_funcpool;
9.69 + CPluginInfoDatabase m_PluginInfo;
9.70 };
9.71
9.72 extern CPluginManager g_PluginMngr;