/**CFile**************************************************************** FileName [extraUtilReader.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [extra] Synopsis [File reading utilities.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include #include "extra.h" #include "misc/vec/vec.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define EXTRA_BUFFER_SIZE 4*1048576 // 1M - size of the data chunk stored in memory #define EXTRA_OFFSET_SIZE 4096 // 4K - load new data when less than this is left #define EXTRA_MINIMUM(a,b) (((a) < (b))? (a) : (b)) struct Extra_FileReader_t_ { // the input file char * pFileName; // the input file name FILE * pFile; // the input file pointer int nFileSize; // the total number of bytes in the file int nFileRead; // the number of bytes currently read from file // info about processing different types of input chars char pCharMap[256]; // the character map // temporary storage for data char * pBuffer; // the buffer int nBufferSize; // the size of the buffer char * pBufferCur; // the current reading position char * pBufferEnd; // the first position not used by currently loaded data char * pBufferStop; // the position where loading new data will be done // tokens given to the user Vec_Ptr_t * vTokens; // the vector of tokens returned to the user Vec_Int_t * vLines; // the vector of line numbers for each token int nLineCounter; // the counter of lines processed // status of the parser int fStop; // this flag goes high when the end of file is reached }; // character types typedef enum { EXTRA_CHAR_COMMENT, // a character that begins the comment EXTRA_CHAR_NORMAL, // a regular character EXTRA_CHAR_STOP, // a character that delimits a series of tokens EXTRA_CHAR_CLEAN // a character that should be cleaned } Extra_CharType_t; // the static functions static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ); static void Extra_FileReaderReload( Extra_FileReader_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName, char * pCharsComment, char * pCharsStop, char * pCharsClean ) { Extra_FileReader_t * p; FILE * pFile; char * pChar; int nCharsToRead; int RetValue; // check if the file can be opened pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName ); return NULL; } // start the file reader p = ABC_ALLOC( Extra_FileReader_t, 1 ); memset( p, 0, sizeof(Extra_FileReader_t) ); p->pFileName = pFileName; p->pFile = pFile; // set the character map memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 ); for ( pChar = pCharsComment; *pChar; pChar++ ) p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT; for ( pChar = pCharsStop; *pChar; pChar++ ) p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP; for ( pChar = pCharsClean; *pChar; pChar++ ) p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN; // get the file size, in bytes fseek( pFile, 0, SEEK_END ); p->nFileSize = ftell( pFile ); rewind( pFile ); // allocate the buffer p->pBuffer = ABC_ALLOC( char, EXTRA_BUFFER_SIZE+1 ); p->nBufferSize = EXTRA_BUFFER_SIZE; p->pBufferCur = p->pBuffer; // determine how many chars to read nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE); // load the first part into the buffer RetValue = fread( p->pBuffer, nCharsToRead, 1, p->pFile ); p->nFileRead = nCharsToRead; // set the ponters to the end and the stopping point p->pBufferEnd = p->pBuffer + nCharsToRead; p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; // start the arrays p->vTokens = Vec_PtrAlloc( 100 ); p->vLines = Vec_IntAlloc( 100 ); p->nLineCounter = 1; // 1-based line counting return p; } /**Function************************************************************* Synopsis [Stops the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileReaderFree( Extra_FileReader_t * p ) { if ( p->pFile ) fclose( p->pFile ); ABC_FREE( p->pBuffer ); Vec_PtrFree( p->vTokens ); Vec_IntFree( p->vLines ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Extra_FileReaderGetFileName( Extra_FileReader_t * p ) { return p->pFileName; } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileReaderGetFileSize( Extra_FileReader_t * p ) { return p->nFileSize; } /**Function************************************************************* Synopsis [Returns the current reading position.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p ) { return p->nFileRead - (p->pBufferEnd - p->pBufferCur); } /**Function************************************************************* Synopsis [Returns the line number for the given token.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken ) { assert( iToken >= 0 && iToken < p->vTokens->nSize ); return p->vLines->pArray[iToken]; } /**Function************************************************************* Synopsis [Returns the next set of tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Extra_FileReaderGetTokens( Extra_FileReader_t * p ) { Vec_Ptr_t * vTokens; while ( (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens_int( p )) ) if ( vTokens->nSize > 0 ) break; return vTokens; } /**Function************************************************************* Synopsis [Returns the next set of tokens.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p ) { char * pChar; int fTokenStarted, MapValue; if ( p->fStop ) return NULL; // reset the token info p->vTokens->nSize = 0; p->vLines->nSize = 0; fTokenStarted = 0; // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Extra_FileReaderReload( p ); // printf( "%d\n", p->pBufferEnd - p->pBufferCur ); // process the string starting from the current position for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // count the lines if ( *pChar == '\n' ) p->nLineCounter++; // switch depending on the character MapValue = p->pCharMap[(int)*pChar]; // printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue ); switch ( MapValue ) { case EXTRA_CHAR_COMMENT: if ( *pChar != '/' || *(pChar+1) == '/' ) { // dealing with the need to have // as a comment // if the token was being written, stop it if ( fTokenStarted ) fTokenStarted = 0; // eraze the comment till the end of line while ( *pChar != '\n' ) { *pChar++ = 0; if ( pChar == p->pBufferEnd ) { // this failure is due to the fact the comment continued // through EXTRA_OFFSET_SIZE chars till the end of the buffer printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); return NULL; } } pChar--; break; } // otherwise it is a normal character case EXTRA_CHAR_NORMAL: if ( !fTokenStarted ) { Vec_PtrPush( p->vTokens, pChar ); Vec_IntPush( p->vLines, p->nLineCounter ); fTokenStarted = 1; } break; case EXTRA_CHAR_STOP: if ( fTokenStarted ) fTokenStarted = 0; *pChar = 0; // prepare before leaving p->pBufferCur = pChar + 1; return p->vTokens; case EXTRA_CHAR_CLEAN: if ( fTokenStarted ) fTokenStarted = 0; *pChar = 0; break; default: assert( 0 ); } } // the file is finished or the last part continued // through EXTRA_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { *pChar = 0; p->fStop = 1; return p->vTokens; } printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName ); /* { int i; for ( i = 0; i < p->vTokens->nSize; i++ ) printf( "%s ", p->vTokens->pArray[i] ); printf( "\n" ); } */ return NULL; } /**Function************************************************************* Synopsis [Loads new data into the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Extra_FileReaderReload( Extra_FileReader_t * p ) { int nCharsUsed, nCharsToRead; int RetValue; assert( !p->fStop ); assert( p->pBufferCur > p->pBufferStop ); assert( p->pBufferCur < p->pBufferEnd ); // figure out how many chars are still not processed nCharsUsed = p->pBufferEnd - p->pBufferCur; // move the remaining data to the beginning of the buffer memmove( p->pBuffer, p->pBufferCur, nCharsUsed ); p->pBufferCur = p->pBuffer; // determine how many chars we will read nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead ); // read the chars RetValue = fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile ); p->nFileRead += nCharsToRead; // set the ponters to the end and the stopping point p->pBufferEnd = p->pBuffer + nCharsUsed + nCharsToRead; p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END