source: libcfa/src/fstream.cfa @ 91e52be

arm-ehjacob/cs343-translationnew-astnew-ast-unique-expr
Last change on this file since 91e52be was 91e52be, checked in by Peter A. Buhr <pabuhr@…>, 18 months ago

raise exception IO_OPEN_FAILURE for open failure with input/output fstreams, ignore attempt to close unopen file

  • Property mode set to 100644
File size: 8.2 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// fstream.c --
8//
9// Author           : Peter A. Buhr
10// Created On       : Wed May 27 17:56:53 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Thu Jun 18 15:37:21 2020
13// Update Count     : 380
14//
15
16#include "fstream.hfa"
17
18#include <stdio.h>                                                                              // vfprintf, vfscanf
19#include <stdlib.h>                                                                             // exit
20#include <stdarg.h>                                                                             // varargs
21#include <string.h>                                                                             // strlen
22#include <float.h>                                                                              // DBL_DIG, LDBL_DIG
23#include <complex.h>                                                                    // creal, cimag
24#include <assert.h>
25#include <errno.h>                                                                              // errno
26
27
28//*********************************** ofstream ***********************************
29
30
31#define IO_MSG "I/O error: "
32
33void ?{}( ofstream & os, void * file ) {
34        os.$file = file;
35        os.$sepDefault = true;
36        os.$sepOnOff = false;
37        os.$nlOnOff = true;
38        os.$prt = false;
39        os.$sawNL = false;
40        $sepSetCur( os, sepGet( os ) );
41        sepSet( os, " " );
42        sepSetTuple( os, ", " );
43} // ?{}
44
45// private
46bool $sepPrt( ofstream & os ) { $setNL( os, false ); return os.$sepOnOff; }
47void $sepReset( ofstream & os ) { os.$sepOnOff = os.$sepDefault; }
48void $sepReset( ofstream & os, bool reset ) { os.$sepDefault = reset; os.$sepOnOff = os.$sepDefault; }
49const char * $sepGetCur( ofstream & os ) { return os.$sepCur; }
50void $sepSetCur( ofstream & os, const char sepCur[] ) { os.$sepCur = sepCur; }
51bool $getNL( ofstream & os ) { return os.$sawNL; }
52void $setNL( ofstream & os, bool state ) { os.$sawNL = state; }
53bool $getANL( ofstream & os ) { return os.$nlOnOff; }
54bool $getPrt( ofstream & os ) { return os.$prt; }
55void $setPrt( ofstream & os, bool state ) { os.$prt = state; }
56
57// public
58void ?{}( ofstream & os ) { os.$file = 0p; }
59
60void ?{}( ofstream & os, const char name[], const char mode[] ) {
61        open( os, name, mode );
62} // ?{}
63
64void ?{}( ofstream & os, const char name[] ) {
65        open( os, name, "w" );
66} // ?{}
67
68void ^?{}( ofstream & os ) {
69        close( os );
70} // ^?{}
71
72void sepOn( ofstream & os ) { os.$sepOnOff = ! $getNL( os ); }
73void sepOff( ofstream & os ) { os.$sepOnOff = false; }
74
75bool sepDisable( ofstream & os ) {
76        bool temp = os.$sepDefault;
77        os.$sepDefault = false;
78        $sepReset( os );
79        return temp;
80} // sepDisable
81
82bool sepEnable( ofstream & os ) {
83        bool temp = os.$sepDefault;
84        os.$sepDefault = true;
85        if ( os.$sepOnOff ) $sepReset( os );                            // start of line ?
86        return temp;
87} // sepEnable
88
89void nlOn( ofstream & os ) { os.$nlOnOff = true; }
90void nlOff( ofstream & os ) { os.$nlOnOff = false; }
91
92const char * sepGet( ofstream & os ) { return os.$separator; }
93void sepSet( ofstream & os, const char s[] ) {
94        assert( s );
95        strncpy( os.$separator, s, sepSize - 1 );
96        os.$separator[sepSize - 1] = '\0';
97} // sepSet
98
99const char * sepGetTuple( ofstream & os ) { return os.$tupleSeparator; }
100void sepSetTuple( ofstream & os, const char s[] ) {
101        assert( s );
102        strncpy( os.$tupleSeparator, s, sepSize - 1 );
103        os.$tupleSeparator[sepSize - 1] = '\0';
104} // sepSet
105
106void ends( ofstream & os ) {
107        if ( $getANL( os ) ) nl( os );
108        else $setPrt( os, false );                                                      // turn off
109        if ( &os == &exit ) exit( EXIT_FAILURE );
110        if ( &os == &abort ) abort();
111} // ends
112
113int fail( ofstream & os ) {
114        return os.$file == 0 || ferror( (FILE *)(os.$file) );
115} // fail
116
117int flush( ofstream & os ) {
118        return fflush( (FILE *)(os.$file) );
119} // flush
120
121void open( ofstream & os, const char name[], const char mode[] ) {
122        FILE * file = fopen( name, mode );
123        #ifdef __CFA_DEBUG__
124        if ( file == 0p ) {
125                throw (IO_OPEN_FAILURE){ os };
126                abort | IO_MSG "open output file \"" | name | "\"" | nl | strerror( errno );
127        } // if
128        #endif // __CFA_DEBUG__
129        (os){ file };
130} // open
131
132void open( ofstream & os, const char name[] ) {
133        open( os, name, "w" );
134} // open
135
136void close( ofstream & os ) {
137  if ( (FILE *)(os.$file) == 0p ) return;
138  if ( (FILE *)(os.$file) == (FILE *)stdout || (FILE *)(os.$file) == (FILE *)stderr ) return;
139
140        if ( fclose( (FILE *)(os.$file) ) == EOF ) {
141                abort | IO_MSG "close output" | nl | strerror( errno );
142        } // if
143        os.$file = 0p;
144} // close
145
146ofstream & write( ofstream & os, const char data[], size_t size ) {
147        if ( fail( os ) ) {
148                abort | IO_MSG "attempt write I/O on failed stream";
149        } // if
150
151        if ( fwrite( data, 1, size, (FILE *)(os.$file) ) != size ) {
152                abort | IO_MSG "write" | nl | strerror( errno );
153        } // if
154        return os;
155} // write
156
157int fmt( ofstream & os, const char format[], ... ) {
158        va_list args;
159        va_start( args, format );
160        int len = vfprintf( (FILE *)(os.$file), format, args );
161        if ( len == EOF ) {
162                if ( ferror( (FILE *)(os.$file) ) ) {
163                        abort | IO_MSG "invalid write";
164                } // if
165        } // if
166        va_end( args );
167
168        $setPrt( os, true );                                                            // called in output cascade
169        $sepReset( os );                                                                        // reset separator
170        return len;
171} // fmt
172
173static ofstream soutFile = { (FILE *)stdout };
174ofstream & sout = soutFile, & stdout = soutFile;
175static ofstream serrFile = { (FILE *)stderr };
176ofstream & serr = serrFile, & stderr = serrFile;
177
178static ofstream exitFile = { (FILE *)stdout };
179ofstream & exit = exitFile;
180static ofstream abortFile = { (FILE *)stderr };
181ofstream & abort = abortFile;
182
183
184//*********************************** ifstream ***********************************
185
186
187// private
188void ?{}( ifstream & is, void * file ) {
189        is.$file = file;
190        is.$nlOnOff = false;
191} // ?{}
192
193// public
194void ?{}( ifstream & is ) { is.$file = 0p; }
195
196void ?{}( ifstream & is, const char name[], const char mode[] ) {
197        open( is, name, mode );
198} // ?{}
199
200void ?{}( ifstream & is, const char name[] ) {
201        open( is, name, "r" );
202} // ?{}
203
204void ^?{}( ifstream & is ) {
205        close( is );
206} // ^?{}
207
208void nlOn( ifstream & os ) { os.$nlOnOff = true; }
209void nlOff( ifstream & os ) { os.$nlOnOff = false; }
210bool getANL( ifstream & os ) { return os.$nlOnOff; }
211
212int fail( ifstream & is ) {
213        return is.$file == 0p || ferror( (FILE *)(is.$file) );
214} // fail
215
216int eof( ifstream & is ) {
217        return feof( (FILE *)(is.$file) );
218} // eof
219
220void open( ifstream & is, const char name[], const char mode[] ) {
221        FILE * file = fopen( name, mode );
222        #ifdef __CFA_DEBUG__
223        if ( file == 0p ) {
224                throw (IO_OPEN_FAILURE){ is };
225                abort | IO_MSG "open input file \"" | name | "\"" | nl | strerror( errno );
226        } // if
227        #endif // __CFA_DEBUG__
228        is.$file = file;
229} // open
230
231void open( ifstream & is, const char name[] ) {
232        open( is, name, "r" );
233} // open
234
235void close( ifstream & is ) {
236  if ( (FILE *)(is.$file) == 0p ) return;
237  if ( (FILE *)(is.$file) == (FILE *)stdin ) return;
238
239        if ( fclose( (FILE *)(is.$file) ) == EOF ) {
240                abort | IO_MSG "close input" | nl | strerror( errno );
241        } // if
242        is.$file = 0p;
243} // close
244
245ifstream & read( ifstream & is, char * data, size_t size ) {
246        if ( fail( is ) ) {
247                abort | IO_MSG "attempt read I/O on failed stream";
248        } // if
249
250        if ( fread( data, size, 1, (FILE *)(is.$file) ) == 0 ) {
251                abort | IO_MSG "read" | nl | strerror( errno );
252        } // if
253        return is;
254} // read
255
256ifstream &ungetc( ifstream & is, char c ) {
257        if ( fail( is ) ) {
258                abort | IO_MSG "attempt ungetc I/O on failed stream";
259        } // if
260
261        if ( ungetc( c, (FILE *)(is.$file) ) == EOF ) {
262                abort | IO_MSG "ungetc" | nl | strerror( errno );
263        } // if
264        return is;
265} // ungetc
266
267int fmt( ifstream & is, const char format[], ... ) {
268        va_list args;
269
270        va_start( args, format );
271        int len = vfscanf( (FILE *)(is.$file), format, args );
272        if ( len == EOF ) {
273                if ( ferror( (FILE *)(is.$file) ) ) {
274                        abort | IO_MSG "invalid read";
275                } // if
276        } // if
277        va_end( args );
278        return len;
279} // fmt
280
281static ifstream sinFile = { (FILE *)stdin };
282ifstream & sin = sinFile, & stdin = sinFile;
283
284
285//*********************************** exceptions ***********************************
286
287
288void ?{}( IO_OPEN_FAILURE & this, ofstream & ostream ) {
289        VTABLE_INIT(this, IO_OPEN_FAILURE);
290        this.ostream = &ostream;
291}
292void ?{}( IO_OPEN_FAILURE & this, ifstream & istream ) {
293        VTABLE_INIT(this, IO_OPEN_FAILURE);
294        this.istream = &istream;
295}
296const char * IO_OPEN_FAILURE_msg(IO_OPEN_FAILURE * this) {
297        return "IO_OPEN_FAILURE";
298}
299VTABLE_INSTANCE(IO_OPEN_FAILURE)(IO_OPEN_FAILURE_msg);
300void throwIO_OPEN_FAILURE( ofstream & ostream ) {
301        IO_OPEN_FAILURE exc = { ostream };
302}
303void throwIO_OPEN_FAILURE( ifstream & istream ) {
304        IO_OPEN_FAILURE exc = { istream };
305}
306
307// Local Variables: //
308// tab-width: 4 //
309// End: //
Note: See TracBrowser for help on using the repository browser.