mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-17 01:11:45 +00:00
If and while now work, and embedded commands use backticks instead of <> now
to prevent conflicts with math expressions. All clients and servers are set to create buffers with the normal parser. However, scripts ending in .gib are now executed in a GIB buffer, and the export command can be used to make specific GIB functions available to normal command buffers (i.e. the console).
This commit is contained in:
parent
e56404d242
commit
5c60be3a49
12 changed files with 224 additions and 63 deletions
|
@ -37,17 +37,20 @@ typedef struct gib_local_s {
|
||||||
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;
|
struct dstring_s *current_token;
|
||||||
|
struct dstring_s *loop_program;
|
||||||
|
|
||||||
// Data for handling return values
|
// Data for handling return values
|
||||||
struct {
|
struct {
|
||||||
qboolean waiting, available; // Return value states
|
qboolean waiting, available; // Return value states
|
||||||
|
struct dstring_s *retval; // Returned value
|
||||||
|
|
||||||
// Data saved by tokenizer/processor
|
// Data saved by tokenizer/processor
|
||||||
unsigned int line_pos; // Position within line
|
unsigned int line_pos; // Position within line
|
||||||
unsigned int token_pos; // Position within token
|
unsigned int token_pos; // Position within token
|
||||||
qboolean cat; // Concatenate to previous token?
|
qboolean cat; // Concatenate to previous token?
|
||||||
|
int noprocess; // Process tokens?
|
||||||
char delim; // delimiter of token
|
char delim; // delimiter of token
|
||||||
struct dstring_s *retval; // Returned value
|
|
||||||
} ret;
|
} ret;
|
||||||
|
|
||||||
struct hashtab_s *locals; // Local variables
|
struct hashtab_s *locals; // Local variables
|
||||||
|
|
|
@ -31,13 +31,13 @@
|
||||||
typedef struct gib_builtin_s {
|
typedef struct gib_builtin_s {
|
||||||
struct dstring_s *name;
|
struct dstring_s *name;
|
||||||
void (*func) (void);
|
void (*func) (void);
|
||||||
enum {
|
enum gib_builtin_type_e {
|
||||||
GIB_BUILTIN_NORMAL, // Normal argument processing
|
GIB_BUILTIN_NORMAL = 0, // Normal argument processing
|
||||||
GIB_BUILTIN_NOPROCESS, // Don't process arguments
|
GIB_BUILTIN_NOPROCESS = 1, // Don't process arguments
|
||||||
GIB_BUILTIN_FIRSTONLY, // Process only the first argument
|
GIB_BUILTIN_FIRSTONLY = 2, // Process only the first argument
|
||||||
} type;
|
} type;
|
||||||
} gib_builtin_t;
|
} gib_builtin_t;
|
||||||
|
|
||||||
void GIB_Builtin_Add (const char *name, void (*func) (void));
|
void GIB_Builtin_Add (const char *name, void (*func) (void), enum gib_builtin_type_e type);
|
||||||
gib_builtin_t *GIB_Builtin_Find (const char *name);
|
gib_builtin_t *GIB_Builtin_Find (const char *name);
|
||||||
void GIB_Builtin_Init (void);
|
void GIB_Builtin_Init (void);
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
typedef struct gib_function_s {
|
typedef struct gib_function_s {
|
||||||
struct dstring_s *name, *program;
|
struct dstring_s *name, *program;
|
||||||
|
qboolean exported;
|
||||||
} gib_function_t;
|
} gib_function_t;
|
||||||
|
|
||||||
void GIB_Function_Define (const char *name, const char *program);
|
void GIB_Function_Define (const char *name, const char *program);
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char GIB_Parse_Match_Angle (const char *str, unsigned int *i);
|
char GIB_Parse_Match_Backtick (const char *str, unsigned int *i);
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -53,6 +53,7 @@ static const char rcsid[] =
|
||||||
#include "QF/vfs.h"
|
#include "QF/vfs.h"
|
||||||
#include "QF/zone.h"
|
#include "QF/zone.h"
|
||||||
#include "QF/gib_builtin.h"
|
#include "QF/gib_builtin.h"
|
||||||
|
#include "QF/gib_parse.h"
|
||||||
|
|
||||||
typedef struct cmdalias_s {
|
typedef struct cmdalias_s {
|
||||||
struct cmdalias_s *next;
|
struct cmdalias_s *next;
|
||||||
|
@ -489,9 +490,19 @@ Cmd_Exec_f (void)
|
||||||
if (!Cvar_Command ()
|
if (!Cvar_Command ()
|
||||||
&& (cmd_warncmd->int_val || (developer && developer->int_val)))
|
&& (cmd_warncmd->int_val || (developer && developer->int_val)))
|
||||||
Sys_Printf ("execing %s\n", Cmd_Argv (1));
|
Sys_Printf ("execing %s\n", Cmd_Argv (1));
|
||||||
|
|
||||||
|
if (!strcmp (Cmd_Argv (1) + strlen (Cmd_Argv(1)) - 4, ".gib")) {
|
||||||
|
// GIB script, put it in a new buffer on the stack
|
||||||
|
cbuf_t *sub = Cbuf_New (&gib_interp);
|
||||||
|
if (cbuf_active->down)
|
||||||
|
Cbuf_DeleteStack (cbuf_active->down);
|
||||||
|
cbuf_active->down = sub;
|
||||||
|
sub->up = cbuf_active;
|
||||||
|
cbuf_active->state = CBUF_STATE_STACK;
|
||||||
|
Cbuf_AddText (sub, f);
|
||||||
|
} else
|
||||||
Cbuf_InsertText (cbuf_active, f);
|
Cbuf_InsertText (cbuf_active, f);
|
||||||
Hunk_FreeToLowMark (mark);
|
Hunk_FreeToLowMark (mark);
|
||||||
Cbuf_Execute (cbuf_active);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -99,6 +99,8 @@ void GIB_Buffer_Destruct (struct cbuf_s *cbuf)
|
||||||
{
|
{
|
||||||
dstring_delete (GIB_DATA (cbuf)->arg_composite);
|
dstring_delete (GIB_DATA (cbuf)->arg_composite);
|
||||||
dstring_delete (GIB_DATA (cbuf)->current_token);
|
dstring_delete (GIB_DATA (cbuf)->current_token);
|
||||||
|
if (GIB_DATA (cbuf)->loop_program)
|
||||||
|
dstring_delete (GIB_DATA(cbuf)->loop_program);
|
||||||
dstring_delete (GIB_DATA (cbuf)->ret.retval);
|
dstring_delete (GIB_DATA (cbuf)->ret.retval);
|
||||||
if (GIB_DATA(cbuf)->locals && GIB_DATA(cbuf)->type == GIB_BUFFER_NORMAL)
|
if (GIB_DATA(cbuf)->locals && GIB_DATA(cbuf)->type == GIB_BUFFER_NORMAL)
|
||||||
Hash_DelTable (GIB_DATA(cbuf)->locals);
|
Hash_DelTable (GIB_DATA(cbuf)->locals);
|
||||||
|
|
|
@ -29,12 +29,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "QF/va.h"
|
||||||
#include "QF/sys.h"
|
#include "QF/sys.h"
|
||||||
#include "QF/cmd.h"
|
#include "QF/cmd.h"
|
||||||
#include "QF/cbuf.h"
|
#include "QF/cbuf.h"
|
||||||
#include "QF/hash.h"
|
#include "QF/hash.h"
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
|
#include "QF/gib_parse.h"
|
||||||
#include "QF/gib_builtin.h"
|
#include "QF/gib_builtin.h"
|
||||||
#include "QF/gib_buffer.h"
|
#include "QF/gib_buffer.h"
|
||||||
#include "QF/gib_function.h"
|
#include "QF/gib_function.h"
|
||||||
|
@ -57,7 +60,7 @@ GIB_Builtin_Free (void *ele, void *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GIB_Builtin_Add (const char *name, void (*func) (void))
|
GIB_Builtin_Add (const char *name, void (*func) (void), enum gib_builtin_type_e type)
|
||||||
{
|
{
|
||||||
gib_builtin_t *new;
|
gib_builtin_t *new;
|
||||||
|
|
||||||
|
@ -67,6 +70,7 @@ GIB_Builtin_Add (const char *name, void (*func) (void))
|
||||||
new = calloc (1, sizeof (gib_builtin_t));
|
new = calloc (1, sizeof (gib_builtin_t));
|
||||||
new->func = func;
|
new->func = func;
|
||||||
new->name = dstring_newstr();
|
new->name = dstring_newstr();
|
||||||
|
new->type = type;
|
||||||
dstring_appendstr (new->name, name);
|
dstring_appendstr (new->name, name);
|
||||||
Hash_Add (gib_builtins, new);
|
Hash_Add (gib_builtins, new);
|
||||||
}
|
}
|
||||||
|
@ -94,12 +98,31 @@ GIB_Argv (unsigned int arg)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
GIB_Args (unsigned int arg)
|
||||||
|
{
|
||||||
|
if (arg < cbuf_active->args->argc)
|
||||||
|
return cbuf_active->args->args[arg];
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Arg_Strip_Delim (unsigned int arg)
|
||||||
|
{
|
||||||
|
char *p = cbuf_active->args->argv[arg]->str;
|
||||||
|
if (*p == '{' || *p == '\"') {
|
||||||
|
dstring_snip (cbuf_active->args->argv[arg], 0, 1);
|
||||||
|
p[strlen(p)-1] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GIB_Function_f (void)
|
GIB_Function_f (void)
|
||||||
{
|
{
|
||||||
if (GIB_Argc () != 3)
|
if (GIB_Argc () != 3)
|
||||||
Cbuf_Error ("numargs",
|
Cbuf_Error ("syntax",
|
||||||
"function: invalid number of arguments\n"
|
"function: invalid syntax\n"
|
||||||
"usage: function function_name {program}");
|
"usage: function function_name {program}");
|
||||||
else
|
else
|
||||||
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2));
|
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2));
|
||||||
|
@ -109,8 +132,8 @@ void
|
||||||
GIB_Lset_f (void)
|
GIB_Lset_f (void)
|
||||||
{
|
{
|
||||||
if (GIB_Argc () != 3)
|
if (GIB_Argc () != 3)
|
||||||
Cbuf_Error ("numargs",
|
Cbuf_Error ("syntax",
|
||||||
"lset: invalid number of arguments\n"
|
"lset: invalid syntax\n"
|
||||||
"usage: lset variable value");
|
"usage: lset variable value");
|
||||||
else
|
else
|
||||||
GIB_Local_Set (cbuf_active, GIB_Argv(1), GIB_Argv(2));
|
GIB_Local_Set (cbuf_active, GIB_Argv(1), GIB_Argv(2));
|
||||||
|
@ -119,28 +142,136 @@ GIB_Lset_f (void)
|
||||||
void
|
void
|
||||||
GIB_Return_f (void)
|
GIB_Return_f (void)
|
||||||
{
|
{
|
||||||
|
cbuf_t *sp;
|
||||||
|
|
||||||
if (GIB_Argc () > 2)
|
if (GIB_Argc () > 2)
|
||||||
Cbuf_Error ("numargs",
|
Cbuf_Error ("syntax",
|
||||||
"return: invalid number of arguments\n"
|
"return: invalid syntax\n"
|
||||||
"usage: return <value>");
|
"usage: return <value>");
|
||||||
else {
|
else {
|
||||||
dstring_clearstr (cbuf_active->buf);
|
sp = cbuf_active;
|
||||||
|
while (sp->interpreter == &gib_interp && GIB_DATA(sp)->type == GIB_BUFFER_LOOP) { // Get out of loops
|
||||||
|
GIB_DATA(sp)->type = GIB_BUFFER_PROXY;
|
||||||
|
dstring_clearstr (sp->buf);
|
||||||
|
dstring_clearstr (sp->line);
|
||||||
|
sp = sp->up;
|
||||||
|
}
|
||||||
|
dstring_clearstr (sp->buf);
|
||||||
|
dstring_clearstr (sp->line);
|
||||||
if (GIB_Argc () == 1)
|
if (GIB_Argc () == 1)
|
||||||
return;
|
return;
|
||||||
if (!cbuf_active->up || !cbuf_active->up->up)
|
if (!sp->up || !sp->up->up)
|
||||||
Cbuf_Error ("return","return attempted at top of stack");
|
Cbuf_Error ("stack","return attempted at top of stack");
|
||||||
if (GIB_DATA(cbuf_active->up->up)->ret.waiting) {
|
else if (sp->up->up->interpreter != &gib_interp)
|
||||||
dstring_clearstr (GIB_DATA(cbuf_active->up->up)->ret.retval);
|
Cbuf_Error ("stack","return to non-GIB command buffer attempted");
|
||||||
dstring_appendstr (GIB_DATA(cbuf_active->up->up)->ret.retval, GIB_Argv(1));
|
else if (GIB_DATA(sp->up->up)->ret.waiting) {
|
||||||
GIB_DATA(cbuf_active->up->up)->ret.available = true;
|
dstring_clearstr (GIB_DATA(sp->up->up)->ret.retval);
|
||||||
|
dstring_appendstr (GIB_DATA(sp->up->up)->ret.retval, GIB_Argv(1));
|
||||||
|
GIB_DATA(sp->up->up)->ret.available = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_If_f (void)
|
||||||
|
{
|
||||||
|
int condition;
|
||||||
|
if ((!strcmp (GIB_Argv (3), "else") && GIB_Argc() >= 5) || // if condition {program} else ...
|
||||||
|
(GIB_Argc() == 3)) { // if condition {program}
|
||||||
|
condition = atoi(GIB_Argv(1));
|
||||||
|
if (!strcmp (GIB_Argv(0), "ifnot"))
|
||||||
|
condition = !condition;
|
||||||
|
if (condition) {
|
||||||
|
GIB_Arg_Strip_Delim (2);
|
||||||
|
Cbuf_InsertText (cbuf_active, GIB_Argv(2));
|
||||||
|
} else if (GIB_Argc() == 5) {
|
||||||
|
GIB_Arg_Strip_Delim (4);
|
||||||
|
Cbuf_InsertText (cbuf_active, GIB_Argv(4));
|
||||||
|
} else if (GIB_Argc() > 5)
|
||||||
|
Cbuf_InsertText (cbuf_active, GIB_Args (4));
|
||||||
|
} else
|
||||||
|
Cbuf_Error ("syntax",
|
||||||
|
"if: invalid syntax\n"
|
||||||
|
"usage: if condition {program} [else ...]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_While_f (void)
|
||||||
|
{
|
||||||
|
if (GIB_Argc() != 3) {
|
||||||
|
Cbuf_Error ("syntax",
|
||||||
|
"while: invalid syntax\n"
|
||||||
|
"usage: while condition {program}"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
cbuf_t *sub = Cbuf_New (&gib_interp);
|
||||||
|
GIB_DATA(sub)->type = GIB_BUFFER_LOOP;
|
||||||
|
GIB_DATA(sub)->locals = GIB_DATA(cbuf_active)->locals;
|
||||||
|
GIB_DATA(sub)->loop_program = dstring_newstr ();
|
||||||
|
if (cbuf_active->down)
|
||||||
|
Cbuf_DeleteStack (cbuf_active->down);
|
||||||
|
cbuf_active->down = sub;
|
||||||
|
sub->up = cbuf_active;
|
||||||
|
GIB_Arg_Strip_Delim (2);
|
||||||
|
dstring_appendstr (GIB_DATA(sub)->loop_program, va("ifnot %s break\n%s", GIB_Argv (1), GIB_Argv (2)));
|
||||||
|
Cbuf_AddText (sub, GIB_DATA(sub)->loop_program->str);
|
||||||
|
cbuf_active->state = CBUF_STATE_STACK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Break_f (void)
|
||||||
|
{
|
||||||
|
if (GIB_DATA(cbuf_active)->type != GIB_BUFFER_LOOP)
|
||||||
|
Cbuf_Error ("syntax",
|
||||||
|
"break attempted outside of a loop"
|
||||||
|
);
|
||||||
|
else {
|
||||||
|
GIB_DATA(cbuf_active)->type = GIB_BUFFER_PROXY; // If we set it to normal locals will get freed
|
||||||
|
dstring_clearstr (cbuf_active->buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Runexported_f (void)
|
||||||
|
{
|
||||||
|
gib_function_t *f;
|
||||||
|
|
||||||
|
if (!(f = GIB_Function_Find (Cmd_Argv (0))))
|
||||||
|
Sys_Printf ("Error: No function found for exported command \"%s\".\n"
|
||||||
|
"This is most likely a bug, please report it to"
|
||||||
|
"The QuakeForge developers.", Cmd_Argv(0));
|
||||||
|
else
|
||||||
|
GIB_Function_Execute (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GIB_Export_f (void)
|
||||||
|
{
|
||||||
|
gib_function_t *f;
|
||||||
|
|
||||||
|
if (GIB_Argc() != 2)
|
||||||
|
Cbuf_Error ("syntax",
|
||||||
|
"export: invalid syntax\n"
|
||||||
|
"usage: export function");
|
||||||
|
else if (!(f = GIB_Function_Find (GIB_Argv (1))))
|
||||||
|
Cbuf_Error ("existance", "export: function '%s' not found", GIB_Argv (1));
|
||||||
|
else if (!f->exported) {
|
||||||
|
Cmd_AddCommand (f->name->str, GIB_Runexported_f, "Exported GIB function.");
|
||||||
|
f->exported = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GIB_Builtin_Init (void)
|
GIB_Builtin_Init (void)
|
||||||
{
|
{
|
||||||
GIB_Builtin_Add ("function", GIB_Function_f);
|
GIB_Builtin_Add ("function", GIB_Function_f, GIB_BUILTIN_NORMAL);
|
||||||
GIB_Builtin_Add ("lset", GIB_Lset_f);
|
GIB_Builtin_Add ("export", GIB_Export_f, GIB_BUILTIN_NORMAL);
|
||||||
GIB_Builtin_Add ("return", GIB_Return_f);
|
GIB_Builtin_Add ("lset", GIB_Lset_f, GIB_BUILTIN_NORMAL);
|
||||||
|
GIB_Builtin_Add ("return", GIB_Return_f, GIB_BUILTIN_NORMAL);
|
||||||
|
GIB_Builtin_Add ("if", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
|
||||||
|
GIB_Builtin_Add ("ifnot", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
|
||||||
|
GIB_Builtin_Add ("while", GIB_While_f, GIB_BUILTIN_NOPROCESS);
|
||||||
|
GIB_Builtin_Add ("break", GIB_Break_f, GIB_BUILTIN_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,29 +96,25 @@ GIB_Parse_Match_Paren (const char *str, unsigned int *i)
|
||||||
return c;
|
return c;
|
||||||
} else if (str[*i] == ')')
|
} else if (str[*i] == ')')
|
||||||
return 0;
|
return 0;
|
||||||
|
else if (str[*i] == '\n') // Newlines in math == bad
|
||||||
|
return '(';
|
||||||
}
|
}
|
||||||
return '(';
|
return '(';
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
GIB_Parse_Match_Angle (const char *str, unsigned int *i)
|
GIB_Parse_Match_Backtick (const char *str, unsigned int *i)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
for ((*i)++; str[*i]; (*i)++) {
|
for ((*i)++; str[*i]; (*i)++) {
|
||||||
if (str[*i] == '>')
|
if (str[*i] == '`')
|
||||||
return 0;
|
return 0;
|
||||||
else if (str[*i] == '<') {
|
else if (str[*i] == '\"') { // Skip over strings
|
||||||
if ((c = GIB_Parse_Match_Angle (str, i))) // Embedded inside embedded
|
|
||||||
return c;
|
|
||||||
} else if (str[*i] == '(') { // Skip over math expressions to avoid < and >
|
|
||||||
if ((c = GIB_Parse_Match_Paren (str, i)))
|
|
||||||
return c;
|
|
||||||
} else if (str[*i] == '\"') { // Skip over strings
|
|
||||||
if ((c = GIB_Parse_Match_Dquote (str, i)))
|
if ((c = GIB_Parse_Match_Dquote (str, i)))
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return '<';
|
return '`';
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -145,11 +141,6 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (dstr->str[i] == '<') {
|
|
||||||
if ((c = GIB_Parse_Match_Angle (dstr->str, &i))) {
|
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (dstr->str[i] == '\n' || dstr->str[i] == ';')
|
} else if (dstr->str[i] == '\n' || dstr->str[i] == ';')
|
||||||
break;
|
break;
|
||||||
else if (dstr->str[i] == '/' && dstr->str[i+1] == '/') {
|
else if (dstr->str[i] == '/' && dstr->str[i+1] == '/') {
|
||||||
|
@ -171,12 +162,15 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
||||||
dstring_snip (dstr, 0, i + (dstr->str[i] == '\n' || dstr->str[i] == ';'));
|
dstring_snip (dstr, 0, i + (dstr->str[i] == '\n' || dstr->str[i] == ';'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (GIB_DATA(cbuf)->type == GIB_BUFFER_LOOP && !dstr->str[0])
|
||||||
|
Cbuf_AddText (cbuf, GIB_DATA(cbuf)->loop_program->str);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static char
|
inline static char
|
||||||
GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr)
|
GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr, qboolean include_delim)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
char c;
|
char c;
|
||||||
|
@ -187,7 +181,7 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr)
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return 0; // Parse error
|
return 0; // Parse error
|
||||||
} else {
|
} else {
|
||||||
dstring_insert (dstr, 0, str+n+1, *i-n-1);
|
dstring_insert (dstr, 0, str+n+!include_delim, *i-n+1-!include_delim-!include_delim);
|
||||||
return '\"';
|
return '\"';
|
||||||
}
|
}
|
||||||
} else if (str[*i] == '{') {
|
} else if (str[*i] == '{') {
|
||||||
|
@ -195,7 +189,7 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr)
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return 0; // Parse error
|
return 0; // Parse error
|
||||||
} else {
|
} else {
|
||||||
dstring_insert (dstr, 0, str+n+1, *i-n-1);
|
dstring_insert (dstr, 0, str+n+!include_delim, *i-n+1-!include_delim-!include_delim);
|
||||||
return '{';
|
return '{';
|
||||||
}
|
}
|
||||||
} else if (str[*i] == '(') {
|
} else if (str[*i] == '(') {
|
||||||
|
@ -203,13 +197,13 @@ GIB_Parse_Get_Token (const char *str, unsigned int *i, dstring_t *dstr)
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return 0; // Parse error
|
return 0; // Parse error
|
||||||
} else {
|
} else {
|
||||||
dstring_insert (dstr, 0, str+n+1, *i-n-1);
|
dstring_insert (dstr, 0, str+n+!include_delim, *i-n+1-!include_delim-!include_delim);
|
||||||
return '\(';
|
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
|
||||||
if (str[*i] == '<') {
|
if (str[*i] == '`') {
|
||||||
if ((c = GIB_Parse_Match_Angle (str, i))) {
|
if ((c = GIB_Parse_Match_Backtick (str, i))) {
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return 0; // Parse error
|
return 0; // Parse error
|
||||||
}
|
}
|
||||||
|
@ -262,6 +256,7 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||||
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;
|
qboolean cat = false;
|
||||||
|
int noprocess;
|
||||||
char delim;
|
char delim;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -276,9 +271,11 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||||
return; // Still not done, or error
|
return; // Still not done, or error
|
||||||
GIB_Parse_Add_Token (cbuf->args, GIB_DATA(cbuf)->ret.cat, arg);
|
GIB_Parse_Add_Token (cbuf->args, GIB_DATA(cbuf)->ret.cat, arg);
|
||||||
i = GIB_DATA(cbuf)->ret.line_pos; // Start tokenizing where we left off
|
i = GIB_DATA(cbuf)->ret.line_pos; // Start tokenizing where we left off
|
||||||
|
noprocess = GIB_DATA(cbuf)->ret.noprocess ? 1 : 0; // Past second token, no sense in having it be 2
|
||||||
} else {
|
} else {
|
||||||
args->argc = 0; // Start from scratch
|
args->argc = 0; // Start from scratch
|
||||||
i = 0;
|
i = 0;
|
||||||
|
noprocess = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (str[i]) {
|
while (str[i]) {
|
||||||
|
@ -292,41 +289,55 @@ GIB_Parse_Tokenize_Line (struct cbuf_s *cbuf)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
dstring_clearstr (arg);
|
dstring_clearstr (arg);
|
||||||
delim = GIB_Parse_Get_Token (str, &i, arg);
|
delim = GIB_Parse_Get_Token (str, &i, arg, noprocess == 1);
|
||||||
if (!delim)
|
if (!delim)
|
||||||
break;
|
break;
|
||||||
Sys_DPrintf("Got token: %s\n", arg->str);
|
Sys_DPrintf("Got token: %s\n", arg->str);
|
||||||
|
if (delim != ' ') // Move into whitespace if we haven't already
|
||||||
|
i++;
|
||||||
|
|
||||||
|
if (noprocess != 1)
|
||||||
if (GIB_Process_Token (arg, delim))
|
if (GIB_Process_Token (arg, delim))
|
||||||
goto FILTER_ERROR; // Error or GIB subroutine needs to be called
|
goto FILTER_ERROR; // Error or GIB subroutine needs to be called
|
||||||
|
|
||||||
|
if (noprocess > 1)
|
||||||
|
noprocess--;
|
||||||
|
|
||||||
GIB_Parse_Add_Token (cbuf->args, cat, arg);
|
GIB_Parse_Add_Token (cbuf->args, cat, arg);
|
||||||
if (cat)
|
if (cat)
|
||||||
cat = false;
|
cat = false;
|
||||||
|
|
||||||
if (delim != ' ') // Move into whitespace if we haven't already
|
|
||||||
i++;
|
if (cbuf->args->argc == 1) {
|
||||||
|
gib_builtin_t *b;
|
||||||
|
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
|
||||||
|
noprocess = b->type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GIB_Parse_Generate_Composite (cbuf);
|
GIB_Parse_Generate_Composite (cbuf);
|
||||||
dstring_clearstr (cbuf->line);
|
|
||||||
return;
|
return;
|
||||||
FILTER_ERROR:
|
FILTER_ERROR:
|
||||||
GIB_DATA(cbuf)->ret.line_pos = i; // save our information in case
|
GIB_DATA(cbuf)->ret.line_pos = i; // save our information in case
|
||||||
GIB_DATA(cbuf)->ret.cat = cat; // error is not fatal
|
GIB_DATA(cbuf)->ret.cat = cat; // error is not fatal
|
||||||
GIB_DATA(cbuf)->ret.delim = delim;
|
GIB_DATA(cbuf)->ret.delim = delim;
|
||||||
|
GIB_DATA(cbuf)->ret.noprocess = noprocess;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GIB_Parse_Execute_Line (cbuf_t *cbuf)
|
void GIB_Parse_Execute_Line (cbuf_t *cbuf)
|
||||||
{
|
{
|
||||||
|
cbuf_args_t *args = cbuf->args;
|
||||||
gib_builtin_t *b;
|
gib_builtin_t *b;
|
||||||
gib_function_t *f;
|
gib_function_t *f;
|
||||||
|
|
||||||
if ((b = GIB_Builtin_Find (cbuf->args->argv[0]->str)))
|
if ((b = GIB_Builtin_Find (args->argv[0]->str)))
|
||||||
b->func ();
|
b->func ();
|
||||||
else if ((f = GIB_Function_Find (cbuf->args->argv[0]->str))) {
|
else if ((f = GIB_Function_Find (args->argv[0]->str)))
|
||||||
GIB_Function_Execute (f);
|
GIB_Function_Execute (f);
|
||||||
} else
|
else if (args->argc == 3 && !strcmp (args->argv[1]->str, "="))
|
||||||
|
GIB_Local_Set (cbuf, args->argv[0]->str, args->argv[2]->str);
|
||||||
|
else
|
||||||
Cmd_Command (cbuf->args);
|
Cmd_Command (cbuf->args);
|
||||||
|
dstring_clearstr (cbuf->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,9 @@ GIB_Process_Variables_All (struct dstring_s *token)
|
||||||
for (i = 0; token->str[i]; i++) {
|
for (i = 0; token->str[i]; i++) {
|
||||||
if (token->str[i] == '$') {
|
if (token->str[i] == '$') {
|
||||||
for (n = 1; token->str[i+n] == '$'; n++); // get past $s
|
for (n = 1; token->str[i+n] == '$'; n++); // get past $s
|
||||||
for (; isalnum(token->str[i+n]); n++); // find end of var
|
for (; isalnum(token->str[i+n]) ||
|
||||||
|
token->str[i+n] == '.' ||
|
||||||
|
token->str[i+n] == '_'; n++); // find end of var
|
||||||
dstring_insert (var, 0, token->str+i, n); // extract it
|
dstring_insert (var, 0, token->str+i, n); // extract it
|
||||||
GIB_Process_Variable (var);
|
GIB_Process_Variable (var);
|
||||||
dstring_replace (token, i, n, var->str, strlen(var->str));
|
dstring_replace (token, i, n, var->str, strlen(var->str));
|
||||||
|
@ -114,9 +116,9 @@ GIB_Process_Embedded (struct dstring_s *token)
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
for (; token->str[i]; i++) {
|
for (; token->str[i]; i++) {
|
||||||
if (token->str[i] == '<') {
|
if (token->str[i] == '`') {
|
||||||
n = i;
|
n = i;
|
||||||
if ((c = GIB_Parse_Match_Angle (token->str, &i))) {
|
if ((c = GIB_Parse_Match_Backtick (token->str, &i))) {
|
||||||
Cbuf_Error ("parse", "Could not find matching %c", c);
|
Cbuf_Error ("parse", "Could not find matching %c", c);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -607,7 +607,7 @@ _Host_Frame (float time)
|
||||||
|
|
||||||
// process console commands
|
// process console commands
|
||||||
cmd_source = src_command;
|
cmd_source = src_command;
|
||||||
Cbuf_Execute (host_cbuf);
|
Cbuf_Execute_Stack (host_cbuf);
|
||||||
|
|
||||||
NET_Poll ();
|
NET_Poll ();
|
||||||
|
|
||||||
|
|
|
@ -1535,7 +1535,7 @@ Host_Frame (float time)
|
||||||
IN_Commands ();
|
IN_Commands ();
|
||||||
|
|
||||||
// process console commands
|
// process console commands
|
||||||
Cbuf_Execute (cl_cbuf);
|
Cbuf_Execute_Stack (cl_cbuf);
|
||||||
|
|
||||||
// fetch results from server
|
// fetch results from server
|
||||||
CL_ReadPackets ();
|
CL_ReadPackets ();
|
||||||
|
|
|
@ -2408,7 +2408,7 @@ SV_Init (void)
|
||||||
// COM_AddParm ("-game");
|
// COM_AddParm ("-game");
|
||||||
// COM_AddParm ("qw");
|
// COM_AddParm ("qw");
|
||||||
|
|
||||||
sv_cbuf = Cbuf_New (&gib_interp);
|
sv_cbuf = Cbuf_New (&id_interp);
|
||||||
sv_args = Cbuf_ArgsNew ();
|
sv_args = Cbuf_ArgsNew ();
|
||||||
|
|
||||||
Sys_RegisterShutdown (SV_Shutdown);
|
Sys_RegisterShutdown (SV_Shutdown);
|
||||||
|
|
Loading…
Reference in a new issue