Initial massive import of the new code module auto-loading code

Important difference - pubtags table is used instead of library table!
This commit is contained in:
David Anderson 2006-05-10 02:32:34 +00:00
parent d8c8e72745
commit f600a96657
9 changed files with 201 additions and 188 deletions

View File

@ -36,6 +36,7 @@
#include "amx.h"
#include "natives.h"
#include "debugger.h"
#include "libraries.h"
extern const char *no_function;
@ -472,3 +473,133 @@ void CPluginMngr::InvalidateFileInCache(const char *file, bool freebuf)
}
}
void CPluginMngr::CacheAndLoadModules(const char *plugin)
{
size_t progsize;
char *prog = ReadIntoOrFromCache(plugin, progsize);
if (!prog)
return;
AMX_HEADER hdr;
memcpy(&hdr, prog, sizeof(AMX_HEADER));
uint16_t magic = hdr.magic;
amx_Align16(&magic);
if (magic != AMX_MAGIC)
{
return;
}
if (hdr.file_version < MIN_FILE_VERSION ||
hdr.file_version > CUR_FILE_VERSION)
{
return;
}
if ((hdr.defsize != sizeof(AMX_FUNCSTUB)) &&
(hdr.defsize != sizeof(AMX_FUNCSTUBNT)))
{
return;
}
amx_Align32((uint32_t*)&hdr.nametable);
uint16_t *namelength=(uint16_t*)((unsigned char*)prog + (unsigned)hdr.nametable);
amx_Align16(namelength);
if (*namelength>sNAMEMAX)
{
return;
}
if (hdr.stp <= 0)
{
return;
}
AMX amx;
memset(&amx, 0, sizeof(AMX));
amx.base = (unsigned char *)prog;
int num;
char name[sNAMEMAX+1];
cell tag_id;
amx_NumTags(&amx, &num);
CVector<LibDecoder *> expects;
CVector<LibDecoder *> defaults;
for (int i=0; i<num; i++)
{
amx_GetTag(&amx, i, name, &tag_id);
if (name[0] == '?')
{
LibDecoder *dc = new LibDecoder;
if (DecodeLibCmdString(name, dc))
{
if (dc->cmd == LibCmd_ForceLib)
{
RunLibCommand(dc);
delete dc;
} else if ( (dc->cmd == LibCmd_ExpectClass) ||
(dc->cmd == LibCmd_ExpectLib) )
{
expects.push_back(dc);
} else if (dc->cmd == LibCmd_DefaultLib) {
defaults.push_back(dc);
}
} else {
delete dc;
}
}
}
for (size_t i=0; i<expects.size(); i++)
{
RunLibCommand(expects[i]);
delete expects[i];
}
for (size_t i=0; i<defaults.size(); i++)
{
RunLibCommand(defaults[i]);
delete defaults[i];
}
return;
}
void CPluginMngr::CALMFromFile(const char *file)
{
char filename[256];
FILE *fp = fopen(build_pathname_r(filename, sizeof(filename) - 1, "%s", file), "rt");
if (!fp)
{
return;
}
// Find now folder
char pluginName[256];
char line[256];
const char *pluginsDir = get_localinfo("amxx_pluginsdir", "addons/amxmodx/plugins");
String rline;
while (!feof(fp))
{
fgets(line, sizeof(line)-1, fp);
if (line[0] == ';' || line[0] == '\n' || line[0] == '\0')
continue;
rline.assign(line);
rline.trim();
pluginName[0] = '\0';
sscanf(rline.c_str(), "%s", pluginName);
if (!isalnum(*pluginName))
continue;
build_pathname_r(filename, sizeof(filename)-1, "%s/%s", pluginsDir, pluginName);
CacheAndLoadModules(filename);
}
fclose(fp);
}

View File

@ -161,6 +161,8 @@ public:
char *ReadIntoOrFromCache(const char *file, size_t &bufsize);
void InvalidateCache();
void InvalidateFileInCache(const char *file, bool freebuf);
void CacheAndLoadModules(const char *plugin);
void CALMFromFile(const char *file);
private:
List<plcache_entry *> m_plcache;
};

View File

@ -844,19 +844,6 @@ int AMXAPI amx_Init(AMX *amx, void *program)
{
AMX_HEADER *hdr;
BROWSEHOOK hook = NULL;
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
char libname[sNAMEMAX+8]; /* +1 for '\0', +3 for 'amx' prefix, +4 for extension */
#if defined _Windows
typedef int (FAR WINAPI *AMX_ENTRY)(AMX _FAR *amx);
HINSTANCE hlib;
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
typedef int (*AMX_ENTRY)(AMX *amx);
void *hlib;
#endif
int numlibraries,i;
AMX_FUNCSTUB *lib;
AMX_ENTRY libinit;
#endif
if ((amx->flags & AMX_FLAG_RELOC)!=0)
return AMX_ERR_INIT; /* already initialized (may not do so twice) */
@ -866,22 +853,6 @@ int AMXAPI amx_Init(AMX *amx, void *program)
* multi-byte words
*/
assert(check_endian());
#if BYTE_ORDER==BIG_ENDIAN
amx_Align32((uint32_t*)&hdr->size);
amx_Align16(&hdr->magic);
amx_Align16((uint16_t*)&hdr->flags);
amx_Align16((uint16_t*)&hdr->defsize);
amx_Align32((uint32_t*)&hdr->cod);
amx_Align32((uint32_t*)&hdr->dat);
amx_Align32((uint32_t*)&hdr->hea);
amx_Align32((uint32_t*)&hdr->stp);
amx_Align32((uint32_t*)&hdr->cip);
amx_Align32((uint32_t*)&hdr->publics);
amx_Align32((uint32_t*)&hdr->natives);
amx_Align32((uint32_t*)&hdr->libraries);
amx_Align32((uint32_t*)&hdr->pubvars);
amx_Align32((uint32_t*)&hdr->tags);
#endif
if (hdr->magic!=AMX_MAGIC)
return AMX_ERR_FORMAT;
@ -902,13 +873,7 @@ int AMXAPI amx_Init(AMX *amx, void *program)
} /* if */
if (hdr->stp<=0)
return AMX_ERR_FORMAT;
#if BYTE_ORDER==BIG_ENDIAN
if ((hdr->flags & AMX_FLAG_COMPACT)==0) {
ucell *code=(ucell *)((unsigned char *)program+(int)hdr->cod);
while (code<(ucell *)((unsigned char *)program+(int)hdr->hea))
swapcell(code++);
} /* if */
#endif
assert((hdr->flags & AMX_FLAG_COMPACT)!=0 || hdr->hea == hdr->size);
if ((hdr->flags & AMX_FLAG_COMPACT)!=0) {
#if AMX_COMPACTMARGIN > 2
@ -935,108 +900,12 @@ int AMXAPI amx_Init(AMX *amx, void *program)
amx->callback=amx_Callback;
amx->data=NULL;
/* also align all addresses in the public function, public variable,
* public tag and native function tables --offsets into the name table
* (if present) must also be swapped.
*/
#if BYTE_ORDER==BIG_ENDIAN
{ /* local */
AMX_FUNCSTUB *fs;
int i,num;
fs=GETENTRY(hdr,natives,0);
num=NUMENTRIES(hdr,natives,libraries);
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address); /* redundant, because it should be zero */
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
fs=GETENTRY(hdr,publics,0);
assert(hdr->publics<=hdr->natives);
num=NUMENTRIES(hdr,publics,natives);
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address);
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
fs=GETENTRY(hdr,pubvars,0);
assert(hdr->pubvars<=hdr->tags);
num=NUMENTRIES(hdr,pubvars,tags);
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address);
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
fs=GETENTRY(hdr,tags,0);
if (hdr->file_version<7) {
assert(hdr->tags<=hdr->cod);
num=NUMENTRIES(hdr,tags,cod);
} else {
assert(hdr->tags<=hdr->nametable);
num=NUMENTRIES(hdr,tags,nametable);
} /* if */
for (i=0; i<num; i++) {
amx_AlignCell(&fs->address);
if (USENAMETABLE(hdr))
amx_AlignCell(&((AMX_FUNCSTUBNT*)fs)->nameofs);
fs=(AMX_FUNCSTUB*)((unsigned char *)fs+hdr->defsize);
} /* for */
} /* local */
#endif
/* relocate call and jump instructions */
hook = (BROWSEHOOK)amx->usertags[UT_BROWSEHOOK];
if (hook)
hook(amx, NULL, NULL);
amx_BrowseRelocate(amx);
/* load any extension modules that the AMX refers to */
#if (defined _Windows || defined LINUX || defined __FreeBSD__ || defined __OpenBSD__) && !defined AMX_NODYNALOAD
hdr=(AMX_HEADER *)amx->base;
numlibraries=NUMENTRIES(hdr,libraries,pubvars);
for (i=0; i<numlibraries; i++) {
lib=GETENTRY(hdr,libraries,i);
strcpy(libname,"amx");
strcat(libname,GETENTRYNAME(hdr,lib));
#if defined _Windows
strcat(libname,".dll");
#if defined __WIN32__
hlib=LoadLibraryA(libname);
#else
hlib=LoadLibrary(libname);
if (hlib<=HINSTANCE_ERROR)
hlib=NULL;
#endif
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
strcat(libname,".so");
hlib=dlopen(libname,RTLD_NOW);
#endif
if (hlib!=NULL) {
/* a library that cannot be loaded or that does not have the required
* initialization function is simply ignored
*/
char funcname[sNAMEMAX+9]; /* +1 for '\0', +4 for 'amx_', +4 for 'Init' */
strcpy(funcname,"amx_");
strcat(funcname,GETENTRYNAME(hdr,lib));
strcat(funcname,"Init");
#if defined _Windows
libinit=(AMX_ENTRY)GetProcAddress(hlib,funcname);
#elif defined LINUX || defined __FreeBSD__ || defined __OpenBSD__
libinit=(AMX_ENTRY)dlsym(hlib,funcname);
#endif
if (libinit!=NULL)
libinit(amx);
} /* if */
lib->address=(ucell)hlib;
} /* for */
#endif
return AMX_ERR_NONE;
}

View File

@ -109,7 +109,7 @@ CAmxxReader::CAmxxReader(const char *filename, int cellsize)
{
DATAREAD(&m_Bh.version, sizeof(int16_t), 1);
if (m_Bh.version != MAGIC_VERSION)
if (m_Bh.version > MAGIC_VERSION)
{
m_Status = Err_OldFile;
fclose(m_pFile);

View File

@ -20,62 +20,62 @@ bool AddLibrary(const char *name, LibType type, LibSource src, void *parent)
return true;
}
bool DecodeLibCmdString(const char *str, LibDecoder &dec)
bool DecodeLibCmdString(const char *str, LibDecoder *dec)
{
if (str[0] != '_')
if (dec->buffer)
{
dec.cmd = LibCmd_ReqLib;
dec.buffer = strdup(str);
if (strcmp(str, "dbi") == 0)
dec.cmd = LibCmd_ReqClass;
dec.param1 = dec.buffer;
dec.param2 = NULL;
free(dec->buffer);
dec->buffer = NULL;
}
if (str[0] != '?')
{
return false;
} else {
str++;
if (*str == 'r')
{
str++;
if (*str == 'c')
dec.cmd = LibCmd_ReqClass;
dec->cmd = LibCmd_ReqClass;
else if (*str == 'l')
dec.cmd = LibCmd_ReqLib;
dec->cmd = LibCmd_ReqLib;
else
return false;
str++;
} else if (*str == 'f') {
str++;
dec.cmd = LibCmd_ForceLib;
dec->cmd = LibCmd_ForceLib;
} else if (*str == 'e') {
str++;
if (*str == 'c')
dec.cmd = LibCmd_ExpectClass;
dec->cmd = LibCmd_ExpectClass;
else if (*str == 'l')
dec.cmd = LibCmd_ExpectLib;
dec->cmd = LibCmd_ExpectLib;
else
return false;
str++;
} else if (*str == 'd') {
str++;
dec.cmd = LibCmd_DefaultLib;
dec->cmd = LibCmd_DefaultLib;
}
if (*str != '_')
return false;
str++;
if (dec.cmd < LibCmd_ExpectLib)
if (dec->cmd < LibCmd_ExpectLib)
{
dec.buffer = strdup(str);
dec.param1 = dec.buffer;
dec.param2 = NULL;
dec->buffer = strdup(str);
dec->param1 = dec->buffer;
dec->param2 = NULL;
} else {
dec.buffer = strdup(str);
char *p = const_cast<char *>(strchr(str, '_'));
dec->buffer = strdup(str);
char *p = strchr(str, '_');
while (p && (*(p+1) != '_'))
p = const_cast<char *>(strchr(str, '_'));
p = strchr(str, '_');
if (!p || !*(p+1))
return false;
*p = '\0';
dec.param1 = dec.buffer;
dec.param2 = p+1;
dec->param1 = dec->buffer;
dec->param2 = p+1;
}
}

View File

@ -58,7 +58,7 @@ struct LibDecoder
};
bool AddLibrary(const char *name, LibType type, LibSource src, void *parent=NULL);
bool DecodeLibCmdString(const char *str, LibDecoder &cmd);
bool DecodeLibCmdString(const char *str, LibDecoder *cmd);
size_t AddLibrariesFromString(const char *name, LibType type, LibSource src, void *parent=NULL);
size_t ClearLibraries(LibSource src);
LibError RunLibCommand(const LibDecoder *enc);

View File

@ -262,6 +262,7 @@ int C_Spawn(edict_t *pent)
// ###### Load modules
loadModules(get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini"), PT_ANYTIME);
g_plugins.CALMFromFile(get_localinfo("amxx_plugins", "addons/amxmodx/configs/plugins.ini"));
int loaded = countModules(CountModules_Running); // Call after attachModules so all modules don't have pending stat
// Set some info about amx version and modules

View File

@ -430,9 +430,12 @@ int CheckModules(AMX *amx, char error[128])
{
int numLibraries = amx_GetLibraries(amx);
char buffer[64];
LibType expect;
bool found;
Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER];
/** decode old style plugins */
for (int i = 0; i < numLibraries; i++)
{
amx_GetLibrary(amx, i, buffer, sizeof(buffer) - 1);
@ -440,41 +443,18 @@ int CheckModules(AMX *amx, char error[128])
if (stricmp(buffer, "float") == 0)
continue;
LibDecoder dcd;
LibType expect;
bool found = false;
const char *search = NULL;
DecodeLibCmdString(buffer, dcd);
switch (dcd.cmd)
if (stricmp(buffer, "dbi") == 0)
{
case LibCmd_ReqLib:
search = dcd.param1;
expect = LibType_Library;
break;
case LibCmd_ExpectLib:
search = dcd.param2;
expect = LibType_Library;
break;
case LibCmd_ReqClass:
search = dcd.param1;
expect = LibType_Class;
break;
case LibCmd_ExpectClass:
search = dcd.param2;
expect = LibType_Class;
break;
} else {
expect = LibType_Library;
}
if (!search)
continue;
found = FindLibrary(search, expect);
found = FindLibrary(buffer, expect);
if (!found)
{
if (pHandler->HandleModule(search))
if (pHandler->HandleModule(buffer))
found = true;
}
@ -483,11 +463,41 @@ int CheckModules(AMX *amx, char error[128])
const char *type = "Module/Library";
if (expect == LibType_Class)
type = "Module/Library Class";
sprintf(error, "%s \"%s\" required for plugin. Check modules.ini.", type, search);
sprintf(error, "%s \"%s\" required for plugin. Check modules.ini.", type, buffer);
return 0;
}
}
/** decode new style plugins */
amx_NumTags(amx, &numLibraries);
cell notused;
LibDecoder dec;
LibError err;
for (int i=0; i<numLibraries; i++)
{
amx_GetTag(amx, i, buffer, &notused);
if (buffer[0] != '?')
continue;
if (DecodeLibCmdString(buffer, &dec))
{
if (dec.cmd == LibCmd_ReqClass || dec.cmd == LibCmd_ReqLib)
{
if ( (err=RunLibCommand(&dec)) != LibErr_None )
{
if (!pHandler->HandleModule(buffer))
{
const char *type = "Module/Library";
if (err == LibErr_NoClass)
type = "Module/Library Class";
sprintf(error, "%s \"%s\" required for plugin. Check modules.ini.", type, buffer);
return 0;
}
}
}
}
}
return 1;
}

View File

@ -39,7 +39,7 @@ void amx_command()
{
print_srvconsole("Currently loaded plugins:\n");
print_srvconsole(" %-18.17s %-8.7s %-17.16s %-16.15s %-9.8s\n", "name", "version", "author", "file", "status");
print_srvconsole(" %-23.22s %-8.7s %-17.16s %-16.15s %-9.8s\n", "name", "version", "author", "file", "status");
int plugins = 0;
int running = 0;
@ -52,7 +52,7 @@ void amx_command()
if ((*a).isValid() && !(*a).isPaused())
++running;
print_srvconsole(" [%3d] %-18.17s %-8.7s %-17.16s %-16.15s %-9.8s\n", plugins, (*a).getTitle(), (*a).getVersion(), (*a).getAuthor(), (*a).getName(), (*a).getStatus());
print_srvconsole(" [%3d] %-23.22s %-8.7s %-17.16s %-16.15s %-9.8s\n", plugins, (*a).getTitle(), (*a).getVersion(), (*a).getAuthor(), (*a).getName(), (*a).getStatus());
++a;
}