int parse_arith(char *inp_string, char **end, char **buffer);
char * parse_dquote ( char *inp, char **end );
-char * dollar_expand ( char *inp );
+char * dollar_expand ( char *inp, char **end );
char * parse_dquote ( char *inp, char **end ) {
char *head;
char *expquote;
char *var;
char *tmp;
- expquote = strdup ( inp );
+ int new_len;
+
+ *inp = 0;
+ expquote = strdup ( inp + 1 );
head = expquote;
- while ( *head && *head != '"' ) {
+ while ( *head ) {
switch ( *head ) {
+ case '"':
+ *head = 0;
+ *end = head + 1;
+ return expquote;
case '\\':
if ( head[1] ) {
if ( head[1] != '\n' ) {
}
break;
case '$':
- var = dollar_expand ( head );
+ var = dollar_expand ( head, &tmp );
+ if ( !tmp || !var ) {
+ *end = NULL;
+ free ( expquote );
+ return NULL;
+ }
+ head = tmp;
tmp = expquote;
- asprintf ( &expquote, "%s%s", expquote, var );
- head = expquote + ( head - tmp );
+ new_len = asprintf ( &expquote, "%s%s%s", expquote, var, head );
+ head = expquote + strlen ( tmp ) + strlen ( var );
+ free ( var );
free ( tmp );
+ if ( new_len < 0 )
+ return NULL;
break;
default:
head++;
}
}
+ printf ( "end of string while looking for \"\n" );
+ free ( expquote );
*end = head;
- return expquote;
+ return NULL;
}
-char * dollar_expand ( char *inp ) {
- char *expdollar;
+char * dollar_expand ( char *inp, char **end ) {
+ char *expdollar = NULL;
char *name;
- char *end;
int setting_len;
- int new_len;
+ //int new_len;
if ( inp[1] == '{' ) {
*inp = 0;
name = ( inp + 2 );
/* Locate closer */
- end = strstr ( name, "}" );
- if ( ! end )
+ *end = strstr ( name, "}" );
+ if ( ! *end )
return NULL;
- *end++ = '\0';
+ **end = '\0';
+ *end += 1;
/* Determine setting length */
setting_len = fetchf_named_setting ( name, NULL, 0 );
/* Read setting into temporary buffer */
{
- char setting_buf[ setting_len + 1 ];
+ char *setting_buf = malloc ( setting_len + 1 );
setting_buf[0] = '\0';
fetchf_named_setting ( name, setting_buf,
- sizeof ( setting_buf ) );
-
- /* Construct expanded string and discard old string */
- new_len = asprintf ( &expdollar, "%s%s", setting_buf, end );
- if ( new_len < 0 )
- return NULL;
+ setting_len + 1 );
+ return setting_buf;
}
} else if ( inp[1] == '(' ) {
*inp = 0;
{
int ret;
char *arith_res;
- ret = parse_arith ( name, &end, &arith_res );
+ ret = parse_arith ( name, end, &arith_res );
if( ret < 0 ) {
return NULL;
}
- new_len = asprintf ( &expdollar, "%s%s", arith_res, end );
- if ( new_len < 0 )
- return NULL;
+ return arith_res;
}
}
return expdollar;
char *start;
char *head;
//char *name;
- //char *tail;
+ char *tail;
//int setting_len;
- //int new_len;
+ int new_len;
char *tmp;
char *var;
struct argument *argv;
/* Obtain temporary modifiable copy of command line */
expcmd = strdup ( command );
if ( ! expcmd )
- return 0;
+ return -ENOMEM;
*argv_start = malloc ( sizeof ( struct argument ) );
if ( !*argv_start )
- return 0;
+ return -ENOMEM;
argv = *argv_start;
/* Expand while expansions remain */
head = expcmd;
}
break;
case '$':
- var = dollar_expand ( head );
+ var = dollar_expand ( head, &tail );
tmp = expcmd;
- asprintf ( &expcmd, "%s%s", expcmd, var );
+ new_len = asprintf ( &expcmd, "%s%s%s", expcmd, var, tail );
head = expcmd + ( head - tmp );
start = expcmd + ( start - tmp );
free ( tmp );
+ if ( new_len < 0 ) {
+ goto out_of_memory;
+ }
break;
case '"':
- var = parse_dquote ( head, &head );
+ var = parse_dquote ( head, &tmp );
+ if ( !var )
+ break;
+ head = tmp;
tmp = expcmd;
- asprintf ( &expcmd, "%s%s", expcmd, var );
- head = expcmd + ( head - tmp );
- start = expcmd + ( head - tmp );
+ new_len = asprintf ( &expcmd, "%s%s%s", expcmd, var, head );
+
+ start = expcmd + ( start - tmp );
+ head = expcmd + strlen ( tmp ) + strlen ( var );
+ free ( var );
free ( tmp );
+
+ if ( new_len < 0 )
+ goto out_of_memory;
+
break;
case '\'':
tmp = strchr ( head + 1, '\'' );
strncpy ( argv -> word, start, head - start );
argv -> word[head - start] = 0;
argv -> next = malloc ( sizeof ( struct argument ) ) ;
+ argv -> next -> next = NULL;
while ( isspace ( *head ) )
head++;
- printf ( "argv: %s %s\n", start, argv -> word );
argv = argv -> next;
start = head;
- printf ( "next: %s\n", start );
argc++;
break;
default:
free ( argv );
}
return argc;
-}
-
-/**
- * Split command line into argv array
- *
- * @v args Command line
- * @v argv Argument array to populate, or NULL
- * @ret argc Argument count
- *
- * Splits the command line into whitespace-delimited arguments. If @c
- * argv is non-NULL, any whitespace in the command line will be
- * replaced with NULs.
- */
-#if 0
-static int split_args ( char *args, char * argv[] ) {
- int argc = 0;
-
- while ( 1 ) {
- /* Skip over any whitespace / convert to NUL */
- while ( *args == ' ' ) {
- if ( argv )
- *args = '\0';
- args++;
- }
- /* Check for end of line */
- if ( ! *args )
- break;
- /* We have found the start of the next argument */
- if ( argv )
- argv[argc] = args;
- argc++;
- /* Skip to start of next whitespace, if any */
- while ( *args && ( *args != ' ' ) ) {
- args++;
- }
+out_of_memory:
+ while ( *argv_start != argv ) {
+ struct argument *tmp;
+ tmp = *argv_start;
+ *argv_start = ( *argv_start ) -> next;
}
- return argc;
+ free ( argv );
+ return -ENOMEM;
}
-#endif
+
/**
* Execute command line
*
free ( args );
#endif
argc = expand_command ( command, &argv_start );
+
+ if ( argc < 0 )
+ return -ENOMEM;
+
arg = argv_start;
{
char *argv[argc + 1];
for ( i = 0; i < argc; i++ ) {
+ struct argument *tmp;
+ tmp = arg;
argv[i] = arg -> word;
arg = arg -> next;
- printf ( "argv[%d] = %s\n", i, argv[i] );
+ free ( tmp );
}
argv[i] = NULL;
+
if ( argv[0][0] != '#' )
- rc = execv ( argv[0], argv );
+ rc = execv ( argv[0], argv );
+ for ( i = 0; i < argc; i++)
+ free ( argv[i] );
}
return rc;
}
#define SEP2 -1, -1
#ifndef __ARITH_TEST__
-#define EPARSE EUNIQ_01
-#define EDIV0 EUNIQ_02
-#define ENOOP EUNIQ_03
-#define EWRONGOP EUNIQ_04
+#define EPARSE (EINVAL | EUNIQ_01)
+#define EDIV0 (EINVAL | EUNIQ_02)
+#define ENOOP (EINVAL | EUNIQ_03)
+#define EWRONGOP (EINVAL | EUNIQ_04)
#else
#define EPARSE 1
#define EDIV0 2
#define EWRONGOP 4
#endif
-char *inp, *prev, *orig;
-int tok;
-int err_val;
-union {
+static char *inp, *prev, *orig;
+static int tok;
+static int err_val;
+static union {
long num_value;
char *str_value;
}tok_value;
/* Here is a table of the operators */
-const char op_table[NUM_OPS * 3 + 1] = { '!', SEP2 , '~', SEP2, '*', SEP2, '/', SEP2, '%', SEP2, '+', SEP2, '-', SEP2,
+static const char op_table[NUM_OPS * 3 + 1] = { '!', SEP2 , '~', SEP2, '*', SEP2, '/', SEP2, '%', SEP2, '+', SEP2, '-', SEP2,
'<', SEP2, '<', '=', SEP1, '<', '<', SEP1, '>', SEP2, '>', '=', SEP1, '>', '>', SEP1, '&', SEP2,
'|', SEP2, '^', SEP2, '&', '&', SEP1, '|', '|', SEP1, '!', '=', SEP1, '=', '=', SEP1, '\0'
};
-const char *keyword_table = " \t\v()!~*/%+-<=>&|^"; /* Characters that cannot appear in a string */
-signed const char op_prio[NUM_OPS] = { 10, 10, 9, 9, 9, 8, 8, 6, 6, 7, 6, 6, 7, 4, 3, 2, 1, 0, 5, 5 };
+static const char *keyword_table = " \t\v()'\"$!~*/%+-<=>&|^"; /* Characters that cannot appear in a string */
+static signed const char op_prio[NUM_OPS] = { 10, 10, 9, 9, 9, 8, 8, 6, 6, 7, 6, 6, 7, 4, 3, 2, 1, 0, 5, 5 };
static void ignore_whitespace ( void );
static int parse_expr ( char **buffer );
+char * dollar_expand ( char *inp, char **end );
+char * parse_dquote ( char *inp, char **end );
+
+
static void input ( void ) {
char t_op[3] = { '\0', '\0', '\0'};
char *p1, *p2;
+ char *strtmp = NULL, *tmp;
size_t len;
if ( tok == -1 )
tok = -1;
return;
}
+ tok = 0;
+ while ( 1 ) { /* Look for a string first */
+
+ if ( *inp == '$' ) {
+ char *var, *tail;
+ int new_len;
+ var = dollar_expand( inp, &tail );
+ tmp = orig;
+ new_len = asprintf ( &orig, "%s%s%s", orig, var, tail );
+ inp = orig + ( inp - tmp );
+ free ( tmp );
+ free ( var );
+ if ( new_len < 0 ) {
+ tok = -1;
+ err_val = -ENOMEM;
+ return;
+ }
+ }
+
+ if ( isdigit ( *inp ) )
+ break;
+
+ /* Check for a string */
+ len = strcspn ( inp, keyword_table );
+
+ if ( len > 0 ) {
+ inp += len;
+
+ if ( ( strtmp = malloc ( len + 1 ) ) == NULL ) {
+ tok = -1;
+ err_val = -ENOMEM;
+ return;
+ }
+ strncpy ( strtmp, inp - len, len );
+ strtmp[len] = 0;
+ } else if ( *inp == '\'' ) {
+ char *end;
+ end = strchr ( inp + 1, '\'' );
+ if ( ( strtmp = malloc ( end - inp ) ) == NULL ) {
+ tok = -1;
+ err_val = -ENOMEM;
+ return;
+ }
+ strncpy ( strtmp, inp + 1, end - inp - 1 );
+ strtmp[end - inp] = 0;
+ inp = end + 1;
+ } else if ( *inp == '"' ) {
+ int new_len;
+ strtmp = parse_dquote ( inp, &inp );
+ if ( !strtmp ) {
+ tok = -1;
+ err_val = -ENOMEM;
+ return;
+ }
+ tmp = orig;
+ new_len = asprintf ( &orig, "%s%s%s", orig, strtmp, inp );
+ free ( tmp );
+ if ( new_len < 0 ) {
+ free ( strtmp );
+ err_val = -ENOMEM;
+ return;
+ }
+ } else
+ break;
+
+ if ( tok == TOK_STRING ) {
+ int new_len;
+ tmp = tok_value.str_value;
+ new_len = asprintf ( &tok_value.str_value, "%s%s", tok_value.str_value, strtmp );
+ free ( tmp );
+ if ( new_len < 0 ) {
+ err_val = -ENOMEM;
+ return;
+ }
+ } else {
+ tok_value.str_value = strtmp;
+ tok = TOK_STRING;
+ }
+ }
+
+ if ( tok ) {
+ return;
+ }
/* Check for a number */
if ( isdigit ( *inp ) ) {
return;
}
- /* Check for a string */
- len = strcspn ( inp, keyword_table );
-
- if ( len > 0 ) {
- inp += len;
- tok = TOK_STRING;
-
- if ( ( tok_value.str_value = malloc ( len + 1 ) ) == NULL ) {
- err_val = -ENOMEM;
- return;
- }
- strncpy ( tok_value.str_value, inp - len, len );
- tok_value.str_value[len] = 0;
- return;
- }
-
/* Check for an operator */
t_op[0] = *inp++;
p1 = strstr ( op_table, t_op );
}
inp++;
tok = MIN_TOK + ( p2 - op_table ) / 3;
+ return;
+
}
/* Check if a string is a number: "-1" and "+42" is accepted, but not "-1a". If so, place it in num and return 1 else num = 0 and return 0 */
int parse_arith ( char *inp_string, char **end, char **buffer ) {
err_val = tok = 0;
- orig = inp = inp_string;
+ orig = strdup ( inp_string );
+ inp = orig;
input();
*buffer = NULL;
printf("out of memory\n");
break;
}
- return - ( EINVAL | -err_val );
+ return err_val;
}
return 0;