+ --cl_net_extresponse_count;
+ first = (cl_net_extresponse_last + NET_EXTRESPONSE_MAX - cl_net_extresponse_count) % NET_EXTRESPONSE_MAX;
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(cl_net_extresponse[first]);
+ }
+}
+
+void VM_SV_getextresponse (void)
+{
+ VM_SAFEPARMCOUNT(0,VM_argv);
+
+ if (sv_net_extresponse_count <= 0)
+ PRVM_G_INT(OFS_RETURN) = OFS_NULL;
+ else
+ {
+ int first;
+ --sv_net_extresponse_count;
+ first = (sv_net_extresponse_last + NET_EXTRESPONSE_MAX - sv_net_extresponse_count) % NET_EXTRESPONSE_MAX;
+ PRVM_G_INT(OFS_RETURN) = PRVM_SetEngineString(sv_net_extresponse[first]);
+ }
+}
+
+/*
+=========
+VM_M_callfunction
+
+ callfunction(...,string function_name)
+Extension: pass
+=========
+*/
+mfunction_t *PRVM_ED_FindFunction (const char *name);
+void VM_callfunction(void)
+{
+ mfunction_t *func;
+ const char *s;
+
+ VM_SAFEPARMCOUNTRANGE(1, 8, VM_callfunction);
+
+ s = PRVM_G_STRING(OFS_PARM0+(prog->argc - 1)*3);
+
+ VM_CheckEmptyString(s);
+
+ func = PRVM_ED_FindFunction(s);
+
+ if(!func)
+ PRVM_ERROR("VM_callfunciton: function %s not found !", s);
+ else if (func->first_statement < 0)
+ {
+ // negative statements are built in functions
+ int builtinnumber = -func->first_statement;
+ prog->xfunction->builtinsprofile++;
+ if (builtinnumber < prog->numbuiltins && prog->builtins[builtinnumber])
+ prog->builtins[builtinnumber]();
+ else
+ PRVM_ERROR("No such builtin #%i in %s; most likely cause: outdated engine build. Try updating!", builtinnumber, PRVM_NAME);
+ }
+ else if(func - prog->functions > 0)
+ {
+ prog->argc--;
+ PRVM_ExecuteProgram(func - prog->functions,"");
+ prog->argc++;
+ }
+}
+
+/*
+=========
+VM_isfunction
+
+float isfunction(string function_name)
+=========
+*/
+mfunction_t *PRVM_ED_FindFunction (const char *name);
+void VM_isfunction(void)
+{
+ mfunction_t *func;
+ const char *s;
+
+ VM_SAFEPARMCOUNT(1, VM_isfunction);
+
+ s = PRVM_G_STRING(OFS_PARM0);
+
+ VM_CheckEmptyString(s);
+
+ func = PRVM_ED_FindFunction(s);
+
+ if(!func)
+ PRVM_G_FLOAT(OFS_RETURN) = false;
+ else
+ PRVM_G_FLOAT(OFS_RETURN) = true;
+}
+
+/*
+=========
+VM_sprintf
+
+string sprintf(string format, ...)
+=========
+*/
+
+void VM_sprintf(void)
+{
+ const char *s, *s0;
+ char outbuf[MAX_INPUTLINE];
+ char *o = outbuf, *end = outbuf + sizeof(outbuf), *err;
+ int argpos = 1;
+ int width, precision, thisarg, flags;
+ char formatbuf[16];
+ char *f;
+ qboolean isfloat;
+#define PRINTF_ALTERNATE 1
+#define PRINTF_ZEROPAD 2
+#define PRINTF_LEFT 4
+#define PRINTF_SPACEPOSITIVE 8
+#define PRINTF_SIGNPOSITIVE 16
+
+ formatbuf[0] = '%';
+
+ s = PRVM_G_STRING(OFS_PARM0);
+
+#define GETARG_FLOAT(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_FLOAT(OFS_PARM0 + 3 * (a))) : 0)
+#define GETARG_INT(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_INT(OFS_PARM0 + 3 * (a))) : 0)
+#define GETARG_STRING(a) (((a)>=1 && (a)<prog->argc) ? (PRVM_G_STRING(OFS_PARM0 + 3 * (a))) : "")
+
+ for(;;)
+ {
+ s0 = s;
+ switch(*s)
+ {
+ case 0:
+ goto finished;
+ break;
+ case '%':
+ ++s;
+
+ if(*s == '%')
+ goto verbatim;
+
+ // complete directive format:
+ // %3$*1$.*2$ld
+
+ width = -1;
+ precision = -1;
+ thisarg = -1;
+ flags = 0;
+
+ // is number following?
+ if(*s >= '0' && *s <= '9')
+ {
+ width = strtol(s, &err, 10);
+ if(!err)
+ {
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ if(*err == '$')
+ {
+ thisarg = width;
+ width = -1;
+ s = err + 1;
+ }
+ else
+ {
+ if(*s == '0')
+ {
+ flags |= PRINTF_ZEROPAD;
+ if(width == 0)
+ width = -1; // it was just a flag
+ }
+ s = err;
+ }
+ }
+
+ if(width < 0)
+ {
+ for(;;)
+ {
+ switch(*s)
+ {
+ case '#': flags |= PRINTF_ALTERNATE; break;
+ case '0': flags |= PRINTF_ZEROPAD; break;
+ case '-': flags |= PRINTF_LEFT; break;
+ case ' ': flags |= PRINTF_SPACEPOSITIVE; break;
+ case '+': flags |= PRINTF_SIGNPOSITIVE; break;
+ default:
+ goto noflags;
+ }
+ ++s;
+ }
+noflags:
+ if(*s == '*')
+ {
+ ++s;
+ if(*s >= '0' && *s <= '9')
+ {
+ width = strtol(s, &err, 10);
+ if(!err || *err != '$')
+ {
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ s = err + 1;
+ }
+ else
+ width = argpos++;
+ width = GETARG_FLOAT(width);
+ }
+ else if(*s >= '0' && *s <= '9')
+ {
+ width = strtol(s, &err, 10);
+ if(!err)
+ {
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ s = err;
+ }
+ if(width < 0)
+ {
+ flags |= PRINTF_LEFT;
+ width = -width;
+ }
+ }
+
+ if(*s == '.')
+ {
+ ++s;
+ if(*s == '*')
+ {
+ ++s;
+ if(*s >= '0' && *s <= '9')
+ {
+ precision = strtol(s, &err, 10);
+ if(!err || *err != '$')
+ {
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ s = err + 1;
+ }
+ else
+ precision = argpos++;
+ precision = GETARG_FLOAT(precision);
+ }
+ else if(*s >= '0' && *s <= '9')
+ {
+ precision = strtol(s, &err, 10);
+ if(!err)
+ {
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ s = err;
+ }
+ else
+ {
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ }
+
+ isfloat = true;
+ for(;;)
+ {
+ switch(*s)
+ {
+ case 'h': isfloat = true; break;
+ case 'l': isfloat = false; break;
+ case 'L': isfloat = false; break;
+ case 'j': break;
+ case 'z': break;
+ case 't': break;
+ default:
+ goto nolength;
+ }
+ ++s;
+ }
+nolength:
+
+ if(thisarg < 0)
+ thisarg = argpos++;
+
+ if(o < end - 1)
+ {
+ f = &formatbuf[1];
+ if(*s != 's' && *s != 'c')
+ if(flags & PRINTF_ALTERNATE) *f++ = '#';
+ if(flags & PRINTF_ZEROPAD) *f++ = '0';
+ if(flags & PRINTF_LEFT) *f++ = '-';
+ if(flags & PRINTF_SPACEPOSITIVE) *f++ = ' ';
+ if(flags & PRINTF_SIGNPOSITIVE) *f++ = '+';
+ *f++ = '*';
+ *f++ = '.';
+ *f++ = '*';
+ *f++ = *s;
+ *f++ = 0;
+
+ if(width < 0)
+ width = 0;
+
+ switch(*s)
+ {
+ case 'd': case 'i':
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (int) GETARG_FLOAT(thisarg) : (int) GETARG_INT(thisarg)));
+ break;
+ case 'o': case 'u': case 'x': case 'X':
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
+ break;
+ case 'e': case 'E': case 'f': case 'F': case 'g': case 'G':
+ if(precision < 0)
+ precision = 6;
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (double) GETARG_FLOAT(thisarg) : (double) GETARG_INT(thisarg)));
+ break;
+ case 'c':
+ if(precision < 0)
+ precision = end - o - 1;
+ if(flags & PRINTF_ALTERNATE)
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg)));
+ else
+ {
+ unsigned int c = (isfloat ? (unsigned int) GETARG_FLOAT(thisarg) : (unsigned int) GETARG_INT(thisarg));
+ const char *buf = u8_encodech(c, NULL);
+ if(!buf)
+ buf = "";
+ o += u8_strpad(o, end - o, buf, (flags & PRINTF_LEFT) != 0, width, precision);
+ }
+ break;
+ case 's':
+ if(precision < 0)
+ precision = end - o - 1;
+ if(flags & PRINTF_ALTERNATE)
+ o += dpsnprintf(o, end - o, formatbuf, width, precision, GETARG_STRING(thisarg));
+ else
+ o += u8_strpad(o, end - o, GETARG_STRING(thisarg), (flags & PRINTF_LEFT) != 0, width, precision);
+ break;
+ default:
+ VM_Warning("VM_sprintf: invalid directive in %s: %s\n", PRVM_NAME, s0);
+ goto finished;
+ }
+ }
+ ++s;
+ break;
+ default:
+verbatim:
+ if(o < end - 1)
+ *o++ = *s++;
+ break;
+ }