summaryrefslogtreecommitdiff
path: root/usr.bin/dc
diff options
context:
space:
mode:
authorOtto Moerbeek <otto@cvs.openbsd.org>2024-11-07 16:20:01 +0000
committerOtto Moerbeek <otto@cvs.openbsd.org>2024-11-07 16:20:01 +0000
commit7fd6f1b5005736cfad227f659fbd781f91dc543b (patch)
tree6d7ced579fa613fdccb77ecafd0d808d19a6d0ef /usr.bin/dc
parent3997efc3b96796a7b3c7119ea89732bad107d8e6 (diff)
Use LibreSSLs specialized functions to print base 10 and base 16.
Also optimize the general case a bit. ok semarie@
Diffstat (limited to 'usr.bin/dc')
-rw-r--r--usr.bin/dc/inout.c92
1 files changed, 56 insertions, 36 deletions
diff --git a/usr.bin/dc/inout.c b/usr.bin/dc/inout.c
index 72d97b30810..389c318169c 100644
--- a/usr.bin/dc/inout.c
+++ b/usr.bin/dc/inout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inout.c,v 1.23 2023/03/08 04:43:10 guenther Exp $ */
+/* $OpenBSD: inout.c,v 1.24 2024/11/07 16:20:00 otto Exp $ */
/*
* Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
@@ -38,7 +38,7 @@ static void src_freestring(struct source *);
static void flushwrap(FILE *);
static void putcharwrap(FILE *, int);
static void printwrap(FILE *, const char *);
-static char *get_digit(u_long, int, u_int);
+static void get_digit(u_long, int, u_int, char *, size_t);
static struct vtable stream_vtable = {
src_getcharstream,
@@ -264,20 +264,17 @@ read_string(struct source *src)
return p;
}
-static char *
-get_digit(u_long num, int digits, u_int base)
+static void
+get_digit(u_long num, int digits, u_int base, char *buf, size_t sz)
{
- char *p;
-
if (base <= 16) {
- p = bmalloc(2);
- p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
- p[1] = '\0';
+ buf[0] = num >= 10 ? num + 'A' - 10 : num + '0';
+ buf[1] = '\0';
} else {
- if (asprintf(&p, "%0*lu", digits, num) == -1)
- err(1, NULL);
+ int ret = snprintf(buf, sz, "%0*lu", digits, num);
+ if (ret < 0 || (size_t)ret >= sz)
+ err(1, "truncation");
}
- return p;
}
void
@@ -285,11 +282,10 @@ printnumber(FILE *f, const struct number *b, u_int base)
{
struct number *int_part, *fract_part;
int digits;
- char buf[11];
- size_t sz;
+ char buf[12], *str, *p;
+ size_t allocated;
int i;
- struct stack stack;
- char *p;
+ BN_ULONG *mem;
charcount = 0;
lastchar = -1;
@@ -307,24 +303,49 @@ printnumber(FILE *f, const struct number *b, u_int base)
}
split_number(b, int_part->number, fract_part->number);
- i = 0;
- stack_init(&stack);
- while (!BN_is_zero(int_part->number)) {
- BN_ULONG rem = BN_div_word(int_part->number, base);
- stack_pushstring(&stack, get_digit(rem, digits, base));
- i++;
- }
- sz = i;
- if (BN_is_negative(b->number))
- putcharwrap(f, '-');
- for (i = 0; i < sz; i++) {
- p = stack_popstring(&stack);
- if (base > 16)
- putcharwrap(f, ' ');
- printwrap(f, p);
- free(p);
+ if (base == 10 && !BN_is_zero(int_part->number)) {
+ str = BN_bn2dec(int_part->number);
+ bn_checkp(str);
+ p = str;
+ while (*p)
+ putcharwrap(f, *p++);
+ free(str);
+ } else if (base == 16 && !BN_is_zero(int_part->number)) {
+ str = BN_bn2hex(int_part->number);
+ bn_checkp(str);
+ p = str;
+ if (*p == '-')
+ putcharwrap(f, *p++);
+ /* skip leading zero's */
+ while (*p == '0')
+ p++;
+ while (*p)
+ putcharwrap(f, *p++);
+ free(str);
+ } else {
+ i = 0;
+ allocated = 1;
+ mem = breallocarray(NULL, allocated, sizeof(BN_ULONG));
+ while (!BN_is_zero(int_part->number)) {
+ if (i >= allocated) {
+ allocated *= 2;
+ mem = breallocarray(mem, allocated,
+ sizeof(BN_ULONG));
+ }
+ mem[i++] = BN_div_word(int_part->number, base);
+ }
+ if (BN_is_negative(b->number))
+ putcharwrap(f, '-');
+ for (i = i - 1; i >= 0; i--) {
+ get_digit(mem[i], digits, base, buf,
+ sizeof(buf));
+ if (base > 16)
+ putcharwrap(f, ' ');
+ printwrap(f, buf);
+ }
+ free(mem);
}
- stack_clear(&stack);
+
if (b->scale > 0) {
struct number *num_base;
BIGNUM *mult, *stop;
@@ -352,13 +373,12 @@ printnumber(FILE *f, const struct number *b, u_int base)
bmachine_scale());
split_number(fract_part, int_part->number, NULL);
rem = BN_get_word(int_part->number);
- p = get_digit(rem, digits, base);
+ get_digit(rem, digits, base, buf, sizeof(buf));
int_part->scale = 0;
normalize(int_part, fract_part->scale);
bn_check(BN_sub(fract_part->number, fract_part->number,
int_part->number));
- printwrap(f, p);
- free(p);
+ printwrap(f, buf);
bn_check(BN_mul_word(mult, base));
}
free_number(num_base);