1 /**CFile****************************************************************
2 
3   FileName    [extraUtilReader.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [extra]
8 
9   Synopsis    [File reading utilities.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: extraUtilReader.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include <stdio.h>
22 #include "extra.h"
23 #include "misc/vec/vec.h"
24 
25 ABC_NAMESPACE_IMPL_START
26 
27 
28 ////////////////////////////////////////////////////////////////////////
29 ///                        DECLARATIONS                              ///
30 ////////////////////////////////////////////////////////////////////////
31 
32 #define EXTRA_BUFFER_SIZE        4*1048576    // 1M   - size of the data chunk stored in memory
33 #define EXTRA_OFFSET_SIZE           4096    // 4K   - load new data when less than this is left
34 
35 #define EXTRA_MINIMUM(a,b)       (((a) < (b))? (a) : (b))
36 
37 struct Extra_FileReader_t_
38 {
39     // the input file
40     char *           pFileName;     // the input file name
41     FILE *           pFile;         // the input file pointer
42     int              nFileSize;     // the total number of bytes in the file
43     int              nFileRead;     // the number of bytes currently read from file
44     // info about processing different types of input chars
45     char             pCharMap[256]; // the character map
46     // temporary storage for data
47     char *           pBuffer;       // the buffer
48     int              nBufferSize;   // the size of the buffer
49     char *           pBufferCur;    // the current reading position
50     char *           pBufferEnd;    // the first position not used by currently loaded data
51     char *           pBufferStop;   // the position where loading new data will be done
52     // tokens given to the user
53     Vec_Ptr_t *      vTokens;       // the vector of tokens returned to the user
54     Vec_Int_t *      vLines;        // the vector of line numbers for each token
55     int              nLineCounter;  // the counter of lines processed
56     // status of the parser
57     int              fStop;         // this flag goes high when the end of file is reached
58 };
59 
60 // character types
61 typedef enum {
62     EXTRA_CHAR_COMMENT,  // a character that begins the comment
63     EXTRA_CHAR_NORMAL,   // a regular character
64     EXTRA_CHAR_STOP,     // a character that delimits a series of tokens
65     EXTRA_CHAR_CLEAN     // a character that should be cleaned
66 } Extra_CharType_t;
67 
68 // the static functions
69 static void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p );
70 static void Extra_FileReaderReload( Extra_FileReader_t * p );
71 
72 ////////////////////////////////////////////////////////////////////////
73 ///                     FUNCTION DEFINITIONS                         ///
74 ////////////////////////////////////////////////////////////////////////
75 
76 /**Function*************************************************************
77 
78   Synopsis    [Starts the file reader.]
79 
80   Description []
81 
82   SideEffects []
83 
84   SeeAlso     []
85 
86 ***********************************************************************/
Extra_FileReaderAlloc(char * pFileName,char * pCharsComment,char * pCharsStop,char * pCharsClean)87 Extra_FileReader_t * Extra_FileReaderAlloc( char * pFileName,
88     char * pCharsComment, char * pCharsStop, char * pCharsClean )
89 {
90     Extra_FileReader_t * p;
91     FILE * pFile;
92     char * pChar;
93     int nCharsToRead;
94     int RetValue;
95     // check if the file can be opened
96     pFile = fopen( pFileName, "rb" );
97     if ( pFile == NULL )
98     {
99         printf( "Extra_FileReaderAlloc(): Cannot open input file \"%s\".\n", pFileName );
100         return NULL;
101     }
102     // start the file reader
103     p = ABC_ALLOC( Extra_FileReader_t, 1 );
104     memset( p, 0, sizeof(Extra_FileReader_t) );
105     p->pFileName   = pFileName;
106     p->pFile       = pFile;
107     // set the character map
108     memset( p->pCharMap, EXTRA_CHAR_NORMAL, 256 );
109     for ( pChar = pCharsComment; *pChar; pChar++ )
110         p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_COMMENT;
111     for ( pChar = pCharsStop; *pChar; pChar++ )
112         p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_STOP;
113     for ( pChar = pCharsClean; *pChar; pChar++ )
114         p->pCharMap[(unsigned char)*pChar] = EXTRA_CHAR_CLEAN;
115     // get the file size, in bytes
116     fseek( pFile, 0, SEEK_END );
117     p->nFileSize = ftell( pFile );
118     rewind( pFile );
119     // allocate the buffer
120     p->pBuffer = ABC_ALLOC( char, EXTRA_BUFFER_SIZE+1 );
121     p->nBufferSize = EXTRA_BUFFER_SIZE;
122     p->pBufferCur  = p->pBuffer;
123     // determine how many chars to read
124     nCharsToRead = EXTRA_MINIMUM(p->nFileSize, EXTRA_BUFFER_SIZE);
125     // load the first part into the buffer
126     RetValue = fread( p->pBuffer, nCharsToRead, 1, p->pFile );
127     p->nFileRead = nCharsToRead;
128     // set the ponters to the end and the stopping point
129     p->pBufferEnd  = p->pBuffer + nCharsToRead;
130     p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
131     // start the arrays
132     p->vTokens = Vec_PtrAlloc( 100 );
133     p->vLines = Vec_IntAlloc( 100 );
134     p->nLineCounter = 1; // 1-based line counting
135     return p;
136 }
137 
138 /**Function*************************************************************
139 
140   Synopsis    [Stops the file reader.]
141 
142   Description []
143 
144   SideEffects []
145 
146   SeeAlso     []
147 
148 ***********************************************************************/
Extra_FileReaderFree(Extra_FileReader_t * p)149 void Extra_FileReaderFree( Extra_FileReader_t * p )
150 {
151     if ( p->pFile )
152         fclose( p->pFile );
153     ABC_FREE( p->pBuffer );
154     Vec_PtrFree( p->vTokens );
155     Vec_IntFree( p->vLines );
156     ABC_FREE( p );
157 }
158 
159 /**Function*************************************************************
160 
161   Synopsis    [Returns the file size.]
162 
163   Description []
164 
165   SideEffects []
166 
167   SeeAlso     []
168 
169 ***********************************************************************/
Extra_FileReaderGetFileName(Extra_FileReader_t * p)170 char * Extra_FileReaderGetFileName( Extra_FileReader_t * p )
171 {
172     return p->pFileName;
173 }
174 
175 /**Function*************************************************************
176 
177   Synopsis    [Returns the file size.]
178 
179   Description []
180 
181   SideEffects []
182 
183   SeeAlso     []
184 
185 ***********************************************************************/
Extra_FileReaderGetFileSize(Extra_FileReader_t * p)186 int Extra_FileReaderGetFileSize( Extra_FileReader_t * p )
187 {
188     return p->nFileSize;
189 }
190 
191 /**Function*************************************************************
192 
193   Synopsis    [Returns the current reading position.]
194 
195   Description []
196 
197   SideEffects []
198 
199   SeeAlso     []
200 
201 ***********************************************************************/
Extra_FileReaderGetCurPosition(Extra_FileReader_t * p)202 int Extra_FileReaderGetCurPosition( Extra_FileReader_t * p )
203 {
204     return p->nFileRead - (p->pBufferEnd - p->pBufferCur);
205 }
206 
207 /**Function*************************************************************
208 
209   Synopsis    [Returns the line number for the given token.]
210 
211   Description []
212 
213   SideEffects []
214 
215   SeeAlso     []
216 
217 ***********************************************************************/
Extra_FileReaderGetLineNumber(Extra_FileReader_t * p,int iToken)218 int Extra_FileReaderGetLineNumber( Extra_FileReader_t * p, int iToken )
219 {
220     assert( iToken >= 0 && iToken < p->vTokens->nSize );
221     return p->vLines->pArray[iToken];
222 }
223 
224 
225 /**Function*************************************************************
226 
227   Synopsis    [Returns the next set of tokens.]
228 
229   Description []
230 
231   SideEffects []
232 
233   SeeAlso     []
234 
235 ***********************************************************************/
Extra_FileReaderGetTokens(Extra_FileReader_t * p)236 void * Extra_FileReaderGetTokens( Extra_FileReader_t * p )
237 {
238     Vec_Ptr_t * vTokens;
239     while ( (vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens_int( p )) )
240         if ( vTokens->nSize > 0 )
241             break;
242     return vTokens;
243 }
244 
245 /**Function*************************************************************
246 
247   Synopsis    [Returns the next set of tokens.]
248 
249   Description []
250 
251   SideEffects []
252 
253   SeeAlso     []
254 
255 ***********************************************************************/
Extra_FileReaderGetTokens_int(Extra_FileReader_t * p)256 void * Extra_FileReaderGetTokens_int( Extra_FileReader_t * p )
257 {
258     char * pChar;
259     int fTokenStarted, MapValue;
260     if ( p->fStop )
261         return NULL;
262     // reset the token info
263     p->vTokens->nSize = 0;
264     p->vLines->nSize = 0;
265     fTokenStarted = 0;
266     // check if the new data should to be loaded
267     if ( p->pBufferCur > p->pBufferStop )
268         Extra_FileReaderReload( p );
269 
270 //    printf( "%d\n", p->pBufferEnd - p->pBufferCur );
271 
272     // process the string starting from the current position
273     for ( pChar = p->pBufferCur; pChar < p->pBufferEnd; pChar++ )
274     {
275         // count the lines
276         if ( *pChar == '\n' )
277             p->nLineCounter++;
278         // switch depending on the character
279         MapValue = p->pCharMap[(int)*pChar];
280 
281 //        printf( "Char value = %d. Map value = %d.\n", *pChar, MapValue );
282 
283 
284         switch ( MapValue )
285         {
286             case EXTRA_CHAR_COMMENT:
287                 if ( *pChar != '/' || *(pChar+1) == '/' )
288                 { // dealing with the need to have // as a comment
289                     // if the token was being written, stop it
290                     if ( fTokenStarted )
291                         fTokenStarted = 0;
292                     // eraze the comment till the end of line
293                     while ( *pChar != '\n' )
294                     {
295                         *pChar++ = 0;
296                         if ( pChar == p->pBufferEnd )
297                         {   // this failure is due to the fact the comment continued
298                             // through EXTRA_OFFSET_SIZE chars till the end of the buffer
299                             printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
300                             return NULL;
301                         }
302                     }
303                     pChar--;
304                     break;
305                 }
306                 // otherwise it is a normal character
307             case EXTRA_CHAR_NORMAL:
308                 if ( !fTokenStarted )
309                 {
310                     Vec_PtrPush( p->vTokens, pChar );
311                     Vec_IntPush( p->vLines, p->nLineCounter );
312                     fTokenStarted = 1;
313                 }
314                 break;
315             case EXTRA_CHAR_STOP:
316                 if ( fTokenStarted )
317                     fTokenStarted = 0;
318                 *pChar = 0;
319                 // prepare before leaving
320                 p->pBufferCur = pChar + 1;
321                 return p->vTokens;
322             case EXTRA_CHAR_CLEAN:
323                 if ( fTokenStarted )
324                     fTokenStarted = 0;
325                 *pChar = 0;
326                 break;
327             default:
328                 assert( 0 );
329         }
330     }
331     // the file is finished or the last part continued
332     // through EXTRA_OFFSET_SIZE chars till the end of the buffer
333     if ( p->pBufferStop == p->pBufferEnd ) // end of file
334     {
335         *pChar = 0;
336         p->fStop = 1;
337         return p->vTokens;
338     }
339     printf( "Extra_FileReader failed to parse the file \"%s\".\n", p->pFileName );
340 /*
341     {
342         int i;
343         for ( i = 0; i < p->vTokens->nSize; i++ )
344             printf( "%s ", p->vTokens->pArray[i] );
345         printf( "\n" );
346     }
347 */
348     return NULL;
349 }
350 
351 /**Function*************************************************************
352 
353   Synopsis    [Loads new data into the file reader.]
354 
355   Description []
356 
357   SideEffects []
358 
359   SeeAlso     []
360 
361 ***********************************************************************/
Extra_FileReaderReload(Extra_FileReader_t * p)362 void Extra_FileReaderReload( Extra_FileReader_t * p )
363 {
364     int nCharsUsed, nCharsToRead;
365     int RetValue;
366     assert( !p->fStop );
367     assert( p->pBufferCur > p->pBufferStop );
368     assert( p->pBufferCur < p->pBufferEnd );
369     // figure out how many chars are still not processed
370     nCharsUsed = p->pBufferEnd - p->pBufferCur;
371     // move the remaining data to the beginning of the buffer
372     memmove( p->pBuffer, p->pBufferCur, (size_t)nCharsUsed );
373     p->pBufferCur = p->pBuffer;
374     // determine how many chars we will read
375     nCharsToRead = EXTRA_MINIMUM( p->nBufferSize - nCharsUsed, p->nFileSize - p->nFileRead );
376     // read the chars
377     RetValue = fread( p->pBuffer + nCharsUsed, nCharsToRead, 1, p->pFile );
378     p->nFileRead += nCharsToRead;
379     // set the ponters to the end and the stopping point
380     p->pBufferEnd  = p->pBuffer + nCharsUsed + nCharsToRead;
381     p->pBufferStop = (p->nFileRead == p->nFileSize)? p->pBufferEnd : p->pBuffer + EXTRA_BUFFER_SIZE - EXTRA_OFFSET_SIZE;
382 }
383 
384 ////////////////////////////////////////////////////////////////////////
385 ///                       END OF FILE                                ///
386 ////////////////////////////////////////////////////////////////////////
387 
388 
389 ABC_NAMESPACE_IMPL_END
390 
391