aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortradke <tradke@b32723a9-ab3a-4a60-88e2-2e5d99d7c17a>2006-08-25 15:51:36 +0000
committertradke <tradke@b32723a9-ab3a-4a60-88e2-2e5d99d7c17a>2006-08-25 15:51:36 +0000
commitfbf420d146ff48792fe7aba75092a9426f6b7a67 (patch)
tree78fe3375c52474a277e64076bf591dee25ab8806
parent779d2cadac44bd50576edfb0dd5c9489c5aa5965 (diff)
Have IOUtil_GetAllParameters() encode parameter values before concatenating
"<parameter> = <value>" pairs by a newline delimiter, and its complement IOUtil_SetAllParameters() do the reverse. This fixes problems with checkpointing/recovery when parameter values themself contained newlines. git-svn-id: http://svn.cactuscode.org/arrangements/CactusBase/IOUtil/trunk@244 b32723a9-ab3a-4a60-88e2-2e5d99d7c17a
-rw-r--r--src/CheckpointRecovery.c117
1 files changed, 111 insertions, 6 deletions
diff --git a/src/CheckpointRecovery.c b/src/CheckpointRecovery.c
index a0563ef..425e6c5 100644
--- a/src/CheckpointRecovery.c
+++ b/src/CheckpointRecovery.c
@@ -18,6 +18,7 @@
#include "ioutil_CheckpointRecovery.h"
+#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
@@ -63,6 +64,8 @@ typedef int (*recover_fn_t) (cGH *GH, const char *basefilename,int called_from);
/********************************************************************
******************** Internal Routines ************************
********************************************************************/
+static char *EncodeString (const char *string);
+static char *DecodeString (const char *string);
static void SetInputFlag (int vindex, const char *optstring, void *arg);
#ifdef HAVE_DIRENT_H
static int CompareFiles (const void *a, const void *b);
@@ -733,6 +736,12 @@ int IOUtil_RecoverParameters (int (*recover_fn) (cGH *GH,
@desc
Collect all parameters of active implementations
into a single string which can then be dumped as an attribute.
+
+ Each "<parameter> = <value>" pair in the resulting string
+ is separated by a newline character from the next pair.
+ The "<value>" substring is encoded such that non-printable
+ characters are contained as escape sequences, and a single
+ '\' character is escaped by another '\' character.
@enddesc
@var GH
@@ -754,7 +763,7 @@ int IOUtil_RecoverParameters (int (*recover_fn) (cGH *GH,
char *IOUtil_GetAllParameters (const cGH *GH, int all)
{
int i, first, add_len, current_len, max_len;
- char *param, *value, *tmp, *retval;
+ char *param, *value, *encoded_value, *tmp, *retval;
const char *thorn;
const cParamData *pdata;
DECLARE_CCTK_PARAMETERS
@@ -795,7 +804,8 @@ char *IOUtil_GetAllParameters (const cGH *GH, int all)
}
else
{
- add_len = strlen (param) + strlen (value) + 5;
+ encoded_value = EncodeString (value);
+ add_len = strlen (param) + strlen (encoded_value) + 5;
if (current_len + add_len >= max_len)
{
/* double new buffer length until buffer is large enough */
@@ -812,9 +822,10 @@ char *IOUtil_GetAllParameters (const cGH *GH, int all)
retval = tmp;
}
- sprintf (retval + current_len, "%s = %s\n", param, value);
+ sprintf (retval + current_len, "%s = %s\n", param, encoded_value);
current_len += add_len - 1;
+ free (encoded_value);
free (value);
}
}
@@ -835,6 +846,15 @@ char *IOUtil_GetAllParameters (const cGH *GH, int all)
@desc
Parse the given string for parameters
and call CCTK_SetParameter() for each.
+
+ The input string is expected to follow the format of
+ IOUtil_GetAllParameters() (see above) where each
+ "<parameter> = <value>" pair is separated by a newline character
+ from the next pair.
+ The "<value>" substring is encoded such that non-printable
+ characters are contained as escape sequences, and a single
+ '\' character is escaped by another '\' character. This
+ encoding is undone before setting the a value of a parameter.
@enddesc
@var parameters
@@ -845,7 +865,7 @@ char *IOUtil_GetAllParameters (const cGH *GH, int all)
@@*/
void IOUtil_SetAllParameters (const char *parameters)
{
- char *tmp, *nextparam, *avalue, *param;
+ char *tmp, *nextparam, *avalue, *decoded_value, *param;
char oldchar;
char *name, *thorn_impl, *parameter_string, *free_me;
const char *thorn;
@@ -856,6 +876,7 @@ void IOUtil_SetAllParameters (const char *parameters)
parameter_string = free_me = strdup (parameters);
while (*parameter_string)
{
+ /* find the end of the current "<parameter> = <value>" pair substring */
nextparam = parameter_string;
while (*nextparam != '\n' && *nextparam)
{
@@ -864,6 +885,7 @@ void IOUtil_SetAllParameters (const char *parameters)
oldchar = *nextparam;
*nextparam = 0;
+ /* find the end of "<parameter>" */
tmp = parameter_string;
while (*tmp != ' ')
{
@@ -872,6 +894,7 @@ void IOUtil_SetAllParameters (const char *parameters)
*tmp = 0;
param = parameter_string;
+ /* skip the " = " delimiter to get to "<value>" */
avalue = tmp + 3;
name = thorn_impl = NULL;
@@ -891,11 +914,14 @@ void IOUtil_SetAllParameters (const char *parameters)
paramdata = CCTK_ParameterData (name, thorn);
if (paramdata && ! paramdata->accumulator_expression)
{
- if (CCTK_ParameterSet (name, thorn, avalue) < 0)
+ decoded_value = DecodeString (avalue);
+ if (CCTK_ParameterSet (name, thorn, decoded_value) < 0)
{
CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING,
- "Couldn't set parameter '%s' to '%s'", param, avalue);
+ "Couldn't set parameter '%s' to '%s'",
+ param, decoded_value);
}
+ free (decoded_value);
}
}
else if (CCTK_Equals (verbose, "full"))
@@ -930,6 +956,85 @@ void IOUtil_SetAllParameters (const char *parameters)
/********************************************************************
******************** Internal Routines ************************
********************************************************************/
+/* encodes a C string with all the non-printable characters converted
+ into a 4-char-long escape sequence representation "\xxx" and
+ the single '\' character converted into "\\" */
+static char *EncodeString (const char *string)
+{
+ size_t i, len = strlen (string);
+ char *p, *retval;
+
+
+ p = retval = malloc (4*len + 1);
+ assert (retval);
+
+ for (i = 0; i < len; i++)
+ {
+ if (! isprint (string[i]))
+ {
+ sprintf (p, "\\%.3d", string[i]);
+ p += 4;
+ }
+ else
+ {
+ *p++ = string[i];
+ if (string[i] == '\\')
+ {
+ *p++ = string[i];
+ }
+ }
+ }
+ *p = 0;
+
+ return (retval);
+}
+
+
+/* decodes a string encoded by EncodeString() back into a C string */
+static char *DecodeString (const char *string)
+{
+ size_t i, len = strlen (string);
+ char *p, *retval;
+
+
+ p = retval = malloc (len + 1);
+ if (! retval)
+ {
+ CCTK_WARN (0, "Out of memory !");
+ }
+
+ for (i = 0; i < len; i++)
+ {
+ if (string[i] != '\\')
+ {
+ *p++ = string[i];
+ }
+ else
+ {
+ assert (i+1 < len);
+ if (string[i+1] == '\\')
+ {
+ *p++ = '\\'; i++;
+ }
+ else
+ {
+ assert (i+3 < len);
+ assert (isdigit (string[i+1]) &&
+ isdigit (string[i+2]) &&
+ isdigit (string[i+3]));
+ *p++ = (char) (100*(string[i+1] - '0') +
+ 10*(string[i+2] - '0') +
+ 1*(string[i+3] - '0'));
+ i += 3;
+ }
+ }
+ }
+ *p = 0;
+
+ return (retval);
+}
+
+
/* callback for CCTK_TraverseString() to set the input flag
for the given variable */
static void SetInputFlag (int vindex, const char *optstring, void *flags)