summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorschnetter <schnetter@17b73243-c579-4c4c-a9d2-2d5706c11dac>2008-06-17 20:24:04 +0000
committerschnetter <schnetter@17b73243-c579-4c4c-a9d2-2d5706c11dac>2008-06-17 20:24:04 +0000
commitc2fd657f1677a3a0335224a68c4ae39c6c2713a3 (patch)
tree45927d66159c35039a56525bf3c8ec9ff5be7b5a /src/util
parent5c085cb015a8a6a3c1e229689b55a6a0cf29fa79 (diff)
Cactus has currently an error in its parameter checking. It
interprets ranges consisting of single numbers as allowing this number and all larger numbers. For example, the specification INT spatial_order "Order of spatial differencing" { 2 :: "second order" 4 :: "fourth order" } 2 allows all numbers not less than 2. This patch corrects this problem. Since this involves regular expressions which are often difficult to read, I have broken up the regular expressions into macros containing sub-expressions. I have also replaced calls to atoi and atof with calls to strtol and strtod, since these allow error checking which also was not present before. git-svn-id: http://svn.cactuscode.org/flesh/trunk@4496 17b73243-c579-4c4c-a9d2-2d5706c11dac
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Misc.c279
1 files changed, 226 insertions, 53 deletions
diff --git a/src/util/Misc.c b/src/util/Misc.c
index f8642e41..37c7ba2f 100644
--- a/src/util/Misc.c
+++ b/src/util/Misc.c
@@ -363,13 +363,11 @@ int Util_InList(const char *string1, int n_elements, ...)
@@*/
int Util_IntInRange(int inval, const char *range)
{
- int retval;
- regmatch_t pmatch[6];
+ int retval = 0;
+ regmatch_t pmatch[8];
int start_closed, end_closed;
int start, end, step;
- 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
@@ -379,14 +377,37 @@ int Util_IntInRange(int inval, const char *range)
*
* 1 - [ or (
* 2 - start
- * 3 - end
- * 4 - step
- * 5 - ) or ]
+ * 3 - whether end is present
+ * 4 - end
+ * 5 - whether step is present
+ * 6 - step
+ * 7 - ) or ]
*/
- if(CCTK_RegexMatch(range,
- "(\\[|\\()?([^]):]*):?([^]):]*)?:?([^]):]*)?(\\]|\\))?",
- 6, pmatch) != 0)
+#define R_BEGIN "(\\[|\\()?"
+#define R_VALUE "([^]):]*)"
+#define R_SEP ":"
+#define R_END "(\\]|\\))?"
+
+#define R_MAYBE(x) "(" x ")?"
+
+ const char pattern[] =
+ R_BEGIN
+ R_VALUE
+ R_MAYBE(R_SEP
+ R_VALUE
+ R_MAYBE(R_SEP
+ R_VALUE))
+ R_END;
+
+#undef R_BEGIN
+#undef R_VALUE
+#undef R_SEP
+#undef R_END
+
+#undef R_MAYBE
+
+ if(CCTK_RegexMatch(range, pattern, 8, pmatch) != 0)
{
/* First work out if the range is closed at the lower end. */
if(pmatch[1].rm_so != -1)
@@ -408,7 +429,13 @@ int Util_IntInRange(int inval, const char *range)
(pmatch[2].rm_eo-pmatch[2].rm_so > 0) &&
range[pmatch[2].rm_so] != '*')
{
- start = atoi(range+pmatch[2].rm_so);
+ char *endptr;
+ start = strtol(range+pmatch[2].rm_so, &endptr, 10);
+ if (endptr == range+pmatch[2].rm_so)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid start");
+ start = INT_MIN;
+ }
}
else
{
@@ -416,27 +443,57 @@ int Util_IntInRange(int inval, const char *range)
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] != '*')
+ /* Next find whether end of the range is present */
+ if(pmatch[3].rm_so != -1)
{
- end = atoi(range+pmatch[3].rm_so);
+ /* Next find the end of the range */
+ if(pmatch[4].rm_so != -1 &&
+ (pmatch[4].rm_eo-pmatch[4].rm_so > 0) &&
+ range[pmatch[4].rm_so] != '*')
+ {
+ char *endptr;
+ end = strtol(range+pmatch[4].rm_so, &endptr, 10);
+ if (endptr == range+pmatch[4].rm_so)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid end");
+ end = INT_MIN;
+ }
+ }
+ else
+ {
+ /* No end range given, so use the largest integer available. */
+ end = INT_MAX;
+ }
}
else
{
- /* No end range given, so use the largest integer available. */
- end = INT_MAX;
+ /* End range not given, so interval has length zero. */
+ end = start;
}
- /* Next find the step of the range */
- if(pmatch[4].rm_so != -1 && (pmatch[4].rm_eo-pmatch[4].rm_so > 0))
+ /* Next find whether step of the range is present */
+ if(pmatch[5].rm_so != -1)
{
- step = atoi(range+pmatch[4].rm_so);
+ /* Next find the step of the range */
+ if(pmatch[6].rm_so != -1 && (pmatch[6].rm_eo-pmatch[6].rm_so > 0))
+ {
+ char *endptr;
+ step = strtol(range+pmatch[6].rm_so, &endptr, 10);
+ if (endptr == range+pmatch[6].rm_so)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid step");
+ step = 1;
+ }
+ }
+ else
+ {
+ /* No step given, so default to 1. */
+ step = 1;
+ }
}
else
{
- /* No step given, so default to 1. */
+ /* Step not given, so default to 1. */
step = 1;
}
if (step <= 0)
@@ -446,9 +503,9 @@ int Util_IntInRange(int inval, const char *range)
}
/* Finally work out if the range is closed at the upper end. */
- if(pmatch[5].rm_so != -1)
+ if(pmatch[7].rm_so != -1)
{
- switch(range[pmatch[5].rm_so])
+ switch(range[pmatch[7].rm_so])
{
case ')' : end_closed = 0; break;
case ']' :
@@ -460,12 +517,12 @@ int Util_IntInRange(int inval, const char *range)
end_closed = 1;
}
- /* Cast to unsigned int, because the subtraction (inval - start)
+ /* Cast to unsigned long, because the subtraction (inval - start)
can overflow, and wrap-around is legal in C only for unsigned
types. */
if(inval >= start + !start_closed &&
inval <= end - !end_closed &&
- ! (((unsigned int)inval-(unsigned int)start) % (unsigned int)step))
+ ! (((unsigned long)inval-(unsigned long)start) % (unsigned long)step))
{
retval = 1;
}
@@ -512,55 +569,159 @@ int Util_IntInRange(int inval, const char *range)
@@*/
int Util_DoubleInRange(double inval, const char *range)
{
- int retval;
- regmatch_t pmatch[6];
- double start, end;
-
- retval = 0;
+ int retval = 0;
+ regmatch_t pmatch[8];
+ int start_closed, end_closed;
+ double start, end, step;
/*
* The following regular expression may match five substrings:
*
* 1 - [ or (
* 2 - start
- * 3 - end
- * 4 - step
- * 5 - ) or ]
+ * 3 - whether end is present
+ * 4 - end
+ * 5 - whether step is present
+ * 6 - step
+ * 7 - ) or ]
*/
- if(CCTK_RegexMatch(range,
- "(\\[|\\()?([^]):]*):?([^]):]*)?:?([^]):]*)?(\\]|\\))?",
- 6, pmatch) != 0)
+#define R_BEGIN "(\\[|\\()?"
+#define R_VALUE "([^]):]*)"
+#define R_SEP ":"
+#define R_END "(\\]|\\))?"
+
+#define R_MAYBE(x) "(" x ")?"
+
+ const char pattern[] =
+ R_BEGIN
+ R_VALUE
+ R_MAYBE(R_SEP
+ R_VALUE
+ R_MAYBE(R_SEP
+ R_VALUE))
+ R_END;
+
+#undef R_BEGIN
+#undef R_VALUE
+#undef R_SEP
+#undef R_END
+
+#undef R_MAYBE
+
+ if(CCTK_RegexMatch(range, pattern, 8, pmatch) != 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;
+ }
+
/* 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);
+ char *endptr;
+ start = strtod(range+pmatch[2].rm_so, &endptr);
+ if (endptr == range+pmatch[2].rm_so)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid start");
+ start = -HUGE_VAL;
+ }
+ }
+ else
+ {
+ /* No start range given, so use the smallest double available. */
+ start = -HUGE_VAL;
+ }
+
+ /* Next find whether end of the range is present */
+ if(pmatch[3].rm_so != -1)
+ {
+ /* Next find the end of the range */
+ if(pmatch[4].rm_so != -1 &&
+ (pmatch[4].rm_eo-pmatch[4].rm_so > 0) &&
+ range[pmatch[4].rm_so] != '*')
+ {
+ char *endptr;
+ end = strtod(range+pmatch[4].rm_so, &endptr);
+ if (endptr == range+pmatch[4].rm_so)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid end");
+ end = HUGE_VAL;
+ }
+ }
+ else
+ {
+ /* No end range given, so use the largest double available. */
+ end = HUGE_VAL;
+ }
+ }
+ else
+ {
+ /* End range not given, so interval has length zero. */
+ end = start;
+ }
+
+ /* Next find whether step of the range is present */
+ if(pmatch[5].rm_so != -1)
+ {
+ /* Next find the step of the range */
+ if(pmatch[6].rm_so != -1 && (pmatch[6].rm_eo-pmatch[6].rm_so > 0))
+ {
+ char *endptr;
+ step = strtod(range+pmatch[6].rm_so, &endptr);
+ if (endptr == range+pmatch[6].rm_so)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid step");
+ step = 0;
+ }
+ }
+ else
+ {
+ /* No step given, so default to 0. */
+ step = 0;
+ }
}
else
{
- /* No start range given, so use the smallest float available. */
- start = -DBL_MAX;
+ /* Step not given, so default to 0. */
+ step = 0;
+ }
+ if (step < 0)
+ {
+ CCTK_Warn(1, __LINE__, __FILE__, "Flesh", "Invalid step");
+ step = 0;
}
- /* 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] != '*')
+ /* Finally work out if the range is closed at the upper end. */
+ if(pmatch[7].rm_so != -1)
{
- end = atof(range+pmatch[3].rm_so);
+ switch(range[pmatch[7].rm_so])
+ {
+ case ')' : end_closed = 0; break;
+ case ']' :
+ default : end_closed = 1;
+ }
}
else
{
- /* No end range given, so use the largest float available. */
- end = DBL_MAX;
+ end_closed = 1;
}
- if(inval >= start /*+ !start_closed */&&
- inval <= end /* - !end_closed */ /* &&
- ! ((inval-start) % step)*/)
+ if((start_closed ? inval >= start : inval > start) &&
+ (end_closed ? inval <= end : inval < end ) &&
+ (step ? ! fmod (inval - start, step) : 1))
{
retval = 1;
}
@@ -746,6 +907,7 @@ int CCTK_SetDoubleInRangeList(CCTK_REAL *data, const char *value,
va_list ap;
char *element;
+ char *endptr;
CCTK_REAL inval;
@@ -757,7 +919,7 @@ int CCTK_SetDoubleInRangeList(CCTK_REAL *data, const char *value,
strncpy(temp, value, sizeof(temp) - 1);
temp[sizeof(temp) - 1] = 0;
- for (p=0;p<strlen(temp);p++)
+ for (p=0;temp[p];p++)
{
if (temp[p] == 'E' ||
temp[p] == 'd' ||
@@ -768,7 +930,12 @@ int CCTK_SetDoubleInRangeList(CCTK_REAL *data, const char *value,
}
}
- inval = atof(temp);
+ inval = strtod(temp, &endptr);
+ if (endptr == temp)
+ {
+ retval = 0;
+ return retval;
+ }
/* Walk through the element list. */
va_start(ap, n_elements);
@@ -835,6 +1002,7 @@ int CCTK_SetIntInRangeList(CCTK_INT *data, const char *value,
va_list ap;
char *element;
+ char *endptr;
CCTK_INT inval;
@@ -842,7 +1010,12 @@ int CCTK_SetIntInRangeList(CCTK_INT *data, const char *value,
/* Convert the value string to an int.*/
- inval = atoi(value);
+ inval = strtol(value, &endptr, 10);
+ if (endptr == value)
+ {
+ retval = 0;
+ return retval;
+ }
/* Walk through the element list. */
va_start(ap, n_elements);