diff options
author | tradke <tradke@b32723a9-ab3a-4a60-88e2-2e5d99d7c17a> | 2006-08-25 15:51:36 +0000 |
---|---|---|
committer | tradke <tradke@b32723a9-ab3a-4a60-88e2-2e5d99d7c17a> | 2006-08-25 15:51:36 +0000 |
commit | fbf420d146ff48792fe7aba75092a9426f6b7a67 (patch) | |
tree | 78fe3375c52474a277e64076bf591dee25ab8806 | |
parent | 779d2cadac44bd50576edfb0dd5c9489c5aa5965 (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.c | 117 |
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) |