summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2003-11-14 20:25:17 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2003-11-14 20:25:17 +0000
commit5ce5828d55ac1a09b8ee46079947c58bb40bbce8 (patch)
tree7e1d056c8e1e9afc005118e11179021d4ddd241d
parenta8ad5ce164dcca73145a3c6fecf18f7e63d0cc5e (diff)
Implement new boolean operations 'N' (not), 'G' (equals), '(' (less)
and '{' (less or equal). These operations push their result back to the stack. Used by soon to appear boolean operations in bc(1). man page tweaks and ok jmc@
-rw-r--r--usr.bin/dc/bcode.c163
-rw-r--r--usr.bin/dc/dc.134
2 files changed, 154 insertions, 43 deletions
diff --git a/usr.bin/dc/bcode.c b/usr.bin/dc/bcode.c
index 73846edf291..2021a408d3d 100644
--- a/usr.bin/dc/bcode.c
+++ b/usr.bin/dc/bcode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bcode.c,v 1.15 2003/11/09 20:33:09 otto Exp $ */
+/* $OpenBSD: bcode.c,v 1.16 2003/11/14 20:25:16 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -17,7 +17,7 @@
*/
#ifndef lint
-static const char rcsid[] = "$OpenBSD: bcode.c,v 1.15 2003/11/09 20:33:09 otto Exp $";
+static const char rcsid[] = "$OpenBSD: bcode.c,v 1.16 2003/11/14 20:25:16 otto Exp $";
#endif /* not lint */
#include <ssl/ssl.h>
@@ -95,6 +95,10 @@ static void bdivmod(void);
static void bexp(void);
static bool bsqrt_stop(const BIGNUM *, const BIGNUM *);
static void bsqrt(void);
+static void not(void);
+static void equal_numbers(void);
+static void less_numbers(void);
+static void lesseq_numbers(void);
static void equal(void);
static void not_equal(void);
static void less(void);
@@ -102,6 +106,8 @@ static void not_less(void);
static void greater(void);
static void not_greater(void);
static void not_compare(void);
+static bool compare_numbers(enum bcode_compare, struct number *,
+ struct number *);
static void compare(enum bcode_compare);
static void load(void);
static void store(void);
@@ -135,6 +141,7 @@ static const struct jump_entry jump_table_data[] = {
{ '!', not_compare },
{ '#', comment },
{ '%', bmod },
+ { '(', less_numbers },
{ '*', bmul },
{ '+', badd },
{ '-', bsub },
@@ -162,15 +169,14 @@ static const struct jump_entry jump_table_data[] = {
{ 'D', parse_number },
{ 'E', parse_number },
{ 'F', parse_number },
+ { 'G', equal_numbers },
{ 'I', get_ibase },
{ 'J', skipN },
{ 'K', get_scale },
{ 'L', load_stack },
{ 'M', nop },
+ { 'N', not },
{ 'O', get_obase },
- { 'd', dup },
- { 'r', swap },
- { 'p', print_tos },
{ 'P', pop_print },
{ 'Q', quitN },
{ 'S', store_stack },
@@ -193,11 +199,14 @@ static const struct jump_entry jump_table_data[] = {
{ 'n', pop_printn },
{ 'o', set_obase },
{ 'p', print_tos },
+ { 'p', print_tos },
{ 'q', quit },
+ { 'r', swap },
{ 's', store },
{ 'v', bsqrt },
{ 'x', eval_tos },
{ 'z', stackdepth },
+ { '{', lesseq_numbers },
{ '~', bdivmod }
};
@@ -1240,12 +1249,86 @@ bsqrt(void)
}
static void
+not(void)
+{
+ struct number *a;
+
+ a = pop_number();
+ if (a == NULL) {
+ return;
+ }
+ a->scale = 0;
+ bn_check(BN_set_word(a->number, BN_get_word(a->number) ? 0 : 1));
+ push_number(a);
+}
+
+static void
equal(void)
{
compare(BCODE_EQUAL);
}
static void
+equal_numbers(void)
+{
+ struct number *a, *b, *r;
+
+ a = pop_number();
+ if (a == NULL) {
+ return;
+ }
+ b = pop_number();
+ if (b == NULL) {
+ push_number(a);
+ return;
+ }
+ r = new_number();
+ bn_check(BN_set_word(r->number,
+ compare_numbers(BCODE_EQUAL, a, b) ? 1 : 0));
+ push_number(r);
+}
+
+static void
+less_numbers(void)
+{
+ struct number *a, *b, *r;
+
+ a = pop_number();
+ if (a == NULL) {
+ return;
+ }
+ b = pop_number();
+ if (b == NULL) {
+ push_number(a);
+ return;
+ }
+ r = new_number();
+ bn_check(BN_set_word(r->number,
+ compare_numbers(BCODE_LESS, a, b) ? 1 : 0));
+ push_number(r);
+}
+
+static void
+lesseq_numbers(void)
+{
+ struct number *a, *b, *r;
+
+ a = pop_number();
+ if (a == NULL) {
+ return;
+ }
+ b = pop_number();
+ if (b == NULL) {
+ push_number(a);
+ return;
+ }
+ r = new_number();
+ bn_check(BN_set_word(r->number,
+ compare_numbers(BCODE_NOT_GREATER, a, b) ? 1 : 0));
+ push_number(r);
+}
+
+static void
not_equal(void)
{
compare(BCODE_NOT_EQUAL);
@@ -1295,13 +1378,46 @@ not_greater(void)
compare(BCODE_NOT_GREATER);
}
+static bool
+compare_numbers(enum bcode_compare type, struct number *a, struct number *b)
+{
+ u_int scale;
+ int cmp;
+
+ scale = max(a->scale, b->scale);
+
+ if (scale > a->scale)
+ normalize(a, scale);
+ else if (scale > scale)
+ normalize(b, scale);
+
+ cmp = BN_cmp(a->number, b->number);
+
+ free_number(a);
+ free_number(b);
+
+ switch (type) {
+ case BCODE_EQUAL:
+ return cmp == 0;
+ case BCODE_NOT_EQUAL:
+ return cmp != 0;
+ case BCODE_LESS:
+ return cmp < 0;
+ case BCODE_NOT_LESS:
+ return cmp >= 0;
+ case BCODE_GREATER:
+ return cmp > 0;
+ case BCODE_NOT_GREATER:
+ return cmp <= 0;
+ }
+ return false;
+}
+
static void
compare(enum bcode_compare type)
{
int index, elseindex;
struct number *a, *b;
- u_int scale;
- int cmp;
bool ok;
struct value *v;
@@ -1321,38 +1437,7 @@ compare(enum bcode_compare type)
return;
}
- scale = max(a->scale, b->scale);
- if (scale > a->scale)
- normalize(a, scale);
- else if (scale > scale)
- normalize(b, scale);
-
- cmp = BN_cmp(a->number, b->number);
-
- free_number(a);
- free_number(b);
-
- ok = false;
- switch (type) {
- case BCODE_EQUAL:
- ok = cmp == 0;
- break;
- case BCODE_NOT_EQUAL:
- ok = cmp != 0;
- break;
- case BCODE_LESS:
- ok = cmp < 0;
- break;
- case BCODE_NOT_LESS:
- ok = cmp >= 0;
- break;
- case BCODE_GREATER:
- ok = cmp > 0;
- break;
- case BCODE_NOT_GREATER:
- ok = cmp <= 0;
- break;
- }
+ ok = compare_numbers(type, a, b);
if (!ok && elseindex != NO_ELSE)
index = elseindex;
diff --git a/usr.bin/dc/dc.1 b/usr.bin/dc/dc.1
index 3cb6be6475b..58c4696d169 100644
--- a/usr.bin/dc/dc.1
+++ b/usr.bin/dc/dc.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: dc.1,v 1.15 2003/11/06 19:48:55 otto Exp $
+.\" $OpenBSD: dc.1,v 1.16 2003/11/14 20:25:16 otto Exp $
.\"
.\" Copyright (C) Caldera International Inc. 2001-2002.
.\" All rights reserved.
@@ -155,6 +155,12 @@ All values on the stack are popped.
The top value on the stack is duplicated.
.It Ic f
All values on the stack are printed, separated by newlines.
+.It Ic G
+The top two numbers are popped from the stack and compared.
+A one is pushed if the top of the stack is equal to the second number
+on the stack.
+A zero is pushed otherwise.
+This is a non-portable extension.
.It Ic i
The top value on the stack is popped and used as the
base for further input.
@@ -205,6 +211,11 @@ The
operator is a non-portable extensions, used by the
.Xr bc 1
command.
+.It Ic N
+The top of the stack is replaced by one if the top of the stack
+is equal to zero.
+If the top of the stack is unequal to zero, it is replaced by zero.
+This is a non-portable extension.
.It Ic n
The top value on the stack is popped and printed without a newline.
This is a non-portable extension.
@@ -308,6 +319,18 @@ will be executed if the relation is true, and register
.Ar y
will be executed if the relation is false.
This is a non-portable extension.
+.It Ic \&(
+The top two numbers are popped from the stack and compared.
+A one is pushed if the top of the stack is less than the second number
+on the stack.
+A zero is pushed otherwise.
+This is a non-portable extension.
+.It Ic {
+The top two numbers are popped from the stack and compared.
+A one is pushed if the top of stack is less than or equal to the
+second number on the stack.
+A zero is pushed otherwise.
+This is a non-portable extension.
.It Ic \&!
Interprets the rest of the line as a
.Ux
@@ -434,9 +457,12 @@ operator.
.El
.Sh SEE ALSO
.Xr bc 1
-.Pp
-USD:05
-.Em "DC \- An Interactive Desk Calculator"
+.Rs
+.%B USD:05
+.%A L. L. Cherry
+.%A R. Morris
+.%T "DC \- An Interactive Desk Calculator"
+.Re
.Sh STANDARDS
The arithmetic operations of the
.Nm