/*/////////
//
//  splitline.c ( adapted from Bruce's splitline.c )
//
//      AUTHOR: Russell Lowke
//   CSCIE-215: Assignment Five
//
//       Usage: a component of smsh
//              Contains methods to parse strings and general string
//              handling, also has routines to check for valid variable
//              names.
//
//     Methods: 
//
//           splitline - parse line [cmdline] into an array of strings
//                       cmdline has a string of white-space separated tokens
//                       put the addresses of the tokens in the array argv[]
//                       put their number in *argcp and do not put more than max
//                       in argv or suffer dire consequences!
//                       NOTE: this modifies cmdline
//                       returns FALSE on too many args or zero args.
//                       TRUE for ok stuff
//      substituteVars - search through original string [orgStr] looking for
//                       embeded vars ('$') and backslash ('\\').  
//                       In case of backslash read the next char 'as is',
//                       otherwise, in case of viarable, substitute in the
//                       variables value.
//                       Put the result into new string [newStr].
//        validVarName - Test string [varName] to see if it is a legal variable
//                       name. Done primarily using isValidVarChar - but also
//                       tests for 1st char not being a number
//      isValidVarChar - Check if a char [c] is considered legal when in a
//                       variable name.
//                       Legal values are: numbers from 0 through 9
//                                        A - Z, a - z, and underscore.
//
*/

#include	"splitline.h"

/*
//  splitline
//
//     parse line [cmdline] into an array of strings
//     cmdline has a string of white-space separated tokens
//     put the addresses of the tokens in the array argv[]
//     put their number in *argcp and do not put more than max 
//     in argv or suffer dire consequences!
//     NOTE: this modifies cmdline
//     returns FALSE on too many args or zero args.  TRUE for ok stuff
//
//     args:  *cmdline    --  line to be parsed into array
//            *argcp      --  argument count
//            *argv[]     --  list of args
//            max         --  limit
*/
int splitline(char *cmdline, int *argcp, char *argv[], int max)
{
    int   i      = 0,
          retval = FALSE;
    char  mode   = ' ',
         *cmdp   = cmdline;

    while ( i<=max ){			            /* still room?            */
						    /* skip leading space     */
        while ( *cmdp == ' ' || *cmdp == '\t' )
            cmdp++;
					
        if ( *cmdp == '\0' )                        /* at end of string?      */
            break;

        if ( *cmdp == '\"' ) {                      /* start of a quote?      */
            cmdp++;                                 /* bump pointer           */
            mode = '\"';                            /* change to quote mode   */
        }
						    /* record string          */
        argv[i++] = cmdp ;		            /* and bump counter       */
		
                                                 /* move to end of word quote */
        while ( *++cmdp && *cmdp != mode && *cmdp != '\t' )
            ;

        mode = ' ';                                 /* revert mode to space   */

        if ( *cmdp != '\0' )		            /* past end of word       */
            *cmdp++ = '\0';                         /* terminate string       */
    }

    if ( i > max )
        printf("Too many args\n");
    else if ( i > 0 ){
        argv[i] = NULL ;                            /* mark end of array      */
       *argcp   = i;                                /* and store argc         */
        retval  = TRUE ;                            /* say ok                 */
    }
    
    return retval ;
}


/*
//  substituteVars
//
//     search through original string [orgStr] looking for embeded vars
//     ('$') and backslash ('\\').  In case of backslash read the next char
//     'as is', otherwise, in case of viarable, substitute in the variables
//     value. Put the result into new string [newStr].
*/
int substituteVars(char *orgStr, char *newStr)
{       
    char *tmpPtr,
          varName[BUFLEN];
    int i = 0;
    
    while (*orgStr) {
        if (*orgStr == '\\') {                      /* check for backslash    */
             orgStr++;                              /* move to next char      */
            *newStr++ = *orgStr++;                  /* add char to new str    */
        }
        else if (*orgStr == '$') {
            
            orgStr++;                               /* skip '$'               */
            while (isValidVarChar (*orgStr))        /* read valid chars       */
                varName[i++] = *orgStr++;
            
            varName[i] = '\0';                      /* terminate varName      */
            
            if (validVarName(varName)) {            /* ensure as valid        */
                tmpPtr = VLlookup(varName);

                while (*tmpPtr)
                    *newStr++ = *tmpPtr++;
            }

            i = 0;                         /* reset varName for other strings */
            
        }
        else
            *newStr++ = *orgStr++;                  /* add char to new str    */
    }
               
     *newStr = '\0';                                /* terminate newString    */
    
    return TRUE;
}

/*
//  validVarName
//
//     Test string [varName] to see if it is a legal variable name.
//     Done primarily using isValidVarChar - but also tests for 1st char not
//     being a number
//
//     args:  *varName  --  string being tested
*/
int validVarName (char *varName)
{      
    if (*varName >= '0' && *varName <= '9' )        /* numbers in first char? */
          return FALSE;

   while(*varName) {                                /*...use isValidVarChar   */
       if ( ! isValidVarChar( *varName ) )
           return FALSE;
       varName++;
   }

   return TRUE;                                     /* name OK                */
}

/*
//  isValidVarChar
//
//     Check if a char [c] is considered legal when in a variable name.
//     Legal values are: numbers from 0 through 9
//                       A - Z, a - z, and underscore.
//
//     args:  c         --  the char [c] being checked
//
//  Note: the case of the first char being a number 
//        is tested for in validVarName
*/
int isValidVarChar (char c) 
{    
    if ( (c < '0' ) ||                              /* check illegal chars    */
         (c > '9' && c < 'A' ) ||
         (c > 'Z' && c < 'a' && c != '_') ||
         (c > 'z') )
        return FALSE;
    else
        return TRUE;                                /* char [c] OK            */
}
