GIB: Many bugfixes and cleanups. Added bitwise math operations, expansion

of leaf names in a stem variable via %var, the builtin functions 'count'
and 'contains', and an initial interface between qw-server and GIB to allow
querying of clients and their info strings.  Also cleaned up the chat event
interface a bit.  Renamed a few builtins.
This commit is contained in:
Brian Koropoff 2003-02-16 19:46:34 +00:00
parent af520a373a
commit 760210dc7b
14 changed files with 151 additions and 69 deletions

View file

@ -30,6 +30,7 @@
*/ */
#include "QF/cbuf.h" // For cbuf_active #include "QF/cbuf.h" // For cbuf_active
#include "QF/gib_buffer.h" // For GIB_DATA()
#include "QF/dstring.h" // For ->str #include "QF/dstring.h" // For ->str
typedef struct gib_builtin_s { typedef struct gib_builtin_s {

View file

@ -36,7 +36,7 @@
// Flags for tokens // Flags for tokens
#define TREE_CONCAT 1 // Concatenate to previous #define TREE_CONCAT 1 // Concatenate to previous
#define TREE_P_EMBED 2 // Embedded stuff needs to be processed #define TREE_P_EMBED 2 // Embedded stuff needs to be processed
#define TREE_ASPLIT 4 // Token is the name of an array that should be split #define TREE_SPLIT 4 // Token is the name of an array that should be split
// Flags for lines // Flags for lines
#define TREE_COND 1 // Conditional jump (if or while command) #define TREE_COND 1 // Conditional jump (if or while command)
#define TREE_NOT 2 // Invert condition #define TREE_NOT 2 // Invert condition

View file

@ -37,6 +37,10 @@ double OP_GreaterThan (double op1, double op2);
double OP_LessThan (double op1, double op2); double OP_LessThan (double op1, double op2);
double OP_GreaterThanEqual (double op1, double op2); double OP_GreaterThanEqual (double op1, double op2);
double OP_LessThanEqual (double op1, double op2); double OP_LessThanEqual (double op1, double op2);
double OP_BitAnd (double op1, double op2);
double OP_BitOr (double op1, double op2);
double OP_BitXor (double op1, double op2);
double OP_BitInv (double op1, double op2);
double Func_Sin (double *oplist, unsigned int numops); double Func_Sin (double *oplist, unsigned int numops);
double Func_Cos (double *oplist, unsigned int numops); double Func_Cos (double *oplist, unsigned int numops);

View file

@ -34,7 +34,11 @@ exp_error_t EXP_ERROR;
char *exp_error_msg = 0; char *exp_error_msg = 0;
optable_t optable[] = { optable_t optable[] = {
{"~", OP_BitInv, 1},
{"!", OP_Not, 1}, {"!", OP_Not, 1},
{"&", OP_BitAnd, 2},
{"|", OP_BitOr, 2},
{"^", OP_BitXor, 2},
{"**", OP_Exp, 2}, {"**", OP_Exp, 2},
{"/", OP_Div, 2}, {"/", OP_Div, 2},
{"-", OP_Negate, 1}, {"-", OP_Negate, 1},

View file

@ -210,7 +210,7 @@ GIB_Local_f (void)
GIB_Argc () - 3); GIB_Argc () - 3);
} else for (i = 1; i < GIB_Argc(); i++) } else for (i = 1; i < GIB_Argc(); i++)
var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero, var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero,
GIB_Argv (1), &index, true); GIB_Argv (i), &index, true);
} }
@ -231,16 +231,15 @@ GIB_Global_f (void)
GIB_Argc () - 3); GIB_Argc () - 3);
} else for (i = 1; i < GIB_Argc(); i++) } else for (i = 1; i < GIB_Argc(); i++)
var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero, var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
GIB_Argv (1), &index, true); GIB_Argv (i), &index, true);
} }
static void static void
GIB_Global_Delete_f (void) GIB_Delete_f (void)
{ {
gib_var_t *var; gib_var_t *var;
unsigned int index, i; unsigned int index, i;
hashtab_t *source; hashtab_t *source;
static hashtab_t *zero = 0;
char *c; char *c;
if (GIB_Argc () < 2) if (GIB_Argc () < 2)
@ -248,7 +247,8 @@ GIB_Global_Delete_f (void)
else for (i = 1; i < GIB_Argc(); i++) { else for (i = 1; i < GIB_Argc(); i++) {
if ((c = strrchr (GIB_Argv(i), '.'))) { if ((c = strrchr (GIB_Argv(i), '.'))) {
*(c++) = 0; *(c++) = 0;
if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero, if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals,
&GIB_DATA(cbuf_active)->globals,
GIB_Argv (i), &index, false))) GIB_Argv (i), &index, false)))
continue; continue;
source = var->array[index].leaves; source = var->array[index].leaves;
@ -425,6 +425,27 @@ GIB_Equal_f (void)
GIB_Return ("1"); GIB_Return ("1");
} }
static void
GIB_Count_f (void)
{
if (GIB_CanReturn())
dsprintf (GIB_Return(0), "%u", GIB_Argc() - 1);
}
static void
GIB_Contains_f (void)
{
unsigned int i;
if (GIB_Argc () < 2)
GIB_USAGE ("needle [straw1 straw2 ...]");
else if (GIB_CanReturn())
for (i = 2; i < GIB_Argc(); i++)
if (!strcmp(GIB_Argv(1), GIB_Argv(i)))
GIB_Return("1");
GIB_Return ("0");
}
static void static void
GIB_Slice_f (void) GIB_Slice_f (void)
{ {
@ -911,7 +932,7 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("function::export", GIB_Function_Export_f); GIB_Builtin_Add ("function::export", GIB_Function_Export_f);
GIB_Builtin_Add ("local", GIB_Local_f); GIB_Builtin_Add ("local", GIB_Local_f);
GIB_Builtin_Add ("global", GIB_Global_f); GIB_Builtin_Add ("global", GIB_Global_f);
GIB_Builtin_Add ("global::delete", GIB_Global_Delete_f); GIB_Builtin_Add ("delete", GIB_Delete_f);
GIB_Builtin_Add ("domain", GIB_Domain_f); GIB_Builtin_Add ("domain", GIB_Domain_f);
GIB_Builtin_Add ("domain::clear", GIB_Domain_Clear_f); GIB_Builtin_Add ("domain::clear", GIB_Domain_Clear_f);
GIB_Builtin_Add ("return", GIB_Return_f); GIB_Builtin_Add ("return", GIB_Return_f);
@ -920,6 +941,8 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("continue", GIB_Continue_f); GIB_Builtin_Add ("continue", GIB_Continue_f);
GIB_Builtin_Add ("length", GIB_Length_f); GIB_Builtin_Add ("length", GIB_Length_f);
GIB_Builtin_Add ("equal", GIB_Equal_f); GIB_Builtin_Add ("equal", GIB_Equal_f);
GIB_Builtin_Add ("count", GIB_Count_f);
GIB_Builtin_Add ("contains", GIB_Contains_f);
GIB_Builtin_Add ("slice", GIB_Slice_f); GIB_Builtin_Add ("slice", GIB_Slice_f);
GIB_Builtin_Add ("slice::find", GIB_Slice_Find_f); GIB_Builtin_Add ("slice::find", GIB_Slice_Find_f);
GIB_Builtin_Add ("split", GIB_Split_f); GIB_Builtin_Add ("split", GIB_Split_f);
@ -928,7 +951,7 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("regex::extract", GIB_Regex_Extract_f); GIB_Builtin_Add ("regex::extract", GIB_Regex_Extract_f);
GIB_Builtin_Add ("thread::create", GIB_Thread_Create_f); GIB_Builtin_Add ("thread::create", GIB_Thread_Create_f);
GIB_Builtin_Add ("thread::kill", GIB_Thread_Kill_f); GIB_Builtin_Add ("thread::kill", GIB_Thread_Kill_f);
GIB_Builtin_Add ("thread::list", GIB_Thread_List_f); GIB_Builtin_Add ("thread::getList", GIB_Thread_List_f);
GIB_Builtin_Add ("event::register", GIB_Event_Register_f); GIB_Builtin_Add ("event::register", GIB_Event_Register_f);
GIB_Builtin_Add ("file::read", GIB_File_Read_f); GIB_Builtin_Add ("file::read", GIB_File_Read_f);
GIB_Builtin_Add ("file::write", GIB_File_Write_f); GIB_Builtin_Add ("file::write", GIB_File_Write_f);

View file

@ -76,7 +76,7 @@ GIB_Execute_Generate_Composite (struct cbuf_s *cbuf)
} }
static void static void
GIB_Execute_Split_Array (cbuf_t * cbuf) GIB_Execute_Split_Var (cbuf_t * cbuf)
{ {
gib_var_t *var; gib_var_t *var;
unsigned int i; unsigned int i;
@ -85,39 +85,53 @@ GIB_Execute_Split_Array (cbuf_t * cbuf)
void *m = cbuf->args->argm[cbuf->args->argc - 1]; void *m = cbuf->args->argm[cbuf->args->argc - 1];
i = strlen (str) - 1; i = strlen (str) - 1;
if (str[i] == ']') if (str[-1] == '@') {
for (; i; i--) if (str[i] == ']')
if (str[i] == '[') { for (; i; i--)
str[i] = 0; if (str[i] == '[') {
start = atoi (str + i + 1); str[i] = 0;
if ((c = strchr (str + i + 1, ':'))) { start = atoi (str + i + 1);
if (c[1] != ']') if ((c = strchr (str + i + 1, ':'))) {
end = atoi (c + 1); if (c[1] != ']')
} else end = atoi (c + 1);
end = start + 1; } else
break; end = start + 1;
} break;
cbuf->args->argc--; }
if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, cbuf->args->argc--;
&GIB_DATA (cbuf)->globals, str, &i, false))) if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
return; &GIB_DATA (cbuf)->globals, str, &i, false)))
if (end < 0) return;
end += var->size; if (end < 0)
else if (end > var->size) end += var->size;
end = var->size; else if (end > var->size)
if (start < 0) { end = var->size;
start += var->size; if (start < 0) {
if (start < 0) start += var->size;
start = 0; if (start < 0)
} else if (start >= var->size || start >= end) start = 0;
return; } else if (start >= var->size || start >= end)
for (i = start; i < end; i++) { return;
if (var->array[i].value) for (i = start; i < end; i++) {
Cbuf_ArgsAdd (cbuf->args, var->array[i].value->str); if (var->array[i].value)
else Cbuf_ArgsAdd (cbuf->args, var->array[i].value->str);
Cbuf_ArgsAdd (cbuf->args, ""); else
cbuf->args->argm[cbuf->args->argc - 1] = m; Cbuf_ArgsAdd (cbuf->args, "");
} cbuf->args->argm[cbuf->args->argc - 1] = m;
}
} else {
gib_var_t **vlist, **v;
cbuf->args->argc--;
if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
&GIB_DATA (cbuf)->globals, str, &i, false)))
return;
if (!var->array[i].leaves)
return;
vlist = (gib_var_t **) Hash_GetList (var->array[i].leaves);
for (v = vlist; *v; v++)
Cbuf_ArgsAdd (cbuf->args, (*v)->key);
}
} }
static int static int
@ -148,8 +162,8 @@ GIB_Execute_Prepare_Line (cbuf_t * cbuf, gib_tree_t * line)
if (cur->delim == '(' if (cur->delim == '('
&& GIB_Process_Math (args->argv[args->argc - 1], pos)) && GIB_Process_Math (args->argv[args->argc - 1], pos))
return -1; return -1;
if (cur->flags & TREE_ASPLIT) if (cur->flags & TREE_SPLIT)
GIB_Execute_Split_Array (cbuf); GIB_Execute_Split_Var (cbuf);
} }
return 0; return 0;
} }

View file

@ -158,8 +158,8 @@ GIB_Function_Prepare_Args (cbuf_t * cbuf, dstring_t ** args, unsigned int argc)
var = var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true); GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true);
var->array = realloc (var->array, sizeof (dstring_t *) * argc); var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc);
memset (var->array + 1, 0, (argc - 1) * sizeof (dstring_t *)); memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
var->size = argc; var->size = argc;
for (i = 0; i < argc; i++) { for (i = 0; i < argc; i++) {
if (var->array[i].value) if (var->array[i].value)

View file

@ -321,7 +321,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs,
// Check for array splitting // Check for array splitting
// Concatenating this onto something else is non-sensical // Concatenating this onto something else is non-sensical
if (cur->delim == ' ' && str[0] == '@' && !cat) { if (cur->delim == ' ' && str[0] == '@' && !cat) {
cur->flags |= TREE_ASPLIT; cur->flags |= TREE_SPLIT;
} }
// We can handle escape characters now // We can handle escape characters now
} else if (cur->delim == '\"') } else if (cur->delim == '\"')

View file

@ -95,20 +95,21 @@ GIB_Var_Get (hashtab_t * first, hashtab_t * second, const char *key)
return 0; return 0;
} }
/* Destroys key! */ /* Alters key, but restores it */
gib_var_t * gib_var_t *
GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key, GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key,
unsigned int *ind, qboolean create) unsigned int *ind, qboolean create)
{ {
static hashtab_t *zero = 0; static hashtab_t *zero = 0;
unsigned int i, n, index, len, start; unsigned int i, n, index = 0, len, start;
gib_var_t *var; gib_var_t *var = 0;
len = strlen(key); len = strlen(key);
for (start = i = 0; i <= len; i++) { for (start = i = 0; i <= len; i++) {
if (key[i] == '.' || key[i] == 0) { if (key[i] == '.' || key[i] == 0) {
index = 0; index = 0;
key[i] = 0; key[i] = 0;
n = 0;
if (i && key[i - 1] == ']') if (i && key[i - 1] == ']')
for (n = i - 1; n; n--) for (n = i - 1; n; n--)
if (key[n] == '[') { if (key[n] == '[') {
@ -128,9 +129,9 @@ GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key,
if (index >= var->size) { if (index >= var->size) {
if (create) { if (create) {
var->array = var->array =
realloc (var->array, (index + 1) * sizeof (struct gib_varray_s *)); realloc (var->array, (index + 1) * sizeof (struct gib_varray_s));
memset (var->array + var->size, 0, memset (var->array + var->size, 0,
(index + 1 - var->size) * sizeof (struct gib_varray_s *)); (index + 1 - var->size) * sizeof (struct gib_varray_s));
var->size = index + 1; var->size = index + 1;
} else } else
return 0; return 0;
@ -138,6 +139,10 @@ GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key,
second = &zero; second = &zero;
first = &var->array[index].leaves; first = &var->array[index].leaves;
start = i+1; start = i+1;
if (n)
key[n] = '[';
if (i < len)
key[i] = '.';
} }
} }
if (!var->array[index].value) if (!var->array[index].value)
@ -146,19 +151,20 @@ GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key,
return var; return var;
} }
/* Mangles the hell out of key */
gib_var_t * gib_var_t *
GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start, GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start,
unsigned int *ind, qboolean create) unsigned int *ind, qboolean create)
{ {
static hashtab_t *zero = 0; static hashtab_t *zero = 0;
hashtab_t *one = *first, *two = *second; hashtab_t *one = *first, *two = *second;
unsigned int i, index, index2, n; unsigned int i, index = 0, index2 = 0, n, protect;
gib_var_t *var; gib_var_t *var = 0;
cvar_t *cvar; cvar_t *cvar;
char c, *str; char c, *str;
qboolean done = false; qboolean done = false;
for (i = start; !done; i++) { for (i = start, protect = 0; !done; i++) {
if (key->str[i] == '.' || key->str[i] == 0) { if (key->str[i] == '.' || key->str[i] == 0) {
index = 0; index = 0;
if (!key->str[i]) if (!key->str[i])
@ -193,7 +199,7 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke
second = &zero; second = &zero;
first = &var->array[index].leaves; first = &var->array[index].leaves;
start = i+1; start = i+1;
} else if (key->str[i] == '$' || key->str[i] == '#') { } else if (i >= protect && (key->str[i] == '$' || key->str[i] == '#')) {
n = i; n = i;
if (GIB_Parse_Match_Var (key->str, &i)) if (GIB_Parse_Match_Var (key->str, &i))
return 0; return 0;
@ -204,13 +210,15 @@ GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *ke
str = va("%u", var->size); str = va("%u", var->size);
else else
str = var->array[index2].value->str; str = var->array[index2].value->str;
dstring_replace (key, n, i-n, str, strlen (str)); dstring_replace (key, n, i-n+(c == '}'), str, strlen (str));
} else if (key->str[n] == '#') } else if (key->str[n] == '#')
dstring_replace (key, n, i-n, "0", 1); dstring_replace (key, n, i-n+(c == '}'), "0", 1);
else if ((cvar = Cvar_FindVar (key->str+n+1+(c == '}')))) else if ((cvar = Cvar_FindVar (key->str+n+1+(c == '}'))))
dstring_replace (key, n, i-n, cvar->string, strlen (cvar->string)); dstring_replace (key, n, i-n+(c == '}'), cvar->string, strlen (cvar->string));
else else
dstring_snip (key, n, n-i); dstring_snip (key, n, n-i+(c == '}'));
protect = i+1;
i = n;
} }
} }

View file

@ -113,6 +113,29 @@ OP_LessThanEqual (double op1, double op2)
return op1 <= op2; return op1 <= op2;
} }
double
OP_BitAnd (double op1, double op2)
{
return (double) ((long int) op1 & (long int) op2);
}
double
OP_BitOr (double op1, double op2)
{
return (double) ((long int) op1 | (long int) op2);
}
double
OP_BitXor (double op1, double op2)
{
return (double) ((long int) op1 ^ (long int) op2);
}
double
OP_BitInv (double op1, double op2)
{
return (double) ~((long int) op1);
}
double double
Func_Sin (double *oplist, unsigned int numops) Func_Sin (double *oplist, unsigned int numops)

View file

@ -479,6 +479,7 @@ void SV_Physics_Client (struct edict_s *ent);
void SV_SetupUserCommands (void); void SV_SetupUserCommands (void);
void SV_ExecuteUserCommand (const char *s); void SV_ExecuteUserCommand (const char *s);
void SV_InitOperatorCommands (void); void SV_InitOperatorCommands (void);
void SV_GIB_Init (void);
void SV_SendServerinfo (client_t *client); void SV_SendServerinfo (client_t *client);
void SV_ExtractFromUserinfo (client_t *cl); void SV_ExtractFromUserinfo (client_t *cl);

View file

@ -68,7 +68,7 @@ endif
EXTRA_DIST=sv_sys_win.c sv_sys_unix.c EXTRA_DIST=sv_sys_win.c sv_sys_unix.c
libqw_server_a_SOURCES= \ libqw_server_a_SOURCES= \
crudefile.c sv_ccmds.c sv_demo.c sv_ents.c sv_init.c sv_main.c \ crudefile.c sv_ccmds.c sv_demo.c sv_ents.c sv_gib.c sv_init.c sv_main.c \
sv_move.c sv_nchan.c sv_phys.c sv_pr_cmds.c sv_progs.c sv_send.c \ sv_move.c sv_nchan.c sv_phys.c sv_pr_cmds.c sv_progs.c sv_send.c \
sv_user.c world.c $(syssv_SRC) sv_user.c world.c $(syssv_SRC)

View file

@ -2504,7 +2504,8 @@ SV_Init (void)
svs.info = Info_ParseString ("", MAX_SERVERINFO_STRING); svs.info = Info_ParseString ("", MAX_SERVERINFO_STRING);
localinfo = Info_ParseString ("", 0); // unlimited localinfo = Info_ParseString ("", 0); // unlimited
SV_InitOperatorCommands (); SV_InitOperatorCommands ();
SV_GIB_Init ();
QFS_Init ("qw"); QFS_Init ("qw");
PI_Init (); PI_Init ();

View file

@ -753,7 +753,7 @@ SV_Say (qboolean team)
{ {
char *i, *p; char *i, *p;
char text[2048], t1[32]; char text[2048], t1[32];
const char *t2; const char *t2, *type;
client_t *client; client_t *client;
int tmp, j, cls = 0; int tmp, j, cls = 0;
@ -765,12 +765,15 @@ SV_Say (qboolean team)
t1[31] = 0; t1[31] = 0;
} }
if (host_client->spectator && (!sv_spectalk->int_val || team)) if (host_client->spectator && (!sv_spectalk->int_val || team)) {
snprintf (text, sizeof (text), "[SPEC] %s: ", host_client->name); snprintf (text, sizeof (text), "[SPEC] %s: ", host_client->name);
else if (team) type = "2";
} else if (team) {
snprintf (text, sizeof (text), "(%s): ", host_client->name); snprintf (text, sizeof (text), "(%s): ", host_client->name);
else { type = "1";
} else {
snprintf (text, sizeof (text), "%s: ", host_client->name); snprintf (text, sizeof (text), "%s: ", host_client->name);
type = "0";
} }
if (fp_messages) { if (fp_messages) {
@ -823,14 +826,14 @@ SV_Say (qboolean team)
*i = '#'; *i = '#';
} }
if (sv_chat_e->func)
GIB_Event_Callback (sv_chat_e, 2, va("%i", host_client->userid), p, type);
strncat (text, p, sizeof (text) - strlen (text)); strncat (text, p, sizeof (text) - strlen (text));
strncat (text, "\n", sizeof (text) - strlen (text)); strncat (text, "\n", sizeof (text) - strlen (text));
SV_Printf ("%s", text); SV_Printf ("%s", text);
if (sv_chat_e->func)
GIB_Event_Callback (sv_chat_e, 1, text);
for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) { for (j = 0, client = svs.clients; j < MAX_CLIENTS; j++, client++) {
if (client->state < cs_connected) // Clients connecting can hear. if (client->state < cs_connected) // Clients connecting can hear.
continue; continue;