#include "quakedef.h"
#include "prvm_cmds.h"
+#include "libcurl.h"
#include <time.h>
extern cvar_t prvm_backtraceforwarnings;
dpvsnprintf(msg,sizeof(msg),fmt,argptr);
va_end(argptr);
- Con_Printf(msg);
+ Con_Print(msg);
// TODO: either add a cvar/cmd to control the state dumping or replace some of the calls with Con_Printf [9/13/2006 Black]
if(prvm_backtraceforwarnings.integer && recursive != realtime) // NOTE: this compares to the time, just in case if PRVM_PrintState causes a Host_Error and keeps recursive set
void VM_CheckEmptyString (const char *s)
{
- if (s[0] <= ' ')
+ if (ISWHITESPACE(s[0]))
PRVM_ERROR ("%s: Bad string", PRVM_NAME);
}
VM_Warning("VM_fopen: %s ran out of file handles (%i)\n", PRVM_NAME, PRVM_MAX_OPENFILES);
return;
}
+ filename = PRVM_G_STRING(OFS_PARM0);
mode = (int)PRVM_G_FLOAT(OFS_PARM1);
switch(mode)
{
case 0: // FILE_READ
modestring = "rb";
+ prog->openfiles[filenum] = FS_OpenVirtualFile(va("data/%s", filename), false);
+ if (prog->openfiles[filenum] == NULL)
+ prog->openfiles[filenum] = FS_OpenVirtualFile(va("%s", filename), false);
break;
case 1: // FILE_APPEND
- modestring = "ab";
+ modestring = "a";
+ prog->openfiles[filenum] = FS_OpenRealFile(va("data/%s", filename), modestring, false);
break;
case 2: // FILE_WRITE
- modestring = "wb";
+ modestring = "w";
+ prog->openfiles[filenum] = FS_OpenRealFile(va("data/%s", filename), modestring, false);
break;
default:
PRVM_G_FLOAT(OFS_RETURN) = -3;
VM_Warning("VM_fopen: %s: no such mode %i (valid: 0 = read, 1 = append, 2 = write)\n", PRVM_NAME, mode);
return;
}
- filename = PRVM_G_STRING(OFS_PARM0);
-
- prog->openfiles[filenum] = FS_Open(va("data/%s", filename), modestring, false, false);
- if (prog->openfiles[filenum] == NULL && mode == 0)
- prog->openfiles[filenum] = FS_Open(va("%s", filename), modestring, false, false);
if (prog->openfiles[filenum] == NULL)
{
// Prepare Strings
VM_SAFEPARMCOUNT(1,VM_strdecolorize);
szString = PRVM_G_STRING(OFS_PARM0);
-
COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE);
-
PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(szNewString);
}
//float(string s) tokenize = #441; // takes apart a string into individal words (access them with argv), returns how many
//this function originally written by KrimZon, made shorter by LordHavoc
//20040203: rewritten by LordHavoc (no longer uses allocations)
-int num_tokens = 0;
-int tokens[256];
+static int num_tokens = 0;
+static int tokens[256];
+static int tokens_startpos[256];
+static int tokens_endpos[256];
+static char tokenize_string[VM_STRINGTEMP_LENGTH];
void VM_tokenize (void)
{
const char *p;
- static char string[VM_STRINGTEMP_LENGTH]; // static, because it's big
VM_SAFEPARMCOUNT(1,VM_tokenize);
- strlcpy(string, PRVM_G_STRING(OFS_PARM0), sizeof(string));
- p = string;
+ strlcpy(tokenize_string, PRVM_G_STRING(OFS_PARM0), sizeof(tokenize_string));
+ p = tokenize_string;
num_tokens = 0;
- while(COM_ParseToken_VM_Tokenize(&p, false))
+ for(;;)
{
if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
break;
- tokens[num_tokens++] = PRVM_SetTempString(com_token);
+
+ // skip whitespace here to find token start pos
+ while(*p && ISWHITESPACE(*p))
+ ++p;
+
+ tokens_startpos[num_tokens] = p - tokenize_string;
+ if(!COM_ParseToken_VM_Tokenize(&p, false))
+ break;
+ tokens_endpos[num_tokens] = p - tokenize_string;
+ tokens[num_tokens] = PRVM_SetTempString(com_token);
+ ++num_tokens;
+ }
+
+ PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
+}
+
+//float(string s) tokenize = #514; // takes apart a string into individal words (access them with argv), returns how many
+void VM_tokenize_console (void)
+{
+ const char *p;
+
+ VM_SAFEPARMCOUNT(1,VM_tokenize);
+
+ strlcpy(tokenize_string, PRVM_G_STRING(OFS_PARM0), sizeof(tokenize_string));
+ p = tokenize_string;
+
+ num_tokens = 0;
+ for(;;)
+ {
+ if (num_tokens >= (int)(sizeof(tokens)/sizeof(tokens[0])))
+ break;
+
+ // skip whitespace here to find token start pos
+ while(*p && ISWHITESPACE(*p))
+ ++p;
+
+ tokens_startpos[num_tokens] = p - tokenize_string;
+ if(!COM_ParseToken_Console(&p))
+ break;
+ tokens_endpos[num_tokens] = p - tokenize_string;
+ tokens[num_tokens] = PRVM_SetTempString(com_token);
+ ++num_tokens;
}
PRVM_G_FLOAT(OFS_RETURN) = num_tokens;
const char *p;
const char *token;
char tokentext[MAX_INPUTLINE];
- static char string[VM_STRINGTEMP_LENGTH]; // static, because it's big
VM_SAFEPARMCOUNTRANGE(2, 8,VM_tokenizebyseparator);
- strlcpy(string, PRVM_G_STRING(OFS_PARM0), sizeof(string));
- p = string;
+ strlcpy(tokenize_string, PRVM_G_STRING(OFS_PARM0), sizeof(tokenize_string));
+ p = tokenize_string;
- numseparators = 0;;
+ numseparators = 0;
for (j = 1;j < prog->argc;j++)
{
// skip any blank separator strings
while (num_tokens < (int)(sizeof(tokens)/sizeof(tokens[0])))
{
token = tokentext + j;
+ tokens_startpos[num_tokens] = p - tokenize_string;
while (*p)
{
for (k = 0;k < numseparators;k++)
tokentext[j++] = *p;
p++;
}
+ tokens_endpos[num_tokens] = p - tokenize_string;
if (j >= (int)sizeof(tokentext))
break;
tokentext[j++] = 0;
token_num = (int)PRVM_G_FLOAT(OFS_PARM0);
+ if(token_num < 0)
+ token_num += num_tokens;
+
if (token_num >= 0 && token_num < num_tokens)
PRVM_G_INT(OFS_RETURN) = tokens[token_num];
else
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
}
+//float(float n) argv_start_index = #515; // returns the start index of a token
+void VM_argv_start_index (void)
+{
+ int token_num;
+
+ VM_SAFEPARMCOUNT(1,VM_argv);
+
+ token_num = (int)PRVM_G_FLOAT(OFS_PARM0);
+
+ if(token_num < 0)
+ token_num += num_tokens;
+
+ if (token_num >= 0 && token_num < num_tokens)
+ PRVM_G_FLOAT(OFS_RETURN) = tokens_startpos[token_num];
+ else
+ PRVM_G_FLOAT(OFS_RETURN) = -1;
+}
+
+//float(float n) argv_end_index = #516; // returns the end index of a token
+void VM_argv_end_index (void)
+{
+ int token_num;
+
+ VM_SAFEPARMCOUNT(1,VM_argv);
+
+ token_num = (int)PRVM_G_FLOAT(OFS_PARM0);
+
+ if(token_num < 0)
+ token_num += num_tokens;
+
+ if (token_num >= 0 && token_num < num_tokens)
+ PRVM_G_FLOAT(OFS_RETURN) = tokens_endpos[token_num];
+ else
+ PRVM_G_FLOAT(OFS_RETURN) = -1;
+}
+
/*
=========
VM_isserver
PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(Key_KeynumToString((int)PRVM_G_FLOAT(OFS_PARM0)));
}
+/*
+=========
+VM_findkeysforcommand
+
+string findkeysforcommand(string command)
+
+the returned string is an altstring
+=========
+*/
+#define NUMKEYS 5 // TODO: merge the constant in keys.c with this one somewhen
+
+void M_FindKeysForCommand(const char *command, int *keys);
+void VM_findkeysforcommand(void)
+{
+ const char *cmd;
+ char ret[VM_STRINGTEMP_LENGTH];
+ int keys[NUMKEYS];
+ int i;
+
+ VM_SAFEPARMCOUNT(1, VM_findkeysforcommand);
+
+ cmd = PRVM_G_STRING(OFS_PARM0);
+
+ VM_CheckEmptyString(cmd);
+
+ M_FindKeysForCommand(cmd, keys);
+
+ ret[0] = 0;
+ for(i = 0; i < NUMKEYS; i++)
+ strlcat(ret, va(" \'%i\'", keys[i]), sizeof(ret));
+
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(ret);
+}
+
/*
=========
VM_stringtokeynum
PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.angles)->vector[0] = ANGLEMOD (current + move);
}
-// TODO: adapt all static function names to use a single naming convention... [12/3/2007 Black]
-static int Is_Text_Color (char c, char t)
-{
- int a = 0;
- char c2 = c - (c & 128);
- char t2 = t - (t & 128);
-
- if(c != STRING_COLOR_TAG && c2 != STRING_COLOR_TAG) return 0;
- if(t >= '0' && t <= '9') a = 1;
- if(t2 >= '0' && t2 <= '9') a = 1;
-/* if(t >= 'A' && t <= 'Z') a = 2;
- if(t2 >= 'A' && t2 <= 'Z') a = 2;
-
- if(a == 1 && scr_colortext.integer > 0)
- return 1;
- if(a == 2 && scr_multifonts.integer > 0)
- return 2;
-*/
- return a;
-}
void VM_uncolorstring (void)
{
- const char *in;
- char out[VM_STRINGTEMP_LENGTH];
- int k = 0, i = 0;
+ char szNewString[VM_STRINGTEMP_LENGTH];
+ const char *szString;
+ // Prepare Strings
VM_SAFEPARMCOUNT(1, VM_uncolorstring);
- in = PRVM_G_STRING(OFS_PARM0);
- VM_CheckEmptyString (in);
-
- while (in[k])
- {
- if(in[k+1])
- if(Is_Text_Color(in[k], in[k+1]) == 1/* || (in[k] == '&' && in[k+1] == 'r')*/)
- {
- k += 2;
- continue;
- }
- out[i] = in[k];
- ++k;
- ++i;
- }
- PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(out);
+ szString = PRVM_G_STRING(OFS_PARM0);
+ COM_StringDecolorize(szString, 0, szNewString, sizeof(szNewString), TRUE);
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(szNewString);
+
}
// #221 float(string str, string sub[, float startpos]) strstrofs (FTE_STRINGS)
{
const char *fn, *pack;
+ VM_SAFEPARMCOUNT(1, VM_whichpack);
fn = PRVM_G_STRING(OFS_PARM0);
pack = FS_WhichPack(fn);
PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(pack ? pack : "");
}
+typedef struct
+{
+ int prognr;
+ double starttime;
+ float id;
+ char buffer[MAX_INPUTLINE];
+}
+uri_to_prog_t;
+
+static void uri_to_string_callback(int status, size_t length_received, unsigned char *buffer, void *cbdata)
+{
+ uri_to_prog_t *handle = cbdata;
+
+ if(!PRVM_ProgLoaded(handle->prognr))
+ {
+ // curl reply came too late... so just drop it
+ Z_Free(handle);
+ return;
+ }
+
+ PRVM_SetProg(handle->prognr);
+ PRVM_Begin;
+ if((prog->starttime == handle->starttime) && (prog->funcoffsets.URI_Get_Callback))
+ {
+ if(length_received >= sizeof(handle->buffer))
+ length_received = sizeof(handle->buffer) - 1;
+ handle->buffer[length_received] = 0;
+
+ PRVM_G_FLOAT(OFS_PARM0) = handle->id;
+ PRVM_G_FLOAT(OFS_PARM1) = status;
+ PRVM_G_INT(OFS_PARM2) = PRVM_SetTempString(handle->buffer);
+ PRVM_ExecuteProgram(prog->funcoffsets.URI_Get_Callback, "QC function URI_Get_Callback is missing");
+ }
+ PRVM_End;
+
+ Z_Free(handle);
+}
+
+// uri_get() gets content from an URL and calls a callback "uri_get_callback" with it set as string; an unique ID of the transfer is returned
+// returns 1 on success, and then calls the callback with the ID, 0 or the HTTP status code, and the received data in a string
+void VM_uri_get (void)
+{
+ const char *url;
+ float id;
+ qboolean ret;
+ uri_to_prog_t *handle;
+
+ if(!prog->funcoffsets.URI_Get_Callback)
+ PRVM_ERROR("uri_get called by %s without URI_Get_Callback defined", PRVM_NAME);
+
+ VM_SAFEPARMCOUNT(2, VM_uri_get);
+
+ url = PRVM_G_STRING(OFS_PARM0);
+ id = PRVM_G_FLOAT(OFS_PARM1);
+ handle = Z_Malloc(sizeof(*handle)); // this can't be the prog's mem pool, as curl may call the callback later!
+
+ handle->prognr = PRVM_GetProgNr();
+ handle->starttime = prog->starttime;
+ handle->id = id;
+ ret = Curl_Begin_ToMemory(url, (unsigned char *) handle->buffer, sizeof(handle->buffer), uri_to_string_callback, handle);
+ if(ret)
+ {
+ PRVM_G_INT(OFS_RETURN) = 1;
+ }
+ else
+ {
+ Z_Free(handle);
+ PRVM_G_INT(OFS_RETURN) = 0;
+ }
+}
+
+void VM_netaddress_resolve (void)
+{
+ const char *ip;
+ char normalized[128];
+ int port;
+ lhnetaddress_t addr;
+
+ VM_SAFEPARMCOUNTRANGE(1, 2, VM_netaddress_resolve);
+
+ ip = PRVM_G_STRING(OFS_PARM0);
+ port = 0;
+ if(prog->argc > 1)
+ port = PRVM_G_FLOAT(OFS_PARM1);
+
+ if(LHNETADDRESS_FromString(&addr, ip, port) && LHNETADDRESS_ToString(&addr, normalized, sizeof(normalized), prog->argc > 1))
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(normalized);
+ else
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString("");
+}