int nextchar;
extern struct generic_stack if_stack;
-extern int if_tos;
/**
* Execute command
/* Hand off to command implementation */
for_each_table_entry ( cmd, COMMANDS ) {
if ( strcmp ( command, cmd->name ) == 0 ) {
- if ( !if_stack.ptr || ( ( int * ) if_stack.ptr )[if_tos] || !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" ) )
return cmd->exec ( argc, ( char ** ) argv );
else
return 0;
return -ENOEXEC;
}
-struct char_table dquote_table[3] = {
- { .token = '"', .type = ENDQUOTES },
- { .token = '$', .type = FUNC, .next.parse_func = dollar_expand },
- { .token = '\\', .type = FUNC, .next.parse_func = parse_escape }
-};
-struct char_table squote_table[1] = {
- { .token = '\'', .type = ENDQUOTES }
-};
-static struct char_table table[6] = {
- { .token = '\\', .type = FUNC, .next.parse_func = parse_escape },
- { .token = '"', .type = TABLE, .next =
- {.next_table = { .ntable = dquote_table, .len = 3 } } },
- { .token = '$', .type = FUNC, .next.parse_func = dollar_expand },
- { .token = '\'', .type = TABLE, .next = { .next_table = { .ntable = squote_table, .len = 1 } } },
- { .token = ' ', .type = ENDTOK },
- { .token = '\t', .type = ENDTOK }
-};
-
static int expand_command ( const char *command, struct generic_stack *argv_stack ) {
char *head, *end;
char *nstring;
argc = 0;
init_generic_stack ( argv_stack, sizeof ( int ) );
- stringcpy ( &expcmd, command );
- if ( ! expcmd.value ) {
+ if ( !stringcpy ( &expcmd, command ) ) {
argc = -ENOMEM;
return argc;
}
if ( *head == '#' ) { /* Comment is a new word that starts with # */
break;
}
- stringcpy ( &expcmd, head );
+ if ( !stringcpy ( &expcmd, head ) ) {
+ argc = -ENOMEM;
+ break;
+ }
head = expcmd.value;
nstring = expand_string ( &expcmd, &head, &end, table, 6, 0, &success );
if ( nstring ) {
expcmd.value = NULL;
stringcpy ( &expcmd, end );
*end = 0;
+ /*
+ So if the command is: word1 word2 word3
+ argv_stack: word1\0word2 word3
+ word2\0word3
+ word3
+ */
}
} else {
argc = -ENOMEM;
rc = argc;
} else {
char **argv;
-
- argv = realloc ( argv_stack.ptr, sizeof ( char * ) * ( argc + 1 ) );
- if ( argv ) {
- argv_stack.ptr = 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 );
}
}
- free_generic_stack ( &argv_stack, 0 );
+ free_generic_stack ( &argv_stack, 1 );
return rc;
}
static void ignore_whitespace ( void );
static int parse_expr ( char **buffer );
-struct char_table table[21] = {
- { .token = '\\', .type = FUNC, .next.parse_func = parse_escape },
- { .token = '"', .type = TABLE, .next = { .next_table = { .ntable = dquote_table, .len = 3 } } },
- { .token = '$', .type = FUNC, .next.parse_func = dollar_expand },
- { .token = '\'', .type = TABLE, .next = { .next_table = { .ntable = squote_table, .len = 1 } } },
- { .token = ' ', .type = ENDQUOTES },
- { .token = '\t', .type = ENDQUOTES },
- { .token = '~', .type = ENDTOK },
- { .token = '!', .type = ENDTOK },
- { .token = '*', .type = ENDTOK },
- { .token = '/', .type = ENDTOK },
- { .token = '%', .type = ENDTOK },
- { .token = '+', .type = ENDTOK },
- { .token = '-', .type = ENDTOK },
- { .token = '<', .type = ENDTOK },
- { .token = '=', .type = ENDTOK },
- { .token = '>', .type = ENDTOK },
- { .token = '&', .type = ENDTOK },
- { .token = '|', .type = ENDTOK },
- { .token = '^', .type = ENDTOK },
- { .token = '(', .type = ENDTOK },
- { .token = ')', .type = ENDTOK }
-};
-
static void input ( void ) {
char t_op[3] = { '\0', '\0', '\0'};
char *p1, *p2;
}
tok = 0;
- tmp = expand_string ( input_str, &inp_ptr, &end, table, 21, 0, &success );
+ tmp = expand_string ( input_str, &inp_ptr, &end, arith_table, 21, 0, &success );
if ( !tmp ) {
tok = -1;
err_val = -ENOMEM;
#include <unistd.h>
#include <gpxe/command.h>
#include <gpxe/gen_stack.h>
+#include <gpxe/init.h>
-struct generic_stack if_stack = { .ptr = NULL, .tos = -1, .size = sizeof ( int ) };
-static struct generic_stack else_stack = { .ptr = NULL, .tos = -1, .size = sizeof ( int ) };
-int if_tos = 0;
+struct generic_stack if_stack;
+static struct generic_stack else_stack;
int isnum ( char *string, long *num );
static int if_exec ( int argc, char **argv ) {
int zero = 0;
if ( argc != 2 ) {
printf ( "Syntax: if <condition>\n" );
- return -1;
+ return 1;
}
if ( !isnum ( argv[1], &cond ) ) {
- printf ( "non-numeric condition\n" );
- return -1;
+ printf ( "non-numeric condition: %s\n", argv[1] );
+ return 1;
}
- cond = cond ? 1 : 0;
- push_generic_stack ( &else_stack, &zero, 0 );
- push_generic_stack ( &if_stack, &cond, 0 );
-
- if ( ( if_tos == -1 || ( ( int * ) if_stack.ptr )[if_tos] ) && if_stack.tos - if_tos == 1 ) /* If the top of logical stack == 1 and the current command has been pushed over it */
- if_tos++;
-
- //printf ( "Condition is %ld\n", cond );
+ cond = TOP_GEN_STACK_INT ( &if_stack ) ? ( cond ? 1 : 0 ) : 0;
+ if ( ( push_generic_stack ( &else_stack, &zero, 0 ) < 0 ) || ( push_generic_stack ( &if_stack, &cond, 0 ) < 0 ) ) {
+ free_generic_stack ( &if_stack );
+ free_generic_stack ( &else_stack );
+ return 1;
+ }
+
return 0;
}
int cond;
if ( argc != 1 ) {
printf ( "Syntax: %s\n", argv[0] );
- return -1;
+ return 1;
}
- if ( pop_generic_stack ( &if_stack, &cond ) == 0 ) {
- if ( if_tos - 1 == if_stack.tos ) {
- if_tos = if_stack.tos;
- }
+ if ( if_stack.tos > 0 ) {
+ if ( pop_generic_stack ( &if_stack, &cond ) < 0 )
+ return 1;
} else {
printf ( "fi without if\n" );
- return -1;
+ return 1;
}
return 0;
}
static int else_exec ( int argc, char **argv ) {
if ( argc != 1 ) {
printf ( "Syntax: %s\n", argv[0] );
+ return 1;
}
- if ( ( ( int * ) else_stack.ptr )[else_stack.tos] != 0 ) {
+ if ( TOP_GEN_STACK_INT ( &else_stack ) != 0 ) {
printf ( "else without if\n" );
- return -1;
+ return 1;
}
- if ( if_tos == if_stack.tos ) {
- ( ( int * ) if_stack.ptr )[if_stack.tos] = !( ( ( int * ) if_stack.ptr )[if_stack.tos] );
- }
+ if ( ELEMENT_GEN_STACK_INT ( &if_stack, if_stack.tos - 1 ) )
+ TOP_GEN_STACK_INT ( &if_stack ) = !TOP_GEN_STACK_INT ( &if_stack );
+
return 0;
}
struct command else_command __command = {
.name = "else",
.exec = else_exec,
+};
+
+void init_if ( void ) {
+ int one = 1;
+ init_generic_stack ( &if_stack, sizeof ( int ) );
+ init_generic_stack ( &else_stack, sizeof ( int ) );
+ 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,
};
\ No newline at end of file
#include <gpxe/gen_stack.h>
-
-
void init_generic_stack ( struct generic_stack *stack, size_t size ) {
stack->ptr = NULL;
stack->tos = -1;
stack->size = size;
}
-
int pop_generic_stack ( struct generic_stack *stack, void *ptr ) {
if ( stack->tos >= 0 ) {
void *nptr;
#include <stdlib.h>
#include <gpxe/settings.h>
+const struct char_table arith_table[21] = {
+ { .token = '\\', .type = FUNC, .next.parse_func = parse_escape },
+ { .token = '"', .type = TABLE, .next = { .next_table = { .ntable = dquote_table, .len = 3 } } },
+ { .token = '$', .type = FUNC, .next.parse_func = dollar_expand },
+ { .token = '\'', .type = TABLE, .next = { .next_table = { .ntable = squote_table, .len = 1 } } },
+ { .token = ' ', .type = ENDQUOTES },
+ { .token = '\t', .type = ENDQUOTES },
+ { .token = '~', .type = ENDTOK },
+ { .token = '!', .type = ENDTOK },
+ { .token = '*', .type = ENDTOK },
+ { .token = '/', .type = ENDTOK },
+ { .token = '%', .type = ENDTOK },
+ { .token = '+', .type = ENDTOK },
+ { .token = '-', .type = ENDTOK },
+ { .token = '<', .type = ENDTOK },
+ { .token = '=', .type = ENDTOK },
+ { .token = '>', .type = ENDTOK },
+ { .token = '&', .type = ENDTOK },
+ { .token = '|', .type = ENDTOK },
+ { .token = '^', .type = ENDTOK },
+ { .token = '(', .type = ENDTOK },
+ { .token = ')', .type = ENDTOK }
+};
+
+const struct char_table dquote_table[3] = {
+ { .token = '"', .type = ENDQUOTES },
+ { .token = '$', .type = FUNC, .next.parse_func = dollar_expand },
+ { .token = '\\', .type = FUNC, .next.parse_func = parse_escape }
+};
+const struct char_table squote_table[1] = {
+ { .token = '\'', .type = ENDQUOTES }
+};
+const struct char_table table[6] = {
+ { .token = '\\', .type = FUNC, .next.parse_func = parse_escape },
+ { .token = '"', .type = TABLE, .next =
+ {.next_table = { .ntable = dquote_table, .len = 3 } } },
+ { .token = '$', .type = FUNC, .next.parse_func = dollar_expand },
+ { .token = '\'', .type = TABLE, .next = { .next_table = { .ntable = squote_table, .len = 1 } } },
+ { .token = ' ', .type = ENDTOK },
+ { .token = '\t', .type = ENDTOK }
+};
+
char * string3cat ( struct string *s1, const char *s2, const char *s3 ) { /* The len is the size of s1 */
char *tmp = s1->value;
asprintf ( &s1->value, "%s%s%s", s1->value, s2, s3 );
char * parse_escape ( struct string *s, char *input, char **end ) {
char *exp;
+ if ( ! input[1] ) {
+ printf ( "stray \\\n" );
+ return s->value;
+ }
*input = 0;
*end = input + 2;
if ( input[1] == '\n' ) {
*success = 1;
*cur_pos = 0;
tmp = s->value;
- stringcat ( s, cur_pos + 1 );
+
+ if ( !stringcat ( s, cur_pos + 1 ) ) {
+ printf ( "stringcat failed\n" );
+ return NULL;
+ }
+ /* tmp is now invalid. Should not be dereferenced */
cur_pos = s->value + ( cur_pos - tmp );
if ( !expand_string ( s, &cur_pos, &end, tline->next.next_table.ntable, tline->next.next_table.len, 1, &s2 ) ) {
return NULL;
break;
case FUNC: /* Call another function */
{
- char *nstr;
-
*success = 1;
- nstr = tline->next.parse_func ( s, cur_pos, &cur_pos );
- if ( !nstr ) {
+ if ( ! tline->next.parse_func ( s, cur_pos, &cur_pos ) )
return NULL;
- }
}
break;
int pop_generic_stack ( struct generic_stack *stack, void *ptr );
void free_generic_stack ( struct generic_stack *stack, int on_stack );
+/* 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 )
+
#endif
\ No newline at end of file
int type;
union {
struct {
- struct char_table *ntable;
+ const struct char_table *ntable;
int len;
} next_table;
char * ( *parse_func ) ( struct string *, char *, char ** );
char * stringcpy ( struct string *s1, const char *s2 );
char * stringcat ( struct string *s1, const char *s2 );
-extern struct char_table dquote_table[3];
-extern struct char_table squote_table[1];
+extern const struct char_table dquote_table[3];
+extern const struct char_table squote_table[1];
+extern const struct char_table arith_table[21];
+extern const struct char_table table[6];
#endif
\ No newline at end of file