Annotation of src/usr.bin/dc/inout.c, Revision 1.7
1.7 ! otto 1: /* $OpenBSD: inout.c,v 1.6 2003/10/18 20:34:26 otto Exp $ */
1.1 otto 2:
3: /*
4: * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #ifndef lint
1.7 ! otto 20: static const char rcsid[] = "$OpenBSD: inout.c,v 1.6 2003/10/18 20:34:26 otto Exp $";
1.1 otto 21: #endif /* not lint */
22:
23: #include <ssl/ssl.h>
24: #include <ctype.h>
25: #include <err.h>
26: #include <string.h>
27:
28: #include "extern.h"
29:
30: #define MAX_CHARS_PER_LINE 68
31:
32: static int charCount;
33:
34:
35: static int src_getcharstream(struct source *);
36: static int src_ungetcharstream(struct source *);
37: static char *src_getlinestream(struct source *);
38: static void src_freestream(struct source *);
39: static int src_getcharstring(struct source *);
40: static int src_ungetcharstring(struct source *);
41: static char *src_getlinestring(struct source *);
42: static void src_freestring(struct source *);
43: static void putcharwrap(FILE *, int);
44: static void printwrap(FILE *, const char *);
45: static char *get_digit(u_long, int, u_int);
46:
47: static struct vtable stream_vtable = {
48: src_getcharstream,
49: src_ungetcharstream,
50: src_getlinestream,
51: src_freestream
52: };
53:
54: static struct vtable string_vtable = {
55: src_getcharstring,
56: src_ungetcharstring,
57: src_getlinestring,
58: src_freestring
59: };
60:
61: void
62: src_setstream(struct source *src, FILE *stream)
63: {
64: src->u.stream = stream;
65: src->vtable = &stream_vtable;
66: }
67:
68: void
69: src_setstring(struct source *src, char *p)
70: {
71: src->u.string.buf = (u_char *)p;
72: src->u.string.pos = 0;
73: src->vtable = &string_vtable;
74: }
75:
76: static int
77: src_getcharstream(struct source *src)
78: {
79: return src->lastchar = getc(src->u.stream);
80: }
81:
82: static int
83: src_ungetcharstream(struct source *src)
84: {
85: return ungetc(src->lastchar, src->u.stream);
86: }
87:
88: static void
89: src_freestream(struct source *src)
90: {
91: }
92:
93: static char *
94: src_getlinestream(struct source *src)
95: {
96: char buf[BUFSIZ];
97:
98: if (fgets(buf, BUFSIZ, src->u.stream) == NULL)
99: return bstrdup("");
100: return bstrdup(buf);
101: }
102:
103: static int
104: src_getcharstring(struct source *src)
105: {
106: src->lastchar = src->u.string.buf[src->u.string.pos];
107: if (src->lastchar == '\0')
108: return EOF;
109: else {
110: src->u.string.pos++;
111: return src->lastchar;
112: }
113: }
114:
115: static int
116: src_ungetcharstring(struct source *src)
117: {
1.7 ! otto 118: int ch;
! 119:
! 120: if (src->u.string.pos > 0) {
! 121: if (src->lastchar != '\0')
! 122: --src->u.string.pos;
! 123: ch = src->u.string.buf[src->u.string.pos];
! 124: return ch == '\0' ? EOF : ch;
! 125: } else
1.1 otto 126: return EOF;
127: }
128:
129: static char *
130: src_getlinestring(struct source *src)
131: {
132: char buf[BUFSIZ];
133: int ch, i;
134:
135: i = 0;
136: while (i < BUFSIZ-1) {
137: ch = src_getcharstring(src);
138: if (ch == EOF)
139: break;
140: buf[i++] = ch;
141: if (ch == '\n')
142: break;
143: }
144: buf[i] = '\0';
145: return bstrdup(buf);
146: }
147:
148: static void
149: src_freestring(struct source *src)
150: {
151: free(src->u.string.buf);
152: }
153:
154: static void
155: putcharwrap(FILE *f, int ch)
156: {
157: putc(ch, f);
158: if (++charCount > MAX_CHARS_PER_LINE) {
159: charCount = 0;
160: fputs("\\\n", f);
161: }
162: }
163:
164: static void
165: printwrap(FILE *f, const char *p)
166: {
167: char buf[12];
168: char *q = buf;
169:
170: snprintf(buf, sizeof(buf), "%s", p);
171: while (*q)
172: putcharwrap(f, *q++);
173: }
174:
175: struct number *
176: readnumber(struct source *src, u_int base)
177: {
178: struct number *n;
179: int ch;
180: bool sign = false;
181: bool dot = false;
182: BN_ULONG v;
183:
184: n = new_number();
185: bn_check(BN_zero(n->number));
186:
187: while ((ch = (*src->vtable->readchar)(src)) != EOF) {
188:
189: if ('0' <= ch && ch <= '9')
190: v = ch - '0';
191: else if ('A' <= ch && ch <= 'F')
192: v = ch - 'A' + 10;
193: else if (ch == '_') {
194: sign = true;
195: continue;
196: } else if (ch == '.') {
197: if (dot)
198: break;
199: dot = true;
200: continue;
201: } else {
202: (*src->vtable->unreadchar)(src);
203: break;
204: }
205: if (dot)
206: n->scale++;
207:
208: bn_check(BN_mul_word(n->number, base));
209:
210: /* work around a bug in BN_add_word: 0 += 0 is buggy.... */
211: if (v > 0)
212: bn_check(BN_add_word(n->number, v));
213: }
214: if (sign)
215: negate(n);
216: return n;
217: }
218:
219: char *
220: read_string(struct source *src)
221: {
1.4 otto 222: int count, i, sz, new_sz, ch;
1.1 otto 223: char *p;
1.5 otto 224: bool escape;
1.1 otto 225:
1.5 otto 226: escape = false;
1.1 otto 227: count = 1;
228: i = 0;
229: sz = 15;
230: p = bmalloc(sz + 1);
231:
232: while ((ch = (*src->vtable->readchar)(src)) != EOF) {
1.5 otto 233: if (!escape) {
234: if (ch == '[')
235: count++;
236: else if (ch == ']')
237: count--;
238: if (count == 0)
239: break;
240: }
241: if (ch == '\\' && !escape)
242: escape = true;
243: else {
244: escape = false;
245: if (i == sz) {
246: new_sz = sz * 2;
247: p = brealloc(p, new_sz + 1);
248: sz = new_sz;
249: }
250: p[i++] = ch;
1.1 otto 251: }
252: }
253: p[i] = '\0';
254: return p;
255: }
256:
257: static char *
258: get_digit(u_long num, int digits, u_int base)
259: {
260: char *p;
1.3 deraadt 261:
1.1 otto 262: if (base <= 16) {
263: p = bmalloc(2);
1.2 deraadt 264: p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
1.1 otto 265: p[1] = '\0';
266: } else {
267: if (asprintf(&p, "%0*lu", digits, num) == -1)
1.6 otto 268: err(1, NULL);
1.1 otto 269: }
270: return p;
271: }
272:
273: void
274: printnumber(FILE *f, const struct number *b, u_int base)
275: {
276: struct number *int_part, *fract_part;
277: int digits;
278: char buf[11];
279: size_t sz;
280: int i;
281: struct stack stack;
282: char *p;
283:
284: if (BN_is_zero(b->number))
285: putcharwrap(f, '0');
286:
287: int_part = new_number();
288: fract_part = new_number();
289: fract_part->scale = b->scale;
290:
291: if (base <= 16)
292: digits = 1;
293: else {
294: digits = snprintf(buf, sizeof(buf), "%u", base-1);
295: }
296: split_number(b, int_part->number, fract_part->number);
297:
298: i = 0;
299: stack_init(&stack);
300: while (!BN_is_zero(int_part->number)) {
301: BN_ULONG rem = BN_div_word(int_part->number, base);
302: stack_pushstring(&stack, get_digit(rem, digits, base));
303: i++;
304: }
305: sz = i;
306: charCount = 0;
307: if (BN_cmp(b->number, &zero) < 0)
308: putcharwrap(f, '-');
309: for (i = 0; i < sz; i++) {
310: p = stack_popstring(&stack);
311: if (base > 16)
312: putcharwrap(f, ' ');
313: printwrap(f, p);
314: free(p);
315: }
316: stack_clear(&stack);
317: if (b->scale > 0) {
318: struct number *num_base;
319: BIGNUM mult, stop;
320:
321: putcharwrap(f, '.');
322: num_base = new_number();
323: BN_set_word(num_base->number, base);
324: BN_init(&mult);
325: BN_one(&mult);
326: BN_init(&stop);
327: BN_one(&stop);
328: scale_number(&stop, b->scale);
329:
330: i = 0;
331: while (BN_cmp(&mult, &stop) < 0) {
332: u_long rem;
333:
334: if (i && base > 16)
335: putcharwrap(f, ' ');
336: i = 1;
337:
338: bmul_number(fract_part, fract_part, num_base);
339: split_number(fract_part, int_part->number, NULL);
340: rem = BN_get_word(int_part->number);
341: p = get_digit(rem, digits, base);
342: int_part->scale = 0;
343: normalize(int_part, fract_part->scale);
344: BN_sub(fract_part->number, fract_part->number,
345: int_part->number);
346: printwrap(f, p);
347: free(p);
348: BN_mul_word(&mult, base);
349: }
350: free_number(num_base);
351: BN_free(&mult);
352: BN_free(&stop);
353: }
354: free_number(int_part);
355: free_number(fract_part);
356: }
357:
358: void
359: print_value(FILE *f, const struct value *value, const char *prefix, u_int base)
360: {
361: fputs(prefix, f);
362: switch (value->type) {
363: case BCODE_NONE:
364: if (value->array != NULL)
365: fputs("<array>", f);
366: break;
367: case BCODE_NUMBER:
368: printnumber(f, value->u.num, base);
369: break;
370: case BCODE_STRING:
371: fputs(value->u.string, f);
372: break;
373: }
374: }
375:
376: void
377: print_ascii(FILE *f, const struct number *n)
378: {
379: BIGNUM *v;
380: int numbits, i, ch;
381:
382: v = BN_dup(n->number);
383: bn_checkp(v);
384:
385: if (BN_cmp(v, &zero) < 0)
386: bn_check(BN_sub(v, &zero, v));
387:
388: numbits = BN_num_bytes(v) * 8;
389: while (numbits > 0) {
390: ch = 0;
391: for (i = 0; i < 8; i++)
392: ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i);
393: putc(ch, f);
394: numbits -= 8;
395: }
396: BN_free(v);
397: }