Added tree variables (blah.1, blah.2, blah.1.foobar, etc), global variables,

made var substitution more robust, and began adding proper comments to
the code.
This commit is contained in:
Brian Koropoff 2002-08-08 09:20:00 +00:00
parent 30012cc753
commit 0390fe22ce
15 changed files with 466 additions and 109 deletions

View file

@ -3,7 +3,7 @@ SUBDIRS = GL plugin
includedir = $(prefix)/include/QF includedir = $(prefix)/include/QF
include_HEADERS = bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ include_HEADERS = bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \
console.h crc.h csqc.h cvar.h dstring.h draw.h gcc_attr.h gib_buffer.h \ console.h crc.h csqc.h cvar.h dstring.h draw.h gcc_attr.h gib_buffer.h \
gib_builtin.h gib_function.h gib_parse.h gib_process.h hash.h hl.h \ gib_builtin.h gib_function.h gib_parse.h gib_process.h gib_vars.h hash.h hl.h \
idparse.h in_event.h info.h input.h joystick.h keys.h link.h locs.h \ idparse.h in_event.h info.h input.h joystick.h keys.h link.h locs.h \
mathlib.h mdfour.h model.h modelgen.h msg.h pak.h pakfile.h pcx.h \ mathlib.h mdfour.h model.h modelgen.h msg.h pak.h pakfile.h pcx.h \
plugin.h pr_comp.h pr_debug.h pr_obj.h progs.h qargs.h qdefs.h qendian.h \ plugin.h pr_comp.h pr_debug.h pr_obj.h progs.h qargs.h qdefs.h qendian.h \

View file

@ -25,15 +25,12 @@
Free Software Foundation, Inc. Free Software Foundation, Inc.
59 Temple Place - Suite 330 59 Temple Place - Suite 330
Boston, MA 02111-1307, USA Boston, MA 02111-1307, USA
$Id$
*/ */
#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;
@ -62,7 +59,6 @@ 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);

View file

@ -26,6 +26,7 @@
59 Temple Place - Suite 330 59 Temple Place - Suite 330
Boston, MA 02111-1307, USA Boston, MA 02111-1307, USA
$Id$
*/ */
typedef struct gib_builtin_s { typedef struct gib_builtin_s {

View file

@ -26,6 +26,7 @@
59 Temple Place - Suite 330 59 Temple Place - Suite 330
Boston, MA 02111-1307, USA Boston, MA 02111-1307, USA
$Id$
*/ */
typedef struct gib_function_s { typedef struct gib_function_s {

View file

@ -26,8 +26,10 @@
59 Temple Place - Suite 330 59 Temple Place - Suite 330
Boston, MA 02111-1307, USA Boston, MA 02111-1307, USA
$Id$
*/ */
char GIB_Parse_Match_Brace (const char *str, unsigned int *i);
char GIB_Parse_Match_Backtick (const char *str, unsigned int *i); char GIB_Parse_Match_Backtick (const char *str, unsigned int *i);
void GIB_Parse_Extract_Line (struct cbuf_s *cbuf); void GIB_Parse_Extract_Line (struct cbuf_s *cbuf);

View file

@ -26,6 +26,7 @@
59 Temple Place - Suite 330 59 Temple Place - Suite 330
Boston, MA 02111-1307, USA Boston, MA 02111-1307, USA
$Id$
*/ */
void GIB_Process_Variable (struct dstring_s *token); void GIB_Process_Variable (struct dstring_s *token);

47
include/QF/gib_vars.h Normal file
View file

@ -0,0 +1,47 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2002 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#include "QF/hash.h"
#include "QF/cbuf.h"
extern hashtab_t *gib_globals;
typedef struct gib_var_s {
struct dstring_s *key, *value;
struct hashtab_s *subvars;
} gib_var_t;
void GIB_Var_Set (cbuf_t *cbuf, const char *key, const char *value);
const char *GIB_Var_Get (cbuf_t *cbuf, const char *key);
const char *GIB_Var_Get_Key (void *ele, void *ptr);
void GIB_Var_Free (void *ele, void *ptr);
void GIB_Var_Set_R (hashtab_t *vars, char *name, const char *value);
gib_var_t *GIB_Var_Get_R (hashtab_t *vars, char *name);

View file

@ -28,8 +28,9 @@ libQFutil_la_DEPENDENCIES= libasm.la
libQFutil_la_SOURCES= \ libQFutil_la_SOURCES= \
buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c exp.c fendian.c \ buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c exp.c fendian.c \
getopt.c getopt1.c gib_buffer.c gib_builtin.c gib_function.c gib_parse.c \ getopt.c getopt1.c gib_buffer.c gib_builtin.c gib_function.c gib_parse.c \
gib_process.c hash.c idparse.c info.c link.c mathlib.c mdfour.c msg.c ops.c \ gib_process.c gib_vars.c hash.c idparse.c info.c link.c mathlib.c mdfour.c \
pakfile.c pcx.c plugin.c qargs.c qendian.c qfplist.c quakefs.c quakeio.c \ msg.c ops.c pakfile.c pcx.c plugin.c qargs.c qendian.c qfplist.c quakefs.c \
sizebuf.c string.c sys.c tga.c va.c ver_check.c wad.c zone.c $(fnmatch) quakeio.c sizebuf.c string.c sys.c tga.c va.c ver_check.c wad.c zone.c \
$(fnmatch)
EXTRA_DIST= $(asm_src) $(fnmatch_src) EXTRA_DIST= $(asm_src) $(fnmatch_src)

View file

@ -28,65 +28,21 @@
*/ */
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/cbuf.h" #include "QF/cbuf.h"
#include "QF/hash.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));

View file

@ -28,6 +28,13 @@
*/ */
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -41,6 +48,7 @@
#include "QF/gib_builtin.h" #include "QF/gib_builtin.h"
#include "QF/gib_buffer.h" #include "QF/gib_buffer.h"
#include "QF/gib_function.h" #include "QF/gib_function.h"
#include "QF/gib_vars.h"
hashtab_t *gib_builtins; hashtab_t *gib_builtins;
@ -129,14 +137,30 @@ GIB_Function_f (void)
} }
void void
GIB_Lset_f (void) GIB_Local_f (void)
{ {
if (GIB_Argc () != 3) if (GIB_Argc () != 2)
Cbuf_Error ("syntax", Cbuf_Error ("syntax",
"lset: invalid syntax\n" "lset: invalid syntax\n"
"usage: lset variable value"); "usage: local variable");
else else
GIB_Local_Set (cbuf_active, GIB_Argv(1), GIB_Argv(2)); GIB_Var_Set (cbuf_active, GIB_Argv(1), "");
}
void
GIB_Global_f (void)
{
if (GIB_Argc () != 2)
Cbuf_Error ("syntax",
"global: invalid syntax\n"
"usage: global variable");
else {
char *a = strdup (GIB_Argv(1));
if (!gib_globals)
gib_globals = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
GIB_Var_Set_R (gib_globals, a, "");
free(a);
}
} }
void void
@ -268,7 +292,8 @@ GIB_Builtin_Init (void)
{ {
GIB_Builtin_Add ("function", GIB_Function_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("function", GIB_Function_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("export", GIB_Export_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("export", GIB_Export_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("lset", GIB_Lset_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("local", GIB_Local_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("global", GIB_Global_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("return", GIB_Return_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("return", GIB_Return_f, GIB_BUILTIN_NORMAL);
GIB_Builtin_Add ("if", GIB_If_f, GIB_BUILTIN_FIRSTONLY); GIB_Builtin_Add ("if", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
GIB_Builtin_Add ("ifnot", GIB_If_f, GIB_BUILTIN_FIRSTONLY); GIB_Builtin_Add ("ifnot", GIB_If_f, GIB_BUILTIN_FIRSTONLY);

View file

@ -28,6 +28,13 @@
*/ */
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h> #include <stdlib.h>
#include "QF/dstring.h" #include "QF/dstring.h"
@ -36,10 +43,17 @@
#include "QF/gib_parse.h" #include "QF/gib_parse.h"
#include "QF/gib_buffer.h" #include "QF/gib_buffer.h"
#include "QF/gib_function.h" #include "QF/gib_function.h"
#include "QF/gib_vars.h"
#include "QF/va.h" #include "QF/va.h"
hashtab_t *gib_functions = 0; hashtab_t *gib_functions = 0;
/*
GIB_Function_New
Builds a new function struct and returns
a pointer to it.
*/
gib_function_t * gib_function_t *
GIB_Function_New (void) GIB_Function_New (void)
{ {
@ -50,12 +64,14 @@ GIB_Function_New (void)
return new; return new;
} }
/*
Hashtable callbacks
*/
const char * const char *
GIB_Function_Get_Key (void *ele, void *ptr) GIB_Function_Get_Key (void *ele, void *ptr)
{ {
return ((gib_function_t *)ele)->name->str; return ((gib_function_t *)ele)->name->str;
} }
void void
GIB_Function_Free (void *ele, void *ptr) GIB_Function_Free (void *ele, void *ptr)
{ {
@ -64,6 +80,13 @@ GIB_Function_Free (void *ele, void *ptr)
dstring_delete (func->program); dstring_delete (func->program);
} }
/*
GIB_Function_Define
Sets the program text of a GIB function,
allocating one and adding it to the functions
hash if needed.
*/
void void
GIB_Function_Define (const char *name, const char *program) GIB_Function_Define (const char *name, const char *program)
{ {
@ -82,6 +105,13 @@ GIB_Function_Define (const char *name, const char *program)
dstring_appendstr (func->program, program); dstring_appendstr (func->program, program);
} }
/*
GIB_Function_Find
Looks up a function in the function hash
and returns a pointer to it on success,
0 otherwise
*/
gib_function_t * gib_function_t *
GIB_Function_Find (const char *name) GIB_Function_Find (const char *name)
{ {
@ -90,6 +120,15 @@ GIB_Function_Find (const char *name)
return (gib_function_t *) Hash_Find (gib_functions, name); return (gib_function_t *) Hash_Find (gib_functions, name);
} }
/*
GIB_Function_Execute
Creates a new buffer on the current stack
and copies the program text of a function
into it. Also sets local variables on the
buffer for all arguments passed to the
function
*/
void void
GIB_Function_Execute (gib_function_t *func) GIB_Function_Execute (gib_function_t *func)
{ {
@ -104,6 +143,6 @@ GIB_Function_Execute (gib_function_t *func)
cbuf_active->state = CBUF_STATE_STACK; cbuf_active->state = CBUF_STATE_STACK;
for (i = 0; i < cbuf_active->args->argc; i++) for (i = 0; i < cbuf_active->args->argc; i++)
GIB_Local_Set (sub, va("%i", i), cbuf_active->args->argv[i]->str); GIB_Var_Set (sub, va("%i", i), cbuf_active->args->argv[i]->str);
GIB_Local_Set (sub, "argc", va("%i", cbuf_active->args->argc)); GIB_Var_Set (sub, "argc", va("%i", cbuf_active->args->argc));
} }

View file

@ -1,11 +1,11 @@
/* /*
#FILENAME# gib_parse.c
#DESCRIPTION# GIB parser functions
Copyright (C) 2002 #AUTHOR# Copyright (C) 2002 Brian Koropoff
Author: #AUTHOR# Author: Brian Koropoff
Date: #DATE# Date: #DATE#
This program is free software; you can redistribute it and/or This program is free software; you can redistribute it and/or
@ -28,6 +28,13 @@
*/ */
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
@ -39,6 +46,7 @@
#include "QF/gib_process.h" #include "QF/gib_process.h"
#include "QF/gib_builtin.h" #include "QF/gib_builtin.h"
#include "QF/gib_function.h" #include "QF/gib_function.h"
#include "QF/gib_vars.h"
// Interpreter structure and prototypes // Interpreter structure and prototypes
@ -55,8 +63,14 @@ cbuf_interpreter_t gib_interp = {
}; };
/* Co-recursive parsing functions */ /*
GIB_Parse_Match_Dquote
Progresses an index variable through a string
until a double quote is reached. Returns
0 on success, or the character it could not
match otherwise
*/
char char
GIB_Parse_Match_Dquote (const char *str, unsigned int *i) GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
{ {
@ -69,6 +83,16 @@ GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
return '\"'; return '\"';
} }
/*
GIB_Parse_Match_Brace
Progresses an index variable through a string
until a closing brace (}) is reached. Calls
other matching functions to skip areas of a
string it does not want to handle. Returns
0 on success, or the character it could not
match otherwise.
*/
char char
GIB_Parse_Match_Brace (const char *str, unsigned int *i) GIB_Parse_Match_Brace (const char *str, unsigned int *i)
{ {
@ -86,6 +110,16 @@ GIB_Parse_Match_Brace (const char *str, unsigned int *i)
return '{'; return '{';
} }
/*
GIB_Parse_Match_Paren
Progresses an index variable through a string
until a closing parenthesis is reached. Calls
other matching functions to skip areas of a
string it does not want to handle. Returns
0 on success, or the character it could not
match otherwise.
*/
char char
GIB_Parse_Match_Paren (const char *str, unsigned int *i) GIB_Parse_Match_Paren (const char *str, unsigned int *i)
{ {
@ -102,6 +136,16 @@ GIB_Parse_Match_Paren (const char *str, unsigned int *i)
return '('; return '(';
} }
/*
GIB_Parse_Match_Backtick
Progresses an index variable through a string
until a backtick (`) is reached. Calls
other matching functions to skip areas of a
string it does not want to handle. Returns
0 on success, or the character it could not
match otherwise.
*/
char char
GIB_Parse_Match_Backtick (const char *str, unsigned int *i) GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
{ {
@ -109,7 +153,7 @@ GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
for ((*i)++; str[*i]; (*i)++) { for ((*i)++; str[*i]; (*i)++) {
if (str[*i] == '`') if (str[*i] == '`')
return 0; return 0;
else if (str[*i] == '\"') { // Skip over strings else if (str[*i] == '\"') { // Skip over strings as usual
if ((c = GIB_Parse_Match_Dquote (str, i))) if ((c = GIB_Parse_Match_Dquote (str, i)))
return c; return c;
} }
@ -117,6 +161,13 @@ GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
return '`'; return '`';
} }
/*
GIB_Parse_Extract_Line
Extracts the next command from a cbuf and
deposits it in cbuf->line, removing the
portion used from the buffer
*/
void void
GIB_Parse_Extract_Line (struct cbuf_s *cbuf) GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
{ {
@ -129,7 +180,6 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
dstring_clearstr (cbuf->line); dstring_clearstr (cbuf->line);
for (i = 0; dstr->str[i]; i++) { for (i = 0; dstr->str[i]; i++) {
if (dstr->str[i] == '{') { if (dstr->str[i] == '{') {
if ((c = GIB_Parse_Match_Brace (dstr->str, &i))) { if ((c = GIB_Parse_Match_Brace (dstr->str, &i))) {
@ -149,19 +199,22 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
dstring_snip (dstr, i, n-dstr->str); dstring_snip (dstr, i, n-dstr->str);
else { else {
dstring_snip (dstr, i, strlen(dstr->str+i)); dstring_snip (dstr, i, strlen(dstr->str+i));
i--; // So we don't go past null break;
} }
} }
} }
if (dstr->str[0]) { if (dstr->str[0]) { // If something is left in the buffer
if (i) { if (i) { // If we used any of it
dstring_insert (cbuf->line, 0, dstr->str, i); dstring_insert (cbuf->line, 0, dstr->str, i);
Sys_DPrintf ("extracted line: %s\n", cbuf->line->str); Sys_DPrintf ("extracted line: %s\n", cbuf->line->str);
} }
// Clip out what we used or any leftover newlines or ;s
dstring_snip (dstr, 0, i + (dstr->str[i] == '\n' || dstr->str[i] == ';')); dstring_snip (dstr, 0, i + (dstr->str[i] == '\n' || dstr->str[i] == ';'));
} }
// If this is a looping buffer and it is now empty
// copy the loop program back in
if (GIB_DATA(cbuf)->type == GIB_BUFFER_LOOP && !dstr->str[0]) if (GIB_DATA(cbuf)->type == GIB_BUFFER_LOOP && !dstr->str[0])
Cbuf_AddText (cbuf, GIB_DATA(cbuf)->loop_program->str); Cbuf_AddText (cbuf, GIB_DATA(cbuf)->loop_program->str);
@ -169,6 +222,16 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
} }
/*
GIB_Parse_Get_Token
Progresses an index variable through a string
until the end of the next token is found.
Stores the token in dstr with or without
wrapping characters as specified by include_delim.
Returns 0 on error or the wrapping character of
the token otherwise
*/
inline static char inline static char
GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr, qboolean include_delim) GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr, qboolean include_delim)
{ {
@ -208,6 +271,12 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr, qboolean
return 0; // Parse error return 0; // Parse error
} }
} }
if (str[*i] == '{') {
if ((c = GIB_Parse_Match_Brace (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);
@ -216,6 +285,14 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr, qboolean
return 0; // We should never get here return 0; // We should never get here
} }
/*
GIB_Parse_Generate_Composite
Concatenates all parsed arguments in cbuf
into a single string and creates an array
of pointers to the beginnings of tokens
within it.
*/
void void
GIB_Parse_Generate_Composite (struct cbuf_s *cbuf) GIB_Parse_Generate_Composite (struct cbuf_s *cbuf)
{ {
@ -240,6 +317,13 @@ GIB_Parse_Generate_Composite (struct cbuf_s *cbuf)
args->args[i] += (unsigned long int) GIB_DATA (cbuf)->arg_composite->str; args->args[i] += (unsigned long int) GIB_DATA (cbuf)->arg_composite->str;
} }
/*
GIB_Parse_Add_Token
Adds a new token to the argument list args
or concatenates it to the end of the last
according to cat.
*/
inline void inline void
GIB_Parse_Add_Token (struct cbuf_args_s *args, qboolean cat, dstring_t *token) GIB_Parse_Add_Token (struct cbuf_args_s *args, qboolean cat, dstring_t *token)
{ {
@ -249,6 +333,16 @@ GIB_Parse_Add_Token (struct cbuf_args_s *args, qboolean cat, dstring_t *token)
Cbuf_ArgsAdd (args, token->str); Cbuf_ArgsAdd (args, token->str);
} }
/*
GIB_Parse_Tokenize_Line
Tokenizes and processes an extracted command,
producing an argument list suitable for executing
the command. This function can be interrupted
to call a GIB subroutine, in which case it will
save important variables and start where it left
off when called again.
*/
void void
GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf) GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
{ {
@ -324,6 +418,18 @@ FILTER_ERROR:
return; return;
} }
/*
GIB_Parse_Execute_Line
After an argument list has been created,
this function executes the appropriate command,
searching in this order:
GIB builtins
GIB functions
Assignment to a local variable
Normal quake console commands
*/
void GIB_Parse_Execute_Line (cbuf_t *cbuf) void GIB_Parse_Execute_Line (cbuf_t *cbuf)
{ {
cbuf_args_t *args = cbuf->args; cbuf_args_t *args = cbuf->args;
@ -334,9 +440,12 @@ void GIB_Parse_Execute_Line (cbuf_t *cbuf)
b->func (); b->func ();
else if ((f = GIB_Function_Find (args->argv[0]->str))) else if ((f = GIB_Function_Find (args->argv[0]->str)))
GIB_Function_Execute (f); GIB_Function_Execute (f);
else if (args->argc == 3 && !strcmp (args->argv[1]->str, "=")) else if (args->argc == 3 && !strcmp (args->argv[1]->str, "=")) {
GIB_Local_Set (cbuf, args->argv[0]->str, args->argv[2]->str); if (!GIB_Var_Get (cbuf, args->argv[0]->str) && GIB_Var_Get_R (gib_globals, args->argv[0]->str))
else GIB_Var_Set_R (gib_globals, args->argv[0]->str, args->argv[2]->str);
else
GIB_Var_Set (cbuf, args->argv[0]->str, args->argv[2]->str);
} else
Cmd_Command (cbuf->args); Cmd_Command (cbuf->args);
dstring_clearstr (cbuf->line); dstring_clearstr (cbuf->line);
} }

View file

@ -28,6 +28,13 @@
*/ */
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -36,49 +43,73 @@
#include "QF/cvar.h" #include "QF/cvar.h"
#include "QF/gib_buffer.h" #include "QF/gib_buffer.h"
#include "QF/gib_parse.h" #include "QF/gib_parse.h"
#include "QF/gib_vars.h"
#include "exp.h" #include "exp.h"
void unsigned int
GIB_Process_Variable (struct dstring_s *dstr) GIB_Process_Variable (struct dstring_s *dstr, unsigned int pos, qboolean tolerant)
{ {
int i;
cvar_t *cvar; cvar_t *cvar;
gib_var_t *gvar;
const char *str; const char *str;
char *p, c;
for (i = 0; dstr->str[i] == '$'; i++); for (p = dstr->str+pos+1; tolerant ? *p : isalnum (*p) || *p == '_'; p++);
i--; c = *p;
for (; i >= 0; i--) { *p = 0;
if ((str = GIB_Local_Get (cbuf_active, dstr->str+i+1))) if ((str = GIB_Var_Get (cbuf_active, dstr->str+pos+1)))
; // yay for us ; // yay for us
else if ((cvar = Cvar_FindVar (dstr->str+i+1))) else if ((gvar = GIB_Var_Get_R (gib_globals, dstr->str+pos+1)))
str = cvar->string; str = gvar->value->str;
else else if ((cvar = Cvar_FindVar (dstr->str+pos+1)))
return; str = cvar->string;
dstr->str[i] = 0; else
dstring_appendstr (dstr, str); str = 0;
} *p = c;
if (str)
dstring_replace (dstr, pos, p - dstr->str - pos, str, strlen(str));
else
dstring_snip (dstr, pos, p - dstr->str - pos);
return str ? strlen (str) : 0;
} }
void int
GIB_Process_Variables_All (struct dstring_s *token) GIB_Process_Variables_All (struct dstring_s *token)
{ {
int i, n; int i, n, m;
dstring_t *var = dstring_newstr (); dstring_t *var = dstring_newstr ();
char c = 0;
for (i = 0; token->str[i]; i++) { for (i = 0; token->str[i]; i++) {
if (token->str[i] == '$') { if (token->str[i] == '$') {
for (n = 1; token->str[i+n] == '$'; n++); // get past $s if (token->str[i+1] == '{') {
for (; isalnum(token->str[i+n]) || n = i+1;
token->str[i+n] == '.' || if ((c = GIB_Parse_Match_Brace (token->str, &n))) {
token->str[i+n] == '_'; n++); // find end of var Cbuf_Error ("parse", "Could not find match for %c", c);
dstring_insert (var, 0, token->str+i, n); // extract it goto ERROR;
GIB_Process_Variable (var); }
n -= i;
dstring_insert (var, 0, token->str+i+2, n-2);
dstring_insertstr (var, 0, "$");
n++;
} else {
for (n = 1; isalnum(token->str[i+n]) || token->str[i+n] == '$' || token->str[i+n] == '_'; n++); // find end of var
dstring_insert (var, 0, token->str+i, n); // extract it
}
for (m = 1; var->str[m]; m++) {
if (var->str[m] == '$')
m += GIB_Process_Variable (var, m, false) - 1;
}
GIB_Process_Variable (var, 0, true);
dstring_replace (token, i, n, var->str, strlen(var->str)); dstring_replace (token, i, n, var->str, strlen(var->str));
i += strlen (var->str) - 1; i += strlen (var->str) - 1;
dstring_clearstr (var); dstring_clearstr (var);
} }
} }
ERROR:
dstring_delete (var);
return c ? -1 : 0;
} }
int int
@ -153,7 +184,8 @@ GIB_Process_Token (struct dstring_s *token, char delim)
if (delim != '{' && delim != '\"') { if (delim != '{' && delim != '\"') {
if (GIB_Process_Embedded (token)) if (GIB_Process_Embedded (token))
return -1; return -1;
GIB_Process_Variables_All (token); if (GIB_Process_Variables_All (token))
return -1;
} }
if (delim == '(') if (delim == '(')
if (GIB_Process_Math (token)) if (GIB_Process_Math (token))

140
libs/util/gib_vars.c Normal file
View file

@ -0,0 +1,140 @@
/*
#FILENAME#
#DESCRIPTION#
Copyright (C) 2002 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#include <string.h>
#include <stdlib.h>
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/gib_vars.h"
#include "QF/gib_buffer.h"
hashtab_t *gib_globals = 0;
gib_var_t *
GIB_Var_New (void)
{
gib_var_t *new = calloc (1, sizeof (gib_var_t));
new->key = dstring_newstr();
new->value = dstring_newstr();
return new;
}
const char *
GIB_Var_Get_Key (void *ele, void *ptr)
{
return ((gib_var_t *)ele)->key->str;
}
void
GIB_Var_Free (void *ele, void *ptr)
{
gib_var_t *l = (gib_var_t *)ele;
dstring_delete (l->key);
dstring_delete (l->value);
if (l->subvars)
Hash_DelTable (l->subvars);
}
gib_var_t *
GIB_Var_Get_R (hashtab_t *vars, char *name)
{
char *p;
gib_var_t *l;
if ((p = strchr (name, '.'))) {
*p = 0;
l = Hash_Find (vars, name);
*p = '.';
if (!l || !l->subvars)
return 0;
return GIB_Var_Get_R (l->subvars, p+1);
} else
return Hash_Find (vars, name);
}
void
GIB_Var_Set_R (hashtab_t *vars, char *name, const char *value)
{
char *p;
gib_var_t *l;
if ((p = strchr (name, '.'))) {
*p = 0;
if (!(l = Hash_Find (vars, name))) {
l = GIB_Var_New ();
dstring_appendstr (l->key, name);
Hash_Add (vars, l);
}
*p = '.';
if (!l->subvars)
l->subvars = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
GIB_Var_Set_R (l->subvars, p+1, value);
} else {
if ((l = Hash_Find (vars, name)))
dstring_clearstr (l->value);
else {
l = GIB_Var_New ();
dstring_appendstr (l->key, name);
Hash_Add (vars, l);
}
dstring_appendstr (l->value, value);
}
}
void
GIB_Var_Set (cbuf_t *cbuf, const char *key, const char *value)
{
char *k = strdup (key);
if (!GIB_DATA(cbuf)->locals)
GIB_DATA(cbuf)->locals = Hash_NewTable (256, GIB_Var_Get_Key, GIB_Var_Free, 0);
GIB_Var_Set_R (GIB_DATA(cbuf)->locals, k, value);
free(k);
}
const char *
GIB_Var_Get (cbuf_t *cbuf, const char *key)
{
gib_var_t *l;
char *k;
if (!GIB_DATA(cbuf)->locals)
return 0;
k = strdup(key);
l = GIB_Var_Get_R (GIB_DATA(cbuf)->locals, k);
free(k);
if (l)
return l->value->str;
else
return 0;
}

View file

@ -28,6 +28,13 @@
*/ */
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <ctype.h> #include <ctype.h>
#include "QF/dstring.h" #include "QF/dstring.h"