Changeset a2e4b0c for libcfa/src
- Timestamp:
- Oct 28, 2021, 11:08:27 AM (3 years ago)
- Branches:
- ADT, ast-experimental, enum, forall-pointer-decay, master, pthread-emulation, qualifiedEnum
- Children:
- 441d11c
- Parents:
- a51a02d (diff), 15885de9 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Location:
- libcfa/src
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/fstream.cfa
ra51a02d ra2e4b0c 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Sep 21 21:51:38202113 // Update Count : 46012 // Last Modified On : Sun Oct 10 11:23:05 2021 13 // Update Count : 512 14 14 // 15 15 … … 28 28 #define IO_MSG "I/O error: " 29 29 30 void ?{}( ofstream & os, void * file ) with(os) { 30 // private 31 void ?{}( ofstream & os, void * file ) with( os ) { 31 32 file$ = file; 32 33 sepDefault$ = true; … … 35 36 prt$ = false; 36 37 sawNL$ = false; 37 acquired$ = false;38 38 sepSetCur$( os, sepGet( os ) ); 39 39 sepSet( os, " " ); … … 41 41 } // ?{} 42 42 43 // private 44 bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; } 45 void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; } 46 void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; } 47 const char * sepGetCur$( ofstream & os ) { return os.sepCur$; } 48 void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; } 49 bool getNL$( ofstream & os ) { return os.sawNL$; } 50 void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; } 51 bool getANL$( ofstream & os ) { return os.nlOnOff$; } 52 bool getPrt$( ofstream & os ) { return os.prt$; } 53 void setPrt$( ofstream & os, bool state ) { os.prt$ = state; } 43 inline bool sepPrt$( ofstream & os ) { setNL$( os, false ); return os.sepOnOff$; } 44 inline void sepReset$( ofstream & os ) { os.sepOnOff$ = os.sepDefault$; } 45 inline void sepReset$( ofstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; } 46 inline const char * sepGetCur$( ofstream & os ) { return os.sepCur$; } 47 inline void sepSetCur$( ofstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; } 48 inline bool getNL$( ofstream & os ) { return os.sawNL$; } 49 inline void setNL$( ofstream & os, bool state ) { os.sawNL$ = state; } 50 inline bool getANL$( ofstream & os ) { return os.nlOnOff$; } 51 inline bool getPrt$( ofstream & os ) { return os.prt$; } 52 inline void setPrt$( ofstream & os, bool state ) { os.prt$ = state; } 53 54 inline void lock( ofstream & os ) with( os ) { lock( os.lock$ ); } 55 inline void unlock( ofstream & os ) { unlock( os.lock$ ); } 54 56 55 57 // public 56 58 void ?{}( ofstream & os ) { os.file$ = 0p; } 57 58 void ?{}( ofstream & os, const char name[], const char mode[] ) { 59 open( os, name, mode ); 60 } // ?{} 61 62 void ?{}( ofstream & os, const char name[] ) { 63 open( os, name, "w" ); 64 } // ?{} 65 66 void ^?{}( ofstream & os ) { 67 close( os ); 68 } // ^?{} 59 void ?{}( ofstream & os, const char name[], const char mode[] ) { open( os, name, mode ); } 60 void ?{}( ofstream & os, const char name[] ) { open( os, name, "w" ); } 61 void ^?{}( ofstream & os ) { close( os ); } 69 62 70 63 void sepOn( ofstream & os ) { os.sepOnOff$ = ! getNL$( os ); } … … 107 100 if ( &os == &exit ) exit( EXIT_FAILURE ); 108 101 if ( &os == &abort ) abort(); 109 if ( os.acquired$ ) { os.acquired$ = false; release( os ); }110 102 } // ends 111 103 112 bool fail( ofstream & os ) { 113 return os.file$ == 0 || ferror( (FILE *)(os.file$) ); 114 } // fail 115 116 void clear( ofstream & os ) { 117 clearerr( (FILE *)(os.file$) ); 118 } // clear 119 120 int flush( ofstream & os ) { 121 return fflush( (FILE *)(os.file$) ); 122 } // flush 104 bool fail( ofstream & os ) { return os.file$ == 0 || ferror( (FILE *)(os.file$) ); } 105 void clear( ofstream & os ) { clearerr( (FILE *)(os.file$) ); } 106 int flush( ofstream & os ) { return fflush( (FILE *)(os.file$) ); } 123 107 124 108 void open( ofstream & os, const char name[], const char mode[] ) { 125 FILE * file = fopen( name, mode ); 109 FILE * file; 110 for ( cnt; 10 ) { 111 errno = 0; 112 file = fopen( name, mode ); 113 if ( file != 0p || errno != EINTR ) break; // timer interrupt ? 114 if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" ); 115 } // for 126 116 if ( file == 0p ) { 127 117 throw (Open_Failure){ os }; … … 131 121 } // open 132 122 133 void open( ofstream & os, const char name[] ) { 134 open( os, name, "w" ); 135 } // open 136 137 void close( ofstream & os ) with(os) { 123 void open( ofstream & os, const char name[] ) { open( os, name, "w" ); } 124 125 void close( ofstream & os ) with( os ) { 138 126 if ( (FILE *)(file$) == 0p ) return; 139 127 if ( (FILE *)(file$) == (FILE *)stdout || (FILE *)(file$) == (FILE *)stderr ) return; 140 128 141 if ( fclose( (FILE *)(file$) ) == EOF ) { 129 int ret; 130 for ( cnt; 10 ) { 131 errno = 0; 132 ret = fclose( (FILE *)(file$) ); 133 if ( ret != EOF || errno != EINTR ) break; // timer interrupt ? 134 if ( cnt == 9 ) abort( "ofstream open EINTR spinning exceeded" ); 135 } // for 136 if ( ret == EOF ) { 142 137 throw (Close_Failure){ os }; 143 138 // abort | IO_MSG "close output" | nl | strerror( errno ); 144 139 } // if 145 file$ = 0p; 140 file$ = 0p; // safety after close 146 141 } // close 147 142 … … 162 157 va_list args; 163 158 va_start( args, format ); 164 int len = vfprintf( (FILE *)(os.file$), format, args ); 159 160 int len; 161 for ( cnt; 10 ) { 162 errno = 0; 163 len = vfprintf( (FILE *)(os.file$), format, args ); 164 if ( len != EOF || errno != EINTR ) break; // timer interrupt ? 165 if ( cnt == 9 ) abort( "ofstream fmt EINTR spinning exceeded" ); 166 } // for 165 167 if ( len == EOF ) { 166 168 if ( ferror( (FILE *)(os.file$) ) ) { … … 175 177 } // fmt 176 178 179 <<<<<<< HEAD 177 180 inline void acquire( ofstream & os ) with(os) { 178 181 lock( lock$ ); // may increase recursive lock … … 191 194 void ^?{}( osacquire & acq ) { release( acq.os ); } 192 195 196 ======= 197 >>>>>>> 15885de998d9500373efda8e609b893c87e6363a 193 198 static ofstream soutFile = { (FILE *)stdout }; 194 199 ofstream & sout = soutFile, & stdout = soutFile; … … 208 213 flush( os ); 209 214 return os; 210 // (ofstream &)(os | '\n');211 // setPrt$( os, false ); // turn off212 // setNL$( os, true );213 // flush( os );214 // return sepOff( os ); // prepare for next line215 215 } // nl 216 216 … … 220 220 221 221 // private 222 void ?{}( ifstream & is, void * file ) with( is) {222 void ?{}( ifstream & is, void * file ) with( is ) { 223 223 file$ = file; 224 224 nlOnOff$ = false; 225 acquired$ = false; 226 } // ?{} 225 } // ?{} 226 227 bool getANL$( ifstream & os ) { return os.nlOnOff$; } 228 229 inline void lock( ifstream & os ) with( os ) { lock( os.lock$ ); } 230 inline void unlock( ifstream & os ) { unlock( os.lock$ ); } 227 231 228 232 // public 229 233 void ?{}( ifstream & is ) { is.file$ = 0p; } 230 231 void ?{}( ifstream & is, const char name[], const char mode[] ) { 232 open( is, name, mode ); 233 } // ?{} 234 235 void ?{}( ifstream & is, const char name[] ) { 236 open( is, name, "r" ); 237 } // ?{} 238 239 void ^?{}( ifstream & is ) { 240 close( is ); 241 } // ^?{} 234 void ?{}( ifstream & is, const char name[], const char mode[] ) { open( is, name, mode ); } 235 void ?{}( ifstream & is, const char name[] ) { open( is, name, "r" ); } 236 void ^?{}( ifstream & is ) { close( is ); } 237 238 bool fail( ifstream & is ) { return is.file$ == 0p || ferror( (FILE *)(is.file$) ); } 239 void clear( ifstream & is ) { clearerr( (FILE *)(is.file$) ); } 242 240 243 241 void nlOn( ifstream & os ) { os.nlOnOff$ = true; } 244 242 void nlOff( ifstream & os ) { os.nlOnOff$ = false; } 245 bool getANL( ifstream & os ) { return os.nlOnOff$; } 246 247 bool fail( ifstream & is ) { 248 return is.file$ == 0p || ferror( (FILE *)(is.file$) ); 249 } // fail 250 251 void clear( ifstream & is ) { 252 clearerr( (FILE *)(is.file$) ); 253 } // clear 254 255 void ends( ifstream & is ) { 256 if ( is.acquired$ ) { is.acquired$ = false; release( is ); } 257 } // ends 258 259 bool eof( ifstream & is ) { 260 return feof( (FILE *)(is.file$) ); 261 } // eof 243 244 void ends( ifstream & is ) {} 245 246 bool eof( ifstream & is ) { return feof( (FILE *)(is.file$) ) != 0; } 262 247 263 248 void open( ifstream & is, const char name[], const char mode[] ) { 264 FILE * file = fopen( name, mode ); 249 FILE * file; 250 for ( cnt; 10 ) { 251 errno = 0; 252 file = fopen( name, mode ); 253 if ( file != 0p || errno != EINTR ) break; // timer interrupt ? 254 if ( cnt == 9 ) abort( "ifstream open EINTR spinning exceeded" ); 255 } // for 265 256 if ( file == 0p ) { 266 257 throw (Open_Failure){ is }; … … 270 261 } // open 271 262 272 void open( ifstream & is, const char name[] ) { 273 open( is, name, "r" ); 274 } // open 275 276 void close( ifstream & is ) with(is) { 263 void open( ifstream & is, const char name[] ) { open( is, name, "r" ); } 264 265 void close( ifstream & is ) with( is ) { 277 266 if ( (FILE *)(file$) == 0p ) return; 278 267 if ( (FILE *)(file$) == (FILE *)stdin ) return; 279 268 280 if ( fclose( (FILE *)(file$) ) == EOF ) { 269 int ret; 270 for ( cnt; 10 ) { 271 errno = 0; 272 ret = fclose( (FILE *)(file$) ); 273 if ( ret != EOF || errno != EINTR ) break; // timer interrupt ? 274 if ( cnt == 9 ) abort( "ifstream close EINTR spinning exceeded" ); 275 } // for 276 if ( ret == EOF ) { 281 277 throw (Close_Failure){ is }; 282 278 // abort | IO_MSG "close input" | nl | strerror( errno ); 283 279 } // if 284 file$ = 0p; 280 file$ = 0p; // safety after close 285 281 } // close 286 282 … … 311 307 int fmt( ifstream & is, const char format[], ... ) { 312 308 va_list args; 313 314 309 va_start( args, format ); 315 int len = vfscanf( (FILE *)(is.file$), format, args ); 310 311 int len; 312 for () { // no check for EINTR limit waiting for keyboard input 313 errno = 0; 314 len = vfscanf( (FILE *)(is.file$), format, args ); 315 if ( len != EOF || errno != EINTR ) break; // timer interrupt ? 316 } // for 316 317 if ( len == EOF ) { 317 318 if ( ferror( (FILE *)(is.file$) ) ) { … … 322 323 return len; 323 324 } // fmt 324 325 inline void acquire( ifstream & is ) with(is) {326 lock( lock$ ); // may increase recursive lock327 if ( ! acquired$ ) acquired$ = true; // not locked ?328 else unlock( lock$ ); // unwind recursive lock at start329 } // acquire330 331 inline void release( ifstream & is ) {332 unlock( is.lock$ );333 } // release334 335 void ?{}( isacquire & acq, ifstream & is ) { lock( is.lock$ ); &acq.is = &is; }336 void ^?{}( isacquire & acq ) { release( acq.is ); }337 325 338 326 static ifstream sinFile = { (FILE *)stdin }; -
libcfa/src/fstream.hfa
ra51a02d ra2e4b0c 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Jul 28 07:35:50202113 // Update Count : 2 3412 // Last Modified On : Sun Oct 10 09:37:32 2021 13 // Update Count : 243 14 14 // 15 15 … … 36 36 char tupleSeparator$[ofstream_sepSize]; 37 37 multiple_acquisition_lock lock$; 38 bool acquired$;39 38 }; // ofstream 40 39 … … 52 51 bool getPrt$( ofstream & ); 53 52 void setPrt$( ofstream &, bool ); 53 54 void lock( ofstream & ); 55 void unlock( ofstream & ); 54 56 55 57 // public … … 75 77 void open( ofstream &, const char name[] ); 76 78 void close( ofstream & ); 79 77 80 ofstream & write( ofstream &, const char data[], size_t size ); 78 79 void acquire( ofstream & );80 void release( ofstream & );81 82 void lock( ofstream & );83 void unlock( ofstream & );84 85 struct osacquire {86 ofstream & os;87 };88 void ?{}( osacquire & acq, ofstream & );89 void ^?{}( osacquire & acq );90 81 91 82 void ?{}( ofstream & ); … … 110 101 bool nlOnOff$; 111 102 multiple_acquisition_lock lock$; 112 bool acquired$;113 103 }; // ifstream 114 104 115 105 // Satisfies istream 116 106 107 // private 108 bool getANL$( ifstream & ); 109 110 void lock( ifstream & ); 111 void unlock( ifstream & ); 112 117 113 // public 118 114 void nlOn( ifstream & ); 119 115 void nlOff( ifstream & ); 120 bool getANL( ifstream & );121 116 void ends( ifstream & ); 122 117 int fmt( ifstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) )); … … 128 123 void open( ifstream & is, const char name[] ); 129 124 void close( ifstream & is ); 125 130 126 ifstream & read( ifstream & is, char data[], size_t size ); 131 127 ifstream & ungetc( ifstream & is, char c ); 132 133 void acquire( ifstream & is );134 void release( ifstream & is );135 136 struct isacquire {137 ifstream & is;138 };139 void ?{}( isacquire & acq, ifstream & is );140 void ^?{}( isacquire & acq );141 128 142 129 void ?{}( ifstream & is ); -
libcfa/src/iostream.cfa
ra51a02d ra2e4b0c 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : S at May 15 09:39:21202113 // Update Count : 134 212 // Last Modified On : Sun Oct 10 09:28:17 2021 13 // Update Count : 1345 14 14 // 15 15 … … 398 398 return os; 399 399 } // nlOff 400 } // distribution401 402 forall( ostype & | ostream( ostype ) ) {403 ostype & acquire( ostype & os ) {404 acquire( os ); // call void returning405 return os;406 } // acquire407 400 } // distribution 408 401 … … 829 822 fmt( is, "%c", &temp ); // must pass pointer through varg to fmt 830 823 // do not overwrite parameter with newline unless appropriate 831 if ( temp != '\n' || getANL ( is ) ) { c = temp; break; }824 if ( temp != '\n' || getANL$( is ) ) { c = temp; break; } 832 825 if ( eof( is ) ) break; 833 826 } // for … … 1035 1028 return is; 1036 1029 } // nlOff 1037 } // distribution1038 1039 forall( istype & | istream( istype ) ) {1040 istype & acquire( istype & is ) {1041 acquire( is ); // call void returning1042 return is;1043 } // acquire1044 1030 } // distribution 1045 1031 -
libcfa/src/iostream.hfa
ra51a02d ra2e4b0c 10 10 // Created On : Wed May 27 17:56:53 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Wed Apr 28 20:37:56202113 // Update Count : 40 112 // Last Modified On : Sun Oct 10 10:02:07 2021 13 // Update Count : 407 14 14 // 15 15 … … 58 58 void close( ostype & ); 59 59 ostype & write( ostype &, const char [], size_t ); 60 void acquire( ostype & ); // concurrent access61 60 }; // ostream 62 61 … … 142 141 ostype & nlOn( ostype & ); 143 142 ostype & nlOff( ostype & ); 144 } // distribution145 146 forall( ostype & | ostream( ostype ) ) {147 ostype & acquire( ostype & );148 143 } // distribution 149 144 … … 296 291 297 292 trait basic_istream( istype & ) { 298 bool getANL( istype & ); // get scan newline (on/off) 293 // private 294 bool getANL$( istype & ); // get scan newline (on/off) 295 // public 299 296 void nlOn( istype & ); // read newline 300 297 void nlOff( istype & ); // scan newline 301 302 298 void ends( istype & os ); // end of output statement 303 299 int fmt( istype &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) )); … … 312 308 void close( istype & is ); 313 309 istype & read( istype &, char [], size_t ); 314 void acquire( istype & ); // concurrent access315 310 }; // istream 316 311 … … 379 374 } // distribution 380 375 381 forall( istype & | istream( istype ) ) {382 istype & acquire( istype & );383 } // distribution384 385 376 // *********************************** manipulators *********************************** 386 377 -
libcfa/src/strstream.cfa
ra51a02d ra2e4b0c 10 10 // Created On : Thu Apr 22 22:24:35 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Apr 27 20:59:53202113 // Update Count : 7812 // Last Modified On : Sun Oct 10 16:13:20 2021 13 // Update Count : 101 14 14 // 15 15 16 16 #include "strstream.hfa" 17 #include "fstream.hfa" // abort 17 18 18 19 #include <stdio.h> // vsnprintf … … 30 31 31 32 // private 32 bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; }33 void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; }34 void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; }35 const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; }36 void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; }37 bool getNL$( ostrstream & os ) { return os.sawNL$; }38 void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; }39 bool getANL$( ostrstream & os ) { return os.nlOnOff$; }40 bool getPrt$( ostrstream & os ) { return os.prt$; }41 void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; }33 inline bool sepPrt$( ostrstream & os ) { setNL$( os, false ); return os.sepOnOff$; } 34 inline void sepReset$( ostrstream & os ) { os.sepOnOff$ = os.sepDefault$; } 35 inline void sepReset$( ostrstream & os, bool reset ) { os.sepDefault$ = reset; os.sepOnOff$ = os.sepDefault$; } 36 inline const char * sepGetCur$( ostrstream & os ) { return os.sepCur$; } 37 inline void sepSetCur$( ostrstream & os, const char sepCur[] ) { os.sepCur$ = sepCur; } 38 inline bool getNL$( ostrstream & os ) { return os.sawNL$; } 39 inline void setNL$( ostrstream & os, bool state ) { os.sawNL$ = state; } 40 inline bool getANL$( ostrstream & os ) { return os.nlOnOff$; } 41 inline bool getPrt$( ostrstream & os ) { return os.prt$; } 42 inline void setPrt$( ostrstream & os, bool state ) { os.prt$ = state; } 42 43 43 44 // public … … 128 129 // *********************************** istrstream *********************************** 129 130 131 // private 132 bool getANL$( istrstream & is ) { return is.nlOnOff$; } 130 133 131 134 // public … … 136 139 } // ?{} 137 140 138 bool getANL( istrstream & is ) { return is.nlOnOff$; }139 141 void nlOn( istrstream & is ) { is.nlOnOff$ = true; } 140 142 void nlOff( istrstream & is ) { is.nlOnOff$ = false; } 141 143 142 void ends( istrstream & is ) { 143 } // ends 144 void ends( istrstream & is ) {} 145 bool eof( istrstream & is ) { return false; } 144 146 145 int eof( istrstream & is ) { 146 return 0; 147 } // eof 147 int fmt( istrstream & is, const char format[], ... ) with(is) { 148 va_list args; 149 va_start( args, format ); 150 // THIS DOES NOT WORK BECAUSE VSSCANF RETURNS NUMBER OF VALUES READ VERSUS BUFFER POSITION SCANNED. 151 int len = vsscanf( buf$ + cursor$, format, args ); 152 va_end( args ); 153 if ( len == EOF ) { 154 abort | IO_MSG "invalid read"; 155 } // if 156 // SKULLDUGGERY: This hack skips over characters read by vsscanf by moving to the next whitespace but it does not 157 // handle C reads with wdi manipulators that leave the cursor at a non-whitespace character. 158 for ( ; buf$[cursor$] != ' ' && buf$[cursor$] != '\t' && buf$[cursor$] != '\0'; cursor$ += 1 ) { 159 //printf( "X \'%c\'\n", buf$[cursor$] ); 160 } // for 161 if ( buf$[cursor$] != '\0' ) cursor$ += 1; // advance to whitespace 162 return len; 163 } // fmt 148 164 149 165 istrstream &ungetc( istrstream & is, char c ) { … … 154 170 } // ungetc 155 171 156 int fmt( istrstream & is, const char format[], ... ) {157 va_list args;158 va_start( args, format );159 // This does not work because vsscanf does not return buffer position.160 int len = vsscanf( is.buf$ + is.cursor$, format, args );161 va_end( args );162 if ( len == EOF ) {163 int j;164 printf( "X %d%n\n", len, &j );165 } // if166 is.cursor$ += len;167 return len;168 } // fmt169 170 172 // Local Variables: // 171 173 // tab-width: 4 // -
libcfa/src/strstream.hfa
ra51a02d ra2e4b0c 10 10 // Created On : Thu Apr 22 22:20:59 2021 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Apr 27 20:58:50202113 // Update Count : 4 112 // Last Modified On : Sun Oct 10 10:14:22 2021 13 // Update Count : 47 14 14 // 15 15 … … 85 85 // Satisfies basic_istream 86 86 87 // private 88 bool getANL$( istrstream & ); 89 87 90 // public 88 bool getANL( istrstream & );89 91 void nlOn( istrstream & ); 90 92 void nlOff( istrstream & ); 91 93 void ends( istrstream & ); 94 92 95 int fmt( istrstream &, const char format[], ... ) __attribute__(( format(scanf, 2, 3) )); 93 istrstream & ungetc( istrstream & is, char c);94 int eof( istrstream & is);96 istrstream & ungetc( istrstream &, char ); 97 bool eof( istrstream & ); 95 98 96 void ?{}( istrstream & is, char buf[] );99 void ?{}( istrstream &, char buf[] ); 97 100 98 101 // Local Variables: //
Note: See TracChangeset
for help on using the changeset viewer.