summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS.md9
-rw-r--r--include/lang.h6
-rw-r--r--include/program.h9
-rw-r--r--include/version.h2
-rw-r--r--src/program.c95
-rw-r--r--tests/bc/scripts/all.txt1
-rw-r--r--tests/bc/scripts/array2.bc20
-rw-r--r--tests/bc/scripts/array2.txt2
8 files changed, 75 insertions, 69 deletions
diff --git a/NEWS.md b/NEWS.md
index 7adabb8cd6b8..36952fdaf582 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,14 @@
# News
+## 6.2.2
+
+This is a production release that fixes a bug.
+
+The bug was that if an array element was used as a parameter, and then a later
+parameter had the same name as the array whose element was used, `bc` would grab
+the element from the new array parameter, not the actual element from before the
+function call.
+
## 6.2.1
This is a production release with one bug fix for a memory bug in history.
diff --git a/include/lang.h b/include/lang.h
index 4ad6df88f5ed..2d9776532249 100644
--- a/include/lang.h
+++ b/include/lang.h
@@ -352,6 +352,12 @@ typedef struct BcLoc
/// The index of the var or array.
size_t loc;
+ /// The index of the array or variable in the array stack. This is to
+ /// prevent a bug with getting the wrong array element or variable after a
+ /// function call. See the tests/bc/scripts/array.bc test for the array
+ /// case; the variable case is in various variable tests.
+ size_t stack_idx;
+
/// The index of the array element. Only used for array elements.
size_t idx;
diff --git a/include/program.h b/include/program.h
index 3acd5157b127..3a3ea6c9dab7 100644
--- a/include/program.h
+++ b/include/program.h
@@ -220,20 +220,11 @@ typedef struct BcProgram
#if !BC_ENABLED
-/// This define disappears the parameter last because for dc only, last is
-/// always true.
-#define bc_program_copyToVar(p, name, t, last) \
- bc_program_copyToVar_impl(p, name, t)
-
/// Returns true if the calculator should pop after printing.
#define BC_PROGRAM_POP(pop) (pop)
#else // !BC_ENABLED
-// This is here to quiet a compiler warning.
-#define bc_program_copyToVar(p, name, t, last) \
- bc_program_copyToVar_impl(p, name, t, last)
-
/// Returns true if the calculator should pop after printing.
#define BC_PROGRAM_POP(pop) (BC_IS_BC || (pop))
diff --git a/include/version.h b/include/version.h
index a9abf5be6c67..e1b72de90eef 100644
--- a/include/version.h
+++ b/include/version.h
@@ -37,6 +37,6 @@
#define BC_VERSION_H
/// The current version.
-#define VERSION 6.2.1
+#define VERSION 6.2.2
#endif // BC_VERSION_H
diff --git a/src/program.c b/src/program.c
index 5424b715a29b..7e2ba8178b61 100644
--- a/src/program.c
+++ b/src/program.c
@@ -346,7 +346,7 @@ bc_program_num(BcProgram* p, BcResult* r)
{
size_t idx = r->d.loc.idx;
- v = bc_vec_top(v);
+ v = bc_vec_item(v, r->d.loc.stack_idx);
#if BC_ENABLED
// If this is true, we have a reference vector, so dereference
@@ -376,8 +376,21 @@ bc_program_num(BcProgram* p, BcResult* r)
n = bc_vec_item(v, idx);
}
// This is either a number (for a var) or an array (for an array).
- // Because bc_vec_top() returns a void*, we don't need to cast.
- else n = bc_vec_top(v);
+ // Because bc_vec_top() and bc_vec_item() return a void*, we don't
+ // need to cast.
+ else
+ {
+#if BC_ENABLED
+ if (BC_IS_BC)
+ {
+ n = bc_vec_item(v, r->d.loc.stack_idx);
+ }
+ else
+#endif // BC_ENABLED
+ {
+ n = bc_vec_top(v);
+ }
+ }
break;
}
@@ -1181,18 +1194,12 @@ bc_program_assignStr(BcProgram* p, BcNum* num, BcVec* v, bool push)
/**
* Copies a value to a variable. This is used for storing in dc as well as to
* set function parameters to arguments in bc.
- * @param p The program.
- * @param idx The index of the variable or array to copy to.
- * @param t The type to copy to. This could be a variable or an array.
- * @param last Whether to grab the last item on the variable stack or not (for
- * bc function parameters). This is important because if a new
- * value has been pushed to the variable already, we need to grab
- * the value pushed before. This happens when you have a parameter
- * named something like "x", and a variable "x" is passed to
- * another parameter.
+ * @param p The program.
+ * @param idx The index of the variable or array to copy to.
+ * @param t The type to copy to. This could be a variable or an array.
*/
static void
-bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
+bc_program_copyToVar(BcProgram* p, size_t idx, BcType t)
{
BcResult *ptr = NULL, r;
BcVec* vec;
@@ -1217,13 +1224,6 @@ bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
{
// Type match the result.
bc_program_type_match(ptr, t);
-
- // Get the variable or array, taking care to get the real item. We take
- // care of last with arrays later.
- if (!last && var)
- {
- n = bc_vec_item_rev(bc_program_vec(p, ptr->d.loc.loc, t), 1);
- }
}
#endif // BC_ENABLED
@@ -1265,19 +1265,8 @@ bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
if (BC_IS_BC)
{
- BcVec* parent;
bool ref, ref_size;
- // We need to figure out if the parameter is a reference or not and
- // construct the reference vector, if necessary. So this gets the
- // parent stack for the array.
- parent = bc_program_vec(p, ptr->d.loc.loc, t);
- assert(parent != NULL);
-
- // This takes care of last for arrays. Mostly.
- if (!last) v = bc_vec_item_rev(parent, !last);
- assert(v != NULL);
-
// True if we are using a reference.
ref = (v->size == sizeof(BcNum) && t == BC_TYPE_REF);
@@ -1297,8 +1286,6 @@ bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
// If this is true, then we need to construct a reference.
if (ref)
{
- assert(parent->len >= (size_t) (!last + 1));
-
// Make sure the pointer was not invalidated.
vec = bc_program_vec(p, idx, t);
@@ -1306,7 +1293,7 @@ bc_program_copyToVar(BcProgram* p, size_t idx, BcType t, bool last)
// care of last; it ensures the reference goes to the right
// place.
bc_vec_pushIndex(rv, ptr->d.loc.loc);
- bc_vec_pushIndex(rv, parent->len - !last - 1);
+ bc_vec_pushIndex(rv, ptr->d.loc.stack_idx);
}
// If we get here, we are copying a ref to a ref. Just push a
// copy of all of the bytes.
@@ -1600,18 +1587,22 @@ bc_program_pushVar(BcProgram* p, const char* restrict code,
{
BcResult r;
size_t idx = bc_program_index(code, bgn);
+ BcVec* v;
// Set the result appropriately.
r.t = BC_RESULT_VAR;
r.d.loc.loc = idx;
+ // Get the stack for the variable. This is used in both bc and dc.
+ v = bc_program_vec(p, idx, BC_TYPE_VAR);
+ r.d.loc.stack_idx = v->len - 1;
+
#if DC_ENABLED
// If this condition is true, then we have the hard case, where we have to
// adjust dc registers.
if (BC_IS_DC && (pop || copy))
{
- // Get the stack for the variable and the number at the top.
- BcVec* v = bc_program_vec(p, idx, BC_TYPE_VAR);
+ // Get the number at the top at the top of the stack.
BcNum* num = bc_vec_top(v);
// Ensure there are enough elements on the stack.
@@ -1674,10 +1665,17 @@ bc_program_pushArray(BcProgram* p, const char* restrict code,
BcResult* operand;
BcNum* num;
BcBigDig temp;
+ BcVec* v;
// Get the index of the array.
r.d.loc.loc = bc_program_index(code, bgn);
+ // We need the array to get its length.
+ v = bc_program_vec(p, r.d.loc.loc, BC_TYPE_ARRAY);
+ assert(v != NULL);
+
+ r.d.loc.stack_idx = v->len - 1;
+
// Doing an array is easy; just set the result type and finish.
if (inst == BC_INST_ARRAY)
{
@@ -1800,35 +1798,14 @@ bc_program_call(BcProgram* p, const char* restrict code, size_t* restrict bgn)
// Push the arguments onto the stacks of their respective parameters.
for (i = 0; i < nargs; ++i)
{
- size_t j;
- bool last = true;
-
arg = bc_vec_top(&p->results);
if (BC_ERR(arg->t == BC_RESULT_VOID)) bc_err(BC_ERR_EXEC_VOID_VAL);
// Get the corresponding parameter.
a = bc_vec_item(&f->autos, nargs - 1 - i);
- // If I have already pushed to a var, I need to make sure I
- // get the previous version, not the already pushed one. This condition
- // must be true for that to even be possible.
- if (arg->t == BC_RESULT_VAR || arg->t == BC_RESULT_ARRAY)
- {
- // Loop through all of the previous parameters.
- for (j = 0; j < i && last; ++j)
- {
- BcAuto* aptr = bc_vec_item(&f->autos, nargs - 1 - j);
-
- // This condition is true if there is a previous parameter with
- // the same name *and* type because variables and arrays do not
- // interfere with each other.
- last = (arg->d.loc.loc != aptr->idx ||
- (!aptr->type) != (arg->t == BC_RESULT_VAR));
- }
- }
-
// Actually push the value onto the parameter's stack.
- bc_program_copyToVar(p, a->idx, a->type, last);
+ bc_program_copyToVar(p, a->idx, a->type);
}
BC_SIG_LOCK;
@@ -3650,7 +3627,7 @@ bc_program_exec(BcProgram* p)
// clang-format on
{
idx = bc_program_index(code, &ip->idx);
- bc_program_copyToVar(p, idx, BC_TYPE_VAR, true);
+ bc_program_copyToVar(p, idx, BC_TYPE_VAR);
BC_PROG_JUMP(inst, code, ip);
}
diff --git a/tests/bc/scripts/all.txt b/tests/bc/scripts/all.txt
index b4a178783796..e2d2aa320c6f 100644
--- a/tests/bc/scripts/all.txt
+++ b/tests/bc/scripts/all.txt
@@ -5,6 +5,7 @@ add.bc
print.bc
parse.bc
array.bc
+array2.bc
atan.bc
bessel.bc
functions.bc
diff --git a/tests/bc/scripts/array2.bc b/tests/bc/scripts/array2.bc
new file mode 100644
index 000000000000..34d88c3e276b
--- /dev/null
+++ b/tests/bc/scripts/array2.bc
@@ -0,0 +1,20 @@
+#! /usr/bin/bc -q
+
+define z(x, a[]) {
+ return x + a[1]
+}
+
+define y(x, *b[]) {
+ return x + b[1]
+}
+
+a[0] = 5
+a[1] = 6
+
+b[0] = 8
+b[1] = 7
+
+z(a[0], b[])
+y(b[0], a[])
+
+halt
diff --git a/tests/bc/scripts/array2.txt b/tests/bc/scripts/array2.txt
new file mode 100644
index 000000000000..76dcb035f907
--- /dev/null
+++ b/tests/bc/scripts/array2.txt
@@ -0,0 +1,2 @@
+12
+14