mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
1571 lines
56 KiB
C++
1571 lines
56 KiB
C++
/*====================================================================
|
|
* ------------------------
|
|
* | CVS File Information |
|
|
* ------------------------
|
|
*
|
|
* $RCSfile$
|
|
*
|
|
* $Author$
|
|
*
|
|
* $Date$
|
|
*
|
|
* $Revision$
|
|
* Symbolic $Name$
|
|
*
|
|
* $Id$
|
|
* $Source$
|
|
*
|
|
*====================================================================*/
|
|
|
|
#ifndef lint
|
|
static char const rcsid[] =
|
|
"$Id$";
|
|
#endif
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <float.h>
|
|
#include <limits.h>
|
|
#include <ctype.h>
|
|
|
|
#include "tok_input_util.h"
|
|
|
|
static char DEFAULT_STR[8] = "default";
|
|
static char DELIMITERS[8] = " \t\n\f\r\v"; /* Defn of white space in isspace()
|
|
- Used in tokenizing lines */
|
|
static char COM_CHAR = '!'; /* This is used as a comment character */
|
|
static char COM_CHAR2 = '#'; /* This is used as a 2nd comment character */
|
|
static char KEY_CHAR = '='; /* This is used to separate the key_string
|
|
from the rest of the line */
|
|
static int PrintInputFile = TRUE; /* Used to turn on and off the
|
|
printing of the input file */
|
|
|
|
/*************** R O U T I N E S I N T H E F I L E *******************
|
|
*
|
|
* NAME TYPE CALLED_BY
|
|
*--------------------------------------------------------------------
|
|
* get_next_keyLine BOOLEAN extern
|
|
* tok_to_int int extern
|
|
* str_to_int int extern, tok_to_int
|
|
* tok_to_double double extern
|
|
* str_to_double double extern,tok_to_double
|
|
* tok_to_boolean BOOLEAN extern
|
|
* str_to_boolean BOOLEAN extern,tok_to_boolean
|
|
* tok_to_string char * extern
|
|
*
|
|
*
|
|
* scan_for_int int extern
|
|
* scan_for_double double extern
|
|
* scan_for_string char * extern
|
|
* scan_for_boolean BOOLEAN extern
|
|
* scan_for_line int extern
|
|
* read_line int scan_for_line,
|
|
* get_next_keyLine
|
|
* interpret_int static BOOLEAN str_to_int + others
|
|
* interpret_boolean static BOOLEAN str_to_boolean
|
|
* interpret_double static BOOLEAN str_to_double
|
|
* strip int read_input_file,
|
|
* look_for,
|
|
* get_next_keyLine
|
|
* read_string static void scan_for_line
|
|
* stokenize int fillTokStruct
|
|
* outofbnds static BOOLEAN all
|
|
* strmatch BOOLEAN extern, toktokmatch
|
|
* strstrmatch BOOLEAN extern
|
|
* strtokmatch BOOLEAN extern
|
|
* toktokmatch BOOLEAN extern, strtokmatch
|
|
* strstrmatch
|
|
* fillTokStruct void extern, strtokmatch
|
|
* strstrmatch,
|
|
* get_next_keyLine
|
|
* copyTokStruct void extern
|
|
*
|
|
******************************************************************************/
|
|
/*
|
|
* Definitions of static functions:
|
|
*/
|
|
|
|
static BOOLEAN outofbnds(const double, const double, const double );
|
|
static BOOLEAN interpret_boolean(const char *, int *, const int);
|
|
static BOOLEAN interpret_int (const char *, int *, const int, const int,
|
|
const int);
|
|
static BOOLEAN interpret_double (const char *, double *, const double,
|
|
const double, const double);
|
|
|
|
|
|
/************ Member Functions for the TOKEN Structure ********************/
|
|
|
|
TOKEN::TOKEN(void) :
|
|
orig_str(0),
|
|
tok_str(0),
|
|
ntokes(0)
|
|
{
|
|
orig_str = copy_string("");
|
|
tok_str = copy_string("");
|
|
tok_ptr[0] = orig_str;
|
|
}
|
|
|
|
|
|
TOKEN::TOKEN(const char *str) :
|
|
orig_str(0),
|
|
tok_str(0),
|
|
ntokes(0)
|
|
{
|
|
if (str == NULL) {
|
|
orig_str = copy_string("");
|
|
tok_str = copy_string("");
|
|
tok_ptr[0] = orig_str;
|
|
ntokes = 0;
|
|
} else {
|
|
orig_str = copy_string(str);
|
|
tok_str = copy_string(str);
|
|
ntokes = stokenize(tok_str, DELIMITERS, tok_ptr, MAXTOKENS);
|
|
}
|
|
}
|
|
|
|
TOKEN::~TOKEN()
|
|
{
|
|
if (orig_str) free(orig_str);
|
|
orig_str = NULL;
|
|
if (tok_str) free(tok_str);
|
|
tok_str = NULL;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
|
|
BOOLEAN get_next_keyLine(FILE *ifp, TOKEN *keyLineTok, TOKEN *keyArgTok)
|
|
/*
|
|
* This routine reads the input file to obtain the next line of
|
|
* uncommented
|
|
* data. The results are returned in two TOKEN structures. keyLineTok
|
|
* contains the key Line (everything before the first equals sign).
|
|
* keyArgTok contains everything after the equals sign.
|
|
* Note - Either keyLineTok or keyArgTok may be the null token
|
|
* (but not both)
|
|
*
|
|
* The definition of a token structure, given in .h file,
|
|
* is as follows:
|
|
*
|
|
* struct TOKEN {
|
|
* char orig_str[MAX_INPUT_STR_LN + 1];
|
|
* char tok_str[MAX_INPUT_STR_LN + 1];
|
|
* char *tok_ptr[MAXTOKENS];
|
|
* int ntokes;
|
|
* };
|
|
* mdp_allo.h
|
|
* orig_str Contains the original string, unmodified.
|
|
* tok_str Contains a modified version of the string,
|
|
* whose positions
|
|
* are pointed to by tok_ptr[i] values. It is usually not
|
|
* referenced directly.
|
|
* tok_ptr[i] Contains the i_th token of the original string. This
|
|
* is a stripped character string. 0 <=i <= i-1
|
|
* ntokes Number of tokens in the string.
|
|
*
|
|
*
|
|
* Comments are denoted by either '!' or '#'.
|
|
* Everything after the comment character on a
|
|
* line is stripped first. The comment character can occur
|
|
* anywhere in the line.
|
|
*
|
|
* Arguments to the keyLine are denoted by everything after a
|
|
* '=' character on the line.
|
|
*
|
|
* Example:
|
|
* ---------------------------------------------------------------
|
|
* ! Jack and Jill went up the hill to fetch a pale of water
|
|
* ! Jack by nimble, Jack be swift; Jack jump over the candle stick
|
|
*
|
|
* The meaning of life is = 36.243 24 136 Not even ! close
|
|
* -----------------------------------------------------------------
|
|
*
|
|
* Then, the routine would return (amongst other things):
|
|
* keyLineTok->orig_str = "The meaning of life is"
|
|
* keyArgTok->orig_str = "36.243 24 36 Not even"
|
|
* keyArgTok->ntokes = 5
|
|
* keyArgTok->tok_ptr[0] = "36.243"
|
|
* keyArgTok->tok_ptr[1] = "24"
|
|
* keyArgTok->tok_ptr[2] = "136"
|
|
* keyArgTok->tok_ptr[3] = "Not"
|
|
* keyArgTok->tok_ptr[4] = "Even"
|
|
*
|
|
* The function returns TRUE if there is a next line to process.
|
|
* It returns false if an EOF is encountered.
|
|
*/
|
|
{
|
|
int retn_value, i;
|
|
char save_input[MAX_INPUT_STR_LN + 1];
|
|
char *token_start = NULL;
|
|
|
|
/*
|
|
* Check the arguments to the routine. This routine needs to be
|
|
* supplied with valid pointers to files and spaces for storage
|
|
* of its output in the return tokens.
|
|
*/
|
|
if (ifp == NULL || keyLineTok == NULL || keyArgTok == NULL) {
|
|
fprintf(stderr, "get_next_keyLine ERROR, arguments are bad\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
/*
|
|
* Read a chunk of text, either up to a newline from the file pointer,
|
|
* ifp. If an EOF occurs, return without changing the input structure
|
|
*/
|
|
do_it_again:
|
|
do {
|
|
if ((retn_value = read_string(ifp, save_input, '\n')) < 0) {
|
|
return(FALSE);
|
|
}
|
|
if (PrintInputFile) {
|
|
if (retn_value <=0) printf ("%s\n", save_input);
|
|
else printf ("%s", save_input);
|
|
}
|
|
for (i = 0; i < (int) strlen(save_input); i++) {
|
|
if (save_input[i] == COM_CHAR || save_input[i] == COM_CHAR2) {
|
|
save_input[i] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
} while (strip(save_input) == 0);
|
|
|
|
/*
|
|
* Discover whether there are arguments in the line
|
|
* and then separate the line into two
|
|
*/
|
|
|
|
for (i = 0; i < (int) strlen(save_input); i++) {
|
|
if (save_input[i] == KEY_CHAR) {
|
|
save_input[i] = '\0';
|
|
token_start = save_input + i + 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Strip the two strings of leading and trailing white space.
|
|
* If both strings are now the null string (because the line
|
|
* consisted of a single '=' character for example),
|
|
* go back and get a new line.
|
|
*/
|
|
|
|
i = strip(token_start);
|
|
if (!strip(save_input)) if (!i) goto do_it_again;
|
|
|
|
/*
|
|
* Now that we have two strings representing the Key String and
|
|
* associated arguments, process them into TOKEN structures.
|
|
* Note - if token_start still points to NULL, then fillTokStruct
|
|
* will fill keyArgTok with a "null token".
|
|
*/
|
|
|
|
fillTokStruct(keyLineTok, save_input);
|
|
fillTokStruct(keyArgTok, token_start);
|
|
return (TRUE);
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
int tok_to_int(const TOKEN *tokPtr, const int maxVal, const int minVal,
|
|
const int defaultVal, BOOLEAN *error)
|
|
/*
|
|
* Interprets the first string of a TOKEN structure as an int.
|
|
* Returns the interpreted value as the return value.
|
|
* AnErrors condition is created if more than one token is found
|
|
* in the struct TOKEN.
|
|
* Bounds checking is done on the value before returning. Value
|
|
* must be between the maxVal and minVal; it can equal the max or min
|
|
* value.
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value (defined in <limits.h>
|
|
* --------- --------------
|
|
* INT_MAX, max, all INT_MAX
|
|
* INT_MIN INT_MIN
|
|
* N/A, Not Available INT_MIN
|
|
* default or "" defaultVal
|
|
*
|
|
* A default may be specified on the command line. The absence of a
|
|
* default may also be specified by setting devault_value to
|
|
* NO_DEFAULT_INT.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
if (tokPtr->ntokes == 0)
|
|
return(str_to_int(DEFAULT_STR, maxVal, minVal, defaultVal, error));
|
|
else if (tokPtr->ntokes > 1) {
|
|
(void) fprintf(stderr, "ERROR: tok_to_int, ntokes > 1: %s\n",
|
|
tokPtr->orig_str);
|
|
*error = TRUE;
|
|
}
|
|
return(str_to_int(tokPtr->tok_ptr[0], maxVal, minVal, defaultVal, error));
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
int str_to_int(const char *int_string, const int maxVal, const int minVal,
|
|
const int defaultVal, BOOLEAN *error)
|
|
/*
|
|
* Interprets a stripped character string as an integer.
|
|
* Bounds checking is done on the value before returning. Value
|
|
* must be between the max and min; it can equal the max or min value.
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value (defined in <limits.h>
|
|
* --------- --------------
|
|
* INT_MAX, max, all INT_MAX
|
|
* INT_MIN INT_MIN
|
|
* N/A, Not Available INT_MIN
|
|
* default default_value
|
|
*
|
|
* A default may be specified on the command line. The absence of a
|
|
* default may also be specified by setting devault_value to
|
|
* NO_DEFAULT_INT.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
int retn_value, check = FALSE;
|
|
double LmaxVal, LminVal;
|
|
if (defaultVal == NO_DEFAULT_INT) check = TRUE;
|
|
if (interpret_int(int_string, &retn_value, maxVal, minVal, defaultVal)) {
|
|
if (check) {
|
|
if (retn_value == NO_DEFAULT_INT) {
|
|
(void) fprintf(stderr,
|
|
"ERROR: str_to_int: Default not allowed\n");
|
|
*error = TRUE;
|
|
}
|
|
}
|
|
if (maxVal < INT_MAX) LmaxVal = (double) maxVal + 0.01;
|
|
else LmaxVal = (double) maxVal;
|
|
if (minVal > INT_MIN) LminVal = (double) minVal - 0.01;
|
|
else LminVal = (double) minVal;
|
|
if (outofbnds((double) retn_value, LmaxVal, LminVal)) {
|
|
fprintf(stderr,
|
|
"ERROR: str_to_int outofbnds:\n\t\"%s\"\n",
|
|
int_string);
|
|
fprintf(stderr,"\tmax = %d, min = %d\n", maxVal, minVal);
|
|
*error = TRUE;
|
|
}
|
|
} else
|
|
*error = TRUE;
|
|
return (retn_value);
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
double tok_to_double(const TOKEN * tokPtr, const double maxVal,
|
|
const double minVal, const double defaultVal,
|
|
BOOLEAN *error)
|
|
/*
|
|
* Interprets the first string of a TOKEN structure as a double.
|
|
* Returns the interpreted value as the return value.
|
|
* Errors conditions are created if more than one token is found.
|
|
*
|
|
* Bounds checking is then done on the value before returning. Value
|
|
* must be between the max and min; it can equal the max or min.
|
|
*
|
|
* Useful values for bounds (specified in <limits.h>:
|
|
* DBL_MAX = largest legitimate value of a double ~ 2.0E-308
|
|
* -DBL_MAX = smallest legitimate value of a double ~ 2.0E-308
|
|
* DBL_EPSILON = smallest value of a double that can be added to one
|
|
* and produce a different number. ~ 2.0E-16
|
|
* DBL_MIN = smallest value of a double ~ 2.0E-308
|
|
* For example:
|
|
* If 0.0 is not a legitimate number for value, set min = DBL_MIN
|
|
* If value>=0.0 is legitimate, set min = 0.0
|
|
* if value<=100., set max = 100.
|
|
* If no range checking is required, set max = DBL_MAX, min = -DBL_MAX
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* Token_String Retn_Value ( specified in <limits.h>
|
|
* --------- ---------------------------------------
|
|
* FLT_MAX, all FLT_MAX
|
|
* DBL_MAX, max DBL_MAX
|
|
* N/A -DBL_MAX
|
|
* default or "" default_value
|
|
* small, DBL_MIN DBL_MIN
|
|
* DBL_EPSILON DBL_EPSILON
|
|
*
|
|
* A default may be specified by either specifying the value as
|
|
* "default" or by the absense of any tokens in the TOKEN struct.
|
|
* The absence of a default may also be specified by setting the
|
|
* value of default_value to NO_DEFAULT_DOUBLE.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
if (tokPtr->ntokes == 0)
|
|
return(str_to_double(DEFAULT_STR, maxVal, minVal, defaultVal, error));
|
|
else if (tokPtr->ntokes > 1) {
|
|
(void) fprintf(stderr, "ERROR: tok_to_double, ntokes > 1: %s\n",
|
|
tokPtr->orig_str);
|
|
*error = TRUE;
|
|
}
|
|
return(str_to_double(tokPtr->tok_ptr[0], maxVal, minVal, defaultVal, error));
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
double str_to_double(const char *dbl_string, const double maxVal,
|
|
const double minVal, const double defaultVal,
|
|
BOOLEAN *error)
|
|
/*
|
|
* Interprets a stripped character string as a double. Returns the
|
|
* interpreted value as the return value.
|
|
*
|
|
* Bounds checking is then done on the value before returning. Value
|
|
* must be between the max and min; it can equal the max or min.
|
|
*
|
|
* Useful values for bounds (specified in <limits.h>:
|
|
* DBL_MAX = largest legitimate value of a double ~ 2.0E-308
|
|
* -DBL_MAX = smallest legitimate value of a double ~ 2.0E-308
|
|
* DBL_EPSILON = smallest value of a double that can be added to one
|
|
* and produce a different number. ~ 2.0E-16
|
|
* DBL_MIN = smallest value of a double ~ 2.0E-308
|
|
* For example:
|
|
* If 0.0 is not a legitimate number for value, set min = DBL_MIN
|
|
* If value>=0.0 is legitimate, set min = 0.0
|
|
* if value<=100., set max = 100.
|
|
* If no range checking is required, set max = DBL_MAX, min = -DBL_MAX
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value ( specified in <limits.h>
|
|
* --------- ---------------------------------------
|
|
* FLT_MAX, all FLT_MAX
|
|
* DBL_MAX, max DBL_MAX
|
|
* N/A -DBL_MAX
|
|
* default default_value
|
|
* small, DBL_MIN DBL_MIN
|
|
* DBL_EPSILON DBL_EPSILON
|
|
*
|
|
* A default may be specified. The absence of a
|
|
* default may also be specified by setting the value of default_value
|
|
* to NO_DEFAULT_DOUBLE.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
double retn_value;
|
|
int check = FALSE;
|
|
if (defaultVal == NO_DEFAULT_DOUBLE) check = TRUE;
|
|
if (interpret_double(dbl_string, &retn_value, maxVal, minVal, defaultVal)) {
|
|
if (check)
|
|
if (retn_value == NO_DEFAULT_DOUBLE) {
|
|
(void) fprintf(stderr,
|
|
"ERROR: keyLine_double: Default not allowed\n");
|
|
*error = TRUE;
|
|
}
|
|
if (outofbnds(retn_value, maxVal, minVal)) {
|
|
(void) fprintf(stderr, "ERROR: keyLine_double outofbnds:\n\t\"%s\"\n",
|
|
dbl_string);
|
|
(void) fprintf(stderr,"\tmax = %e, min = %e\n", maxVal, minVal);
|
|
*error = TRUE;
|
|
}
|
|
} else
|
|
*error = TRUE;
|
|
return (retn_value);
|
|
}
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
|
|
BOOLEAN tok_to_boolean(const TOKEN *tokPtr, const int default_value,
|
|
BOOLEAN *error)
|
|
/*
|
|
* Interprets the first string of a TOKEN structure as a BOOLEAN.
|
|
* (i.e., TRUE or FALSE). Returns the interpreted value as the
|
|
* return value.
|
|
* Errors conditions are created if more than one token is found.
|
|
*
|
|
* The following character strings are interpreted
|
|
* (case doesn't matter):
|
|
*
|
|
* TRUE = "YES", "TRUE", "T", "Y"
|
|
* FALSE = "NO, "FALSE", "N", "F"
|
|
* default_value = "DEFAULT" or ""
|
|
*
|
|
* A default may be specified on the command line. The absence of a
|
|
* default may also be specified by using the value of NO_DEFAULT_INT.
|
|
* If tokPtr contains no tokens, this routine will try to use the
|
|
* default value.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
if (tokPtr->ntokes == 0)
|
|
return(str_to_boolean(DEFAULT_STR, default_value, error));
|
|
else if (tokPtr->ntokes > 1) {
|
|
(void) fprintf(stderr, "ERROR: tok_to_boolean, ntokes > 1: %s\n",
|
|
tokPtr->orig_str);
|
|
*error = TRUE;
|
|
}
|
|
return(str_to_boolean(tokPtr->tok_ptr[0], default_value, error));
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
BOOLEAN str_to_boolean(const char *string, const int default_value,
|
|
BOOLEAN *error)
|
|
/*
|
|
* Interprets a stripped character string as a BOOLEAN value
|
|
* (i.e., TRUE or FALSE). It returns that value as the return value.
|
|
*
|
|
* The following character strings are interpreted
|
|
* (case doesn't matter):
|
|
*
|
|
* TRUE = "YES", "TRUE", "T", "Y"
|
|
* FALSE = "NO, "FALSE", "N", "F"
|
|
* default_value = "DEFAULT"
|
|
*
|
|
* A default may be specified on the command line. The absence of a
|
|
* default may also be specified by using the value of NO_DEFAULT_INT.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
int retn_value;
|
|
if (interpret_boolean(string, &retn_value, default_value)) {
|
|
if (retn_value == NO_DEFAULT_BOOLEAN) {
|
|
(void) fprintf(stderr,
|
|
"ERROR: keyLine_boolean: Default not allowed\n");
|
|
*error = TRUE;
|
|
}
|
|
} else
|
|
*error = TRUE;
|
|
return ((BOOLEAN) retn_value);
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
char *tok_to_string(const TOKEN *tokPtr, const int maxTok,
|
|
const int minTok, const char *defaultVal, BOOLEAN *error)
|
|
/*
|
|
* Interprets the arguments in a TOKEN structure as a string.
|
|
* It mallocs new space for the string, are returns the pointer to it.
|
|
* The number of tokens in the string is checked before returning.
|
|
* The value must be between the maxTok and minTok; it can equal the
|
|
* max or min value.
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value
|
|
* --------- --------------
|
|
* default or "" defaultVal
|
|
*
|
|
* A default may be specified on the command line. The absence of a
|
|
* default may also be specified by setting devault_value to
|
|
* NO_DEFAULT_INT.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
char *str;
|
|
if (tokPtr->ntokes == 0)
|
|
str = str_to_string(DEFAULT_STR, defaultVal, error);
|
|
else
|
|
str = str_to_string(tokPtr->orig_str, defaultVal, error);
|
|
if (outofbnds((double) tokPtr->ntokes, (double) maxTok,
|
|
(double) minTok)) {
|
|
(void) fprintf(stderr, "ERROR: tok_to_String:\n\t\"%s\"\n",
|
|
tokPtr->orig_str);
|
|
(void) fprintf(stderr,"\tmaxTok = %d, minTok = %d\n", maxTok, minTok);
|
|
*error = TRUE;
|
|
}
|
|
return (str);
|
|
}
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
|
|
char *str_to_string(const char *str, const char *defaultVal,
|
|
BOOLEAN *error)
|
|
/*
|
|
* Interprets the argument string as a string.
|
|
* It mallocs new space for the string, are returns the pointer to it.
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value
|
|
* --------- --------------
|
|
* default defaultVal
|
|
*
|
|
* A default may be specified on the command line. The absence of a
|
|
* default may also be specified by setting devault_value to
|
|
* NO_DEFAULT_INT.
|
|
*
|
|
* If there is an error, *error is set to TRUE. *error isn't touched
|
|
* if there isn't an error.
|
|
*/
|
|
{
|
|
if (str == NULL) {
|
|
*error = TRUE;
|
|
(void) fprintf(stderr,"ERROR str_to_string: str is uninialized\n");
|
|
return(NULL);
|
|
}
|
|
if (strmatch(str, DEFAULT_STR)) {
|
|
if (strmatch(defaultVal, NO_DEFAULT_STR)) {
|
|
*error = TRUE;
|
|
(void) fprintf(stderr,"ERROR str_to_string: no default allowed\n");
|
|
return(copy_string(NO_DEFAULT_STR));
|
|
} else
|
|
return(copy_string(defaultVal));
|
|
}
|
|
return(copy_string(str));
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
int scan_for_int(FILE *ifp, const char *str, const int maxVal,
|
|
const int minVal)
|
|
/*
|
|
* Scans the file for a line matching string. Then, interprets
|
|
* everything after the equals sign as a single integer.
|
|
* Bounds checking is done on the value before returning. Value
|
|
* must be between the max and min; it can equal the max or min value.
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value
|
|
* --------- --------------
|
|
* INT_MAX, max, all INT_MAX
|
|
* INT_MIN, default INT_MIN
|
|
* N/A, Not Available INT_MIN
|
|
*
|
|
* Because this is a fixed format input file routine, errors are
|
|
* handled by terminally exiting the program.
|
|
*/
|
|
{
|
|
int retn_value, defaultVal = INT_MIN;
|
|
char *tok_ptr[2];
|
|
char input[MAX_INPUT_STR_LN + 1];
|
|
if (scan_for_line(ifp, str, input, KEY_CHAR, PrintInputFile) < 0)
|
|
exit(-1);
|
|
if (stokenize(input, DELIMITERS, tok_ptr, 2) == 1) {
|
|
if (interpret_int(tok_ptr[0], &retn_value,
|
|
maxVal, minVal, defaultVal)) {
|
|
if (outofbnds((double) retn_value, (double) maxVal,
|
|
(double) minVal)) {
|
|
fprintf(stderr,
|
|
"ERROR: scan_for_int outofbnds:\n\t\"%s\"\n",str);
|
|
fprintf(stderr,"\tmax = %d, min = %d\n", maxVal, minVal);
|
|
exit(-1);
|
|
} else
|
|
return(retn_value);
|
|
}
|
|
}
|
|
fprintf(stderr, "ERROR while processing line, \"%s\"\n", str);
|
|
exit(-1); /*NOTREACHED*/
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
BOOLEAN scan_for_boolean(FILE *ifp, const char *string)
|
|
/*
|
|
* Scans the file for a line matching string. Then, interprets
|
|
* everything after the equals sign as a single boolean value
|
|
*
|
|
* Because this is a fixed format input file routine, errors are
|
|
* handled by terminally exiting the program.
|
|
*/
|
|
{
|
|
int ret_value;
|
|
char *tok_ptr[2];
|
|
char input[MAX_INPUT_STR_LN + 1];
|
|
if (scan_for_line(ifp, string, input, KEY_CHAR, PrintInputFile) < 0) exit(-1);
|
|
if (stokenize(input, DELIMITERS, tok_ptr, 2) == 1) {
|
|
if (interpret_boolean(tok_ptr[0], &ret_value, NO_DEFAULT_BOOLEAN)) {
|
|
if (ret_value == NO_DEFAULT_BOOLEAN) {
|
|
(void) fprintf(stderr, "scan_for_boolean: default not allowed\n");
|
|
exit (-1);
|
|
}
|
|
return((BOOLEAN) ret_value);
|
|
}
|
|
}
|
|
(void) fprintf(stderr, "scan_for_boolean: ERROR on line \"%s\"\n", string);
|
|
exit (-1); /*NOTREACHED*/
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
double scan_for_double(FILE *ifp, const char *string, const double maxVal,
|
|
const double minVal)
|
|
/*
|
|
* Scans the file for a line matching string. Then, interprets
|
|
* everything after the equals sign as a single floating point number.
|
|
* Bounds checking is then done on the value before returning. Value
|
|
* must be between the max and min; it can equal the max or min.
|
|
*
|
|
* Useful values for bounds:
|
|
* DBL_MAX = largest legitimate value of a double ~ 2.0E-308
|
|
* -DBL_MAX = smallest legitimate value of a double ~ 2.0E-308
|
|
* DBL_EPSILON = smallest value of a double that can be added to one
|
|
* and produce a different number. ~ 2.0E-16
|
|
* DBL_MIN = smallest value of a double ~ 2.0E-308
|
|
* For example:
|
|
* If 0.0 is not a legitimate number for value, set min = DBL_MIN
|
|
* If value>=0.0 is legitimate, set min = 0.0
|
|
* if value<=100., set max = 100.
|
|
* If no range checking is required, set max = DBL_MAX, min = -DBL_MAX
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value
|
|
* --------- --------------
|
|
* FLT_MAX, all FLT_MAX
|
|
* DBL_MAX, max DBL_MAX
|
|
* N/A, default -DBL_MAX
|
|
* small, DBL_MIN DBL_MIN
|
|
* DBL_EPSILON DBL_EPSILON
|
|
*
|
|
* Because this is a fixed format input file routine, errors are
|
|
* handled by terminally exiting the program.
|
|
*/
|
|
{
|
|
double retn_value;
|
|
char *tok_ptr[2];
|
|
char input[MAX_INPUT_STR_LN + 1];
|
|
if (scan_for_line(ifp, string, input, KEY_CHAR, TRUE) < 0) exit(-1);
|
|
if (stokenize(input, DELIMITERS, tok_ptr, 2) > 0) {
|
|
if (interpret_double(tok_ptr[0], &retn_value, maxVal, minVal,
|
|
NO_DEFAULT_DOUBLE)) {
|
|
if (retn_value == NO_DEFAULT_DOUBLE) {
|
|
(void) fprintf(stderr,
|
|
"ERROR: scan_for_double has no default\n");
|
|
exit(-1);
|
|
}
|
|
if (outofbnds(retn_value, maxVal, minVal)) {
|
|
(void) fprintf(stderr,
|
|
"ERROR: scan_for_double outofbnds:\n \"%s = %e\"\n",
|
|
string, retn_value);
|
|
(void) fprintf(stderr,"\tmax = %e, min = %e\n", maxVal, minVal);
|
|
exit(-1);
|
|
} else
|
|
return(retn_value);
|
|
}
|
|
}
|
|
(void) fprintf(stderr, "ERROR scan_for_double: \"%s\"\n", string);
|
|
exit(-1); /*NOTREACHED*/
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
char *scan_for_string(FILE *ifp, const char *string, const int maxVal,
|
|
const int minVal)
|
|
/*
|
|
* Scans the file for a line matching string. Then, interprets
|
|
* everything after the equals sign as string to be returned.
|
|
* Storage for the resulting string is malloced, and the address
|
|
* of the string is returned.
|
|
* The string is returned stripped of leading and trailing white space,
|
|
* and of comments.
|
|
*
|
|
* Length checking is then done on the number of characters returned.
|
|
*
|
|
* Because this is a fixed format input file routine, errors are
|
|
* handled by terminally exiting the program.
|
|
*/
|
|
{
|
|
int len;
|
|
char input[MAX_INPUT_STR_LN + 1];
|
|
if (scan_for_line(ifp, string, input, KEY_CHAR, PrintInputFile) < 0)
|
|
exit(-1);
|
|
len = strlen(input);
|
|
if (outofbnds((double) len, (double) maxVal, (double) minVal)) {
|
|
(void) fprintf(stderr,
|
|
"ERROR: scan_for_string string length: \"%s = %s\"\n", string, input);
|
|
(void) fprintf(stderr, "\tlength max = %d, min = %d\n", maxVal, minVal);
|
|
exit(-1);
|
|
}
|
|
return (copy_string(input));
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
int scan_for_line(FILE *ifp, const char *str, char input[],
|
|
const char ch_term, const int print_flag)
|
|
/*
|
|
* Scan the input file (reading in strings according to
|
|
* 'read_string(ifp,)'
|
|
* specifications) until the character pattern in 'string' is matched.
|
|
* Returns all of the characters after the termination character in
|
|
* a null-character terminated string,
|
|
*
|
|
* Parameter list:
|
|
*
|
|
* ifp == pointer to file "input"
|
|
* string == contains string pattern to be matched.
|
|
* input == buffer array to hold characters that are read in.
|
|
* On output, it contains the return character string
|
|
* ch_term== Termination character. When scanning a line of input
|
|
* is read until either a newline, the 'ch' termination
|
|
* character is read, or the end-of-file is read.
|
|
*
|
|
* Output:
|
|
* This function returns the number of characters in the string
|
|
* input,
|
|
* excluding the null character. Error conditions are currently
|
|
* handled by returning with negative return values.
|
|
*/
|
|
{
|
|
int retn_value, i;
|
|
BOOLEAN found = FALSE;
|
|
char match_string[MAX_INPUT_STR_LN+1],
|
|
save_input[MAX_INPUT_STR_LN+1];
|
|
static const char *ename = "ERROR scan_for_line: ";
|
|
|
|
/*
|
|
* Error test the input match string
|
|
*/
|
|
|
|
if (strlen(str) > MAX_INPUT_STR_LN) {
|
|
fprintf(stderr,"%sMatch string is too long:\n\t%s\n",
|
|
ename, str);
|
|
return(-1);
|
|
}
|
|
|
|
/*
|
|
* Make it an error to have the comment indicator in a
|
|
* match string
|
|
*/
|
|
|
|
for (i = 0; i < (int) strlen(str); i++) {
|
|
if (str[i] == COM_CHAR || str[i] == COM_CHAR2) {
|
|
fprintf(stderr, "%s Comment in match string\n\t%s\n",
|
|
ename, str);
|
|
return(-1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Strip the string of leading and trailing white space
|
|
*/
|
|
|
|
if ((retn_value = strip(strcpy(match_string, str))) <= 0) {
|
|
fprintf(stderr, "%sMatch string is white space: \"%s\"\n",
|
|
ename, str);
|
|
return(-1);
|
|
}
|
|
|
|
/*
|
|
* Start the search for the string
|
|
*/
|
|
|
|
do
|
|
{
|
|
/*
|
|
* Read a chunk of text, either up to a newline or to the
|
|
* character ch_term, from the file pointer, ifp.
|
|
*/
|
|
|
|
if ((retn_value = read_string(ifp, save_input, ch_term)) < 0) {
|
|
fprintf (stderr,
|
|
"%sEOF found in input file while searching for:\n", ename);
|
|
fprintf (stderr, "\t\"%s\"\n", match_string);
|
|
return(retn_value);
|
|
}
|
|
|
|
/*
|
|
* copy the string just read to the output string, and the
|
|
* strip it of leading and trailing white space, and comments.
|
|
* Then, compare the stripped input string with the stripped
|
|
* match_string
|
|
*/
|
|
|
|
strcpy(input, save_input);
|
|
if (strip(input) > 0)
|
|
found = strmatch(input, match_string);
|
|
|
|
/*
|
|
* If requested print the line, including comments, on standard output.
|
|
* Use the retn_value from read_string to test whether a \n needs to
|
|
* be written.
|
|
*/
|
|
|
|
if (print_flag) {
|
|
if (found) printf ("->\t");
|
|
if (retn_value == 0)
|
|
printf("%s\n", save_input);
|
|
else
|
|
printf("%s%c", save_input, ch_term);
|
|
}
|
|
|
|
/*
|
|
* Read and print the rest of the line, if we are in the middle of it.
|
|
*/
|
|
|
|
if (retn_value > 0) {
|
|
if ((retn_value = read_line(ifp, input, print_flag)) < 0) {
|
|
fprintf(stderr,
|
|
"ERROR, EOF found in input file while reading line:\n");
|
|
fprintf(stderr, "%s %c\n", str, ch_term);
|
|
return(retn_value);
|
|
}
|
|
}
|
|
else
|
|
input[0] = '\0';
|
|
} while (!found);
|
|
return (retn_value);
|
|
}
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
|
|
int read_line(FILE *ifp, char input[], const int print_flag)
|
|
|
|
/*
|
|
* read_line:
|
|
*
|
|
* Reads a line of input. The line is
|
|
* printed to standard output, if print_flag is true.
|
|
* The line is returned in the character
|
|
* string pointed to by input. Leading and trailing white spaces are
|
|
* stripped from the line.
|
|
* The number of characters, excluding the null character, is
|
|
* returned, except when read_string encounters an error condition
|
|
* (negative return values). Then, the error condition is returned.
|
|
*/
|
|
{
|
|
int retn_value;
|
|
|
|
/*
|
|
* read the file up to the next new line, read_string will return
|
|
* a 0 for a success, and a negative value for failure
|
|
*/
|
|
|
|
retn_value = read_string(ifp, input, '\n');
|
|
|
|
/*
|
|
* Print out the line before stripping it of comments and white space
|
|
*/
|
|
|
|
if (print_flag) printf ("%s\n", input);
|
|
|
|
/*
|
|
* Strip the return line of comments and leading/trailing white space
|
|
* Use the function strip to return the number of characters remaining
|
|
*/
|
|
|
|
if (retn_value == 0) return (strip(input));
|
|
|
|
/*
|
|
* If an error condition occurred in read_string, return the error
|
|
* condition value instead of the character count
|
|
*/
|
|
|
|
(void) strip(input);
|
|
return (retn_value);
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
int read_string(FILE *ifp, char string[], const char ch)
|
|
/*
|
|
* This routine reads the standard input until encountering
|
|
* the end-of-file, a newline, the character 'ch' or until
|
|
* MAX_INPUT_STR_LN characters are read. The inputted characters
|
|
* are read into 'string'.
|
|
* If an EOF occurs, -1 is returned.
|
|
* If a line is longer than MAX_INPUT_STR_LN, a -2 is returned
|
|
* and an error message is written to standard error.
|
|
* string[] will be returned null-terminated with the
|
|
* first MAX_INPUT_STR_LN of the line.
|
|
* Upon successful completion with the read terminated by the
|
|
* character 'ch', the number of characters read plus 1 for the
|
|
* null character at the end of the string is returned. If the
|
|
* read is terminated by '\n', a 0 is returned, even if ch = '\n'
|
|
*
|
|
*
|
|
* Parameter list:
|
|
*
|
|
* ifp == pointer to file "input"
|
|
* string == On output, 'string' contains the characters read
|
|
* from the input stream. However, the termination character
|
|
* or the newline character is not included
|
|
* ch == Additional Termination character. That is, input function
|
|
* stops when 'ch' or '\n' is read.
|
|
*/
|
|
{
|
|
int i = 0, rtn_value, new_ch;
|
|
|
|
/*
|
|
* Read from the file, until termination conditions occur
|
|
* The order in the while statement is important.
|
|
*/
|
|
while( (i < MAX_INPUT_STR_LN )
|
|
&& ((new_ch = getc(ifp)) != ch )
|
|
&& ( new_ch != '\n')
|
|
&& ( new_ch != EOF )) string[i++] = new_ch;
|
|
|
|
/*
|
|
* Check for termination conditions
|
|
*/
|
|
if (new_ch == EOF) {
|
|
rtn_value = -1;
|
|
}
|
|
else if (i == MAX_INPUT_STR_LN) {
|
|
fprintf(stderr,
|
|
"read_string ERROR: Maxed line character count, %d,"
|
|
" before finding (%c)\n", MAX_INPUT_STR_LN, ch);
|
|
rtn_value = -2;
|
|
}
|
|
else if (new_ch == '\n')
|
|
rtn_value = 0;
|
|
else
|
|
rtn_value = i + 1;
|
|
|
|
/*
|
|
* Make sure the string is null terminated and return
|
|
*/
|
|
string[i] = '\0';
|
|
return (rtn_value);
|
|
}
|
|
/**************************************************************************/
|
|
|
|
static BOOLEAN interpret_boolean(const char *token, int *ret_value,
|
|
const int default_value)
|
|
/*
|
|
* This routine interprets a string token to be either true or false
|
|
* and then returns the appropriate answer as an int value in the
|
|
* variable ret_value. It is int because the default value may not
|
|
* be only 0 or 1
|
|
*/
|
|
{
|
|
/* lower_case (token); */
|
|
if (token[0] == '\0')
|
|
*ret_value = default_value;
|
|
else if (strlen(token) == 1) {
|
|
switch (token[0]) {
|
|
case 't':
|
|
case 'y':
|
|
*ret_value = TRUE; break;
|
|
case 'f':
|
|
case 'n':
|
|
*ret_value = FALSE; break;
|
|
default:
|
|
return (FALSE);
|
|
}
|
|
} else {
|
|
if (strmatch(token,"true") || strmatch(token,"yes"))
|
|
*ret_value = TRUE;
|
|
else if (strmatch(token,"false") || strmatch(token,"no"))
|
|
*ret_value = FALSE;
|
|
else if (strmatch(token,DEFAULT_STR) == 0) {
|
|
*ret_value = default_value;
|
|
} else {
|
|
return (FALSE);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
/**************************************************************************/
|
|
|
|
static BOOLEAN interpret_int(const char *token, int *retn_value,
|
|
const int maxVal, const int minVal,
|
|
const int defaultVal)
|
|
/*
|
|
* This routine interprets a string token to be an integer
|
|
* and then returns the appropriate answer as an int value in the
|
|
* variable ret_value.
|
|
* Errors are indicated by returning FALSE. Success is indicated
|
|
* by returning TRUE.
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value
|
|
* --------- --------------
|
|
* INT_MAX, all INT_MAX
|
|
* INT_MIN INT_MIN
|
|
* max maxVal
|
|
* min minVal
|
|
* default defaultVal
|
|
* NULL string defaultVal
|
|
* N/A, Not_Available INT_MIN
|
|
*/
|
|
{
|
|
int retn;
|
|
|
|
/*
|
|
* Allow a few key ascii phrases in place of an actual int
|
|
*/
|
|
|
|
/* lower_case(token); */
|
|
if (token[0] == '\0')
|
|
*retn_value = defaultVal;
|
|
else if ((strmatch(token,"all")) || strmatch(token,"int_max") )
|
|
*retn_value = INT_MAX;
|
|
else if (strmatch(token,"int_min"))
|
|
*retn_value = INT_MIN;
|
|
else if (strmatch(token,"max"))
|
|
*retn_value = maxVal;
|
|
else if (strmatch(token,"min"))
|
|
*retn_value = minVal;
|
|
else if (strmatch(token,DEFAULT_STR))
|
|
*retn_value = defaultVal;
|
|
else if (strmatch(token,"n/a") || strmatch(token,"not_available"))
|
|
*retn_value = INT_MIN;
|
|
else {
|
|
if ((retn = sscanf(token, "%d", retn_value)) != 1) {
|
|
*retn_value = retn;
|
|
return (FALSE);
|
|
}
|
|
}
|
|
return (TRUE);
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
static BOOLEAN interpret_double(const char *token, double *retn_value,
|
|
const double maxVal, const double minVal,
|
|
const double defaultVal)
|
|
/*
|
|
* This routine interprets a string token to be a double
|
|
* and then returns the appropriate answer as a double value in the
|
|
* variable retn_value.
|
|
* The function itself returns TRUE if successful or FALSE if unsuccessful
|
|
*
|
|
*
|
|
* Certain ascii strings are checked for first (case is insignificant):
|
|
*
|
|
* String Retn_Value
|
|
* --------- --------------
|
|
* FLT_MAX, all FLT_MAX
|
|
* FLT_MIN FLT_MIN
|
|
* DBL_MAX DBL_MAX
|
|
* max maxVal
|
|
* min minVal
|
|
* default defaultVal
|
|
* NULL string defaultVal
|
|
* N/A -DBL_MAX
|
|
* small, DBL_MIN DBL_MIN
|
|
* DBL_EPSILON DBL_EPSILON
|
|
*
|
|
* DBL_MAX = largest legitimate value of a double ~ 2.0E-308
|
|
* -DBL_MAX = smallest legitimate value of a double ~ - 2.0E-308
|
|
* DBL_EPSILON = smallest value of a double that can be added to one
|
|
* and produce a different number. ~ 2.0E-16
|
|
* DBL_MIN = tiniest value of a double ~ 2.0E-308
|
|
*/
|
|
{
|
|
int retn;
|
|
float retn_float;
|
|
|
|
/*
|
|
* Allow a few key ascii phrases in place of an actual float
|
|
*/
|
|
|
|
/* lower_case(token); */
|
|
if (token[0] == '\0')
|
|
*retn_value = defaultVal;
|
|
else if ((strmatch(token,"all")) || strmatch(token,"flt_max"))
|
|
*retn_value = FLT_MAX;
|
|
else if (strmatch(token,"flt_min"))
|
|
*retn_value = FLT_MIN;
|
|
else if (strmatch(token,"dbl_max"))
|
|
*retn_value = DBL_MAX;
|
|
else if (strmatch(token,"max"))
|
|
*retn_value = maxVal;
|
|
else if (strmatch(token,"min"))
|
|
*retn_value = minVal;
|
|
else if (strmatch(token,"n/a"))
|
|
*retn_value = -DBL_MAX;
|
|
else if (strmatch(token, DEFAULT_STR))
|
|
*retn_value = defaultVal;
|
|
else if (strmatch(token,"small") || strmatch(token,"dbl_min"))
|
|
*retn_value = DBL_MIN;
|
|
else if (strmatch(token,"dbl_epsilon"))
|
|
*retn_value = DBL_EPSILON;
|
|
else {
|
|
if ((retn = sscanf(token, "%e", &retn_float)) != 1) {
|
|
*retn_value = (double) retn;
|
|
return (FALSE);
|
|
} else
|
|
*retn_value = (double) retn_float;
|
|
}
|
|
return(TRUE);
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
int strip(char str[])
|
|
/*
|
|
* This routine strips off blanks and tabs (only leading and trailing
|
|
* characters) in 'str'. On return, it returns the number of
|
|
* characters still included in the string (excluding the null character).
|
|
*
|
|
* Comments are excluded -> All instances of the comment character, '!',
|
|
* are replaced by '\0' thereby terminating
|
|
* the string
|
|
*
|
|
* Parameter list:
|
|
*
|
|
* str == On output 'str' contains the same characters as on
|
|
* input except the leading and trailing white space and
|
|
* comments have been removed.
|
|
*/
|
|
{
|
|
int i = 0, j = 0;
|
|
char ch;
|
|
|
|
/*
|
|
* Quick Returns
|
|
*/
|
|
|
|
if ((str == NULL) || (str[0] == '\0')) return (0);
|
|
|
|
/* Find first non-space character character */
|
|
|
|
while(((ch = str[i]) != '\0') && isspace(ch)) i++;
|
|
|
|
/*
|
|
* Move real part of str to the front by copying the string
|
|
* - Comments are handled here, by terminating the copy at the
|
|
* first comment indicator, and inserting the null character at
|
|
* that point.
|
|
*/
|
|
|
|
while ( (ch = str[j+i]) != '\0' &&
|
|
(ch != COM_CHAR) &&
|
|
(ch != COM_CHAR2) ) {
|
|
str[j] = ch;
|
|
j++;
|
|
}
|
|
str[j] = '\0';
|
|
j--;
|
|
|
|
/* Remove trailing white space by inserting a null character */
|
|
|
|
while( (j != -1 ) && isspace(str[j])) j--;
|
|
j++;
|
|
str[j] = '\0';
|
|
return (j);
|
|
}
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
void lower_case(char str[])
|
|
/*
|
|
* lower_case:
|
|
* Translates a string delimited by a NULL character
|
|
* to lower case. There is no error checking in this version.
|
|
* Relies on stlib function, tolower.
|
|
*/
|
|
{
|
|
int i;
|
|
for (i = 0; i < (int) strlen(str); i++) {
|
|
# if defined(_INCLUDE_XOPEN_SOURCE) && ! defined(__lint)
|
|
str[i] = _tolower((str[i]));
|
|
# else
|
|
str[i] = tolower(str[i]);
|
|
# endif
|
|
}
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
char *TokToStrng (const TOKEN *keyptr)
|
|
/*
|
|
* TokToStrng:
|
|
* Mallocs a new character string and copies
|
|
* the tokens character string to it, appending all tokens together
|
|
* into a single string separated by a single space character.
|
|
* It returns the pointer to the new string;
|
|
* The new string should be freed when no longer needed.
|
|
*/
|
|
{
|
|
int i;
|
|
if (!keyptr) return NULL;
|
|
if (!keyptr->orig_str) return NULL;
|
|
int iln = strlen(keyptr->orig_str) + 1 + keyptr->ntokes;
|
|
char *fstr = (char *) malloc(iln * sizeof(char));
|
|
|
|
char *const*str = &(keyptr->tok_ptr[0]);
|
|
for (i = 0, fstr[0]= '\0'; i < (keyptr->ntokes - 1); i++, str++) {
|
|
(void) strcat(strcat(fstr, *str), " ");
|
|
}
|
|
return(strcat(fstr, *str));
|
|
}
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
/******************************************************************************/
|
|
|
|
int stokenize(char *string, const char *delimiters, char *tok_ptr[],
|
|
const int max_tokens)
|
|
/*
|
|
* stokenize
|
|
*
|
|
* This function will break up a string into its respective "tokens".
|
|
* It returns the number of tokens found. See the strtok(3) man page.
|
|
*
|
|
* input
|
|
* ----------
|
|
* string - String to be tokenized. Note, that the string is
|
|
* changed by this procedure. Null characters are
|
|
* put between each symbol.
|
|
* delimiters - String containing a list of delimiters.
|
|
* The example below covers 'white space'
|
|
* e.g., char *delimiters = " \t\n";
|
|
* max_tokens - Maximum number of tokens to be found
|
|
*
|
|
* output
|
|
* -----------
|
|
* tok_ptr - Vector of pointers to strings, that contain the input
|
|
* string's tokens
|
|
*/
|
|
{
|
|
int i = 0;
|
|
if (string == NULL) {
|
|
tok_ptr[0] = NULL;
|
|
return 0;
|
|
}
|
|
if (strlen(string) == 0) {
|
|
tok_ptr[0] = string;
|
|
return 0;
|
|
}
|
|
if ( (tok_ptr[0] = strtok(string, delimiters)) != NULL) {
|
|
do {
|
|
if ( (++i) == max_tokens) break;
|
|
} while ( (tok_ptr[i] = strtok(NULL, delimiters)) != NULL);
|
|
}
|
|
return (i);
|
|
}
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
|
|
static BOOLEAN outofbnds(const double value, const double maxVal,
|
|
const double minVal)
|
|
/*
|
|
* This routine checks the bounds of a single double value.
|
|
* If it is inside or on the bounds, it returns false.
|
|
* If it is outside the bounds, it returns true.
|
|
*/
|
|
{
|
|
if ((value <= maxVal) && (value >= minVal)) return (FALSE);
|
|
return(TRUE);
|
|
}
|
|
/******************************************************************************
|
|
*
|
|
* strmatch():
|
|
*
|
|
* This routine checks whether one string is the same as another.
|
|
* Upper case is transformed into lower case before the comparison is done.
|
|
* Thus, case doesn't matter in the comparison. However, white space
|
|
* does matter in this comparison.
|
|
* If they are, it returns true
|
|
* If they aren't, it returns false
|
|
*/
|
|
BOOLEAN strmatch(const char *s1, const char *s2)
|
|
{
|
|
while (*s1 != '\0') {
|
|
# if defined (_INCLUDE_XOPEN_SOURCE) && ! defined(__lint)
|
|
if (_tolower((*s1++)) != _tolower((*s2++))) return (FALSE);
|
|
# else
|
|
if (tolower(*s1) != tolower(*s2)) return (FALSE);
|
|
s1++; s2++;
|
|
# endif
|
|
}
|
|
if (*s2 != '\0') return (FALSE);
|
|
return (TRUE);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* strstrmatch():
|
|
*
|
|
* This routine checks whether two strings are the same modulo differences
|
|
* in their white space
|
|
*/
|
|
BOOLEAN strstrmatch(const char *s1, const char*s2)
|
|
{
|
|
struct TOKEN tmpKeyStruct1, tmpKeyStruct2;
|
|
fillTokStruct(&tmpKeyStruct1, s1);
|
|
fillTokStruct(&tmpKeyStruct2, s2);
|
|
return (toktokmatch(&tmpKeyStruct2, &tmpKeyStruct1));
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* strtokmatch():
|
|
*
|
|
* This routine checks whether a string matches the string contained in
|
|
* the tokens of a keyLineStr.
|
|
* White space and case are ignored.
|
|
* If they are, it returns true
|
|
* If they aren't, it returns false
|
|
*/
|
|
BOOLEAN strtokmatch(const TOKEN *keyptr, const char*s2)
|
|
{
|
|
struct TOKEN tmpKeyStruct;
|
|
fillTokStruct(&tmpKeyStruct, s2);
|
|
return (toktokmatch(keyptr, &tmpKeyStruct));
|
|
}
|
|
|
|
/**************************************************************************
|
|
*
|
|
* toktokmatch()
|
|
*
|
|
* This routine checks whether two TOKEN structures contain the
|
|
* same data up to differences in white space.
|
|
* Case is ignored as well, as strmatch is called.
|
|
*/
|
|
BOOLEAN toktokmatch(const TOKEN *keyptr1, const TOKEN *keyptr2)
|
|
{
|
|
int i = keyptr1->ntokes;
|
|
if (i != keyptr2->ntokes) return FALSE;
|
|
while (i > 0) {
|
|
i--;
|
|
if (!strmatch(keyptr1->tok_ptr[i], keyptr2->tok_ptr[i])) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/*
|
|
* fillTokStruct()
|
|
*
|
|
* Fill in a keyLineStruct with a string. Use the defn of white space
|
|
* at the start of the file to tokenize the string, storring it in the
|
|
* TOKEN structure.
|
|
*/
|
|
void fillTokStruct(TOKEN *keyptr1, const char *s2)
|
|
{
|
|
if (keyptr1 == NULL) return;
|
|
if (keyptr1->orig_str) free(keyptr1->orig_str);
|
|
if (keyptr1->tok_str) free(keyptr1->tok_str);
|
|
if (s2 == NULL) {
|
|
keyptr1->orig_str = copy_string("");
|
|
keyptr1->tok_str = copy_string("");
|
|
keyptr1->ntokes = 0;
|
|
keyptr1->tok_ptr[0] = keyptr1->orig_str;
|
|
return;
|
|
}
|
|
keyptr1->orig_str = copy_string(s2);
|
|
keyptr1->tok_str = copy_string(s2);
|
|
keyptr1->ntokes = stokenize(keyptr1->tok_str, DELIMITERS, keyptr1->tok_ptr,
|
|
MAXTOKENS);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* copyTokStruct():
|
|
*
|
|
* Copies the information stored in keyptr2 into keyptr1
|
|
*/
|
|
void copyTokStruct(TOKEN *keyptr1, const TOKEN *keyptr2)
|
|
{
|
|
if (keyptr1 == NULL) return;
|
|
if (keyptr2 == NULL) return;
|
|
if (keyptr1->orig_str) free(keyptr1->orig_str);
|
|
if (keyptr1->tok_str) free(keyptr1->tok_str);
|
|
if (keyptr2->orig_str == NULL) {
|
|
keyptr1->orig_str = copy_string("");
|
|
keyptr1->tok_str = copy_string("");
|
|
keyptr1->ntokes = 0;
|
|
keyptr1->tok_ptr[0] = keyptr1->orig_str;
|
|
return;
|
|
}
|
|
keyptr1->orig_str = copy_string(keyptr2->orig_str);
|
|
keyptr1->tok_str = copy_string(keyptr2->orig_str);
|
|
keyptr1->ntokes = stokenize(keyptr1->tok_str, DELIMITERS, keyptr1->tok_ptr,
|
|
MAXTOKENS);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* in_char_list():
|
|
*
|
|
* Finds a match of one string against a list of strings. Returns
|
|
* the position that the first match occurred.
|
|
* If no match occurred, returns -1.
|
|
* The comparisons ignore differences in white space.
|
|
*/
|
|
int in_char_list(const char * const str1, const char ** const list,
|
|
int num_list)
|
|
{
|
|
int i;
|
|
for (i = 0; i < num_list; i++) if (strstrmatch(str1, list[i])) return(i);
|
|
return (-1);
|
|
}
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
|
|
char *copy_string(const char *string)
|
|
/*
|
|
* copy_string:
|
|
* Mallocs a new character string and copies the old string to it
|
|
*
|
|
* NOTE: Memory leak may result if the calling program doesn't free
|
|
* the malloced space
|
|
*/
|
|
{
|
|
char *new_string;
|
|
new_string = (char *) malloc(strlen(string)+1);
|
|
if (new_string == NULL) {
|
|
(void) fprintf(stderr, "copy_string ERROR: malloc returned NULL");
|
|
} else {
|
|
(void) strcpy(new_string, string);
|
|
}
|
|
return (new_string);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* strip_item_from_token ():
|
|
*
|
|
* Change the token by taking eliminating the iword'th token from the token
|
|
* structure and reformulating the token expression
|
|
*/
|
|
void strip_item_from_token(int iword, TOKEN *tok)
|
|
{
|
|
if (!tok) return;
|
|
if (iword < 0 || iword > tok->ntokes) return;
|
|
int ioffset = tok->tok_ptr[iword] - tok->tok_str;
|
|
int ilength = strlen(tok->tok_ptr[iword]);
|
|
int i = ioffset;
|
|
int j = ioffset + ilength;
|
|
if (j <= (int) strlen(tok->orig_str)) {
|
|
while(tok->orig_str[j] != '\0') {
|
|
tok->orig_str[i] = tok->orig_str[j];
|
|
i++;
|
|
j++;
|
|
}
|
|
tok->orig_str[i] = '\0';
|
|
}
|
|
strcpy(tok->tok_str, tok->orig_str);
|
|
tok->ntokes = stokenize(tok->tok_str, DELIMITERS, tok->tok_ptr,
|
|
MAXTOKENS);
|
|
}
|
|
|
|
/*****************************************************************************/
|