www.pudn.com > vxworks_usb.rar > cmdParser.c


/* cmdParser.c - Command line parser routines. */

/* Copyright 2000 Wind River Systems, Inc. */

/*
Modification history
--------------------
01f,18sep01,wef  merge from wrs.tor2_0.usb1_1-f for veloce, fixed formatting
01e,08aug01,dat  Removing warnings
01d,31jul01,wef  fix man page generation errors
01c,23nov99,rcb  Make KeywordMatch() function public.
01b,16aug99,rcb  Add option in CmdParserHelpFunc to display help only for
		 a specific command.
01a,01jun99,rcb  First.
*/

/*
DESCRIPTION

This file includes a collection of command-line parsing functions which are
useful in the creation of command line utilities, such as bus exercisers.

There are three groups of functions defined by this library.  The first is
a collection of general string parser functions, such as functions to eliminate
white space, functions to strip tokens out of a string, and so forth.  

The second set of functions drive the actual parsing process.  In order to 
use this second set of functions, clients must construct a table of CMD_DESCR
structures which define the commands to be recognized by the parser.  A 
brief example of such a table is shown below.

.CS
CMD_DESCR Commands [] =
    {
    {"Help", 4, "Help/?", "Displays list of commands.", CmdParserHelpFunc},
    {"?",    1, NULL,	  NULL, 	    CmdParserHelpFunc},
    {"Exit", 4, "Exit",   "Exits program.",	CmdParserExitFunc},
    {NULL,   0, NULL,	  NULL, 	    NULL}
    };
.CE

The first field is the keyword for the command.  The second field specifies
the number of characters of the command which must match - allowing the user
to enter only a portion of the keyword as a shortcut.  The third and fourth
fields are strings giving the command usage and a brief help string.  A NULL
in the Help field indicates that the corresponding keyword is a synonym for 
another command its usage/help should not be shown.  The final field is a 
pointer to a function of type CMD_EXEC_FUNC which will be invoked if the 
parser encounters the corresponding command.

The third group of functions provide standard CMD_EXEC_FUNCs for certain
commonly used commands, such as CmdParserHelpFunc and CmdParserExitFunc as
shown in the preceding example.

The caller may pass a generic (pVOID) parameter to the command line parsing
functions in the second group.	This function is in turn passed to the
CMD_EXEC_FUNCs.  In this way, the caller can specify context information
for the command execution functions.

Commands are executed after the user presses [enter].  Multiple commands may 
be entered on the same command line separated by semicolons (';').  Each 
command as if it had been entered on a separate line (unless a command 
terminates with an error, in which case all remaining commands entered on the 
same line will be ignored).
*/


/* Include files */

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "ctype.h"

#include "usb/usbPlatform.h"    /* Basic definitions */
#include "usb/tools/cmdParser.h"    /* Our API */


/* Constants */

#define PAUSE_DISPLAY	    22  /* Help display pauses every n lines */


/*************************************************************************
*
* PromptAndExecCmd - Prompt for a command and execute it.
*
* Displays  to  and prompts for input from . Then, 
* parses/executes the command.	 points to an array of
* CMD_DESCR structures defining the command to be recognized by the
* parser, and  is a generic parameter passed down to individual 
* command execution functions.
*
* RETURNS:  RET_OK for normal termination
*	RET_ERROR for program failure.
*	RET_CONTINUE if execution should continue.
*/

UINT16 PromptAndExecCmd (pVOID param,   /* Generic parameter for exec funcs */
                         char *pPrompt, /* Prompt to display */
                         FILE * fin,    /* Input stream */
                         FILE * fout,   /* Output stream */
                         CMD_DESCR * pCmdTable  /* CMD_DESCR table */
    )
{
    char cmd[MAX_CMD_LEN];      /* Buffer for input command */


    /* Display prompt */

    fprintf (fout, pPrompt);


    /* Retrieve input */

    if (fgets (cmd, sizeof (cmd), fin) != cmd)
        return RET_ERROR;


    /* Execute input */

    return ExecCmd (param, cmd, fin, fout, pCmdTable);
}


/*************************************************************************
*
* KeywordMatch - Compare keywords
*
* Compares  and  up to  characters, case insensitive.  
* Returns 0 if strings are equal.  
*
* NOTE: This function is equivalent to strnicmp(), but that function is
* not available in all libraries.
*
* RETURNS:  0 if s1 and s2 are the same
*	-n if s1 < s2
*	+n if s1 > s2
*/

int KeywordMatch (char *s1,     /* string 1 */
                  char *s2,     /* string 2 */
                  int len       /* max length to compare */
    )
{
    int n = 0;

    for (; len > 0; len--) {
        if ((n = toupper (*s1) - toupper (*s2)) != 0 || *s1 == 0 || *s2 == 0)
            break;
        s1++;
        s2++;
    }

    return n;
}


/*************************************************************************
*
* ExecCmd - Execute the command line
*
* Parses and executes the commands in the  buffer.  I/O - if any -
* will go to /.  The  may contain any number of commands
* separated by CMD_SEPARATOR.  points to an array of
* CMD_DESCR structures defining the command to be recognized by the
* parser, and  is a generic parameter passed down to individual 
* command execution functions.
*
* RETURNS:  RET_OK for normal termination.
*	RET_ERROR for program failure.
*	RET_CONTINUE if execution should continue.
*/

UINT16 ExecCmd (pVOID param,    /* Generic parameter for exec funcs */
                char *pCmd,     /* Cmd buffer to be parsed/executed */
                FILE * fin,     /* Stream for input */
                FILE * fout,    /* Stream for output */
                CMD_DESCR * pCmdTable   /* CMD_DESCR table */
    )
{
    UINT16 s = RET_CONTINUE;    /* Execution status */

    char keyword[MAX_KEYWORD_LEN];  /* Bfr for command keyword */

    CMD_DESCR *pEntry;          /* Pointer to entry in CmdTable */

    /* Parse each command on the command line. */

    TruncSpace (pCmd);

    do {

        /* Retrieve keyword and match against known keywords. */

        pCmd = GetNextToken (pCmd, keyword, sizeof (keyword));

        if (strlen (keyword) > 0) {
            for (pEntry = pCmdTable; pEntry != NULL && pEntry->keyword != NULL; pEntry++) {
                if (KeywordMatch (pEntry->keyword,
                                  keyword, max (strlen (keyword), (unsigned) pEntry->minMatch))
                    == 0) {

                    /* 
                     * We found a matching keyword.  Execute the CMD_EXEC_FUNC
                     * for this command. 
                     */

                    if (pEntry->execFunc == CmdParserHelpFunc)

                        s = (*pEntry->execFunc) (pCmdTable, &pCmd, fin, fout);

                    else

                        s = (*pEntry->execFunc) (param, &pCmd, fin, fout);

                    break;
                }
            }

            if (pEntry == NULL || pEntry->keyword == NULL) {
                fprintf (fout, "Unrecognized command: %s\n", keyword);
                break;
            }
        }

        /* Skip over trailing CMD_SEPARATOR characters. */

        if (*pCmd != CMD_SEPARATOR)
            while (*pCmd != CMD_SEPARATOR && *pCmd != 0)
                pCmd++;

        while (*pCmd == CMD_SEPARATOR)
            pCmd++;
    }
    while (strlen (pCmd) > 0 && s == RET_CONTINUE);

    return s;
}



/*************************************************************************
*
* SkipSpace - Skips leading white space in a string
*
* Returns a pointer to the first non-white-space character in .
*
* RETURNS: Ptr to first non-white-space character in 
*/

#define IS_SPACE(c) (isspace ((int) (c)) || ((c) > 0 && (c) < 32))

char *SkipSpace (char *pStr     /* Input string */
    )
{
    while (IS_SPACE (*pStr))
        pStr++;

    return pStr;
}


/*************************************************************************
*
* TruncSpace - Truncates string to eliminate trailing whitespace
*
* Trucates  to eliminate trailing white space.  Returns count
* of characters left in  upon return.
*
* RETURNS: Number of characters in  after truncation.
*/

UINT16 TruncSpace (char *pStr   /* Input string */
    )
{
    UINT16 len;

    while ((len = strlen (pStr)) > 0 && IS_SPACE (pStr[len - 1]))
        pStr[len - 1] = 0;

    return len;
}


/*************************************************************************
*
* GetNextToken - Retrieves the next token from an input string
*
* Copies the next token from  to .  White space before the
* next token is discarded.  Tokens are delimited by white space and by
* the command separator, CMD_SEPARATOR.  No more than  - 1
* characters from  will be copied into .	 must be
* at least one and  will be NULL terminated upon return.
*
* RETURNS: Pointer into  following end of copied .
*/

char *GetNextToken (char *pStr, /* Input string */
                    char *pToken,   /* Bfr to receive token */
                    UINT16 tokenLen /* Max length of Token bfr */
    )
{
    UINT16 len;                 /* Temporary length counter */

    /* Skip leading white space */

    pStr = SkipSpace (pStr);


    /* Copy next token into Token bfr */

    pToken[0] = 0;

    while ((len = strlen (pToken)) < tokenLen &&
           *pStr != 0 && !IS_SPACE (*pStr) && *pStr != CMD_SEPARATOR) {
        pToken[len] = *pStr;
        pToken[len + 1] = 0;
        pStr++;
    }

    return pStr;
}


/*************************************************************************
*
* GetHexToken - Retrieves value of hex token
*
* Retrieves the next token from  line, interprets it as a hex 
* value, and stores the result in .  If there are no remaining 
* tokens, stores  in  instead.
*
* RETURNS: Pointer into  following end of copied 
*/

char *GetHexToken (char *pStr,  /* input string */
                   long *pToken,    /* buffer to receive token value */
                   long defVal  /* default value */
    )
{
    char temp[9];               /* Temp storage for token */

    /* Retrieve next token */

    pStr = GetNextToken (pStr, temp, sizeof (temp));

    /* Evaluate Token value */

    if (strlen (temp) == 0 || sscanf (temp, "%lx", pToken) == 0)
        *pToken = defVal;

    return pStr;
}


/*************************************************************************
*
* CmdParserHelpFunc - Displays list of supported commands
*
* Displays the list of commands in the parser command table to .	
* When the parser recognizes that this function is about to be executed, 
* it substitutes a pointer to the current CMD_DESCR table in . 
* If this function is called directly,  should point to a table
* of CMD_DESCR structures.
*
* RETURNS: RET_CONTINUE
*/

UINT16 CmdParserHelpFunc (pVOID param,  /* Generic parameter passed down */
                          char **ppCmd, /* Ptr to remainder of cmd line */
                          FILE * fin,   /* stream for input (if any) */
                          FILE * fout   /* stream for output (if any) */
    )
{
    CMD_DESCR *pCmdTable = (CMD_DESCR *) param;
    char keyword[MAX_KEYWORD_LEN];
    int lines = 0;


    *ppCmd = GetNextToken (*ppCmd, keyword, sizeof (keyword));


    if (strlen (keyword) == 0)
        fprintf (fout, "\n");

    for (; pCmdTable != NULL && pCmdTable->keyword != NULL; pCmdTable++) {
        if (pCmdTable->help != NULL) {
            /* If a parameter has been entered, display help only for 
             * matching cmds */

            if (strlen (keyword) > 0)
                if (KeywordMatch (pCmdTable->keyword,
                                  keyword, max (strlen (keyword), (unsigned) pCmdTable->minMatch))
                    != 0)
                    continue;

            /* Pause the display every PAUSE_DISPLAY lines */

            if (lines == PAUSE_DISPLAY) {
                fprintf (fout, "[Press a key to continue]");
                fgetc (fin);
                fprintf (fout, "\r		\r");
                lines = 0;
            }

            fprintf (fout, "%*s  %s\n",
                     (strlen (keyword) == 0) ? 22 : 0,
                     (pCmdTable->usage == NULL) ?
                     pCmdTable->keyword : pCmdTable->usage, pCmdTable->help);

            ++lines;
        }
    }

    if (strlen (keyword) == 0)
        fprintf (fout, "\n\n");

    return RET_CONTINUE;
}


/*************************************************************************
*
* CmdParserExitFunc - Terminates parser execution
*
* Returns RET_OK, causing the parser to return RET_OK to the caller
* signally normal termination of the parser.
*
* RETURNS: RET_OK
*/

UINT16 CmdParserExitFunc (pVOID param,  /* Generic parameter passed down */
                          char **ppCmd, /* Ptr to remainder of cmd line */
                          FILE * fin,   /* stream for input (if any) */
                          FILE * fout   /* stream for output (if any) */
    )
{
    return RET_OK;
}


/* End of file. */