A few GIB bugfixes, cleanups, and enhancements. Still more to come.

This commit is contained in:
Brian Koropoff 2003-01-29 04:34:23 +00:00
parent 06cd013fc6
commit 1f5cabcba9
10 changed files with 112 additions and 103 deletions

View File

@ -55,11 +55,10 @@ typedef struct cbuf_s {
CBUF_STATE_NORMAL = 0, // Normal condition
CBUF_STATE_WAIT, // Buffer is stalled until next frame
CBUF_STATE_ERROR, // An unrecoverable error occured
CBUF_STATE_STACK, // A buffer has been added to the stack
CBUF_STATE_DONE, // This buffer has completed execution
} state;
CBUF_STATE_STACK // A buffer has been added to the stack
} state;
qboolean strict; // Should we tolerate unknown commands
qboolean strict; // Should we tolerate unknown commands?
double resumetime; // Time when stack can be executed again
void *data; // Pointer to interpreter data
@ -72,7 +71,6 @@ typedef struct cbuf_interpreter_s {
void (*insert) (struct cbuf_s *cbuf, const char *str);
void (*execute) (struct cbuf_s *cbuf);
void (*execute_sets) (struct cbuf_s *cbuf);
void (*reset) (struct cbuf_s *cbuf);
} cbuf_interpreter_t;
extern cbuf_t *cbuf_active;

View File

@ -39,7 +39,7 @@
typedef struct gib_buffer_data_s {
struct gib_tree_s *program, *ip;
struct dstring_s *arg_composite;
qboolean done, waitret, haveret;
qboolean done, waitret;
struct gib_sstack_s {
struct gib_dsarray_s {
struct dstring_s **dstrs;
@ -53,7 +53,6 @@ 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_Reset (struct cbuf_s *cbuf);
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

@ -47,6 +47,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);
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);
void GIB_Var_Init (void);

View File

@ -111,16 +111,6 @@ GIB_Buffer_Insert (cbuf_t *cbuf, const char *str)
Cbuf_Error ("parse", "Parse error in program!");
}
void
GIB_Buffer_Reset (cbuf_t *cbuf)
{
GIB_DATA(cbuf)->done = GIB_DATA(cbuf)->waitret = GIB_DATA(cbuf)->haveret = false;
if (GIB_DATA(cbuf)->program)
GIB_Tree_Free_Recursive (GIB_DATA(cbuf)->program, false);
GIB_DATA(cbuf)->ip = 0;
GIB_DATA(cbuf)->program = 0;
}
void
GIB_Buffer_Push_Sstack (struct cbuf_s *cbuf)
{
@ -160,5 +150,4 @@ cbuf_interpreter_t gib_interp = {
GIB_Buffer_Insert,
GIB_Execute,
GIB_Execute,
GIB_Buffer_Reset
};

View File

@ -124,7 +124,6 @@ GIB_Return (const char *str)
{
dstring_t *dstr;
if (GIB_DATA(cbuf_active)->waitret) {
GIB_DATA(cbuf_active)->haveret = true;
dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
dstring_clearstr (dstr);
if (!str)
@ -179,32 +178,38 @@ GIB_Function_Get_f (void)
static void
GIB_Local_f (void)
{
unsigned int i, index;
gib_var_t *var;
unsigned int index;
hashtab_t *zero = 0;
if (GIB_Argc () < 2)
GIB_USAGE ("var1 [var2 var3 ...]");
else
for (i = 1; i < GIB_Argc(); i++)
GIB_Var_Get_Complex (&GIB_DATA(cbuf_active)->locals, &zero, GIB_Argv(i), &index, true);
GIB_USAGE ("var [= value1 value2 ...]");
else {
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);
}
}
static void
GIB_Global_f (void)
{
unsigned int i, index;
gib_var_t *var;
unsigned int index;
hashtab_t *zero = 0;
if (GIB_Argc () < 2)
GIB_USAGE ("var1 [var2 var3 ...]");
else
for (i = 1; i < GIB_Argc(); i++)
GIB_Var_Get_Complex (&GIB_DATA(cbuf_active)->globals, &zero, GIB_Argv(i), &index, true);
GIB_USAGE ("var [= value1 value2 ...]");
else {
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);
}
}
static void
GIB_Global_Domain_f (void)
GIB_Domain_f (void)
{
if (GIB_Argc() != 2)
GIB_USAGE ("domain");
@ -218,15 +223,8 @@ GIB_Return_f (void)
cbuf_t *sp = cbuf_active->up;
GIB_DATA(cbuf_active)->done = true;
if (!GIB_Argm(0)->next) // No return values
return;
else if (GIB_Argc() == 1) // Empty return array
GIB_DATA(sp)->waitret = false;
else if (!sp || // Nothing above us on the stack
sp->interpreter != &gib_interp || // Not a GIB buffer
!GIB_DATA(sp)->waitret) // Doesn't want a return value
Sys_DPrintf("GIB warning: unwanted return value(s) discarded.\n"); // Not a serious error
else {
if (GIB_Argc() > 1 && sp && sp->interpreter == &gib_interp && GIB_DATA(sp)->waitret) {
unsigned int i;
dstring_t *dstr;
for (i = 1; i < GIB_Argc(); i++) {
@ -234,7 +232,6 @@ GIB_Return_f (void)
dstring_clearstr (dstr);
dstring_appendstr (dstr, GIB_Argv(i));
}
GIB_DATA(sp)->waitret = false;
}
}
@ -395,12 +392,36 @@ GIB_String_Equal_f (void)
}
static void
GIB_String_Findsub_f (void)
GIB_String_Sub_f (void)
{
dstring_t *ret;
int start, end, len;
if (GIB_Argc() != 4)
GIB_USAGE ("string start end");
else {
len = strlen (GIB_Argv(1));
start = atoi (GIB_Argv(2));
end = atoi (GIB_Argv(3));
while (start < 0)
start += len-1;
while (end < 0)
end += len;
if (start >= len)
return;
if (end > len || !end)
end = len;
if ((ret = GIB_Return (0)))
dstring_appendsubstr (ret, GIB_Argv(1)+start, end-start);
}
}
static void
GIB_String_Find_f (void)
{
dstring_t *ret;
char *haystack, *res;
if (GIB_Argc() != 3) {
GIB_USAGE ("string substr");
GIB_USAGE ("haystack needle");
return;
}
haystack = GIB_Argv(1);
@ -752,6 +773,16 @@ GIB_Print_f (void)
Sys_Printf ("%s", GIB_Argv(1));
}
static void
GIB_Random_f (void)
{
dstring_t *ret;
if (GIB_Argc() != 1)
GIB_USAGE ("");
else if ((ret = GIB_Return (0)))
dsprintf (ret, "%.10g", (double) random()/(double) RAND_MAX);
}
void
GIB_Builtin_Init (qboolean sandbox)
{
@ -766,15 +797,15 @@ 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::domain", GIB_Global_Domain_f);
GIB_Builtin_Add ("domain", GIB_Domain_f);
GIB_Builtin_Add ("return", GIB_Return_f);
// GIB_Builtin_Add ("dieifnot", GIB_Dieifnot_f);
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::findsub", GIB_String_Findsub_f);
GIB_Builtin_Add ("string::sub", GIB_String_Sub_f);
GIB_Builtin_Add ("string::find", GIB_String_Find_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);
@ -788,4 +819,5 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("file::delete", GIB_File_Delete_f);
GIB_Builtin_Add ("range", GIB_Range_f);
GIB_Builtin_Add ("print", GIB_Print_f);
GIB_Builtin_Add ("random", GIB_Random_f);
}

View File

@ -145,38 +145,6 @@ GIB_Execute_Prepare_Line (cbuf_t *cbuf, gib_tree_t *line)
return 0;
}
static void
GIB_Execute_Assign (cbuf_t *cbuf)
{
cbuf_args_t *args = cbuf->args;
gib_var_t *var;
unsigned int index, i, len, el;
// First, grab our variable
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &GIB_DATA(cbuf)->globals, args->argv[0]->str, &index, true);
// Now, expand the array to the correct size
len = args->argc-2 + index;
if (len >= var->size) {
var->array = realloc (var->array, len * sizeof (dstring_t *));
memset (var->array+var->size, 0, (len-var->size) * sizeof (dstring_t *));
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 *));
}
var->size = len;
for (i = 2; i < args->argc; i++) {
el = i-2+index;
if (var->array[el])
dstring_clearstr (var->array[el]);
else
var->array[el] = dstring_newstr ();
dstring_appendstr (var->array[el], args->argv[i]->str);
}
}
int
GIB_Execute_For_Next (cbuf_t *cbuf)
{
@ -201,13 +169,8 @@ GIB_Execute (cbuf_t *cbuf)
gib_builtin_t *b;
gib_function_t *f;
if (g->waitret) {
Cbuf_Error ("return", "Embedded function '%s' did not return a value.", cbuf->args->argv[0]->str);
return;
}
if (!g->program) {
if (!g->program)
return;
}
if (!g->ip)
g->ip = g->program;
while (!g->done) {
@ -225,29 +188,23 @@ GIB_Execute (cbuf_t *cbuf)
continue;
} else if (cbuf->args->argc) {
if (g->ip->flags & TREE_EMBED) {
// Get ready for return values
g->waitret = true;
GIB_Buffer_Push_Sstack (cbuf); // Make room for return values
GIB_Buffer_Push_Sstack (cbuf);
} else
g->waitret = false;
if (cbuf->args->argc >= 2 && !strcmp (cbuf->args->argv[1]->str, "=") && ((gib_tree_t *)cbuf->args->argm[1])->delim == ' ') {
unsigned int index;
GIB_Var_Assign (GIB_Var_Get_Complex (&g->locals, &g->globals, cbuf->args->argv[0]->str, &index, true), index, cbuf->args->argv+2, cbuf->args->argc-2);
}
if (!strcmp (cbuf->args->argv[1]->str, "=") && ((gib_tree_t *)cbuf->args->argm[1])->delim == ' ')
GIB_Execute_Assign (cbuf);
else if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str))) {
b->func ();
// If there already was an error, don't override it
if (g->ip->flags & TREE_EMBED && !cbuf->state) {
if (!g->haveret) {
Cbuf_Error ("return", "Embedded builtin '%s' did not return a value.", cbuf->args->argv[0]->str);
return;
}
g->haveret = g->waitret = 0;
}
} else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
cbuf_t *new = Cbuf_New (&gib_interp);
cbuf->down = new;
new->up = cbuf;
cbuf->state = CBUF_STATE_STACK;
GIB_Function_Execute (new, f, cbuf->args);
if (g->ip->flags & TREE_EMBED)
g->waitret = true;
} else {
GIB_Execute_Generate_Composite (cbuf);
Cmd_Command (cbuf->args);

View File

@ -246,7 +246,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_
// Handle comments
} else if (program[*i] == '/' && program[*i+1] == '/') {
for((*i) += 2; program[*i] && program[*i] != '\n'; (*i)++);
return nodes;
goto DONE;
}
}
}
@ -276,7 +276,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_
cur->flags |= TREE_P_EMBED;
// Add any embedded commands to top of chain
if (new) {
for (tmp = new; tmp->next; tmp = tmp->next); // Get to end of embedded list
for (tmp = new; tmp->next; tmp = tmp->next);
tmp->next = embs;
embs = new;
}
@ -306,6 +306,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_
(*i)++;
node = &cur->next;
}
DONE:
*embedded = embs;
return nodes;
ERROR:
@ -375,7 +376,11 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
// If we have a while loop, handle that
if (!strcmp (line->children->str, "while")) {
// Sanity checks
if (!line->children->next || !line->children->next->next || !line->children->next->next->children || line->flags & TREE_EMBED) {
if (!line->children->next ||
!line->children->next->next ||
line->children->next->next->delim != '{' ||
!line->children->next->next->children ||
line->flags & TREE_EMBED) {
gib_parse_error = true;
return line;
}
@ -406,7 +411,7 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
// Find last token in line (contains program block)
for (tmp = line->children->next->next->next->next; tmp->next; tmp = tmp->next);
// More sanity
if (!tmp->children) {
if (tmp->delim != '{' || !tmp->children) {
gib_parse_error = true;
return line;
}

View File

@ -127,6 +127,33 @@ GIB_Var_Get_Complex (hashtab_t **first, hashtab_t **second, char *key, unsigned
return var;
}
void
GIB_Var_Assign (gib_var_t *var, unsigned int index, dstring_t **values, unsigned int numv)
{
unsigned int i, len;
// Now, expand the array to the correct size
len = numv + index;
if (len >= var->size) {
var->array = realloc (var->array, len * sizeof (dstring_t *));
memset (var->array+var->size, 0, (len-var->size) * sizeof (dstring_t *));
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 *));
}
var->size = len;
for (i = 0; i < numv; i++) {
if (var->array[i+index])
dstring_clearstr (var->array[i+index]);
else
var->array[i+index] = dstring_newstr ();
dstring_appendstr (var->array[i+index], values[i]->str);
}
}
static const char *
GIB_Domain_Get_Key (void *ele, void *ptr)
{
@ -150,6 +177,7 @@ GIB_Domain_Get (const char *name)
d = calloc (1, sizeof (gib_domain_t));
d->name = strdup(name);
d->vars = Hash_NewTable (1024, GIB_Var_Get_Key, GIB_Var_Free, 0);
Hash_Add (gib_domains, d);
}
return d->vars;
}

View File

@ -191,8 +191,9 @@ ERROR:
Cbuf_DeleteStack (cbuf->down);
cbuf->down = 0;
}
if (cbuf->interpreter->reset)
cbuf->interpreter->reset (cbuf);
// Tear it down and build it back up
cbuf->interpreter->destruct (cbuf);
cbuf->interpreter->construct (cbuf);
}
void

View File

@ -236,5 +236,4 @@ cbuf_interpreter_t id_interp = {
COM_insert,
COM_execute,
COM_execute_sets,
NULL
};