mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
Add support for named arguments in GIB functions and methods, fix a few
bugs, allow subclasses of classes written in GIB to access the same set of instance variables.
This commit is contained in:
parent
389ead6f01
commit
f4c174184d
9 changed files with 180 additions and 74 deletions
|
@ -60,7 +60,7 @@ typedef struct gib_object_s {
|
|||
hashtab_t *methods;
|
||||
void **data;
|
||||
unsigned long int handle, refs;
|
||||
hashtab_t *signals;
|
||||
hashtab_t *signals, *vars;
|
||||
llist_t *slots;
|
||||
const char *handstr;
|
||||
} gib_object_t;
|
||||
|
|
|
@ -43,14 +43,14 @@ typedef struct gib_function_s {
|
|||
struct dstring_s *text;
|
||||
struct gib_tree_s *program;
|
||||
struct hashtab_s *globals;
|
||||
struct llist_s *arglist;
|
||||
unsigned int minargs;
|
||||
qboolean exported;
|
||||
} gib_function_t;
|
||||
|
||||
gib_function_t *GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals);
|
||||
gib_function_t *GIB_Function_Find (const char *name);
|
||||
void GIB_Function_Prepare_Args (cbuf_t *cbuf, const char **args, unsigned int argc);
|
||||
void GIB_Function_Prepare_Args_D (cbuf_t *cbuf, dstring_t **args, unsigned int argc);
|
||||
void GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, const char **args, unsigned int argc);
|
||||
void GIB_Function_Execute_D (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);
|
||||
int GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, const char **args, unsigned int argc);
|
||||
int GIB_Function_Execute_D (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,7 @@ const char rcsid[] =
|
|||
#include "QF/cmd.h"
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/hash.h"
|
||||
#include "QF/llist.h"
|
||||
#include "QF/dstring.h"
|
||||
#include "QF/gib.h"
|
||||
|
||||
|
@ -174,24 +175,31 @@ static void
|
|||
GIB_Function_f (void)
|
||||
{
|
||||
gib_tree_t *program;
|
||||
gib_function_t *func;
|
||||
int i;
|
||||
|
||||
if (GIB_Argc () != 3)
|
||||
GIB_USAGE ("name program");
|
||||
if (GIB_Argc () < 3)
|
||||
GIB_USAGE ("name [arg1 arg2 ...] program");
|
||||
else {
|
||||
// Is the function program already tokenized?
|
||||
if (GIB_Argm (2)->delim != '{') {
|
||||
if (GIB_Argm (GIB_Argc()-1)->delim != '{') {
|
||||
// Parse on the fly
|
||||
if (!(program = GIB_Parse_Lines (GIB_Argv (2), 0))) {
|
||||
if (!(program = GIB_Parse_Lines (GIB_Argv
|
||||
(GIB_Argc()-1), 0))) {
|
||||
// Error!
|
||||
GIB_Error ("parse", "Parse error while defining function '%s'.",
|
||||
GIB_Argv (1));
|
||||
return;
|
||||
}
|
||||
} else
|
||||
program = GIB_Argm (2)->children;
|
||||
GIB_Function_Define (GIB_Argv (1), GIB_Argv (2), program,
|
||||
program = GIB_Argm (GIB_Argc()-1)->children;
|
||||
func = GIB_Function_Define (GIB_Argv (1), GIB_Argv (GIB_Argc()-1), program,
|
||||
GIB_DATA (cbuf_active)->script,
|
||||
GIB_DATA (cbuf_active)->globals);
|
||||
llist_flush (func->arglist);
|
||||
for (i = 2; i < GIB_Argc()-1; i++)
|
||||
llist_append (func->arglist, strdup (GIB_Argv(i)));
|
||||
func->minargs = GIB_Argc()-2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -855,12 +863,8 @@ GIB_File_Find_f (void)
|
|||
glob = s + 1;
|
||||
}
|
||||
directory = opendir (path);
|
||||
if (!directory) {
|
||||
GIB_Error ("file",
|
||||
"%s: could not open directory %s: %s", GIB_Argv (0), path,
|
||||
strerror (errno));
|
||||
if (!directory)
|
||||
return;
|
||||
}
|
||||
while ((entry = readdir (directory)))
|
||||
if (strcmp (entry->d_name, ".") && strcmp (entry->d_name, "..")
|
||||
&& !fnmatch (glob, entry->d_name, 0))
|
||||
|
@ -984,6 +988,25 @@ GIB_Emit_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Exists_f (void)
|
||||
{
|
||||
if (GIB_Object_Get (GIB_Argv (1)))
|
||||
GIB_Return ("1");
|
||||
else
|
||||
GIB_Return ("0");
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_Error_f (void)
|
||||
{
|
||||
if (GIB_Argc() < 3) {
|
||||
GIB_USAGE ("error_type explanation");
|
||||
return;
|
||||
} else
|
||||
GIB_Error (GIB_Argv(1), "%s", GIB_Argv(2));
|
||||
}
|
||||
|
||||
static void
|
||||
GIB_bp1_f (void)
|
||||
{
|
||||
|
@ -1049,6 +1072,8 @@ GIB_Builtin_Init (qboolean sandbox)
|
|||
GIB_Builtin_Add ("print", GIB_Print_f);
|
||||
GIB_Builtin_Add ("class", GIB_Class_f);
|
||||
GIB_Builtin_Add ("emit", GIB_Emit_f);
|
||||
GIB_Builtin_Add ("exists", GIB_Exists_f);
|
||||
GIB_Builtin_Add ("error", GIB_Error_f);
|
||||
GIB_Builtin_Add ("bp1", GIB_bp1_f);
|
||||
GIB_Builtin_Add ("bp2", GIB_bp2_f);
|
||||
GIB_Builtin_Add ("bp3", GIB_bp3_f);
|
||||
|
|
|
@ -526,11 +526,16 @@ typedef struct Scrobj_method_s {
|
|||
static void *
|
||||
Scrobj_Construct (gib_object_t *obj)
|
||||
{
|
||||
Scrobj_t *new = malloc (sizeof (Scrobj_t));
|
||||
//Scrobj_t *new = malloc (sizeof (Scrobj_t));
|
||||
//
|
||||
//new->shared = GIB_Var_Hash_New ();
|
||||
|
||||
new->shared = GIB_Var_Hash_New ();
|
||||
//return new;
|
||||
|
||||
return new;
|
||||
if (!obj->vars)
|
||||
obj->vars = GIB_Var_Hash_New ();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
|
@ -546,10 +551,10 @@ Scrobj_Class_Construct (gib_object_t *obj)
|
|||
static void
|
||||
Scrobj_Destruct (void *data)
|
||||
{
|
||||
Scrobj_t *s = (Scrobj_t *) data;
|
||||
//Scrobj_t *s = (Scrobj_t *) data;
|
||||
|
||||
Hash_DelTable (s->shared);
|
||||
free (s);
|
||||
//Hash_DelTable (s->shared);
|
||||
//free (s);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -569,14 +574,15 @@ Scrobj_Method_f (gib_object_t *obj, gib_method_t *method, void *data,
|
|||
static hashtab_t *nhash = NULL;
|
||||
gib_var_t *var;
|
||||
|
||||
if (GIB_Function_Execute (thread, ((Scrobj_method_t *)method->data)->func,
|
||||
mesg.argv, mesg.argc))
|
||||
return -1;
|
||||
|
||||
GIB_DATA(thread)->dnotify = Scrobj_Thread_Died;
|
||||
GIB_DATA(thread)->reply.obj = obj;
|
||||
GIB_DATA(thread)->reply.method = method;
|
||||
GIB_DATA(thread)->reply.mesg = mesg;
|
||||
GIB_Function_Execute (thread, ((Scrobj_method_t *)method->data)->func,
|
||||
mesg.argv, mesg.argc);
|
||||
GIB_DATA(thread)->globals = ((Scrobj_t *)data)->shared;
|
||||
GIB_DATA(thread)->globals = obj->vars;
|
||||
var = GIB_Var_Get_Complex (&GIB_DATA(thread)->locals, &nhash, this,
|
||||
&ind, true);
|
||||
if (obj->handle)
|
||||
|
@ -633,16 +639,31 @@ GIB_Classes_Build_Scripted (const char *name, const char *parentname,
|
|||
case TREE_T_CMD:
|
||||
if (!strcmp (line->children->str,
|
||||
"function")) {
|
||||
gib_tree_t *cur, *last;
|
||||
gib_methodtab_t *new = malloc (sizeof
|
||||
(gib_methodtab_t));
|
||||
Scrobj_method_t *data = malloc (sizeof
|
||||
(Scrobj_method_t));
|
||||
for (last =
|
||||
line->children->next->next;
|
||||
last->next; last =
|
||||
last->next);
|
||||
data->func = GIB_Function_Define
|
||||
(fname
|
||||
(line->children->next->str),
|
||||
line->children->next->next->str,
|
||||
line->children->next->next->children,
|
||||
last->str,
|
||||
last->children,
|
||||
script, NULL);
|
||||
llist_flush (data->func->arglist);
|
||||
data->func->minargs = 1;
|
||||
for (cur = line->children->next->next;
|
||||
cur != last; cur =
|
||||
cur->next) {
|
||||
llist_append
|
||||
(data->func->arglist,
|
||||
strdup (cur->str));
|
||||
data->func->minargs++;
|
||||
}
|
||||
new->data = data;
|
||||
new->name = line->children->next->str;
|
||||
new->func = Scrobj_Method_f;
|
||||
|
|
|
@ -339,10 +339,15 @@ GIB_Execute (cbuf_t * cbuf)
|
|||
b->func ();
|
||||
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
|
||||
cbuf_t *new = Cbuf_PushStack (&gib_interp);
|
||||
GIB_Function_Execute_D (
|
||||
new, f,
|
||||
cbuf->args->argv, cbuf->args->argc
|
||||
);
|
||||
if (GIB_Function_Execute_D
|
||||
(new, f,
|
||||
cbuf->args->argv,
|
||||
cbuf->args->argc))
|
||||
GIB_Error ("syntax", "not "
|
||||
"enough "
|
||||
"arguments to "
|
||||
"function '%s'",
|
||||
cbuf->args->argv[0]->str);
|
||||
} else {
|
||||
GIB_Execute_Generate_Composite (cbuf);
|
||||
if (Cmd_Command (cbuf->args))
|
||||
|
|
|
@ -53,22 +53,6 @@ const char rcsid[] =
|
|||
|
||||
hashtab_t *gib_functions = 0;
|
||||
|
||||
/*
|
||||
GIB_Function_New
|
||||
|
||||
Builds a new function struct and returns
|
||||
a pointer to it.
|
||||
*/
|
||||
static gib_function_t *
|
||||
GIB_Function_New (const char *name)
|
||||
{
|
||||
gib_function_t *new = calloc (1, sizeof (gib_function_t));
|
||||
|
||||
new->text = dstring_newstr ();
|
||||
new->name = strdup (name);
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
Hashtable callbacks
|
||||
*/
|
||||
|
@ -95,6 +79,29 @@ GIB_Function_Free (void *ele, void *ptr)
|
|||
free (func);
|
||||
}
|
||||
|
||||
/*
|
||||
GIB_Function_New
|
||||
|
||||
Builds a new function struct and returns
|
||||
a pointer to it.
|
||||
*/
|
||||
static gib_function_t *
|
||||
GIB_Function_New (const char *name)
|
||||
{
|
||||
gib_function_t *new = calloc (1, sizeof (gib_function_t));
|
||||
|
||||
static void
|
||||
afree (void *data, void *unused)
|
||||
{
|
||||
free (data);
|
||||
};
|
||||
|
||||
new->text = dstring_newstr ();
|
||||
new->name = strdup (name);
|
||||
new->arglist = llist_new (afree, NULL, NULL);
|
||||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
GIB_Function_Define
|
||||
|
||||
|
@ -151,16 +158,32 @@ GIB_Function_Find (const char *name)
|
|||
return (gib_function_t *) Hash_Find (gib_functions, name);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int argc)
|
||||
static void
|
||||
GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int
|
||||
argc, llist_t *arglist)
|
||||
{
|
||||
static hashtab_t *zero = 0;
|
||||
unsigned int i;
|
||||
unsigned int i, ind;
|
||||
gib_var_t *var;
|
||||
static char argss[] = "args";
|
||||
|
||||
static qboolean
|
||||
iterate (char *arg, llist_node_t *node)
|
||||
{
|
||||
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero,
|
||||
arg, &ind, true);
|
||||
if (!var->array[0].value)
|
||||
var->array[0].value = dstring_newstr ();
|
||||
dstring_copystr (var->array[0].value, args[i]);
|
||||
i++;
|
||||
return i < argc;
|
||||
}
|
||||
|
||||
i = 1; llist_iterate (arglist, LLIST_ICAST (iterate));
|
||||
|
||||
var =
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true);
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss,
|
||||
&ind, true);
|
||||
var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc);
|
||||
memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
|
||||
var->size = argc;
|
||||
|
@ -173,16 +196,32 @@ GIB_Function_Prepare_Args (cbuf_t * cbuf, const char **args, unsigned int argc)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int argc)
|
||||
static void
|
||||
GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int
|
||||
argc, llist_t *arglist)
|
||||
{
|
||||
static hashtab_t *zero = 0;
|
||||
unsigned int i;
|
||||
unsigned int i, ind;
|
||||
gib_var_t *var;
|
||||
static char argss[] = "args";
|
||||
|
||||
static qboolean
|
||||
iterate (char *arg, llist_node_t *node)
|
||||
{
|
||||
var = GIB_Var_Get_Complex (&GIB_DATA(cbuf)->locals, &zero,
|
||||
arg, &ind, true);
|
||||
if (!var->array[0].value)
|
||||
var->array[0].value = dstring_newstr ();
|
||||
dstring_copystr (var->array[0].value, args[i]->str);
|
||||
i++;
|
||||
return i < argc;
|
||||
}
|
||||
|
||||
i = 1; llist_iterate (arglist, LLIST_ICAST (iterate));
|
||||
|
||||
var =
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss, &i, true);
|
||||
GIB_Var_Get_Complex (&GIB_DATA (cbuf)->locals, &zero, argss,
|
||||
&ind, true);
|
||||
var->array = realloc (var->array, sizeof (struct gib_varray_s) * argc);
|
||||
memset (var->array + 1, 0, (argc - 1) * sizeof (struct gib_varray_s));
|
||||
var->size = argc;
|
||||
|
@ -202,28 +241,34 @@ GIB_Function_Prepare_Args_D (cbuf_t * cbuf, dstring_t **args, unsigned int argc)
|
|||
a GIB function with certain arguments
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
GIB_Function_Execute (cbuf_t * cbuf, gib_function_t * func, const char ** args,
|
||||
unsigned int argc)
|
||||
{
|
||||
if (argc < func->minargs)
|
||||
return -1;
|
||||
GIB_Tree_Ref (&func->program);
|
||||
if (func->script)
|
||||
func->script->refs++;
|
||||
GIB_Buffer_Set_Program (cbuf, func->program);
|
||||
GIB_DATA (cbuf)->script = func->script;
|
||||
GIB_DATA (cbuf)->globals = func->globals;
|
||||
GIB_Function_Prepare_Args (cbuf, args, argc);
|
||||
GIB_Function_Prepare_Args (cbuf, args, argc, func->arglist);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
GIB_Function_Execute_D (cbuf_t * cbuf, gib_function_t * func, dstring_t ** args,
|
||||
unsigned int argc)
|
||||
{
|
||||
if (argc < func->minargs)
|
||||
return -1;
|
||||
GIB_Tree_Ref (&func->program);
|
||||
if (func->script)
|
||||
func->script->refs++;
|
||||
GIB_Buffer_Set_Program (cbuf, func->program);
|
||||
GIB_DATA (cbuf)->script = func->script;
|
||||
GIB_DATA (cbuf)->globals = func->globals;
|
||||
GIB_Function_Prepare_Args_D (cbuf, args, argc);
|
||||
GIB_Function_Prepare_Args_D (cbuf, args, argc, func->arglist);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -240,6 +240,8 @@ GIB_Object_Finish_Destroy (int argc, const char **argv, void *data)
|
|||
GIB_Handle_Free (obj->handle);
|
||||
free ((void *) obj->handstr);
|
||||
Hash_DelTable (obj->signals);
|
||||
if (obj->vars)
|
||||
Hash_DelTable (obj->vars);
|
||||
llist_delete (obj->slots);
|
||||
free (obj);
|
||||
}
|
||||
|
@ -316,9 +318,11 @@ void
|
|||
GIB_Reply (gib_object_t *obj, gib_message_t mesg, int argc, const char
|
||||
**argv)
|
||||
{
|
||||
if (mesg.reply) {
|
||||
mesg.reply (argc, argv, mesg.replydata);
|
||||
GIB_Object_Decref (obj);
|
||||
}
|
||||
}
|
||||
|
||||
gib_object_t *
|
||||
GIB_Object_Get (const char *id)
|
||||
|
|
|
@ -87,16 +87,22 @@ GIB_Semantic_Validate_Class (gib_tree_t * tokens)
|
|||
"function.",
|
||||
cmd->start);
|
||||
return -1;
|
||||
} else if (!cmd->next || !cmd->next->next ||
|
||||
cmd->next->next->delim != '{'
|
||||
|| !cmd->next->next->children) {
|
||||
} else {
|
||||
gib_tree_t *last;
|
||||
|
||||
for (last = cmd; last->next; last = last->next);
|
||||
|
||||
if (!cmd->next || !last || last->delim != '{' ||
|
||||
!last->children) {
|
||||
GIB_Parse_Error ("Malformed function "
|
||||
"definition; name, "
|
||||
"optional arg list, "
|
||||
"program block "
|
||||
"expected.",
|
||||
cmd->start);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GIB_Parse_Error ("Malformed class "
|
||||
|
|
|
@ -69,7 +69,7 @@ Carne_Execute_Script (const char *path, cbuf_args_t *args)
|
|||
goto ERROR;
|
||||
}
|
||||
|
||||
GIB_Function_Prepare_Args_D (mbuf, args->argv, args->argc);
|
||||
//GIB_Function_Prepare_Args_D (mbuf, args->argv, args->argc);
|
||||
|
||||
// Main loop
|
||||
while (1) {
|
||||
|
|
Loading…
Reference in a new issue