2 * $OpenBSD: inout.c,v 1.12 2005/03/29 10:53:54 otto Exp $
3 * $DragonFly: src/usr.bin/dc/inout.c,v 1.2 2005/04/21 18:50:50 swildner Exp $
7 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <openssl/ssl.h>
29 #define MAX_CHARS_PER_LINE 68
34 static int src_getcharstream(struct source
*);
35 static int src_ungetcharstream(struct source
*);
36 static char *src_getlinestream(struct source
*);
37 static void src_freestream(struct source
*);
38 static int src_getcharstring(struct source
*);
39 static int src_ungetcharstring(struct source
*);
40 static char *src_getlinestring(struct source
*);
41 static void src_freestring(struct source
*);
42 static void flushwrap(FILE *);
43 static void putcharwrap(FILE *, int);
44 static void printwrap(FILE *, const char *);
45 static char *get_digit(u_long
, int, u_int
);
47 static struct vtable stream_vtable
= {
54 static struct vtable string_vtable
= {
62 src_setstream(struct source
*src
, FILE *stream
)
64 src
->u
.stream
= stream
;
65 src
->vtable
= &stream_vtable
;
69 src_setstring(struct source
*src
, char *p
)
71 src
->u
.string
.buf
= (u_char
*)p
;
72 src
->u
.string
.pos
= 0;
73 src
->vtable
= &string_vtable
;
77 src_getcharstream(struct source
*src
)
79 return src
->lastchar
= getc(src
->u
.stream
);
83 src_ungetcharstream(struct source
*src
)
85 return ungetc(src
->lastchar
, src
->u
.stream
);
89 src_freestream(struct source
*src
)
94 src_getlinestream(struct source
*src
)
98 if (fgets(buf
, BUFSIZ
, src
->u
.stream
) == NULL
)
104 src_getcharstring(struct source
*src
)
106 src
->lastchar
= src
->u
.string
.buf
[src
->u
.string
.pos
];
107 if (src
->lastchar
== '\0')
111 return src
->lastchar
;
116 src_ungetcharstring(struct source
*src
)
120 if (src
->u
.string
.pos
> 0) {
121 if (src
->lastchar
!= '\0')
123 ch
= src
->u
.string
.buf
[src
->u
.string
.pos
];
124 return ch
== '\0' ? EOF
: ch
;
130 src_getlinestring(struct source
*src
)
136 while (i
< BUFSIZ
-1) {
137 ch
= src_getcharstring(src
);
149 src_freestring(struct source
*src
)
151 free(src
->u
.string
.buf
);
162 putcharwrap(FILE *f
, int ch
)
164 if (charcount
>= MAX_CHARS_PER_LINE
) {
168 if (lastchar
!= -1) {
176 printwrap(FILE *f
, const char *p
)
181 strlcpy(buf
, p
, sizeof(buf
));
183 putcharwrap(f
, *q
++);
187 readnumber(struct source
*src
, u_int base
)
196 bn_check(BN_zero(n
->number
));
198 while ((ch
= (*src
->vtable
->readchar
)(src
)) != EOF
) {
200 if ('0' <= ch
&& ch
<= '9')
202 else if ('A' <= ch
&& ch
<= 'F')
204 else if (ch
== '_') {
207 } else if (ch
== '.') {
213 (*src
->vtable
->unreadchar
)(src
);
219 bn_check(BN_mul_word(n
->number
, base
));
222 /* work around a bug in BN_add_word: 0 += 0 is buggy.... */
225 bn_check(BN_add_word(n
->number
, v
));
233 read_string(struct source
*src
)
235 int count
, i
, sz
, new_sz
, ch
;
245 while ((ch
= (*src
->vtable
->readchar
)(src
)) != EOF
) {
254 if (ch
== '\\' && !escape
)
260 p
= brealloc(p
, new_sz
+ 1);
271 get_digit(u_long num
, int digits
, u_int base
)
277 p
[0] = num
>= 10 ? num
+ 'A' - 10 : num
+ '0';
280 if (asprintf(&p
, "%0*lu", digits
, num
) == -1)
287 printnumber(FILE *f
, const struct number
*b
, u_int base
)
289 struct number
*int_part
, *fract_part
;
299 if (BN_is_zero(b
->number
))
302 int_part
= new_number();
303 fract_part
= new_number();
304 fract_part
->scale
= b
->scale
;
309 digits
= snprintf(buf
, sizeof(buf
), "%u", base
-1);
311 split_number(b
, int_part
->number
, fract_part
->number
);
315 while (!BN_is_zero(int_part
->number
)) {
316 BN_ULONG rem
= BN_div_word(int_part
->number
, base
);
317 stack_pushstring(&stack
, get_digit(rem
, digits
, base
));
321 if (BN_cmp(b
->number
, &zero
) < 0)
323 for (i
= 0; i
< sz
; i
++) {
324 p
= stack_popstring(&stack
);
332 struct number
*num_base
;
336 num_base
= new_number();
337 BN_set_word(num_base
->number
, base
);
342 scale_number(&stop
, b
->scale
);
345 while (BN_cmp(&mult
, &stop
) < 0) {
352 bmul_number(fract_part
, fract_part
, num_base
);
353 split_number(fract_part
, int_part
->number
, NULL
);
354 rem
= BN_get_word(int_part
->number
);
355 p
= get_digit(rem
, digits
, base
);
357 normalize(int_part
, fract_part
->scale
);
358 BN_sub(fract_part
->number
, fract_part
->number
,
362 BN_mul_word(&mult
, base
);
364 free_number(num_base
);
369 free_number(int_part
);
370 free_number(fract_part
);
374 print_value(FILE *f
, const struct value
*value
, const char *prefix
, u_int base
)
377 switch (value
->type
) {
379 if (value
->array
!= NULL
)
383 printnumber(f
, value
->u
.num
, base
);
386 fputs(value
->u
.string
, f
);
392 print_ascii(FILE *f
, const struct number
*n
)
397 v
= BN_dup(n
->number
);
400 if (BN_cmp(v
, &zero
) < 0)
401 bn_check(BN_sub(v
, &zero
, v
));
403 numbits
= BN_num_bytes(v
) * 8;
404 while (numbits
> 0) {
406 for (i
= 0; i
< 8; i
++)
407 ch
|= BN_is_bit_set(v
, numbits
-i
-1) << (7 - i
);