This update adds a proper instruction and subroutine stack and a better parser.

This commit is contained in:
Brian Koropoff 2000-08-30 06:07:02 +00:00
parent 60c112bc68
commit c1ac5ca92a
12 changed files with 231 additions and 176 deletions

View file

@ -9,3 +9,4 @@
#define GIB_E_BUFFER 7
#define GIB_E_TYPE 8
#define GIB_E_ULIMIT 9
#define GIB_E_ILLINST 10

View file

@ -3,12 +3,8 @@ gib_inst_t *GIB_Find_Instruction (char *name);
void GIB_Init_Instructions (void);
int GIB_Echo_f (void);
int GIB_Call_f (void);
int GIB_VarPrint_f (void);
int GIB_Return_f (void);
int GIB_VarSub_f (void);
int GIB_Con_f (void);
int GIB_Eval_f (void);
int GIB_ListFetch_f (void);
int GIB_BackTick_f (void);
int GIB_ExpandVars (char *source, char *buffer, int bufferlen);
int GIB_ExpandBackticks (char *source, char *buffer, int bufferlen);

View file

@ -1,23 +1,15 @@
#define GIB_MAXCALLS 2048
#define GIB_MAXSUBARGS 256
extern gib_module_t *gib_currentmod[GIB_MAXCALLS];
extern gib_sub_t *gib_currentsub[GIB_MAXCALLS];
extern int gib_subsp;
extern int gib_argc[GIB_MAXCALLS];
extern char *gib_argv[GIB_MAXCALLS][80];
extern int gib_argofs;
extern char *GIB_SUBARGV[GIB_MAXSUBARGS];
extern int GIB_SUBARGC;
extern char errorline[1024];
extern char *gib_subargv[256];
extern int gib_subargc;
char *GIB_Argv(int i);
int GIB_Argc(void);
void GIB_Strip_Arg (char *arg);
int GIB_Execute_Block (char *block, int retflag);
int GIB_Execute_Inst (char *inst);
int GIB_Execute_Inst (void);
int GIB_Execute_Sub (void);
int GIB_Interpret_Inst (char *inst);
int GIB_Run_Inst (char *inst);
int GIB_Run_Sub (gib_module_t *mod, gib_sub_t *sub);

29
include/gib_stack.h Normal file
View file

@ -0,0 +1,29 @@
#define GIB_LOCALS gib_substack[gib_subsp - 1].local
#define GIB_CURRENTMOD gib_substack[gib_subsp - 1].mod
#define GIB_CURRENTSUB gib_substack[gib_subsp - 1].sub
typedef struct gib_instack_s
{
gib_inst_t *instruction;
char **argv;
int argc;
} gib_instack_t;
typedef struct gib_substack_s
{
gib_module_t *mod;
gib_sub_t *sub;
gib_var_t *local;
} gib_substack_t;
extern gib_instack_t *gib_instack;
extern gib_substack_t *gib_substack;
extern int gib_insp;
extern int gib_subsp;
void GIB_InStack_Push (gib_inst_t *instruction, int argc, char **argv);
void GIB_InStack_Pop ();
void GIB_SubStack_Push (gib_module_t *mod, gib_sub_t *sub, gib_var_t *local);
void GIB_SubStack_Pop ();

View file

@ -1,4 +1,3 @@
extern gib_var_t *gib_locals[GIB_MAXCALLS];
gib_var_t *GIB_Var_FindLocal (char *key);
gib_var_t *GIB_Var_FindGlobal (char *key);

View file

@ -115,7 +115,7 @@ client_LIBS= -L. -lqfsys -lqfsnd -lqfcd -lqfnet $(SOUND_LIBS) $(NET_LIBS)
client_SOURCES= cl_cam.c cl_demo.c cl_input.c cl_main.c cl_parse.c \
cl_tent.c console.c keys.c menu.c sbar.c r_view.c \
nonintel.c gib.c gib_instructions.c gib_vars.c \
gib_interpret.c gib_modules.c gib_parse.c
gib_interpret.c gib_modules.c gib_parse.c gib_stack.c
server_SOURCES= host.c host_cmd.c \
pr_cmds.c pr_edict.c pr_exec.c \

View file

@ -18,9 +18,6 @@
#include "gib_vars.h"
//static char *gib_args;
// Standard cvars
void GIB_Init (void)
@ -45,13 +42,13 @@ void GIB_Gib_f (void)
Con_Printf("Subroutine not found!\n");
else
{
GIB_SUBARGC = Cmd_Argc() - 1;
GIB_SUBARGV[0] = sub->name;
for (i = 1; i <= GIB_SUBARGC; i++)
GIB_SUBARGV[i] = Cmd_Argv(i + 1);
gib_subargc = Cmd_Argc() - 1;
gib_subargv[0] = sub->name;
for (i = 1; i <= gib_subargc; i++)
gib_subargv[i] = Cmd_Argv(i + 1);
ret = GIB_Run_Sub(mod, sub);
if (ret != 0)
Con_Printf("Error in execution of %s!\nError code: %i\n\nLine at fault: %s\n", Cmd_Argv(1), ret, errorline);
Con_Printf("Error in execution of %s!\nError code: %i\n", Cmd_Argv(1), ret);
}
}

View file

@ -18,6 +18,7 @@
#include "gib_parse.h"
#include "gib_vars.h"
#include "gib_error.h"
#include "gib_stack.h"
static gib_inst_t *gibinstructions;
@ -49,13 +50,9 @@ void GIB_Init_Instructions (void)
{
GIB_AddInstruction("echo", GIB_Echo_f);
GIB_AddInstruction("call", GIB_Call_f);
GIB_AddInstruction("varprint", GIB_VarPrint_f);
GIB_AddInstruction("return", GIB_Return_f);
GIB_AddInstruction("varsub", GIB_VarSub_f);
GIB_AddInstruction("con", GIB_Con_f);
GIB_AddInstruction("listfetch", GIB_ListFetch_f);
GIB_AddInstruction("eval", GIB_Eval_f);
GIB_AddInstruction("backtick", GIB_BackTick_f);
}
@ -77,10 +74,10 @@ int GIB_Call_f (void)
sub = GIB_Get_ModSub_Sub (GIB_Argv(1));
if (!sub)
return GIB_E_NOSUB;
GIB_SUBARGC = GIB_Argc() - 1;
GIB_SUBARGV[0] = sub->name;
for (i = 1; i <= GIB_SUBARGC; i++)
GIB_SUBARGV[i] = GIB_Argv(i + 1);
gib_subargc = GIB_Argc() - 1;
gib_subargv[0] = sub->name;
for (i = 1; i <= gib_subargc; i++)
gib_subargv[i] = GIB_Argv(i + 1);
ret = GIB_Run_Sub (mod, sub);
if (gib_subret)
{
@ -115,20 +112,6 @@ int GIB_Return_f (void)
return GIB_E_RETURN; // Signal to block executor to return immediately
}
int GIB_VarSub_f (void)
{
char buffer[1024];
int ret;
if (GIB_Argc() != 1)
return GIB_E_NUMARGS;
if ((ret = GIB_ExpandVars(GIB_Argv(1), buffer, 1024)))
return ret;
GIB_Var_Set ("retval", buffer);
return 0;
}
int GIB_ListFetch_f (void)
{
char *element;
@ -167,40 +150,6 @@ int GIB_Con_f (void)
return 0;
}
int GIB_Eval_f (void)
{
gib_var_t *var;
char *buffer;
int ret;
if (GIB_Argc() != 1)
return GIB_E_NUMARGS;
if (!(var = GIB_Var_FindLocal (GIB_Argv(1))))
return GIB_E_NOVAR;
buffer = malloc(strlen(var->value) + 1);
strcpy(buffer, var->value);
gib_argofs++; /* HACK HACK HACK - This is required or
GIB_Execute_Instruction will smash gib_argv */
ret = GIB_Execute_Block (buffer, 0);
gib_argofs--;
free (buffer);
return ret;
}
int GIB_BackTick_f (void)
{
char buffer[1024];
int ret;
if (GIB_Argc() != 1)
return GIB_E_NUMARGS;
if ((ret = GIB_ExpandBackticks (GIB_Argv(1), buffer, 1024)))
return ret;
GIB_Var_Set ("retval", buffer);
return 0;
}
int GIB_ExpandVars (char *source, char *buffer, int buffersize)
{
int i, n, m;
@ -252,9 +201,7 @@ int GIB_ExpandBackticks (char *source, char *buffer, int buffersize)
tick[m++] = source[i];
tick[m++] = 0;
gib_argofs++;
ret = GIB_Execute_Inst (tick);
gib_argofs--;
ret = GIB_Run_Inst (tick);
if (ret)
{
return ret;

View file

@ -18,29 +18,19 @@
#include "gib_parse.h"
#include "gib_vars.h"
#include "gib_error.h"
#include "gib_stack.h"
gib_module_t *gib_currentmod[GIB_MAXCALLS];
gib_sub_t *gib_currentsub[GIB_MAXCALLS];
int gib_subsp = 0;
char *GIB_SUBARGV[GIB_MAXSUBARGS];
int GIB_SUBARGC;
int gib_argc[GIB_MAXCALLS];
char *gib_argv[GIB_MAXCALLS][80];
int gib_argofs = 0;
char errorline[1024];
char *gib_subargv[256];
int gib_subargc;
char *GIB_Argv(int i)
{
return gib_argv[gib_subsp + gib_argofs][i];
return gib_instack[gib_insp - 1].argv[i];
}
int GIB_Argc(void)
{
return gib_argc[gib_subsp + gib_argofs];
return gib_instack[gib_insp - 1].argc;
}
void GIB_Strip_Arg (char *arg)
@ -64,29 +54,41 @@ int GIB_Execute_Block (char *block, int retflag)
code = malloc(len + 1);
strncpy(code, block + i, len);
code[len] = 0;
if ((ret = GIB_Execute_Inst(code)))
if ((ret = GIB_Interpret_Inst(code)))
{
if (retflag && ret == GIB_E_RETURN)
return 0;
else
{
strcpy(errorline, code);
free (code);
return ret;
}
}
if ((ret = GIB_Execute_Inst()))
{
free (code);
i += len + 1;
if (ret == GIB_E_RETURN && retflag)
return 0;
return ret;
}
i += len + 1;
free (code);
}
if (len == -1)
return GIB_E_PARSE;
return 0;
}
int GIB_Execute_Inst (char *inst)
int GIB_Execute_Inst (void)
{
int ret;
ret = gib_instack[gib_insp - 1].instruction->func ();
GIB_InStack_Pop();
return ret;
}
int GIB_Interpret_Inst (char *inst)
{
char *buffer;
char *buffer2;
char *buffer3;
int i, n, len, ret;
int i, n, len, ret, gib_argc;
char *gib_argv[256];
gib_inst_t *ginst;
@ -108,66 +110,89 @@ int GIB_Execute_Inst (char *inst)
buffer2 = malloc(2048);
buffer3 = malloc(2048);
GIB_ExpandVars (buffer, buffer2, 2048);
GIB_ExpandBackticks (buffer2, buffer3, 2048);
gib_argc[gib_subsp + gib_argofs] = 0;
ret = GIB_ExpandVars (buffer, buffer2, 2048);
if (ret)
return ret;
ret = GIB_ExpandBackticks (buffer2, buffer3, 2048);
if (ret)
return ret;
gib_argc = 0;
for (i = 0; buffer3[i] != ' '; i++);
gib_argv[gib_subsp + gib_argofs][0] = malloc(i + 1);
strncpy(gib_argv[gib_subsp + gib_argofs][0], buffer3, i);
gib_argv[gib_subsp + gib_argofs][0][i] = 0;
gib_argv[0] = malloc(i + 1);
strncpy(gib_argv[0], buffer3, i);
gib_argv[0][i] = 0;
for (n = 0;;n++)
{
for (;isspace(buffer3[i]); i++);
if (buffer3[i] == 0)
break;
if ((len = GIB_Get_Arg(buffer3 + i)) < 0) // Parse error
if ((len = GIB_Get_Arg(buffer3 + i)) < 0)
return GIB_E_PARSE;
else
{
gib_argv[gib_subsp + gib_argofs][n + 1] = malloc(len + 1);
strncpy(gib_argv[gib_subsp + gib_argofs][n + 1], buffer3 + i, len);
gib_argv[gib_subsp + gib_argofs][n + 1][len] = 0;
GIB_ExpandEscapes (gib_argv[gib_subsp + gib_argofs][n + 1]);
gib_argv[n + 1] = malloc(len + 1);
strncpy(gib_argv[n + 1], buffer3 + i, len);
gib_argv[n + 1][len] = 0;
GIB_ExpandEscapes (gib_argv[n + 1]);
i += len;
}
}
gib_argc[gib_subsp + gib_argofs] = n;
gib_argc = n;
free(buffer);
free(buffer2);
free(buffer3);
for (i = 1; i <= n; i++)
GIB_Strip_Arg (gib_argv[gib_subsp + gib_argofs][i]);
if (!(ginst = GIB_Find_Instruction(gib_argv[gib_subsp + gib_argofs][0])))
return 1;
ret = ginst->func ();
GIB_Strip_Arg (gib_argv[i]);
if (!(ginst = GIB_Find_Instruction(gib_argv[0])))
return GIB_E_ILLINST;
GIB_InStack_Push(ginst, gib_argc, gib_argv);
for (i = 0; i <= n; i++)
free(gib_argv[gib_subsp + gib_argofs][i]);
return ret;
free(gib_argv[i]);
return 0;
}
int GIB_Run_Sub (gib_module_t *mod, gib_sub_t *sub)
{
int ret, i;
char buf[256];
if (++gib_subsp >= GIB_MAXCALLS)
return 3;
gib_currentmod[gib_subsp] = mod;
gib_currentsub[gib_subsp] = sub;
gib_locals[gib_subsp] = 0;
for (i = 0; i <= GIB_SUBARGC; i++)
GIB_SubStack_Push (mod, sub, 0);
for (i = 0; i <= gib_subargc; i++)
{
sprintf(buf, "arg%i", i);
GIB_Var_Set (buf, GIB_SUBARGV[i]);
GIB_Var_Set (buf, gib_subargv[i]);
}
ret = GIB_Execute_Block(sub->code, 1);
if (gib_locals[gib_subsp])
GIB_Var_FreeAll(gib_locals[gib_subsp]);
gib_subsp--;
sprintf(buf, "%i", gib_subargc);
GIB_Var_Set ("argc", buf);
ret = GIB_Execute_Sub ();
if (GIB_LOCALS)
GIB_Var_FreeAll(GIB_LOCALS);
GIB_SubStack_Pop ();
return ret;
}
int GIB_Execute_Sub (void)
{
return GIB_Execute_Block (GIB_CURRENTSUB->code, 1);
}
int GIB_Run_Inst (char *inst)
{
int ret;
ret = GIB_Interpret_Inst (inst);
if (ret)
{
GIB_InStack_Pop ();
return ret;
}
return GIB_Execute_Inst ();
}

View file

@ -53,32 +53,29 @@ int GIB_Get_Inst(char *start)
int GIB_Get_Arg (char *start)
{
int i;
int len = 0;
int ret = -2;
for (i = 0; start[i] != ' ' && start[i] != 0; i++)
Con_Printf("Parsing at %s\n", start);
if (*start == '\'')
{
if (start[i] == '\'')
ret = GIB_End_Quote(start);
}
if (*start == '\"')
{
if ((len = GIB_End_Quote(start + i)) < 0)
return len;
else
i += len;
ret = GIB_End_DQuote(start);
}
if (start[i] == '\"')
if (*start == '{')
{
if ((len = GIB_End_DQuote(start + i)) < 0)
return len;
else
i += len;
}
if (start[i] == '{')
{
if ((len = GIB_End_Bracket(start + i)) < 0)
return len;
else
i += len;
}
ret = GIB_End_Bracket(start);
}
if (ret == -1)
return -1;
if (ret >= 0)
return ret;
for (i = 1; (start[i] != ' ' && start[i] != 0 && start[i] != '\'' && start[i] != '\"' && start[i] != '{') || start[i - 1] == '\\'; i++);
return i;
}
int GIB_End_Quote (char *start)

73
source/gib_stack.c Normal file
View file

@ -0,0 +1,73 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "cvar.h"
#include "console.h"
#include "qargs.h"
#include "cmd.h"
#include "zone.h"
#include "quakefs.h"
#include "gib.h"
#include "gib_instructions.h"
#include "gib_interpret.h"
#include "gib_modules.h"
#include "gib_parse.h"
#include "gib_vars.h"
#include "gib_error.h"
#include "gib_stack.h"
gib_instack_t *gib_instack = 0;
gib_substack_t *gib_substack = 0;
int gib_insp = 0;
int gib_subsp = 0;
void GIB_InStack_Push (gib_inst_t *instruction, int argc, char **argv)
{
int i;
gib_instack = realloc(gib_instack, sizeof(gib_instack_t) * (gib_insp + 1));
gib_instack[gib_insp].argv = malloc(argc + 1);
for (i = 0; i <= argc; i++)
{
gib_instack[gib_insp].argv[i] = malloc(strlen(argv[i]) + 1);
strcpy(gib_instack[gib_insp].argv[i], argv[i]);
}
gib_instack[gib_insp].argc = argc;
gib_instack[gib_insp].instruction = instruction;
gib_insp++;
}
void GIB_InStack_Pop (void)
{
int i;
gib_insp--;
for (i = 0; i <= gib_instack[gib_insp].argc; i++)
free(gib_instack[gib_insp].argv[i]);
free(gib_instack[gib_insp].argv);
gib_instack = realloc(gib_instack, sizeof(gib_instack_t) * gib_insp);
}
void GIB_SubStack_Push (gib_module_t *mod, gib_sub_t *sub, gib_var_t *local)
{
gib_substack = realloc(gib_substack, sizeof(gib_substack_t) * (gib_subsp + 1));
gib_substack[gib_subsp].mod = mod;
gib_substack[gib_subsp].sub = sub;
gib_substack[gib_subsp].local = local;
gib_subsp++;
}
void GIB_SubStack_Pop (void)
{
gib_instack = realloc(gib_instack, sizeof(gib_instack_t) * (--gib_subsp));
}

View file

@ -17,15 +17,14 @@
#include "gib_modules.h"
#include "gib_parse.h"
#include "gib_vars.h"
gib_var_t *gib_locals[GIB_MAXCALLS];
#include "gib_stack.h"
gib_var_t *GIB_Var_FindLocal (char *key)
{
gib_var_t *var;
if (!(gib_locals[gib_subsp]))
if (!(GIB_LOCALS))
return 0;
for (var = gib_locals[gib_subsp]; strcmp(key, var->key); var = var->next)
for (var = GIB_LOCALS; strcmp(key, var->key); var = var->next)
if (!(var->next))
return 0;
return var;
@ -33,9 +32,9 @@ gib_var_t *GIB_Var_FindLocal (char *key)
gib_var_t *GIB_Var_FindGlobal (char *key)
{
gib_var_t *var;
if (!(gib_currentmod[gib_subsp]->vars))
if (!(GIB_CURRENTMOD->vars))
return 0;
for (var = gib_currentmod[gib_subsp]->vars; strcmp(key, var->key); var = var->next)
for (var = GIB_CURRENTMOD->vars; strcmp(key, var->key); var = var->next)
if (!(var->next))
return 0;
return var;
@ -54,8 +53,8 @@ void GIB_Var_Set (char *key, char *value)
var = malloc(sizeof(gib_var_t));
var->key = malloc(strlen(key) + 1);
strcpy(var->key, key);
var->next = gib_locals[gib_subsp];
gib_locals[gib_subsp] = var;
var->next = GIB_LOCALS;
GIB_LOCALS = var;
}
var->value = malloc(strlen(value) + 1);
strcpy(var->value, value);