mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
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:
parent
30012cc753
commit
0390fe22ce
15 changed files with 466 additions and 109 deletions
|
@ -3,7 +3,7 @@ SUBDIRS = GL plugin
|
|||
includedir = $(prefix)/include/QF
|
||||
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 \
|
||||
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 \
|
||||
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 \
|
||||
|
|
|
@ -25,15 +25,12 @@
|
|||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#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;
|
||||
|
@ -62,7 +59,6 @@ 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);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
typedef struct gib_builtin_s {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
typedef struct gib_function_s {
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
59 Temple Place - Suite 330
|
||||
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);
|
||||
|
||||
void GIB_Parse_Extract_Line (struct cbuf_s *cbuf);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
void GIB_Process_Variable (struct dstring_s *token);
|
||||
|
|
47
include/QF/gib_vars.h
Normal file
47
include/QF/gib_vars.h
Normal 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);
|
|
@ -28,8 +28,9 @@ libQFutil_la_DEPENDENCIES= libasm.la
|
|||
libQFutil_la_SOURCES= \
|
||||
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 \
|
||||
gib_process.c hash.c idparse.c info.c link.c mathlib.c mdfour.c msg.c ops.c \
|
||||
pakfile.c pcx.c plugin.c qargs.c qendian.c qfplist.c quakefs.c quakeio.c \
|
||||
sizebuf.c string.c sys.c tga.c va.c ver_check.c wad.c zone.c $(fnmatch)
|
||||
gib_process.c gib_vars.c hash.c idparse.c info.c link.c mathlib.c mdfour.c \
|
||||
msg.c ops.c pakfile.c pcx.c plugin.c qargs.c qendian.c qfplist.c quakefs.c \
|
||||
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)
|
||||
|
|
|
@ -28,65 +28,21 @@
|
|||
|
||||
*/
|
||||
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#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));
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
|
||||
*/
|
||||
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -41,6 +48,7 @@
|
|||
#include "QF/gib_builtin.h"
|
||||
#include "QF/gib_buffer.h"
|
||||
#include "QF/gib_function.h"
|
||||
#include "QF/gib_vars.h"
|
||||
|
||||
hashtab_t *gib_builtins;
|
||||
|
||||
|
@ -129,14 +137,30 @@ GIB_Function_f (void)
|
|||
}
|
||||
|
||||
void
|
||||
GIB_Lset_f (void)
|
||||
GIB_Local_f (void)
|
||||
{
|
||||
if (GIB_Argc () != 3)
|
||||
if (GIB_Argc () != 2)
|
||||
Cbuf_Error ("syntax",
|
||||
"lset: invalid syntax\n"
|
||||
"usage: lset variable value");
|
||||
"usage: local variable");
|
||||
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
|
||||
|
@ -268,7 +292,8 @@ GIB_Builtin_Init (void)
|
|||
{
|
||||
GIB_Builtin_Add ("function", GIB_Function_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 ("if", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
|
||||
GIB_Builtin_Add ("ifnot", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
|
||||
*/
|
||||
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
|
@ -36,10 +43,17 @@
|
|||
#include "QF/gib_parse.h"
|
||||
#include "QF/gib_buffer.h"
|
||||
#include "QF/gib_function.h"
|
||||
#include "QF/gib_vars.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
hashtab_t *gib_functions = 0;
|
||||
|
||||
/*
|
||||
GIB_Function_New
|
||||
|
||||
Builds a new function struct and returns
|
||||
a pointer to it.
|
||||
*/
|
||||
gib_function_t *
|
||||
GIB_Function_New (void)
|
||||
{
|
||||
|
@ -50,12 +64,14 @@ GIB_Function_New (void)
|
|||
return new;
|
||||
}
|
||||
|
||||
/*
|
||||
Hashtable callbacks
|
||||
*/
|
||||
const char *
|
||||
GIB_Function_Get_Key (void *ele, void *ptr)
|
||||
{
|
||||
return ((gib_function_t *)ele)->name->str;
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Function_Free (void *ele, void *ptr)
|
||||
{
|
||||
|
@ -64,6 +80,13 @@ GIB_Function_Free (void *ele, void *ptr)
|
|||
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
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
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_Find (const char *name)
|
||||
{
|
||||
|
@ -90,6 +120,15 @@ GIB_Function_Find (const char *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
|
||||
GIB_Function_Execute (gib_function_t *func)
|
||||
{
|
||||
|
@ -104,6 +143,6 @@ GIB_Function_Execute (gib_function_t *func)
|
|||
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));
|
||||
GIB_Var_Set (sub, va("%i", i), cbuf_active->args->argv[i]->str);
|
||||
GIB_Var_Set (sub, "argc", va("%i", cbuf_active->args->argc));
|
||||
}
|
||||
|
|
|
@ -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#
|
||||
|
||||
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 <string.h>
|
||||
|
||||
|
@ -39,6 +46,7 @@
|
|||
#include "QF/gib_process.h"
|
||||
#include "QF/gib_builtin.h"
|
||||
#include "QF/gib_function.h"
|
||||
#include "QF/gib_vars.h"
|
||||
|
||||
// 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
|
||||
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 '\"';
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
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 '{';
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
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 '(';
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
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)++) {
|
||||
if (str[*i] == '`')
|
||||
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)))
|
||||
return c;
|
||||
}
|
||||
|
@ -117,6 +161,13 @@ GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
|
|||
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
|
||||
GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
||||
{
|
||||
|
@ -129,7 +180,6 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
|||
|
||||
dstring_clearstr (cbuf->line);
|
||||
|
||||
|
||||
for (i = 0; dstr->str[i]; i++) {
|
||||
if (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);
|
||||
else {
|
||||
dstring_snip (dstr, i, strlen(dstr->str+i));
|
||||
i--; // So we don't go past null
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dstr->str[0]) {
|
||||
if (i) {
|
||||
if (dstr->str[0]) { // If something is left in the buffer
|
||||
if (i) { // If we used any of it
|
||||
dstring_insert (cbuf->line, 0, dstr->str, i);
|
||||
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] == ';'));
|
||||
}
|
||||
|
||||
// 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])
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
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)++;
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||
{
|
||||
|
@ -324,6 +418,18 @@ FILTER_ERROR:
|
|||
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)
|
||||
{
|
||||
cbuf_args_t *args = cbuf->args;
|
||||
|
@ -334,9 +440,12 @@ void GIB_Parse_Execute_Line (cbuf_t *cbuf)
|
|||
b->func ();
|
||||
else if ((f = GIB_Function_Find (args->argv[0]->str)))
|
||||
GIB_Function_Execute (f);
|
||||
else if (args->argc == 3 && !strcmp (args->argv[1]->str, "="))
|
||||
GIB_Local_Set (cbuf, args->argv[0]->str, args->argv[2]->str);
|
||||
else
|
||||
else if (args->argc == 3 && !strcmp (args->argv[1]->str, "=")) {
|
||||
if (!GIB_Var_Get (cbuf, args->argv[0]->str) && GIB_Var_Get_R (gib_globals, args->argv[0]->str))
|
||||
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);
|
||||
dstring_clearstr (cbuf->line);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,13 @@
|
|||
|
||||
*/
|
||||
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
@ -36,49 +43,73 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/gib_buffer.h"
|
||||
#include "QF/gib_parse.h"
|
||||
#include "QF/gib_vars.h"
|
||||
|
||||
#include "exp.h"
|
||||
|
||||
void
|
||||
GIB_Process_Variable (struct dstring_s *dstr)
|
||||
unsigned int
|
||||
GIB_Process_Variable (struct dstring_s *dstr, unsigned int pos, qboolean tolerant)
|
||||
{
|
||||
int i;
|
||||
cvar_t *cvar;
|
||||
gib_var_t *gvar;
|
||||
const char *str;
|
||||
char *p, c;
|
||||
|
||||
for (i = 0; dstr->str[i] == '$'; i++);
|
||||
i--;
|
||||
for (; i >= 0; i--) {
|
||||
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, str);
|
||||
}
|
||||
for (p = dstr->str+pos+1; tolerant ? *p : isalnum (*p) || *p == '_'; p++);
|
||||
c = *p;
|
||||
*p = 0;
|
||||
if ((str = GIB_Var_Get (cbuf_active, dstr->str+pos+1)))
|
||||
; // yay for us
|
||||
else if ((gvar = GIB_Var_Get_R (gib_globals, dstr->str+pos+1)))
|
||||
str = gvar->value->str;
|
||||
else if ((cvar = Cvar_FindVar (dstr->str+pos+1)))
|
||||
str = cvar->string;
|
||||
else
|
||||
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)
|
||||
{
|
||||
int i, n;
|
||||
int i, n, m;
|
||||
dstring_t *var = dstring_newstr ();
|
||||
char c = 0;
|
||||
|
||||
for (i = 0; token->str[i]; i++) {
|
||||
if (token->str[i] == '$') {
|
||||
for (n = 1; token->str[i+n] == '$'; n++); // get past $s
|
||||
for (; 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
|
||||
GIB_Process_Variable (var);
|
||||
if (token->str[i+1] == '{') {
|
||||
n = i+1;
|
||||
if ((c = GIB_Parse_Match_Brace (token->str, &n))) {
|
||||
Cbuf_Error ("parse", "Could not find match for %c", c);
|
||||
goto ERROR;
|
||||
}
|
||||
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));
|
||||
i += strlen (var->str) - 1;
|
||||
dstring_clearstr (var);
|
||||
}
|
||||
}
|
||||
ERROR:
|
||||
dstring_delete (var);
|
||||
return c ? -1 : 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -153,7 +184,8 @@ GIB_Process_Token (struct dstring_s *token, char delim)
|
|||
if (delim != '{' && delim != '\"') {
|
||||
if (GIB_Process_Embedded (token))
|
||||
return -1;
|
||||
GIB_Process_Variables_All (token);
|
||||
if (GIB_Process_Variables_All (token))
|
||||
return -1;
|
||||
}
|
||||
if (delim == '(')
|
||||
if (GIB_Process_Math (token))
|
||||
|
|
140
libs/util/gib_vars.c
Normal file
140
libs/util/gib_vars.c
Normal 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;
|
||||
}
|
|
@ -28,6 +28,13 @@
|
|||
|
||||
*/
|
||||
|
||||
static const char rcsid[] =
|
||||
"$Id$";
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
|
|
Loading…
Reference in a new issue