More of GIB done: builtins, functions, various cleanups, math, etc.

This commit is contained in:
Brian Koropoff 2002-08-03 06:04:00 +00:00
parent c5192540c8
commit cf48363c6e
24 changed files with 599 additions and 110 deletions

View file

@ -3,9 +3,10 @@ SUBDIRS = GL plugin
includedir = $(prefix)/include/QF includedir = $(prefix)/include/QF
include_HEADERS = bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \ 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 \ console.h crc.h csqc.h cvar.h dstring.h draw.h gcc_attr.h gib_buffer.h \
gib_parse.h gib_process.h hash.h hl.h idparse.h in_event.h info.h \ gib_builtin.h gib_function.h gib_parse.h gib_process.h hash.h hl.h idparse.h \
input.h joystick.h keys.h link.h locs.h mathlib.h mdfour.h model.h \ in_event.h info.h input.h joystick.h keys.h link.h locs.h mathlib.h \
modelgen.h msg.h pak.h pakfile.h pcx.h plugin.h pr_comp.h pr_debug.h \ mdfour.h model.h modelgen.h msg.h pak.h pakfile.h pcx.h plugin.h \
pr_obj.h progs.h qargs.h qdefs.h qendian.h qfplist.h qtypes.h render.h \ pr_comp.h pr_debug.h pr_obj.h progs.h qargs.h qdefs.h qendian.h \
screen.h sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h texture.h \ qfplist.h qtypes.h render.h screen.h sizebuf.h skin.h sound.h \
tga.h uint32.h va.h ver_check.h vfile.h vfs.h vid.h wad.h zone.h spritegn.h sys.h teamplay.h texture.h tga.h uint32.h va.h ver_check.h \
vfile.h vfs.h vid.h wad.h zone.h

View file

@ -43,13 +43,12 @@ typedef struct cbuf_args_s {
int argv_size; int argv_size;
} cbuf_args_t; } cbuf_args_t;
typedef struct cbuf_s { typedef struct cbuf_s {
struct dstring_s *buf; struct dstring_s *buf;
struct dstring_s *line; struct dstring_s *line;
cbuf_args_t *args; cbuf_args_t *args;
void (*extract_line) (struct cbuf_s *cbuf); struct cbuf_interpreter_s *interpreter;
void (*parse_line) (struct cbuf_s *cbuf);
void (*destructor) (struct cbuf_s *cbuf);
struct cbuf_s *up, *down; // The stack struct cbuf_s *up, *down; // The stack
@ -63,23 +62,28 @@ typedef struct cbuf_s {
void *data; // Pointer to a custom structure if needed void *data; // Pointer to a custom structure if needed
} cbuf_t; } cbuf_t;
typedef struct cbuf_interpreter_s {
void (*extract_line) (struct cbuf_s *cbuf);
void (*parse_line) (struct cbuf_s *cbuf);
void (*execute_line) (struct cbuf_s *cbuf);
void (*construct) (struct cbuf_s *cbuf);
void (*destruct) (struct cbuf_s *cbuf);
} cbuf_interpreter_t;
extern cbuf_t *cbuf_active; extern cbuf_t *cbuf_active;
cbuf_args_t *Cbuf_ArgsNew (void); cbuf_args_t *Cbuf_ArgsNew (void);
void Cbuf_ArgsDelete (cbuf_args_t *); void Cbuf_ArgsDelete (cbuf_args_t *);
void Cbuf_ArgsAdd (cbuf_args_t *args, const char *arg); void Cbuf_ArgsAdd (cbuf_args_t *args, const char *arg);
cbuf_t * Cbuf_New ( cbuf_t * Cbuf_New (cbuf_interpreter_t *interp);
void (*extract) (struct cbuf_s *cbuf),
void (*parse) (struct cbuf_s *cbuf),
void (*construct) (struct cbuf_s *cbuf),
void (*destruct) (struct cbuf_s *cbuf)
);
void Cbuf_Delete (cbuf_t *cbuf); void Cbuf_Delete (cbuf_t *cbuf);
void Cbuf_DeleteStack (cbuf_t *stack);
void Cbuf_AddText (cbuf_t *cbuf, const char *text); void Cbuf_AddText (cbuf_t *cbuf, const char *text);
void Cbuf_InsertText (cbuf_t *cbuf, const char *text); void Cbuf_InsertText (cbuf_t *cbuf, const char *text);
void Cbuf_Execute (cbuf_t *cbuf); void Cbuf_Execute (cbuf_t *cbuf);
void Cbuf_Execute_Stack (cbuf_t *cbuf);
void Cbuf_Execute_Sets (cbuf_t *cbuf); void Cbuf_Execute_Sets (cbuf_t *cbuf);
void Cbuf_Error (const char *class, const char *fmt, ...); void Cbuf_Error (const char *class, const char *fmt, ...);

View file

@ -44,19 +44,19 @@ dstring_t *dstring_new(void);
void dstring_delete (dstring_t *dstr); void dstring_delete (dstring_t *dstr);
void dstring_adjust (dstring_t *dstr); void dstring_adjust (dstring_t *dstr);
void dstring_append (dstring_t *dstr, const char *data, unsigned int len); void dstring_append (dstring_t *dstr, const char *data, unsigned int len);
void dstring_insert(dstring_t *dstr, const char *data, unsigned int len, void dstring_insert (dstring_t *dstr, unsigned int pos, const char *data,
unsigned int pos); unsigned int len);
void dstring_snip (dstring_t *dstr, unsigned int pos, unsigned int len); void dstring_snip (dstring_t *dstr, unsigned int pos, unsigned int len);
void dstring_clear (dstring_t *dstr); void dstring_clear (dstring_t *dstr);
void dstring_replace (dstring_t *dstr, const char *data, unsigned int len, void dstring_replace (dstring_t *dstr, unsigned int pos, unsigned int rlen,
unsigned int pos, unsigned int rlen); const char *data, unsigned int len);
// String-specific functions // String-specific functions
dstring_t *dstring_newstr (void); dstring_t *dstring_newstr (void);
void dstring_appendstr (dstring_t *dstr, const char *str); void dstring_appendstr (dstring_t *dstr, const char *str);
void dstring_appendsubstr (dstring_t *dstr, const char *str, unsigned int len); void dstring_appendsubstr (dstring_t *dstr, const char *str, unsigned int len);
void dstring_insertstr (dstring_t *dstr, const char *str, unsigned int pos); void dstring_insertstr (dstring_t *dstr, unsigned int pos, const char *str);
void dstring_insertsubstr (dstring_t *dstr, const char *str, unsigned int pos, void dstring_insertsubstr (dstring_t *dstr, unsigned int pos, const char *str,
unsigned int len); unsigned int len);
void dstring_clearstr (dstring_t *dstr); void dstring_clearstr (dstring_t *dstr);

View file

@ -32,6 +32,21 @@
typedef struct gib_buffer_data_s { typedef struct gib_buffer_data_s {
struct dstring_s *arg_composite; struct dstring_s *arg_composite;
struct dstring_s *current_token;
// Data for handling return values
struct {
qboolean waiting, available;
unsigned int line_pos; // Position within line
unsigned int token_pos; // Position within token
struct dstring_s *retval; // Returned value
} ret;
enum {
GIB_BUFFER_NORMAL, // Normal buffer
GIB_BUFFER_LOOP, // Looping buffer
GIB_BUFFER_PROXY // Responsible for embedded command
} type;
} gib_buffer_data_t; } gib_buffer_data_t;
void GIB_Buffer_Construct (struct cbuf_s *cbuf); void GIB_Buffer_Construct (struct cbuf_s *cbuf);

38
include/QF/gib_builtin.h Normal file
View file

@ -0,0 +1,38 @@
/*
#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
*/
typedef struct gib_builtin_s {
struct dstring_s *name;
void (*func) (void);
} gib_builtin_t;
void GIB_Builtin_Add (const char *name, void (*func) (void));
gib_builtin_t *GIB_Builtin_Find (const char *name);
void GIB_Builtin_Init (void);

36
include/QF/gib_function.h Normal file
View file

@ -0,0 +1,36 @@
/*
#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
*/
typedef struct gib_function_s {
struct dstring_s *name, *program;
} gib_function_t;
void GIB_Function_Define (const char *name, const char *program);
gib_function_t *GIB_Function_Find (const char *name);

View file

@ -30,3 +30,5 @@
void GIB_Parse_Extract_Line (struct cbuf_s *cbuf); void GIB_Parse_Extract_Line (struct cbuf_s *cbuf);
void GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf); void GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf);
extern struct cbuf_interpreter_s gib_interp;

View file

@ -29,3 +29,5 @@
*/ */
void GIB_Process_Variable (struct dstring_s *token); void GIB_Process_Variable (struct dstring_s *token);
void GIB_Process_Variables_All (struct dstring_s *token);
int GIB_Process_Math (struct dstring_s *token);

View file

@ -32,5 +32,5 @@ extern const char *com_token;
const char *COM_Parse (const char *data); const char *COM_Parse (const char *data);
void COM_TokenizeString (const char *str, cbuf_args_t *args); void COM_TokenizeString (const char *str, cbuf_args_t *args);
void COM_extract_line (cbuf_t *cbuf);
void COM_parse_line (cbuf_t *cbuf); extern struct cbuf_interpreter_s id_interp;

View file

@ -40,7 +40,7 @@ static inline void
check_cbuf (void) check_cbuf (void)
{ {
if (!cbuf) if (!cbuf)
cbuf = Cbuf_New (COM_extract_line, COM_parse_line, NULL, NULL); cbuf = Cbuf_New (&id_interp);
} }
static void static void

View file

@ -50,7 +50,7 @@ static inline void
check_cbuf (void) check_cbuf (void)
{ {
if (!cbuf) if (!cbuf)
cbuf = Cbuf_New (COM_extract_line, COM_parse_line, NULL, NULL); cbuf = Cbuf_New (&id_interp);
} }
/* /*

View file

@ -27,9 +27,9 @@ libQFutil_la_LIBADD= libasm.la $(Z_LIBS) $(DL_LIBS)
libQFutil_la_DEPENDENCIES= libasm.la libQFutil_la_DEPENDENCIES= libasm.la
libQFutil_la_SOURCES= \ libQFutil_la_SOURCES= \
buildnum.c cbuf.c checksum.c cmd.c crc.c cvar.c dstring.c exp.c fendian.c \ 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_parse.c gib_process.c hash.c idparse.c \ getopt.c getopt1.c gib_buffer.c gib_builtin.c gib_function.c gib_parse.c \
info.c link.c mathlib.c mdfour.c msg.c ops.c pakfile.c pcx.c plugin.c qargs.c \ gib_process.c hash.c idparse.c info.c link.c mathlib.c mdfour.c msg.c ops.c \
qendian.c qfplist.c quakefs.c quakeio.c sizebuf.c string.c sys.c tga.c va.c \ pakfile.c pcx.c plugin.c qargs.c qendian.c qfplist.c quakefs.c quakeio.c \
ver_check.c wad.c zone.c $(fnmatch) sizebuf.c string.c sys.c tga.c va.c ver_check.c wad.c zone.c $(fnmatch)
EXTRA_DIST= $(asm_src) $(fnmatch_src) EXTRA_DIST= $(asm_src) $(fnmatch_src)

View file

@ -91,23 +91,16 @@ Cbuf_ArgsAdd (cbuf_args_t *args, const char *arg)
} }
cbuf_t * cbuf_t *
Cbuf_New ( Cbuf_New (cbuf_interpreter_t *interp)
void (*extract) (struct cbuf_s *cbuf),
void (*parse) (struct cbuf_s *cbuf),
void (*construct) (struct cbuf_s *cbuf),
void (*destruct) (struct cbuf_s *cbuf)
)
{ {
cbuf_t *cbuf = calloc (1, sizeof (cbuf_t)); cbuf_t *cbuf = calloc (1, sizeof (cbuf_t));
cbuf->buf = dstring_newstr (); cbuf->buf = dstring_newstr ();
cbuf->line = dstring_newstr (); cbuf->line = dstring_newstr ();
cbuf->args = Cbuf_ArgsNew (); cbuf->args = Cbuf_ArgsNew ();
cbuf->extract_line = extract; cbuf->interpreter = interp;
cbuf->parse_line = parse; if (interp->construct)
cbuf->destructor = destruct; interp->construct (cbuf);
if (construct)
construct (cbuf);
return cbuf; return cbuf;
} }
@ -119,11 +112,22 @@ Cbuf_Delete (cbuf_t *cbuf)
dstring_delete (cbuf->buf); dstring_delete (cbuf->buf);
dstring_delete (cbuf->line); dstring_delete (cbuf->line);
Cbuf_ArgsDelete (cbuf->args); Cbuf_ArgsDelete (cbuf->args);
if (cbuf->destructor) if (cbuf->interpreter->destruct)
cbuf->destructor (cbuf); cbuf->interpreter->destruct (cbuf);
free (cbuf); free (cbuf);
} }
void
Cbuf_DeleteStack (cbuf_t *stack)
{
cbuf_t *next;
for (; stack; stack = next) {
next = stack->down;
Cbuf_Delete (stack);
}
}
void void
Cbuf_AddText (cbuf_t *cbuf, const char *text) Cbuf_AddText (cbuf_t *cbuf, const char *text)
{ {
@ -133,27 +137,25 @@ Cbuf_AddText (cbuf_t *cbuf, const char *text)
void void
Cbuf_InsertText (cbuf_t *cbuf, const char *text) Cbuf_InsertText (cbuf_t *cbuf, const char *text)
{ {
dstring_insertstr (cbuf->buf, "\n", 0); dstring_insertstr (cbuf->buf, 0, "\n");
dstring_insertstr (cbuf->buf, text, 0); dstring_insertstr (cbuf->buf, 0, text);
} }
void void
Cbuf_Execute (cbuf_t *cbuf) Cbuf_Execute (cbuf_t *cbuf)
{ {
cbuf_args_t *args = cbuf->args;
cbuf_active = cbuf; cbuf_active = cbuf;
cbuf->state = CBUF_STATE_NORMAL; cbuf->state = CBUF_STATE_NORMAL;
while (cbuf->buf->str[0]) { while (cbuf->buf->str[0]) {
cbuf->extract_line (cbuf); cbuf->interpreter->extract_line (cbuf);
if (cbuf->state) if (cbuf->state)
break; break;
cbuf->parse_line (cbuf); cbuf->interpreter->parse_line (cbuf);
if (cbuf->state) // Merging extract and parse if (cbuf->state) // Merging extract and parse
break; // will get rid of extra checks break; // will get rid of extra checks
if (!args->argc) if (!cbuf->args->argc)
continue; continue;
Cmd_Command (args); cbuf->interpreter->execute_line (cbuf);
if (cbuf->state) if (cbuf->state)
break; break;
} }
@ -166,6 +168,10 @@ Cbuf_Execute_Stack (cbuf_t *cbuf)
for (sp = cbuf; sp->down; sp = sp->down); for (sp = cbuf; sp->down; sp = sp->down);
while (sp) { while (sp) {
if (sp->down) {
Cbuf_Delete (sp->down);
sp->down = 0;
}
Cbuf_Execute (sp); Cbuf_Execute (sp);
if (sp->state) { if (sp->state) {
if (sp->state == CBUF_STATE_STACK) { if (sp->state == CBUF_STATE_STACK) {
@ -175,13 +181,13 @@ Cbuf_Execute_Stack (cbuf_t *cbuf)
break; break;
else else
return; return;
} }
sp = sp->up; sp = sp->up;
} }
dstring_clearstr (cbuf->buf); dstring_clearstr (cbuf->buf);
for (cbuf = cbuf->down; cbuf; cbuf = sp) { // Reduce, reuse, recycle if (cbuf->down) {
sp = cbuf->down; Cbuf_DeleteStack (cbuf->down);
Cbuf_Delete (cbuf); cbuf->down = 0;
} }
} }
@ -192,8 +198,8 @@ Cbuf_Execute_Sets (cbuf_t *cbuf)
cbuf_active = cbuf; cbuf_active = cbuf;
while (cbuf->buf->str[0]) { while (cbuf->buf->str[0]) {
cbuf->extract_line (cbuf); cbuf->interpreter->extract_line (cbuf);
cbuf->parse_line (cbuf); cbuf->interpreter->parse_line (cbuf);
if (!args->argc) if (!args->argc)
continue; continue;
if (strequal (args->argv[0]->str, "set") if (strequal (args->argv[0]->str, "set")

View file

@ -52,6 +52,7 @@ static const char rcsid[] =
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/vfs.h" #include "QF/vfs.h"
#include "QF/zone.h" #include "QF/zone.h"
#include "QF/gib_builtin.h"
typedef struct cmdalias_s { typedef struct cmdalias_s {
struct cmdalias_s *next; struct cmdalias_s *next;
@ -589,7 +590,11 @@ Cmd_Init (void)
Cmd_AddCommand ("wait", Cmd_Wait_f, "Wait a game tic"); Cmd_AddCommand ("wait", Cmd_Wait_f, "Wait a game tic");
cmd_warncmd = Cvar_Get ("cmd_warncmd", "0", CVAR_NONE, NULL, "Toggles the " cmd_warncmd = Cvar_Get ("cmd_warncmd", "0", CVAR_NONE, NULL, "Toggles the "
"display of error messages for unknown commands"); "display of error messages for unknown commands");
cmd_cbuf = Cbuf_New (COM_extract_line, COM_parse_line, NULL, NULL); cmd_cbuf = Cbuf_New (&id_interp);
// FIXME: GIB should really be initialized elsewhere
GIB_Builtin_Init ();
} }
int int

View file

@ -77,8 +77,8 @@ dstring_append (dstring_t *dstr, const char *data, unsigned int len)
} }
void void
dstring_insert (dstring_t *dstr, const char *data, unsigned int len, dstring_insert (dstring_t *dstr, unsigned int pos, const char *data,
unsigned int pos) unsigned int len)
{ {
unsigned int oldsize = dstr->size; unsigned int oldsize = dstr->size;
@ -104,8 +104,8 @@ dstring_clear (dstring_t *dstr)
} }
void void
dstring_replace (dstring_t *dstr, const char *data, unsigned int len, dstring_replace (dstring_t *dstr, unsigned int pos, unsigned int rlen,
unsigned int pos, unsigned int rlen) const char *data, unsigned int len)
{ {
unsigned int oldsize = dstr->size; unsigned int oldsize = dstr->size;
if (rlen < len) { if (rlen < len) {
@ -158,21 +158,21 @@ dstring_appendsubstr (dstring_t *dstr, const char *str, unsigned int len)
} }
void void
dstring_insertstr (dstring_t *dstr, const char *str, unsigned int pos) dstring_insertstr (dstring_t *dstr, unsigned int pos, const char *str)
{ {
// Don't insert strlen + 1 to achieve concatenation // Don't insert strlen + 1 to achieve concatenation
dstring_insert (dstr, str, strlen (str), pos); dstring_insert (dstr, pos, str, strlen (str));
} }
void void
dstring_insertsubstr (dstring_t *dstr, const char *str, unsigned int pos, dstring_insertsubstr (dstring_t *dstr, unsigned int pos, const char *str,
unsigned int len) unsigned int len)
{ {
unsigned int l = strlen (str); unsigned int l = strlen (str);
if (len > l) if (len > l)
len = l; len = l;
dstring_insert (dstr, str, len, pos); dstring_insert (dstr, pos, str, len);
} }
void void

View file

@ -38,6 +38,7 @@ void GIB_Buffer_Construct (struct cbuf_s *cbuf)
{ {
cbuf->data = calloc (1, sizeof (gib_buffer_data_t)); cbuf->data = calloc (1, sizeof (gib_buffer_data_t));
GIB_DATA (cbuf)->arg_composite = dstring_newstr (); GIB_DATA (cbuf)->arg_composite = dstring_newstr ();
GIB_DATA (cbuf)->current_token = dstring_newstr ();
} }
void GIB_Buffer_Destruct (struct cbuf_s *cbuf) void GIB_Buffer_Destruct (struct cbuf_s *cbuf)

111
libs/util/gib_builtin.c Normal file
View file

@ -0,0 +1,111 @@
/*
#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
*/
#include <stdlib.h>
#include "QF/sys.h"
#include "QF/cmd.h"
#include "QF/cbuf.h"
#include "QF/hash.h"
#include "QF/dstring.h"
#include "QF/gib_builtin.h"
#include "QF/gib_function.h"
hashtab_t *gib_builtins;
const char *
GIB_Builtin_Get_Key (void *ele, void *ptr)
{
return ((gib_builtin_t *)ele)->name->str;
}
void
GIB_Builtin_Free (void *ele, void *ptr)
{
gib_builtin_t *b;
b = (gib_builtin_t *) ele;
dstring_delete (b->name);
free (b);
}
void
GIB_Builtin_Add (const char *name, void (*func) (void))
{
gib_builtin_t *new;
if (!gib_builtins)
gib_builtins = Hash_NewTable (1024, GIB_Builtin_Get_Key, GIB_Builtin_Free, 0);
new = calloc (1, sizeof (gib_builtin_t));
new->func = func;
new->name = dstring_newstr();
dstring_appendstr (new->name, name);
Hash_Add (gib_builtins, new);
}
gib_builtin_t *
GIB_Builtin_Find (const char *name)
{
if (!gib_builtins)
return 0;
return (gib_builtin_t *) Hash_Find (gib_builtins, name);
}
unsigned int
GIB_Argc (void)
{
return cbuf_active->args->argc;
}
const char *
GIB_Argv (unsigned int arg)
{
if (arg < cbuf_active->args->argc)
return cbuf_active->args->argv[arg]->str;
else
return "";
}
void
GIB_Function_f (void)
{
if (GIB_Argc () != 3) {
Cbuf_Error ("numargs",
"function: invalid number of arguments\n"
"usage: function function_name {program}");
} else
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2));
}
void
GIB_Builtin_Init (void)
{
GIB_Builtin_Add ("function", GIB_Function_f);
}

87
libs/util/gib_function.c Normal file
View file

@ -0,0 +1,87 @@
/*
#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
*/
#include <stdlib.h>
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/gib_function.h"
hashtab_t *gib_functions = 0;
gib_function_t *
GIB_Function_New (void)
{
gib_function_t *new = calloc (1, sizeof (gib_function_t));
new->name = dstring_newstr();
new->program = dstring_newstr();
return new;
}
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)
{
gib_function_t *func = (gib_function_t *)ele;
dstring_delete (func->name);
dstring_delete (func->program);
}
void
GIB_Function_Define (const char *name, const char *program)
{
gib_function_t *func;
if (!gib_functions)
gib_functions = Hash_NewTable (1024, GIB_Function_Get_Key, GIB_Function_Free, 0);
func = Hash_Find(gib_functions, name);
if (func)
dstring_clearstr (func->program);
else {
func = GIB_Function_New ();
dstring_appendstr (func->name, name);
Hash_Add (gib_functions, func);
}
dstring_appendstr (func->program, program);
}
gib_function_t *
GIB_Function_Find (const char *name)
{
if (!gib_functions)
return 0;
return (gib_function_t *) Hash_Find (gib_functions, name);
}

View file

@ -33,9 +33,27 @@
#include "QF/sys.h" #include "QF/sys.h"
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/cmd.h"
#include "QF/cbuf.h" #include "QF/cbuf.h"
#include "QF/gib_buffer.h" #include "QF/gib_buffer.h"
#include "QF/gib_process.h" #include "QF/gib_process.h"
#include "QF/gib_builtin.h"
#include "QF/gib_function.h"
// Interpreter structure and prototypes
void GIB_Parse_Extract_Line (cbuf_t *cbuf);
void GIB_Parse_Tokenize_Line (cbuf_t *cbuf);
void GIB_Parse_Execute_Line (cbuf_t *cbuf);
cbuf_interpreter_t gib_interp = {
GIB_Parse_Extract_Line,
GIB_Parse_Tokenize_Line,
GIB_Parse_Execute_Line,
GIB_Buffer_Construct,
GIB_Buffer_Destruct,
};
/* Co-recursive parsing functions */ /* Co-recursive parsing functions */
@ -43,6 +61,8 @@ inline char
GIB_Parse_Match_Dquote (const char *str, unsigned int *i) GIB_Parse_Match_Dquote (const char *str, unsigned int *i)
{ {
for ((*i)++; str[*i]; (*i)++) { for ((*i)++; str[*i]; (*i)++) {
if (str[*i] == '\n')
return '\"'; // Newlines should never occur inside quotes
if (str[*i] == '\"') if (str[*i] == '\"')
return 0; return 0;
} }
@ -68,34 +88,66 @@ GIB_Parse_Match_Brace (const char *str, unsigned int *i)
return '{'; return '{';
} }
inline char
GIB_Parse_Match_Paren (const char *str, unsigned int *i)
{
char c;
for ((*i)++; str[*i]; (*i)++) {
if (str[*i] == '(') {
if ((c = GIB_Parse_Match_Paren (str, i)))
return c;
}
if (str[*i] == ')')
return 0;
}
return '(';
}
void void
GIB_Parse_Extract_Line (struct cbuf_s *cbuf) GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
{ {
int i; int i;
char c; char c;
if (GIB_DATA(cbuf)->ret.waiting) // Not ready for next line
return;
dstring_t *dstr = cbuf->buf; dstring_t *dstr = cbuf->buf;
dstring_clearstr (cbuf->line); dstring_clearstr (cbuf->line);
for (i = 0; dstr->str[i]; i++) { for (i = 0; dstr->str[i]; i++) {
if (dstr->str[i] == '{') { if (dstr->str[i] == '{') {
if ((c = GIB_Parse_Match_Brace (dstr->str, &i))) { if ((c = GIB_Parse_Match_Brace (dstr->str, &i))) {
Cbuf_Error ("parse", "Could not find match for character %c", c); Cbuf_Error ("parse", "Could not find matching %c", c);
return; return;
} }
} } else if (dstr->str[i] == '\"') {
else if (dstr->str[i] == '\n' || dstr->str[i] == ';') if ((c = GIB_Parse_Match_Dquote (dstr->str, &i))) {
Cbuf_Error ("parse", "Could not find matching %c", c);
return;
}
} else if (dstr->str[i] == '\n' || dstr->str[i] == ';')
break; break;
else if (dstr->str[i] == '/' && dstr->str[i+1] == '/') {
char *n;
if ((n = strchr (dstr->str+i, '\n')))
dstring_snip (dstr, i, n-dstr->str);
else {
dstring_snip (dstr, i, strlen(dstr->str+i));
i--; // So we don't go past null
}
}
} }
if (i) { if (dstr->str[0]) {
dstring_insert (cbuf->line, dstr->str, i, 0); if (i) {
Sys_DPrintf ("extracted line: %s\n", cbuf->line->str); dstring_insert (cbuf->line, 0, dstr->str, i);
if (dstr->str[0]) Sys_DPrintf ("extracted line: %s\n", cbuf->line->str);
dstring_snip (dstr, 0, i); }
dstring_snip (dstr, 0, i + (dstr->str[i] == '\n' || dstr->str[i] == ';'));
} }
else
dstring_clearstr (dstr);
return; return;
} }
@ -109,24 +161,32 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr)
n = *i; // Save start position n = *i; // Save start position
if (str[*i] == '\"') { if (str[*i] == '\"') {
if ((c = GIB_Parse_Match_Dquote (str, i))) { if ((c = GIB_Parse_Match_Dquote (str, i))) {
Cbuf_Error ("parse", "Could not find match for character %c", c); Cbuf_Error ("parse", "Could not find matching %c", c);
return 0; // Parse error return 0; // Parse error
} else { } else {
dstring_insert (dstr, str+n+1, *i-n-1, 0); dstring_insert (dstr, 0, str+n+1, *i-n-1);
return '\"'; return '\"';
} }
} else if (str[*i] == '{') { } else if (str[*i] == '{') {
if ((c = GIB_Parse_Match_Brace (str, i))) { if ((c = GIB_Parse_Match_Brace (str, i))) {
Cbuf_Error ("parse", "Could not find match for character %c", c); Cbuf_Error ("parse", "Could not find matching %c", c);
return 0; // Parse error return 0; // Parse error
} else { } else {
dstring_insert (dstr, str+n+1, *i-n-1, 0); dstring_insert (dstr, 0, str+n+1, *i-n-1);
return '{'; return '{';
} }
} else if (str[*i] == '(') {
if ((c = GIB_Parse_Match_Paren (str, i))) {
Cbuf_Error ("parse", "Could not find matching %c", c);
return 0; // Parse error
} else {
dstring_insert (dstr, 0, str+n+1, *i-n-1);
return '\(';
}
} else { } else {
while (str[*i] && !isspace(str[*i]) && str[*i] != ',') // find end of token while (str[*i] && !isspace(str[*i]) && str[*i] != ',') // find end of token
(*i)++; (*i)++;
dstring_insert (dstr, str+n, *i-n, 0); dstring_insert (dstr, 0, str+n, *i-n);
return ' '; return ' ';
} }
return 0; // We should never get here return 0; // We should never get here
@ -140,28 +200,59 @@ GIB_Parse_Generate_Composite (struct cbuf_s *cbuf)
dstring_clearstr (GIB_DATA (cbuf)->arg_composite); dstring_clearstr (GIB_DATA (cbuf)->arg_composite);
for (i = 0; i < args->argc; i++) { for (i = 0; i < args->argc; i++) {
// ->str could be moved by realloc when a dstring is resized
// so save the offset instead of the pointer
args->args[i] = (const char *) strlen (GIB_DATA (cbuf)->arg_composite->str); args->args[i] = (const char *) strlen (GIB_DATA (cbuf)->arg_composite->str);
dstring_appendstr (GIB_DATA (cbuf)->arg_composite, args->argv[i]->str); dstring_appendstr (GIB_DATA (cbuf)->arg_composite, args->argv[i]->str);
dstring_appendstr (GIB_DATA (cbuf)->arg_composite, " "); dstring_appendstr (GIB_DATA (cbuf)->arg_composite, " ");
} }
// Get rid of trailing space
GIB_DATA (cbuf)->arg_composite->str[strlen(GIB_DATA (cbuf)->arg_composite->str)-1] = 0; GIB_DATA (cbuf)->arg_composite->str[strlen(GIB_DATA (cbuf)->arg_composite->str)-1] = 0;
for (i = 0; i < args->argc; i++) for (i = 0; i < args->argc; i++)
// now that arg_composite is done we can add the pointer to the stored
// offsets and get valid pointers. This *should* be portable.
args->args[i] += (unsigned long int) GIB_DATA (cbuf)->arg_composite->str; args->args[i] += (unsigned long int) GIB_DATA (cbuf)->arg_composite->str;
} }
inline void
GIB_Parse_Add_Token (struct cbuf_args_s *args, qboolean cat, dstring_t *token)
{
if (cat) {
dstring_appendstr (args->argv[args->argc-1], token->str);
} else
Cbuf_ArgsAdd (args, token->str);
}
void void
GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf) GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
{ {
dstring_t *arg = dstring_newstr (); dstring_t *arg = GIB_DATA(cbuf)->current_token;
const char *str = cbuf->line->str; const char *str = cbuf->line->str;
cbuf_args_t *args = cbuf->args; cbuf_args_t *args = cbuf->args;
qboolean cat = false; static qboolean cat = false;
char delim; char delim;
int i; int i;
cbuf->args->argc = 0; // This function can be interrupted to call a GIB
// subroutine. First we need to clean up anything
// we left unfinished
for (i = 0;str[i];) { // Do we have a left-over token that needs processing?
if (GIB_DATA(cbuf)->ret.waiting) {
// FIXME: Call processing function here
if (GIB_DATA(cbuf)->ret.waiting) // Still not done?
return;
i = GIB_DATA(cbuf)->ret.line_pos; // Start where we left off
} else {
args->argc = 0; // Start from scratch
i = 0;
cat = false;
}
for (i = 0; str[i];) {
while (isspace(str[i])) // Eliminate whitespace while (isspace(str[i])) // Eliminate whitespace
i++; i++;
if (!str[i]) // Blank token if (!str[i]) // Blank token
@ -175,17 +266,51 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
if (!delim) if (!delim)
break; break;
Sys_DPrintf("Got token: %s\n", arg->str); Sys_DPrintf("Got token: %s\n", arg->str);
if (*arg->str == '$' && delim == ' ')
GIB_Process_Variable (arg); // Global filters -- command sub and var sub
if (cat) {
dstring_appendstr (args->argv[args->argc-1], arg->str); // FIXME: Command sub goes here with subroutine handling
if (delim != '{' && delim != '\"')
GIB_Process_Variables_All (arg);
if (delim == '(')
if (GIB_Process_Math (arg))
goto FILTER_ERROR; // GOTO??!?!?!? AHHHH!
// Add token to list
GIB_Parse_Add_Token (args, cat, arg);
if (cat)
cat = false; cat = false;
} else
Cbuf_ArgsAdd (args, arg->str); if (delim != ' ') // Move into whitespace if we haven't already
if (delim != ' ')
i++; i++;
dstring_clearstr (arg); dstring_clearstr (arg);
} }
dstring_delete (arg);
GIB_Parse_Generate_Composite (cbuf); GIB_Parse_Generate_Composite (cbuf);
return;
FILTER_ERROR: // Error during filtering, clean up mess
dstring_clearstr (arg);
args->argc = 0;
return;
} }
void GIB_Parse_Execute_Line (cbuf_t *cbuf)
{
gib_builtin_t *b;
gib_function_t *f;
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
b->func ();
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
cbuf_t *sub = Cbuf_New (&gib_interp);
Cbuf_AddText (sub, f->program->str);
if (cbuf_active->down)
Cbuf_DeleteStack (cbuf_active->down);
cbuf_active->down = sub;
sub->up = cbuf_active;
cbuf_active->state = CBUF_STATE_STACK;
} else
Cmd_Command (cbuf->args);
}

View file

@ -28,22 +28,64 @@
*/ */
#include <QF/dstring.h> #include <string.h>
#include <QF/cvar.h> #include <ctype.h>
#include "QF/dstring.h"
#include "QF/cbuf.h"
#include "QF/cvar.h"
#include "exp.h"
void void
GIB_Process_Variable (struct dstring_s *token) GIB_Process_Variable (struct dstring_s *dstr)
{ {
int i; int i;
cvar_t *var; cvar_t *var;
for (i = 0; token->str[i] == '$'; i++); for (i = 0; dstr->str[i] == '$'; i++);
i--; i--;
for (; i >= 0; i--) { for (; i >= 0; i--) {
var = Cvar_FindVar (token->str+i+1); var = Cvar_FindVar (dstr->str+i+1);
if (!var) if (!var)
return; return;
token->str[i] = 0; dstr->str[i] = 0;
dstring_appendstr (token, var->string); dstring_appendstr (dstr, var->string);
} }
} }
void
GIB_Process_Variables_All (struct dstring_s *token)
{
int i, n;
dstring_t *var = dstring_newstr ();
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]); n++); // find end of var
dstring_insert (var, 0, token->str+i, n); // extract it
GIB_Process_Variable (var);
dstring_replace (token, i, n, var->str, strlen(var->str));
i += strlen (var->str) - 1;
dstring_clearstr (var);
}
}
}
int
GIB_Process_Math (struct dstring_s *token)
{
double value;
value = EXP_Evaluate (token->str);
if (EXP_ERROR) {
// FIXME: Give real error descriptions
Cbuf_Error ("math", "Expression \"%s\" caused error %i", token->str, EXP_ERROR);
return -1;
} else {
dstring_clearstr (token);
dsprintf (token, "%.10g", value);
}
return 0;
}

View file

@ -32,6 +32,7 @@
#include "QF/dstring.h" #include "QF/dstring.h"
#include "QF/cbuf.h" #include "QF/cbuf.h"
#include "QF/cmd.h"
static dstring_t *_com_token; static dstring_t *_com_token;
const char *com_token; const char *com_token;
@ -68,7 +69,7 @@ skipwhite:
while (1) { while (1) {
c = data[i++]; c = data[i++];
if (c == '"' || !c) { if (c == '"' || !c) {
dstring_insert (_com_token, data, i - 1, 0); dstring_insert (_com_token, 0, data, i - 1);
goto done; goto done;
} }
} }
@ -77,7 +78,7 @@ skipwhite:
do { do {
i++; i++;
} while (data[i] && !isspace ((byte) data[i])); } while (data[i] && !isspace ((byte) data[i]));
dstring_insert (_com_token, data, i, 0); dstring_insert (_com_token, 0, data, i);
done: done:
com_token = _com_token->str; com_token = _com_token->str;
return data + i; return data + i;
@ -140,7 +141,7 @@ COM_extract_line (cbuf_t *cbuf)
break; break;
} }
if (i) if (i)
dstring_insert (cbuf->line, text, i, 0); dstring_insert (cbuf->line, 0, text, i);
if (text[i]) { if (text[i]) {
dstring_snip (cbuf->buf, 0, i + 1); dstring_snip (cbuf->buf, 0, i + 1);
} else { } else {
@ -154,3 +155,17 @@ COM_parse_line (cbuf_t *cbuf)
{ {
COM_TokenizeString (cbuf->line->str, cbuf->args);; COM_TokenizeString (cbuf->line->str, cbuf->args);;
} }
void
COM_execute_line (cbuf_t *cbuf)
{
Cmd_Command (cbuf->args);
}
cbuf_interpreter_t id_interp = {
COM_extract_line,
COM_parse_line,
COM_execute_line,
NULL,
NULL,
};

View file

@ -851,7 +851,7 @@ Host_Init (void)
{ {
Con_Printf ("Host_Init\n"); Con_Printf ("Host_Init\n");
host_cbuf = Cbuf_New (COM_extract_line, COM_parse_line, NULL, NULL); host_cbuf = Cbuf_New (&id_interp);
cmd_source = src_command; cmd_source = src_command;
Cvar_Init_Hash (); Cvar_Init_Hash ();

View file

@ -1663,7 +1663,7 @@ CL_Init_Memory (void)
void void
Host_Init (void) Host_Init (void)
{ {
cl_cbuf = Cbuf_New (COM_extract_line, COM_parse_line, NULL, NULL); cl_cbuf = Cbuf_New (&id_interp);
Cvar_Init_Hash (); Cvar_Init_Hash ();
Cmd_Init_Hash (); Cmd_Init_Hash ();

View file

@ -263,7 +263,7 @@ SV_Error (const char *error, va_list argptr)
inerror = true; inerror = true;
dvsprintf (string, error, argptr); dvsprintf (string, error, argptr);
dstring_insertstr (string, "server crashed: ", 0); dstring_insertstr (string, 0, "server crashed: ");
dstring_appendstr (string, "\n"); dstring_appendstr (string, "\n");
SV_FinalMessage (string->str); SV_FinalMessage (string->str);
@ -1915,7 +1915,7 @@ SV_Frame (float time)
SV_GetConsoleCommands (); SV_GetConsoleCommands ();
// process console commands // process console commands
Cbuf_Execute (sv_cbuf); Cbuf_Execute_Stack (sv_cbuf);
SV_CheckVars (); SV_CheckVars ();
@ -2408,8 +2408,7 @@ SV_Init (void)
// COM_AddParm ("-game"); // COM_AddParm ("-game");
// COM_AddParm ("qw"); // COM_AddParm ("qw");
sv_cbuf = Cbuf_New (GIB_Parse_Extract_Line, GIB_Parse_Tokenize_Line, sv_cbuf = Cbuf_New (&gib_interp);
GIB_Buffer_Construct, GIB_Buffer_Destruct);
sv_args = Cbuf_ArgsNew (); sv_args = Cbuf_ArgsNew ();
Sys_RegisterShutdown (SV_Shutdown); Sys_RegisterShutdown (SV_Shutdown);