aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Eßer <se@FreeBSD.org>2021-10-06 21:27:16 +0000
committerStefan Eßer <se@FreeBSD.org>2021-10-06 21:27:16 +0000
commit6f49f5cdde1c62c4e5a743e895f3afe592b5c0e5 (patch)
tree638d9b77f65147c13d7a09f5b28e32076f72bbf3
parent5d58a51571721190681c50d4bd3a1f45e6282d72 (diff)
downloadsrc-6f49f5cdde1c62c4e5a743e895f3afe592b5c0e5.tar.gz
src-6f49f5cdde1c62c4e5a743e895f3afe592b5c0e5.zip
vendor/bc: update to version 5.1.1vendor/bc/5.1.1
This update fixes a parser issue, which in special situations could reject syntactically correct if statements.
-rw-r--r--NEWS.md8
-rw-r--r--include/bc.h9
-rw-r--r--include/version.h2
-rw-r--r--manuals/build.md6
-rw-r--r--src/bc_parse.c47
-rw-r--r--src/vm.c43
-rw-r--r--tests/bc/scripts/all.txt2
-rw-r--r--tests/bc/scripts/ifs.bc49
-rw-r--r--tests/bc/scripts/ifs.txt18
-rw-r--r--tests/bc/scripts/ifs2.bc33
-rw-r--r--tests/bc/scripts/ifs2.txt34
-rw-r--r--tests/bc/stdin2.txt3
-rw-r--r--tests/bc/stdin2_results.txt21
-rwxr-xr-xtests/stdin.sh4
-rw-r--r--vs/bin/some.txt0
-rw-r--r--vs/tests/some.txt0
16 files changed, 230 insertions, 49 deletions
diff --git a/NEWS.md b/NEWS.md
index 98b52024b2e8..5251096d9f2a 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,5 +1,13 @@
# News
+## 5.1.1
+
+This is a production release that completes a bug fix from `5.1.0`. The bug
+exists in all versions of `bc`.
+
+The bug was that `if` statements without `else` statements would not be handled
+correctly at the end of files or right before a function definition.
+
## 5.1.0
This is a production release with some fixes and new features.
diff --git a/include/bc.h b/include/bc.h
index 3d4a11592875..a4198b91ebc6 100644
--- a/include/bc.h
+++ b/include/bc.h
@@ -396,6 +396,15 @@ void bc_parse_expr(BcParse *p, uint8_t flags);
*/
void bc_parse_parse(BcParse *p);
+/**
+ * Ends a series of if statements. This is to ensure that full parses happen
+ * when a file finishes or before defining a function. Without this, bc thinks
+ * that it cannot parse any further. But if we reach the end of a file or a
+ * function definition, we know we can add an empty else clause.
+ * @param p The parser.
+ */
+void bc_parse_endif(BcParse *p);
+
/// References to the signal message and its length.
extern const char bc_sig_msg[];
extern const uchar bc_sig_msg_len;
diff --git a/include/version.h b/include/version.h
index 3be823189b8f..72500c8e3f28 100644
--- a/include/version.h
+++ b/include/version.h
@@ -37,6 +37,6 @@
#define BC_VERSION_H
/// The current version.
-#define VERSION 5.1.0
+#define VERSION 5.1.1
#endif // BC_VERSION_H
diff --git a/manuals/build.md b/manuals/build.md
index 13e969e8e673..1ed2b269f13c 100644
--- a/manuals/build.md
+++ b/manuals/build.md
@@ -65,7 +65,7 @@ with Visual Studio*.
To build `bc`, run the following from the root directory:
```
-msbuild -property:Configuration=<config> bc.sln
+msbuild -property:Configuration=<config> vs/bc.sln
```
where `<config>` is either one of `Debug` or `Release`.
@@ -73,10 +73,10 @@ where `<config>` is either one of `Debug` or `Release`.
To build the library, run the following from the root directory:
```
-msbuild -property:Configuration=<config> bcl.sln
+msbuild -property:Configuration=<config> vs/bcl.sln
```
-where `<config>` is either one of `Debug` or `Release`.
+where `<config>` is either one of `Debug`, `ReleaseMD`, or `ReleaseMT`.
## POSIX-Compatible Systems
diff --git a/src/bc_parse.c b/src/bc_parse.c
index c64121ec5da8..c2fc2186a065 100644
--- a/src/bc_parse.c
+++ b/src/bc_parse.c
@@ -999,6 +999,44 @@ static void bc_parse_startBody(BcParse *p, uint16_t flags) {
bc_vec_push(&p->flags, &flags);
}
+void bc_parse_endif(BcParse *p) {
+
+ size_t i;
+ bool good;
+
+ // Not a problem if this is true.
+ if (BC_NO_ERR(!BC_PARSE_NO_EXEC(p))) return;
+
+ good = true;
+
+ // Find an instance of a body that needs closing, i.e., a statement that did
+ // not have a right brace when it should have.
+ for (i = 0; good && i < p->flags.len; ++i) {
+ uint16_t flag = *((uint16_t*) bc_vec_item(&p->flags, i));
+ good = ((flag & BC_PARSE_FLAG_BRACE) != BC_PARSE_FLAG_BRACE);
+ }
+
+ // If we did not find such an instance...
+ if (good) {
+
+ // We set this to restore it later. We don't want the parser thinking
+ // that we are on stdin for this one because it will want more.
+ bool is_stdin = vm.is_stdin;
+
+ vm.is_stdin = false;
+
+ // End all of the if statements and loops.
+ while (p->flags.len > 1 || BC_PARSE_IF_END(p)) {
+ if (BC_PARSE_IF_END(p)) bc_parse_noElse(p);
+ if (p->flags.len > 1) bc_parse_endBody(p, false);
+ }
+
+ vm.is_stdin = is_stdin;
+ }
+ // If we reach here, a block was not properly closed, and we should error.
+ else bc_parse_err(&vm.prs, BC_ERR_PARSE_BLOCK);
+}
+
/**
* Parses an if statement.
* @param p The parser.
@@ -1730,12 +1768,9 @@ void bc_parse_parse(BcParse *p) {
// Functions need special parsing.
else if (p->l.t == BC_LEX_KW_DEFINE) {
if (BC_ERR(BC_PARSE_NO_EXEC(p))) {
- if (p->flags.len == 1 &&
- BC_PARSE_TOP_FLAG(p) == BC_PARSE_FLAG_IF_END)
- {
- bc_parse_noElse(p);
- }
- else bc_parse_err(p, BC_ERR_PARSE_TOKEN);
+ bc_parse_endif(p);
+ if (BC_ERR(BC_PARSE_NO_EXEC(p)))
+ bc_parse_err(p, BC_ERR_PARSE_TOKEN);
}
bc_parse_func(p);
}
diff --git a/src/vm.c b/src/vm.c
index 8f222f8ccf69..853dff0820dd 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -839,45 +839,14 @@ static void bc_vm_process(const char *text, bool is_stdin) {
#if BC_ENABLED
/**
- * Ends an if statement that ends a file. This is to ensure that full parses
- * happen when a file finishes. Without this, bc thinks that it cannot parse
- * any further. But if we reach the end of a file, we know we can add an empty
- * else clause.
+ * Ends a series of if statements. This is to ensure that full parses happen
+ * when a file finishes or stdin has no more data. Without this, bc thinks that
+ * it cannot parse any further. But if we reach the end of a file or stdin has
+ * no more data, we know we can add an empty else clause.
*/
static void bc_vm_endif(void) {
-
- size_t i;
- bool good;
-
- // Not a problem if this is true.
- if (BC_NO_ERR(!BC_PARSE_NO_EXEC(&vm.prs))) return;
-
- good = true;
-
- // Find an instance of a body that needs closing, i.e., a statement that did
- // not have a right brace when it should have.
- for (i = 0; good && i < vm.prs.flags.len; ++i) {
- uint16_t flag = *((uint16_t*) bc_vec_item(&vm.prs.flags, i));
- good = ((flag & BC_PARSE_FLAG_BRACE) != BC_PARSE_FLAG_BRACE);
- }
-
- // If we did not find such an instance...
- if (good) {
-
- // We set this to restore it later. We don't want the parser thinking
- // that we are on stdin for this one because it will want more.
- bool is_stdin = vm.is_stdin;
-
- vm.is_stdin = false;
-
- // Cheat and keep parsing empty else clauses until all of them are
- // satisfied.
- while (BC_PARSE_IF_END(&vm.prs)) bc_vm_process("else {}", false);
-
- vm.is_stdin = is_stdin;
- }
- // If we reach here, a block was not properly closed, and we should error.
- else bc_parse_err(&vm.prs, BC_ERR_PARSE_BLOCK);
+ bc_parse_endif(&vm.prs);
+ bc_program_exec(&vm.prog);
}
#endif // BC_ENABLED
diff --git a/tests/bc/scripts/all.txt b/tests/bc/scripts/all.txt
index 4ebfe5643c3d..0a8d2fe17c6c 100644
--- a/tests/bc/scripts/all.txt
+++ b/tests/bc/scripts/all.txt
@@ -14,3 +14,5 @@ rand.bc
references.bc
screen.bc
strings2.bc
+ifs.bc
+ifs2.bc
diff --git a/tests/bc/scripts/ifs.bc b/tests/bc/scripts/ifs.bc
new file mode 100644
index 000000000000..9d6ab2dbb0ef
--- /dev/null
+++ b/tests/bc/scripts/ifs.bc
@@ -0,0 +1,49 @@
+#! /usr/bin/bc -q
+
+a = 1
+b = 2
+c = 3
+
+if (a == 1) if (b == 2) if (c == 3) print "Yay!\n"
+
+define void g(x) {
+ print "g: x: ", x, "\n"
+}
+
+if (a == 1) {
+ if (b == 2) {
+ if (c == 3) {
+ g(5)
+ }
+ }
+}
+
+define void h(x) {
+ print "h: x: ", x, "\n"
+}
+
+if (z == 0)
+ for (i = 0; i < 2; ++i)
+ if (a == 1)
+ for (j = 0; j < 2; ++j)
+ if (b == 2)
+ for (k = 0; k < 2; ++k)
+ if (c == 3) h(k)
+
+define void i(x) {
+ print "i: x: ", x, "\n"
+}
+
+if (z == 0) {
+ for (i = 0; i < 2; ++i) {
+ if (a == 1) {
+ for (j = 0; j < 2; ++j) {
+ if (b == 2) {
+ for (k = 0; k < 2; ++k) {
+ if (c == 3) i(k)
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/bc/scripts/ifs.txt b/tests/bc/scripts/ifs.txt
new file mode 100644
index 000000000000..56e07330f1f2
--- /dev/null
+++ b/tests/bc/scripts/ifs.txt
@@ -0,0 +1,18 @@
+Yay!
+g: x: 5
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+i: x: 0
+i: x: 1
+i: x: 0
+i: x: 1
+i: x: 0
+i: x: 1
+i: x: 0
+i: x: 1
diff --git a/tests/bc/scripts/ifs2.bc b/tests/bc/scripts/ifs2.bc
new file mode 100644
index 000000000000..052ef06ee4e3
--- /dev/null
+++ b/tests/bc/scripts/ifs2.bc
@@ -0,0 +1,33 @@
+#! /usr/bin/bc -q
+
+a = 1
+b = 2
+c = 3
+
+if (a == 1) if (b == 2) if (c == 3) print "Yay!\n"
+
+define void g(x) {
+ print "g: x: ", x, "\n"
+}
+
+if (a == 1) {
+ if (b == 2) {
+ if (c == 3) {
+ g(5)
+ }
+ }
+}
+
+define void h(x) {
+ print "h: x: ", x, "\n"
+}
+
+if (z == 0)
+ for (i = 0; i < 2; ++i)
+ for (l = 0; l < 2; ++l)
+ if (a == 1)
+ for (j = 0; j < 2; ++j)
+ for (m = 0; m < 2; ++m)
+ if (b == 2)
+ for (k = 0; k < 2; ++k)
+ if (c == 3) h(k)
diff --git a/tests/bc/scripts/ifs2.txt b/tests/bc/scripts/ifs2.txt
new file mode 100644
index 000000000000..b226e98ad44b
--- /dev/null
+++ b/tests/bc/scripts/ifs2.txt
@@ -0,0 +1,34 @@
+Yay!
+g: x: 5
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
+h: x: 0
+h: x: 1
diff --git a/tests/bc/stdin2.txt b/tests/bc/stdin2.txt
index f260cfa7dbcf..a7f1981c6658 100644
--- a/tests/bc/stdin2.txt
+++ b/tests/bc/stdin2.txt
@@ -1 +1,4 @@
for (i = 0; i < 3; ++i) if (2 < 3) 1
+if (3 < 4) for (i = 0; i < 3; ++i) if (4 < 5) 2
+for (j = 0; j < 3; ++j) if (5 < 6) for (i = 0; i < 3; ++i) if (4 < 5) 3
+if (6 < 7) for (j = 0; j < 3; ++j) if (5 < 6) for (i = 0; i < 3; ++i) if (4 < 5) 4
diff --git a/tests/bc/stdin2_results.txt b/tests/bc/stdin2_results.txt
index e8183f05f5db..43e2b02f53f2 100644
--- a/tests/bc/stdin2_results.txt
+++ b/tests/bc/stdin2_results.txt
@@ -1,3 +1,24 @@
1
1
1
+2
+2
+2
+3
+3
+3
+3
+3
+3
+3
+3
+3
+4
+4
+4
+4
+4
+4
+4
+4
+4
diff --git a/tests/stdin.sh b/tests/stdin.sh
index c9e02253c30a..69e6f2cabf34 100755
--- a/tests/stdin.sh
+++ b/tests/stdin.sh
@@ -92,10 +92,10 @@ checktest "$d" "$?" "stdin" "$testdir/$d/stdin_results.txt" "$out"
if [ "$d" = "bc" ]; then
cat "$testdir/$d/stdin1.txt" | "$exe" "$@" "$options" > "$out" 2> /dev/null
- checktest "$d" "$?" "stdin" "$testdir/$d/stdin1_results.txt" "$out"
+ checktest "$d" "$?" "stdin1" "$testdir/$d/stdin1_results.txt" "$out"
cat "$testdir/$d/stdin2.txt" | "$exe" "$@" "$options" > "$out" 2> /dev/null
- checktest "$d" "$?" "stdin" "$testdir/$d/stdin2_results.txt" "$out"
+ checktest "$d" "$?" "stdin2" "$testdir/$d/stdin2_results.txt" "$out"
fi
rm -f "$out"
diff --git a/vs/bin/some.txt b/vs/bin/some.txt
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/vs/bin/some.txt
+++ /dev/null
diff --git a/vs/tests/some.txt b/vs/tests/some.txt
deleted file mode 100644
index e69de29bb2d1..000000000000
--- a/vs/tests/some.txt
+++ /dev/null