/**CFile**************************************************************** FileName [verStream.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Verilog parser.] Synopsis [Input file stream, which knows nothing about Verilog.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - August 19, 2006.] Revision [$Id: verStream.c,v 1.00 2006/08/19 00:00:00 alanmi Exp $] ***********************************************************************/ #include "ver.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// #define VER_BUFFER_SIZE 1048576 // 1M - size of the data chunk stored in memory #define VER_OFFSET_SIZE 65536 // 64K - load new data when less than this is left #define VER_WORD_SIZE 65536 // 64K - the largest token that can be returned #define VER_MINIMUM(a,b) (((a) < (b))? (a) : (b)) struct Ver_Stream_t_ { // the input file char * pFileName; // the input file name FILE * pFile; // the input file pointer iword nFileSize; // the total number of bytes in the file iword nFileRead; // the number of bytes currently read from file iword nLineCounter; // the counter of lines processed // temporary storage for data iword nBufferSize; // the size of the buffer char * pBuffer; // 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 char pChars[VER_WORD_SIZE+5]; // temporary storage for a word (plus end-of-string and two parantheses) int nChars; // the total number of characters in the word // status of the parser int fStop; // this flag goes high when the end of file is reached }; static void Ver_StreamReload( Ver_Stream_t * p ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the file reader for the given file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ver_Stream_t * Ver_StreamAlloc( char * pFileName ) { Ver_Stream_t * p; FILE * pFile; int nCharsToRead; int RetValue; // check if the file can be opened pFile = fopen( pFileName, "rb" ); if ( pFile == NULL ) { printf( "Ver_StreamAlloc(): Cannot open input file \"%s\".\n", pFileName ); return NULL; } // start the file reader p = ABC_ALLOC( Ver_Stream_t, 1 ); memset( p, 0, sizeof(Ver_Stream_t) ); p->pFileName = pFileName; p->pFile = pFile; // 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, VER_BUFFER_SIZE+1 ); p->nBufferSize = VER_BUFFER_SIZE; p->pBufferCur = p->pBuffer; // determine how many chars to read nCharsToRead = VER_MINIMUM(p->nFileSize, VER_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 + VER_BUFFER_SIZE - VER_OFFSET_SIZE; // start the arrays p->nLineCounter = 1; // 1-based line counting return p; } /**Function************************************************************* Synopsis [Loads new data into the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamReload( Ver_Stream_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 = VER_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 + VER_BUFFER_SIZE - VER_OFFSET_SIZE; } /**Function************************************************************* Synopsis [Stops the file reader.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamFree( Ver_Stream_t * p ) { if ( p->pFile ) fclose( p->pFile ); ABC_FREE( p->pBuffer ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ver_StreamGetFileName( Ver_Stream_t * p ) { return p->pFileName; } /**Function************************************************************* Synopsis [Returns the file size.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamGetFileSize( Ver_Stream_t * p ) { return p->nFileSize; } /**Function************************************************************* Synopsis [Returns the current reading position.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamGetCurPosition( Ver_Stream_t * p ) { return p->nFileRead - (p->pBufferEnd - p->pBufferCur); } /**Function************************************************************* Synopsis [Returns the line number for the given token.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamGetLineNumber( Ver_Stream_t * p ) { return p->nLineCounter; } /**Function************************************************************* Synopsis [Returns current symbol.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Ver_StreamIsOkey( Ver_Stream_t * p ) { return !p->fStop; } /**Function************************************************************* Synopsis [Returns current symbol.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char Ver_StreamScanChar( Ver_Stream_t * p ) { assert( !p->fStop ); return *p->pBufferCur; } /**Function************************************************************* Synopsis [Returns current symbol and moves to the next.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char Ver_StreamPopChar( Ver_Stream_t * p ) { assert( !p->fStop ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // check if there are symbols left if ( p->pBufferCur == p->pBufferEnd ) // end of file { p->fStop = 1; return -1; } // count the lines if ( *p->pBufferCur == '\n' ) p->nLineCounter++; return *p->pBufferCur++; } /**Function************************************************************* Synopsis [Skips the current symbol and all symbols from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamSkipChars( Ver_Stream_t * p, char * pCharsToSkip ) { char * pChar, * pTemp; assert( !p->fStop ); assert( pCharsToSkip != NULL ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // skip the symbols for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // skip symbols as long as they are in the list for ( pTemp = pCharsToSkip; *pTemp; pTemp++ ) if ( *pChar == *pTemp ) break; if ( *pTemp == 0 ) // pChar is not found in the list { p->pBufferCur = pChar; return; } // count the lines if ( *pChar == '\n' ) p->nLineCounter++; } // the file is finished or the last part continued // through VER_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { p->fStop = 1; return; } printf( "Ver_StreamSkipSymbol() failed to parse the file \"%s\".\n", p->pFileName ); } /**Function************************************************************* Synopsis [Skips all symbols until encountering one from the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ver_StreamSkipToChars( Ver_Stream_t * p, char * pCharsToStop ) { char * pChar, * pTemp; assert( !p->fStop ); assert( pCharsToStop != NULL ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // skip the symbols for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // skip symbols as long as they are NOT in the list for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) if ( *pChar == *pTemp ) break; if ( *pTemp == 0 ) // pChar is not found in the list { // count the lines if ( *pChar == '\n' ) p->nLineCounter++; continue; } // the symbol is found - move position and return p->pBufferCur = pChar; return; } // the file is finished or the last part continued // through VER_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { p->fStop = 1; return; } printf( "Ver_StreamSkipToSymbol() failed to parse the file \"%s\".\n", p->pFileName ); } /**Function************************************************************* Synopsis [Returns current word delimited by the set of symbols.] Description [Modifies the stream by inserting 0 at the first encounter of one of the symbols in the list.] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ver_StreamGetWord( Ver_Stream_t * p, char * pCharsToStop ) { char * pChar, * pTemp; if ( p->fStop ) return NULL; assert( pCharsToStop != NULL ); // check if the new data should to be loaded if ( p->pBufferCur > p->pBufferStop ) Ver_StreamReload( p ); // skip the symbols p->nChars = 0; for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ ) { // skip symbols as long as they are NOT in the list for ( pTemp = pCharsToStop; *pTemp; pTemp++ ) if ( *pChar == *pTemp ) break; if ( *pTemp == 0 ) // pChar is not found in the list { p->pChars[p->nChars++] = *pChar; if ( p->nChars == VER_WORD_SIZE ) { printf( "Ver_StreamGetWord(): The buffer size is exceeded.\n" ); return NULL; } // count the lines if ( *pChar == '\n' ) p->nLineCounter++; continue; } // the symbol is found - move the position, set the word end, return the word p->pBufferCur = pChar; p->pChars[p->nChars] = 0; return p->pChars; } // the file is finished or the last part continued // through VER_OFFSET_SIZE chars till the end of the buffer if ( p->pBufferStop == p->pBufferEnd ) // end of file { p->fStop = 1; p->pChars[p->nChars] = 0; return p->pChars; } printf( "Ver_StreamGetWord() failed to parse the file \"%s\".\n", p->pFileName ); return NULL; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END