Cleaned up the GIB parser and GIB_Execute() a lot. Made aliases work in

GIB.  Added some breakpoint GIB builtins for debugging script/intepreter
interactions.  Made carne work properly again (local variables don't
disappear in interactive mode)
This commit is contained in:
Brian Koropoff 2003-02-25 06:52:27 +00:00
parent 1201f615ee
commit c9fbb334f1
9 changed files with 226 additions and 178 deletions

View file

@ -39,8 +39,8 @@ 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 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);
gib_tree_t *GIB_Parse_Lines (const char *program, unsigned int pofs);
gib_tree_t *GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_t **embedded);
extern qboolean gib_parse_error;
const char *GIB_Parse_ErrorMsg (void);

View file

@ -33,16 +33,14 @@
#define __GIB_TREE_H
#define TREE_NORMAL 0 // Normal node
// Flags for tokens
#define TREE_CONCAT 1 // Concatenate to previous
#define TREE_P_EMBED 2 // Embedded stuff needs to be processed
#define TREE_SPLIT 4 // Token is the name of an array that should be split
// Flags for arguments
#define TREE_A_CONCAT 1 // Concatenate to previous
#define TREE_A_EMBED 2 // Embedded stuff needs to be processed
#define TREE_A_EXPAND 4 // Token needs to be expanded
// 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)
#define TREE_L_NOT 1 // Invert condition
#define TREE_L_FORNEXT 4 // For loop is starting again
#define TREE_L_EMBED 8 // Embedded command (expect return value)
typedef char gib_tree_flags_t;
@ -51,10 +49,20 @@ typedef struct gib_tree_s {
char delim;
unsigned int start, end, refs;
gib_tree_flags_t flags;
enum gib_tree_type_e {
TREE_T_CMD, // A command
TREE_T_COND, // Conditional jump
TREE_T_ASSIGN, // Assignment
TREE_T_JUMP, // Jump
TREE_T_JUMPPLUS, // Jump, go to next instruction
TREE_T_ARG, // Argument (not a line)
TREE_T_FORNEXT, // Fetch next arg in for loop
TREE_T_META // Info node
} type;
struct gib_tree_s *children, *next, *jump;
} gib_tree_t;
gib_tree_t *GIB_Tree_New (gib_tree_flags_t flags);
gib_tree_t *GIB_Tree_New (enum gib_tree_type_e type);
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);

View file

@ -48,6 +48,7 @@ const char rcsid[] = "$Id$";
#include "QF/gib_tree.h"
#include "QF/gib_vars.h"
#include "QF/gib_execute.h"
#include "QF/idparse.h"
void
GIB_Buffer_Construct (struct cbuf_s *cbuf)
@ -101,7 +102,7 @@ GIB_Buffer_Reset (struct cbuf_s *cbuf)
free (g->script);
}
g->script = 0;
g->program = 0;
g->program = g->ip = 0;
g->stack.p = 0;
g->waitret = g->done = false;
@ -130,12 +131,30 @@ GIB_Buffer_Add (cbuf_t * cbuf, const char *str)
gib_buffer_data_t *g = GIB_DATA (cbuf);
gib_tree_t **save, *cur;
if (g->program) {
// AddText should only be used to populate a buffer before
// executing it and shouldn't happen to a running GIB buffer,
// but if it does, try to find somewhere else to put the text.
if (g->ip) {
for (;cbuf; cbuf = cbuf->up)
if (cbuf->interpreter == &id_interp) {
Cbuf_AddText (cbuf, str);
return;
}
Sys_Printf (
"-------------\n"
"|GIB Warning|\n"
"-------------\n"
"Text added to running GIB buffer discarded.\n"
"Text: %s\n",
str
);
return;
} else if (g->program) {
for (cur = g->program; cur->next; cur = cur->next);
save = &cur->next;
} else
save = &g->program;
if (!(*save = GIB_Parse_Lines (str, 0, TREE_NORMAL)))
if (!(*save = GIB_Parse_Lines (str, 0)))
Sys_Printf (
"-----------------\n"
"|GIB Parse Error|\n"
@ -153,11 +172,18 @@ 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, 0, TREE_NORMAL))) {
// No GIB builtin should ever insert text into a running
// GIB buffer, so create an idparse buffer to handle the
// legacy console code.
if (g->ip) {
cbuf_t *new = Cbuf_New (&id_interp);
new->up = cbuf;
cbuf->down = new;
cbuf->state = CBUF_STATE_STACK;
Cbuf_InsertText (new, str);
return;
} else if ((lines = GIB_Parse_Lines (str, 0))) {
for (cur = lines; cur; cur = cur->next);
// if (g->ip) { // This buffer is already running!
GIB_Tree_Unref (&g->program);
cur->next = g->program;
g->program = lines;
} else

View file

@ -164,7 +164,7 @@ 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), 0, TREE_NORMAL))) {
if (!(program = GIB_Parse_Lines (GIB_Argv (2), 0))) {
// Error!
GIB_Error ("parse", "Parse error while defining function '%s'.",
GIB_Argv (1));
@ -304,10 +304,6 @@ GIB_For_f (void)
dstring_t *dstr;
unsigned int i;
if (GIB_Argc () < 5) {
GIB_DATA (cbuf_active)->ip = GIB_DATA (cbuf_active)->ip->jump;
return;
}
GIB_Buffer_Push_Sstack (cbuf_active);
dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
dstring_clearstr (dstr);
@ -316,43 +312,6 @@ GIB_For_f (void)
dstr = GIB_Buffer_Dsarray_Get (cbuf_active);
dstring_appendstr (dstr, GIB_Argv (i));
}
GIB_Execute_For_Next (cbuf_active);
}
static void
GIB_Break_f (void)
{
if (!GIB_DATA (cbuf_active)->ip->jump) {
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?
GIB_Buffer_Pop_Sstack (cbuf_active); // Kill it
GIB_DATA (cbuf_active)->ip = GIB_DATA (cbuf_active)->ip->jump->jump;
}
static gib_tree_t gib_cont = {
"",
' ',
0, 0, 0, 0,
TREE_NORMAL
};
static void
GIB_Continue_f (void)
{
if (!GIB_DATA (cbuf_active)->ip->jump) {
GIB_Error ("loop", "Continue command attempted outside of a loop.");
return;
}
if (GIB_DATA (cbuf_active)->ip->jump->flags & TREE_COND) {
gib_cont.next = GIB_DATA (cbuf_active)->ip->jump;
GIB_DATA (cbuf_active)->ip = &gib_cont;
} else {
GIB_Execute_For_Next (cbuf_active);
GIB_DATA (cbuf_active)->ip = GIB_DATA (cbuf_active)->ip->jump;
}
}
// Note: this is a standard console command, not a GIB builtin
@ -910,6 +869,26 @@ GIB_Print_f (void)
Sys_Printf ("%s", GIB_Argv (1));
}
static void
GIB_bp1_f (void)
{
}
static void
GIB_bp2_f (void)
{
}
static void
GIB_bp3_f (void)
{
}
static void
GIB_bp4_f (void)
{
}
void
GIB_Builtin_Init (qboolean sandbox)
{
@ -929,8 +908,6 @@ GIB_Builtin_Init (qboolean sandbox)
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);
GIB_Builtin_Add ("continue", GIB_Continue_f);
GIB_Builtin_Add ("length", GIB_Length_f);
GIB_Builtin_Add ("equal", GIB_Equal_f);
GIB_Builtin_Add ("count", GIB_Count_f);
@ -952,4 +929,8 @@ GIB_Builtin_Init (qboolean sandbox)
GIB_Builtin_Add ("file::delete", GIB_File_Delete_f);
GIB_Builtin_Add ("range", GIB_Range_f);
GIB_Builtin_Add ("print", GIB_Print_f);
GIB_Builtin_Add ("bp1", GIB_bp1_f);
GIB_Builtin_Add ("bp2", GIB_bp2_f);
GIB_Builtin_Add ("bp3", GIB_bp3_f);
GIB_Builtin_Add ("bp4", GIB_bp4_f);
}

View file

@ -144,15 +144,15 @@ GIB_Execute_Prepare_Line (cbuf_t * cbuf, gib_tree_t * line)
args->argc = 0;
for (cur = line->children; cur; cur = cur->next) {
if (cur->flags & TREE_CONCAT) {
if (cur->flags & TREE_A_CONCAT) {
pos = args->argv[args->argc - 1]->size - 1;
if (cur->flags & TREE_P_EMBED) {
if (cur->flags & TREE_A_EMBED) {
GIB_Process_Embedded (cur, cbuf->args);
} else
dstring_appendstr (args->argv[args->argc - 1], cur->str);
} else {
pos = 0;
if (cur->flags & TREE_P_EMBED) {
if (cur->flags & TREE_A_EMBED) {
Cbuf_ArgsAdd (args, "");
GIB_Process_Embedded (cur, cbuf->args);
} else
@ -162,7 +162,7 @@ GIB_Execute_Prepare_Line (cbuf_t * cbuf, gib_tree_t * line)
if (cur->delim == '('
&& GIB_Process_Math (args->argv[args->argc - 1], pos))
return -1;
if (cur->flags & TREE_SPLIT)
if (cur->flags & TREE_A_EXPAND)
GIB_Execute_Split_Var (cbuf);
}
return 0;
@ -177,7 +177,7 @@ GIB_Execute_For_Next (cbuf_t * cbuf)
GIB_DATA (cbuf)->stack.values + GIB_DATA (cbuf)->stack.p - 1;
if (array->size == 1) {
GIB_Buffer_Pop_Sstack (cbuf);
return 0;
return -1;
}
array->size--;
var =
@ -186,7 +186,7 @@ GIB_Execute_For_Next (cbuf_t * cbuf)
&index, true);
dstring_clearstr (var->array[index].value);
dstring_appendstr (var->array[index].value, array->dstrs[array->size]->str);
return 1;
return 0;
}
void
@ -195,63 +195,73 @@ GIB_Execute (cbuf_t * cbuf)
gib_buffer_data_t *g = GIB_DATA (cbuf);
gib_builtin_t *b;
gib_function_t *f;
double cond;
unsigned int index;
gib_var_t *var;
if (!g->program)
return;
if (!g->ip)
g->ip = g->program;
while (!g->done) {
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
return;
if (g->ip->flags & TREE_COND) {
cond = g->ip->flags & TREE_NOT ?
atof (cbuf->args->argv[1]->str) :
!atof (cbuf->args->argv[1]->str);
if (cond)
g->ip = g->ip ? g->ip->next : g->program;
while (g->ip) {
switch (g->ip->type) {
case TREE_T_JUMP:
g->ip = g->ip->jump;
} else if (g->ip->flags & TREE_FORNEXT) {
if (GIB_Execute_For_Next (cbuf))
g->ip = g->ip->jump;
} else if (g->ip->flags & TREE_END) {
g->ip = g->ip->jump;
if (g->ip->flags & TREE_COND)
continue;
} else if (cbuf->args->argc) {
if (g->ip->flags & TREE_EMBED) {
// Get ready for return values
g->waitret = true;
GIB_Buffer_Push_Sstack (cbuf);
} else
g->waitret = false;
if (cbuf->args->argc >= 2 && !strcmp (cbuf->args->argv[1]->str, "=")
&& ((gib_tree_t *) cbuf->args->argm[1])->delim == ' ') {
unsigned int index;
gib_var_t *var =
GIB_Var_Get_Complex (&g->locals, &g->globals,
cbuf->args->argv[0]->str, &index,
true);
GIB_Var_Assign (var, index, cbuf->args->argv + 2,
cbuf->args->argc - 2);
} 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_PushStack (&gib_interp);
GIB_Function_Execute (new, f, cbuf->args->argv,
cbuf->args->argc);
} else {
GIB_Execute_Generate_Composite (cbuf);
if (Cmd_Command (cbuf->args))
GIB_Error ("command",
"No builtin, function, or console command named '%s' was found.",
cbuf->args->argv[0]->str);
}
case TREE_T_JUMPPLUS:
g->ip = g->ip->jump->next;
continue;
case TREE_T_FORNEXT:
if (GIB_Execute_For_Next (cbuf))
g->ip = g->ip->jump->next;
else
g->ip = g->ip->next;
continue;
case TREE_T_COND:
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
return;
if (g->ip->flags & TREE_L_NOT ? atof (cbuf->args->argv[1]->str) : !atof (cbuf->args->argv[1]->str))
g->ip = g->ip->jump->next;
else
g->ip = g->ip->next;
continue;
case TREE_T_ASSIGN:
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
return;
var = GIB_Var_Get_Complex (&g->locals, &g->globals, cbuf->args->argv[0]->str, &index, true);
GIB_Var_Assign (var, index, cbuf->args->argv + 2, cbuf->args->argc - 2);
g->ip = g->ip->next;
continue;
case TREE_T_CMD:
if (GIB_Execute_Prepare_Line (cbuf, g->ip))
return;
else if (cbuf->args->argc) {
if (g->ip->flags & TREE_L_EMBED) {
// Get ready for return values
g->waitret = true;
GIB_Buffer_Push_Sstack (cbuf);
} else
g->waitret = false;
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_PushStack (&gib_interp);
GIB_Function_Execute (new, f, cbuf->args->argv, cbuf->args->argc);
} else {
GIB_Execute_Generate_Composite (cbuf);
if (Cmd_Command (cbuf->args))
GIB_Error (
"command",
"No builtin, function, or console command named '%s' was found.",
cbuf->args->argv[0]->str
);
}
if (cbuf->state)
return;
g->ip = g->ip->next;
}
continue;
default:
GIB_Error ("QUAKEFORGE-BUG-PLEASE-REPORT", "Unknown instruction type; tastes like chicken.");
return;
}
if (!(g->ip = g->ip->next)) // No more commands
g->done = true;
if (cbuf->state) // Let the stack walker figure out what
// to do
return;
}
g->ip = g->program = 0;
g->script = 0;
}

View file

@ -218,8 +218,7 @@ GIB_Parse_ErrorPos (void)
// FIXME: Concatenation in stupid circumstances should generate errors
static gib_tree_t *
GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs,
gib_tree_flags_t flags, gib_tree_t ** embedded)
GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs, gib_tree_t ** embedded)
{
char c, delim, *str;
unsigned int tstart, start;
@ -284,33 +283,29 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs,
}
}
c = 0;
cur = *node = GIB_Tree_New (flags);
cur = *node = GIB_Tree_New (TREE_T_ARG);
cur->start = start + pofs;
cur->end = *i + pofs;
cur->delim = delim;
str = calloc (*i - tstart + 1, sizeof (char));
memcpy (str, program + tstart, *i - tstart);
// Don't bother parsing further if we are concatenating, as the
// resulting
// string would differ from the parsed program.
if (cur->delim == '{' && !cat) {
if (cur->delim == '{') {
// Try to parse sub-program
if (!(new = GIB_Parse_Lines (str, tstart + pofs, flags)))
if (!(new = GIB_Parse_Lines (str, tstart + pofs)))
goto ERROR;
cur->children = new;
// Check for embedded commands/variables
} else if (cur->delim == ' ' || cur->delim == '(') {
if (!
(cur->children =
GIB_Parse_Embedded (str, tstart + pofs, flags, &new))) {
GIB_Parse_Embedded (str, tstart + pofs, &new))) {
// There could be no embedded elements, so check for a real
// error
if (gib_parse_error)
goto ERROR;
} else {
// Link/set flags
cur->flags |= TREE_P_EMBED;
cur->flags |= TREE_A_EMBED;
// Add any embedded commands to top of chain
if (new) {
for (tmp = new; tmp->next; tmp = tmp->next);
@ -321,7 +316,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs,
// Check for array splitting
// Concatenating this onto something else is non-sensical
if (cur->delim == ' ' && (str[0] == '@' || str[0] == '%') && !cat) {
cur->flags |= TREE_SPLIT;
cur->flags |= TREE_A_EXPAND;
}
// We can handle escape characters now
} else if (cur->delim == '\"')
@ -329,7 +324,7 @@ GIB_Parse_Tokens (const char *program, unsigned int *i, unsigned int pofs,
cur->str = str;
if (cat) {
cur->flags |= TREE_CONCAT;
cur->flags |= TREE_A_CONCAT;
cat = false;
}
// Nothing left to parse?
@ -355,7 +350,6 @@ static gib_tree_t *
GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
{
gib_tree_t *p, *start = line;
unsigned int flags = line->flags;
while (!strcmp (line->children->str, "if")
|| !strcmp (line->children->str, "ifnot")) {
@ -370,16 +364,16 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
("First program block in 'if' statement not enclosed in braces or invalid.",
line->start);
return line;
} else if (line->flags & TREE_EMBED) {
} else if (line->flags & TREE_L_EMBED) {
GIB_Parse_Error
("'if' statements may not be used in embedded commands.",
line->start);
return line;
}
// Set conditional flag
line->flags |= TREE_COND;
// Set as conditional
line->type = TREE_T_COND;
if (line->children->str[2])
line->flags |= TREE_NOT;
line->flags |= TREE_L_NOT;
// Save our spot
p = line;
// Move subprogram inline
@ -388,11 +382,6 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
// Find end of subprogram
while (line->next)
line = line->next;
line->next = GIB_Tree_New (flags | TREE_END);
line = line->next;
// Mark jump point
p->jump = line;
line->flags |= TREE_END; // Last instruction of subprogram
// Handle "else"
if (p->children->next->next->next
&& !strcmp (p->children->next->next->next->str, "else")) {
@ -403,6 +392,12 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
line->start);
return line;
}
// On 'true' first block must jump past this
// We will figure out jump target later
line->next = GIB_Tree_New (TREE_T_JUMPPLUS);
line = line->next;
// Jump to else block on 'false'
p->jump = line;
// Is "else" followed by a subprogram?
if (p->children->next->next->next->next->delim == '{') {
// Move subprogram inline
@ -412,18 +407,20 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
line = line->next;
} else {
// Push rest of tokens into a new line
line->next = GIB_Tree_New (flags);
line->next = GIB_Tree_New (TREE_T_CMD);
line->next->children = p->children->next->next->next->next;
p->children->next->next->next->next = 0;
line = line->next;
}
} else
break; // Don't touch if statements in the sub
// program
} else {
// Jump past block on 'false'
p->jump = line;
break; // Don't touch if statements in the sub program
}
}
// Now we know our exit point, set it on all our ending instructions
// Now we know exit point from if-else if chain, set our jumps
while (start) {
if (start->flags & TREE_END && !start->jump)
if (start->type == TREE_T_JUMPPLUS && !start->jump)
start->jump = line;
start = start->next;
}
@ -443,28 +440,39 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
("Program block in 'while' statement not enclosed in braces or invalid.",
line->start);
return line;
} else if (line->flags & TREE_EMBED) {
} else if (line->flags & TREE_L_EMBED) {
GIB_Parse_Error
("'while' statements may not be used in embedded commands.",
line->start);
return line;
}
// Set conditional flag
line->flags |= TREE_COND;
line->type = TREE_T_COND;
// Save our spot
p = line;
// Move subprogram inline
line->next = line->children->next->next->children;
line->children->next->next->children = 0;
// Find end of subprogram, set jump point back to top of loop as we go
// Find end of subprogram
for (; line->next; line = line->next)
if (!line->jump)
line->jump = p;
line->next = GIB_Tree_New (flags | TREE_END);
if (!line->jump && line->children) {
if (!strcmp (line->children->str, "continue")) {
line->type = TREE_T_JUMP;
line->jump = p;
} else if (!strcmp (line->children->str, "break"))
line->type = TREE_T_JUMPPLUS;
}
line->next = GIB_Tree_New (TREE_T_JUMP);
line->next->jump = p;
line = line->next;
// Mark jump point out of loop
p->jump = line;
// Set jumps out of loop for "break" commands;
while (p) {
if (p->type == TREE_T_JUMPPLUS && !p->jump)
p->jump = line;
p = p->next;
}
} else if (!strcmp (line->children->str, "for")) {
gib_tree_t *tmp;
@ -486,25 +494,40 @@ GIB_Parse_Semantic_Preprocess (gib_tree_t * line)
line->start);
return line;
}
// Add instruction to fetch next argument (this is the true loop start)
line->next = GIB_Tree_New (TREE_T_FORNEXT);
line = line->next;
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
// Find end of subprogram
for (; line->next; line = line->next)
if (!line->jump)
line->jump = p;
line->next = GIB_Tree_New (flags | TREE_FORNEXT);
if (!line->jump && line->children) {
if (!strcmp (line->children->str, "continue")) {
line->type = TREE_T_JUMP;
line->jump = p;
} else if (!strcmp (line->children->str, "break"))
line->type = TREE_T_JUMPPLUS;
}
line->next = GIB_Tree_New (TREE_T_JUMP);
line->next->jump = p;
line = line->next;
// Mark jump point out of loop
p->jump = line;
}
// Mark jump point out of loop for break command
while (p) {
if (p->type == TREE_T_JUMPPLUS && !p->jump)
p->jump = line;
p = p->next;
}
} else if (line->children->next && line->children->next->delim == ' ' && !strcmp (line->children->next->str, "="))
line->type = TREE_T_ASSIGN;
return line;
}
gib_tree_t *
GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags)
GIB_Parse_Lines (const char *program, unsigned int pofs)
{
unsigned int i = 0, lstart;
gib_tree_t *lines = 0, *cur, *tokens, **line = &lines, *embs;
@ -517,9 +540,9 @@ GIB_Parse_Lines (const char *program, unsigned int pofs, gib_tree_flags_t flags)
break;
lstart = i;
// If we parse something useful...
if ((tokens = GIB_Parse_Tokens (program, &i, pofs, flags, &embs))) {
if ((tokens = GIB_Parse_Tokens (program, &i, pofs, &embs))) {
// Link it in
cur = GIB_Tree_New (flags);
cur = GIB_Tree_New (TREE_T_CMD);
cur->delim = '\n';
str = calloc (i - lstart + 1, sizeof (char));
memcpy (str, program + lstart, i - lstart);
@ -549,8 +572,7 @@ 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)
GIB_Parse_Embedded (const char *program, unsigned int pofs, gib_tree_t ** embedded)
{
unsigned int i, n, t;
char c, d, *str;
@ -575,7 +597,8 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs,
}
end = i + 1;
// Construct the actual line to be executed
cur = GIB_Tree_New (flags | TREE_EMBED);
cur = GIB_Tree_New (TREE_T_CMD);
cur->flags |= TREE_L_EMBED;
cur->delim = '`';
str = calloc (i - n + 1, sizeof (char));
memcpy (str, program + n, i - n);
@ -586,7 +609,7 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs,
t = 0;
if (!
(tokens =
GIB_Parse_Tokens (cur->str, &t, start + pofs, flags, &emb)))
GIB_Parse_Tokens (cur->str, &t, start + pofs, &emb)))
goto ERROR;
cur->children = tokens;
GIB_Parse_Semantic_Preprocess (cur)->next = *embedded;
@ -602,7 +625,7 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs,
*embedded = cur;
// Create a representative child node for GIB_Process_Embedded to
// use
cur = GIB_Tree_New (flags | TREE_EMBED);
cur = GIB_Tree_New (TREE_T_META);
cur->delim = '`';
// Save start/end indices
cur->start = start;
@ -624,7 +647,7 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs,
goto ERROR;
end += i;
cur = GIB_Tree_New (flags | TREE_EMBED);
cur = GIB_Tree_New (TREE_T_META);
cur->delim = d;
str = calloc (i - n + 1, sizeof (char));
memcpy (str, program + n, i - n);
@ -632,7 +655,7 @@ GIB_Parse_Embedded (const char *program, unsigned int pofs,
// Can we use the name as is, or must processing be done at
// runtime?
if (strchr (str, '$') || strchr (str, '#'))
cur->flags |= TREE_P_EMBED;
cur->flags |= TREE_A_EMBED;
// Save start/end indices
cur->start = start;
cur->end = end;

View file

@ -101,7 +101,7 @@ GIB_Process_Embedded (gib_tree_t * node, cbuf_args_t * args)
dstring_appendstr (args->argv[args->argc - 1],
retvals->dstrs[0]->str);
GIB_Buffer_Pop_Sstack (cbuf_active);
} else if (cur->flags & TREE_P_EMBED) {
} else if (cur->flags & TREE_A_EMBED) {
n = args->argv[args->argc - 1]->size - 1;
dstring_appendstr (args->argv[args->argc - 1], cur->str);
var = GIB_Var_Get_Very_Complex (&GIB_DATA (cbuf_active)->locals,

View file

@ -43,11 +43,11 @@ const char rcsid[] = "$Id$";
#include "QF/gib_tree.h"
gib_tree_t *
GIB_Tree_New (gib_tree_flags_t flags)
GIB_Tree_New (enum gib_tree_type_e type)
{
gib_tree_t *new = calloc (1, sizeof (gib_tree_t));
new->flags = flags;
new->type = type;
// All nodes are created for a reason, so start with 1 ref
new->refs = 1;
return new;

View file

@ -197,12 +197,12 @@ Cbuf_Execute_Stack (cbuf_t *cbuf)
sp->state = CBUF_STATE_JUNK;
sp = sp->up;
}
if (cbuf->down) {
Cbuf_DeleteStack (cbuf->down);
cbuf->down = 0;
}
Cbuf_Reset (cbuf);
if (sp) // This should be null if we exited normally
Cbuf_Reset (cbuf);
}
void