Local variables work, preparing to get embedded commands done.

This commit is contained in:
Brian Koropoff 2002-08-05 00:01:06 +00:00
parent 86d495491f
commit 87f0f480e4
9 changed files with 176 additions and 30 deletions

View file

@ -30,6 +30,10 @@
#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 {
struct dstring_s *arg_composite;
struct dstring_s *current_token;
@ -42,6 +46,8 @@ typedef struct gib_buffer_data_s {
struct dstring_s *retval; // Returned value
} ret;
struct hashtab_s *locals; // Local variables
enum {
GIB_BUFFER_NORMAL, // Normal buffer
GIB_BUFFER_LOOP, // Looping buffer
@ -49,5 +55,7 @@ typedef struct gib_buffer_data_s {
} type;
} 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_Destruct (struct cbuf_s *cbuf);

View file

@ -31,6 +31,11 @@
typedef struct gib_builtin_s {
struct dstring_s *name;
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;
void GIB_Builtin_Add (const char *name, void (*func) (void));

View file

@ -34,3 +34,4 @@ typedef struct gib_function_s {
void GIB_Function_Define (const char *name, const char *program);
gib_function_t *GIB_Function_Find (const char *name);
void GIB_Function_Execute (gib_function_t *func);

View file

@ -31,3 +31,4 @@
void GIB_Process_Variable (struct dstring_s *token);
void GIB_Process_Variables_All (struct dstring_s *token);
int GIB_Process_Math (struct dstring_s *token);
int GIB_Process_Token (struct dstring_s *token, char delim);

View file

@ -32,8 +32,61 @@
#include "QF/dstring.h"
#include "QF/cbuf.h"
#include "QF/hash.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)
{
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)
{
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);
}

View file

@ -36,6 +36,7 @@
#include "QF/hash.h"
#include "QF/dstring.h"
#include "QF/gib_builtin.h"
#include "QF/gib_buffer.h"
#include "QF/gib_function.h"
hashtab_t *gib_builtins;
@ -96,16 +97,28 @@ GIB_Argv (unsigned int arg)
void
GIB_Function_f (void)
{
if (GIB_Argc () != 3) {
if (GIB_Argc () != 3)
Cbuf_Error ("numargs",
"function: invalid number of arguments\n"
"usage: function function_name {program}");
} else
else
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
GIB_Builtin_Init (void)
{
GIB_Builtin_Add ("function", GIB_Function_f);
GIB_Builtin_Add ("lset", GIB_Lset_f);
}

View file

@ -32,7 +32,11 @@
#include "QF/dstring.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/va.h"
hashtab_t *gib_functions = 0;
@ -85,3 +89,21 @@ GIB_Function_Find (const char *name)
return 0;
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));
}

View file

@ -57,19 +57,19 @@ cbuf_interpreter_t gib_interp = {
/* Co-recursive parsing functions */
inline char
char
GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
{
for ((*i)++; str[*i]; (*i)++) {
if (str[*i] == '\n')
return '\"'; // Newlines should never occur inside quotes
return '\"'; // Newlines should never occur inside quotes, EVER
if (str[*i] == '\"')
return 0;
}
return '\"';
}
inline char
char
GIB_Parse_Match_Brace (const char *str, unsigned int *i)
{
char c;
@ -88,7 +88,7 @@ GIB_Parse_Match_Brace (const char *str, unsigned int *i)
return '{';
}
inline char
char
GIB_Parse_Match_Paren (const char *str, unsigned int *i)
{
char c;
@ -103,6 +103,27 @@ GIB_Parse_Match_Paren (const char *str, unsigned int *i)
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
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);
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] == ';')
break;
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 '\(';
}
} 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)++;
}
dstring_insert (dstr, 0, str+n, *i-n);
return ' ';
}
@ -233,7 +266,7 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
cbuf_args_t *args = cbuf->args;
static qboolean cat = false;
char delim;
int i;
int i = 0;
// This function can be interrupted to call a GIB
// subroutine. First we need to clean up anything
@ -252,7 +285,10 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
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
i++;
if (!str[i]) // Blank token
@ -267,19 +303,12 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
break;
Sys_DPrintf("Got token: %s\n", arg->str);
// Global filters -- command sub and var sub
// FIXME: Command sub goes here with subroutine handling
if (delim != '{' && delim != '\"')
GIB_Process_Variables_All (arg);
if (GIB_Process_Token (arg, delim))
goto FILTER_ERROR;
if (delim == '(')
if (GIB_Process_Math (arg))
goto FILTER_ERROR; // GOTO??!?!?!? AHHHH!
// Add token to list
GIB_Parse_Add_Token (args, cat, arg);
GIB_Parse_Add_Token (cbuf->args, cat, arg);
if (cat)
cat = false;
@ -303,13 +332,7 @@ void GIB_Parse_Execute_Line (cbuf_t *cbuf)
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
b->func ();
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
cbuf_t *sub = Cbuf_New (&gib_interp);
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;
GIB_Function_Execute (f);
} else
Cmd_Command (cbuf->args);
}

View file

@ -34,6 +34,7 @@
#include "QF/dstring.h"
#include "QF/cbuf.h"
#include "QF/cvar.h"
#include "QF/gib_buffer.h"
#include "exp.h"
@ -41,16 +42,20 @@ void
GIB_Process_Variable (struct dstring_s *dstr)
{
int i;
cvar_t *var;
cvar_t *cvar;
const char *str;
for (i = 0; dstr->str[i] == '$'; i++);
i--;
for (; i >= 0; i--) {
var = Cvar_FindVar (dstr->str+i+1);
if (!var)
if ((str = GIB_Local_Get (cbuf_active, dstr->str+i+1)))
; // yay for us
else if ((cvar = Cvar_FindVar (dstr->str+i+1)))
str = cvar->string;
else
return;
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;
}
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;
}