diff options
author | tradke <tradke@17b73243-c579-4c4c-a9d2-2d5706c11dac> | 2001-07-31 18:02:23 +0000 |
---|---|---|
committer | tradke <tradke@17b73243-c579-4c4c-a9d2-2d5706c11dac> | 2001-07-31 18:02:23 +0000 |
commit | 582e313ba78b1b9d4687612e0c4bc510fc8a1a36 (patch) | |
tree | af0801a33b214a5fb331e2e3ca145532a69fd404 /src/main/Groups.c | |
parent | 7954ec568940a12b64450827c281b849fd44dd3f (diff) |
Fixed parsing of option string in CCTK_TraverseString().
git-svn-id: http://svn.cactuscode.org/flesh/trunk@2297 17b73243-c579-4c4c-a9d2-2d5706c11dac
Diffstat (limited to 'src/main/Groups.c')
-rw-r--r-- | src/main/Groups.c | 247 |
1 files changed, 144 insertions, 103 deletions
diff --git a/src/main/Groups.c b/src/main/Groups.c index dbcbe801..ca122b8c 100644 --- a/src/main/Groups.c +++ b/src/main/Groups.c @@ -8,6 +8,7 @@ @version $Id$ @@*/ +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -1511,13 +1512,13 @@ void CCTK_FCALL CCTK_FNAME (CCTK_GroupDimFromVarI) @desc Traverse through all variables and/or groups whose names appear in the given string, and call the callback routine - with those indices and an optstring string appended the - the variable/group name. + with those indices and an optional option string appended + to the variable/group name enclosed in square braces. The special keyword "all" in the string can be used to indicate that the callback should be called for all variables/groups. @enddesc - @var string + @var traverse_string @vdesc list of variable and/or group names @vtype const char * @vio in @@ -1542,155 +1543,195 @@ void CCTK_FCALL CCTK_FNAME (CCTK_GroupDimFromVarI) @returntype int @returndesc positive for the number of traversed variables, or - -1 if no callback routine was given + -1 no callback routine was given<BR> + -2 option string is not associated with a group or variable<BR> + -3 unterminated option string<BR> + -4 garbage found at end of option string @endreturndesc @@*/ -int CCTK_TraverseString (const char *parsestring, +int CCTK_TraverseString (const char *traverse_string, void (*callback) (int idx, const char *optstring, void *callback_arg), void *callback_arg, int selection) { - int retval; - char *before; - char *after; - char *optstring; - int idx, first, last; - int selected_all; - union - { - char *string; - const char *const_string; - } splitstring; + int retval, nesting, vindex, gindex, first, last, selected_all; + char delimiter, *string, *parse_string, *group_var_string, *option_string; if (callback == NULL) { - CCTK_VWarn (1, __LINE__, __FILE__, "Cactus", - "CCTK_TraverseString: No callback given"); + CCTK_VWarn (5, __LINE__, __FILE__, "Cactus", + "CCTK_TraverseString: No callback given"); return (-1); } retval = 0; - /* avoid the compiler warning "cast discards `const' from pointer - target type" */ - splitstring.const_string = parsestring; - after = NULL; + /* create a work copy of the string to traverse + which we can edit in-place */ + parse_string = strdup (traverse_string); - while (splitstring.string && *splitstring.string) + /* parse it token by token */ + string = parse_string; + while (string && *string) { - if (Util_SplitString (&before, &after, splitstring.string, " ")) + /* skip leading spaces */ + while (*string && isspace (*string)) + { + string++; + } + if (! *string) + { + break; + } + + /* find end of group/varname string (can be either EOS, + space before next token, or following option string) */ + group_var_string = string; + while (*string) { - before = splitstring.string; - if (after) + if (! *string || isspace (*string) || *string == '[') { - free (after); - after = NULL; + break; } + string++; } -#ifdef DEBUG_GROUPS - printf (" String is '%s'\n", splitstring.string); - printf (" Split is '%s' and '%s'\n", before, after); -#endif + /* mark end of group/varname string */ + delimiter = *string; + *string = 0; - if (strlen (before) > 0) + /* parse the option string if there is one */ + option_string = delimiter == '[' ? string + 1: NULL; + if (option_string) { - - optstring = strchr (before, '['); - if (optstring) + /* find end of option string (matching bracket) */ + nesting = 1; + while (*(++string)) { - *optstring = '\0'; + if (*string == '[') + { + nesting++; + } + else if (*string == ']') + { + if (--nesting == 0) + { + break; + } + } } + delimiter = *string; + *string = 0; + if (option_string == group_var_string + 1) + { + CCTK_VWarn (5, __LINE__, __FILE__, "Cactus", + "CCTK_TraverseString: option string '%s' not associated " + "with a group or variable name", option_string); + retval = -2; + break; + } + else if (! (delimiter == ']' && nesting == 0)) + { + CCTK_VWarn (5, __LINE__, __FILE__, "Cactus", + "CCTK_TraverseString: unterminated option string '%s'", + option_string); + retval = -3; + break; + } + else if (! (string[1] == 0 || isspace (string[1]))) + { + CCTK_VWarn (5, __LINE__, __FILE__, "Cactus", + "CCTK_TraverseString: garbage at end of option string '%s'", + option_string); + retval = -4; + break; + } + } - /* Look for the token 'all' */ - selected_all = CCTK_Equals (before, "all"); +#ifdef DEBUG_GROUPS + printf ("group/varname is '%s', option string is '%s'\n", + group_var_string, option_string ? option_string : "(null)"); +#endif - /* See if this name is "<implementation>::<variable>" */ + /* Look for the token 'all' */ + selected_all = CCTK_Equals (group_var_string, "all"); + + /* See if this name is "<implementation>::<variable>" */ + if (! selected_all && + (selection == CCTK_VAR || selection == CCTK_GROUP_OR_VAR)) + { + first = last = CCTK_VarIndex (group_var_string); + } + else + { + first = last = -1; + } + if (first < 0) + { + + /* See if this name is "<implementation>::<group>" */ if (! selected_all && - (selection == CCTK_VAR || selection == CCTK_GROUP_OR_VAR)) + (selection == CCTK_GROUP || selection == CCTK_GROUP_OR_VAR)) { - first = last = CCTK_VarIndex (before); + gindex = CCTK_GroupIndex (group_var_string); } else { - first = last = -1; + gindex = -1; } - if (first < 0) + if (gindex >= 0) { - - /* See if this name is "<implementation>::<group>" */ - if (! selected_all && - (selection == CCTK_GROUP || selection == CCTK_GROUP_OR_VAR)) - { - idx = CCTK_GroupIndex (before); - } - else - { - idx = -1; - } - if (idx >= 0) + /* We have a group so now need all the variables in the group */ + first = CCTK_FirstVarIndexI (gindex); + last = first + CCTK_NumVarsInGroupI (gindex) - 1; + } + else if (selected_all) + { + first = 0; + if (selection == CCTK_GROUP) { - /* We have a group so now need all the variables in the group */ - first = CCTK_FirstVarIndexI (idx); - last = first + CCTK_NumVarsInGroupI (idx) - 1; - } - else if (selected_all) - { - first = 0; - if (selection == CCTK_GROUP) - { - last = CCTK_NumGroups () - 1; - } - else - { - last = CCTK_NumVars () - 1; - } + last = CCTK_NumGroups () - 1; } else { - first = last = -1; - } - } - - if (optstring) - { - *optstring = '['; - } - if (first >= 0) - { - for (idx = first; idx <= last; idx++) - { - (*callback) (idx, optstring, callback_arg); + last = CCTK_NumVars () - 1; } - retval += last - first + 1; } else { - CCTK_VWarn (1, __LINE__, __FILE__, "Cactus", - "CCTK_TraverseString: " - "Ignoring '%s' in string (invalid token)", before); + first = last = -1; } } - if (before != splitstring.string) + /* invoke the callback */ + if (first >= 0) + { + for (vindex = first; vindex <= last; vindex++) + { + (*callback) (vindex, option_string, callback_arg); + } + retval += last - first + 1; + } + else { - free (before); + CCTK_VWarn (1, __LINE__, __FILE__, "Cactus", + "CCTK_TraverseString: Ignoring '%s' in string " + "(invalid token)", group_var_string); } - if (splitstring.string != parsestring) + + /* advance the parse string pointer */ + if (delimiter) { - free (splitstring.string); + string++; } - splitstring.string = after; - } + } /* end of while loop over all tokens in parse string */ - if (after) - { - free (after); - } + /* clean up */ + free (parse_string); return (retval); } @@ -1845,14 +1886,14 @@ int CCTKi_CreateGroup (const char *gname, { if (gfdim > 0) { - if (group->dim != gfdim) - { - retval = 1; - } + if (group->dim != gfdim) + { + retval = 1; + } } else { - gfdim = group->dim; + gfdim = group->dim; } } |