From fbf420d146ff48792fe7aba75092a9426f6b7a67 Mon Sep 17 00:00:00 2001 From: tradke Date: Fri, 25 Aug 2006 15:51:36 +0000 Subject: Have IOUtil_GetAllParameters() encode parameter values before concatenating " = " 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 --- src/CheckpointRecovery.c | 117 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file 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 #include #include #include @@ -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 " = " pair in the resulting string + is separated by a newline character from the next pair. + The "" 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 + " = " pair is separated by a newline character + from the next pair. + The "" 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 " = " 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 "" */ 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 "" */ 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) -- cgit v1.2.3