mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-18 06:51:47 +00:00
Local variables work, preparing to get embedded commands done.
This commit is contained in:
parent
86d495491f
commit
87f0f480e4
9 changed files with 176 additions and 30 deletions
|
@ -30,6 +30,10 @@
|
||||||
|
|
||||||
#define GIB_DATA(buffer) ((gib_buffer_data_t *)(buffer->data))
|
#define GIB_DATA(buffer) ((gib_buffer_data_t *)(buffer->data))
|
||||||
|
|
||||||
|
typedef struct gib_local_s {
|
||||||
|
struct dstring_s *key, *value;
|
||||||
|
} gib_local_t;
|
||||||
|
|
||||||
typedef struct gib_buffer_data_s {
|
typedef struct gib_buffer_data_s {
|
||||||
struct dstring_s *arg_composite;
|
struct dstring_s *arg_composite;
|
||||||
struct dstring_s *current_token;
|
struct dstring_s *current_token;
|
||||||
|
@ -42,6 +46,8 @@ typedef struct gib_buffer_data_s {
|
||||||
struct dstring_s *retval; // Returned value
|
struct dstring_s *retval; // Returned value
|
||||||
} ret;
|
} ret;
|
||||||
|
|
||||||
|
struct hashtab_s *locals; // Local variables
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
GIB_BUFFER_NORMAL, // Normal buffer
|
GIB_BUFFER_NORMAL, // Normal buffer
|
||||||
GIB_BUFFER_LOOP, // Looping buffer
|
GIB_BUFFER_LOOP, // Looping buffer
|
||||||
|
@ -49,5 +55,7 @@ typedef struct gib_buffer_data_s {
|
||||||
} type;
|
} type;
|
||||||
} gib_buffer_data_t;
|
} gib_buffer_data_t;
|
||||||
|
|
||||||
|
void GIB_Local_Set (cbuf_t *cbuf, const char *key, const char *value);
|
||||||
|
const char *GIB_Local_Get (cbuf_t *cbuf, const char *key);
|
||||||
void GIB_Buffer_Construct (struct cbuf_s *cbuf);
|
void GIB_Buffer_Construct (struct cbuf_s *cbuf);
|
||||||
void GIB_Buffer_Destruct (struct cbuf_s *cbuf);
|
void GIB_Buffer_Destruct (struct cbuf_s *cbuf);
|
||||||
|
|
|
@ -31,6 +31,11 @@
|
||||||
typedef struct gib_builtin_s {
|
typedef struct gib_builtin_s {
|
||||||
struct dstring_s *name;
|
struct dstring_s *name;
|
||||||
void (*func) (void);
|
void (*func) (void);
|
||||||
|
enum {
|
||||||
|
GIB_BUILTIN_NORMAL, // Normal argument processing
|
||||||
|
GIB_BUILTIN_NOPROCESS, // Don't process arguments
|
||||||
|
GIB_BUILTIN_FIRSTONLY, // Process only the first argument
|
||||||
|
} type;
|
||||||
} gib_builtin_t;
|
} gib_builtin_t;
|
||||||
|
|
||||||
void GIB_Builtin_Add (const char *name, void (*func) (void));
|
void GIB_Builtin_Add (const char *name, void (*func) (void));
|
||||||
|
|
|
@ -34,3 +34,4 @@ typedef struct gib_function_s {
|
||||||
|
|
||||||
void GIB_Function_Define (const char *name, const char *program);
|
void GIB_Function_Define (const char *name, const char *program);
|
||||||
gib_function_t *GIB_Function_Find (const char *name);
|
gib_function_t *GIB_Function_Find (const char *name);
|
||||||
|
void GIB_Function_Execute (gib_function_t *func);
|
||||||
|
|
|
@ -31,3 +31,4 @@
|
||||||
void GIB_Process_Variable (struct dstring_s *token);
|
void GIB_Process_Variable (struct dstring_s *token);
|
||||||
void GIB_Process_Variables_All (struct dstring_s *token);
|
void GIB_Process_Variables_All (struct dstring_s *token);
|
||||||
int GIB_Process_Math (struct dstring_s *token);
|
int GIB_Process_Math (struct dstring_s *token);
|
||||||
|
int GIB_Process_Token (struct dstring_s *token, char delim);
|
||||||
|
|
|
@ -32,8 +32,61 @@
|
||||||
|
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
#include "QF/cbuf.h"
|
#include "QF/cbuf.h"
|
||||||
|
#include "QF/hash.h"
|
||||||
#include "QF/gib_buffer.h"
|
#include "QF/gib_buffer.h"
|
||||||
|
|
||||||
|
gib_local_t *
|
||||||
|
GIB_Local_New (void)
|
||||||
|
{
|
||||||
|
gib_local_t *new = calloc (1, sizeof (gib_local_t));
|
||||||
|
new->key = dstring_newstr();
|
||||||
|
new->value = dstring_newstr();
|
||||||
|
|
||||||
|
return new;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
GIB_Local_Get_Key (void *ele, void *ptr)
|
||||||
|
{
|
||||||
|
return ((gib_local_t *)ele)->key->str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Local_Free (void *ele, void *ptr)
|
||||||
|
{
|
||||||
|
gib_local_t *l = (gib_local_t *)ele;
|
||||||
|
dstring_delete (l->key);
|
||||||
|
dstring_delete (l->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Local_Set (cbuf_t *cbuf, const char *key, const char *value)
|
||||||
|
{
|
||||||
|
gib_local_t *l;
|
||||||
|
if (!GIB_DATA(cbuf)->locals)
|
||||||
|
GIB_DATA(cbuf)->locals = Hash_NewTable (256, GIB_Local_Get_Key, GIB_Local_Free, 0);
|
||||||
|
if ((l = Hash_Find (GIB_DATA(cbuf)->locals, key)))
|
||||||
|
dstring_clearstr (l->value);
|
||||||
|
else {
|
||||||
|
l = GIB_Local_New ();
|
||||||
|
dstring_appendstr (l->key, key);
|
||||||
|
Hash_Add (GIB_DATA(cbuf)->locals, l);
|
||||||
|
}
|
||||||
|
dstring_appendstr (l->value, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
GIB_Local_Get (cbuf_t *cbuf, const char *key)
|
||||||
|
{
|
||||||
|
gib_local_t *l;
|
||||||
|
|
||||||
|
if (!GIB_DATA(cbuf)->locals)
|
||||||
|
return 0;
|
||||||
|
if (!(l = Hash_Find (GIB_DATA(cbuf)->locals, key)))
|
||||||
|
return 0;
|
||||||
|
return l->value->str;
|
||||||
|
}
|
||||||
|
|
||||||
void GIB_Buffer_Construct (struct cbuf_s *cbuf)
|
void GIB_Buffer_Construct (struct cbuf_s *cbuf)
|
||||||
{
|
{
|
||||||
cbuf->data = calloc (1, sizeof (gib_buffer_data_t));
|
cbuf->data = calloc (1, sizeof (gib_buffer_data_t));
|
||||||
|
@ -44,5 +97,8 @@ void GIB_Buffer_Construct (struct cbuf_s *cbuf)
|
||||||
void GIB_Buffer_Destruct (struct cbuf_s *cbuf)
|
void GIB_Buffer_Destruct (struct cbuf_s *cbuf)
|
||||||
{
|
{
|
||||||
dstring_delete (GIB_DATA (cbuf)->arg_composite);
|
dstring_delete (GIB_DATA (cbuf)->arg_composite);
|
||||||
|
dstring_delete (GIB_DATA (cbuf)->current_token);
|
||||||
|
if (GIB_DATA(cbuf)->locals)
|
||||||
|
Hash_DelTable (GIB_DATA(cbuf)->locals);
|
||||||
free (cbuf->data);
|
free (cbuf->data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
#include "QF/gib_builtin.h"
|
#include "QF/gib_builtin.h"
|
||||||
|
#include "QF/gib_buffer.h"
|
||||||
#include "QF/gib_function.h"
|
#include "QF/gib_function.h"
|
||||||
|
|
||||||
hashtab_t *gib_builtins;
|
hashtab_t *gib_builtins;
|
||||||
|
@ -96,16 +97,28 @@ GIB_Argv (unsigned int arg)
|
||||||
void
|
void
|
||||||
GIB_Function_f (void)
|
GIB_Function_f (void)
|
||||||
{
|
{
|
||||||
if (GIB_Argc () != 3) {
|
if (GIB_Argc () != 3)
|
||||||
Cbuf_Error ("numargs",
|
Cbuf_Error ("numargs",
|
||||||
"function: invalid number of arguments\n"
|
"function: invalid number of arguments\n"
|
||||||
"usage: function function_name {program}");
|
"usage: function function_name {program}");
|
||||||
} else
|
else
|
||||||
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2));
|
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Lset_f (void)
|
||||||
|
{
|
||||||
|
if (GIB_Argc () != 3)
|
||||||
|
Cbuf_Error ("numargs",
|
||||||
|
"lset: invalid number of arguments\n"
|
||||||
|
"usage: lset variable value");
|
||||||
|
else
|
||||||
|
GIB_Local_Set (cbuf_active, GIB_Argv(1), GIB_Argv(2));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GIB_Builtin_Init (void)
|
GIB_Builtin_Init (void)
|
||||||
{
|
{
|
||||||
GIB_Builtin_Add ("function", GIB_Function_f);
|
GIB_Builtin_Add ("function", GIB_Function_f);
|
||||||
|
GIB_Builtin_Add ("lset", GIB_Lset_f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,11 @@
|
||||||
|
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
|
#include "QF/cbuf.h"
|
||||||
|
#include "QF/gib_parse.h"
|
||||||
|
#include "QF/gib_buffer.h"
|
||||||
#include "QF/gib_function.h"
|
#include "QF/gib_function.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
|
||||||
hashtab_t *gib_functions = 0;
|
hashtab_t *gib_functions = 0;
|
||||||
|
|
||||||
|
@ -85,3 +89,21 @@ GIB_Function_Find (const char *name)
|
||||||
return 0;
|
return 0;
|
||||||
return (gib_function_t *) Hash_Find (gib_functions, name);
|
return (gib_function_t *) Hash_Find (gib_functions, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Function_Execute (gib_function_t *func)
|
||||||
|
{
|
||||||
|
cbuf_t *sub = Cbuf_New (&gib_interp);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
Cbuf_AddText (sub, func->program->str);
|
||||||
|
if (cbuf_active->down)
|
||||||
|
Cbuf_DeleteStack (cbuf_active->down);
|
||||||
|
cbuf_active->down = sub;
|
||||||
|
sub->up = cbuf_active;
|
||||||
|
cbuf_active->state = CBUF_STATE_STACK;
|
||||||
|
|
||||||
|
for (i = 0; i < cbuf_active->args->argc; i++)
|
||||||
|
GIB_Local_Set (sub, va("%i", i), cbuf_active->args->argv[i]->str);
|
||||||
|
GIB_Local_Set (sub, "argc", va("%i", cbuf_active->args->argc));
|
||||||
|
}
|
||||||
|
|
|
@ -57,19 +57,19 @@ cbuf_interpreter_t gib_interp = {
|
||||||
|
|
||||||
/* Co-recursive parsing functions */
|
/* Co-recursive parsing functions */
|
||||||
|
|
||||||
inline char
|
char
|
||||||
GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
|
GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
|
||||||
{
|
{
|
||||||
for ((*i)++; str[*i]; (*i)++) {
|
for ((*i)++; str[*i]; (*i)++) {
|
||||||
if (str[*i] == '\n')
|
if (str[*i] == '\n')
|
||||||
return '\"'; // Newlines should never occur inside quotes
|
return '\"'; // Newlines should never occur inside quotes, EVER
|
||||||
if (str[*i] == '\"')
|
if (str[*i] == '\"')
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return '\"';
|
return '\"';
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char
|
char
|
||||||
GIB_Parse_Match_Brace (const char *str, unsigned int *i)
|
GIB_Parse_Match_Brace (const char *str, unsigned int *i)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
@ -88,7 +88,7 @@ GIB_Parse_Match_Brace (const char *str, unsigned int *i)
|
||||||
return '{';
|
return '{';
|
||||||
}
|
}
|
||||||
|
|
||||||
inline char
|
char
|
||||||
GIB_Parse_Match_Paren (const char *str, unsigned int *i)
|
GIB_Parse_Match_Paren (const char *str, unsigned int *i)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
@ -103,6 +103,27 @@ GIB_Parse_Match_Paren (const char *str, unsigned int *i)
|
||||||
return '(';
|
return '(';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char
|
||||||
|
GIB_Parse_Match_Angle (const char *str, unsigned int *i)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
for ((*i)++; str[*i]; (*i)++) {
|
||||||
|
if (str[*i] == '>')
|
||||||
|
return 0;
|
||||||
|
else if (str[*i] == '<') {
|
||||||
|
if ((c = GIB_Parse_Match_Angle (str, i))) // Embedded inside embedded
|
||||||
|
return c;
|
||||||
|
} else if (str[*i] == '(') { // Skip over math expressions to avoid < and >
|
||||||
|
if ((c = GIB_Parse_Match_Paren (str, i)))
|
||||||
|
return c;
|
||||||
|
} else if (str[*i] == '\"') { // Skip over strings
|
||||||
|
if ((c = GIB_Parse_Match_Dquote (str, i)))
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '<';
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
||||||
{
|
{
|
||||||
|
@ -127,6 +148,11 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (dstr->str[i] == '<') {
|
||||||
|
if ((c = GIB_Parse_Match_Angle (dstr->str, &i))) {
|
||||||
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
|
return;
|
||||||
|
}
|
||||||
} else if (dstr->str[i] == '\n' || dstr->str[i] == ';')
|
} else if (dstr->str[i] == '\n' || dstr->str[i] == ';')
|
||||||
break;
|
break;
|
||||||
else if (dstr->str[i] == '/' && dstr->str[i+1] == '/') {
|
else if (dstr->str[i] == '/' && dstr->str[i+1] == '/') {
|
||||||
|
@ -184,8 +210,15 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr)
|
||||||
return '\(';
|
return '\(';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
while (str[*i] && !isspace(str[*i]) && str[*i] != ',') // find end of token
|
while (str[*i] && !isspace(str[*i]) && str[*i] != ',') { // find end of token
|
||||||
|
if (str[*i] == '<') {
|
||||||
|
if ((c = GIB_Parse_Match_Angle (str, i))) {
|
||||||
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
|
return 0; // Parse error
|
||||||
|
}
|
||||||
|
}
|
||||||
(*i)++;
|
(*i)++;
|
||||||
|
}
|
||||||
dstring_insert (dstr, 0, str+n, *i-n);
|
dstring_insert (dstr, 0, str+n, *i-n);
|
||||||
return ' ';
|
return ' ';
|
||||||
}
|
}
|
||||||
|
@ -233,7 +266,7 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||||
cbuf_args_t *args = cbuf->args;
|
cbuf_args_t *args = cbuf->args;
|
||||||
static qboolean cat = false;
|
static qboolean cat = false;
|
||||||
char delim;
|
char delim;
|
||||||
int i;
|
int i = 0;
|
||||||
|
|
||||||
// This function can be interrupted to call a GIB
|
// This function can be interrupted to call a GIB
|
||||||
// subroutine. First we need to clean up anything
|
// subroutine. First we need to clean up anything
|
||||||
|
@ -252,7 +285,10 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||||
cat = false;
|
cat = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; str[i];) {
|
// Get just the first token so we can look up any
|
||||||
|
// parsing options that a builtin requests
|
||||||
|
|
||||||
|
while (str[i]) {
|
||||||
while (isspace(str[i])) // Eliminate whitespace
|
while (isspace(str[i])) // Eliminate whitespace
|
||||||
i++;
|
i++;
|
||||||
if (!str[i]) // Blank token
|
if (!str[i]) // Blank token
|
||||||
|
@ -267,19 +303,12 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||||
break;
|
break;
|
||||||
Sys_DPrintf("Got token: %s\n", arg->str);
|
Sys_DPrintf("Got token: %s\n", arg->str);
|
||||||
|
|
||||||
// Global filters -- command sub and var sub
|
|
||||||
|
|
||||||
// FIXME: Command sub goes here with subroutine handling
|
// FIXME: Command sub goes here with subroutine handling
|
||||||
|
|
||||||
if (delim != '{' && delim != '\"')
|
if (GIB_Process_Token (arg, delim))
|
||||||
GIB_Process_Variables_All (arg);
|
goto FILTER_ERROR;
|
||||||
|
|
||||||
if (delim == '(')
|
GIB_Parse_Add_Token (cbuf->args, cat, arg);
|
||||||
if (GIB_Process_Math (arg))
|
|
||||||
goto FILTER_ERROR; // GOTO??!?!?!? AHHHH!
|
|
||||||
|
|
||||||
// Add token to list
|
|
||||||
GIB_Parse_Add_Token (args, cat, arg);
|
|
||||||
if (cat)
|
if (cat)
|
||||||
cat = false;
|
cat = false;
|
||||||
|
|
||||||
|
@ -303,13 +332,7 @@ void GIB_Parse_Execute_Line (cbuf_t *cbuf)
|
||||||
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
|
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
|
||||||
b->func ();
|
b->func ();
|
||||||
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
|
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
|
||||||
cbuf_t *sub = Cbuf_New (&gib_interp);
|
GIB_Function_Execute (f);
|
||||||
Cbuf_AddText (sub, f->program->str);
|
|
||||||
if (cbuf_active->down)
|
|
||||||
Cbuf_DeleteStack (cbuf_active->down);
|
|
||||||
cbuf_active->down = sub;
|
|
||||||
sub->up = cbuf_active;
|
|
||||||
cbuf_active->state = CBUF_STATE_STACK;
|
|
||||||
} else
|
} else
|
||||||
Cmd_Command (cbuf->args);
|
Cmd_Command (cbuf->args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
#include "QF/cbuf.h"
|
#include "QF/cbuf.h"
|
||||||
#include "QF/cvar.h"
|
#include "QF/cvar.h"
|
||||||
|
#include "QF/gib_buffer.h"
|
||||||
|
|
||||||
#include "exp.h"
|
#include "exp.h"
|
||||||
|
|
||||||
|
@ -41,16 +42,20 @@ void
|
||||||
GIB_Process_Variable (struct dstring_s *dstr)
|
GIB_Process_Variable (struct dstring_s *dstr)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
cvar_t *var;
|
cvar_t *cvar;
|
||||||
|
const char *str;
|
||||||
|
|
||||||
for (i = 0; dstr->str[i] == '$'; i++);
|
for (i = 0; dstr->str[i] == '$'; i++);
|
||||||
i--;
|
i--;
|
||||||
for (; i >= 0; i--) {
|
for (; i >= 0; i--) {
|
||||||
var = Cvar_FindVar (dstr->str+i+1);
|
if ((str = GIB_Local_Get (cbuf_active, dstr->str+i+1)))
|
||||||
if (!var)
|
; // yay for us
|
||||||
|
else if ((cvar = Cvar_FindVar (dstr->str+i+1)))
|
||||||
|
str = cvar->string;
|
||||||
|
else
|
||||||
return;
|
return;
|
||||||
dstr->str[i] = 0;
|
dstr->str[i] = 0;
|
||||||
dstring_appendstr (dstr, var->string);
|
dstring_appendstr (dstr, str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,3 +94,15 @@ GIB_Process_Math (struct dstring_s *token)
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
GIB_Process_Token (struct dstring_s *token, char delim)
|
||||||
|
{
|
||||||
|
if (delim != '{' && delim != '\"')
|
||||||
|
GIB_Process_Variables_All (token);
|
||||||
|
|
||||||
|
if (delim == '(')
|
||||||
|
if (GIB_Process_Math (token))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue