From 32f4e53aa59e29512bc4e74525dc4ef320ea4389 Mon Sep 17 00:00:00 2001 From: Brian Koropoff Date: Fri, 23 Aug 2002 21:18:00 +0000 Subject: [PATCH] Fixed the GIB math evaluator to handle unary operators properly, made indexing/clipping more like python, made some cosmetic changes to zoom.gib, and added the ability for GIB builtins to return values. --- doc/config/zoom.gib | 3 ++- include/ops.h | 1 + libs/util/exp.c | 27 ++++++++++++++++++--------- libs/util/gib_builtin.c | 27 +++++++++++++++++++++++++++ libs/util/gib_parse.c | 5 +++++ libs/util/gib_process.c | 30 ++++++++++++++++++++---------- libs/util/ops.c | 5 +++++ 7 files changed, 78 insertions(+), 20 deletions(-) diff --git a/doc/config/zoom.gib b/doc/config/zoom.gib index 1c34d6136..095f43b5d 100644 --- a/doc/config/zoom.gib +++ b/doc/config/zoom.gib @@ -1,4 +1,4 @@ -// zoom.rc +// zoom.gib // // zoom script for GIB in QuakeForge 0.5 // @@ -42,6 +42,7 @@ function "zoom.init" { // Initialize basic options set in_amp ${zoom.amp} } +// Default initial values zoom.init 1 90 1 90 1.15 function "zoom.adjust" { // Adjust fov and sensitivity to match zoom factor diff --git a/include/ops.h b/include/ops.h index 6cb92f7d7..dbb594189 100644 --- a/include/ops.h +++ b/include/ops.h @@ -23,6 +23,7 @@ #define __ops_h double OP_Not (double op1, double op2); +double OP_Negate (double op1, double op2); double OP_Add (double op1, double op2); double OP_Sub (double op1, double op2); double OP_Mult (double op1, double op2); diff --git a/libs/util/exp.c b/libs/util/exp.c index bc488587f..882d38eea 100644 --- a/libs/util/exp.c +++ b/libs/util/exp.c @@ -36,6 +36,7 @@ optable_t optable[] = {"!", OP_Not, 1}, {"**", OP_Exp, 2}, {"/", OP_Div, 2}, + {"-", OP_Negate, 1}, {"*", OP_Mult, 2}, {"+", OP_Add, 2}, {"-", OP_Sub, 2}, @@ -168,6 +169,16 @@ int EXP_DoFunction (token *chain) return -2; // We shouldn't get here } +int EXP_DoUnary (token *chain) +{ + if (chain->generic.next->generic.type == TOKEN_OP) + EXP_DoUnary (chain->generic.next); + if (chain->generic.next->generic.type != TOKEN_NUM) + return -1; // In theory, this should never happen + chain->generic.next->num.value = chain->op.op->func(chain->generic.next->num.value, 0); + EXP_RemoveToken (chain); + return 0; +} token *EXP_ParseString (char *str) { @@ -250,6 +261,8 @@ token *EXP_ParseString (char *str) i -= (m - strlen(op->str) + 1); new = EXP_NewToken(); new->generic.type = TOKEN_OP; + if (*(op->str) == '-') // HACK HACK HACK + op = optable + 6; // Always assume subtraction for - new->op.op = op; new->generic.prev = cur; new->generic.next = 0; @@ -317,6 +330,10 @@ exp_error_t EXP_SimplifyTokens (token *chain) for (cur = chain->generic.next; cur->generic.type != TOKEN_CPAREN; cur = cur->generic.next) { if (cur->generic.type == TOKEN_OP && cur->op.op == optable + i && cur->generic.next) { + // If a unary operator is in our way, it gets evaluated early + if (cur->generic.next->generic.type == TOKEN_OP) + if (EXP_DoUnary (cur->generic.next)) + return EXP_E_SYNTAX; if (optable[i].operands == 1 && cur->generic.next->generic.type == TOKEN_NUM) { cur->generic.next->num.value = optable[i].func(cur->generic.next->num.value, 0); temp = cur; @@ -422,15 +439,7 @@ exp_error_t EXP_Validate (token *chain) else if ((cur->generic.type == TOKEN_OP || cur->generic.type == TOKEN_OPAREN) && cur->generic.next->generic.type == TOKEN_OP) { if (cur->generic.next->op.op->func == OP_Sub) /* Stupid hack for negation */ - { - cur = cur->generic.next; - cur->generic.type = TOKEN_NUM; - cur->num.value = -1.0; - new = EXP_NewToken(); - new->generic.type = TOKEN_OP; - new->op.op = EXP_FindOpByStr ("*"); - EXP_InsertTokenAfter (cur, new); - } + cur->generic.next->op.op = optable + 3; else if (cur->generic.next->op.op->operands == 2) return EXP_E_SYNTAX; /* Operator misuse */ } diff --git a/libs/util/gib_builtin.c b/libs/util/gib_builtin.c index c3b463306..d543bf8e1 100644 --- a/libs/util/gib_builtin.c +++ b/libs/util/gib_builtin.c @@ -162,6 +162,16 @@ GIB_Arg_Strip_Delim (unsigned int arg) } } +void +GIB_Return (const char *str) +{ + if (GIB_DATA(cbuf_active)->type != GIB_BUFFER_PROXY) + return; + dstring_clearstr (GIB_DATA(cbuf_active->up)->ret.retval); + dstring_appendstr (GIB_DATA(cbuf_active->up)->ret.retval, str); + GIB_DATA(cbuf_active->up)->ret.available = true; +} + /* GIB Builtin functions @@ -178,6 +188,22 @@ GIB_Function_f (void) GIB_Function_Define (GIB_Argv(1), GIB_Argv(2)); } +void +GIB_FunctionDotGet_f (void) +{ + if (GIB_Argc () != 2) + Cbuf_Error ("syntax", + "function.get: invalid syntax\n" + "usage: function.get function_name"); + else { + gib_function_t *f; + if ((f = GIB_Function_Find (GIB_Argv (1)))) + GIB_Return (f->program->str); + else + GIB_Return (""); + } +} + void GIB_Local_f (void) { @@ -335,6 +361,7 @@ void GIB_Builtin_Init (void) { GIB_Builtin_Add ("function", GIB_Function_f, GIB_BUILTIN_NORMAL); + GIB_Builtin_Add ("function.get", GIB_FunctionDotGet_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("export", GIB_Export_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("local", GIB_Local_f, GIB_BUILTIN_NORMAL); GIB_Builtin_Add ("global", GIB_Global_f, GIB_BUILTIN_NORMAL); diff --git a/libs/util/gib_parse.c b/libs/util/gib_parse.c index 964af3344..c7b97e1e9 100644 --- a/libs/util/gib_parse.c +++ b/libs/util/gib_parse.c @@ -213,6 +213,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_Backtick (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] == '/') { diff --git a/libs/util/gib_process.c b/libs/util/gib_process.c index 86a91271c..3be682155 100644 --- a/libs/util/gib_process.c +++ b/libs/util/gib_process.c @@ -64,7 +64,13 @@ GIB_Process_Index (dstring_t *index, unsigned int pos, int *i1, int *i2) } v1 = atoi (index->str+pos+1); if ((p = strchr (index->str+pos, ':'))) { - v2 = atoi (p+1); + if (*(p+1) == ']') + v2 = -1; + else { + v2 = atoi (p+1); + if (v2 < 0) + v2--; + } } else v2 = v1; dstring_snip (index, pos, i - pos + 1); @@ -140,9 +146,14 @@ GIB_Process_Variables_All (struct dstring_s *token) token->str[i+n] == '_' || token->str[i+n] == '[' || token->str[i+n] == ':'; n++) { - if (token->str[i+n] == '[') + if (token->str[i+n] == '[') { while (token->str[i+n] && token->str[i+n] != ']') n++; + if (!token->str[i+n]) { + Cbuf_Error ("parse", "Could not find match for ["); + goto ERROR; + } + } } dstring_insert (var, 0, token->str+i, n); // extract it } @@ -172,15 +183,14 @@ GIB_Process_Variables_All (struct dstring_s *token) i2 = 0; } else if (i2 >= strlen (var->str)) i2 = strlen(var->str)-1; - if (i2 < i1) { - i1 ^= i2; - i2 ^= i1; - i1 ^= i2; + if (i2 < i1) + dstring_clearstr (var); + else { + if (i2 < strlen(var->str)-1) // Snip everthing after index 2 + dstring_snip (var, i2+1, strlen(var->str)-i2-1); + if (i1 > 0) // Snip everything before index 1 + dstring_snip (var, 0, i1); } - if (i2 < strlen(var->str)-1) // Snip everthing after index 2 - dstring_snip (var, i2+1, strlen(var->str)-i2-1); - if (i1 > 0) // Snip everything before index 1 - dstring_snip (var, 0, i1); } dstring_replace (token, i, n, var->str, strlen(var->str)); i += strlen (var->str) - 1; diff --git a/libs/util/ops.c b/libs/util/ops.c index 954ccc960..e8142d0e1 100644 --- a/libs/util/ops.c +++ b/libs/util/ops.c @@ -26,6 +26,11 @@ double OP_Not (double op1, double op2) return !op1; } +double OP_Negate (double op1, double op2) +{ + return -op1; +} + double OP_Add (double op1, double op2) { return op1 + op2;