| /**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 <stdio.h> |
| #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 |
| |