// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // fstream.c -- // // Author : Peter A. Buhr // Created On : Wed May 27 17:56:53 2015 // Last Modified By : Peter A. Buhr // Last Modified On : Tue Oct 1 20:59:45 2024 // Update Count : 582 // #include "fstream.hfa" // also includes iostream.hfa #include // vfprintf, vfscanf #include // exit #include // varargs #include // strncpy, strerror #include #include // errno #pragma GCC visibility push(default) // *********************************** ofstream *********************************** #define IO_MSG "I/O error: " // private void ?{}( ofstream & os, void * file ) with( os ) { file$ = file; sepDefault$ = true; sepOnOff$ = false; nlOnOff$ = true; prt$ = false; sawNL$ = false; sepSetCur$( os, sepGet( os ) ); sepSet( os, " " ); sepSetTuple( os, ", " ); } // ?{} inline bool getNL$( ofstream & os ) { return os.sawNL$; } inline bool setNL$( ofstream & os, bool state ) { bool temp = os.sawNL$; os.sawNL$ = state; return temp; } inline bool getANL$( ofstream & os ) { return os.nlOnOff$; } inline bool setANL$( ofstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; } inline bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; } inline void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; } inline void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; } inline const char * sepGetCur$( ofstream & os ) { return os.sepCur$; } inline void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; } inline bool getPrt$( ofstream & os ) { return os.prt$; } inline bool setPrt$( ofstream & os, bool state ) { bool temp = os.prt$; os.prt$ = state; return temp; } inline void lock( ofstream & os ) with( os ) { lock( os.lock$ ); } inline void unlock( ofstream & os ) { unlock( os.lock$ ); } // public void ?{}( ofstream & os ) { os.file$ = 0p; } void ?{}( ofstream & os, const char name[], const char mode[] ) { open( os, name, mode ); } void ?{}( ofstream & os, const char name[] ) { open( os, name, "w" ); } void ^?{}( ofstream & os ) { close( os ); } void nlOn( ofstream & os ) { os.nlOnOff$ = true; } void nlOff( ofstream & os ) { os.nlOnOff$ = false; } void sep( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); } void nosep( ofstream & os ) { os.sepOnOff$ = false; } bool sepOn( ofstream & os ) { bool temp = os.sepDefault$; os.sepDefault$ = true; if ( os.sepOnOff$ ) sepReset$( os ); // start of line ? return temp; } // sepOn bool sepOff( ofstream & os ) { bool temp = os.sepDefault$; os.sepDefault$ = false; sepReset$( os ); return temp; } // sepOff const char * sepGet( ofstream & os ) { return os.separator$; } void sepSet( ofstream & os, const char s[] ) { assert( s ); strncpy( os.separator$, s, ofstream_sepSize - 1 ); os.separator$[ofstream_sepSize - 1] = '\0'; } // sepSet const char * sepGetTuple( ofstream & os ) { return os.tupleSeparator$; } void sepSetTuple( ofstream & os, const char s[] ) { assert( s ); strncpy( os.tupleSeparator$, s, ofstream_sepSize - 1 ); os.tupleSeparator$[ofstream_sepSize - 1] = '\0'; } // sepSet void ends( ofstream & os ) { if ( getANL$( os ) ) nl( os ); else setPrt$( os, false ); // turn off if ( &os == &exit ) exit( EXIT_FAILURE ); if ( &os == &abort ) abort(); } // ends bool fail( ofstream & os ) { return os.file$ == 0 || ferror( (FILE *)(os.file$) ); } void clear( ofstream & os ) { clearerr( (FILE *)(os.file$) ); } int flush( ofstream & os ) { return fflush( (FILE *)(os.file$) ); } void open( ofstream & os, const char name[], const char mode[] ) { FILE * file; for ( cnt; 10 ) { errno = 0; file = fopen( name, mode ); if ( file != 0p || errno != EINTR ) break; // timer interrupt ? if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" ); } // for if ( file == 0p ) { throwResume (open_failure){ os }; // abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno ); } // if (os){ file }; // initialize } // open void open( ofstream & os, const char name[] ) { open( os, name, "w" ); } void close( ofstream & os ) with( os ) { if ( (FILE *)(file$) == 0p ) return; if ( (FILE *)(file$) == (FILE *)stdout || (FILE *)(file$) == (FILE *)stderr ) return; int ret; for ( cnt; 10 ) { errno = 0; ret = fclose( (FILE *)(file$) ); if ( ret != EOF || errno != EINTR ) break; // timer interrupt ? if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" ); } // for if ( ret == EOF ) { throw (close_failure){ os }; // abort | IO_MSG "close output" | nl | strerror( errno ); } // if file$ = 0p; // safety after close } // close ofstream & write( ofstream & os, const char data[], size_t size ) { if ( fail( os ) ) { throw (write_failure){ os }; // abort | IO_MSG "attempt write I/O on failed stream"; } // if if ( fwrite( data, 1, size, (FILE *)(os.file$) ) != size ) { throw (write_failure){ os }; // abort | IO_MSG "write" | nl | strerror( errno ); } // if return os; } // write int fmt( ofstream & os, const char format[], ... ) { va_list args; va_start( args, format ); int len; for ( cnt; 10 ) { errno = 0; disable_interrupts(); len = vfprintf( (FILE *)(os.file$), format, args ); enable_interrupts(); if ( len != EOF || errno != EINTR ) break; // timer interrupt ? if ( cnt == 9 ) abort( "ofstream fmt EINTR spinning exceeded" ); } // for if ( len == EOF ) { // error writing ? abort | IO_MSG "invalid write"; } // if va_end( args ); setPrt$( os, true ); // called in output cascade sepReset$( os ); // reset separator return len; } // fmt static ofstream soutFile = { (FILE *)stdout }; ofstream & sout = soutFile, & stdout = soutFile; static ofstream serrFile = { (FILE *)stderr }; ofstream & serr = serrFile, & stderr = serrFile; static ofstream lsoutFile = { (FILE *)stdout }; ofstream & lsout = lsoutFile; static ofstream exitFile = { (FILE *)stderr }; ofstream & exit = exitFile; static ofstream abortFile = { (FILE *)stderr }; ofstream & abort = abortFile; ofstream & nl( ofstream & os ) { nl$( os ); // call basic_ostream nl flush( os ); return os; } // nl // *********************************** ifstream *********************************** // private void ?{}( ifstream & is, void * file ) with( is ) { file$ = file; nlOnOff$ = false; // => skip newlines when reading single characters } // ?{} bool getANL$( ifstream & os ) { return os.nlOnOff$; } bool setANL$( ifstream & os, bool state ) { bool temp = os.nlOnOff$; os.nlOnOff$ = state; return temp; } inline void lock( ifstream & os ) with( os ) { lock( os.lock$ ); } inline void unlock( ifstream & os ) { unlock( os.lock$ ); } // public void ?{}( ifstream & is ) { is.file$ = 0p; } void ?{}( ifstream & is, const char name[], const char mode[] ) { open( is, name, mode ); } void ?{}( ifstream & is, const char name[] ) { open( is, name, "r" ); } void ^?{}( ifstream & is ) { close( is ); } bool fail( ifstream & is ) { return is.file$ == 0p || ferror( (FILE *)(is.file$) ); } void clear( ifstream & is ) { clearerr( (FILE *)(is.file$) ); } void nlOn( ifstream & os ) { os.nlOnOff$ = true; } void nlOff( ifstream & os ) { os.nlOnOff$ = false; } bool eof( ifstream & is ) { return feof( (FILE *)(is.file$) ) != 0; } void open( ifstream & is, const char name[], const char mode[] ) { FILE * file; for ( cnt; 10 ) { errno = 0; file = fopen( name, mode ); if ( file != 0p || errno != EINTR ) break; // timer interrupt ? if ( cnt == 9 ) abort( "ifstream open EINTR spinning exceeded" ); } // for if ( file == 0p ) { throwResume (open_failure){ is }; // abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno ); } // if (is){ file }; // initialize } // open void open( ifstream & is, const char name[] ) { open( is, name, "r" ); } void close( ifstream & is ) with( is ) { if ( (FILE *)(file$) == 0p ) return; if ( (FILE *)(file$) == (FILE *)stdin ) return; int ret; for ( cnt; 10 ) { errno = 0; ret = fclose( (FILE *)(file$) ); if ( ret != EOF || errno != EINTR ) break; // timer interrupt ? if ( cnt == 9 ) abort( "ifstream close EINTR spinning exceeded" ); } // for if ( ret == EOF ) { throw (close_failure){ is }; // abort | IO_MSG "close input" | nl | strerror( errno ); } // if file$ = 0p; // safety after close } // close ifstream & read( ifstream & is, char data[], size_t size ) { if ( fail( is ) ) { throw (read_failure){ is }; // abort | IO_MSG "attempt read I/O on failed stream"; } // if if ( fread( data, size, 1, (FILE *)(is.file$) ) == 0 ) { throw (read_failure){ is }; // abort | IO_MSG "read" | nl | strerror( errno ); } // if return is; } // read ifstream &ungetc( char c, ifstream & is ) { if ( fail( is ) ) { abort | IO_MSG "attempt ungetc I/O on failed stream"; } // if if ( ungetc( c, (FILE *)(is.file$) ) == EOF ) { abort | IO_MSG "ungetc" | nl | strerror( errno ); } // if return is; } // ungetc int fmt( ifstream & is, const char format[], ... ) { va_list args; va_start( args, format ); int nargs, tmperrno; for () { // no check for EINTR limit waiting for keyboard input disable_interrupts(); errno = 0; nargs = vfscanf( (FILE *)(is.file$), format, args ); tmperrno = errno; enable_interrupts(); if ( nargs != EOF || errno != EINTR ) break; // timer interrupt ? } // for if ( nargs == EOF ) { // EOF or matching failure ? if ( ! feof( (FILE *)(is.file$) ) && ferror( (FILE *)(is.file$) ) ) { abort | IO_MSG "invalid read"; } // if } // if if ( tmperrno == ERANGE ) throwResume ExceptionInst( data_range ); va_end( args ); return nargs; } // fmt static ifstream sinFile = { (FILE *)stdin }; ifstream & sin = sinFile, & stdin = sinFile; // *********************************** exceptions *********************************** // exception I/O constructors void ?{}( open_failure & ex, ofstream & ostream ) with( ex ) { virtual_table = &open_failure_vt; ostream = &ostream; tag = 1; } // ?{} void ?{}( open_failure & ex, ifstream & istream ) with( ex ) { virtual_table = &open_failure_vt; istream = &istream; tag = 0; } // ?{} // exception I/O constructors void ?{}( close_failure & ex, ofstream & ostream ) with( ex ) { virtual_table = &close_failure_vt; ostream = &ostream; tag = 1; } // ?{} void ?{}( close_failure & ex, ifstream & istream ) with( ex ) { virtual_table = &close_failure_vt; istream = &istream; tag = 0; } // ?{} // exception I/O constructors void ?{}( write_failure & ex, ofstream & ostream ) with( ex ) { virtual_table = &write_failure_vt; ostream = &ostream; tag = 1; } // ?{} void ?{}( write_failure & ex, ifstream & istream ) with( ex ) { virtual_table = &write_failure_vt; istream = &istream; tag = 0; } // ?{} // exception I/O constructors void ?{}( read_failure & ex, ofstream & ostream ) with( ex ) { virtual_table = &read_failure_vt; ostream = &ostream; tag = 1; } // ?{} void ?{}( read_failure & ex, ifstream & istream ) with( ex ) { virtual_table = &read_failure_vt; istream = &istream; tag = 0; } // ?{} // void throwopen_failure( ofstream & ostream ) { // open_failure exc = { ostream }; // } // void throwopen_failure( ifstream & istream ) { // open_failure exc = { istream }; // } // Local Variables: // // tab-width: 4 // // End: //