/* lil-gp Genetic Programming System, version 1.0, 11 July 1995 * Copyright (C) 1995 Michigan State University * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Douglas Zongker (zongker@isl.cps.msu.edu) * Dr. Bill Punch (punch@isl.cps.msu.edu) * * Computer Science Department * A-714 Wells Hall * Michigan State University * East Lansing, Michigan 48824 * USA * */ #include char buffer[MAXMESSAGELENGTH]; typedef struct { int id; char *ext; int reset; char *mode; int autoflush; FILE *f; int valid; char *buffer; } output; output streams[MAXOUTPUTSTREAMS] = { { OUT_SYS, ".sys", 0, "w", 1, NULL, 0 }, { OUT_GEN, ".gen", 0, "w", 0, NULL, 0 }, { OUT_PRG, ".prg", 0, "w", 0, NULL, 0 }, { OUT_STT, ".stt", 0, "w", 0, NULL, 0 }, { OUT_BST, ".bst", 1, "w", 0, NULL, 0 }, { OUT_HIS, ".his", 0, "w", 0, NULL, 0 } }; int output_stream_count = SYSOUTPUTSTREAMS; int toolate = 0; char *global_basename = NULL; int detail_level = DEFDETAILLEVEL; char error_type[3][20] = { "WARNING: ", "ERROR: ", "FATAL ERROR: " }; extern int quietmode; /* create_output_stream() * * make a new entry in the outputstream table. */ int create_output_stream ( int id, char *ext, int reset, char *mode, int autoflush ) { int i; /* can't create a new stream if they've already been opened. */ if ( toolate ) return OUTPUT_TOOLATE; /* is the stream table full? */ if ( output_stream_count >= MAXOUTPUTSTREAMS ) return OUTPUT_TOOMANY; /* is the id or extension the same as an existing stream? */ for ( i = 0; i < output_stream_count; ++i ) { if ( id == streams[i].id ) return OUTPUT_DUP_ID; if ( strcmp ( ext, streams[i].ext ) == 0 ) return OUTPUT_DUP_EXT; } /** save stuff in the table. **/ streams[output_stream_count].id = id; streams[output_stream_count].ext = (char *)malloc ( strlen(ext)+1 ); strcpy ( streams[output_stream_count].ext, ext ); streams[output_stream_count].reset = reset; streams[output_stream_count].mode = (char *)malloc ( strlen(mode)+1 ); strcpy ( streams[output_stream_count].mode, mode ); streams[output_stream_count].autoflush = autoflush; streams[output_stream_count].f = NULL; streams[output_stream_count].valid = 0; ++output_stream_count; return OUTPUT_OK; } /* initialize_output_streams() * * initialize the output streams. until they are opened, anything printed * to one (via oputs() or oprintf()) is saved in memory. */ void initialize_output_streams ( void ) { int i; toolate = 1; for ( i = 0; i < output_stream_count; ++i ) streams[i].buffer = NULL; } /* open_output_streams() * * open files associated with each output stream. dump anything buffered * in memory to the file. */ void open_output_streams ( void ) { int i; char *fn; char *basename; basename = get_parameter ( "output.basename" ); fn = (char *)malloc ( strlen(basename)+50 ); for ( i = 0; i < output_stream_count; ++i ) { strcpy ( fn, basename ); strcat ( fn, streams[i].ext ); streams[i].f = fopen ( fn, streams[i].mode ); if ( streams[i].f == NULL ) { error ( E_ERROR, "can't open output file \"%s\".", fn ); } else { streams[i].valid = 1; if ( streams[i].buffer ) fputs ( streams[i].buffer, streams[i].f ); FREE ( streams[i].buffer ); streams[i].buffer = NULL; } } global_basename = (char *)malloc ( strlen(basename)+1 ); strcpy ( global_basename, basename ); set_detail_level ( atoi ( get_parameter ( "output.detail" ) ) ); } /* oputs() * * prints a string to an output stream. */ void oputs ( int streamid, int detail, char *string ) { int i, j; if ( streamid == OUT_SYS && !quietmode ) { printf ( string ); fflush ( stdout ); } if ( detail_level < detail ) return; for ( i = 0; i < output_stream_count; ++i ) { if ( streamid == streams[i].id ) { if ( streams[i].valid ) { fputs ( string, streams[i].f ); if ( streams[i].autoflush ) fflush ( streams[i].f ); break; } else { if ( streams[i].buffer ) { j = strlen ( streams[i].buffer ) + strlen ( string ) + 1; streams[i].buffer = (char *)REALLOC ( streams[i].buffer, j ); strcat ( streams[i].buffer, string ); } else { streams[i].buffer = (char *)MALLOC ( strlen ( string ) + 1 ); strcpy ( streams[i].buffer, string ); } } } } } /* oprintf() * * prints a formatted string to an output stream. */ void oprintf ( int streamid, int detail, char *format, ... ) { va_list ap; if ( detail_level < detail ) return; va_start ( ap, format ); vsprintf ( buffer, format, ap ); va_end ( ap ); oputs ( streamid, detail, buffer ); } /* output_filehandle() * * returns the filehandle associated with a given stream. */ FILE *output_filehandle ( int streamid ) { int i; for ( i = 0; i < output_stream_count; ++i ) if ( streamid == streams[i].id ) if ( streams[i].valid ) return ( streams[i].f ); return NULL; } /* output_stream_close() * * closes an output stream, if it has been marked as resettable. */ void output_stream_close ( int streamid ) { int i; for ( i = 0; i < output_stream_count; ++i ) if ( streamid == streams[i].id ) if ( streams[i].reset ) if ( streams[i].valid ) { fclose ( streams[i].f ); streams[i].valid = 0; break; } } /* output_stream_open() * * reopens a resettable output stream. */ void output_stream_open ( int streamid ) { char *fn; int i; for ( i = 0; i < output_stream_count; ++i ) if ( streamid == streams[i].id ) if ( streams[i].reset ) if ( !streams[i].valid ) { fn = (char *)malloc ( strlen(global_basename)+50 ); strcpy ( fn, global_basename ); strcat ( fn, streams[i].ext ); streams[i].f = fopen ( fn, streams[i].mode ); if ( streams[i].f == NULL ) { /* an error. */ } else streams[i].valid = 1; } } /* output_stream_flush() * * flushes all the resettable output streams. */ void output_stream_flush ( int streamid ) { int i; for ( i = 0; i < output_stream_count; ++i ) if ( streamid == streams[i].id ) if ( streams[i].reset ) if ( streams[i].valid ) fflush ( streams[i].f ); } /* close_output_streams() * * closes all the output streams. */ void close_output_streams ( void ) { int i; for ( i = 0; i < output_stream_count; ++i ) { if ( streams[i].valid ) { fclose ( streams[i].f ); streams[i].valid = 0; } } for ( i = SYSOUTPUTSTREAMS; i < MAXOUTPUTSTREAMS; ++i ) { free ( streams[i].ext ); free ( streams[i].mode ); } free ( global_basename ); } /* flush_output_streams() * * flushes all the output streams. */ void flush_output_streams ( void ) { int i; for ( i = 0; i < output_stream_count; ++i ) if ( streams[i].valid ) fflush ( streams[i].f ); } /* error() * * prints an error message to the system output stream, with a given * level of severity. If the error is fatal, then the error is also * printed to stderr and the program exits with status 1. */ void error ( int severity, char *format, ... ) { va_list ap; va_start ( ap, format ); vsprintf ( buffer, format, ap ); va_end ( ap ); strcat ( buffer, "\n" ); oputs ( OUT_SYS, 0, error_type[severity] ); oputs ( OUT_SYS, 0, buffer ); if ( severity == E_FATAL_ERROR ) { fprintf ( stderr, "exiting due to fatal error.\n" ); exit(1); } } /* set_detail_level() * * sets the detail level to a given value. */ void set_detail_level ( int newlevel ) { if ( newlevel >= MINDETAILLEVEL && newlevel <= MAXDETAILLEVEL ) detail_level = newlevel; } /* test_detail_level() * * returns 1 if the argument is less than or equal to the current * detail level. */ int test_detail_level ( int detail ) { if ( detail_level < detail ) return 0; return 1; }