[scripting] Start on while loops
authorLynus Vaz <lynus@Arch.localdomain>
Sat, 27 Jun 2009 13:00:14 +0000 (18:30 +0530)
committerLynus Vaz <lynus@Arch.localdomain>
Sat, 27 Jun 2009 13:00:14 +0000 (18:30 +0530)
src/core/exec.c
src/hci/arith.c
src/hci/commands/if_cmd.c
src/hci/gen_stack.c
src/include/gpxe/gen_stack.h
src/tests/while.gpxe [new file with mode: 0644]

index 0175a26..efa8074 100644 (file)
@@ -42,6 +42,9 @@ int optind;
 int nextchar;
 
 extern struct generic_stack if_stack;
+extern struct generic_stack command_list;
+extern struct generic_stack loop_stack;
+extern int prog_ctr;
 
 /**
  * Execute command
@@ -80,7 +83,8 @@ int execv ( const char *command, char * const argv[] ) {
        /* Hand off to command implementation */
        for_each_table_entry ( cmd, COMMANDS ) {
                if ( strcmp ( command, cmd->name ) == 0 ) {
-                       if ( TOP_GEN_STACK_INT ( &if_stack ) || !strcmp ( cmd->name, "if" ) || !strcmp ( cmd->name, "fi" ) || !strcmp ( cmd->name, "else" ) )
+                       if ( TOP_GEN_STACK_INT ( &if_stack ) || !strcmp ( cmd->name, "if" ) || !strcmp ( cmd->name, "fi" ) || !strcmp ( cmd->name, "else" )
+                               || !strcmp ( cmd->name, "while" ) || !strcmp ( cmd->name, "done" ) )
                                return cmd->exec ( argc, ( char ** ) argv );
                        else
                                return 0;
@@ -99,7 +103,7 @@ static int expand_command ( const char *command, struct generic_stack *argv_stac
        struct string expcmd = { .value = NULL };
        
        argc = 0;
-       init_generic_stack ( argv_stack, sizeof ( int ) );
+       init_generic_stack ( argv_stack, sizeof ( char * ) );
        
        if ( !stringcpy ( &expcmd, command ) ) {
                argc = -ENOMEM;
@@ -149,6 +153,20 @@ static int expand_command ( const char *command, struct generic_stack *argv_stac
        return argc;
 }
 
+int system_exec_list ( void ) {
+       int rc = 0;
+       while ( prog_ctr < SIZE_GEN_STACK ( &command_list ) ) {
+               const char *command = ELEMENT_GEN_STACK_STRING ( &command_list, prog_ctr );
+               printf ( "command = [%s]\n", command );
+               printf ( "pc = %d. size of loop_stack = %d, command list = %d\n", prog_ctr, loop_stack.tos + 1, SIZE_GEN_STACK ( &command_list ) );
+               //printf ( "pc = %d. command = [%s]\n", prog_ctr, 
+               if ( ( rc = system ( command ) ) != 0 )
+                       return rc;
+       }
+       printf ( "end of list: %d\n", prog_ctr );
+       return rc;
+}
+
 /**
  * Execute command line
  *
@@ -161,6 +179,12 @@ int system ( const char *command ) {
        int argc;
        int rc = 0;
        struct generic_stack argv_stack;
+       
+       if ( prog_ctr == SIZE_GEN_STACK ( &command_list ) ) {
+               push_generic_stack ( &command_list, &command, 1 );
+               //printf ( "appending %s at %d\n", TOP_GEN_STACK_STRING ( &command_list ), prog_ctr );
+       }
+       
 
        argc = expand_command ( command, &argv_stack );
        if ( argc < 0 ) {
@@ -169,12 +193,11 @@ int system ( const char *command ) {
                char **argv;
                if ( ! push_generic_stack ( &argv_stack, NULL, 0 ) ) {
                        argv = ( char ** ) argv_stack.ptr;
-                       argv[argc] = NULL;
                        if ( argc > 0 )
                                rc = execv ( argv[0], argv );
                }
        }
-       
+       prog_ctr++;
        free_generic_stack ( &argv_stack, 1 );
        return rc;
 }
index 5618e06..1828392 100644 (file)
@@ -387,7 +387,8 @@ char * parse_arith ( struct string *inp, char *orig ) {
                }
        }
                
-       if ( err_val )  {               
+       if ( err_val )  {
+               
                if ( tok == TOK_STRING )
                        free ( tok_value.str_value );
                switch ( err_val ) {
index c329ec7..4a8a66e 100644 (file)
@@ -5,9 +5,14 @@
 #include <gpxe/init.h>
 
 struct generic_stack if_stack;
-static struct generic_stack else_stack;
+struct generic_stack else_stack;
+struct generic_stack loop_stack;
+struct generic_stack command_list;
+int prog_ctr;
 int isnum ( char *string, long *num );
 
+int system ( const char * );
+
 static int if_exec ( int argc, char **argv ) {
        long cond;
        int zero = 0;
@@ -84,6 +89,9 @@ void init_if ( void ) {
        int one = 1;
        init_generic_stack ( &if_stack, sizeof ( int ) );
        init_generic_stack ( &else_stack, sizeof ( int ) );
+       init_generic_stack ( &loop_stack, sizeof ( int ) );
+       init_generic_stack ( &command_list, sizeof ( char * ) );
+       prog_ctr = 0;
        push_generic_stack ( &if_stack, &one, 0 );
        push_generic_stack ( &else_stack, &one, 0 );
        return;
@@ -91,4 +99,60 @@ void init_if ( void ) {
 
 struct init_fn initialise_if __init_fn ( INIT_NORMAL ) = {
        .initialise = init_if,
+};
+
+static int while_exec ( int argc, char **argv ) {
+       if ( argc != 2 ) {
+               printf ( "Syntax: while <condition>\n" );
+               return 1;
+       }
+       if ( if_exec ( argc, argv ) != 0 )
+               return 1;
+       TOP_GEN_STACK_INT ( &else_stack ) = 1;
+       push_generic_stack ( &loop_stack, &prog_ctr, 0 );
+       //printf ( "pc = %d. size of loop_stack = %d\n", prog_ctr, SIZE_GEN_STACK ( &loop_stack ) );
+       return 0;
+}
+
+struct command while_command __command = {
+       .name = "while",
+       .exec = while_exec,
+};
+
+static int done_exec ( int argc, char **argv ) {
+       int cond;
+       int tmp_pc;
+       int pot;
+       int rc = 0;
+       if ( argc != 1 ) {
+               printf ( "Syntax: %s\n", argv[0] );
+               return 1;
+       }
+       
+       //printf ( "size of if_stack = %d. size of loop stack = %d\n", SIZE_GEN_STACK ( &if_stack ), SIZE_GEN_STACK ( &loop_stack ) );
+       
+       if ( SIZE_GEN_STACK ( &loop_stack ) == 0 ) {
+               printf ( "done outside a loop\n" );
+               return 1;
+       }
+       
+       pop_generic_stack ( &if_stack, &cond );
+       pop_generic_stack ( &loop_stack, &pot );
+       
+       while ( cond ) {
+               tmp_pc = prog_ctr;
+               prog_ctr = pot;
+               while ( prog_ctr < tmp_pc ) {
+                       if ( ( rc = system ( ELEMENT_GEN_STACK_STRING ( &command_list, prog_ctr ) ) ) ) 
+                               return rc;
+               }
+               pop_generic_stack ( &if_stack, &cond );
+               pop_generic_stack ( &loop_stack, &pot );
+       }
+       return rc;
+}
+
+struct command done_command __command = {
+       .name = "done",
+       .exec = done_exec,
 };
\ No newline at end of file
index 5859cc6..92c53fd 100644 (file)
@@ -15,6 +15,11 @@ int pop_generic_stack ( struct generic_stack *stack, void *ptr ) {
        if ( stack->tos >= 0 ) {
                void *nptr;
                memcpy ( ptr, ( void * ) ( ( (int)stack->ptr ) + stack->size * stack->tos-- ), stack->size );
+               if ( stack->tos == -1 ) {
+                       free ( stack->ptr );
+                       stack->ptr = NULL;
+                       return 0;
+               }
                nptr = realloc ( stack->ptr, stack->size * ( stack->tos + 1 ) );
                if ( nptr ) {
                        stack->ptr = nptr;
@@ -30,11 +35,12 @@ int pop_generic_stack ( struct generic_stack *stack, void *ptr ) {
 void free_generic_stack ( struct generic_stack *stack, int on_stack ) {
        void *ptr = NULL;
        if ( on_stack ) {
-               while ( !pop_generic_stack ( stack, ptr ) ) {
+               while ( !pop_generic_stack ( stack, &ptr ) ) {
                        free ( ptr );
                }
        }
        free ( stack->ptr );
+       stack->ptr = NULL;
 }
 
 int push_generic_stack ( struct generic_stack *stack, void *str, int is_string ) {
index 620dd77..35c31c6 100644 (file)
@@ -19,6 +19,9 @@ void free_generic_stack ( struct generic_stack *stack, int on_stack );                        /* Use
 /* convenience macros */
 #define TOP_GEN_STACK_INT( stack ) ( ( ( int * ) ( stack )->ptr )[( stack )->tos] )
 #define ELEMENT_GEN_STACK_INT( stack, pos ) ( ( ( int * ) ( stack )->ptr )[pos] )
-#define SIZE_GEN_STACK( stack ) ( stack->tos )
+#define SIZE_GEN_STACK( stack ) ( ( ( stack ) ->tos ) + 1 )
+
+#define TOP_GEN_STACK_STRING( stack ) ( ( ( char ** ) ( stack )->ptr )[( stack )->tos] )
+#define ELEMENT_GEN_STACK_STRING( stack, pos ) ( ( ( char ** ) ( stack )->ptr )[pos] )
 
 #endif
\ No newline at end of file
diff --git a/src/tests/while.gpxe b/src/tests/while.gpxe
new file mode 100644 (file)
index 0000000..3507038
--- /dev/null
@@ -0,0 +1,10 @@
+#!gpxe
+set a 500
+while $(${a} > 0)
+set b 2
+while $(${b} > 0)
+echo ${a}, ${b}
+set b $(${b} - 1)
+done
+set a $(${a} - 1)
+done