xref: /freebsd/usr.bin/dc/inout.c (revision 1d386b48)
163433bc9SPedro F. Giffuni /*	$OpenBSD: inout.c,v 1.18 2014/12/01 13:13:00 deraadt Exp $	*/
2fdf1f88bSGabor Kovesdan 
3fdf1f88bSGabor Kovesdan /*
4fdf1f88bSGabor Kovesdan  * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5fdf1f88bSGabor Kovesdan  *
6fdf1f88bSGabor Kovesdan  * Permission to use, copy, modify, and distribute this software for any
7fdf1f88bSGabor Kovesdan  * purpose with or without fee is hereby granted, provided that the above
8fdf1f88bSGabor Kovesdan  * copyright notice and this permission notice appear in all copies.
9fdf1f88bSGabor Kovesdan  *
10fdf1f88bSGabor Kovesdan  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11fdf1f88bSGabor Kovesdan  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12fdf1f88bSGabor Kovesdan  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13fdf1f88bSGabor Kovesdan  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14fdf1f88bSGabor Kovesdan  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15fdf1f88bSGabor Kovesdan  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16fdf1f88bSGabor Kovesdan  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17fdf1f88bSGabor Kovesdan  */
18fdf1f88bSGabor Kovesdan 
19fdf1f88bSGabor Kovesdan #include <sys/cdefs.h>
20fdf1f88bSGabor Kovesdan #include <openssl/ssl.h>
21fdf1f88bSGabor Kovesdan #include <ctype.h>
22fdf1f88bSGabor Kovesdan #include <err.h>
23fdf1f88bSGabor Kovesdan #include <string.h>
24fdf1f88bSGabor Kovesdan 
25fdf1f88bSGabor Kovesdan #include "extern.h"
26fdf1f88bSGabor Kovesdan 
27fdf1f88bSGabor Kovesdan #define MAX_CHARS_PER_LINE 68
28fdf1f88bSGabor Kovesdan 
29fdf1f88bSGabor Kovesdan static int	 lastchar;
30fdf1f88bSGabor Kovesdan static int	 charcount;
31fdf1f88bSGabor Kovesdan 
32fdf1f88bSGabor Kovesdan static int	 src_getcharstream(struct source *);
33fdf1f88bSGabor Kovesdan static void	 src_ungetcharstream(struct source *);
34fdf1f88bSGabor Kovesdan static char	*src_getlinestream(struct source *);
35fdf1f88bSGabor Kovesdan static int	 src_getcharstring(struct source *);
36fdf1f88bSGabor Kovesdan static void	 src_ungetcharstring(struct source *);
37fdf1f88bSGabor Kovesdan static char	*src_getlinestring(struct source *);
38fdf1f88bSGabor Kovesdan static void	 src_freestring(struct source *);
39fdf1f88bSGabor Kovesdan static void	 flushwrap(FILE *);
40fdf1f88bSGabor Kovesdan static void	 putcharwrap(FILE *, int);
41fdf1f88bSGabor Kovesdan static void	 printwrap(FILE *, const char *);
42fdf1f88bSGabor Kovesdan static char	*get_digit(u_long, int, u_int);
43fdf1f88bSGabor Kovesdan 
44fdf1f88bSGabor Kovesdan static struct vtable stream_vtable = {
45fdf1f88bSGabor Kovesdan 	src_getcharstream,
46fdf1f88bSGabor Kovesdan 	src_ungetcharstream,
47fdf1f88bSGabor Kovesdan 	src_getlinestream,
48fdf1f88bSGabor Kovesdan 	NULL
49fdf1f88bSGabor Kovesdan };
50fdf1f88bSGabor Kovesdan 
51fdf1f88bSGabor Kovesdan static struct vtable string_vtable = {
52fdf1f88bSGabor Kovesdan 	src_getcharstring,
53fdf1f88bSGabor Kovesdan 	src_ungetcharstring,
54fdf1f88bSGabor Kovesdan 	src_getlinestring,
55fdf1f88bSGabor Kovesdan 	src_freestring
56fdf1f88bSGabor Kovesdan };
57fdf1f88bSGabor Kovesdan 
58fdf1f88bSGabor Kovesdan void
src_setstream(struct source * src,FILE * stream)59fdf1f88bSGabor Kovesdan src_setstream(struct source *src, FILE *stream)
60fdf1f88bSGabor Kovesdan {
61fdf1f88bSGabor Kovesdan 
62fdf1f88bSGabor Kovesdan 	src->u.stream = stream;
63fdf1f88bSGabor Kovesdan 	src->vtable = &stream_vtable;
64fdf1f88bSGabor Kovesdan }
65fdf1f88bSGabor Kovesdan 
66fdf1f88bSGabor Kovesdan void
src_setstring(struct source * src,char * p)67fdf1f88bSGabor Kovesdan src_setstring(struct source *src, char *p)
68fdf1f88bSGabor Kovesdan {
69fdf1f88bSGabor Kovesdan 
70fdf1f88bSGabor Kovesdan 	src->u.string.buf = (u_char *)p;
71fdf1f88bSGabor Kovesdan 	src->u.string.pos = 0;
72fdf1f88bSGabor Kovesdan 	src->vtable = &string_vtable;
73fdf1f88bSGabor Kovesdan }
74fdf1f88bSGabor Kovesdan 
75fdf1f88bSGabor Kovesdan static int
src_getcharstream(struct source * src)76fdf1f88bSGabor Kovesdan src_getcharstream(struct source *src)
77fdf1f88bSGabor Kovesdan {
78fdf1f88bSGabor Kovesdan 
79fdf1f88bSGabor Kovesdan 	return (src->lastchar = getc(src->u.stream));
80fdf1f88bSGabor Kovesdan }
81fdf1f88bSGabor Kovesdan 
82fdf1f88bSGabor Kovesdan static void
src_ungetcharstream(struct source * src)83fdf1f88bSGabor Kovesdan src_ungetcharstream(struct source *src)
84fdf1f88bSGabor Kovesdan {
85fdf1f88bSGabor Kovesdan 
86fdf1f88bSGabor Kovesdan 	ungetc(src->lastchar, src->u.stream);
87fdf1f88bSGabor Kovesdan }
88fdf1f88bSGabor Kovesdan 
89fdf1f88bSGabor Kovesdan static char *
src_getlinestream(struct source * src)90fdf1f88bSGabor Kovesdan src_getlinestream(struct source *src)
91fdf1f88bSGabor Kovesdan {
92fdf1f88bSGabor Kovesdan 	char buf[BUFSIZ];
93fdf1f88bSGabor Kovesdan 
94fdf1f88bSGabor Kovesdan 	if (fgets(buf, BUFSIZ, src->u.stream) == NULL)
95fdf1f88bSGabor Kovesdan 		return (bstrdup(""));
96fdf1f88bSGabor Kovesdan 	return bstrdup(buf);
97fdf1f88bSGabor Kovesdan }
98fdf1f88bSGabor Kovesdan 
99fdf1f88bSGabor Kovesdan static int
src_getcharstring(struct source * src)100fdf1f88bSGabor Kovesdan src_getcharstring(struct source *src)
101fdf1f88bSGabor Kovesdan {
102fdf1f88bSGabor Kovesdan 
103fdf1f88bSGabor Kovesdan 	src->lastchar = src->u.string.buf[src->u.string.pos];
104fdf1f88bSGabor Kovesdan 	if (src->lastchar == '\0')
105fdf1f88bSGabor Kovesdan 		return (EOF);
106fdf1f88bSGabor Kovesdan 	else {
107fdf1f88bSGabor Kovesdan 		src->u.string.pos++;
108fdf1f88bSGabor Kovesdan 		return (src->lastchar);
109fdf1f88bSGabor Kovesdan 	}
110fdf1f88bSGabor Kovesdan }
111fdf1f88bSGabor Kovesdan 
112fdf1f88bSGabor Kovesdan static void
src_ungetcharstring(struct source * src)113fdf1f88bSGabor Kovesdan src_ungetcharstring(struct source *src)
114fdf1f88bSGabor Kovesdan {
115fdf1f88bSGabor Kovesdan 
116fdf1f88bSGabor Kovesdan 	if (src->u.string.pos > 0) {
117fdf1f88bSGabor Kovesdan 		if (src->lastchar != '\0')
118fdf1f88bSGabor Kovesdan 			--src->u.string.pos;
119fdf1f88bSGabor Kovesdan 	}
120fdf1f88bSGabor Kovesdan }
121fdf1f88bSGabor Kovesdan 
122fdf1f88bSGabor Kovesdan static char *
src_getlinestring(struct source * src)123fdf1f88bSGabor Kovesdan src_getlinestring(struct source *src)
124fdf1f88bSGabor Kovesdan {
125fdf1f88bSGabor Kovesdan 	char buf[BUFSIZ];
1267121df63SGabor Kovesdan 	int i, ch;
127fdf1f88bSGabor Kovesdan 
128fdf1f88bSGabor Kovesdan 	i = 0;
129fdf1f88bSGabor Kovesdan 	while (i < BUFSIZ-1) {
130fdf1f88bSGabor Kovesdan 		ch = src_getcharstring(src);
131fdf1f88bSGabor Kovesdan 		if (ch == EOF)
132fdf1f88bSGabor Kovesdan 			break;
133fdf1f88bSGabor Kovesdan 		buf[i++] = ch;
134fdf1f88bSGabor Kovesdan 		if (ch == '\n')
135fdf1f88bSGabor Kovesdan 			break;
136fdf1f88bSGabor Kovesdan 	}
137fdf1f88bSGabor Kovesdan 	buf[i] = '\0';
138fdf1f88bSGabor Kovesdan 	return (bstrdup(buf));
139fdf1f88bSGabor Kovesdan }
140fdf1f88bSGabor Kovesdan 
141fdf1f88bSGabor Kovesdan static void
src_freestring(struct source * src)142fdf1f88bSGabor Kovesdan src_freestring(struct source *src)
143fdf1f88bSGabor Kovesdan {
144fdf1f88bSGabor Kovesdan 
145fdf1f88bSGabor Kovesdan 	free(src->u.string.buf);
146fdf1f88bSGabor Kovesdan }
147fdf1f88bSGabor Kovesdan 
148fdf1f88bSGabor Kovesdan static void
flushwrap(FILE * f)149fdf1f88bSGabor Kovesdan flushwrap(FILE *f)
150fdf1f88bSGabor Kovesdan {
151fdf1f88bSGabor Kovesdan 
152fdf1f88bSGabor Kovesdan 	if (lastchar != -1)
153fdf1f88bSGabor Kovesdan 		putc(lastchar, f);
154fdf1f88bSGabor Kovesdan }
155fdf1f88bSGabor Kovesdan 
156fdf1f88bSGabor Kovesdan static void
putcharwrap(FILE * f,int ch)157fdf1f88bSGabor Kovesdan putcharwrap(FILE *f, int ch)
158fdf1f88bSGabor Kovesdan {
159fdf1f88bSGabor Kovesdan 
160fdf1f88bSGabor Kovesdan 	if (charcount >= MAX_CHARS_PER_LINE) {
161fdf1f88bSGabor Kovesdan 		charcount = 0;
162fdf1f88bSGabor Kovesdan 		fputs("\\\n", f);
163fdf1f88bSGabor Kovesdan 	}
164fdf1f88bSGabor Kovesdan 	if (lastchar != -1) {
165fdf1f88bSGabor Kovesdan 		charcount++;
166fdf1f88bSGabor Kovesdan 		putc(lastchar, f);
167fdf1f88bSGabor Kovesdan 	}
168fdf1f88bSGabor Kovesdan 	lastchar = ch;
169fdf1f88bSGabor Kovesdan }
170fdf1f88bSGabor Kovesdan 
171fdf1f88bSGabor Kovesdan static void
printwrap(FILE * f,const char * p)172fdf1f88bSGabor Kovesdan printwrap(FILE *f, const char *p)
173fdf1f88bSGabor Kovesdan {
1747121df63SGabor Kovesdan 	char *q;
175fdf1f88bSGabor Kovesdan 	char buf[12];
176fdf1f88bSGabor Kovesdan 
1777121df63SGabor Kovesdan 	q = buf;
178fdf1f88bSGabor Kovesdan 	strlcpy(buf, p, sizeof(buf));
179fdf1f88bSGabor Kovesdan 	while (*q)
180fdf1f88bSGabor Kovesdan 		putcharwrap(f, *q++);
181fdf1f88bSGabor Kovesdan }
182fdf1f88bSGabor Kovesdan 
183fdf1f88bSGabor Kovesdan struct number *
readnumber(struct source * src,u_int base,u_int bscale)18495639a80SAlan Somers readnumber(struct source *src, u_int base, u_int bscale)
185fdf1f88bSGabor Kovesdan {
186fdf1f88bSGabor Kovesdan 	struct number *n;
187fdf1f88bSGabor Kovesdan 	BN_ULONG v;
1887121df63SGabor Kovesdan 	int ch;
18995639a80SAlan Somers 	u_int iscale = 0;
1907121df63SGabor Kovesdan 	bool dot = false, sign = false;
191fdf1f88bSGabor Kovesdan 
192fdf1f88bSGabor Kovesdan 	n = new_number();
193c45e66dcSEnji Cooper 	BN_zero(n->number);
194fdf1f88bSGabor Kovesdan 
195fdf1f88bSGabor Kovesdan 	while ((ch = (*src->vtable->readchar)(src)) != EOF) {
196fdf1f88bSGabor Kovesdan 
197fdf1f88bSGabor Kovesdan 		if ('0' <= ch && ch <= '9')
198fdf1f88bSGabor Kovesdan 			v = ch - '0';
199fdf1f88bSGabor Kovesdan 		else if ('A' <= ch && ch <= 'F')
200fdf1f88bSGabor Kovesdan 			v = ch - 'A' + 10;
201fdf1f88bSGabor Kovesdan 		else if (ch == '_') {
202fdf1f88bSGabor Kovesdan 			sign = true;
203fdf1f88bSGabor Kovesdan 			continue;
204fdf1f88bSGabor Kovesdan 		} else if (ch == '.') {
205fdf1f88bSGabor Kovesdan 			if (dot)
206fdf1f88bSGabor Kovesdan 				break;
207fdf1f88bSGabor Kovesdan 			dot = true;
208fdf1f88bSGabor Kovesdan 			continue;
209fdf1f88bSGabor Kovesdan 		} else {
210fdf1f88bSGabor Kovesdan 			(*src->vtable->unreadchar)(src);
211fdf1f88bSGabor Kovesdan 			break;
212fdf1f88bSGabor Kovesdan 		}
213fdf1f88bSGabor Kovesdan 		if (dot)
21495639a80SAlan Somers 			iscale++;
215fdf1f88bSGabor Kovesdan 
216fdf1f88bSGabor Kovesdan 		bn_check(BN_mul_word(n->number, base));
217fdf1f88bSGabor Kovesdan 		bn_check(BN_add_word(n->number, v));
218fdf1f88bSGabor Kovesdan 	}
21995639a80SAlan Somers 	if (base == 10) {
22095639a80SAlan Somers 		n->scale = iscale;
22195639a80SAlan Somers 	} else {
22295639a80SAlan Somers 		/* At this point, the desired result is n->number / base^iscale*/
22395639a80SAlan Somers 		struct number *quotient, *divisor, *_n;
22495639a80SAlan Somers 		BIGNUM *base_n, *exponent;
22595639a80SAlan Somers 		BN_CTX *ctx;
22695639a80SAlan Somers 
22795639a80SAlan Somers 		ctx = BN_CTX_new();
22895639a80SAlan Somers 		base_n = BN_new();
22995639a80SAlan Somers 		exponent = BN_new();
23095639a80SAlan Somers 		divisor = new_number();
231c45e66dcSEnji Cooper 		BN_zero(base_n);
232c45e66dcSEnji Cooper 		BN_zero(exponent);
23395639a80SAlan Somers 
23495639a80SAlan Somers 		bn_check(BN_add_word(base_n, base));
23595639a80SAlan Somers 		bn_check(BN_add_word(exponent, iscale));
23695639a80SAlan Somers 		bn_check(BN_exp(divisor->number, base_n, exponent, ctx));
23795639a80SAlan Somers 		divisor->scale = 0;
23895639a80SAlan Somers 		quotient = div_number(n, divisor, bscale);
23995639a80SAlan Somers 		_n = n;
24095639a80SAlan Somers 		n = quotient;
24195639a80SAlan Somers 
24295639a80SAlan Somers 		/*
24395639a80SAlan Somers 		 * Trim off trailing zeros to yield the smallest scale without
24495639a80SAlan Somers 		 * loss of accuracy
24595639a80SAlan Somers 		 */
24695639a80SAlan Somers 		while ( n->scale > 0 &&
24795639a80SAlan Somers 			BN_mod_word(n->number, 10) == 0) {
24895639a80SAlan Somers 			normalize(n, n->scale - 1);
24995639a80SAlan Somers 		}
25095639a80SAlan Somers 
25195639a80SAlan Somers 		free_number(_n);
25295639a80SAlan Somers 		free_number(divisor);
25395639a80SAlan Somers 		BN_CTX_free(ctx);
25495639a80SAlan Somers 		BN_free(base_n);
25595639a80SAlan Somers 		BN_free(exponent);
256fdf1f88bSGabor Kovesdan 	}
257fdf1f88bSGabor Kovesdan 	if (sign)
258fdf1f88bSGabor Kovesdan 		negate(n);
259fdf1f88bSGabor Kovesdan 	return (n);
260fdf1f88bSGabor Kovesdan }
261fdf1f88bSGabor Kovesdan 
262fdf1f88bSGabor Kovesdan char *
read_string(struct source * src)263fdf1f88bSGabor Kovesdan read_string(struct source *src)
264fdf1f88bSGabor Kovesdan {
265fdf1f88bSGabor Kovesdan 	char *p;
2667121df63SGabor Kovesdan 	int count, ch, i, new_sz, sz;
267fdf1f88bSGabor Kovesdan 	bool escape;
268fdf1f88bSGabor Kovesdan 
269fdf1f88bSGabor Kovesdan 	escape = false;
270fdf1f88bSGabor Kovesdan 	count = 1;
271fdf1f88bSGabor Kovesdan 	i = 0;
272fdf1f88bSGabor Kovesdan 	sz = 15;
273fdf1f88bSGabor Kovesdan 	p = bmalloc(sz + 1);
274fdf1f88bSGabor Kovesdan 
275fdf1f88bSGabor Kovesdan 	while ((ch = (*src->vtable->readchar)(src)) != EOF) {
276fdf1f88bSGabor Kovesdan 		if (!escape) {
277fdf1f88bSGabor Kovesdan 			if (ch == '[')
278fdf1f88bSGabor Kovesdan 				count++;
279fdf1f88bSGabor Kovesdan 			else if (ch == ']')
280fdf1f88bSGabor Kovesdan 				count--;
281fdf1f88bSGabor Kovesdan 			if (count == 0)
282fdf1f88bSGabor Kovesdan 				break;
283fdf1f88bSGabor Kovesdan 		}
284fdf1f88bSGabor Kovesdan 		if (ch == '\\' && !escape)
285fdf1f88bSGabor Kovesdan 			escape = true;
286fdf1f88bSGabor Kovesdan 		else {
287fdf1f88bSGabor Kovesdan 			escape = false;
288fdf1f88bSGabor Kovesdan 			if (i == sz) {
289fdf1f88bSGabor Kovesdan 				new_sz = sz * 2;
29063433bc9SPedro F. Giffuni 				p = breallocarray(p, 1, new_sz + 1);
291fdf1f88bSGabor Kovesdan 				sz = new_sz;
292fdf1f88bSGabor Kovesdan 			}
293fdf1f88bSGabor Kovesdan 			p[i++] = ch;
294fdf1f88bSGabor Kovesdan 		}
295fdf1f88bSGabor Kovesdan 	}
296fdf1f88bSGabor Kovesdan 	p[i] = '\0';
297fdf1f88bSGabor Kovesdan 	return (p);
298fdf1f88bSGabor Kovesdan }
299fdf1f88bSGabor Kovesdan 
300fdf1f88bSGabor Kovesdan static char *
get_digit(u_long num,int digits,u_int base)301fdf1f88bSGabor Kovesdan get_digit(u_long num, int digits, u_int base)
302fdf1f88bSGabor Kovesdan {
303fdf1f88bSGabor Kovesdan 	char *p;
304fdf1f88bSGabor Kovesdan 
305fdf1f88bSGabor Kovesdan 	if (base <= 16) {
306fdf1f88bSGabor Kovesdan 		p = bmalloc(2);
307fdf1f88bSGabor Kovesdan 		p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
308fdf1f88bSGabor Kovesdan 		p[1] = '\0';
309fdf1f88bSGabor Kovesdan 	} else {
310fdf1f88bSGabor Kovesdan 		if (asprintf(&p, "%0*lu", digits, num) == -1)
311fdf1f88bSGabor Kovesdan 			err(1, NULL);
312fdf1f88bSGabor Kovesdan 	}
313fdf1f88bSGabor Kovesdan 	return (p);
314fdf1f88bSGabor Kovesdan }
315fdf1f88bSGabor Kovesdan 
316fdf1f88bSGabor Kovesdan void
printnumber(FILE * f,const struct number * b,u_int base)317fdf1f88bSGabor Kovesdan printnumber(FILE *f, const struct number *b, u_int base)
318fdf1f88bSGabor Kovesdan {
3197121df63SGabor Kovesdan 	struct number *fract_part, *int_part;
3207121df63SGabor Kovesdan 	struct stack stack;
3217121df63SGabor Kovesdan 	char *p;
322fdf1f88bSGabor Kovesdan 	char buf[11];
323fdf1f88bSGabor Kovesdan 	size_t sz;
324fdf1f88bSGabor Kovesdan 	unsigned int i;
3257121df63SGabor Kovesdan 	int digits;
326fdf1f88bSGabor Kovesdan 
327fdf1f88bSGabor Kovesdan 	charcount = 0;
328fdf1f88bSGabor Kovesdan 	lastchar = -1;
329fdf1f88bSGabor Kovesdan 	if (BN_is_zero(b->number))
330fdf1f88bSGabor Kovesdan 		putcharwrap(f, '0');
331fdf1f88bSGabor Kovesdan 
332fdf1f88bSGabor Kovesdan 	int_part = new_number();
333fdf1f88bSGabor Kovesdan 	fract_part = new_number();
334fdf1f88bSGabor Kovesdan 	fract_part->scale = b->scale;
335fdf1f88bSGabor Kovesdan 
336fdf1f88bSGabor Kovesdan 	if (base <= 16)
337fdf1f88bSGabor Kovesdan 		digits = 1;
338fdf1f88bSGabor Kovesdan 	else {
339fdf1f88bSGabor Kovesdan 		digits = snprintf(buf, sizeof(buf), "%u", base-1);
340fdf1f88bSGabor Kovesdan 	}
341fdf1f88bSGabor Kovesdan 	split_number(b, int_part->number, fract_part->number);
342fdf1f88bSGabor Kovesdan 
343fdf1f88bSGabor Kovesdan 	i = 0;
344fdf1f88bSGabor Kovesdan 	stack_init(&stack);
345fdf1f88bSGabor Kovesdan 	while (!BN_is_zero(int_part->number)) {
346fdf1f88bSGabor Kovesdan 		BN_ULONG rem = BN_div_word(int_part->number, base);
347fdf1f88bSGabor Kovesdan 		stack_pushstring(&stack, get_digit(rem, digits, base));
348fdf1f88bSGabor Kovesdan 		i++;
349fdf1f88bSGabor Kovesdan 	}
350fdf1f88bSGabor Kovesdan 	sz = i;
351c3761c38SKevin Lo 	if (BN_is_negative(b->number))
352fdf1f88bSGabor Kovesdan 		putcharwrap(f, '-');
353fdf1f88bSGabor Kovesdan 	for (i = 0; i < sz; i++) {
354fdf1f88bSGabor Kovesdan 		p = stack_popstring(&stack);
355fdf1f88bSGabor Kovesdan 		if (base > 16)
356fdf1f88bSGabor Kovesdan 			putcharwrap(f, ' ');
357fdf1f88bSGabor Kovesdan 		printwrap(f, p);
358fdf1f88bSGabor Kovesdan 		free(p);
359fdf1f88bSGabor Kovesdan 	}
360fdf1f88bSGabor Kovesdan 	stack_clear(&stack);
361fdf1f88bSGabor Kovesdan 	if (b->scale > 0) {
362fdf1f88bSGabor Kovesdan 		struct number *num_base;
363ee4526c0SJung-uk Kim 		BIGNUM *mult, *stop;
364fdf1f88bSGabor Kovesdan 
365fdf1f88bSGabor Kovesdan 		putcharwrap(f, '.');
366fdf1f88bSGabor Kovesdan 		num_base = new_number();
367fdf1f88bSGabor Kovesdan 		bn_check(BN_set_word(num_base->number, base));
368ee4526c0SJung-uk Kim 		mult = BN_new();
369ee4526c0SJung-uk Kim 		bn_checkp(mult);
370ee4526c0SJung-uk Kim 		bn_check(BN_one(mult));
371ee4526c0SJung-uk Kim 		stop = BN_new();
372ee4526c0SJung-uk Kim 		bn_checkp(stop);
373ee4526c0SJung-uk Kim 		bn_check(BN_one(stop));
374ee4526c0SJung-uk Kim 		scale_number(stop, b->scale);
375fdf1f88bSGabor Kovesdan 
376fdf1f88bSGabor Kovesdan 		i = 0;
377ee4526c0SJung-uk Kim 		while (BN_cmp(mult, stop) < 0) {
378fdf1f88bSGabor Kovesdan 			u_long rem;
379fdf1f88bSGabor Kovesdan 
380fdf1f88bSGabor Kovesdan 			if (i && base > 16)
381fdf1f88bSGabor Kovesdan 				putcharwrap(f, ' ');
382fdf1f88bSGabor Kovesdan 			i = 1;
383fdf1f88bSGabor Kovesdan 
384c3761c38SKevin Lo 			bmul_number(fract_part, fract_part, num_base,
385c3761c38SKevin Lo 			    bmachine_scale());
386fdf1f88bSGabor Kovesdan 			split_number(fract_part, int_part->number, NULL);
387fdf1f88bSGabor Kovesdan 			rem = BN_get_word(int_part->number);
388fdf1f88bSGabor Kovesdan 			p = get_digit(rem, digits, base);
389fdf1f88bSGabor Kovesdan 			int_part->scale = 0;
390fdf1f88bSGabor Kovesdan 			normalize(int_part, fract_part->scale);
391fdf1f88bSGabor Kovesdan 			bn_check(BN_sub(fract_part->number, fract_part->number,
392fdf1f88bSGabor Kovesdan 			    int_part->number));
393fdf1f88bSGabor Kovesdan 			printwrap(f, p);
394fdf1f88bSGabor Kovesdan 			free(p);
395ee4526c0SJung-uk Kim 			bn_check(BN_mul_word(mult, base));
396fdf1f88bSGabor Kovesdan 		}
397fdf1f88bSGabor Kovesdan 		free_number(num_base);
398ee4526c0SJung-uk Kim 		BN_free(mult);
399ee4526c0SJung-uk Kim 		BN_free(stop);
400fdf1f88bSGabor Kovesdan 	}
401fdf1f88bSGabor Kovesdan 	flushwrap(f);
402fdf1f88bSGabor Kovesdan 	free_number(int_part);
403fdf1f88bSGabor Kovesdan 	free_number(fract_part);
404fdf1f88bSGabor Kovesdan }
405fdf1f88bSGabor Kovesdan 
406fdf1f88bSGabor Kovesdan void
print_value(FILE * f,const struct value * value,const char * prefix,u_int base)407fdf1f88bSGabor Kovesdan print_value(FILE *f, const struct value *value, const char *prefix, u_int base)
408fdf1f88bSGabor Kovesdan {
409fdf1f88bSGabor Kovesdan 
410fdf1f88bSGabor Kovesdan 	fputs(prefix, f);
411fdf1f88bSGabor Kovesdan 	switch (value->type) {
412fdf1f88bSGabor Kovesdan 	case BCODE_NONE:
413fdf1f88bSGabor Kovesdan 		if (value->array != NULL)
414fdf1f88bSGabor Kovesdan 			fputs("<array>", f);
415fdf1f88bSGabor Kovesdan 		break;
416fdf1f88bSGabor Kovesdan 	case BCODE_NUMBER:
417fdf1f88bSGabor Kovesdan 		printnumber(f, value->u.num, base);
418fdf1f88bSGabor Kovesdan 		break;
419fdf1f88bSGabor Kovesdan 	case BCODE_STRING:
420fdf1f88bSGabor Kovesdan 		fputs(value->u.string, f);
421fdf1f88bSGabor Kovesdan 		break;
422fdf1f88bSGabor Kovesdan 	}
423fdf1f88bSGabor Kovesdan }
424fdf1f88bSGabor Kovesdan 
425fdf1f88bSGabor Kovesdan void
print_ascii(FILE * f,const struct number * n)426fdf1f88bSGabor Kovesdan print_ascii(FILE *f, const struct number *n)
427fdf1f88bSGabor Kovesdan {
428fdf1f88bSGabor Kovesdan 	BIGNUM *v;
4297121df63SGabor Kovesdan 	int ch, i, numbits;
430fdf1f88bSGabor Kovesdan 
431fdf1f88bSGabor Kovesdan 	v = BN_dup(n->number);
432fdf1f88bSGabor Kovesdan 	bn_checkp(v);
433fdf1f88bSGabor Kovesdan 
434c3761c38SKevin Lo 	if (BN_is_negative(v))
435c3761c38SKevin Lo 		BN_set_negative(v, 0);
436fdf1f88bSGabor Kovesdan 
437fdf1f88bSGabor Kovesdan 	numbits = BN_num_bytes(v) * 8;
438fdf1f88bSGabor Kovesdan 	while (numbits > 0) {
439fdf1f88bSGabor Kovesdan 		ch = 0;
440fdf1f88bSGabor Kovesdan 		for (i = 0; i < 8; i++)
441fdf1f88bSGabor Kovesdan 			ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i);
442fdf1f88bSGabor Kovesdan 		putc(ch, f);
443fdf1f88bSGabor Kovesdan 		numbits -= 8;
444fdf1f88bSGabor Kovesdan 	}
445fdf1f88bSGabor Kovesdan 	BN_free(v);
446fdf1f88bSGabor Kovesdan }
447