Annotation of src/usr.bin/dc/inout.c, Revision 1.10
1.10 ! otto 1: /* $OpenBSD: inout.c,v 1.9 2005/03/15 10:28:38 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.10 ! otto 20: static const char rcsid[] = "$OpenBSD: inout.c,v 1.9 2005/03/15 10:28:38 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:
1.10 ! otto 30: #define MAX_CHARS_PER_LINE 69
1.1 otto 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);
1.10 ! otto 158: if (++charCount >= MAX_CHARS_PER_LINE) {
1.1 otto 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:
1.9 otto 170: strlcpy(buf, p, sizeof(buf));
1.1 otto 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:
1.8 otto 210: #if 0
1.1 otto 211: /* work around a bug in BN_add_word: 0 += 0 is buggy.... */
212: if (v > 0)
1.8 otto 213: #endif
1.1 otto 214: bn_check(BN_add_word(n->number, v));
215: }
216: if (sign)
217: negate(n);
218: return n;
219: }
220:
221: char *
222: read_string(struct source *src)
223: {
1.4 otto 224: int count, i, sz, new_sz, ch;
1.1 otto 225: char *p;
1.5 otto 226: bool escape;
1.1 otto 227:
1.5 otto 228: escape = false;
1.1 otto 229: count = 1;
230: i = 0;
231: sz = 15;
232: p = bmalloc(sz + 1);
233:
234: while ((ch = (*src->vtable->readchar)(src)) != EOF) {
1.5 otto 235: if (!escape) {
236: if (ch == '[')
237: count++;
238: else if (ch == ']')
239: count--;
240: if (count == 0)
241: break;
242: }
243: if (ch == '\\' && !escape)
244: escape = true;
245: else {
246: escape = false;
247: if (i == sz) {
248: new_sz = sz * 2;
249: p = brealloc(p, new_sz + 1);
250: sz = new_sz;
251: }
252: p[i++] = ch;
1.1 otto 253: }
254: }
255: p[i] = '\0';
256: return p;
257: }
258:
259: static char *
260: get_digit(u_long num, int digits, u_int base)
261: {
262: char *p;
1.3 deraadt 263:
1.1 otto 264: if (base <= 16) {
265: p = bmalloc(2);
1.2 deraadt 266: p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
1.1 otto 267: p[1] = '\0';
268: } else {
269: if (asprintf(&p, "%0*lu", digits, num) == -1)
1.6 otto 270: err(1, NULL);
1.1 otto 271: }
272: return p;
273: }
274:
275: void
276: printnumber(FILE *f, const struct number *b, u_int base)
277: {
278: struct number *int_part, *fract_part;
279: int digits;
280: char buf[11];
281: size_t sz;
282: int i;
283: struct stack stack;
284: char *p;
285:
286: if (BN_is_zero(b->number))
287: putcharwrap(f, '0');
288:
289: int_part = new_number();
290: fract_part = new_number();
291: fract_part->scale = b->scale;
292:
293: if (base <= 16)
294: digits = 1;
295: else {
296: digits = snprintf(buf, sizeof(buf), "%u", base-1);
297: }
298: split_number(b, int_part->number, fract_part->number);
299:
300: i = 0;
301: stack_init(&stack);
302: while (!BN_is_zero(int_part->number)) {
303: BN_ULONG rem = BN_div_word(int_part->number, base);
304: stack_pushstring(&stack, get_digit(rem, digits, base));
305: i++;
306: }
307: sz = i;
308: charCount = 0;
309: if (BN_cmp(b->number, &zero) < 0)
310: putcharwrap(f, '-');
311: for (i = 0; i < sz; i++) {
312: p = stack_popstring(&stack);
313: if (base > 16)
314: putcharwrap(f, ' ');
315: printwrap(f, p);
316: free(p);
317: }
318: stack_clear(&stack);
319: if (b->scale > 0) {
320: struct number *num_base;
321: BIGNUM mult, stop;
322:
323: putcharwrap(f, '.');
324: num_base = new_number();
325: BN_set_word(num_base->number, base);
326: BN_init(&mult);
327: BN_one(&mult);
328: BN_init(&stop);
329: BN_one(&stop);
330: scale_number(&stop, b->scale);
331:
332: i = 0;
333: while (BN_cmp(&mult, &stop) < 0) {
334: u_long rem;
335:
336: if (i && base > 16)
337: putcharwrap(f, ' ');
338: i = 1;
339:
340: bmul_number(fract_part, fract_part, num_base);
341: split_number(fract_part, int_part->number, NULL);
342: rem = BN_get_word(int_part->number);
343: p = get_digit(rem, digits, base);
344: int_part->scale = 0;
345: normalize(int_part, fract_part->scale);
346: BN_sub(fract_part->number, fract_part->number,
347: int_part->number);
348: printwrap(f, p);
349: free(p);
350: BN_mul_word(&mult, base);
351: }
352: free_number(num_base);
353: BN_free(&mult);
354: BN_free(&stop);
355: }
356: free_number(int_part);
357: free_number(fract_part);
358: }
359:
360: void
361: print_value(FILE *f, const struct value *value, const char *prefix, u_int base)
362: {
363: fputs(prefix, f);
364: switch (value->type) {
365: case BCODE_NONE:
366: if (value->array != NULL)
367: fputs("<array>", f);
368: break;
369: case BCODE_NUMBER:
370: printnumber(f, value->u.num, base);
371: break;
372: case BCODE_STRING:
373: fputs(value->u.string, f);
374: break;
375: }
376: }
377:
378: void
379: print_ascii(FILE *f, const struct number *n)
380: {
381: BIGNUM *v;
382: int numbits, i, ch;
383:
384: v = BN_dup(n->number);
385: bn_checkp(v);
386:
387: if (BN_cmp(v, &zero) < 0)
388: bn_check(BN_sub(v, &zero, v));
389:
390: numbits = BN_num_bytes(v) * 8;
391: while (numbits > 0) {
392: ch = 0;
393: for (i = 0; i < 8; i++)
394: ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i);
395: putc(ch, f);
396: numbits -= 8;
397: }
398: BN_free(v);
399: }