Annotation of src/usr.bin/dc/inout.c, Revision 1.13
1.13 ! otto 1: /* $OpenBSD: inout.c,v 1.12 2005/03/29 10:53:54 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.13 ! otto 20: static const char rcsid[] = "$OpenBSD: inout.c,v 1.12 2005/03/29 10:53:54 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.11 otto 30: #define MAX_CHARS_PER_LINE 68
1.1 otto 31:
1.12 otto 32: static int lastchar;
33: static int charcount;
1.1 otto 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 *);
1.12 otto 43: static void flushwrap(FILE *);
1.1 otto 44: static void putcharwrap(FILE *, int);
45: static void printwrap(FILE *, const char *);
46: static char *get_digit(u_long, int, u_int);
47:
48: static struct vtable stream_vtable = {
49: src_getcharstream,
50: src_ungetcharstream,
51: src_getlinestream,
52: src_freestream
53: };
54:
55: static struct vtable string_vtable = {
56: src_getcharstring,
57: src_ungetcharstring,
58: src_getlinestring,
59: src_freestring
60: };
61:
62: void
63: src_setstream(struct source *src, FILE *stream)
64: {
65: src->u.stream = stream;
66: src->vtable = &stream_vtable;
67: }
68:
69: void
70: src_setstring(struct source *src, char *p)
71: {
72: src->u.string.buf = (u_char *)p;
73: src->u.string.pos = 0;
74: src->vtable = &string_vtable;
75: }
76:
77: static int
78: src_getcharstream(struct source *src)
79: {
80: return src->lastchar = getc(src->u.stream);
81: }
82:
83: static int
84: src_ungetcharstream(struct source *src)
85: {
86: return ungetc(src->lastchar, src->u.stream);
87: }
88:
89: static void
90: src_freestream(struct source *src)
91: {
92: }
93:
94: static char *
95: src_getlinestream(struct source *src)
96: {
97: char buf[BUFSIZ];
98:
99: if (fgets(buf, BUFSIZ, src->u.stream) == NULL)
100: return bstrdup("");
101: return bstrdup(buf);
102: }
103:
104: static int
105: src_getcharstring(struct source *src)
106: {
107: src->lastchar = src->u.string.buf[src->u.string.pos];
108: if (src->lastchar == '\0')
109: return EOF;
110: else {
111: src->u.string.pos++;
112: return src->lastchar;
113: }
114: }
115:
116: static int
117: src_ungetcharstring(struct source *src)
118: {
1.7 otto 119: int ch;
120:
121: if (src->u.string.pos > 0) {
122: if (src->lastchar != '\0')
123: --src->u.string.pos;
124: ch = src->u.string.buf[src->u.string.pos];
125: return ch == '\0' ? EOF : ch;
126: } else
1.1 otto 127: return EOF;
128: }
129:
130: static char *
131: src_getlinestring(struct source *src)
132: {
133: char buf[BUFSIZ];
134: int ch, i;
135:
136: i = 0;
137: while (i < BUFSIZ-1) {
138: ch = src_getcharstring(src);
139: if (ch == EOF)
140: break;
141: buf[i++] = ch;
142: if (ch == '\n')
143: break;
144: }
145: buf[i] = '\0';
146: return bstrdup(buf);
147: }
148:
149: static void
150: src_freestring(struct source *src)
151: {
152: free(src->u.string.buf);
153: }
154:
155: static void
1.12 otto 156: flushwrap(FILE *f)
157: {
158: if (lastchar != -1)
159: putc(lastchar, f);
160: }
161:
162: static void
1.1 otto 163: putcharwrap(FILE *f, int ch)
164: {
1.12 otto 165: if (charcount >= MAX_CHARS_PER_LINE) {
166: charcount = 0;
1.1 otto 167: fputs("\\\n", f);
168: }
1.12 otto 169: if (lastchar != -1) {
170: charcount++;
171: putc(lastchar, f);
172: }
173: lastchar = ch;
1.1 otto 174: }
175:
176: static void
177: printwrap(FILE *f, const char *p)
178: {
179: char buf[12];
180: char *q = buf;
181:
1.9 otto 182: strlcpy(buf, p, sizeof(buf));
1.1 otto 183: while (*q)
184: putcharwrap(f, *q++);
185: }
186:
187: struct number *
188: readnumber(struct source *src, u_int base)
189: {
190: struct number *n;
191: int ch;
192: bool sign = false;
193: bool dot = false;
194: BN_ULONG v;
1.13 ! otto 195: u_int i;
1.1 otto 196:
197: n = new_number();
198: bn_check(BN_zero(n->number));
199:
200: while ((ch = (*src->vtable->readchar)(src)) != EOF) {
201:
202: if ('0' <= ch && ch <= '9')
203: v = ch - '0';
204: else if ('A' <= ch && ch <= 'F')
205: v = ch - 'A' + 10;
206: else if (ch == '_') {
207: sign = true;
208: continue;
209: } else if (ch == '.') {
210: if (dot)
211: break;
212: dot = true;
213: continue;
214: } else {
215: (*src->vtable->unreadchar)(src);
216: break;
217: }
218: if (dot)
219: n->scale++;
220:
221: bn_check(BN_mul_word(n->number, base));
222:
1.8 otto 223: #if 0
1.1 otto 224: /* work around a bug in BN_add_word: 0 += 0 is buggy.... */
225: if (v > 0)
1.8 otto 226: #endif
1.1 otto 227: bn_check(BN_add_word(n->number, v));
1.13 ! otto 228: }
! 229: if (base != 10) {
! 230: scale_number(n->number, n->scale);
! 231: for (i = 0; i < n->scale; i++)
! 232: BN_div_word(n->number, base);
1.1 otto 233: }
234: if (sign)
235: negate(n);
236: return n;
237: }
238:
239: char *
240: read_string(struct source *src)
241: {
1.4 otto 242: int count, i, sz, new_sz, ch;
1.1 otto 243: char *p;
1.5 otto 244: bool escape;
1.1 otto 245:
1.5 otto 246: escape = false;
1.1 otto 247: count = 1;
248: i = 0;
249: sz = 15;
250: p = bmalloc(sz + 1);
251:
252: while ((ch = (*src->vtable->readchar)(src)) != EOF) {
1.5 otto 253: if (!escape) {
254: if (ch == '[')
255: count++;
256: else if (ch == ']')
257: count--;
258: if (count == 0)
259: break;
260: }
261: if (ch == '\\' && !escape)
262: escape = true;
263: else {
264: escape = false;
265: if (i == sz) {
266: new_sz = sz * 2;
267: p = brealloc(p, new_sz + 1);
268: sz = new_sz;
269: }
270: p[i++] = ch;
1.1 otto 271: }
272: }
273: p[i] = '\0';
274: return p;
275: }
276:
277: static char *
278: get_digit(u_long num, int digits, u_int base)
279: {
280: char *p;
1.3 deraadt 281:
1.1 otto 282: if (base <= 16) {
283: p = bmalloc(2);
1.2 deraadt 284: p[0] = num >= 10 ? num + 'A' - 10 : num + '0';
1.1 otto 285: p[1] = '\0';
286: } else {
287: if (asprintf(&p, "%0*lu", digits, num) == -1)
1.6 otto 288: err(1, NULL);
1.1 otto 289: }
290: return p;
291: }
292:
293: void
294: printnumber(FILE *f, const struct number *b, u_int base)
295: {
296: struct number *int_part, *fract_part;
297: int digits;
298: char buf[11];
299: size_t sz;
300: int i;
301: struct stack stack;
302: char *p;
303:
1.12 otto 304: charcount = 0;
305: lastchar = -1;
1.1 otto 306: if (BN_is_zero(b->number))
307: putcharwrap(f, '0');
308:
309: int_part = new_number();
310: fract_part = new_number();
311: fract_part->scale = b->scale;
312:
313: if (base <= 16)
314: digits = 1;
315: else {
316: digits = snprintf(buf, sizeof(buf), "%u", base-1);
317: }
318: split_number(b, int_part->number, fract_part->number);
319:
320: i = 0;
321: stack_init(&stack);
322: while (!BN_is_zero(int_part->number)) {
323: BN_ULONG rem = BN_div_word(int_part->number, base);
324: stack_pushstring(&stack, get_digit(rem, digits, base));
325: i++;
326: }
327: sz = i;
328: if (BN_cmp(b->number, &zero) < 0)
329: putcharwrap(f, '-');
330: for (i = 0; i < sz; i++) {
331: p = stack_popstring(&stack);
332: if (base > 16)
333: putcharwrap(f, ' ');
334: printwrap(f, p);
335: free(p);
336: }
337: stack_clear(&stack);
338: if (b->scale > 0) {
339: struct number *num_base;
340: BIGNUM mult, stop;
341:
342: putcharwrap(f, '.');
343: num_base = new_number();
344: BN_set_word(num_base->number, base);
345: BN_init(&mult);
346: BN_one(&mult);
347: BN_init(&stop);
348: BN_one(&stop);
349: scale_number(&stop, b->scale);
350:
351: i = 0;
352: while (BN_cmp(&mult, &stop) < 0) {
353: u_long rem;
354:
355: if (i && base > 16)
356: putcharwrap(f, ' ');
357: i = 1;
358:
359: bmul_number(fract_part, fract_part, num_base);
360: split_number(fract_part, int_part->number, NULL);
361: rem = BN_get_word(int_part->number);
362: p = get_digit(rem, digits, base);
363: int_part->scale = 0;
364: normalize(int_part, fract_part->scale);
365: BN_sub(fract_part->number, fract_part->number,
366: int_part->number);
367: printwrap(f, p);
368: free(p);
369: BN_mul_word(&mult, base);
370: }
371: free_number(num_base);
372: BN_free(&mult);
373: BN_free(&stop);
374: }
1.12 otto 375: flushwrap(f);
1.1 otto 376: free_number(int_part);
377: free_number(fract_part);
378: }
379:
380: void
381: print_value(FILE *f, const struct value *value, const char *prefix, u_int base)
382: {
383: fputs(prefix, f);
384: switch (value->type) {
385: case BCODE_NONE:
386: if (value->array != NULL)
387: fputs("<array>", f);
388: break;
389: case BCODE_NUMBER:
390: printnumber(f, value->u.num, base);
391: break;
392: case BCODE_STRING:
393: fputs(value->u.string, f);
394: break;
395: }
396: }
397:
398: void
399: print_ascii(FILE *f, const struct number *n)
400: {
401: BIGNUM *v;
402: int numbits, i, ch;
403:
404: v = BN_dup(n->number);
405: bn_checkp(v);
406:
407: if (BN_cmp(v, &zero) < 0)
408: bn_check(BN_sub(v, &zero, v));
409:
410: numbits = BN_num_bytes(v) * 8;
411: while (numbits > 0) {
412: ch = 0;
413: for (i = 0; i < 8; i++)
414: ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i);
415: putc(ch, f);
416: numbits -= 8;
417: }
418: BN_free(v);
419: }