initial import of new format zomg

This commit is contained in:
David Anderson
2006-02-22 00:33:19 +00:00
parent 2843c333aa
commit 2ba0b079ab
9 changed files with 447 additions and 710 deletions

View File

@ -32,6 +32,7 @@
#include <stdarg.h>
#include "amxmodx.h"
#include "CLang.h"
#include "format.h"
#ifdef __linux__
#define _snprintf snprintf
@ -368,277 +369,13 @@ int CLangMngr::GetKeyEntry(String &key)
return val.index;
}
/**
* FORMATTING ROUTINES
*/
#define FMTPM_NEXTPARAM() \
if (*param > numParams) { \
LogError(amx, AMX_ERR_PARAMS, "String formatted incorrectly - parameter %d (total %d)", *param, numParams); \
return 0; \
} \
_addr = params[*param]; \
(*param)++;
extern "C" size_t do_amx_format(AMX *amx, cell *params, int *param, const char **lex, char *output, size_t maxlen, int level);
THash<String, lang_err> BadLang_Table;
static cvar_t *amx_mldebug = NULL;
static cvar_t *amx_cl_langs = NULL;
extern "C" const char *translate(AMX *amx, cell amxaddr, const char *key)
{
const char *pLangName = NULL;
const char *def = NULL;
int status;
cell *addr = get_amxaddr(amx, amxaddr);
char name[4];
if (addr[0] == LANG_PLAYER)
{
if (!amx_cl_langs)
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
if ( (int)amx_cl_langs->value == 0 )
{
pLangName = g_vault.get("server_language");
} else {
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(g_langMngr.GetDefLang())->pEdict, "lang");
}
} else if (addr[0] == LANG_SERVER) {
pLangName = g_vault.get("server_language");
} else if (addr[0] >= 1 && addr[0] <= gpGlobals->maxClients) {
if (!amx_cl_langs)
amx_cl_langs = CVAR_GET_POINTER("amx_client_languages");
if ( (int)amx_cl_langs->value == 0 )
{
pLangName = g_vault.get("server_language");
} else {
pLangName = ENTITY_KEYVALUE(GET_PLAYER_POINTER_I(addr[0])->pEdict, "lang");
}
} else {
get_amxstring_r(amx, amxaddr, name, 3);
pLangName = name;
}
if (!pLangName || !isalpha(pLangName[0]))
pLangName = "en";
//next parameter!
def = g_langMngr.GetDef(pLangName, key, status);
if (!amx_mldebug)
amx_mldebug = CVAR_GET_POINTER("amx_mldebug");
bool debug = (amx_mldebug && amx_mldebug->string && (amx_mldebug->string[0] != '\0'));
if (debug)
{
int debug_status;
bool validlang = true;
const char *testlang = amx_mldebug->string;
if (!g_langMngr.LangExists(testlang))
{
AMXXLOG_Log("[AMXX] \"%s\" is an invalid debug language", testlang);
validlang = false;
}
g_langMngr.GetDef(testlang, key, debug_status);
if (validlang && debug_status == ERR_BADKEY)
AMXXLOG_Log("[AMXX] Language key \"%s\" not found for language \"%s\", check \"%s\"", key, testlang, GetFileName(amx));
}
if (def == NULL)
{
if (debug)
{
if (status == ERR_BADLANG && (BadLang_Table[make_string(pLangName)].last + 120.0f < gpGlobals->time))
{
AMXXLOG_Log("[AMXX] Language \"%s\" not found", pLangName);
BadLang_Table[make_string(pLangName)].last = gpGlobals->time;
}
}
if (addr[0] != LANG_SERVER)
def = g_langMngr.GetDef(g_vault.get("server_language"), key, status);
if (!def && (strcmp(pLangName, "en") != 0 && strcmp(g_vault.get("server_language"), "en") != 0))
def = g_langMngr.GetDef("en", key, status);
}
return def;
}
#if defined AMD64
size_t do_amx_format_parameter(AMX *amx, cell *params, const char **fmtstr, int *param, char *output, size_t maxlen)
{
char fmt[32];
size_t len = 0;
char *fmtptr = fmt;
register const char *fmtsrc = *fmtstr;
char ctrl_code;
int numParams = params[0] / sizeof(cell);
cell _addr, *addr;
*fmtptr++ = '%';
while (*fmtsrc && !isalpha(*fmtsrc))
{
if (len >= sizeof(fmt)-2)
break;
*fmtptr++ = static_cast<char>(*fmtsrc++);
len++;
}
//get the final character
ctrl_code = *fmtsrc++;
if (!ctrl_code)
return 0;
//inc the source pointer
*fmtstr = fmtsrc;
//finalize the string
*fmtptr++ = ctrl_code;
*fmtptr = '\0';
len = 0;
//reset the format pointer
fmtptr = fmt;
//we now have the format
switch (ctrl_code)
{
case 's':
{
FMTPM_NEXTPARAM();
char buffer[2048];
get_amxstring_r(amx, _addr, buffer, 2047);
return _snprintf(output, maxlen, fmtptr, buffer);
break;
}
case 'g':
case 'f':
{
FMTPM_NEXTPARAM();
addr = get_amxaddr(amx, _addr);
return _snprintf(output, maxlen, fmtptr, *(REAL *)addr);
break;
}
case 'p':
{
FMTPM_NEXTPARAM();
addr = get_amxaddr(amx, _addr);
return _snprintf(output, maxlen, fmtptr, addr);
break;
}
case 'x':
case 'i':
case 'd':
case 'c':
{
FMTPM_NEXTPARAM();
addr = get_amxaddr(amx, _addr);
return _snprintf(output, maxlen, fmtptr, (int)addr[0]);
break;
}
case 'L':
{
FMTPM_NEXTPARAM();
cell lang_addr = _addr;
FMTPM_NEXTPARAM();
int tmpLen;
const char *key = get_amxstring(amx, _addr, 3, tmpLen);
const char *def = translate(amx, lang_addr, key);
if (!def)
return _snprintf(output, maxlen, "ML_NOTFOUND: %s", key);
return do_amx_format(amx, params, param, &def, output, maxlen, 1);
}
default:
{
return _snprintf(output, maxlen, "%s", fmtptr);
break;
}
}
}
//we implement this in raw asm for x86
//we'll do it for AMD64 once VAC2 works on it
extern "C" size_t do_amx_format(AMX *amx, cell *params, int *param, const char **lex, char *output, size_t maxlen, int level)
{
size_t written;
size_t orig_maxlen = maxlen;
const char *save = *lex;
register const char *lexptr = save;
while (*lexptr && maxlen)
{
switch (*lexptr)
{
case '%':
{
lexptr++;
if (*lexptr == '%' || *lexptr == '\0')
{
*output++ = *lexptr++;
*output++ = *lexptr++;
maxlen -= 2;
} else {
written = do_amx_format_parameter(amx, params, &lexptr, param, output, maxlen);
output += written;
maxlen -= written;
}
break;
}
case '^':
{
if (level)
{
lexptr++;
switch (*lexptr)
{
case 'n':
{
*output++ = '\n';
break;
}
case 't':
{
*output++ = '\t';
break;
}
default:
{
*output++ = *lexptr;
break;
}
}
lexptr++;
maxlen--;
break;
}
}
default:
{
*output++ = *lexptr++;
maxlen--;
}
}
}
*output = '\0';
*lex = lexptr;
return (orig_maxlen-maxlen);
}
#endif
char * CLangMngr::FormatAmxString(AMX *amx, cell *params, int parm, int &len)
{
//do an initial run through all this
static char mystr[4096];
static char outbuf[4096];
const char *ptr = mystr;
cell *addr = get_amxaddr(amx, params[parm++]);
get_amxstring_r(amx, params[parm++], mystr, sizeof(mystr)-1);
len = do_amx_format(amx, params, &parm, &ptr, outbuf, sizeof(outbuf)-1, 0);
len = atcprintf(outbuf, sizeof(outbuf)-1, addr, amx, params, &parm);
return outbuf;
}