From c9fbb334f191ec2184cdc9d4c5ccc1d155a6ed98 Mon Sep 17 00:00:00 2001 From: Brian Koropoff Date: Tue, 25 Feb 2003 06:52:27 +0000 Subject: [PATCH] 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) --- include/QF/gib_parse.h | 4 +- include/QF/gib_tree.h | 28 +++++---- libs/gib/gib_buffer.c | 40 ++++++++++--- libs/gib/gib_builtin.c | 69 ++++++++-------------- libs/gib/gib_execute.c | 130 ++++++++++++++++++++++------------------- libs/gib/gib_parse.c | 123 ++++++++++++++++++++++---------------- libs/gib/gib_process.c | 2 +- libs/gib/gib_tree.c | 4 +- libs/util/cbuf.c | 4 +- 9 files changed, 226 insertions(+), 178 deletions(-) diff --git a/include/QF/gib_parse.h b/include/QF/gib_parse.h index 7ecdd3e72..e66226d28 100644 --- a/include/QF/gib_parse.h +++ b/include/QF/gib_parse.h @@ -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); diff --git a/include/QF/gib_tree.h b/include/QF/gib_tree.h index 6b0fc05aa..b596b448e 100644 --- a/include/QF/gib_tree.h +++ b/include/QF/gib_tree.h @@ -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); diff --git a/libs/gib/gib_buffer.c b/libs/gib/gib_buffer.c index 4553e9db0..f748a2705 100644 --- a/libs/gib/gib_buffer.c +++ b/libs/gib/gib_buffer.c @@ -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 diff --git a/libs/gib/gib_builtin.c b/libs/gib/gib_builtin.c index 29095fe57..131939e83 100644 --- a/libs/gib/gib_builtin.c +++ b/libs/gib/gib_builtin.c @@ -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); } diff --git a/libs/gib/gib_execute.c b/libs/gib/gib_execute.c index fe63f106c..694c72eb2 100644 --- a/libs/gib/gib_execute.c +++ b/libs/gib/gib_execute.c @@ -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; } diff --git a/libs/gib/gib_parse.c b/libs/gib/gib_parse.c index 8b6282ee5..078257962 100644 --- a/libs/gib/gib_parse.c +++ b/libs/gib/gib_parse.c @@ -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; diff --git a/libs/gib/gib_process.c b/libs/gib/gib_process.c index 2561c7dc9..af714c9b8 100644 --- a/libs/gib/gib_process.c +++ b/libs/gib/gib_process.c @@ -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, diff --git a/libs/gib/gib_tree.c b/libs/gib/gib_tree.c index c5f3c5496..b1be31a84 100644 --- a/libs/gib/gib_tree.c +++ b/libs/gib/gib_tree.c @@ -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; diff --git a/libs/util/cbuf.c b/libs/util/cbuf.c index 2df9d9671..977dc1b75 100644 --- a/libs/util/cbuf.c +++ b/libs/util/cbuf.c @@ -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