752 lines
19 KiB
C
752 lines
19 KiB
C
|
/* 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 <lilgp.h>
|
||
|
|
||
|
/** array of parameters, along with the size of the array and the number
|
||
|
of parameters used. **/
|
||
|
parameter *param;
|
||
|
int param_size = 0, param_alloc = 0;
|
||
|
|
||
|
/* read_parameter_file()
|
||
|
*
|
||
|
* reads and parses a parameter file.
|
||
|
*/
|
||
|
|
||
|
void read_parameter_file ( char *filename )
|
||
|
{
|
||
|
FILE *f;
|
||
|
char buffer[MAXPARAMLINELENGTH+1];
|
||
|
char *buf2;
|
||
|
int buf2size;
|
||
|
int line = 0;
|
||
|
int errors = 0;
|
||
|
int including = 1;
|
||
|
int flag;
|
||
|
int buflen, buf2len;
|
||
|
int cont;
|
||
|
|
||
|
/** open it. **/
|
||
|
f = fopen ( filename, "r" );
|
||
|
if ( f == NULL )
|
||
|
error ( E_FATAL_ERROR, "can't open parameter file \"%s\".",
|
||
|
filename );
|
||
|
|
||
|
/** lines are read into buffer. they are appended to buf2 until a
|
||
|
line which is not continued is hit, then buf2 is parsed and the
|
||
|
parameter added. **/
|
||
|
|
||
|
/* initial allocation of buf2. */
|
||
|
buf2 = (char *)MALLOC ( MAXPARAMLINELENGTH * sizeof ( char ) );
|
||
|
buf2size = MAXPARAMLINELENGTH;
|
||
|
buf2[0] = 0;
|
||
|
buf2len = 0;
|
||
|
cont = 0;
|
||
|
|
||
|
while ( fgets ( buffer, MAXPARAMLINELENGTH, f ) != NULL )
|
||
|
{
|
||
|
++line;
|
||
|
|
||
|
/* remove comments, skip line if it's blank after comment
|
||
|
removal. */
|
||
|
if ( delete_comment ( buffer ) )
|
||
|
continue;
|
||
|
|
||
|
/** if this is a %ifdef, %ifndef, or %endif directive, then
|
||
|
set the including variable accordingly. **/
|
||
|
if ( buffer[0] == '%' )
|
||
|
{
|
||
|
flag = 0;
|
||
|
if ( strncmp ( buffer+1, "ifdef", 5 ) == 0 )
|
||
|
including = test_directive ( buffer+6 );
|
||
|
else if ( strncmp ( buffer+1, "ifndef", 6 ) == 0 )
|
||
|
including = !test_directive ( buffer+7 );
|
||
|
else if ( strncmp ( buffer+1, "endif", 5 ) == 0 )
|
||
|
including = 1;
|
||
|
else
|
||
|
flag = 1;
|
||
|
|
||
|
if ( !flag )
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
/* skip this line unless including is set. */
|
||
|
if ( !including )
|
||
|
continue;
|
||
|
|
||
|
/** if this is a %define or %undefine directive, then process
|
||
|
it. **/
|
||
|
if ( buffer[0] == '%' )
|
||
|
{
|
||
|
if ( strncmp ( buffer+1, "define", 6 ) == 0 )
|
||
|
define_directive ( buffer+7 );
|
||
|
else if ( strncmp ( buffer+1, "undefine", 8 ) == 0 )
|
||
|
undefine_directive ( buffer+9 );
|
||
|
else
|
||
|
error ( E_ERROR, "%s line %d: unknown directive.",
|
||
|
filename, line );
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
/* is this line continued? (is the last nonwhitespace character
|
||
|
a backslash?) */
|
||
|
cont = check_continuation ( buffer );
|
||
|
|
||
|
/** make buf2 bigger if necessary. **/
|
||
|
buflen = strlen ( buffer );
|
||
|
while ( buf2len + buflen > buf2size + 10 )
|
||
|
{
|
||
|
buf2size += MAXPARAMLINELENGTH;
|
||
|
buf2 = (char *)REALLOC ( buf2, buf2size * sizeof ( char ) );
|
||
|
}
|
||
|
|
||
|
/** tack the current line onto buf2. **/
|
||
|
strcat ( buf2, buffer );
|
||
|
buf2len += buflen;
|
||
|
|
||
|
/** if this line is not continued further, then parse buf2. and
|
||
|
add the parameter. **/
|
||
|
if ( !cont )
|
||
|
{
|
||
|
if ( parse_one_parameter ( buf2 ) )
|
||
|
{
|
||
|
errors = 1;
|
||
|
error ( E_ERROR, "%s line %d: syntax error.",
|
||
|
filename, line );
|
||
|
}
|
||
|
|
||
|
/** reset buf2 as empty. **/
|
||
|
buf2len = 0;
|
||
|
buf2[0] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* close file. */
|
||
|
fclose ( f );
|
||
|
|
||
|
/** if the last line was continued, and nothing followed it, that's
|
||
|
an error. **/
|
||
|
if ( buf2len != 0 )
|
||
|
{
|
||
|
errors = 1;
|
||
|
error ( E_ERROR, "unexpected EOF." );
|
||
|
}
|
||
|
|
||
|
/** if any errors occurred during parsing, stop now. **/
|
||
|
if ( errors )
|
||
|
error ( E_FATAL_ERROR,
|
||
|
"some syntax errors occurred parsing \"%s\".", filename );
|
||
|
|
||
|
FREE ( buf2 );
|
||
|
|
||
|
}
|
||
|
|
||
|
/* check_continuation()
|
||
|
*
|
||
|
* returns true/false depending on whether the given string is continued
|
||
|
* (the last nonwhitespace character is a backslash). If so, the backslash
|
||
|
* and everything after it is chopped.
|
||
|
*/
|
||
|
|
||
|
int check_continuation ( char *buffer )
|
||
|
{
|
||
|
int i, l;
|
||
|
l = strlen ( buffer );
|
||
|
for ( i = l-1; i >= 0; --i )
|
||
|
if ( !isspace(buffer[i]) )
|
||
|
{
|
||
|
if ( buffer[i] == '\\' )
|
||
|
{
|
||
|
buffer[i] = '\n';
|
||
|
buffer[i+1] = 0;
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* a blank line was passed. */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* delete_comment()
|
||
|
*
|
||
|
* this searches the string for a '#' or ';' and chops everything
|
||
|
* following, if one is found. returns 1 if the resulting line is blank
|
||
|
* (all whitespace), 0 otherwise.
|
||
|
*/
|
||
|
|
||
|
int delete_comment ( char *buffer )
|
||
|
{
|
||
|
int i, l;
|
||
|
|
||
|
l = strlen ( buffer );
|
||
|
/* zero-length lines are considered blank. */
|
||
|
if ( l == 0 )
|
||
|
return 1;
|
||
|
/* if the last character is a newline, chop it. */
|
||
|
if ( buffer[--l] == '\n' )
|
||
|
buffer[l] = 0;
|
||
|
for ( i = 0; i < l; ++i )
|
||
|
if ( buffer[i] == '#' || buffer[i] == ';' )
|
||
|
{
|
||
|
/* chop the line at a '#' or ';'. */
|
||
|
buffer[i] = 0;
|
||
|
break;
|
||
|
}
|
||
|
/* look for a nonwhitespace character. */
|
||
|
l = strlen ( buffer );
|
||
|
for ( i = 0; i < l; ++i )
|
||
|
if ( !isspace(buffer[i]) )
|
||
|
/* found one, return 0. */
|
||
|
return 0;
|
||
|
|
||
|
/* blank line, return 1. */
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* translate_binary()
|
||
|
*
|
||
|
* this translates all of the valid strings representing binary values
|
||
|
* to the corresponding integer.
|
||
|
*/
|
||
|
|
||
|
int translate_binary ( char *string )
|
||
|
{
|
||
|
if ( strcmp ( string, "true" ) == 0 ||
|
||
|
strcmp ( string, "t" ) == 0 ||
|
||
|
strcmp ( string, "on" ) == 0 ||
|
||
|
strcmp ( string, "yes" ) == 0 ||
|
||
|
strcmp ( string, "y" ) == 0 ||
|
||
|
strcmp ( string, "1" ) == 0 )
|
||
|
return 1;
|
||
|
else if ( strcmp ( string, "false" ) == 0 ||
|
||
|
strcmp ( string, "f" ) == 0 ||
|
||
|
strcmp ( string, "off" ) == 0 ||
|
||
|
strcmp ( string, "no" ) == 0 ||
|
||
|
strcmp ( string, "n" ) == 0 ||
|
||
|
strcmp ( string, "0" ) == 0 )
|
||
|
return 0;
|
||
|
else
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
/* read_parameter_database()
|
||
|
*
|
||
|
* this reads parameters from a checkpoint file.
|
||
|
*/
|
||
|
|
||
|
void read_parameter_database ( FILE *f )
|
||
|
{
|
||
|
int i, j, k;
|
||
|
int count;
|
||
|
char *buf1, *buf2;
|
||
|
int buf2len, buf2alloc;
|
||
|
|
||
|
/* how many parameters are we supposed to find? */
|
||
|
fscanf ( f, "%*s %d\n", &count );
|
||
|
if ( fgetc ( f ) != '#' )
|
||
|
error ( E_FATAL_ERROR, "error in parameter section of checkpoint file." );
|
||
|
|
||
|
buf1 = (char *)MALLOC ( MAXPARAMLINELENGTH );
|
||
|
buf2 = (char *)MALLOC ( MAXPARAMLINELENGTH );
|
||
|
buf2alloc = MAXPARAMLINELENGTH;
|
||
|
buf2[0] = 0;
|
||
|
buf2len = 0;
|
||
|
|
||
|
for ( i = 0; i < count; )
|
||
|
{
|
||
|
/* get a line in buf1. */
|
||
|
fgets ( buf1, MAXPARAMLINELENGTH, f );
|
||
|
|
||
|
/** lengthen buf2 if necessary. */
|
||
|
while ( buf2len + strlen ( buf1 ) >= buf2alloc )
|
||
|
{
|
||
|
buf2 = (char *)REALLOC ( buf2, buf2alloc + MAXPARAMLINELENGTH );
|
||
|
buf2alloc += MAXPARAMLINELENGTH;
|
||
|
}
|
||
|
/** tack line onto buf2. **/
|
||
|
strcat ( buf2, buf1 );
|
||
|
buf2len += strlen ( buf1 );
|
||
|
|
||
|
/* get the first character of the next line. */
|
||
|
k = fgetc ( f );
|
||
|
if ( k != '+' )
|
||
|
{
|
||
|
/** not a '+', so the line is not continued. **/
|
||
|
|
||
|
/* chop the final newline. */
|
||
|
buf2[buf2len-1] = 0;
|
||
|
for ( j = 0; j < buf2len; ++j )
|
||
|
/* look for a " = " substring, and break it into name/value
|
||
|
there. */
|
||
|
if ( buf2[j] == ' ' && buf2[j+1] == '=' &&
|
||
|
buf2[j+2] == ' ' )
|
||
|
{
|
||
|
/** add the parameter. **/
|
||
|
buf2[j] = 0;
|
||
|
add_parameter ( buf2, buf2+j+3,
|
||
|
PARAM_COPY_NAME|PARAM_COPY_VALUE );
|
||
|
#ifdef DEBUG
|
||
|
fprintf ( stderr, "name = [%s]\nvalue = [%s]\n",
|
||
|
buf2, buf2+j+3 );
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/** reset buf2. **/
|
||
|
buf2[0] = 0;
|
||
|
buf2len = 0;
|
||
|
|
||
|
/* count of how many we've found. */
|
||
|
++i;
|
||
|
}
|
||
|
}
|
||
|
/* put the extra character we read back. */
|
||
|
ungetc ( k, f );
|
||
|
|
||
|
FREE ( buf1 );
|
||
|
FREE ( buf2 );
|
||
|
}
|
||
|
|
||
|
/* write_parameter_database()
|
||
|
*
|
||
|
* this writes all the parameters to a checkpoint file, as "name = value\n".
|
||
|
* since parameters can have embedded newlines, we begin each line of the
|
||
|
* file with a "#" to indicate the start of a new name/value pair or a "+"
|
||
|
* to indicate a continuation of the previous line.
|
||
|
*/
|
||
|
|
||
|
void write_parameter_database ( FILE *f )
|
||
|
{
|
||
|
int i, j;
|
||
|
|
||
|
/* write the total count. */
|
||
|
fprintf ( f, "parameter-count: %d\n", param_size );
|
||
|
for ( i = 0; i < param_size; ++i )
|
||
|
{
|
||
|
/* start the pair with a '#'. */
|
||
|
fputc ( '#', f );
|
||
|
/** write the name, adding '+' after newlines. */
|
||
|
for ( j = 0; j < strlen ( param[i].n ); ++j )
|
||
|
{
|
||
|
fputc ( param[i].n[j], f );
|
||
|
if ( param[i].n[j] == '\n' )
|
||
|
fputc ( '+', f );
|
||
|
}
|
||
|
/* write " = ". */
|
||
|
fputs ( " = ", f );
|
||
|
/** write the value, adding '+' after newlines. */
|
||
|
for ( j = 0; j < strlen ( param[i].v ); ++j )
|
||
|
{
|
||
|
fputc ( param[i].v[j], f );
|
||
|
if ( param[i].v[j] == '\n' )
|
||
|
fputc ( '+', f );
|
||
|
}
|
||
|
/* end the pair. */
|
||
|
fputc ( '\n', f );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* initialize_parameters()
|
||
|
*
|
||
|
* initializes the parameter database. */
|
||
|
|
||
|
void initialize_parameters ( void )
|
||
|
{
|
||
|
oputs ( OUT_SYS, 30, " parameter database.\n" );
|
||
|
|
||
|
param = (parameter *)MALLOC ( PARAMETER_MINSIZE * sizeof ( parameter ) );
|
||
|
param_alloc = PARAMETER_MINSIZE;
|
||
|
param_size = 0;
|
||
|
}
|
||
|
|
||
|
/* free_parameters()
|
||
|
*
|
||
|
* frees all the parameters.
|
||
|
*/
|
||
|
|
||
|
void free_parameters ( void )
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < param_size; ++i )
|
||
|
{
|
||
|
/* if add_parameter made a copy of the name, then free it. */
|
||
|
if ( param[i].copyflags & PARAM_COPY_NAME )
|
||
|
FREE ( param[i].n );
|
||
|
/* if add_parameter make a copy of the value, then free it. */
|
||
|
if ( param[i].copyflags & PARAM_COPY_VALUE )
|
||
|
FREE ( param[i].v );
|
||
|
}
|
||
|
|
||
|
FREE ( param );
|
||
|
param = NULL;
|
||
|
param_alloc = 0;
|
||
|
param_size = 0;
|
||
|
}
|
||
|
|
||
|
/* add_parameter()
|
||
|
*
|
||
|
* adds the given name/value pair to the database. the flags indicate
|
||
|
* which if any of the strings need to be copied.
|
||
|
*/
|
||
|
|
||
|
void add_parameter ( char *name, char *value, int copyflags )
|
||
|
{
|
||
|
|
||
|
/* erase any existing parameter of the same name. */
|
||
|
delete_parameter ( name );
|
||
|
|
||
|
/** if the database is full, make it bigger. **/
|
||
|
while ( param_alloc < param_size+1 )
|
||
|
{
|
||
|
param_alloc += PARAMETER_CHUNKSIZE;
|
||
|
param = (parameter *)REALLOC ( param,
|
||
|
param_alloc * sizeof ( parameter ) );
|
||
|
}
|
||
|
|
||
|
/** add the name. **/
|
||
|
if ( copyflags & PARAM_COPY_NAME )
|
||
|
{
|
||
|
/* make a copy of the string if requested. */
|
||
|
param[param_size].n = (char *)MALLOC ( strlen(name)+1 );
|
||
|
strcpy ( param[param_size].n, name );
|
||
|
}
|
||
|
else
|
||
|
/* just store the pointer passed to us. */
|
||
|
param[param_size].n = name;
|
||
|
|
||
|
/** add the value. **/
|
||
|
if ( copyflags & PARAM_COPY_VALUE )
|
||
|
{
|
||
|
/* make a copy of the string if requested. */
|
||
|
param[param_size].v = (char *)MALLOC ( strlen(value)+1 );
|
||
|
strcpy ( param[param_size].v, value );
|
||
|
}
|
||
|
else
|
||
|
/* just store the pointer passed to us. */
|
||
|
param[param_size].v = value;
|
||
|
|
||
|
/* record whether our values are copies or not. */
|
||
|
param[param_size].copyflags = copyflags;
|
||
|
|
||
|
++param_size;
|
||
|
|
||
|
}
|
||
|
|
||
|
/* delete_parameter()
|
||
|
*
|
||
|
* deletes a parameter from the database.
|
||
|
*/
|
||
|
|
||
|
int delete_parameter ( char *name )
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < param_size; ++i )
|
||
|
if ( strcmp ( name, param[i].n ) == 0 )
|
||
|
{
|
||
|
/** free any copies make by add_parameter. **/
|
||
|
if ( param[i].copyflags & PARAM_COPY_NAME )
|
||
|
FREE ( param[i].n );
|
||
|
if ( param[i].copyflags & PARAM_COPY_VALUE )
|
||
|
FREE ( param[i].v );
|
||
|
|
||
|
/** move the last value in the database to the position
|
||
|
of the deleted one. **/
|
||
|
if ( param_size-1 != i )
|
||
|
{
|
||
|
param[i].n = param[param_size-1].n;
|
||
|
param[i].v = param[param_size-1].v;
|
||
|
param[i].copyflags = param[param_size-1].copyflags;
|
||
|
}
|
||
|
--param_size;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* get_parameter()
|
||
|
*
|
||
|
* looks up a parameter in the database.
|
||
|
*/
|
||
|
|
||
|
char *get_parameter ( char *name )
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < param_size; ++i )
|
||
|
if ( strcmp ( name, param[i].n ) == 0 )
|
||
|
return param[i].v;
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* print_parameters()
|
||
|
*
|
||
|
* dumps parameter database to stdout.
|
||
|
*/
|
||
|
|
||
|
void print_parameters ( void )
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < param_size; ++i )
|
||
|
printf ( "name: \"%s\" value: \"%s\" copy: %d\n",
|
||
|
param[i].n, param[i].v, param[i].copyflags );
|
||
|
|
||
|
}
|
||
|
|
||
|
/* parse_one_parameter()
|
||
|
*
|
||
|
* breaks a string at the first equals sign into name and value parts.
|
||
|
* removes leading and trailing whitespace from both parts. inserts the
|
||
|
* resulting pair into the parameter database.
|
||
|
*/
|
||
|
|
||
|
int parse_one_parameter ( char *buffer )
|
||
|
{
|
||
|
char name[MAXPARAMLINELENGTH+1];
|
||
|
char data[MAXPARAMLINELENGTH+1];
|
||
|
int i, j, k, l;
|
||
|
int n, d;
|
||
|
|
||
|
k = -1;
|
||
|
j = 0;
|
||
|
l = strlen ( buffer );
|
||
|
/** scan for a equals sign. **/
|
||
|
for ( i = 0; i < l; ++i )
|
||
|
{
|
||
|
/* j records whether or not we have found a nonwhitespace
|
||
|
character. */
|
||
|
j += (buffer[i] != ' ' && buffer[i] != '\t' && buffer[i] != '\n');
|
||
|
if ( buffer[i] == '=' )
|
||
|
{
|
||
|
k = i;
|
||
|
/* copy the name part. */
|
||
|
strncpy ( name, buffer, k );
|
||
|
name[k] = 0;
|
||
|
/* copy the value part. */
|
||
|
strcpy ( data, buffer+k+1 );
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* if we found no '=', return an error unless the line was
|
||
|
completely blank. */
|
||
|
if ( k == -1 )
|
||
|
return !!j;
|
||
|
|
||
|
/* trim leading and trailing whitespace. */
|
||
|
n = trim_string ( name );
|
||
|
d = trim_string ( data );
|
||
|
|
||
|
/** if either section is blank, return an error, otherwise add
|
||
|
the pair as a parameter. **/
|
||
|
if ( n == 0 || d == 0 )
|
||
|
return 1;
|
||
|
else
|
||
|
add_parameter ( name, data, PARAM_COPY_NAME|PARAM_COPY_VALUE );
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* trim_string()
|
||
|
*
|
||
|
* trims leading and trailing whitespace from a string, overwriting the
|
||
|
* argument with the result. returns number of characters in result.
|
||
|
*/
|
||
|
|
||
|
int trim_string ( char *string )
|
||
|
{
|
||
|
int i, j, l;
|
||
|
|
||
|
j = -1;
|
||
|
l = strlen ( string );
|
||
|
for ( i = 0; i < l; ++i )
|
||
|
{
|
||
|
if ( j == -1 )
|
||
|
{
|
||
|
if ( string[i] != ' ' && string[i] != '\t' &&
|
||
|
string[i] != '\n' )
|
||
|
{
|
||
|
j = i;
|
||
|
--i;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
string[i-j] = string[i];
|
||
|
}
|
||
|
if ( j == -1 )
|
||
|
{
|
||
|
string[0] = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
string[i-j] = 0;
|
||
|
l = i-j;
|
||
|
j = -1;
|
||
|
for ( i = 0; i < l; ++i )
|
||
|
{
|
||
|
if ( string[i] != ' ' && string[i] != '\t' && string[i] != '\n' )
|
||
|
j = i;
|
||
|
}
|
||
|
string[j+1] = 0;
|
||
|
|
||
|
return j+1;
|
||
|
}
|
||
|
|
||
|
/* define_directive()
|
||
|
*
|
||
|
* defines a directive "SYMBOL", which is just a parameter called
|
||
|
* "__define:SYMBOL". trims leading and trailing whitespace from SYMBOL.
|
||
|
*/
|
||
|
|
||
|
void define_directive ( char *string )
|
||
|
{
|
||
|
char *buffer;
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < strlen(string) && isspace(string[i]); ++i );
|
||
|
|
||
|
buffer = (char *)MALLOC ( (20 + strlen(string)) * sizeof ( char ) );
|
||
|
strcpy ( buffer, "__define:" );
|
||
|
strcat ( buffer, string+i );
|
||
|
|
||
|
for ( i = strlen(buffer)-1; i >= 0 && isspace(buffer[i]); --i )
|
||
|
buffer[i] = 0;
|
||
|
|
||
|
add_parameter ( buffer, "1", PARAM_COPY_NAME );
|
||
|
FREE ( buffer );
|
||
|
}
|
||
|
|
||
|
/* undefine_directive()
|
||
|
*
|
||
|
* undefines a directive "SYMBOL".
|
||
|
*/
|
||
|
|
||
|
void undefine_directive ( char *string )
|
||
|
{
|
||
|
char *buffer;
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < strlen(string) && isspace(string[i]); ++i );
|
||
|
|
||
|
buffer = (char *)MALLOC ( (20 + strlen(string)) * sizeof ( char ) );
|
||
|
strcpy ( buffer, "__define:" );
|
||
|
strcat ( buffer, string+i );
|
||
|
|
||
|
for ( i = strlen(buffer)-1; i >= 0 && isspace(buffer[i]); --i )
|
||
|
buffer[i] = 0;
|
||
|
|
||
|
delete_parameter ( buffer );
|
||
|
FREE ( buffer );
|
||
|
}
|
||
|
|
||
|
/* test_directive()
|
||
|
*
|
||
|
* returns 1 iff a given directive is defined.
|
||
|
*/
|
||
|
|
||
|
int test_directive ( char *string )
|
||
|
{
|
||
|
char *buffer;
|
||
|
int ret;
|
||
|
int i;
|
||
|
|
||
|
for ( i = 0; i < strlen(string) && isspace(string[i]); ++i );
|
||
|
|
||
|
buffer = (char *)MALLOC ( (20 + strlen(string)) * sizeof ( char ) );
|
||
|
strcpy ( buffer, "__define:" );
|
||
|
strcat ( buffer, string+i );
|
||
|
|
||
|
for ( i = strlen(buffer)-1; i >= 0 && isspace(buffer[i]); --i )
|
||
|
buffer[i] = 0;
|
||
|
|
||
|
if ( get_parameter ( buffer ) )
|
||
|
ret = 1;
|
||
|
else
|
||
|
ret = 0;
|
||
|
|
||
|
FREE ( buffer );
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* binary_parameter()
|
||
|
*
|
||
|
* checks for the existence of a parameter. if it exists, then it is changed
|
||
|
* to the string "0" or "1" using lilgp's list of strings representing
|
||
|
* binary values. if the value is not on the list, or the parameter is
|
||
|
* not found, then the parameter is set according to the value argument (it
|
||
|
* acts as a default).
|
||
|
*/
|
||
|
|
||
|
void binary_parameter ( char *name, int value )
|
||
|
{
|
||
|
char *param = get_parameter ( name );
|
||
|
char string[2];
|
||
|
char *i, *is;
|
||
|
int v;
|
||
|
|
||
|
if ( param != NULL )
|
||
|
{
|
||
|
/* copy the value and lowercase it. */
|
||
|
v = strlen ( param );
|
||
|
i = (char *)MALLOC ( (v+1)*sizeof ( char ) );
|
||
|
strcpy ( i, param );
|
||
|
for ( is = i; *is; ++is )
|
||
|
*is = tolower(*is);
|
||
|
|
||
|
/* translate to a binary integer. */
|
||
|
v = translate_binary ( i );
|
||
|
|
||
|
if ( v == -1 )
|
||
|
{
|
||
|
/* translation failed, use the value argument. */
|
||
|
error ( E_ERROR,
|
||
|
"\"%s\" is not a legal value for \"%s\"; assuming default.",
|
||
|
i, name );
|
||
|
v = value;
|
||
|
}
|
||
|
|
||
|
FREE ( i );
|
||
|
|
||
|
}
|
||
|
else
|
||
|
/* parameter not found, use the value argument. */
|
||
|
v = value;
|
||
|
|
||
|
/** print the value to a string and put it in the parameter database. */
|
||
|
sprintf ( string, "%d", !!v );
|
||
|
add_parameter ( name, string, PARAM_COPY_VALUE|PARAM_COPY_NAME );
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|