diff --git a/include/QF/Makefile.am b/include/QF/Makefile.am index 0f116a411..35c1d1c9c 100644 --- a/include/QF/Makefile.am +++ b/include/QF/Makefile.am @@ -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 \ diff --git a/include/QF/gib_buffer.h b/include/QF/gib_buffer.h index f7764f2c8..d6aa53a4b 100644 --- a/include/QF/gib_buffer.h +++ b/include/QF/gib_buffer.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); + diff --git a/include/QF/gib_builtin.h b/include/QF/gib_builtin.h index c6170000a..7d819ace5 100644 --- a/include/QF/gib_builtin.h +++ b/include/QF/gib_builtin.h @@ -26,6 +26,7 @@ 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA + $Id$ */ typedef struct gib_builtin_s { diff --git a/include/QF/gib_function.h b/include/QF/gib_function.h index 17348a596..289919bba 100644 --- a/include/QF/gib_function.h +++ b/include/QF/gib_function.h @@ -26,6 +26,7 @@ 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA + $Id$ */ typedef struct gib_function_s { diff --git a/include/QF/gib_parse.h b/include/QF/gib_parse.h index b8f4d7824..1f27d3f36 100644 --- a/include/QF/gib_parse.h +++ b/include/QF/gib_parse.h @@ -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); diff --git a/include/QF/gib_process.h b/include/QF/gib_process.h index b02a626db..956ee4362 100644 --- a/include/QF/gib_process.h +++ b/include/QF/gib_process.h @@ -26,6 +26,7 @@ 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA + $Id$ */ void GIB_Process_Variable (struct dstring_s *token); diff --git a/include/QF/gib_vars.h b/include/QF/gib_vars.h new file mode 100644 index 000000000..cceac3aef --- /dev/null +++ b/include/QF/gib_vars.h @@ -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); diff --git a/libs/util/Makefile.am b/libs/util/Makefile.am index 7a309cd29..f6e1cb12c 100644 --- a/libs/util/Makefile.am +++ b/libs/util/Makefile.am @@ -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) diff --git a/libs/util/gib_buffer.c b/libs/util/gib_buffer.c index 67d98daee..492372c05 100644 --- a/libs/util/gib_buffer.c +++ b/libs/util/gib_buffer.c @@ -28,65 +28,21 @@ */ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include +#include #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)); diff --git a/libs/util/gib_builtin.c b/libs/util/gib_builtin.c index 09c1bd3b7..5aaee8b76 100644 --- a/libs/util/gib_builtin.c +++ b/libs/util/gib_builtin.c @@ -28,6 +28,13 @@ */ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include @@ -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); diff --git a/libs/util/gib_function.c b/libs/util/gib_function.c index f62797129..e1d1d6c82 100644 --- a/libs/util/gib_function.c +++ b/libs/util/gib_function.c @@ -28,6 +28,13 @@ */ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #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)); } diff --git a/libs/util/gib_parse.c b/libs/util/gib_parse.c index 089af35a6..f3369e95e 100644 --- a/libs/util/gib_parse.c +++ b/libs/util/gib_parse.c @@ -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 #include @@ -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); } diff --git a/libs/util/gib_process.c b/libs/util/gib_process.c index 0de961259..6625b0670 100644 --- a/libs/util/gib_process.c +++ b/libs/util/gib_process.c @@ -28,6 +28,13 @@ */ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include @@ -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)) diff --git a/libs/util/gib_vars.c b/libs/util/gib_vars.c new file mode 100644 index 000000000..ce7aa5e0b --- /dev/null +++ b/libs/util/gib_vars.c @@ -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 +#include + +#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; +} diff --git a/libs/util/idparse.c b/libs/util/idparse.c index 05bbbb4f6..7567f9a55 100644 --- a/libs/util/idparse.c +++ b/libs/util/idparse.c @@ -28,6 +28,13 @@ */ +static const char rcsid[] = + "$Id$"; + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include "QF/dstring.h"