GIB: Added proper reference counting on parse trees, got threads working

again, added a few new builtins and renamed some others, made misc. fixes
and enhancements.
This commit is contained in:
Brian Koropoff 2003-01-30 23:26:43 +00:00
parent 4ee0c42dcc
commit 580ca17546
12 changed files with 126 additions and 127 deletions

View file

@ -53,6 +53,7 @@ typedef struct gib_buffer_data_s {
void GIB_Buffer_Construct (struct cbuf_s *cbuf);
void GIB_Buffer_Destruct (struct cbuf_s *cbuf);
void GIB_Buffer_Set_Program (cbuf_t *cbuf, gib_tree_t *program);
void GIB_Buffer_Add (cbuf_t *cbuf, const char *str);
void GIB_Buffer_Insert (cbuf_t *cbuf, const char *str);
void GIB_Buffer_Push_Sstack (struct cbuf_s *cbuf);

View file

@ -32,6 +32,7 @@
#ifndef __gib_function_h
#define __gib_function_h
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/gib_tree.h"
@ -45,7 +46,7 @@ typedef struct gib_function_s {
void GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, hashtab_t *globals);
gib_function_t *GIB_Function_Find (const char *name);
void GIB_Function_Prepare_Args (cbuf_t *cbuf, cbuf_args_t *args);
void GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, cbuf_args_t *args);
void GIB_Function_Prepare_Args (cbuf_t *cbuf, dstring_t **args, unsigned int argc);
void GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);
#endif

View file

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

View file

@ -48,10 +48,9 @@ typedef struct gib_tree_s {
const char *str;
char delim;
struct gib_tree_s *children, *next, *parent, *jump;
unsigned int flags, start, end;
unsigned int flags, start, end, refs;
} gib_tree_t;
gib_tree_t *GIB_Tree_New (unsigned int flags);
void GIB_Tree_Free_Recursive (gib_tree_t *tree, qboolean force);
void GIB_Tree_Add_Flag_Recursive (gib_tree_t *tree, unsigned int flag);
void GIB_Tree_Free_Recursive (gib_tree_t *tree);
#endif /* __GIB_TREE_H */

View file

@ -65,8 +65,10 @@ GIB_Buffer_Destruct (struct cbuf_s *cbuf)
dstring_delete (g->arg_composite);
if (g->locals)
Hash_DelTable (g->locals);
if (g->program)
GIB_Tree_Free_Recursive (g->program, false);
if (g->program) {
g->program->refs--;
GIB_Tree_Free_Recursive (g->program);
}
for (i = 0; i < g->stack.size; i++) {
for (j = 0; j < g->stack.values[i].realsize; j++)
dstring_delete (g->stack.values[i].dstrs[j]);
@ -78,6 +80,12 @@ GIB_Buffer_Destruct (struct cbuf_s *cbuf)
free (cbuf->data);
}
void
GIB_Buffer_Set_Program (cbuf_t *cbuf, gib_tree_t *program)
{
GIB_DATA(cbuf)->program = program;
}
void
GIB_Buffer_Add (cbuf_t *cbuf, const char *str)
{
@ -104,6 +112,10 @@ GIB_Buffer_Insert (cbuf_t *cbuf, const char *str)
if ((lines = GIB_Parse_Lines (str, TREE_NORMAL))) {
for (cur = lines; cur; cur = cur->next);
//if (g->ip) { // This buffer is already running!
if (g->program)
g->program->refs--;
cur->next = g->program;
g->program = lines;
}

View file

@ -234,49 +234,6 @@ GIB_Return_f (void)
}
}
}
/*
static void
GIB_Field_Get_f (void)
{
unsigned int field;
char *list, *end;
const char *ifs;
if (GIB_Argc() < 3 || GIB_Argc() > 4) {
GIB_USAGE ("list element [fs]");
return;
}
field = atoi (GIB_Argv(2));
if (GIB_Argc() == 4)
ifs = GIB_Argv (3);
else if (!(ifs = GIB_Var_Get_Local (cbuf_active, "ifs")))
ifs = " \t\n\r";
if (!*ifs) {
if (field < strlen(GIB_Argv(1))) {
GIB_Argv(1)[field+1] = 0;
GIB_Return (GIB_Argv(1)+field);
} else
GIB_Return ("");
return;
}
for (list = GIB_Argv(1); *list && strchr(ifs, *list); list++);
while (field) {
while (!strchr(ifs, *list))
list++;
while (*list && strchr(ifs, *list))
list++;
if (!*list) {
GIB_Return ("");
return;
}
field--;
}
for (end = list; !strchr(ifs, *end); end++);
*end = 0;
GIB_Return (list);
}
*/
static void
GIB_For_f (void)
@ -345,7 +302,7 @@ GIB_Runexported_f (void)
"The QuakeForge developers.", Cmd_Argv(0));
else {
cbuf_t *sub = Cbuf_New (&gib_interp);
GIB_Function_Execute (sub, f, cbuf_active->args);
GIB_Function_Execute (sub, f, cbuf_active->args->argv, cbuf_active->args->argc);
cbuf_active->down = sub;
sub->up = cbuf_active;
cbuf_active->state = CBUF_STATE_STACK;
@ -371,7 +328,7 @@ GIB_Function_Export_f (void)
}
static void
GIB_String_Length_f (void)
GIB_Length_f (void)
{
dstring_t *ret;
if (GIB_Argc() != 2)
@ -381,7 +338,7 @@ GIB_String_Length_f (void)
}
static void
GIB_String_Equal_f (void)
GIB_Equal_f (void)
{
if (GIB_Argc() != 3)
GIB_USAGE ("string1 string2");
@ -392,7 +349,7 @@ GIB_String_Equal_f (void)
}
static void
GIB_String_Sub_f (void)
GIB_Slice_f (void)
{
dstring_t *ret;
int start, end, len;
@ -415,8 +372,9 @@ GIB_String_Sub_f (void)
}
}
/*
static void
GIB_String_Find_f (void)
GIB_Find_f (void)
{
dstring_t *ret;
char *haystack, *res;
@ -431,7 +389,35 @@ GIB_String_Find_f (void)
} else
GIB_Return ("-1");
}
*/
static void
GIB_Split_f (void)
{
char *end, *start;
const char *ifs;
if (GIB_Argc() < 2 || GIB_Argc() > 3) {
GIB_USAGE ("string [fs]");
return;
}
ifs = GIB_Argc() == 3 ? GIB_Argv (2) : " \t\r\n";
end = GIB_Argv(1);
while (*end) {
for (; strchr(ifs, *end); end++)
if (!*end)
return;
start = end;
while (!strchr(ifs, *end))
end++;
if (*end)
*(end++) = 0;
GIB_Return (start);
}
}
static void
GIB_Regex_Match_f (void)
{
@ -513,11 +499,14 @@ static void
GIB_Thread_Create_f (void)
{
dstring_t *ret;
if (GIB_Argc() != 2)
GIB_USAGE ("program");
gib_function_t *f;
if (GIB_Argc() < 2)
GIB_USAGE ("function [arg1 arg2 ...]");
else if (!(f = GIB_Function_Find (GIB_Argv(1))))
Cbuf_Error ("function", "thread::create: no function named '%s' exists.", GIB_Argv(1));
else {
gib_thread_t *thread = GIB_Thread_New ();
Cbuf_AddText (thread->cbuf, GIB_Argv(1));
GIB_Function_Execute (thread->cbuf, f, cbuf_active->args->argv+1, cbuf_active->args->argc-1);
GIB_Thread_Add (thread);
if ((ret = GIB_Return (0)))
dsprintf (ret, "%lu", thread->id);
@ -752,9 +741,10 @@ GIB_Range_f (void)
}
limit = atof(GIB_Argv(2));
start = atof(GIB_Argv(1));
if (GIB_Argc () == 4 && (inc = atof(GIB_Argv(3))) == 0.0)
return;
else
if (GIB_Argc () == 4) {
if ((inc = atof(GIB_Argv(3))) == 0.0)
return;
} else
inc = limit < start ? -1.0 : 1.0;
for (i = atof(GIB_Argv(1)); inc < 0 ? i >= limit : i <= limit; i += inc) {
if (!(dstr = GIB_Return(0)))
@ -802,10 +792,10 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("for", GIB_For_f);
GIB_Builtin_Add ("break", GIB_Break_f);
GIB_Builtin_Add ("continue", GIB_Continue_f);
GIB_Builtin_Add ("string::length", GIB_String_Length_f);
GIB_Builtin_Add ("string::equal", GIB_String_Equal_f);
GIB_Builtin_Add ("string::sub", GIB_String_Sub_f);
GIB_Builtin_Add ("string::find", GIB_String_Find_f);
GIB_Builtin_Add ("length", GIB_Length_f);
GIB_Builtin_Add ("equal", GIB_Equal_f);
GIB_Builtin_Add ("slice", GIB_Slice_f);
GIB_Builtin_Add ("split", GIB_Split_f);
GIB_Builtin_Add ("regex::match", GIB_Regex_Match_f);
GIB_Builtin_Add ("regex::replace", GIB_Regex_Replace_f);
GIB_Builtin_Add ("regex::extract", GIB_Regex_Extract_f);

View file

@ -204,7 +204,7 @@ GIB_Execute (cbuf_t *cbuf)
cbuf->down = new;
new->up = cbuf;
cbuf->state = CBUF_STATE_STACK;
GIB_Function_Execute (new, f, cbuf->args);
GIB_Function_Execute (new, f, cbuf->args->argv, cbuf->args->argc);
} else {
GIB_Execute_Generate_Composite (cbuf);
Cmd_Command (cbuf->args);
@ -216,6 +216,7 @@ GIB_Execute (cbuf_t *cbuf)
return;
}
g->done = false;
GIB_Tree_Free_Recursive (g->program, false);
g->program->refs--;
GIB_Tree_Free_Recursive (g->program);
g->program = g->ip = 0;
}

View file

@ -81,7 +81,7 @@ GIB_Function_Free (void *ele, void *ptr)
dstring_delete (func->text);
free ((void *)func->name);
if (func->program)
GIB_Tree_Free_Recursive (func->program, true);
GIB_Tree_Free_Recursive (func->program);
free (func);
}
@ -97,12 +97,16 @@ GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, ha
{
gib_function_t *func;
program->refs++;
if (!gib_functions)
gib_functions = Hash_NewTable (1024, GIB_Function_Get_Key, GIB_Function_Free, 0);
func = Hash_Find(gib_functions, name);
if (func) {
dstring_clearstr (func->text);
GIB_Tree_Free_Recursive (func->program, true);
func->program->refs--;
GIB_Tree_Free_Recursive (func->program);
} else {
func = GIB_Function_New (name);
Hash_Add (gib_functions, func);
@ -110,8 +114,6 @@ GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, ha
dstring_appendstr (func->text, text);
func->program = program;
func->globals = globals;
GIB_Tree_Add_Flag_Recursive (program, TREE_PERM); // Don't free this, we are using it now
program->flags |= TREE_FUNC; // Even when forcing a recursive free, don't free this
}
/*
@ -130,26 +132,24 @@ GIB_Function_Find (const char *name)
}
void
GIB_Function_Prepare_Args (cbuf_t *cbuf, cbuf_args_t *args)
GIB_Function_Prepare_Args (cbuf_t *cbuf, dstring_t **args, unsigned int argc)
{
static hashtab_t *zero = 0;
unsigned int i;
gib_var_t *var;
static char argss[] = "args", argcs[] = "argc";
static char argss[] = "args";
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero, argss, &i, true);
var->array = realloc (var->array, sizeof (dstring_t *) * args->argc);
memset (var->array+1, 0, (args->argc-1) * sizeof (dstring_t *));
var->size = args->argc;
for (i = 0; i < args->argc; i++) {
var->array = realloc (var->array, sizeof (dstring_t *) * 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]);
else
var->array[i] = dstring_newstr();
dstring_appendstr (var->array[i], args->argv[i]->str);
dstring_appendstr (var->array[i], args[i]->str);
}
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero, argcs, &i, true);
dsprintf(var->array[0], "%u", args->argc);
}
/*
@ -160,9 +160,10 @@ GIB_Function_Prepare_Args (cbuf_t *cbuf, cbuf_args_t *args)
*/
void
GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, cbuf_args_t *args)
GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc)
{
GIB_DATA(cbuf)->program = func->program;
func->program->refs++;
GIB_Buffer_Set_Program (cbuf, func->program);
GIB_DATA(cbuf)->globals = func->globals;
GIB_Function_Prepare_Args (cbuf, args);
GIB_Function_Prepare_Args (cbuf, args, argc);
}

View file

@ -310,7 +310,7 @@ DONE:
*embedded = embs;
return nodes;
ERROR:
GIB_Tree_Free_Recursive (nodes, true);
GIB_Tree_Free_Recursive (nodes);
gib_parse_error = true;
return 0;
}
@ -472,7 +472,7 @@ GIB_Parse_Lines (const char *program, unsigned int flags)
}
return lines;
ERROR:
GIB_Tree_Free_Recursive (lines, true);
GIB_Tree_Free_Recursive (lines);
return 0;
}
@ -570,6 +570,6 @@ GIB_Parse_Embedded (const char *program, unsigned int flags, gib_tree_t **embedd
return lines;
ERROR:
gib_parse_error = true;
GIB_Tree_Free_Recursive (lines, true);
GIB_Tree_Free_Recursive (lines);
return 0;
}

View file

@ -48,32 +48,34 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "QF/dstring.h"
#include "QF/hash.h"
gib_thread_t *gib_threads;
gib_thread_t *gib_threads = 0;
gib_thread_t **gib_thread_p = &gib_threads;
hashtab_t *gib_events;
static unsigned long int nextid = 0;
void
GIB_Thread_Add (gib_thread_t *thread)
{
thread->prev = 0;
thread->next = gib_threads;
if (gib_threads)
gib_threads->prev = thread;
gib_threads = thread;
thread->prev = *gib_thread_p;
*gib_thread_p = thread;
gib_thread_p = &thread->next;
}
void
GIB_Thread_Remove (gib_thread_t *thread)
{
if (thread == gib_threads) {
gib_threads = gib_threads->next;
if (gib_threads)
gib_threads->prev = 0;
} else {
if (thread->prev)
thread->prev->next = thread->next;
if (thread->next)
thread->next->prev = thread->prev;
}
else
gib_threads = thread->next;
if (thread->next)
thread->next->prev = thread->prev;
else if (thread->prev)
gib_thread_p = &thread->prev->next;
else
gib_thread_p = &gib_threads;
}
gib_thread_t *
@ -111,14 +113,14 @@ GIB_Thread_Execute (void)
if (!gib_threads)
return;
for (cur = gib_threads; cur->next; cur = cur->next);
for (; cur; cur = tmp) {
tmp = cur->prev;
if (!cur->cbuf->down) {
for (cur = gib_threads; cur; cur = tmp) {
tmp = cur->next;
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);
}
}
}
@ -181,7 +183,7 @@ GIB_Event_Callback (gib_event_t *event, unsigned int argc, ...)
va_end (ap);
GIB_Function_Execute (thread->cbuf, f, args);
GIB_Function_Execute (thread->cbuf, f, args->argv, args->argc);
GIB_Thread_Add (thread);
Cbuf_ArgsDelete (args);
}

View file

@ -46,6 +46,8 @@ GIB_Tree_New (unsigned int flags)
{
gib_tree_t *new = calloc (1, sizeof (gib_tree_t));
new->flags = flags;
// All nodes are created for a reason, so start with 1 ref
new->refs = 1;
return new;
}
@ -60,29 +62,19 @@ GIB_Tree_Free (gib_tree_t *tree)
}
void
GIB_Tree_Free_Recursive (gib_tree_t *tree, qboolean force)
GIB_Tree_Free_Recursive (gib_tree_t *tree)
{
gib_tree_t *n;
if (tree->refs)
return;
for (; tree; tree = n) {
n = tree->next;
// Leave perm nodes and their children alone
// (creating a temp child of a perm node is illegal)
if (tree->flags & TREE_PERM && !force)
return;
/* Free the children (but not on virtuals, and don't free nested functions EVER) */
if (tree->children && !(tree->children->flags & TREE_FUNC))
GIB_Tree_Free_Recursive (tree->children, force);
if (tree->children) {
// Parent is about to bite the dust, meaning one less reference
tree->children->refs--;
GIB_Tree_Free_Recursive (tree->children);
}
GIB_Tree_Free (tree);
}
}
void
GIB_Tree_Add_Flag_Recursive (gib_tree_t *tree, unsigned int flag)
{
for (; tree; tree = tree->next) {
tree->flags |= flag;
if (tree->children)
GIB_Tree_Add_Flag_Recursive (tree->children, flag);
}
}

View file

@ -65,7 +65,7 @@ Carne_Execute_Script (const char *path, cbuf_args_t *args)
//GIB_Parse_Strip_Comments (mbuf);
GIB_Function_Prepare_Args (mbuf, args);
GIB_Function_Prepare_Args (mbuf, args->argv, args->argc);
// Main loop
while (1) {