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