[scripting] Implemented quoting
authorLynus Vaz <lynus@Arch.localdomain>
Thu, 18 Jun 2009 13:30:02 +0000 (19:00 +0530)
committerLynus Vaz <lynus@Arch.localdomain>
Thu, 18 Jun 2009 13:30:02 +0000 (19:00 +0530)
src/core/exec.c
src/hci/arith.c

index 7358a5a..5cb50e0 100644 (file)
@@ -93,18 +93,25 @@ struct argument {
 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' ) {
@@ -116,35 +123,46 @@ char * parse_dquote ( char *inp, char **end ) {
                                }
                                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 );
@@ -153,16 +171,12 @@ char * dollar_expand ( char *inp ) {
 
                /* 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;
@@ -170,15 +184,13 @@ char * dollar_expand ( char *inp ) {
                {
                        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;       
@@ -198,9 +210,9 @@ int expand_command ( const char *command, struct argument **argv_start ) {
        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;
@@ -209,11 +221,11 @@ int expand_command ( const char *command, struct argument **argv_start ) {
        /* 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;
@@ -233,20 +245,32 @@ int expand_command ( const char *command, struct argument **argv_start ) {
                                }
                                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, '\'' );
@@ -260,13 +284,12 @@ int expand_command ( const char *command, struct argument **argv_start ) {
                                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:
@@ -282,45 +305,16 @@ int expand_command ( const char *command, struct argument **argv_start ) {
                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
  *
@@ -359,17 +353,26 @@ int system ( const char *command ) {
        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;
 }
index bedf33b..eecff49 100644 (file)
 #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 )
@@ -82,6 +87,89 @@ static void input ( void ) {
                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 ) ) {
@@ -90,22 +178,6 @@ static void input ( void ) {
                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 );
@@ -127,6 +199,8 @@ static void input ( void ) {
        }
        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 */
@@ -367,7 +441,8 @@ static int parse_expr ( char **buffer ) {
 
 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;
        
@@ -403,7 +478,7 @@ int parse_arith ( char *inp_string, char **end, char **buffer ) {
                                printf("out of memory\n");
                                break;
                }
-               return - ( EINVAL | -err_val );
+               return err_val;
        }
        
        return 0;