/*@@ @file Misc.c @date Wed Jan 20 10:06:35 1999 @author Tom Goodale @desc Miscellaneuous routines. @enddesc @version $Header$ @@*/ /*#define DEBUG_MISC*/ #include "cctk_Config.h" #include #include #include #include #include #ifdef HAVE_ASSERT_H #include #endif #include #include #include #include "cctk_GNU.h" #include "cctk_Flesh.h" #include "cctk_Misc.h" #include "cctk_FortranString.h" #include "cctk_WarnLevel.h" #include "util_String.h" static const char *rcsid = "$Header$"; CCTK_FILEVERSION(util_Misc_c) /******************************************************************** ********************* Local Data Types *********************** ********************************************************************/ /******************************************************************** ********************* Local Routine Prototypes ********************* ********************************************************************/ int CCTK_RegexMatch(const char *string, const char *pattern, const int nmatch, regmatch_t *pmatch); int CCTK_SetStringInRegexList(char **data, const char *value, int n_elements, ...); void CCTK_PrintString(const char *data); int CCTK_FCALL CCTK_FNAME(CCTK_Equals) (const char **arg1,ONE_FORTSTRING_ARG); void CCTK_FCALL CCTK_FNAME(CCTK_PrintString) (const char **arg1); void CCTK_FCALL CCTK_FNAME (CCTK_FortranString) (CCTK_INT *nchars, const char *const *cstring, ONE_FORTSTRING_ARG); /******************************************************************** ********************* Other Routine Prototypes ********************* ********************************************************************/ /******************************************************************** ********************* Local Data ***************************** ********************************************************************/ /******************************************************************** ********************* External Routines ********************** ********************************************************************/ /*@@ @routine CCTK_Equals @date Wed Jan 20 10:25:30 1999 @author Tom Goodale @desc Does a case independent comparison of strings. Returns true if they are equal. @enddesc @calls @calledby @history @endhistory @var string1 @vdesc First string in comparison @vtype const char * @vio in @vcomment @endvar @var string2 @vdesc Second string in comparison @vtype const char * @vio in @vcomment @endvar @returntype int @returndesc 1 - equal 0 - not equal @endreturndesc @@*/ int CCTK_Equals(const char *string1, const char *string2) { int retval; retval = 1; /* Check that string1 isn't null */ if (!string1 || !string2) { retval = 0; if (!string1 && string2) { CCTK_VWarn(0,__LINE__,__FILE__,"Cactus", "CCTK_Equals: First string null (2nd is %s)",string2); } else if (string1 && !string2) { CCTK_VWarn(0,__LINE__,__FILE__,"Cactus", "CCTK_Equals: Second string null (1st is %s)",string1); } else { CCTK_Warn(0,__LINE__,__FILE__,"Cactus", "CCTK_Equals: Both strings null"); } } else { if (Util_StrCmpi(string1,string2)) { retval = 0; } } return retval; } int CCTK_FCALL CCTK_FNAME(CCTK_Equals) (const char **arg1,ONE_FORTSTRING_ARG) { int retval; ONE_FORTSTRING_CREATE(arg2) retval = CCTK_Equals(*arg1,arg2); free(arg2); return(retval); } /*@@ @routine Util_NullTerminateString @author Paul Walker @desc Null terminates a fortran string. Need to free the string it returns @enddesc @calls @calledby @history @endhistory @var instring @vdesc String to null terminate @vtype const char * @vio in @vcomment @endvar @var len @vdesc Length of string to be null terminated @vtype unsigned int @vio in @vcomment @endvar @returntype char * @returndesc The null terminated string. @endreturndesc @@*/ char *Util_NullTerminateString(const char *instring, unsigned int len) { char *outstring; unsigned int i; unsigned int position; if (len > 100000) { CCTK_VWarn(1,__LINE__,__FILE__,"Cactus", "Null Terminating a string with length %d !!\n" "This is probably an error in calling a C routine from Fortran", len); } #ifdef DEBUG_MISC printf("Util_NullTerminateString: -%s-, (%u)\n",instring,len); #endif position = len; while (position > 0 && instring[position-1] == ' ') { position--; } outstring = (char *)malloc((position+1)*sizeof(char)); if (outstring) { for (i=0;i 0) && range[pmatch[2].rm_so] != '*') { start = atoi(range+pmatch[2].rm_so); } else { /* No start range given, so use the smallest integer available. */ start = INT_MIN; } /* Next find the end of the range */ if(pmatch[3].rm_so != -1 && (pmatch[3].rm_eo-pmatch[3].rm_so > 0) && range[pmatch[3].rm_so] != '*') { end = atoi(range+pmatch[3].rm_so); } else { /* No end range given, so use the largest integer available. */ end = INT_MAX; } /* Next find the step of the range */ if(pmatch[4].rm_so != -1 && (pmatch[4].rm_eo-pmatch[4].rm_so > 0)) { step = atoi(range+pmatch[4].rm_so); } else { /* No step given, so default to 1. */ step = 1; } /* Finally work out if the range is closed at the upper end. */ if(pmatch[5].rm_so != -1) { switch(range[pmatch[5].rm_so]) { case ')' : end_closed = 0; break; case ']' : default : end_closed = 1; } } else { end_closed = 1; } if(inval >= start + !start_closed && inval <= end - !end_closed && ! ((inval-start) % step)) { retval = 1; } } else { CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid range"); } return retval; } /*@@ @routine Util_DoubleInRange @date Wed Jan 20 10:32:36 1999 @author Tom Goodale @desc This routine will determine if a double is in the range specified in the range string. @enddesc @calls @calledby @history @endhistory @var inval @vdesc The value to check @vtype double @vio in @vcomment @endvar @var range @vdesc The range to look in @vtype const char * @vio in @vcomment @endvar @returntype int @returndesc 1 - in range 0 - not in range @endreturndesc @@*/ int Util_DoubleInRange(double inval, const char *range) { int retval; regmatch_t pmatch[6]; double start, end; #if 0 int start_closed, end_closed; double step; #endif retval = 0; /* Valid ranges are of the form start:end:step * possibly preceeded by a [ or ( and ended by a ) or ] to indicate * closure. The end and step are optional. A * can also be used * to indicate any value. * * The following regular expression may match five substrings: * * 1 - [ or ( * 2 - start * 3 - end * 4 - step * 5 - ) or ] */ if(CCTK_RegexMatch(range, "(\\[|\\()?([^]):]*):?([^]):]*)?:?([^]):]*)?(\\]|\\))?", 6, pmatch) != 0) { #if 0 /* First work out if the range is closed at the lower end. */ if(pmatch[1].rm_so != -1) { switch(range[pmatch[1].rm_so]) { case '(' : start_closed = 0; break; case '[' : default : start_closed = 1; } } else { start_closed = 1; } #endif /* Next find the start of the range */ if(pmatch[2].rm_so != -1 && (pmatch[2].rm_eo-pmatch[2].rm_so > 0) && range[pmatch[2].rm_so] != '*') { start = atof(range+pmatch[2].rm_so); } else { /* No start range given, so use the smallest float available. */ start = -DBL_MAX; } /* Next find the end of the range */ if(pmatch[3].rm_so != -1 && (pmatch[3].rm_eo-pmatch[3].rm_so > 0) && range[pmatch[3].rm_so] != '*') { end = atof(range+pmatch[3].rm_so); } else { /* No end range given, so use the largest float available. */ end = DBL_MAX; } #if 0 /* Next find the step of the range */ if(pmatch[4].rm_so != -1 && (pmatch[4].rm_eo-pmatch[4].rm_so > 0)) { step = atof(range+pmatch[4].rm_so); } else { /* No step given, so default to 1. */ step = 1; } /* Finally work out if the range is closed at the upper end. */ if(pmatch[5].rm_so != -1) { switch(range[pmatch[5].rm_so]) { case ')' : end_closed = 0; break; case ']' : default : end_closed = 1; } } else { end_closed = 1; } #endif if(inval >= start /*+ !start_closed */&& inval <= end /* - !end_closed */ /* && ! ((inval-start) % step)*/) { retval = 1; } } else { CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid range"); } return retval; } /*@@ @routine Util_IntInRangeList @date Wed Jan 20 10:36:31 1999 @author Tom Goodale @desc Determines if an integer is in a given list of ranges. @enddesc @calls @calledby @history @endhistory @var inval @vdesc The value to check @vtype int @vio in @vcomment @endvar @var n_elements @vdesc The number of elements in the list @vtype int @vio in @vcomment @endvar @var ... @vdesc The list of ranges to look in @vtype multiple const char * @vio in @vcomment @endvar @returntype int @returndesc 1 - in range in list 0 - not in range in list @endreturndesc @@*/ int Util_IntInRangeList(int inval, int n_elements, ...) { int retval; int arg; va_list ap; char *element; retval = 0; /* Walk through the element list. */ va_start(ap, n_elements); for(arg = 0; arg < n_elements; arg++) { element = va_arg(ap, char *); if(Util_IntInRange(inval, element)) { retval = 1; break; } } va_end(ap); return retval; } /*@@ @routine Util_DoubleInRangeList @date Wed Jan 20 10:36:31 1999 @author Tom Goodale @desc Determines if a double is in a given list of ranges. @enddesc @calls @calledby @history @endhistory @var inval @vdesc The value to check @vtype double @vio in @vcomment @endvar @var n_elements @vdesc The number of elements in the list @vtype int @vio in @vcomment @endvar @var ... @vdesc The list of ranges to look in @vtype multiple const char * @vio in @vcomment @endvar @returntype int @returndesc 1 - in range in list 0 - not in range in list @endreturndesc @@*/ int Util_DoubleInRangeList(double inval, int n_elements, ...) { int retval; int arg; va_list ap; char *element; retval = 0; /* Walk through the element list. */ va_start(ap, n_elements); for(arg = 0; arg < n_elements; arg++) { element = va_arg(ap, char *); if(Util_DoubleInRange(inval, element)) { retval = 1; break; } } va_end(ap); return retval; } /*@@ @routine CCTK_SetDoubleInRangeList @date Thu Jan 21 09:41:21 1999 @author Tom Goodale @desc Sets the value of a double if the desired value is in one of the specified ranges. @enddesc @calls @calledby @history @endhistory @var data @vdesc Pointer to the value to set @vtype CCTK_REAL * @vio out @vcomment @endvar @var value @vdesc The value to check @vtype const char * @vio in @vcomment @endvar @var n_elements @vdesc The number of elements in the list @vtype int @vio in @vcomment @endvar @var ... @vdesc The list of ranges to look in @vtype multiple const char * @vio in @vcomment @endvar @returntype int @returndesc 1 - in range in list 0 - not in range in list @endreturndesc @@*/ int CCTK_SetDoubleInRangeList(CCTK_REAL *data, const char *value, int n_elements, ...) { int retval; char temp[1001]; unsigned int p; int arg; va_list ap; char *element; CCTK_REAL inval; retval = 1; /* Convert the value string to a double. * Allow various formats. */ strncpy(temp, value, 1000); for (p=0;p (size_t) cctk_strlen1) { CCTK_VWarn (1, __LINE__, __FILE__, "Cactus", "CCTK_FortranString: fortran string buffer is too short to " "hold C string '%s, string will be truncated", *c_string); c_strlen = (size_t) cctk_strlen1; } /* copy up to the size of the fortran string and pad remaining chars in the fortran string with spaces */ memcpy (fortran_string, *c_string, c_strlen); memset (fortran_string + c_strlen, ' ', (size_t) cctk_strlen1 - c_strlen); free (fstring); }