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