mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
More of GIB done: builtins, functions, various cleanups, math, etc.
This commit is contained in:
parent
c5192540c8
commit
cf48363c6e
24 changed files with 599 additions and 110 deletions
|
@ -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
|
||||||
|
|
|
@ -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, ...);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
38
include/QF/gib_builtin.h
Normal 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
36
include/QF/gib_function.h
Normal 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);
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
111
libs/util/gib_builtin.c
Normal 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
87
libs/util/gib_function.c
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue