/* * =========================================================== * parser.c -- parse a string into a token table * * Functions defined: wordLength, parseString, freeTable, * error, skipWhiteSpace, showTable * =========================================================== */ #include /* for malloc, calloc, realloc declarations */ #include /* for strchr decl. */ #include /* for isspace decl. */ #include #include #include "parser.h" /* * ================================================================ * return length of next word pointed to by cpStart or 0 if none * ================================================================ */ int wordLength( const char * cpStart ) { char * cpEnd; /* [a] : Test for end of string first */ if( '\0' == *cpStart ) return 0; /* [b] : find next separator in string and calculate length of field */ cpEnd = strchr( cpStart, Separator ); if( 0 == cpEnd) { /* Separator not found, so see */ cpEnd = strchr( cpStart, 0 ); /* if this is the last word ? */ if( 0 == cpEnd ) error( "No terminating zero found in string", __LINE__ ); /* error condition */ } return (cpEnd - cpStart); } /* * ================================================================ * Parse a string pointed to by cpCmdLine into an "argv" like array * of pointers to char strings. * ================================================================ */ char ** parseString( char * cpCmdLine ) { char * cpStart; /* pointers for parsing/copying words */ char ** cppCommands; /* pointer to table */ int iCmdCount = 0; /* count of words/commands in the string so far */ int iCmdLength; /* length of next field in the string */ /* [a] : initialization */ cpStart = cpCmdLine; /* start parsing at beginning of string */ cppCommands = NULL; /* cppCommands is 0 initially, realloc resets */ /* [b] : parse the line, build array of pointers to each word */ /* While still words on input line, extend table */ while( 0 != (iCmdLength = wordLength( cpStart )) ) { if( 0 == cppCommands ) { /* unix hack (BC++ does it right) */ cppCommands = (char**) malloc( sizeof(char *) *(iCmdCount + 1)); if( 0 == cppCommands) error( "malloc failure in parse", __LINE__ ); } else if( 0 == ( cppCommands = (char**) realloc((malloc_t) cppCommands, sizeof(char *) * (iCmdCount + 1) ))) error( "realloc failure in parse", __LINE__ ); /* initialize next value */ cppCommands[iCmdCount] = (char *) malloc( (iCmdLength + 1)*sizeof(char) ); if( 0 == cppCommands[iCmdCount] ) error( "malloc failure in parse", __LINE__ ); /* copy the string into the new allocated memory */ strncpy( cppCommands[iCmdCount], cpStart, iCmdLength ); /* add terminating 0 or NULL */ *(cppCommands[iCmdCount] + iCmdLength) = '\0'; /* update counters/pointers */ iCmdCount++; cpStart += iCmdLength; /* move just past end of word/command */ cpStart = skipWhiteSpace( cpStart ); /* skip any white space before next word */ } /* terminate the table (need a zero at the end like argv[argc] */ /* first, check that table was built, */ if( 0 == cppCommands ) return 0; /* early exit */ cppCommands = (char**) realloc((malloc_t) cppCommands, sizeof(char *) * (iCmdCount + 1)); if( 0 == cppCommands ) error( "realloc failure in parse", __LINE__ ); cppCommands[iCmdCount] = NULL; return cppCommands; } /* * =========================================== * free the memory used to build a parse table * =========================================== */ void freeTable( char ** cppTable ) { char ** cppFree = cppTable; /* make a copy for stepping through the table */ /* [a] : free each of the character pointers in the table */ while( 0 != *cppFree ) free( *cppFree++ ); /* [b] : free the table itself */ free( (char*)cppTable ); return; } /* * ================================ * print the error message and exit * ================================ */ void error( char * cpMessage, int iLine ){ printf( "\nFatal Error: %s on line %3i.", cpMessage, iLine ); exit(1); } /* * ============================================== * starting at cpStart, skip over any white space * ============================================== */ char * skipWhiteSpace( char * cpStart ) { while( '\0' != *cpStart && isspace( *cpStart ) ) { putchar( *cpStart ); cpStart++; } return cpStart; } /* * ====================================== * print the table pointed to by cppTable * ====================================== */ void showTable( char ** cppTable ) { int iOffset; /* index into table */ /* [a] : print the table information */ printf( "\n (Address) |Contents|" ); printf( "\n---------------------------------------------" ); printf( "\n&cppTable (%8x) |%8x|", &cppTable, cppTable ); printf( "\n---------------------------------------------" ); iOffset = 0; while( 0 != cppTable[iOffset] ) { printf( "\ncppTable+%-2i(%8x) |%8x|", iOffset, cppTable+iOffset, cppTable[iOffset] ); iOffset++; } /* [b] : print the character strings referred to by the table */ iOffset = 0; printf( "\n---------------------------------------------" ); while( 0 != cppTable[iOffset] ) { printf( "\n (%8x) |%s\\0|", cppTable[iOffset], cppTable[iOffset] ); iOffset++; } return; }