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
/* 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;
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;
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
*
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 ) {
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;
}
}
}
- if ( err_val ) {
+ if ( err_val ) {
+
if ( tok == TOK_STRING )
free ( tok_value.str_value );
switch ( err_val ) {
#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;
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;
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
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;
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 ) {
/* 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
--- /dev/null
+#!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