Adds GIB, an experimental scripting language for QF, and a few compile fixes.

This commit is contained in:
Brian Koropoff 2000-08-28 00:45:40 +00:00
parent 86a0a6aa3e
commit a4a7abb902
17 changed files with 875 additions and 1 deletions

38
include/gib.h Normal file
View file

@ -0,0 +1,38 @@
typedef int (*gib_func_t) (void);
typedef struct gib_var_s
{
char *key;
char *value;
struct gib_var_s *next;
} gib_var_t;
typedef struct gib_sub_s
{
char *name;
char *code;
gib_var_t *vars;
struct gib_sub_s *next;
} gib_sub_t;
typedef struct gib_module_s
{
char *name;
gib_sub_t *subs;
gib_var_t *vars;
struct gib_module_s *next;
} gib_module_t;
typedef struct gib_inst_s
{
char *name;
gib_func_t func;
struct gib_inst_s *next;
} gib_inst_t;
void GIB_Init (void);
void GIB_Gib_f (void);
void GIB_Load_f (void);
void GIB_Stats_f (void);

8
include/gib_error.h Normal file
View file

@ -0,0 +1,8 @@
#define GIB_E_EXIT -2
#define GIB_E_RETURN -1
#define GIB_E_PARSE 6
#define GIB_E_NUMARGS 1
#define GIB_E_ARG 2
#define GIB_E_CALLS 3
#define GIB_E_NOSUB 4
#define GIB_E_NOVAR 5

View file

@ -0,0 +1,7 @@
void GIB_AddInstruction (char *name, gib_func_t func);
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);

19
include/gib_interpret.h Normal file
View file

@ -0,0 +1,19 @@
#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];
char *gib_argv[GIB_MAXCALLS][80];
extern char *GIB_SUBARGV[GIB_MAXSUBARGS];
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_Run_Sub (gib_module_t *mod, gib_sub_t *sub);

7
include/gib_modules.h Normal file
View file

@ -0,0 +1,7 @@
void GIB_Module_Load (char *name, FILE *f);
gib_module_t *GIB_Create_Module (char *name);
gib_sub_t *GIB_Create_Sub (gib_module_t *mod, char *name);
void GIB_Read_Sub (gib_sub_t *sub, FILE *f);
gib_module_t *GIB_Find_Module (char *name);
gib_sub_t *GIB_Find_Sub (gib_module_t *mod, char *name);
void GIB_Stats_f (void);

7
include/gib_parse.h Normal file
View file

@ -0,0 +1,7 @@
int GIB_Get_Inst (char *start);
int GIB_Get_Arg (char *start);
int GIB_End_Quote (char *start);
int GIB_End_DQuote (char *start);
int GIB_End_Bracket (char *start);
gib_sub_t *GIB_Get_ModSub_Sub (char *modsub);
gib_module_t *GIB_Get_ModSub_Mod (char *modsub);

6
include/gib_vars.h Normal file
View file

@ -0,0 +1,6 @@
extern gib_var_t *gib_locals[GIB_MAXCALLS];
gib_var_t *GIB_Var_FindLocal (char *key);
gib_var_t *GIB_Var_FindGlobal (char *key);
void GIB_Var_Set (char *key, char *value);
void GIB_Var_FreeAll (gib_var_t *var);

View file

@ -114,7 +114,8 @@ 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
nonintel.c gib.c gib_instructions.c gib_vars.c \
gib_interpret.c gib_modules.c gib_parse.c
server_SOURCES= host.c host_cmd.c \
pr_cmds.c pr_edict.c pr_exec.c \

81
source/gib.c Normal file
View file

@ -0,0 +1,81 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <ctype.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"
//static char *gib_args;
// Standard cvars
void GIB_Init (void)
{
Cmd_AddCommand("gibload", GIB_Load_f);
Cmd_AddCommand("gibstats", GIB_Stats_f);
Cmd_AddCommand("gib", GIB_Gib_f);
GIB_Init_Instructions ();
}
void GIB_Gib_f (void)
{
gib_sub_t *sub;
gib_module_t *mod;
int i, ret;
if (!(mod = GIB_Get_ModSub_Mod(Cmd_Argv(1))))
{
Con_Printf("Module not found!\n");
return;
}
if (!(sub = GIB_Get_ModSub_Sub(Cmd_Argv(1))))
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);
ret = GIB_Run_Sub(mod, sub);
if (ret != 0)
Con_Printf("Error in execution of %s!\nError code: %i\n", Cmd_Argv(1), ret);
}
}
void GIB_Load_f (void)
{
char filename[256];
FILE *f;
sprintf(filename, "%s/%s.gib", com_gamedir, Cmd_Argv(1));
f = fopen(filename, "r");
if (f)
{
GIB_Module_Load(Cmd_Argv(1), f);
fclose(f);
}
else
Con_Printf("gibload: File not found.\n");
}

106
source/gib_instructions.c Normal file
View file

@ -0,0 +1,106 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <ctype.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"
static gib_inst_t *gibinstructions;
char *gib_subret;
void GIB_AddInstruction (char *name, gib_func_t func)
{
gib_inst_t *new;
new = malloc(sizeof(gib_inst_t));
new->name = malloc(strlen(name) + 1);
new->func = func;
strcpy(new->name, name);
new->next = gibinstructions;
gibinstructions = new;
}
gib_inst_t *GIB_Find_Instruction (char *name)
{
gib_inst_t *inst;
if (!(gibinstructions))
return 0;
for (inst = gibinstructions; strcmp(inst->name, name); inst = inst->next)
if (!(inst->next))
return 0;
return inst;
}
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);
}
int GIB_Echo_f (void)
{
Con_Printf("%s\n",GIB_Argv(1));
return 0;
}
int GIB_Call_f (void)
{
gib_module_t *mod;
gib_sub_t *sub;
int i, ret;
mod = GIB_Get_ModSub_Mod (GIB_Argv(1));
if (!mod)
return GIB_E_NOSUB;
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);
ret = GIB_Run_Sub (mod, sub);
if (gib_subret)
GIB_Var_Set("retval", gib_subret);
gib_subret = 0;
return ret;
}
int GIB_VarPrint_f (void)
{
gib_var_t *var;
int i;
for (i = 1; i <= GIB_Argc(); i++)
{
var = GIB_Var_FindLocal(GIB_Argv(i));
if (!var)
return GIB_E_NOVAR;
Con_Printf("%s", var->value);
}
Con_Printf ("\n");
return 0;
}
int GIB_Return_f (void)
{
if (GIB_Argc() != 1)
return GIB_E_NUMARGS;
gib_subret = malloc(strlen(GIB_Argv(1)) + 1);
strcpy(gib_subret, GIB_Argv(1));
return GIB_E_RETURN; // Signal to block executor to return immediately
}

152
source/gib_interpret.c Normal file
View file

@ -0,0 +1,152 @@
#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"
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];
char *GIB_Argv(int i)
{
return gib_argv[gib_subsp][i];
}
int GIB_Argc(void)
{
return gib_argc[gib_subsp];
}
void GIB_Strip_Arg (char *arg)
{
if (arg[0] == '{' || arg[0] == '\'' || arg[0] == '\"')
{
arg[strlen(arg) - 1] = 0;
memmove(arg, arg + 1, strlen(arg));
}
}
int GIB_Execute_Block (char *block, int retflag)
{
int len, i, ret;
char *code;
i = 0;
while ((len = GIB_Get_Inst(block + i)) > 0)
{
code = malloc(len + 1);
strncpy(code, block + i, len);
code[len] = 0;
if ((ret = GIB_Execute_Inst(code)))
{
if (retflag && ret == GIB_E_RETURN)
return 0;
else
return ret;
}
free (code);
i += len + 1;
}
return 0;
}
int GIB_Execute_Inst (char *inst)
{
char *buffer;
int i, n, len, ret;
gib_inst_t *ginst;
buffer = malloc(strlen(inst) + 1);
i = 0;
while (isspace(inst[i]))
i++;
for (n = 0; i <= strlen(inst); i++)
{
if (inst[i] == '\n' || inst[i] == '\t')
buffer[n] = ' ';
else
buffer[n] = inst[i];
n++;
}
gib_argc[gib_subsp] = 0;
for (i = 0; buffer[i] != ' '; i++);
gib_argv[gib_subsp][0] = malloc(i + 1);
strncpy(gib_argv[gib_subsp][0], buffer, i);
gib_argv[gib_subsp][0][i] = 0;
for (n = 0;;n++)
{
for (;isspace(buffer[i]); i++);
if (buffer[i] == 0)
break;
if ((len = GIB_Get_Arg(buffer + i)) < 0) // Parse error
return len;
else
{
gib_argv[gib_subsp][n + 1] = malloc(len + 1);
strncpy(gib_argv[gib_subsp][n + 1], buffer + i, len);
gib_argv[gib_subsp][n + 1][len] = 0;
i += len;
}
}
gib_argc[gib_subsp] = n;
free(buffer);
for (i = 1; i <= n; i++)
GIB_Strip_Arg (gib_argv[gib_subsp][i]);
if (!(ginst = GIB_Find_Instruction(gib_argv[gib_subsp][0])))
return 1;
ret = ginst->func ();
for (i = 0; i <= n; i++)
free(gib_argv[gib_subsp][i]);
return ret;
}
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++)
{
sprintf(buf, "arg%i", 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--;
return ret;
}

157
source/gib_modules.c Normal file
View file

@ -0,0 +1,157 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <ctype.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"
static gib_module_t *gibmodules;
void GIB_Module_Load (char *name, FILE *f)
{
char line[1024];
gib_module_t *newmod;
gib_sub_t *newsub;
int nameofs;
int namelen;
newmod = GIB_Create_Module(name);
while (fgets(line, 1024, f))
{
if (strncmp("sub", line, 3) == 0)
{
nameofs = 3;
while(isspace(line[nameofs]))
nameofs++;
namelen = 0;
while(!(isspace(line[nameofs+namelen])))
{
namelen++;
}
line[nameofs + namelen] = 0;
newsub = GIB_Create_Sub(newmod, line + nameofs);
GIB_Read_Sub(newsub, f);
}
}
}
gib_module_t *GIB_Create_Module(char *name)
{
gib_module_t *new;
new = malloc(sizeof(gib_module_t));
new->name = malloc(strlen(name) + 1);
strcpy(new->name, name);
new->subs = 0;
new->vars = 0;
new->next = gibmodules;
gibmodules = new;
return new;
}
gib_sub_t *GIB_Create_Sub(gib_module_t *mod, char *name)
{
gib_sub_t *new;
new = malloc(sizeof(gib_sub_t));
new->name = malloc(strlen(name) + 1);
strcpy(new->name, name);
new->code = 0;
new->vars = 0;
new->next = mod->subs;
mod->subs = new;
return new;
}
void GIB_Read_Sub(gib_sub_t *sub, FILE *f)
{
char line[1024];
fpos_t begin;
int sublen = 0;
int insub = 0;
while (fgets(line, 1024, f))
{
if (strncmp("}}", line, 2) == 0 && insub == 1)
{
insub = 0;
break;
}
if (insub == 1)
{
sublen += strlen(line);
}
if (strncmp("{{", line, 2) == 0)
{
fgetpos(f, &begin);
insub = 1;
}
}
sub->code = malloc(sublen + 1);
fsetpos(f, &begin);
fread(sub->code, 1, sublen, f);
sub->code[sublen] = 0;
Con_Printf("Loaded sub %s\n", sub->name);
}
gib_module_t *GIB_Find_Module(char *name)
{
gib_module_t *mod;
if (!(gibmodules))
return 0;
for (mod = gibmodules; strcmp(mod->name, name); mod = mod->next)
if (mod->next == 0)
return 0;
return mod;
}
gib_sub_t *GIB_Find_Sub(gib_module_t *mod, char *name)
{
gib_sub_t *sub;
if (!(mod->subs))
return 0;
for (sub = mod->subs; strcmp(sub->name, name); sub = sub->next)
if (sub->next == 0)
return 0;
return sub;
}
void GIB_Stats_f (void)
{
int modc, subc;
gib_module_t *mod;
gib_sub_t *sub;
modc = 0;
Con_Printf("---=== GIB statistics ===---\n");
for(mod = gibmodules; mod; mod = mod->next)
{
Con_Printf("\nSubroutines for module %s:\n", mod->name);
Con_Printf("-------------------------------------\n");
subc = 0;
for(sub = mod->subs; sub; sub = sub->next)
{
Con_Printf("%s::%s\n", mod->name, sub->name);
subc++;
}
Con_Printf("-------------------------------------\nSubroutines: %i\n", subc);
modc++;
}
Con_Printf("Modules installed: %i\n", modc);
Con_Printf("---=== GIB statistics ===---\n");
}

199
source/gib_parse.c Normal file
View file

@ -0,0 +1,199 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include <ctype.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"
int GIB_Get_Inst(char *start)
{
int i;
int len = 0;
for (i = 0; start[i] != ';'; i++)
{
if (start[i] == '\'')
{
if ((len = GIB_End_Quote(start + i)) < 0)
return len;
else
i += len;
}
if (start[i] == '\"')
{
if ((len = GIB_End_DQuote(start + i)) < 0)
return len;
else
i += len;
}
if (start[i] == '{')
{
if ((len = GIB_End_DQuote(start + i)) < 0)
return len;
else
i += len;
}
if (start[i] == 0)
return 0;
}
return i;
}
int GIB_Get_Arg (char *start)
{
int i;
int len = 0;
for (i = 0; start[i] != ' ' && start[i] != 0; i++)
{
if (start[i] == '\'')
{
if ((len = GIB_End_Quote(start + i)) < 0)
return len;
else
i += len;
}
if (start[i] == '\"')
{
if ((len = GIB_End_DQuote(start + i)) < 0)
return len;
else
i += len;
}
if (start[i] == '{')
{
if ((len = GIB_End_DQuote(start + i)) < 0)
return len;
else
i += len;
}
}
return i;
}
int GIB_End_Quote (char *start)
{
int i;
int len = 0;
for (i = 1; start[i] != '\''; i++)
{
if (start[i] == '\"')
{
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;
}
if (start[i] == 0)
return -1;
}
return i;
}
int GIB_End_DQuote (char *start)
{
int i, ret;
for (i = 1; start[i] != '\"'; i++)
{
if (start[i] == '\'')
{
if ((ret = GIB_End_Quote(start + i)) < 0)
return ret;
else
i += ret;
}
if (start[i] == '{')
{
if ((ret = GIB_End_Bracket(start +i)) < 0)
return ret;
else
i += ret;
}
if (start[i] == 0)
return -2;
}
return i;
}
int GIB_End_Bracket (char *start)
{
int i, ret;
for (i = 1; start[i] != '}'; i++)
{
if (start[i] == '\'')
{
if ((ret = GIB_End_Quote(start + i)) < 0)
return ret;
else
i += ret;
}
if (start[i] == '\"')
{
if ((ret = GIB_End_DQuote(start + i)) < 0)
return ret;
else
i += ret;
}
if (start[i] == '{')
{
if ((ret = GIB_End_Bracket(start + i)) < 0)
return ret;
else
i += ret;
}
if (start[i] == 0)
return -3;
}
return i;
}
gib_sub_t *GIB_Get_ModSub_Sub (char *modsub)
{
gib_module_t *mod;
gib_sub_t *sub;
char *divider;
if (!(divider = strstr(modsub, "::")))
return 0;
*divider = 0;
mod = GIB_Find_Module (modsub);
*divider = ':';
if (!mod)
return 0;
sub = GIB_Find_Sub (mod, divider + 2);
return sub;
}
gib_module_t *GIB_Get_ModSub_Mod (char *modsub)
{
gib_module_t *mod;
char *divider;
if (!(divider = strstr(modsub, "::")))
return 0;
*divider = 0;
mod = GIB_Find_Module (modsub);
*divider = ':';
return mod;
}

76
source/gib_vars.c Normal file
View file

@ -0,0 +1,76 @@
#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"
gib_var_t *gib_locals[GIB_MAXCALLS];
gib_var_t *GIB_Var_FindLocal (char *key)
{
gib_var_t *var;
if (!(gib_locals[gib_subsp]))
return 0;
for (var = gib_locals[gib_subsp]; strcmp(key, var->key); var = var->next)
if (!(var->next))
return 0;
return var;
}
gib_var_t *GIB_Var_FindGlobal (char *key)
{
gib_var_t *var;
if (!(gib_currentmod[gib_subsp]->vars))
return 0;
for (var = gib_currentmod[gib_subsp]->vars; strcmp(key, var->key); var = var->next)
if (!(var->next))
return 0;
return var;
}
void GIB_Var_Set (char *key, char *value)
{
gib_var_t *var;
if ((var = GIB_Var_FindLocal(key)))
{
Con_Printf("Value already found.\n");
free(var->value);
}
else
{
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->value = malloc(strlen(value) + 1);
strcpy(var->value, value);
}
void GIB_Var_FreeAll (gib_var_t *var)
{
gib_var_t *temp;
for (;var; var = temp)
{
temp = var->next;
free(var->key);
free(var->value);
free(var);
}
}

View file

@ -49,6 +49,7 @@
#include "console.h"
#include "sys.h"
#include "screen.h"
#include "gib.h"
/*
@ -889,6 +890,8 @@ void Host_Init (quakeparms_t *parms)
Cbuf_Init ();
Cmd_Init ();
GIB_Init ();
// execute +set as early as possible
Cmd_StuffCmds_f ();
Cbuf_Execute_Sets ();

View file

@ -387,6 +387,9 @@ void PR_ExecuteProgram (func_t fnum)
int exitdepth;
eval_t *ptr;
a = b = c = 0;
st = 0;
if (!fnum || fnum >= progs->numfunctions)
{
if (pr_global_struct->self)

View file

@ -40,6 +40,10 @@
#include <sys/wait.h>
#include <linux/soundcard.h>
#include <stdio.h>
#include "qtypes.h"
#include "console.h"
#include "sound.h"
#include "qargs.h"
int audio_fd;
int snd_inited;