[PATCH] conf: fix snd_func_imul accumulator initialization

Bojan Janjatović <[email protected]>
Newsgroups org.alsa-project.alsa-devel
Message-ID <CAA-EO1fe_YusfgLNhjyry4ybjnUuSjd6cVgXahnjWYepvvcjQA@mail.gmail.com>
snd_func_iops() initialized result to 0 for both iadd and imul. For
imul this made every multiplication step multiply by 0, so
snd_func_imul() returned 0 for every input since it was added in
aa7a0dd7 (2006-10-11). The doxygen example for imul therefore did not
match observed behavior.

Initialize the accumulator to 1 for imul and keep the empty integers
list result as 0. Add table-driven config tests covering iadd and imul
single, multi, zero, negative, empty, and out-of-order integer lists.

Fixes: https://github.com/alsa-project/alsa-lib/issues/456
Signed-off-by: Bojan Janjatović <[email protected]>
---
This is my first ALSA patch submission, so please let me know if I
should adjust the format or routing.

 src/confmisc.c    |  8 +++++-
 test/lsb/config.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/src/confmisc.c b/src/confmisc.c
index c1f5410c..4acc3cd6 100644
--- a/src/confmisc.c
+++ b/src/confmisc.c
@@ -488,7 +488,7 @@ static int snd_func_iops(snd_config_t **dst,
  snd_config_iterator_t i, next;
  const char *id;
  char *res = NULL;
- long result = 0, val;
+ long result = op == 1 ? 1 : 0, val;
  int idx = 0, err, hit;

  err = snd_config_search(src, "integers", &n);
@@ -531,6 +531,9 @@ static int snd_func_iops(snd_config_t **dst,
  }
  }
  } while (hit);
+ /* Preserve pre-fix behavior for an empty integers list. */
+ if (op == 1 && idx == 0)
+ result = 0;
  err = snd_config_get_id(src, &id);
  if (err >= 0)
  err = snd_config_imake_integer(dst, id, result);
@@ -582,6 +585,9 @@ SND_DLSYM_BUILD_VERSION(snd_func_iadd,
SND_CONFIG_DLSYM_VERSION_EVALUATE);
  integers [ 2 3 2 ]
  }
 \endcode
+ *
+ * \note An empty \c integers list yields 0 (not the multiplicative
+ *       identity 1) for backward compatibility.
  */
 int snd_func_imul(snd_config_t **dst, snd_config_t *root,
    snd_config_t *src, snd_config_t *private_data)
diff --git a/test/lsb/config.c b/test/lsb/config.c
index e8699f13..9906c355 100644
--- a/test/lsb/config.c
+++ b/test/lsb/config.c
@@ -548,6 +548,74 @@ static void test_for_each(void)
  ALSA_CHECK(snd_config_delete(c));
 }

+static void test_evaluate_integer_functions(void)
+{
+ const char *text =
+ "sum {\n"
+ " @func iadd\n"
+ " integers [ 2 3 5 ]\n"
+ "}\n"
+ "product {\n"
+ " @func imul\n"
+ " integers [ 2 4 6 ]\n"
+ "}\n"
+ "single {\n"
+ " @func imul\n"
+ " integers [ 7 ]\n"
+ "}\n"
+ "with_zero {\n"
+ " @func imul\n"
+ " integers [ 2 0 5 ]\n"
+ "}\n"
+ "negative {\n"
+ " @func imul\n"
+ " integers [ -2 3 ]\n"
+ "}\n"
+ "empty {\n"
+ " @func imul\n"
+ " integers [ ]\n"
+ "}\n"
+ "out_of_order {\n"
+ " @func imul\n"
+ " integers {\n"
+ " 2 = 5\n"
+ " 0 = 2\n"
+ " 1 = 3\n"
+ " }\n"
+ "}\n";
+ struct {
+ const char *id;
+ long result;
+ } *p, expected[] = {
+ { .id = "sum", .result = 10 },
+ { .id = "product", .result = 48 },
+ { .id = "single", .result = 7 },
+ { .id = "with_zero", .result = 0 },
+ { .id = "negative", .result = -6 },
+ { .id = "empty", .result = 0 },
+ { .id = "out_of_order", .result = 30 },
+ { .id = NULL, .result = 0 },
+ };
+ snd_config_t *top, *node;
+ snd_input_t *input;
+ long value;
+
+ ALSA_CHECK(snd_input_buffer_open(&input, text, strlen(text)));
+ ALSA_CHECK(snd_config_top(&top));
+ ALSA_CHECK(snd_config_load(top, input));
+ ALSA_CHECK(snd_input_close(input));
+ ALSA_CHECK(snd_config_evaluate(top, top, NULL, NULL));
+
+ for (p = expected; p->id; p++) {
+ ALSA_CHECK(snd_config_search(top, p->id, &node));
+ TEST_CHECK(snd_config_get_type(node) == SND_CONFIG_TYPE_INTEGER);
+ ALSA_CHECK(snd_config_get_integer(node, &value));
+ TEST_CHECK(value == p->result);
+ }
+
+ ALSA_CHECK(snd_config_delete(top));
+}
+
 static int _expand_fcn(snd_config_t **dst, const char *s, void
*private_data ATTRIBUTE_UNUSED)
 {
  if (strcmp(s, "var10") == 0)
@@ -644,6 +712,7 @@ int main(void)
  test_get_ascii();
  test_iterators();
  test_for_each();
+ test_evaluate_integer_functions();
  test_evaluate_string();
  test_load_string();
  return TEST_EXIT_CODE();
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.