More cleanups and bug fixes. Added stem-and-leaf variables back in and

added the global::delete builtin.
This commit is contained in:
Brian Koropoff 2003-02-16 02:44:24 +00:00
parent d626575091
commit af520a373a
9 changed files with 218 additions and 162 deletions

View file

@ -38,7 +38,6 @@ typedef struct gib_thread_s {
unsigned long int id;
struct cbuf_s *cbuf;
struct gib_thread_s *prev, *next;
qboolean trash;
} gib_thread_t;
typedef struct gib_event_s {

View file

@ -36,7 +36,10 @@ extern hashtab_t *gib_globals;
typedef struct gib_var_s {
const char *key;
struct dstring_s **array;
struct gib_varray_s {
struct dstring_s *value;
struct hashtab_s *leaves;
} *array;
unsigned int size;
} gib_var_t;
@ -47,6 +50,7 @@ typedef struct gib_domain_s {
gib_var_t *GIB_Var_Get (hashtab_t *first, hashtab_t *second, const char *key);
gib_var_t *GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned int *ind, qboolean create);
gib_var_t *GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start, unsigned int *ind, qboolean create);
void GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned int numv);
hashtab_t *GIB_Domain_Get (const char *name);

View file

@ -101,6 +101,7 @@ GIB_Buffer_Reset (struct cbuf_s *cbuf)
free (g->script);
}
g->script = 0;
g->program = 0;
g->stack.p = 0;
g->waitret = g->done = false;

View file

@ -197,19 +197,20 @@ static void
GIB_Local_f (void)
{
gib_var_t *var;
unsigned int index;
hashtab_t *zero = 0;
unsigned int index, i;
static hashtab_t *zero = 0;
if (GIB_Argc () < 2)
GIB_USAGE ("var [= value1 value2 ...]");
else {
var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero,
GIB_USAGE ("var [= value1 value2 ...] || var [var2 var3 ...]");
else if (!strcmp (GIB_Argv(2), "=")) {
var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero,
GIB_Argv (1), &index, true);
if (GIB_Argc () >= 3)
GIB_Var_Assign (var, index, cbuf_active->args->argv + 3,
GIB_Argc () - 3);
}
} else for (i = 1; i < GIB_Argc(); i++)
var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals, &zero,
GIB_Argv (1), &index, true);
}
@ -217,18 +218,45 @@ static void
GIB_Global_f (void)
{
gib_var_t *var;
unsigned int index;
hashtab_t *zero = 0;
unsigned int index, i;
static hashtab_t *zero = 0;
if (GIB_Argc () < 2)
GIB_USAGE ("var [= value1 value2 ...]");
else {
var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
GIB_USAGE ("var [= value1 value2 ...] || var [var2 var3 ...]");
else if (!strcmp (GIB_Argv(2), "=")) {
var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
GIB_Argv (1), &index, true);
if (GIB_Argc () >= 3)
GIB_Var_Assign (var, index, cbuf_active->args->argv + 3,
GIB_Argc () - 3);
} else for (i = 1; i < GIB_Argc(); i++)
var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
GIB_Argv (1), &index, true);
}
static void
GIB_Global_Delete_f (void)
{
gib_var_t *var;
unsigned int index, i;
hashtab_t *source;
static hashtab_t *zero = 0;
char *c;
if (GIB_Argc () < 2)
GIB_USAGE ("var [var2 var2 ...]");
else for (i = 1; i < GIB_Argc(); i++) {
if ((c = strrchr (GIB_Argv(i), '.'))) {
*(c++) = 0;
if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->globals, &zero,
GIB_Argv (i), &index, false)))
continue;
source = var->array[index].leaves;
} else {
c = GIB_Argv(i);
source = GIB_DATA(cbuf_active)->globals;
}
Hash_Free (source, Hash_Del (source, c));
}
}
@ -598,13 +626,12 @@ GIB_Thread_Kill_f (void)
id);
return;
}
thread->trash = true;
// Set error condition on the top of the stack so the thread will exit
// if currently running
// We can't simply nuke the thread, as it would cause the stack walker
// to segfault if a thread kills itself.
for (cur = thread->cbuf;
cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down);
cur->state = CBUF_STATE_ERROR;
GIB_DATA (cur)->done = true;
}
}
@ -884,6 +911,7 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("function::export", GIB_Function_Export_f);
GIB_Builtin_Add ("local", GIB_Local_f);
GIB_Builtin_Add ("global", GIB_Global_f);
GIB_Builtin_Add ("global::delete", GIB_Global_Delete_f);
GIB_Builtin_Add ("domain", GIB_Domain_f);
GIB_Builtin_Add ("domain::clear", GIB_Domain_Clear_f);
GIB_Builtin_Add ("return", GIB_Return_f);

View file

@ -80,7 +80,7 @@ GIB_Execute_Split_Array (cbuf_t * cbuf)
{
gib_var_t *var;
unsigned int i;
int start = 0, end = 0;
int start = 0, end = (int) ((unsigned int) ~0 >> 1);
char *c, *str = cbuf->args->argv[cbuf->args->argc - 1]->str + 1;
void *m = cbuf->args->argm[cbuf->args->argc - 1];
@ -93,16 +93,12 @@ GIB_Execute_Split_Array (cbuf_t * cbuf)
if ((c = strchr (str + i + 1, ':'))) {
if (c[1] != ']')
end = atoi (c + 1);
else
end = (int) ((unsigned int) ~0 >> 1);
} else
end = start + 1;
break;
}
cbuf->args->argc--;
if (!
(var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
if (!(var = GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
&GIB_DATA (cbuf)->globals, str, &i, false)))
return;
if (end < 0)
@ -116,8 +112,8 @@ GIB_Execute_Split_Array (cbuf_t * cbuf)
} else if (start >= var->size || start >= end)
return;
for (i = start; i < end; i++) {
if (var->array[i])
Cbuf_ArgsAdd (cbuf->args, var->array[i]->str);
if (var->array[i].value)
Cbuf_ArgsAdd (cbuf->args, var->array[i].value->str);
else
Cbuf_ArgsAdd (cbuf->args, "");
cbuf->args->argm[cbuf->args->argc - 1] = m;
@ -174,8 +170,8 @@ GIB_Execute_For_Next (cbuf_t * cbuf)
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals,
&GIB_DATA (cbuf)->globals, array->dstrs[0]->str,
&index, true);
dstring_clearstr (var->array[index]);
dstring_appendstr (var->array[index], array->dstrs[array->size]->str);
dstring_clearstr (var->array[index].value);
dstring_appendstr (var->array[index].value, array->dstrs[array->size]->str);
return 1;
}
@ -195,10 +191,9 @@ GIB_Execute (cbuf_t * cbuf)
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
return;
if (g->ip->flags & TREE_COND) {
cond =
g->ip->flags & TREE_NOT ? atoi (cbuf->args->argv[1]->
str) : !atoi (cbuf->args->
argv[1]->str);
cond = g->ip->flags & TREE_NOT ?
atoi (cbuf->args->argv[1]->str) :
!atoi (cbuf->args->argv[1]->str);
if (cond)
g->ip = g->ip->jump;
} else if (g->ip->flags & TREE_FORNEXT) {

View file

@ -162,11 +162,11 @@ GIB_Function_Prepare_Args (cbuf_t * cbuf, dstring_t ** args, unsigned int argc)
memset (var->array + 1, 0, (argc - 1) * sizeof (dstring_t *));
var->size = argc;
for (i = 0; i < argc; i++) {
if (var->array[i])
dstring_clearstr (var->array[i]);
if (var->array[i].value)
dstring_clearstr (var->array[i].value);
else
var->array[i] = dstring_newstr ();
dstring_appendstr (var->array[i], args[i]->str);
var->array[i].value = dstring_newstr ();
dstring_appendstr (var->array[i].value, args[i]->str);
}
}

View file

@ -51,72 +51,6 @@ const char rcsid[] = "$Id$";
#include "exp.h"
static int
GIB_Process_Variable (dstring_t * token, unsigned int *i)
{
hashtab_t *one = GIB_DATA (cbuf_active)->locals, *two =
GIB_DATA (cbuf_active)->globals;
unsigned int n = *i, j, k, start = *i, index = 0, len, len2;
gib_var_t *var = 0;
cvar_t *cvar;
char c;
const char *str;
(*i)++;
if (token->str[*i] == '{') {
if ((c = GIB_Parse_Match_Brace (token->str, i))) {
GIB_Error ("Parse", "Could not find match for %c.", c);
return -1;
}
n += 2;
len = 1;
} else {
for (; isalnum ((byte) token->str[*i]) || token->str[*i] == '_';
(*i)++);
if (token->str[*i] == '[') {
if ((c = GIB_Parse_Match_Index (token->str, i))) {
GIB_Error ("Parse", "Could not find match for %c.", c);
return -1;
} else
(*i)++;
}
n++;
len = 0;
}
c = token->str[*i];
token->str[*i] = 0;
for (k = n; token->str[n]; n++)
if (token->str[n] == '$' || token->str[n] == '#')
if (GIB_Process_Variable (token, &n))
return -1;
index = 0;
if (n && token->str[n - 1] == ']')
for (j = n - 1; j; j--)
if (token->str[j] == '[') {
index = atoi (token->str + j + 1);
token->str[j] = 0;
}
if ((var = GIB_Var_Get (one, two, token->str + k)) && index < var->size
&& var->array[index]) {
if (token->str[start] == '#')
str = va ("%u", var->size - index);
else
str = var->array[index]->str;
} else if (token->str[start] == '#')
str = "0";
else if ((cvar = Cvar_FindVar (token->str + k)))
str = cvar->string;
else
str = "";
token->str[n] = c;
len += n - start;
len2 = strlen (str);
dstring_replace (token, start, len, str, len2);
*i = start + len2 - 1;
return 0;
}
int
GIB_Process_Math (struct dstring_s *token, unsigned int i)
{
@ -169,22 +103,28 @@ GIB_Process_Embedded (gib_tree_t * node, cbuf_args_t * args)
GIB_Buffer_Pop_Sstack (cbuf_active);
} else if (cur->flags & TREE_P_EMBED) {
n = args->argv[args->argc - 1]->size - 1;
if (cur->delim == '$')
dstring_appendstr (args->argv[args->argc - 1], "${");
else
dstring_appendstr (args->argv[args->argc - 1], "#{");
dstring_appendstr (args->argv[args->argc - 1], cur->str);
dstring_appendstr (args->argv[args->argc - 1], "}");
if (GIB_Process_Variable (args->argv[args->argc - 1], &n))
return -1;
} else
if ((var =
GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals,
var = GIB_Var_Get_Very_Complex (&GIB_DATA (cbuf_active)->locals,
&GIB_DATA (cbuf_active)->globals,
args->argv[args->argc - 1], n, &index, false);
cvar = Cvar_FindVar (args->argv[args->argc - 1]->str);
args->argv[args->argc - 1]->size = n+1;
args->argv[args->argc - 1]->str[n] = 0;
if (var) {
if (cur->delim == '#')
dasprintf (args->argv[args->argc - 1], "%u", var->size);
else
dstring_appendstr (args->argv[args->argc - 1], var->array[index].value->str);
} else if (cur->delim == '#')
dstring_appendstr (args->argv[args->argc - 1], "0");
else if (cvar)
dstring_appendstr (args->argv[args->argc - 1], cvar->string);
} else if ((var = GIB_Var_Get_Complex (&GIB_DATA (cbuf_active)->locals,
&GIB_DATA (cbuf_active)->globals,
(char *) cur->str, &index, false))) {
if (cur->delim == '$')
dstring_appendstr (args->argv[args->argc - 1],
var->array[index]->str);
var->array[index].value->str);
else
dasprintf (args->argv[args->argc - 1], "%u", var->size - index);
} else if (cur->delim == '#')

View file

@ -117,11 +117,12 @@ GIB_Thread_Execute (void)
for (cur = gib_threads; cur; cur = tmp) {
tmp = cur->next;
if (cur->trash) {
if (GIB_DATA(cur->cbuf)->program)
Cbuf_Execute_Stack (cur->cbuf);
else {
GIB_Thread_Remove (cur);
GIB_Thread_Delete (cur);
} else
Cbuf_Execute_Stack (cur->cbuf);
}
}
}

View file

@ -39,7 +39,9 @@ const char rcsid[] = "$Id$";
#include <stdlib.h>
#include "QF/dstring.h"
#include "QF/va.h"
#include "QF/hash.h"
#include "QF/cvar.h"
#include "QF/gib_vars.h"
#include "QF/gib_buffer.h"
#include "QF/gib_parse.h"
@ -69,9 +71,13 @@ GIB_Var_Free (void *ele, void *ptr)
unsigned int i;
gib_var_t *l = (gib_var_t *) ele;
for (i = 0; i < l->size; i++)
if (l->array[i])
dstring_delete (l->array[i]);
for (i = 0; i < l->size; i++) {
if (l->array[i].value)
dstring_delete (l->array[i].value);
if (l->array[i].leaves)
Hash_DelTable (l->array[i].leaves);
}
free (l->array);
free ((void *) l->key);
free (l);
}
@ -89,48 +95,127 @@ GIB_Var_Get (hashtab_t * first, hashtab_t * second, const char *key)
return 0;
}
/* Modifies key but restores it before returning */
/* Destroys key! */
gib_var_t *
GIB_Var_Get_Complex (hashtab_t ** first, hashtab_t ** second, char *key,
unsigned int *ind, qboolean create)
{
unsigned int i, index;
qboolean fix = false;
static hashtab_t *zero = 0;
unsigned int i, n, index, len, start;
gib_var_t *var;
i = strlen (key);
index = 0;
if (i && key[i - 1] == ']')
for (i--; i; i--)
if (key[i] == '[') {
index = atoi (key + i + 1);
key[i] = 0;
fix = true;
break;
len = strlen(key);
for (start = i = 0; i <= len; i++) {
if (key[i] == '.' || key[i] == 0) {
index = 0;
key[i] = 0;
if (i && key[i - 1] == ']')
for (n = i - 1; n; n--)
if (key[n] == '[') {
index = atoi (key + n + 1);
key[n] = 0;
break;
}
if (!(var = GIB_Var_Get (*first, *second, key+start))) {
if (create) {
var = GIB_Var_New (key+start);
if (!*first)
*first = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
Hash_Add (*first, var);
} else
return 0;
}
if (!(var = GIB_Var_Get (*first, *second, key))) {
if (create) {
var = GIB_Var_New (key);
if (!*first)
*first = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
Hash_Add (*first, var);
} else
return 0;
if (index >= var->size) {
if (create) {
var->array =
realloc (var->array, (index + 1) * sizeof (struct gib_varray_s *));
memset (var->array + var->size, 0,
(index + 1 - var->size) * sizeof (struct gib_varray_s *));
var->size = index + 1;
} else
return 0;
}
second = &zero;
first = &var->array[index].leaves;
start = i+1;
}
}
if (fix)
key[i] = '[';
if (index >= var->size) {
if (create) {
var->array =
realloc (var->array, (index + 1) * sizeof (dstring_t *));
memset (var->array + var->size, 0,
(index + 1 - var->size) * sizeof (dstring_t *));
var->size = index + 1;
} else
return 0;
if (!var->array[index].value)
var->array[index].value = dstring_newstr ();
*ind = index;
return var;
}
gib_var_t *
GIB_Var_Get_Very_Complex (hashtab_t ** first, hashtab_t ** second, dstring_t *key, unsigned int start,
unsigned int *ind, qboolean create)
{
static hashtab_t *zero = 0;
hashtab_t *one = *first, *two = *second;
unsigned int i, index, index2, n;
gib_var_t *var;
cvar_t *cvar;
char c, *str;
qboolean done = false;
for (i = start; !done; i++) {
if (key->str[i] == '.' || key->str[i] == 0) {
index = 0;
if (!key->str[i])
done = true;
key->str[i] = 0;
if (i && key->str[i - 1] == ']')
for (n = i-1; n; n--)
if (key->str[n] == '[') {
index = atoi (key->str + n + 1);
key->str[n] = 0;
break;
}
if (!(var = GIB_Var_Get (*first, *second, key->str+start))) {
if (create) {
var = GIB_Var_New (key->str+start);
if (!*first)
*first = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
Hash_Add (*first, var);
} else
return 0;
}
if (index >= var->size) {
if (create) {
var->array =
realloc (var->array, (index + 1) * sizeof (struct gib_varray_s));
memset (var->array + var->size, 0,
(index + 1 - var->size) * sizeof (struct gib_varray_s));
var->size = index + 1;
} else
return 0;
}
second = &zero;
first = &var->array[index].leaves;
start = i+1;
} else if (key->str[i] == '$' || key->str[i] == '#') {
n = i;
if (GIB_Parse_Match_Var (key->str, &i))
return 0;
c = key->str[i];
key->str[i+(c != '}')] = 0;
if ((var = GIB_Var_Get_Very_Complex (&one, &two, key, n+1+(c == '}'), &index2, create))) {
if (key->str[n] == '#')
str = va("%u", var->size);
else
str = var->array[index2].value->str;
dstring_replace (key, n, i-n, str, strlen (str));
} else if (key->str[n] == '#')
dstring_replace (key, n, i-n, "0", 1);
else if ((cvar = Cvar_FindVar (key->str+n+1+(c == '}'))))
dstring_replace (key, n, i-n, cvar->string, strlen (cvar->string));
else
dstring_snip (key, n, n-i);
}
}
if (!var->array[index])
var->array[index] = dstring_newstr ();
if (!var->array[index].value)
var->array[index].value = dstring_newstr ();
*ind = index;
return var;
}
@ -144,23 +229,26 @@ GIB_Var_Assign (gib_var_t * var, unsigned int index, dstring_t ** values,
// Now, expand the array to the correct size
len = numv + index;
if (len >= var->size) {
var->array = realloc (var->array, len * sizeof (dstring_t *));
var->array = realloc (var->array, len * sizeof (struct gib_varray_s));
memset (var->array + var->size, 0,
(len - var->size) * sizeof (dstring_t *));
(len - var->size) * sizeof (struct gib_varray_s));
var->size = len;
} else if (len < var->size) {
for (i = len; i < var->size; i++)
if (var->array[i])
dstring_delete (var->array[i]);
var->array = realloc (var->array, len * sizeof (dstring_t *));
for (i = len; i < var->size; i++) {
if (var->array[i].value)
dstring_delete (var->array[i].value);
if (var->array[i].leaves)
Hash_DelTable (var->array[i].leaves);
}
var->array = realloc (var->array, len * sizeof (struct gib_varray_s));
}
var->size = len;
for (i = 0; i < numv; i++) {
if (var->array[i + index])
dstring_clearstr (var->array[i + index]);
if (var->array[i + index].value)
dstring_clearstr (var->array[i + index].value);
else
var->array[i + index] = dstring_newstr ();
dstring_appendstr (var->array[i + index], values[i]->str);
var->array[i + index].value = dstring_newstr ();
dstring_appendstr (var->array[i + index].value, values[i]->str);
}
}