Shell Variable and Symbol Processing

The MicroMonitor CLI provides for two similar types of token substitution: shell variables and symbols. Shell variables (strings preceded by $ ) get their substitution data from the MicroMonitor environment in RAM. Symbols (strings preceded by % ) get their substitution data from a file. From the parsing point of view, both symbols and shell variables are handled exactly the same way except that, at the time of substitution, MicroMonitor searches a file for symbols and the environment for shell variables. Shell variables are convenient and do not require a file system; however, storage of a large number of shell variables is a bit impractical because of the RAM space needed and the volatility of the RAM. On the other hand, if TFS is included in the monitor build, then a symbol table file can be downloaded to TFS, and the system can process a large number of symbols because the data is stored in flash memory. I typically use the symbol table feature of MicroMonitor for storage of the applications actual symbol-to-address list. Putting the symbol-to-address list in a symbol table makes debugging more convenient when I am not attached to a symbolic debugger.

Listing 5.5 shows the code in the docommand() function that initiates the substitution.

Listing 5.5: Expanding Shell Variables and Symbols.
image from book
 /* If there are any instances of a dollar or percent sign within the   * command line, then expand any shell variables (or symbols) that may  * be present.  */ if (strpbrk(cmdcpy,"$%")) {     if (expandshellvars(cmdcpy) < 0) {         return(CMD_LINE_ERROR);     } } 
image from book
 

The workhorse for this functionality is the expandshellvars() function (see Listing 5.6). The expandshellvars() function is passed a string that is to be expanded with all shell variables converted. It supports variables of type $VARNAME and ${VARNAME} . The expandshellvars() function also supports the ability to have shell variables embedded within shell variables. For example ${VAR${ NAME }} causes a two-pass expansion in which ${NAME} is evaluated and then ${VARXXX} is evaluated (where XXX is whatever was in the variable ${NAME} ).

Listing 5.6: expandshellvars().
image from book
 int expandshellvars(char *newstring) {     char    *cp;     int     result, cno, ndp;     /* Verify that there is a balanced set of braces in the incoming      * string...      */     ndp = 0;     if (braceimbalance(newstring,&cno,&ndp)) {         printf("Brace imbalance @ %d%s.\n",             cno,ndp ? " ({ missing $ or %)" : "");         return(-1);     }     /* Process the variable names within braces... */     while((result = processbraces(newstring)) == 1);     if (result == -1)         return(-1);     /* Process dollar signs (left-most first)...    */     while((result = processprefixes(newstring)) == 1);     if (result == -1)         return(-1);     /* Cleanup any remaining "\{", "\}" or "$" strings... */     cp = newstring+1;      while(*cp) {         if (*cp == '{'  *cp == '}'  *cp == '$'  *cp == '%') {             if (*(cp-1) == '\') {                 strcpy(cp-1,cp);                 cp -= 2;             }         }         cp++;     }     return(0); } 
image from book
 

The function braceimbalance() in Listing 5.6 does some preprocessing to verify the basic sanity of the command line. The braceimbalance() function returns zero if there is an even number of braces on the command line. It takes into account backslash processing (meaning that a \} or \{ is taken as a literal brace instead of a brace enclosing a shell variable). If braceimbalance() returns non-zero , an error message is printed, and an error ( 1 ) is returned. If braceimbalance() completes successfully, then the rest of the code can at least assume basic brace sanity in the line. If the braces balance, expandshellvars() calls processbraces(). This function looks into the incoming string for the deepest set of braces and replaces those braces and the enclosed variable name with the value stored in the corresponding shell variable. The function returns 1 if a set of braces was processed , and if all braces have been processed. Also, processbraces() returns -1 if some kind of processing error occurs.

The processprefixes() function conducts a similiar looping process. It processes the $ for shell variables and the % for symbols. The processprefixes() function looks for the last $ (or % ) in the incoming string and attempts to make a shell variable (or symbol) substitution. If no prefix ( $ or % ) is found, processprefixes() returns 0.

The bottom while loop in Listing 5.6 removes any backslashes that may have been present to provide immunity to the previous special-case character processing. The complete code for each of these functions is on the CD. Because of the nitty-gritty detail involved in parsing each line, only the top-level details have been repeated here.



Embedded Systems Firmware Demystified
Embedded Systems Firmware Demystified (With CD-ROM)
ISBN: 1578200997
EAN: 2147483647
Year: 2002
Pages: 118
Authors: Ed Sutter

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net