diff --git a/include/QF/gib_buffer.h b/include/QF/gib_buffer.h index 6a82581c4..7040f15d5 100644 --- a/include/QF/gib_buffer.h +++ b/include/QF/gib_buffer.h @@ -37,7 +37,7 @@ typedef struct gib_buffer_data_s { struct dstring_s *loop_program; struct dstring_s *loop_data; - char *loop_var_p, *loop_list_p; + char *loop_var_p, *loop_list_p, *loop_ifs_p; // Data for handling return values struct { diff --git a/include/QF/gib_process.h b/include/QF/gib_process.h index 956ee4362..9eab68c8b 100644 --- a/include/QF/gib_process.h +++ b/include/QF/gib_process.h @@ -30,6 +30,5 @@ */ void GIB_Process_Variable (struct dstring_s *token); -void GIB_Process_Variables_All (struct dstring_s *token); int GIB_Process_Math (struct dstring_s *token); int GIB_Process_Token (struct dstring_s *token, char delim); diff --git a/libs/util/gib_builtin.c b/libs/util/gib_builtin.c index c63af9229..e5d68767d 100644 --- a/libs/util/gib_builtin.c +++ b/libs/util/gib_builtin.c @@ -329,7 +329,7 @@ GIB___For_f (void) Cbuf_InsertText (cbuf_active, "break;"); return; } - for (end = GIB_DATA(cbuf_active)->loop_list_p; *end && !isspace((byte) *end); end++); + for (end = GIB_DATA(cbuf_active)->loop_list_p; !strchr(GIB_DATA(cbuf_active)->loop_ifs_p, *end); end++); if (*end) { old = *end; *end = 0; @@ -337,7 +337,7 @@ GIB___For_f (void) GIB_Var_Set_Local (cbuf_active, GIB_DATA(cbuf_active)->loop_var_p, GIB_DATA(cbuf_active)->loop_list_p); if (old) *end = old; - while (isspace ((byte)*end)) + while (*end && strchr(GIB_DATA(cbuf_active)->loop_ifs_p, *end)) end++; GIB_DATA(cbuf_active)->loop_list_p = end; } @@ -352,7 +352,9 @@ GIB_For_f (void) ); } else if (GIB_Argv (3)[0]) { char *ll; + const char *ifs; cbuf_t *sub = Cbuf_New (&gib_interp); + // Create loop buffer GIB_DATA(sub)->type = GIB_BUFFER_LOOP; GIB_DATA(sub)->locals = GIB_DATA(cbuf_active)->locals; GIB_DATA(sub)->loop_program = dstring_newstr (); @@ -361,13 +363,19 @@ GIB_For_f (void) Cbuf_DeleteStack (cbuf_active->down); cbuf_active->down = sub; sub->up = cbuf_active; + // Store all for-loop data in one big buffer (easy to clean up) dstring_appendstr (GIB_DATA(sub)->loop_data, GIB_Argv(3)); dstring_append (GIB_DATA(sub)->loop_data, GIB_Argv(1), strlen(GIB_Argv(1))+1); + if (!(ifs = GIB_Var_Get_Local (cbuf_active, "ifs"))) + ifs = " \n\t"; + dstring_append (GIB_DATA(sub)->loop_data, ifs, strlen(ifs)+1); + // Store pointers to data ll = GIB_DATA(sub)->loop_data->str; while (isspace ((byte) *ll)) ll++; - GIB_DATA(sub)->loop_list_p = ll; - GIB_DATA(sub)->loop_var_p = GIB_DATA(sub)->loop_data->str + strlen(GIB_Argv(3))+1; + GIB_DATA(sub)->loop_list_p = ll; // List to iterate through + GIB_DATA(sub)->loop_var_p = GIB_DATA(sub)->loop_data->str + strlen(GIB_Argv(3))+1; // Var to use + GIB_DATA(sub)->loop_ifs_p = GIB_DATA(sub)->loop_var_p + strlen(GIB_Argv(1))+1; // Internal field separator dstring_appendstr (GIB_DATA(sub)->loop_program, "__for;"); dstring_appendstr (GIB_DATA(sub)->loop_program, GIB_Argv(4)); Cbuf_AddText (sub, GIB_DATA(sub)->loop_program->str); @@ -596,6 +604,7 @@ GIB_File_Find_f (void) DIR *directory; struct dirent *entry; char *path; + const char *ifs; dstring_t *list; if (GIB_Argc () < 2 || GIB_Argc () > 3) { @@ -620,9 +629,13 @@ GIB_File_Find_f (void) return; } list = dstring_newstr (); + if (!(ifs = GIB_Var_Get_Local (cbuf_active, "ifs"))) + ifs = " "; while ((entry = readdir (directory))) { - if (!fnmatch (GIB_Argv (1), entry->d_name, 0)) { - dstring_appendstr (list, " "); + if (strcmp (entry->d_name, ".") && + strcmp (entry->d_name, "..") && + !fnmatch (GIB_Argv (1), entry->d_name, 0)) { + dstring_appendstr (list, ifs); dstring_appendstr (list, entry->d_name); } } diff --git a/libs/util/gib_process.c b/libs/util/gib_process.c index 4bc973367..6624a4452 100644 --- a/libs/util/gib_process.c +++ b/libs/util/gib_process.c @@ -106,17 +106,69 @@ GIB_Process_Variable (struct dstring_s *dstr, unsigned int pos, qboolean toleran } int -GIB_Process_Variables_All (struct dstring_s *token) +GIB_Process_Math (struct dstring_s *token) { - int i, n, m; + double value; + + value = EXP_Evaluate (token->str); + if (EXP_ERROR) { + // FIXME: Give real error descriptions + Cbuf_Error ("math", "Expression \"%s\" caused error %i", token->str, EXP_ERROR); + return -1; + } else { + dstring_clearstr (token); + dsprintf (token, "%.10g", value); + } + return 0; +} + +int +GIB_Process_Embedded (struct dstring_s *token) +{ + cbuf_t *sub; + int i, n, m, i1, i2; + char c = 0, *p; dstring_t *var = dstring_newstr (); - char c = 0; - char *p; - int i1, i2; qboolean index; - for (i = 0; token->str[i]; i++) { - if (token->str[i] == '$') { + if (GIB_DATA(cbuf_active)->ret.waiting) { + if (!GIB_DATA(cbuf_active)->ret.available) { + GIB_DATA(cbuf_active)->ret.waiting = false; + Cbuf_Error ("return", "Embedded command did not return a value."); + return -1; + } + i = GIB_DATA(cbuf_active)->ret.token_pos; // Jump to the right place + } else + i = 0; + + for (; token->str[i]; i++) { + if (token->str[i] == '`') { + n = i; + if ((c = GIB_Parse_Match_Backtick (token->str, &i))) { + Cbuf_Error ("parse", "Could not find matching %c", c); + return -1; + } + if (GIB_DATA(cbuf_active)->ret.available) { + dstring_replace (token, n, i-n+1, GIB_DATA(cbuf_active)->ret.retval->str, + strlen(GIB_DATA(cbuf_active)->ret.retval->str)); + i = n + strlen(GIB_DATA(cbuf_active)->ret.retval->str) - 1; + GIB_DATA(cbuf_active)->ret.waiting = false; + GIB_DATA(cbuf_active)->ret.available = false; + } else { + sub = Cbuf_New (&gib_interp); + GIB_DATA(sub)->type = GIB_BUFFER_PROXY; + GIB_DATA(sub)->locals = GIB_DATA(cbuf_active)->locals; + dstring_insert (sub->buf, 0, token->str+n+1, i-n-1); + if (cbuf_active->down) + Cbuf_DeleteStack (cbuf_active->down); + cbuf_active->down = sub; + sub->up = cbuf_active; + cbuf_active->state = CBUF_STATE_STACK; + GIB_DATA(cbuf_active)->ret.waiting = true; + GIB_DATA(cbuf_active)->ret.token_pos = n; + return -1; + } + } else if (token->str[i] == '$') { index = false; if (token->str[i+1] == '{') { n = i+1; @@ -150,6 +202,7 @@ GIB_Process_Variables_All (struct dstring_s *token) n++; if (!token->str[i+n]) { Cbuf_Error ("parse", "Could not find match for ["); + c = '['; goto ERROR; } } @@ -196,77 +249,13 @@ GIB_Process_Variables_All (struct dstring_s *token) dstring_clearstr (var); } } + return 0; + dstring_delete (var); ERROR: dstring_delete (var); return c ? -1 : 0; } -int -GIB_Process_Math (struct dstring_s *token) -{ - double value; - - value = EXP_Evaluate (token->str); - if (EXP_ERROR) { - // FIXME: Give real error descriptions - Cbuf_Error ("math", "Expression \"%s\" caused error %i", token->str, EXP_ERROR); - return -1; - } else { - dstring_clearstr (token); - dsprintf (token, "%.10g", value); - } - return 0; -} - -int -GIB_Process_Embedded (struct dstring_s *token) -{ - cbuf_t *sub; - int i, n; - char c; - - if (GIB_DATA(cbuf_active)->ret.waiting) { - if (!GIB_DATA(cbuf_active)->ret.available) { - GIB_DATA(cbuf_active)->ret.waiting = false; - Cbuf_Error ("return", "Embedded command did not return a value."); - return -1; - } - i = GIB_DATA(cbuf_active)->ret.token_pos; // Jump to the right place - } else - i = 0; - - for (; token->str[i]; i++) { - if (token->str[i] == '`') { - n = i; - if ((c = GIB_Parse_Match_Backtick (token->str, &i))) { - Cbuf_Error ("parse", "Could not find matching %c", c); - return -1; - } - if (GIB_DATA(cbuf_active)->ret.available) { - dstring_replace (token, n, i-n+1, GIB_DATA(cbuf_active)->ret.retval->str, - strlen(GIB_DATA(cbuf_active)->ret.retval->str)); - i = n + strlen(GIB_DATA(cbuf_active)->ret.retval->str) - 1; - GIB_DATA(cbuf_active)->ret.waiting = false; - GIB_DATA(cbuf_active)->ret.available = false; - } else { - sub = Cbuf_New (&gib_interp); - GIB_DATA(sub)->type = GIB_BUFFER_PROXY; - GIB_DATA(sub)->locals = GIB_DATA(cbuf_active)->locals; - dstring_insert (sub->buf, 0, token->str+n+1, i-n-1); - if (cbuf_active->down) - Cbuf_DeleteStack (cbuf_active->down); - cbuf_active->down = sub; - sub->up = cbuf_active; - cbuf_active->state = CBUF_STATE_STACK; - GIB_DATA(cbuf_active)->ret.waiting = true; - GIB_DATA(cbuf_active)->ret.token_pos = n; - return -1; - } - } - } - return 0; -} - void GIB_Process_Escapes (dstring_t *token) { @@ -283,13 +272,9 @@ GIB_Process_Escapes (dstring_t *token) int GIB_Process_Token (dstring_t *token, char delim) { - if (delim != '{' && delim != '\"') { + if (delim != '{' && delim != '\"') if (GIB_Process_Embedded (token)) return -1; - if (GIB_Process_Variables_All (token)) - return -1; - } - if (delim == '(') if (GIB_Process_Math (token)) return -1;