/* * Reader.c * Author: Hannah C. Tang (hctang@cs) * * Implementation of public and private functions for the * Reader struct * * $Id: Reader.c,v 1.4 2001/12/18 14:48:49 cse466_t Exp $ * */ #include #include #include #include "Reader.h" #include "common.h" /* * PRIVATE: * * Reader struct, method for skipping past whitespace and comments */ struct Reader { FILE *pFile; }; static unsigned int Reader_skipWhitespace( struct Reader *pR, Bool *nlWasSkipped ); static unsigned int Reader_skipWhitespaceAndComments( struct Reader *pR ); /* Dynamically allocate a Reader struct. */ struct Reader* Reader_malloc( FILE *pInFile ) { struct Reader *pR = ( struct Reader* ) malloc( sizeof( struct Reader ) ); if( pR == NULL ) { fprintf( stderr, "Out of memory allocating a Reader!\n" ); exit( 0 ); } if( pInFile == NULL ) { fprintf( stderr, "Error: Cannot read from NULL file\n" ); free( pR ); exit( 0 ); } pR->pFile = pInFile; return pR; } /* Deallocate a Reader struct */ void Reader_free( struct Reader *pR ) { if( pR != NULL ) { if( fclose( pR->pFile ) ) { fprintf( stderr, "Could not close file for reading\n" ); } free( pR ); } } /* Return the type of the next token */ enum Reader_TokenType Reader_getNextTokenType( struct Reader *pR ) { int next = -1; enum Reader_TokenType t; Reader_skipWhitespaceAndComments( pR ); next = getc( pR->pFile ); if( next < 0 || next > 254 ) { return END_OF_FILE; } /* Figure out what charecter we got */ switch( next ) { case 'M': /* Beginning of a mode block */ t = MODE_START; break; case 'P': /* Beginning of the program block */ t = PROGRAM_START; break; case '(': /* Begining of another sequence tuple */ t = SEQUENCE; break; case 'L': /* Beginning of a loop */ t = LOOP_START; break; case '}': /* End of a block */ t = BLOCK_END; break; default: /* If we've gotten to this point, then there was a parse error somewhere */ fprintf( stderr, "Malformed input: unrecognized charecter %c\n", next ); exit( 0 ); } /* Put back the charecter we fetched */ ungetc( next, pR->pFile ); return t; } /* Get the value of the user-specified mode. Returns Bool_false * if not successful */ Bool Reader_getMode( struct Reader *pR, unsigned int* pNewModeNum ) { int c; int retVal; c = getc( pR->pFile ); if( c != 'M' ) { ungetc( c, pR->pFile ); return Bool_false; } Reader_skipWhitespaceAndComments( pR ); /* Get the mode number */ retVal = fscanf( pR->pFile, "%ui", pNewModeNum ); if( retVal == 0 || retVal == EOF ) { return Bool_false; } Reader_skipWhitespaceAndComments( pR ); c = getc( pR->pFile ); if( c != '{' ) { ungetc( c, pR->pFile ); return Bool_false; } return Bool_true; } /* Get the mode-sequence values as a bit-vector. Returns Bool_false * if not successful */ Bool Reader_getModeSequence( struct Reader *pR, unsigned int *pModeSeq ) { unsigned int c, i = 0; int retVal = 0; c = getc( pR->pFile ); if( c != '(' ) { ungetc( c, pR->pFile ); return Bool_false; } /* I'm going to hard-code the number of bits in an unsigned int/light * as 16. This may not be very extensible */ for( ; i < 16; i++ ) { Reader_skipWhitespaceAndComments( pR ); if( !fscanf( pR->pFile, "%ui", &c ) ) { ungetc( c, pR->pFile ); fprintf( stderr, "Error reading from input!\n" ); return Bool_false; } if( c != 0 && c != 1 ) { ungetc( c, pR->pFile ); fprintf( stderr, "Unrecognized charecter %c (ascii %d) in" " mode specification\n", (char) c, c ); return Bool_false; } /* OR our input into our current bit vector */ retVal |= ( c << i ); } Reader_skipWhitespaceAndComments( pR ); c = getc( pR->pFile ); if( c != ')' ) { ungetc( c, pR->pFile ); return Bool_false; } *pModeSeq = retVal; return Bool_true; } /* Clear out the Program-start flag. Returns Bool_false if * not successful */ Bool Reader_getProgram( struct Reader *pR ) { int c; c = getc( pR->pFile ); if( c != 'P' ) { ungetc( c, pR->pFile ); return Bool_false; } Reader_skipWhitespaceAndComments( pR ); c = getc( pR->pFile ); if( c != '{' ) { ungetc( c, pR->pFile ); return Bool_false; } return Bool_true; } /* Get the sequence-values. Returns Bool_false if not successful */ Bool Reader_getSequence( struct Reader *pR, unsigned int *pLength, unsigned int *pPeriod, unsigned int *pMode ) { int c; int retVal; c = getc( pR->pFile ); if( c != '(' ) { ungetc( c, pR->pFile ); return Bool_false; } Reader_skipWhitespaceAndComments( pR ); /* Get the numbers in the sequence */ retVal = fscanf( pR->pFile, "%ui", pLength ); Reader_skipWhitespaceAndComments( pR ); retVal += fscanf( pR->pFile, "%ui", pPeriod ); Reader_skipWhitespaceAndComments( pR ); retVal += fscanf( pR->pFile, "%ui", pMode ); if( retVal != 3 ) { return Bool_false; } Reader_skipWhitespaceAndComments( pR ); c = getc( pR->pFile ); if( c != ')' ) { ungetc( c, pR->pFile ); return Bool_false; } return Bool_true; } /* Get the number of times this loop should execute */ Bool Reader_getLoop( struct Reader *pR, unsigned int *pNumLoops ) { int retVal; int c; c = getc( pR->pFile ); if( c != 'L' ) { ungetc( c, pR->pFile ); return Bool_false; } Reader_skipWhitespaceAndComments( pR ); /* Get the number of loops */ retVal = fscanf( pR->pFile, "%ui", pNumLoops ); if( retVal != 1 ) { return Bool_false; } Reader_skipWhitespaceAndComments( pR ); c = getc( pR->pFile ); if( c != '{' ) { ungetc( c, pR->pFile ); return Bool_false; } return Bool_true; } /* Clear out the loop-end flag */ Bool Reader_getBlockEnd( struct Reader *pR ) { int c; c = getc( pR->pFile ); if( c != '}' ) { ungetc( c, pR->pFile ); return Bool_false; } return Bool_true; } /* Skip whitespace in the input */ static unsigned int Reader_skipWhitespace( struct Reader *pR, Bool *nlWasSkipped ) { int next; unsigned int count = -1; do { next = getc( pR->pFile ); count++; if( next == '\n' ) { *nlWasSkipped = Bool_true; } } while( next != EOF && !isgraph( next ) ); /* Put back the charecter we fetched, unless we're at EOF */ ungetc( next, pR->pFile ); return count; } static unsigned int Reader_skipWhitespaceAndComments( struct Reader* pR ) { Bool commentExists = Bool_false; Bool nlWasSkipped; unsigned int count = -1; int next; do { /* Get rid of whitespace and a single charecter */ count += Reader_skipWhitespace( pR, &nlWasSkipped ); next = getc( pR->pFile ); count++; if( next == '#' ) { /* We just found a comment to clear out */ commentExists = Bool_true; nlWasSkipped = Bool_false; } if( next == EOF ) { /* This comment terminated with the end of the file */ commentExists = Bool_false; } if( commentExists && nlWasSkipped ) { /* Check the next line for comments */ if( next == EOF || next != '#' ) { /* This comment terminated with non-comments or the EOF */ commentExists = Bool_false; } } } while( commentExists ); ungetc( next, pR->pFile ); return count; }