mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
Added initial support for newline-delimeted lists to GIB, including a for
loop that takes a variable through all elements of such a list.
This commit is contained in:
parent
e1a9cfb6f0
commit
33d132fc4e
4 changed files with 116 additions and 7 deletions
|
@ -35,6 +35,9 @@ typedef struct gib_buffer_data_s {
|
|||
struct dstring_s *arg_composite;
|
||||
struct dstring_s *current_token;
|
||||
struct dstring_s *loop_program;
|
||||
struct dstring_s *loop_data;
|
||||
|
||||
char *loop_var_p, *loop_list_p;
|
||||
|
||||
// Data for handling return values
|
||||
struct {
|
||||
|
|
|
@ -57,6 +57,8 @@ void GIB_Buffer_Destruct (struct cbuf_s *cbuf)
|
|||
dstring_delete (GIB_DATA (cbuf)->current_token);
|
||||
if (GIB_DATA (cbuf)->loop_program)
|
||||
dstring_delete (GIB_DATA(cbuf)->loop_program);
|
||||
if (GIB_DATA (cbuf)->loop_data)
|
||||
dstring_delete (GIB_DATA(cbuf)->loop_data);
|
||||
dstring_delete (GIB_DATA (cbuf)->ret.retval);
|
||||
if (GIB_DATA(cbuf)->locals && GIB_DATA(cbuf)->type == GIB_BUFFER_NORMAL)
|
||||
Hash_DelTable (GIB_DATA(cbuf)->locals);
|
||||
|
|
|
@ -314,7 +314,54 @@ GIB_While_f (void)
|
|||
cbuf_active->down = sub;
|
||||
sub->up = cbuf_active;
|
||||
GIB_Arg_Strip_Delim (2);
|
||||
dstring_appendstr (GIB_DATA(sub)->loop_program, va("ifnot %s break\n%s", GIB_Argv (1), GIB_Argv (2)));
|
||||
dstring_appendstr (GIB_DATA(sub)->loop_program, va("ifnot %s break;%s", GIB_Argv (1), GIB_Argv (2)));
|
||||
Cbuf_AddText (sub, GIB_DATA(sub)->loop_program->str);
|
||||
cbuf_active->state = CBUF_STATE_STACK;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GIB___For_f (void)
|
||||
{
|
||||
char *end = 0;
|
||||
if (!GIB_DATA(cbuf_active)->loop_list_p) {
|
||||
Cbuf_InsertText (cbuf_active, "break;");
|
||||
return;
|
||||
}
|
||||
if ((end = strchr (GIB_DATA(cbuf_active)->loop_list_p, '\n')))
|
||||
*end = 0;
|
||||
GIB_Var_Set_Local (cbuf_active, GIB_DATA(cbuf_active)->loop_var_p, GIB_DATA(cbuf_active)->loop_list_p);
|
||||
if (end) {
|
||||
*end = '\n';
|
||||
end++;
|
||||
}
|
||||
GIB_DATA(cbuf_active)->loop_list_p = end;
|
||||
}
|
||||
|
||||
void
|
||||
GIB_For_f (void)
|
||||
{
|
||||
if (GIB_Argc() != 5) {
|
||||
Cbuf_Error ("syntax",
|
||||
"for: invalid syntax\n"
|
||||
"usage: for variable in list {program}"
|
||||
);
|
||||
} else if (GIB_Argv (3)[0]) {
|
||||
cbuf_t *sub = Cbuf_New (&gib_interp);
|
||||
GIB_DATA(sub)->type = GIB_BUFFER_LOOP;
|
||||
GIB_DATA(sub)->locals = GIB_DATA(cbuf_active)->locals;
|
||||
GIB_DATA(sub)->loop_program = dstring_newstr ();
|
||||
GIB_DATA(sub)->loop_data = dstring_newstr ();
|
||||
if (cbuf_active->down)
|
||||
Cbuf_DeleteStack (cbuf_active->down);
|
||||
cbuf_active->down = sub;
|
||||
sub->up = cbuf_active;
|
||||
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);
|
||||
GIB_DATA(sub)->loop_list_p = GIB_DATA(sub)->loop_data->str;
|
||||
GIB_DATA(sub)->loop_var_p = GIB_DATA(sub)->loop_data->str + strlen(GIB_Argv(3))+1;
|
||||
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);
|
||||
cbuf_active->state = CBUF_STATE_STACK;
|
||||
}
|
||||
|
@ -576,6 +623,58 @@ GIB_File_Find_f (void)
|
|||
dstring_delete (list);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_List_Get_f (void)
|
||||
{
|
||||
char *list, *pos, *end;
|
||||
unsigned long int i;
|
||||
if (GIB_Argc () < 3) {
|
||||
Cbuf_Error ("syntax",
|
||||
"list.get: invalid syntax\n"
|
||||
"usage: list.get list element");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = strtoul (GIB_Argv(2), 0, 10), pos = list = cbuf_active->args->argv[1]->str; i > 0 && *pos; pos++)
|
||||
i -= (*pos == '\n');
|
||||
if (i) {
|
||||
GIB_Return ("");
|
||||
return;
|
||||
}
|
||||
if ((end = strchr (pos, '\n')))
|
||||
*end = 0;
|
||||
GIB_Return (pos);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Range_f (void)
|
||||
{
|
||||
double i, inc, start, limit;
|
||||
dstring_t *dstr;
|
||||
if (GIB_Argc () < 3 || GIB_Argc () > 4) {
|
||||
Cbuf_Error ("syntax",
|
||||
"range: invalid syntax\n"
|
||||
"range: lower upper [step]");
|
||||
return;
|
||||
}
|
||||
|
||||
limit = atof(GIB_Argv(2));
|
||||
start = atof(GIB_Argv(1));
|
||||
if (GIB_Argc () == 4)
|
||||
inc = atof(GIB_Argv(3));
|
||||
else
|
||||
inc = limit < start ? -1.0 : 1.0;
|
||||
if (inc == 0.0) {
|
||||
GIB_Return ("");
|
||||
return;
|
||||
}
|
||||
dstr = dstring_newstr ();
|
||||
for (i = atof(GIB_Argv(1)); inc < 0 ? i >= limit : i <= limit; i += inc)
|
||||
dstring_appendstr (dstr, va("\n%.10g", i));
|
||||
GIB_Return (dstr->str[0] ? dstr->str+1 : "");
|
||||
dstring_delete (dstr);
|
||||
}
|
||||
|
||||
void
|
||||
GIB_Builtin_Init (void)
|
||||
{
|
||||
|
@ -590,6 +689,8 @@ GIB_Builtin_Init (void)
|
|||
GIB_Builtin_Add ("if", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
|
||||
GIB_Builtin_Add ("ifnot", GIB_If_f, GIB_BUILTIN_FIRSTONLY);
|
||||
GIB_Builtin_Add ("while", GIB_While_f, GIB_BUILTIN_NOPROCESS);
|
||||
GIB_Builtin_Add ("for", GIB_For_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("__for", GIB___For_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("break", GIB_Break_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("string.length", GIB_String_Length_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("string.equal", GIB_String_Equal_f, GIB_BUILTIN_NORMAL);
|
||||
|
@ -598,4 +699,6 @@ GIB_Builtin_Init (void)
|
|||
GIB_Builtin_Add ("file.read", GIB_File_Read_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("file.write", GIB_File_Write_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("file.find", GIB_File_Find_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("list.get", GIB_List_Get_f, GIB_BUILTIN_NORMAL);
|
||||
GIB_Builtin_Add ("range", GIB_Range_f, GIB_BUILTIN_NORMAL);
|
||||
}
|
||||
|
|
|
@ -241,11 +241,6 @@ GIB_Parse_Extract_Line (struct cbuf_s *cbuf)
|
|||
dstring_snip (dstr, 0, i + (dstr->str[i] == '\n' || dstr->str[i] == ';'));
|
||||
}
|
||||
|
||||
// If this is a looping buffer and it is now empty
|
||||
// copy the loop program back in
|
||||
if (GIB_DATA(cbuf)->type == GIB_BUFFER_LOOP && !dstr->str[0])
|
||||
Cbuf_AddText (cbuf, GIB_DATA(cbuf)->loop_program->str);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
@ -488,5 +483,11 @@ void GIB_Parse_Execute_Line (cbuf_t *cbuf)
|
|||
} else
|
||||
Cmd_Command (cbuf->args);
|
||||
dstring_clearstr (cbuf->line);
|
||||
|
||||
// If this is a looping buffer and it is now empty,
|
||||
// copy the loop program back in and execute any
|
||||
// loop callbacks
|
||||
if (GIB_DATA(cbuf)->type == GIB_BUFFER_LOOP && !cbuf->buf->str[0])
|
||||
Cbuf_AddText (cbuf, GIB_DATA(cbuf)->loop_program->str);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue