Various cleanups and bugfixes. Added proper line number reporting to

errors.  A few new builtin functions, such as slice::find and thread::list.
This commit is contained in:
Brian Koropoff 2003-02-14 08:06:01 +00:00
parent 2cb4c7836d
commit 3c522a83bc
24 changed files with 456 additions and 217 deletions

View file

@ -55,7 +55,8 @@ typedef struct cbuf_s {
CBUF_STATE_NORMAL = 0, // Normal condition
CBUF_STATE_WAIT, // Buffer is stalled until next frame
CBUF_STATE_ERROR, // An unrecoverable error occured
CBUF_STATE_STACK // A buffer has been added to the stack
CBUF_STATE_STACK, // A buffer has been added to the stack
CBUF_STATE_JUNK // Buffer can be freed or reused
} state;
qboolean strict; // Should we tolerate unknown commands?
@ -67,6 +68,7 @@ typedef struct cbuf_s {
typedef struct cbuf_interpreter_s {
void (*construct) (struct cbuf_s *cbuf);
void (*destruct) (struct cbuf_s *cbuf);
void (*reset) (struct cbuf_s *cbuf);
void (*add) (struct cbuf_s *cbuf, const char *str);
void (*insert) (struct cbuf_s *cbuf, const char *str);
void (*execute) (struct cbuf_s *cbuf);
@ -83,12 +85,12 @@ cbuf_t * Cbuf_New (cbuf_interpreter_t *interp);
void Cbuf_Delete (cbuf_t *cbuf);
void Cbuf_DeleteStack (cbuf_t *stack);
void Cbuf_PushStack (cbuf_t *new);
void Cbuf_Reset (cbuf_t *cbuf);
cbuf_t *Cbuf_PushStack (cbuf_interpreter_t *interp);
void Cbuf_AddText (cbuf_t *cbuf, const char *text);
void Cbuf_InsertText (cbuf_t *cbuf, const char *text);
void Cbuf_Execute (cbuf_t *cbuf);
void Cbuf_Execute_Stack (cbuf_t *cbuf);
void Cbuf_Execute_Sets (cbuf_t *cbuf);
void Cbuf_Error (const char *class, const char *fmt, ...);
#endif//__QF_cbuf_h

View file

@ -57,7 +57,7 @@ int Cmd_Argc (void);
const char *Cmd_Argv (int arg);
const char *Cmd_Args (int start);
struct cbuf_args_s;
void Cmd_Command (struct cbuf_args_s *args);
int Cmd_Command (struct cbuf_args_s *args);
int Cmd_ExecuteString (const char *text, cmd_source_t src);
struct cbuf_s;
void Cmd_StuffCmds (struct cbuf_s *cbuf);

View file

@ -29,6 +29,9 @@
$Id$
*/
#ifndef __gib_buffer_h
#define __gib_buffer_h
#include "QF/cbuf.h"
#include "QF/gib_tree.h"
#include "QF/dstring.h"
@ -36,7 +39,13 @@
#define GIB_DATA(buffer) ((gib_buffer_data_t *)(buffer->data))
typedef struct gib_script_s {
const char *text, *file;
unsigned int refs;
} gib_script_t;
typedef struct gib_buffer_data_s {
struct gib_script_s *script;
struct gib_tree_s *program, *ip;
struct dstring_s *arg_composite;
qboolean done, waitret;
@ -51,13 +60,18 @@ typedef struct gib_buffer_data_s {
struct hashtab_s *globals; // Current domain
} gib_buffer_data_t;
void GIB_Buffer_Construct (struct cbuf_s *cbuf);
void GIB_Buffer_Destruct (struct cbuf_s *cbuf);
void GIB_Buffer_Reset (struct cbuf_s *cbuf);
void GIB_Buffer_Set_Program (cbuf_t *cbuf, gib_tree_t *program);
void GIB_Buffer_Add (cbuf_t *cbuf, const char *str);
void GIB_Buffer_Insert (cbuf_t *cbuf, const char *str);
void GIB_Buffer_Push_Sstack (struct cbuf_s *cbuf);
void GIB_Buffer_Pop_Sstack (struct cbuf_s *cbuf);
dstring_t *GIB_Buffer_Dsarray_Get (struct cbuf_s *cbuf);
void GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args);
extern struct cbuf_interpreter_s gib_interp;
#endif // __gib_buffer_h

View file

@ -45,10 +45,13 @@ extern char gib_null_string[];
#define GIB_Argd(x) ((x) < cbuf_active->args->argc ? cbuf_active->args->argv[(x)] : NULL)
#define GIB_Argm(x) ((x) < cbuf_active->args->argc ? (gib_tree_t *)cbuf_active->args->argm[(x)] : NULL)
#define GIB_USAGE(x) (Cbuf_Error ("syntax", "%s: invalid syntax\nusage: %s %s", GIB_Argv(0), GIB_Argv(0), (x)))
#define GIB_USAGE(x) (GIB_Error ("syntax", "%s: invalid syntax\nusage: %s %s", GIB_Argv(0), GIB_Argv(0), (x)))
#define GIB_CanReturn() (GIB_DATA(cbuf_active)->waitret)
void GIB_Arg_Strip_Delim (unsigned int arg);
dstring_t *GIB_Return (const char *str);
void GIB_Error (const char *type, const char *fmt, ...);
void GIB_Builtin_Add (const char *name, void (*func) (void));
gib_builtin_t *GIB_Builtin_Find (const char *name);
void GIB_Builtin_Init (qboolean sandbox);

View file

@ -35,16 +35,18 @@
#include "QF/dstring.h"
#include "QF/hash.h"
#include "QF/gib_tree.h"
#include "QF/gib_buffer.h"
typedef struct gib_function_s {
const char *name;
struct gib_script_s *script;
struct dstring_s *text;
struct gib_tree_s *program;
struct hashtab_s *globals;
qboolean exported;
} gib_function_t;
void GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, hashtab_t *globals);
void GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals);
gib_function_t *GIB_Function_Find (const char *name);
void GIB_Function_Prepare_Args (cbuf_t *cbuf, dstring_t **args, unsigned int argc);
void GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc);

View file

@ -39,7 +39,9 @@ char GIB_Parse_Match_Index (const char *str, unsigned int *i);
char GIB_Parse_Match_Paren (const char *str, unsigned int *i);
char GIB_Parse_Match_Var (const char *str, unsigned int *i);
gib_tree_t *GIB_Parse_Lines (const char *program, unsigned int flags);
gib_tree_t *GIB_Parse_Embedded (const char *program, unsigned int flags, gib_tree_t **embedded);
gib_tree_t *GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags);
gib_tree_t *GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_flags_t flags, gib_tree_t **embedded);
extern qboolean gib_parse_error;
const char *GIB_Parse_ErrorMsg (void);
unsigned int GIB_Parse_ErrorPos (void);

View file

@ -38,6 +38,7 @@ typedef struct gib_thread_s {
unsigned long int id;
struct cbuf_s *cbuf;
struct gib_thread_s *prev, *next;
qboolean trash;
} gib_thread_t;
typedef struct gib_event_s {
@ -55,4 +56,6 @@ int GIB_Event_Register (const char *name, gib_function_t *func);
void GIB_Event_Callback (gib_event_t *event, unsigned int argc, ...);
void GIB_Event_Init (void);
extern gib_thread_t *gib_threads;
#endif

View file

@ -33,23 +33,30 @@
#define __GIB_TREE_H
#define TREE_NORMAL 0 // Normal node
// Flags for tokens
#define TREE_CONCAT 1 // Concatenate to previous
#define TREE_EMBED 2 // Embedded command (expect return value)
#define TREE_P_EMBED 4 // Embedded stuff needs to be processed
#define TREE_ASPLIT 8 // Token is the name of an array that should be split
#define TREE_FUNC 16 // Node is the first in a function
#define TREE_COND 32 // Conditional jump (if or while command)
#define TREE_NOT 64
#define TREE_END 128 // Node ends a loop or conditional
#define TREE_FORNEXT 256 // For loop is starting again
#define TREE_P_EMBED 2 // Embedded stuff needs to be processed
#define TREE_ASPLIT 4 // Token is the name of an array that should be split
// Flags for lines
#define TREE_COND 1 // Conditional jump (if or while command)
#define TREE_NOT 2 // Invert condition
#define TREE_END 4 // Node ends a loop or conditional
#define TREE_FORNEXT 8 // For loop is starting again
#define TREE_EMBED 16 // Embedded command (expect return value)
typedef char gib_tree_flags_t;
typedef struct gib_tree_s {
const char *str;
char delim;
unsigned int start, end, refs;
gib_tree_flags_t flags;
struct gib_tree_s *children, *next, *jump;
unsigned int flags, start, end, refs;
} gib_tree_t;
gib_tree_t *GIB_Tree_New (unsigned int flags);
gib_tree_t *GIB_Tree_New (gib_tree_flags_t flags);
void GIB_Tree_Free_Recursive (gib_tree_t *tree);
void GIB_Tree_Ref (gib_tree_t **tp);
void GIB_Tree_Unref (gib_tree_t **tp);
#endif /* __GIB_TREE_H */

View file

@ -345,12 +345,9 @@ static void
C_GIB_Print_Center_f (void)
{
if (GIB_Argc () != 2) {
Cbuf_Error ("syntax",
"print::center: invalid syntax\n"
"usage: print::center text");
return;
}
SCR_CenterPrint (GIB_Argv(1));
GIB_USAGE ("text");
} else
SCR_CenterPrint (GIB_Argv(1));
}

View file

@ -37,7 +37,9 @@ static __attribute__ ((unused)) const char rcsid[] =
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "QF/sys.h"
#include "QF/dstring.h"
#include "QF/cbuf.h"
#include "QF/hash.h"
@ -65,9 +67,12 @@ GIB_Buffer_Destruct (struct cbuf_s *cbuf)
dstring_delete (g->arg_composite);
if (g->locals)
Hash_DelTable (g->locals);
if (g->program) {
g->program->refs--;
GIB_Tree_Free_Recursive (g->program);
if (g->program)
GIB_Tree_Unref (&g->program);
if (g->script && !(--g->script->refs)) {
free ((void *)g->script->text);
free ((void *)g->script->file);
free (g->script);
}
for (i = 0; i < g->stack.size; i++) {
for (j = 0; j < g->stack.values[i].realsize; j++)
@ -80,12 +85,43 @@ GIB_Buffer_Destruct (struct cbuf_s *cbuf)
free (cbuf->data);
}
void
GIB_Buffer_Reset (struct cbuf_s *cbuf)
{
gib_buffer_data_t *g = GIB_DATA(cbuf);
if (g->locals)
Hash_FlushTable (g->locals);
g->globals = gib_globals;
if (g->program)
GIB_Tree_Unref (&g->program);
if (g->script && !(--g->script->refs)) {
free ((void *) g->script->text);
free ((void *) g->script->file);
free (g->script);
}
g->script = 0;
g->stack.p = 0;
g->waitret = g->done = false;
}
void
GIB_Buffer_Set_Program (cbuf_t *cbuf, gib_tree_t *program)
{
GIB_DATA(cbuf)->program = program;
}
static unsigned int
GIB_Buffer_Get_Line_Num (const char *program, unsigned int pos)
{
unsigned int i, line;
for (i = 0, line = 1; i < pos; i++)
if (program[i] == '\n')
line++;
return line;
}
void
GIB_Buffer_Add (cbuf_t *cbuf, const char *str)
{
@ -97,9 +133,14 @@ GIB_Buffer_Add (cbuf_t *cbuf, const char *str)
save = &cur->next;
} else
save = &g->program;
*save = GIB_Parse_Lines (str, TREE_NORMAL);
if (gib_parse_error)
Cbuf_Error ("parse", "Parse error in program!");
if (!(*save = GIB_Parse_Lines (str, 0, TREE_NORMAL)))
Sys_Printf (
"-----------------\n"
"|GIB Parse Error|\n"
"-----------------\n"
"Parse error while adding text to GIB buffer.\n"
"Line %u: %s\n", GIB_Buffer_Get_Line_Num (str, GIB_Parse_ErrorPos()), GIB_Parse_ErrorMsg()
);
}
void
@ -108,17 +149,21 @@ GIB_Buffer_Insert (cbuf_t *cbuf, const char *str)
gib_buffer_data_t *g = GIB_DATA (cbuf);
gib_tree_t *lines, *cur;
if ((lines = GIB_Parse_Lines (str, TREE_NORMAL))) {
if ((lines = GIB_Parse_Lines (str, 0, TREE_NORMAL))) {
for (cur = lines; cur; cur = cur->next);
//if (g->ip) { // This buffer is already running!
if (g->program)
g->program->refs--;
GIB_Tree_Unref (&g->program);
cur->next = g->program;
g->program = lines;
}
if (gib_parse_error)
Cbuf_Error ("parse", "Parse error in program!");
} else
Sys_Printf (
"-----------------\n"
"|GIB Parse Error|\n"
"-----------------\n"
"Parse error while inserting text into GIB buffer.\n"
"Line %u: %s\n", GIB_Buffer_Get_Line_Num (str, GIB_Parse_ErrorPos()), GIB_Parse_ErrorMsg()
);
}
void
@ -153,9 +198,71 @@ GIB_Buffer_Dsarray_Get (struct cbuf_s *cbuf)
return vals->dstrs[vals->size-1];
}
static int
GIB_Buffer_Get_Line_Info (cbuf_t *cbuf, char **line)
{
const char *text;
unsigned int ofs, i, start, linenum;
// Do we have a copy of the original program this buffer comes from?
if (GIB_DATA(cbuf)->script) {
text = GIB_DATA(cbuf)->script->text;
for (ofs = GIB_DATA(cbuf)->ip->start, start = 0, i = 0, linenum = 1; i <= ofs; i++)
if (text[i] == '\n') {
start = i+1;
linenum++;
}
while (text[i] != '\n')
i++;
*line = malloc (i - start + 1);
memcpy (*line, text+start, i - start);
(*line)[i-start] = 0;
return linenum;
} else {
*line = strdup (GIB_DATA(cbuf)->ip->str);
return -1;
}
}
void
GIB_Buffer_Error (cbuf_t *cbuf, const char *type, const char *fmt, va_list args)
{
char *line;
int linenum;
dstring_t *message = dstring_newstr();
dvsprintf (message, fmt, args);
va_end (args);
Sys_Printf ( "---------------------\n"
"|GIB Execution Error|\n"
"---------------------\n"
"Type: %s\n",
type
);
if ((linenum = GIB_Buffer_Get_Line_Info (cbuf, &line)) != -1)
Sys_Printf ( "%s:%i: %s\n"
"-->%s\n",
GIB_DATA(cbuf)->script->file,
linenum,
message->str,
line
);
else
Sys_Printf ( "%s\n"
"-->%s\n",
message->str,
line
);
cbuf->state = CBUF_STATE_ERROR;
dstring_delete (message);
free (line);
}
cbuf_interpreter_t gib_interp = {
GIB_Buffer_Construct,
GIB_Buffer_Destruct,
GIB_Buffer_Reset,
GIB_Buffer_Add,
GIB_Buffer_Insert,
GIB_Execute,

View file

@ -134,6 +134,16 @@ GIB_Return (const char *str)
return 0;
}
void
GIB_Error (const char *type, const char *fmt, ...)
{
va_list args;
va_start (args, fmt);
GIB_Buffer_Error (cbuf_active, type, fmt, args);
va_end (args);
}
/*
GIB Builtin functions
@ -150,14 +160,14 @@ GIB_Function_f (void)
// Is the function program already tokenized?
if (GIB_Argm (2)->delim != '{') {
// Parse on the fly
if (!(program = GIB_Parse_Lines (GIB_Argv(2), TREE_NORMAL))) {
if (!(program = GIB_Parse_Lines (GIB_Argv(2), 0, TREE_NORMAL))) {
// Error!
Cbuf_Error ("parse", "Parse error while defining function '%s'.", GIB_Argv(1));
GIB_Error ("parse", "Parse error while defining function '%s'.", GIB_Argv(1));
return;
}
} else
program = GIB_Argm (2)->children;
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2), program, GIB_DATA(cbuf_active)->globals);
GIB_Function_Define (GIB_Argv(1), GIB_Argv(2), program, GIB_DATA(cbuf_active)->script, GIB_DATA(cbuf_active)->globals);
}
}
@ -217,6 +227,15 @@ GIB_Domain_f (void)
GIB_DATA(cbuf_active)->globals = GIB_Domain_Get (GIB_Argv(1));
}
static void
GIB_Domain_Clear_f (void)
{
if (GIB_Argc() != 2)
GIB_USAGE ("domain");
else
Hash_FlushTable (GIB_Domain_Get (GIB_Argv(2)));
}
static void
GIB_Return_f (void)
{
@ -259,7 +278,7 @@ static void
GIB_Break_f (void)
{
if (!GIB_DATA(cbuf_active)->ip->jump) {
Cbuf_Error ("loop", "Break command attempted outside of a loop.");
GIB_Error ("loop", "Break command attempted outside of a loop.");
return;
}
if (!GIB_DATA(cbuf_active)->ip->jump->flags & TREE_COND) // In a for loop?
@ -278,7 +297,7 @@ static void
GIB_Continue_f (void)
{
if (!GIB_DATA(cbuf_active)->ip->jump) {
Cbuf_Error ("loop", "Continue command attempted outside of a loop.");
GIB_Error ("loop", "Continue command attempted outside of a loop.");
return;
}
if (GIB_DATA(cbuf_active)->ip->jump->flags & TREE_COND) {
@ -319,10 +338,15 @@ GIB_Function_Export_f (void)
GIB_USAGE ("function1 [function2 function3 ...]");
for (i = 1; i < GIB_Argc(); i++) {
if (!(f = GIB_Function_Find (GIB_Argv (i))))
Cbuf_Error ("function", "function::export: function '%s' not found", GIB_Argv (i));
GIB_Error ("function", "%s: function '%s' not found.", GIB_Argv(0), GIB_Argv (i));
else if (!f->exported) {
Cmd_AddCommand (f->name, GIB_Runexported_f, "Exported GIB function.");
f->exported = true;
if (Cmd_Exists (f->name)) {
GIB_Error ("export", "%s: A console command with the name '%s' already exists.", GIB_Argv(0), GIB_Argv(i));
return;
} else {
Cmd_AddCommand (f->name, GIB_Runexported_f, "Exported GIB function.");
f->exported = true;
}
}
}
}
@ -374,24 +398,22 @@ GIB_Slice_f (void)
}
}
/*
static void
GIB_Find_f (void)
GIB_Slice_Find_f (void)
{
dstring_t *ret;
char *haystack, *res;
char *res;
if (GIB_Argc() != 3) {
GIB_USAGE ("haystack needle");
return;
}
haystack = GIB_Argv(1);
if ((res = strstr(haystack, GIB_Argv(2)))) {
if ((ret = GIB_Return (0)))
dsprintf (ret, "%lu", (unsigned long int)(res - haystack));
} else
GIB_Return ("-1");
} else if (!GIB_CanReturn ())
return;
else if ((res = strstr(GIB_Argv(1), GIB_Argv(2)))) {
dsprintf (GIB_Return (0), "%lu", (unsigned long int)(res - GIB_Argv(1)));
dsprintf (GIB_Return (0), "%lu", (unsigned long int)(res - GIB_Argv(1))+strlen (GIB_Argv(2)));
}
}
*/
static void
GIB_Split_f (void)
@ -431,7 +453,7 @@ GIB_Regex_Match_f (void)
}
if (!(reg = GIB_Regex_Compile (GIB_Argv(2), REG_EXTENDED | GIB_Regex_Translate_Options (GIB_Argv(3)))))
Cbuf_Error ("regex", "%s: %s", GIB_Argv(0), GIB_Regex_Error ());
GIB_Error ("regex", "%s: %s", GIB_Argv(0), GIB_Regex_Error ());
else if (regexec(reg, GIB_Argv(1), 0, 0, 0))
GIB_Return ("0");
else
@ -454,7 +476,7 @@ GIB_Regex_Replace_f (void)
len = strlen (GIB_Argv(4));
if (!(reg = GIB_Regex_Compile (GIB_Argv(2), REG_EXTENDED | GIB_Regex_Translate_Options (GIB_Argv(3)))))
Cbuf_Error ("regex", "%s: %s", GIB_Argv(0), GIB_Regex_Error ());
GIB_Error ("regex", "%s: %s", GIB_Argv(0), GIB_Regex_Error ());
else if (strchr(GIB_Argv(3), 'g'))
while (!regexec(reg, GIB_Argv(1)+ofs, 10, match, ofs > 0 ? REG_NOTBOL : 0) && match[0].rm_eo)
ofs += GIB_Regex_Apply_Match (match, GIB_Argd(1), ofs, GIB_Argv(4));
@ -468,22 +490,20 @@ GIB_Regex_Extract_f (void)
{
regex_t *reg;
regmatch_t *match;
dstring_t *ret;
int i;
char o;
if (GIB_Argc() != 4) {
GIB_USAGE ("string regex options");
return;
}
} else if (!GIB_CanReturn ())
return;
match = calloc (32, sizeof(regmatch_t));
if (!(reg = GIB_Regex_Compile (GIB_Argv(2), REG_EXTENDED | GIB_Regex_Translate_Options (GIB_Argv(3)))))
Cbuf_Error ("regex", "%s: %s", GIB_Argv(0), GIB_Regex_Error ());
GIB_Error ("regex", "%s: %s", GIB_Argv(0), GIB_Regex_Error ());
else if (!regexec(reg, GIB_Argv(1), 32, match, 0) && match[0].rm_eo) {
if (!(ret = GIB_Return(0)))
return;
dsprintf (ret, "%lu", (unsigned long) match[0].rm_eo);
dsprintf (GIB_Return (0), "%lu", (unsigned long) match[0].rm_eo);
for (i = 0; i < 32; i++) {
if (match[i].rm_so != -1) {
o = GIB_Argv(1)[match[i].rm_eo];
@ -492,26 +512,24 @@ GIB_Regex_Extract_f (void)
GIB_Argv(1)[match[i].rm_eo] = o;
}
}
} else
GIB_Return ("-1");
}
free (match);
}
static void
GIB_Thread_Create_f (void)
{
dstring_t *ret;
gib_function_t *f;
if (GIB_Argc() < 2)
GIB_USAGE ("function [arg1 arg2 ...]");
else if (!(f = GIB_Function_Find (GIB_Argv(1))))
Cbuf_Error ("function", "thread::create: no function named '%s' exists.", GIB_Argv(1));
GIB_Error ("function", "%s: no function named '%s' exists.", GIB_Argv(0), GIB_Argv(1));
else {
gib_thread_t *thread = GIB_Thread_New ();
GIB_Function_Execute (thread->cbuf, f, cbuf_active->args->argv+1, cbuf_active->args->argc-1);
GIB_Thread_Add (thread);
if ((ret = GIB_Return (0)))
dsprintf (ret, "%lu", thread->id);
if (GIB_CanReturn ())
dsprintf (GIB_Return(0), "%lu", thread->id);
}
}
@ -522,12 +540,30 @@ GIB_Thread_Kill_f (void)
GIB_USAGE ("id");
else {
gib_thread_t *thread;
cbuf_t *cur;
unsigned long int id = strtoul (GIB_Argv(1), 0, 10);
thread = GIB_Thread_Find (id);
if (!thread) {
Cbuf_Error ("thread", "thread.kill: thread %lu does not exist.", id);
GIB_Error ("thread", "%s: thread %lu does not exist.", GIB_Argv(0), id);
return;
}
thread->trash = true;
// Set error condition on the top of the stack so the thread will exit if currently running
for (cur = thread->cbuf; cur->down && cur->down->state != CBUF_STATE_JUNK; cur = cur->down);
cur->state = CBUF_STATE_ERROR;
GIB_DATA(cur)->done = true;
}
}
static void
GIB_Thread_List_f (void)
{
if (GIB_Argc() != 1)
GIB_USAGE ("");
else if (GIB_CanReturn()) {
gib_thread_t *cur;
for (cur = gib_threads; cur; cur = cur->next)
dsprintf (GIB_Return (0), "%lu", cur->id);
}
}
@ -538,9 +574,9 @@ GIB_Event_Register_f (void)
if (GIB_Argc() != 3)
GIB_USAGE ("event function");
else if (!(func = GIB_Function_Find (GIB_Argv(2))) && GIB_Argv(2)[0])
Cbuf_Error ("function", "Function %s not found.", GIB_Argv(2));
GIB_Error ("function", "Function %s not found.", GIB_Argv(2));
else if (GIB_Event_Register (GIB_Argv(1), func))
Cbuf_Error ("event", "Event %s not found.", GIB_Argv(1));
GIB_Error ("event", "Event %s not found.", GIB_Argv(1));
}
/* File access */
@ -586,13 +622,13 @@ GIB_File_Read_f (void)
return;
}
if (!*GIB_Argv (1)) {
Cbuf_Error ("file",
"file::read: null filename provided");
GIB_Error ("file",
"%s: null filename provided", GIB_Argv(0));
return;
}
if (GIB_File_Transform_Path (GIB_Argd(1))) {
Cbuf_Error ("access",
"file::read: access to %s denied", GIB_Argv(1));
GIB_Error ("access",
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
return;
}
if (!(ret = GIB_Return (0)))
@ -608,8 +644,8 @@ GIB_File_Read_f (void)
Qclose (file);
}
if (!file) {
Cbuf_Error ("file",
"file::read: could not read %s: %s", path, strerror (errno));
GIB_Error ("file",
"%s: could not read %s: %s", GIB_Argv(0), path, strerror (errno));
return;
}
}
@ -625,19 +661,19 @@ GIB_File_Write_f (void)
return;
}
if (!*GIB_Argv(1)) {
Cbuf_Error ("file",
"file::write: null filename provided");
GIB_Error ("file",
"%s: null filename provided", GIB_Argv(0));
return;
}
if (GIB_File_Transform_Path (GIB_Argd(1))) {
Cbuf_Error ("access",
"file::write: access to %s denied", GIB_Argv(1));
GIB_Error ("access",
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
return;
}
path = GIB_Argv(1);
if (!(file = Qopen (path, "w"))) {
Cbuf_Error ("file",
"file::write: could not open %s for writing: %s", path, strerror (errno));
GIB_Error ("file",
"%s: could not open %s for writing: %s", GIB_Argv(0), path, strerror (errno));
return;
}
Qprintf (file, "%s", GIB_Argv (2));
@ -657,8 +693,8 @@ GIB_File_Find_f (void)
return;
}
if (GIB_File_Transform_Path (GIB_Argd(1))) {
Cbuf_Error ("access",
"file::find: access to %s denied", GIB_Argv(1));
GIB_Error ("access",
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
return;
}
path = GIB_Argv(1);
@ -674,8 +710,8 @@ GIB_File_Find_f (void)
}
directory = opendir (path);
if (!directory) {
Cbuf_Error ("file",
"file.find: could not open directory %s: %s", path, strerror (errno));
GIB_Error ("file",
"%s: could not open directory %s: %s", GIB_Argv(0), path, strerror (errno));
return;
}
while ((entry = readdir (directory)))
@ -694,21 +730,19 @@ GIB_File_Move_f (void)
return;
}
if (GIB_File_Transform_Path (GIB_Argd(1))) {
Cbuf_Error ("access",
"file::move: access to %s denied", GIB_Argv(1));
GIB_Error ("access",
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
return;
}
if (GIB_File_Transform_Path (GIB_Argd(2))) {
Cbuf_Error ("access",
"file::move: access to %s denied", GIB_Argv(2));
GIB_Error ("access",
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(2));
return;
}
path1 = GIB_Argv(1);
path2 = GIB_Argv(2);
if (Qrename (path1, path2))
Cbuf_Error ("file",
"file::move: could not move %s to %s: %s",
path1, path2, strerror(errno));
GIB_Error ("file", "%s: could not move %s to %s: %s", GIB_Argv(0), path1, path2, strerror(errno));
}
static void
@ -721,15 +755,13 @@ GIB_File_Delete_f (void)
return;
}
if (GIB_File_Transform_Path (GIB_Argd(1))) {
Cbuf_Error ("access",
"file::delete: access to %s denied", GIB_Argv(1));
GIB_Error ("access",
"%s: access to %s denied", GIB_Argv(0), GIB_Argv(1));
return;
}
path = GIB_Argv (1);
if (Qremove(path))
Cbuf_Error ("file",
"file::delete: could not delete %s: %s",
path, strerror(errno));
GIB_Error ("file", "%s: could not delete %s: %s", GIB_Argv(0), path, strerror(errno));
}
static void
@ -790,6 +822,7 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("local", GIB_Local_f);
GIB_Builtin_Add ("global", GIB_Global_f);
GIB_Builtin_Add ("domain", GIB_Domain_f);
GIB_Builtin_Add ("domain::clear", GIB_Domain_Clear_f);
GIB_Builtin_Add ("return", GIB_Return_f);
GIB_Builtin_Add ("for", GIB_For_f);
GIB_Builtin_Add ("break", GIB_Break_f);
@ -797,12 +830,14 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("length", GIB_Length_f);
GIB_Builtin_Add ("equal", GIB_Equal_f);
GIB_Builtin_Add ("slice", GIB_Slice_f);
GIB_Builtin_Add ("slice::find", GIB_Slice_Find_f);
GIB_Builtin_Add ("split", GIB_Split_f);
GIB_Builtin_Add ("regex::match", GIB_Regex_Match_f);
GIB_Builtin_Add ("regex::replace", GIB_Regex_Replace_f);
GIB_Builtin_Add ("regex::extract", GIB_Regex_Extract_f);
GIB_Builtin_Add ("thread::create", GIB_Thread_Create_f);
GIB_Builtin_Add ("thread::kill", GIB_Thread_Kill_f);
GIB_Builtin_Add ("thread::list", GIB_Thread_List_f);
GIB_Builtin_Add ("event::register", GIB_Event_Register_f);
GIB_Builtin_Add ("file::read", GIB_File_Read_f);
GIB_Builtin_Add ("file::write", GIB_File_Write_f);

View file

@ -207,23 +207,17 @@ GIB_Execute (cbuf_t *cbuf)
else 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 *new = Cbuf_New (&gib_interp);
cbuf->down = new;
new->up = cbuf;
cbuf->state = CBUF_STATE_STACK;
cbuf_t *new = Cbuf_PushStack (&gib_interp);
GIB_Function_Execute (new, f, cbuf->args->argv, cbuf->args->argc);
} else {
GIB_Execute_Generate_Composite (cbuf);
Cmd_Command (cbuf->args);
if (Cmd_Command (cbuf->args))
GIB_Error ("command", "No builtin, function, or console command named '%s' was found.", cbuf->args->argv[0]->str);
}
}
if (!(g->ip = g->ip->next)) // No more commands
g->done = true;
g->done = true;
if (cbuf->state) // Let the stack walker figure out what to do
return;
}
g->done = false;
g->program->refs--;
GIB_Tree_Free_Recursive (g->program);
g->program = g->ip = 0;
}

View file

@ -74,6 +74,7 @@ GIB_Function_Get_Key (void *ele, void *ptr)
{
return ((gib_function_t *)ele)->name;
}
static void
GIB_Function_Free (void *ele, void *ptr)
{
@ -82,6 +83,11 @@ GIB_Function_Free (void *ele, void *ptr)
free ((void *)func->name);
if (func->program)
GIB_Tree_Free_Recursive (func->program);
if (func->script && !(--func->script->refs)) {
free ((void *)func->script->text);
free ((void *)func->script->file);
free (func->script);
}
free (func);
}
@ -93,20 +99,25 @@ GIB_Function_Free (void *ele, void *ptr)
hash if needed.
*/
void
GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, hashtab_t *globals)
GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, gib_script_t *script, hashtab_t *globals)
{
gib_function_t *func;
program->refs++;
GIB_Tree_Ref (&program);
if (script)
script->refs++;
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->text);
func->program->refs--;
GIB_Tree_Free_Recursive (func->program);
GIB_Tree_Unref (&func->program);
if (func->script && !(--func->script->refs)) {
free ((void *)func->script->text);
free ((void *)func->script->file);
free (func->script);
}
} else {
func = GIB_Function_New (name);
Hash_Add (gib_functions, func);
@ -114,6 +125,7 @@ GIB_Function_Define (const char *name, const char *text, gib_tree_t *program, ha
dstring_appendstr (func->text, text);
func->program = program;
func->globals = globals;
func->script = script;
}
/*
@ -162,8 +174,11 @@ GIB_Function_Prepare_Args (cbuf_t *cbuf, dstring_t **args, unsigned int argc)
void
GIB_Function_Execute (cbuf_t *cbuf, gib_function_t *func, dstring_t **args, unsigned int argc)
{
func->program->refs++;
GIB_Tree_Ref (&func->program);
if (func->script)
func->script->refs++;
GIB_Buffer_Set_Program (cbuf, func->program);
GIB_DATA(cbuf)->script = func->script;
GIB_DATA(cbuf)->globals = func->globals;
GIB_Function_Prepare_Args (cbuf, args, argc);
}

View file

@ -36,6 +36,8 @@ static __attribute__ ((unused)) const char rcsid[] =
"$Id$";
#include <string.h>
#include <stdlib.h>
#include "QF/qtypes.h"
#include "QF/cbuf.h"
#include "QF/quakefs.h"
@ -71,14 +73,14 @@ GIB_Exec_Override_f (void) {
Sys_Printf ("execing %s\n", Cmd_Argv (1));
if (!strcmp (Cmd_Argv (1) + strlen (Cmd_Argv(1)) - 4, ".gib") || cbuf_active->interpreter == &gib_interp) {
// 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_t *sub = Cbuf_PushStack (&gib_interp);
GIB_DATA(sub)->script = malloc (sizeof (gib_script_t));
GIB_DATA(sub)->script->file = strdup (Cmd_Argv(1));
GIB_DATA(sub)->script->text = strdup (f);
GIB_DATA(sub)->script->refs = 1;
Cbuf_AddText (sub, f);
//GIB_Parse_Strip_Comments (sub);
if (gib_parse_error && cbuf_active->interpreter == &gib_interp)
GIB_Error ("parse", "%s: Parse error while executing %s.", Cmd_Argv(0), Cmd_Argv(1));
} else
Cbuf_InsertText (cbuf_active, f);
Hunk_FreeToLowMark (mark);

View file

@ -186,14 +186,36 @@ GIB_Parse_Match_Var (const char *str, unsigned int *i)
}
qboolean gib_parse_error;
unsigned int gib_parse_error_pos;
const char *gib_parse_error_msg;
static void
GIB_Parse_Error (const char *msg, unsigned int pos)
{
gib_parse_error = true;
gib_parse_error_msg = msg;
gib_parse_error_pos = pos;
}
const char *
GIB_Parse_ErrorMsg (void)
{
return gib_parse_error_msg;
}
unsigned int
GIB_Parse_ErrorPos (void)
{
return gib_parse_error_pos;
}
// FIXME: Concatenation in stupid circumstances should generate errors
static gib_tree_t *
GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_tree_t **embedded)
GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_tree_flags_t flags, gib_tree_t **embedded)
{
char c, delim, *str;
unsigned int tstart;
unsigned int tstart, start;
gib_tree_t *nodes = 0, *cur, *new, *embs = 0, *tmp;
gib_tree_t **node = &nodes;
qboolean cat = false;
@ -214,7 +236,8 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_
if (!program[*i] || program[*i] == '\n' || program[*i] == ';')
break;
// Save our start position
tstart = *i + 1;
start = *i;
tstart = start + 1;
delim = program[*i];
switch (delim) {
case '{':
@ -250,8 +273,10 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_
}
}
}
c = 0;
cur = *node = GIB_Tree_New (flags);
cur->start = start + pofs;
cur->end = *i + pofs;
cur->delim = delim;
str = calloc (*i - tstart + 1, sizeof(char));
memcpy (str, program+tstart, *i - tstart);
@ -260,12 +285,12 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int flags, gib_
// string would differ from the parsed program.
if (cur->delim == '{' && !cat) {
// Try to parse sub-program
if (!(new = GIB_Parse_Lines (str, flags)))
if (!(new = GIB_Parse_Lines (str, tstart+pofs, flags)))
goto ERROR;
cur->children = new;
// Check for embedded commands/variables
} else if (cur->delim == ' ' || cur->delim == '(') {
if (!(cur->children = GIB_Parse_Embedded (str, flags, &new))) {
if (!(cur->children = GIB_Parse_Embedded (str, tstart+pofs, flags, &new))) {
// There could be no embedded elements, so check for a real error
if (gib_parse_error)
goto ERROR;
@ -305,9 +330,10 @@ DONE:
*embedded = embs;
return nodes;
ERROR:
if (c)
GIB_Parse_Error (va("Could not find match for '%c'.", c), *i+pofs);
if (nodes)
GIB_Tree_Free_Recursive (nodes);
gib_parse_error = true;
return 0;
}
@ -318,8 +344,14 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
unsigned int flags = line->flags;
while (!strcmp (line->children->str, "if") || !strcmp (line->children->str, "ifnot")) {
// Sanity checking
if (!line->children->next || !line->children->next->next || !line->children->next->next->children || line->flags & TREE_EMBED) {
gib_parse_error = true;
if (!line->children->next || !line->children->next->next) {
GIB_Parse_Error ("Not enough arguments to 'if' statement.", line->start);
return line;
} else if (!line->children->next->next->children || line->children->next->next->delim != '{') {
GIB_Parse_Error ("First program block in 'if' statement not enclosed in braces or invalid.", line->start);
return line;
} else if (line->flags & TREE_EMBED) {
GIB_Parse_Error ("'if' statements may not be used in embedded commands.", line->start);
return line;
}
// Set conditional flag
@ -342,7 +374,7 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
if (p->children->next->next->next && !strcmp (p->children->next->next->next->str, "else")) {
// Sanity checking
if (!p->children->next->next->next->next) {
gib_parse_error = true;
GIB_Parse_Error ("'if' statement contains 'else' but no secondary program block or command.", line->start);
return line;
}
// Is "else" followed by a subprogram?
@ -372,12 +404,14 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
// If we have a while loop, handle that
if (!strcmp (line->children->str, "while")) {
// Sanity checks
if (!line->children->next ||
!line->children->next->next ||
line->children->next->next->delim != '{' ||
!line->children->next->next->children ||
line->flags & TREE_EMBED) {
gib_parse_error = true;
if (!line->children->next || !line->children->next->next) {
GIB_Parse_Error ("Not enough arguments to 'while' statement.", line->start);
return line;
} else if (!line->children->next->next->children || line->children->next->next->delim != '{') {
GIB_Parse_Error ("Program block in 'while' statement not enclosed in braces or invalid.", line->start);
return line;
} else if (line->flags & TREE_EMBED) {
GIB_Parse_Error ("'while' statements may not be used in embedded commands.", line->start);
return line;
}
// Set conditional flag
@ -400,19 +434,20 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
gib_tree_t *tmp;
// Sanity checks
if (!line->children->next || !line->children->next->next || strcmp (line->children->next->next->str, "in") || !line->children->next->next->next || !line->children->next->next->next->next) {
gib_parse_error = true;
GIB_Parse_Error ("Malformed 'for' statement.", line->start);
return line;
}
// Find last token in line (contains program block)
for (tmp = line->children->next->next->next->next; tmp->next; tmp = tmp->next);
// More sanity
if (tmp->delim != '{' || !tmp->children) {
gib_parse_error = true;
GIB_Parse_Error ("Program block in 'for' statement not enclosed in braces or invalid.", line->start);
return line;
}
p = line;
// Move subprogram inline
line->next = tmp->children;
tmp->children = 0;
// Find end of subprogram, set jump point back to top of loop as we go
for (; line->next; line = line->next)
if (!line->jump)
@ -427,7 +462,7 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t *line)
}
gib_tree_t *
GIB_Parse_Lines (const char *program, unsigned int flags)
GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags)
{
unsigned int i = 0, lstart;
gib_tree_t *lines = 0, *cur, *tokens, **line = &lines, *embs;
@ -440,13 +475,15 @@ GIB_Parse_Lines (const char *program, unsigned int flags)
break;
lstart = i;
// If we parse something useful...
if ((tokens = GIB_Parse_Tokens (program, &i, flags, &embs))) {
if ((tokens = GIB_Parse_Tokens (program, &i, pofs, flags, &embs))) {
// Link it in
cur = GIB_Tree_New (flags);
cur->delim = '\n';
str = calloc (i - lstart + 1, sizeof(char));
memcpy (str, program+lstart, i - lstart);
cur->str = str;
cur->start = lstart + pofs;
cur->end = i + pofs;
cur->children = tokens;
// Line contains embedded commands?
if (embs) {
@ -470,7 +507,7 @@ ERROR:
}
gib_tree_t *
GIB_Parse_Embedded (const char *program, unsigned int flags, gib_tree_t **embedded)
GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_flags_t flags, gib_tree_t **embedded)
{
unsigned int i, n, t;
char c, d, *str;
@ -500,12 +537,12 @@ GIB_Parse_Embedded (const char *program, unsigned int flags, gib_tree_t **embedd
str = calloc (i - n + 1, sizeof (char));
memcpy (str, program+n, i - n);
cur->str = str;
cur->start = start + pofs;
cur->end = end + pofs;
c = 0;
t = 0;
if (!(tokens = GIB_Parse_Tokens (cur->str, &t, flags, &emb))) {
c = 0;
if (!(tokens = GIB_Parse_Tokens (cur->str, &t, start + pofs, flags, &emb)))
goto ERROR;
}
cur->children = tokens;
GIB_Parse_Semantic_Preprocess (cur)->next = *embedded;
if (gib_parse_error)
@ -561,7 +598,8 @@ GIB_Parse_Embedded (const char *program, unsigned int flags, gib_tree_t **embedd
}
return lines;
ERROR:
gib_parse_error = true;
if (c)
GIB_Parse_Error (va ("Could not find match for '%c'.", c), i + pofs);
if (lines)
GIB_Tree_Free_Recursive (lines);
return 0;

View file

@ -47,6 +47,7 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "QF/gib_parse.h"
#include "QF/gib_vars.h"
#include "QF/gib_process.h"
#include "QF/gib_builtin.h"
#include "exp.h"
@ -63,7 +64,7 @@ GIB_Process_Variable (dstring_t *token, unsigned int *i)
(*i)++;
if (token->str[*i] == '{') {
if ((c = GIB_Parse_Match_Brace (token->str, i))) {
Cbuf_Error ("Parse", "Could not find match for %c.", c);
GIB_Error ("Parse", "Could not find match for %c.", c);
return -1;
}
n += 2;
@ -71,9 +72,10 @@ GIB_Process_Variable (dstring_t *token, unsigned int *i)
} else {
for (; isalnum((byte) token->str[*i]) || token->str[*i] == '_'; (*i)++);
if (token->str[*i] == '[') {
if ((c = GIB_Parse_Match_Index (token->str, i)))
if ((c = GIB_Parse_Match_Index (token->str, i))) {
GIB_Error ("Parse", "Could not find match for %c.", c);
return -1;
else
} else
(*i)++;
}
n++;
@ -119,7 +121,7 @@ GIB_Process_Math (struct dstring_s *token, unsigned int i)
value = EXP_Evaluate (token->str+i);
if (EXP_ERROR) {
Cbuf_Error ("math", "Expression \"%s\" caused an error:\n%s", token->str, EXP_GetErrorMsg());
GIB_Error ("math", "Expression \"%s\" caused an error:\n%s", token->str, EXP_GetErrorMsg());
return -1;
} else {
token->str[i] = 0;

View file

@ -115,12 +115,11 @@ GIB_Thread_Execute (void)
for (cur = gib_threads; cur; cur = tmp) {
tmp = cur->next;
if (GIB_DATA(cur->cbuf)->program)
Cbuf_Execute_Stack (cur->cbuf);
else {
if (cur->trash) {
GIB_Thread_Remove (cur);
GIB_Thread_Delete (cur);
}
} else
Cbuf_Execute_Stack (cur->cbuf);
}
}

View file

@ -38,11 +38,12 @@ static __attribute__ ((unused)) const char rcsid[] =
#include <stdlib.h>
#include <string.h>
#include "QF/sys.h"
#include "QF/qtypes.h"
#include "QF/gib_tree.h"
gib_tree_t *
GIB_Tree_New (unsigned int flags)
GIB_Tree_New (gib_tree_flags_t flags)
{
gib_tree_t *new = calloc (1, sizeof (gib_tree_t));
new->flags = flags;
@ -60,13 +61,30 @@ GIB_Tree_Free_Recursive (gib_tree_t *tree)
return;
for (; tree; tree = n) {
n = tree->next;
if (tree->children) {
if (tree->children)
// Parent is about to bite the dust, meaning one less reference
tree->children->refs--;
GIB_Tree_Free_Recursive (tree->children);
}
GIB_Tree_Unref (&tree->children);
if (tree->str)
free((void *) tree->str);
free(tree);
}
}
void
GIB_Tree_Ref (gib_tree_t **tp)
{
(*tp)->refs++;
Sys_DPrintf ("Ref: %p %u\n", *tp, (*tp)->refs);
}
void
GIB_Tree_Unref (gib_tree_t **tp)
{
Sys_DPrintf ("Unref: %p %u\n", *tp, (*tp)->refs-1);
if (!(--(*tp)->refs)) {
GIB_Tree_Free_Recursive (*tp);
*tp = 0;
}
}

View file

@ -127,13 +127,28 @@ Cbuf_DeleteStack (cbuf_t *stack)
}
void
Cbuf_PushStack (cbuf_t *new)
Cbuf_Reset (cbuf_t *cbuf)
{
if (cbuf_active->down)
Cbuf_DeleteStack (cbuf_active->down);
cbuf->resumetime = 0.0;
cbuf->args->argc = 0;
if (cbuf->interpreter->reset)
cbuf->interpreter->reset (cbuf);
}
cbuf_t *
Cbuf_PushStack (cbuf_interpreter_t *interp)
{
cbuf_t *new;
if (cbuf_active->down) {
new = cbuf_active->down;
Cbuf_Reset (new);
new->state = CBUF_STATE_NORMAL;
} else
new = Cbuf_New (interp);
cbuf_active->down = new;
new->up = cbuf_active;
cbuf_active->state = CBUF_STATE_STACK;
return new;
}
void
@ -167,33 +182,27 @@ Cbuf_Execute_Stack (cbuf_t *cbuf)
else
return;
}
for (sp = cbuf; sp->down; sp = sp->down);
for (sp = cbuf; sp->down && sp->down->state != CBUF_STATE_JUNK; sp = sp->down);
while (sp) {
if (sp->down) {
Cbuf_Delete (sp->down);
sp->down = 0;
}
Cbuf_Execute (sp);
if (sp->state) {
if (sp->state == CBUF_STATE_STACK) {
sp = sp->down;
continue;
} else if (sp->state == CBUF_STATE_ERROR)
goto ERROR;
break;
else
return;
}
}
sp->state = CBUF_STATE_JUNK;
sp = sp->up;
}
return;
ERROR:
if (cbuf->down) {
Cbuf_DeleteStack (cbuf->down);
cbuf->down = 0;
}
// Tear it down and build it back up
cbuf->interpreter->destruct (cbuf);
cbuf->interpreter->construct (cbuf);
Cbuf_Reset (cbuf);
}
void
@ -202,24 +211,3 @@ Cbuf_Execute_Sets (cbuf_t *cbuf)
cbuf->interpreter->execute_sets (cbuf);
}
void
Cbuf_Error (const char *class, const char *fmt, ...)
{
dstring_t *message = dstring_newstr();
va_list args;
va_start (args, fmt);
dvsprintf (message, fmt, args);
va_end (args);
Sys_Printf (
"-----------------------------------\n"
"|Error in command buffer execution|\n"
"-----------------------------------\n"
"Type: %s\n\n"
"%s\n\n",
class,
message->str
);
cbuf_active->state = CBUF_STATE_ERROR;
dstring_delete (message);
}

View file

@ -106,7 +106,7 @@ Cmd_Args (int start)
return cmd_args->args[start];
}
void
int
Cmd_Command (cbuf_args_t *args)
{
cmd_function_t *cmd;
@ -115,7 +115,7 @@ Cmd_Command (cbuf_args_t *args)
//cmd_source = src;
if (!args->argc)
return; // no tokens
return 0; // no tokens
// check functions
cmd = (cmd_function_t *) Hash_Find (cmd_hash, args->argv[0]->str);
@ -123,16 +123,16 @@ Cmd_Command (cbuf_args_t *args)
if (cmd->function) {
cmd->function ();
}
return;
return 0;
}
// check cvars
if (Cvar_Command ())
return;
return 0;
if (cbuf_active->strict)
Cbuf_Error ("command", "Command '%s' not found.", args->argv[0]->str);
return -1;
else if (cmd_warncmd->int_val || developer->int_val)
Sys_Printf ("Unknown command \"%s\"\n", Cmd_Argv (0));
return 0;
}
/* Registers a command and handler function */

View file

@ -68,6 +68,13 @@ COM_destruct (cbuf_t *cbuf)
free(cbuf->data);
}
static void
COM_reset (cbuf_t *cbuf)
{
dstring_clearstr (DATA(cbuf)->buf);
dstring_clearstr (DATA(cbuf)->line);
}
static void
COM_add (cbuf_t *cbuf, const char *str)
{
@ -232,6 +239,7 @@ COM_execute_sets (cbuf_t *cbuf)
cbuf_interpreter_t id_interp = {
COM_construct,
COM_destruct,
COM_reset,
COM_add,
COM_insert,
COM_execute,

View file

@ -681,10 +681,7 @@ Key_GIB_Bind_Get_f (void)
int t, k;
if (GIB_Argc() != 2) {
Cbuf_Error ("syntax",
"bind::get: invalid syntax\n"
"usage: bind::get key"
);
GIB_USAGE ("key");
return;
}
@ -693,12 +690,12 @@ Key_GIB_Bind_Get_f (void)
key = OK_TranslateKeyName (GIB_Argv (1));
if ((t = Key_StringToIMTnum (imt)) == -1) {
Cbuf_Error ("bind", "bind::get: invalid imt %s", imt);
GIB_Error ("bind", "bind::get: invalid imt %s", imt);
return;
}
if ((k = Key_StringToKeynum (key)) == -1) {
Cbuf_Error ("bind", "bind::get: invalid key %s", key);
GIB_Error ("bind", "bind::get: invalid key %s", key);
return;
}

View file

@ -409,9 +409,7 @@ Locs_Loc_Get (void)
location_t *location;
if (GIB_Argc() != 1)
Cbuf_Error ("syntax",
"loc::get: invalid syntax\n"
"usage: loc::get");
GIB_USAGE ("");
else {
location = locs_find (cl.simorg);
GIB_Return (location ? location->name : "unknown");

View file

@ -55,6 +55,10 @@ Carne_Execute_Script (const char *path, cbuf_args_t *args)
if (f[0] == '#')
for (; f[i] != '\n' && f[i+1]; i++);
Cbuf_AddText (mbuf, f+i);
GIB_DATA(mbuf)->script = malloc (sizeof (gib_script_t));
GIB_DATA(mbuf)->script->file = strdup (path);
GIB_DATA(mbuf)->script->text = strdup (f);
GIB_DATA(mbuf)->script->refs = 1;
free (f);
}
Qclose (file);
@ -63,8 +67,11 @@ Carne_Execute_Script (const char *path, cbuf_args_t *args)
return 1;
}
//GIB_Parse_Strip_Comments (mbuf);
if (gib_parse_error)
return 1;
GIB_Function_Prepare_Args (mbuf, args->argv, args->argc);
// Main loop
@ -90,7 +97,8 @@ Carne_Execute_Stdin (void)
while (fgets(linebuf, sizeof(linebuf)-1, stdin)) {
GIB_Thread_Execute ();
Cbuf_AddText (cbuf, linebuf);
Cbuf_Execute_Stack (cbuf);
if (!gib_parse_error)
Cbuf_Execute_Stack (cbuf);
if (carne_done)
break;
}