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