From 20e6174e59fab97366f89f9ea8a7280e5299027a Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Mon, 29 Mar 2021 21:11:07 -0400 Subject: [PATCH] cannot use tokenizer for parse_args() as the search for commata must be away of parenthesis --- src/variable.cpp | 36 +++++++++++++++++++++------- src/variable.h | 3 ++- unittest/commands/test_variables.cpp | 7 ++++-- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/variable.cpp b/src/variable.cpp index 76a4b84f89..3bf88db55e 100644 --- a/src/variable.cpp +++ b/src/variable.cpp @@ -4690,23 +4690,43 @@ void Variable::atom_vector(char *word, Tree **tree, max allowed # of args = MAXFUNCARG ------------------------------------------------------------------------- */ -int Variable::parse_args(const std::string &str, char **args) +int Variable::parse_args(char *str, char **args) { + char *ptrnext; int narg = 0; - args[0] = nullptr; + char *ptr = str; - Tokenizer values(str,","); - - while (values.has_next() && narg < MAXFUNCARG) { - args[narg] = utils::strdup(values.next()); + while (ptr && narg < MAXFUNCARG) { + ptrnext = find_next_comma(ptr); + if (ptrnext) *ptrnext = '\0'; + args[narg] = utils::strdup(ptr); narg++; + ptr = ptrnext; + if (ptr) ptr++; } - if (values.has_next()) - error->all(FLERR,"Too many args in variable function"); + if (ptr) error->all(FLERR,"Too many args in variable function"); return narg; } +/* ---------------------------------------------------------------------- + find next comma in str + skip commas inside one or more nested parenthesis + only return ptr to comma at level 0, else nullptr if not found +------------------------------------------------------------------------- */ + +char *Variable::find_next_comma(char *str) +{ + int level = 0; + for (char *p = str; *p; ++p) { + if ('(' == *p) level++; + else if (')' == *p) level--; + else if (',' == *p && !level) return p; + } + return nullptr; +} + + /* ---------------------------------------------------------------------- helper routine for printing variable name with error message ------------------------------------------------------------------------- */ diff --git a/src/variable.h b/src/variable.h index a43e7f3ad7..da759ecf6a 100644 --- a/src/variable.h +++ b/src/variable.h @@ -126,7 +126,8 @@ class Variable : protected Pointers { Tree **, Tree **, int &, double *, int &); int is_atom_vector(char *); void atom_vector(char *, Tree **, Tree **, int &); - int parse_args(const std::string &, char **); + int parse_args(char *, char **); + char *find_next_comma(char *); void print_var_error(const std::string &, int, const std::string &, int, int global=1); void print_tree(Tree *, int); diff --git a/unittest/commands/test_variables.cpp b/unittest/commands/test_variables.cpp index d41ad52e57..eb533aee86 100644 --- a/unittest/commands/test_variables.cpp +++ b/unittest/commands/test_variables.cpp @@ -334,8 +334,9 @@ TEST_F(VariableTest, Functions) file_vars(); BEGIN_HIDE_OUTPUT(); + command("variable seed index 643532"); command("variable one index 1"); - command("variable two equal random(1,2,643532)"); + command("variable two equal random(1,2,v_seed)"); command("variable three equal atan2(v_one,1)"); command("variable four equal atan2()"); command("variable five equal sqrt(v_one+v_one)"); @@ -346,6 +347,7 @@ TEST_F(VariableTest, Functions) command("variable ten equal floor(1.85)+ceil(1.85)"); command("variable ten1 equal tan(v_eight/2.0)"); command("variable ten2 equal asin(-1.0)+acos(0.0)"); + command("variable ten3 equal floor(100*random(0.2,0.8,v_seed)+1)"); END_HIDE_OUTPUT(); ASSERT_GT(variable->compute_equal(variable->find("two")), 0.99); @@ -357,7 +359,8 @@ TEST_F(VariableTest, Functions) ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("nine")), 1); ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("ten")), 3); ASSERT_FLOAT_EQ(variable->compute_equal(variable->find("ten1")), 1); - ASSERT_DOUBLE_EQ(variable->compute_equal(variable->find("ten2")), 0); + ASSERT_GT(variable->compute_equal(variable->find("ten3")), 19); + ASSERT_LT(variable->compute_equal(variable->find("ten3")), 81); TEST_FAILURE(".*ERROR: Variable four: Invalid syntax in variable formula.*", command("print \"${four}\""););