1265533Sdelphij/* $OpenBSD: inout.c,v 1.17 2012/11/07 11:06:14 otto Exp $ */ 2202719Sgabor 3202719Sgabor/* 4202719Sgabor * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 5202719Sgabor * 6202719Sgabor * Permission to use, copy, modify, and distribute this software for any 7202719Sgabor * purpose with or without fee is hereby granted, provided that the above 8202719Sgabor * copyright notice and this permission notice appear in all copies. 9202719Sgabor * 10202719Sgabor * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11202719Sgabor * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12202719Sgabor * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13202719Sgabor * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14202719Sgabor * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15202719Sgabor * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16202719Sgabor * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17202719Sgabor */ 18202719Sgabor 19202719Sgabor#include <sys/cdefs.h> 20202719Sgabor__FBSDID("$FreeBSD: releng/10.3/usr.bin/dc/inout.c 265533 2014-05-07 08:06:54Z delphij $"); 21202719Sgabor 22202719Sgabor#include <openssl/ssl.h> 23202719Sgabor#include <ctype.h> 24202719Sgabor#include <err.h> 25202719Sgabor#include <string.h> 26202719Sgabor 27202719Sgabor#include "extern.h" 28202719Sgabor 29202719Sgabor#define MAX_CHARS_PER_LINE 68 30202719Sgabor 31202719Sgaborstatic int lastchar; 32202719Sgaborstatic int charcount; 33202719Sgabor 34202719Sgaborstatic int src_getcharstream(struct source *); 35202719Sgaborstatic void src_ungetcharstream(struct source *); 36202719Sgaborstatic char *src_getlinestream(struct source *); 37202719Sgaborstatic int src_getcharstring(struct source *); 38202719Sgaborstatic void src_ungetcharstring(struct source *); 39202719Sgaborstatic char *src_getlinestring(struct source *); 40202719Sgaborstatic void src_freestring(struct source *); 41202719Sgaborstatic void flushwrap(FILE *); 42202719Sgaborstatic void putcharwrap(FILE *, int); 43202719Sgaborstatic void printwrap(FILE *, const char *); 44202719Sgaborstatic char *get_digit(u_long, int, u_int); 45202719Sgabor 46202719Sgaborstatic struct vtable stream_vtable = { 47202719Sgabor src_getcharstream, 48202719Sgabor src_ungetcharstream, 49202719Sgabor src_getlinestream, 50202719Sgabor NULL 51202719Sgabor}; 52202719Sgabor 53202719Sgaborstatic struct vtable string_vtable = { 54202719Sgabor src_getcharstring, 55202719Sgabor src_ungetcharstring, 56202719Sgabor src_getlinestring, 57202719Sgabor src_freestring 58202719Sgabor}; 59202719Sgabor 60202719Sgaborvoid 61202719Sgaborsrc_setstream(struct source *src, FILE *stream) 62202719Sgabor{ 63202719Sgabor 64202719Sgabor src->u.stream = stream; 65202719Sgabor src->vtable = &stream_vtable; 66202719Sgabor} 67202719Sgabor 68202719Sgaborvoid 69202719Sgaborsrc_setstring(struct source *src, char *p) 70202719Sgabor{ 71202719Sgabor 72202719Sgabor src->u.string.buf = (u_char *)p; 73202719Sgabor src->u.string.pos = 0; 74202719Sgabor src->vtable = &string_vtable; 75202719Sgabor} 76202719Sgabor 77202719Sgaborstatic int 78202719Sgaborsrc_getcharstream(struct source *src) 79202719Sgabor{ 80202719Sgabor 81202719Sgabor return (src->lastchar = getc(src->u.stream)); 82202719Sgabor} 83202719Sgabor 84202719Sgaborstatic void 85202719Sgaborsrc_ungetcharstream(struct source *src) 86202719Sgabor{ 87202719Sgabor 88202719Sgabor ungetc(src->lastchar, src->u.stream); 89202719Sgabor} 90202719Sgabor 91202719Sgaborstatic char * 92202719Sgaborsrc_getlinestream(struct source *src) 93202719Sgabor{ 94203443Sgabor char buf[BUFSIZ]; 95202719Sgabor 96202719Sgabor if (fgets(buf, BUFSIZ, src->u.stream) == NULL) 97202719Sgabor return (bstrdup("")); 98202719Sgabor return bstrdup(buf); 99202719Sgabor} 100202719Sgabor 101202719Sgaborstatic int 102202719Sgaborsrc_getcharstring(struct source *src) 103202719Sgabor{ 104202719Sgabor 105202719Sgabor src->lastchar = src->u.string.buf[src->u.string.pos]; 106202719Sgabor if (src->lastchar == '\0') 107202719Sgabor return (EOF); 108202719Sgabor else { 109202719Sgabor src->u.string.pos++; 110202719Sgabor return (src->lastchar); 111202719Sgabor } 112202719Sgabor} 113202719Sgabor 114202719Sgaborstatic void 115202719Sgaborsrc_ungetcharstring(struct source *src) 116202719Sgabor{ 117202719Sgabor 118202719Sgabor if (src->u.string.pos > 0) { 119202719Sgabor if (src->lastchar != '\0') 120202719Sgabor --src->u.string.pos; 121202719Sgabor } 122202719Sgabor} 123202719Sgabor 124202719Sgaborstatic char * 125202719Sgaborsrc_getlinestring(struct source *src) 126202719Sgabor{ 127203443Sgabor char buf[BUFSIZ]; 128203443Sgabor int i, ch; 129202719Sgabor 130202719Sgabor i = 0; 131202719Sgabor while (i < BUFSIZ-1) { 132202719Sgabor ch = src_getcharstring(src); 133202719Sgabor if (ch == EOF) 134202719Sgabor break; 135202719Sgabor buf[i++] = ch; 136202719Sgabor if (ch == '\n') 137202719Sgabor break; 138202719Sgabor } 139202719Sgabor buf[i] = '\0'; 140202719Sgabor return (bstrdup(buf)); 141202719Sgabor} 142202719Sgabor 143202719Sgaborstatic void 144202719Sgaborsrc_freestring(struct source *src) 145202719Sgabor{ 146202719Sgabor 147202719Sgabor free(src->u.string.buf); 148202719Sgabor} 149202719Sgabor 150202719Sgaborstatic void 151202719Sgaborflushwrap(FILE *f) 152202719Sgabor{ 153202719Sgabor 154202719Sgabor if (lastchar != -1) 155202719Sgabor putc(lastchar, f); 156202719Sgabor} 157202719Sgabor 158202719Sgaborstatic void 159202719Sgaborputcharwrap(FILE *f, int ch) 160202719Sgabor{ 161202719Sgabor 162202719Sgabor if (charcount >= MAX_CHARS_PER_LINE) { 163202719Sgabor charcount = 0; 164202719Sgabor fputs("\\\n", f); 165202719Sgabor } 166202719Sgabor if (lastchar != -1) { 167202719Sgabor charcount++; 168202719Sgabor putc(lastchar, f); 169202719Sgabor } 170202719Sgabor lastchar = ch; 171202719Sgabor} 172202719Sgabor 173202719Sgaborstatic void 174202719Sgaborprintwrap(FILE *f, const char *p) 175202719Sgabor{ 176203443Sgabor char *q; 177203443Sgabor char buf[12]; 178202719Sgabor 179203443Sgabor q = buf; 180202719Sgabor strlcpy(buf, p, sizeof(buf)); 181202719Sgabor while (*q) 182202719Sgabor putcharwrap(f, *q++); 183202719Sgabor} 184202719Sgabor 185202719Sgaborstruct number * 186202719Sgaborreadnumber(struct source *src, u_int base) 187202719Sgabor{ 188203443Sgabor struct number *n; 189203443Sgabor BN_ULONG v; 190203443Sgabor u_int i; 191203443Sgabor int ch; 192203443Sgabor bool dot = false, sign = false; 193202719Sgabor 194202719Sgabor n = new_number(); 195202719Sgabor bn_check(BN_zero(n->number)); 196202719Sgabor 197202719Sgabor while ((ch = (*src->vtable->readchar)(src)) != EOF) { 198202719Sgabor 199202719Sgabor if ('0' <= ch && ch <= '9') 200202719Sgabor v = ch - '0'; 201202719Sgabor else if ('A' <= ch && ch <= 'F') 202202719Sgabor v = ch - 'A' + 10; 203202719Sgabor else if (ch == '_') { 204202719Sgabor sign = true; 205202719Sgabor continue; 206202719Sgabor } else if (ch == '.') { 207202719Sgabor if (dot) 208202719Sgabor break; 209202719Sgabor dot = true; 210202719Sgabor continue; 211202719Sgabor } else { 212202719Sgabor (*src->vtable->unreadchar)(src); 213202719Sgabor break; 214202719Sgabor } 215202719Sgabor if (dot) 216202719Sgabor n->scale++; 217202719Sgabor 218202719Sgabor bn_check(BN_mul_word(n->number, base)); 219202719Sgabor 220202719Sgabor#if 0 221202719Sgabor /* work around a bug in BN_add_word: 0 += 0 is buggy.... */ 222202719Sgabor if (v > 0) 223202719Sgabor#endif 224202719Sgabor bn_check(BN_add_word(n->number, v)); 225202719Sgabor } 226202719Sgabor if (base != 10) { 227202719Sgabor scale_number(n->number, n->scale); 228202719Sgabor for (i = 0; i < n->scale; i++) 229202719Sgabor BN_div_word(n->number, base); 230202719Sgabor } 231202719Sgabor if (sign) 232202719Sgabor negate(n); 233202719Sgabor return (n); 234202719Sgabor} 235202719Sgabor 236202719Sgaborchar * 237202719Sgaborread_string(struct source *src) 238202719Sgabor{ 239203443Sgabor char *p; 240203443Sgabor int count, ch, i, new_sz, sz; 241203443Sgabor bool escape; 242202719Sgabor 243202719Sgabor escape = false; 244202719Sgabor count = 1; 245202719Sgabor i = 0; 246202719Sgabor sz = 15; 247202719Sgabor p = bmalloc(sz + 1); 248202719Sgabor 249202719Sgabor while ((ch = (*src->vtable->readchar)(src)) != EOF) { 250202719Sgabor if (!escape) { 251202719Sgabor if (ch == '[') 252202719Sgabor count++; 253202719Sgabor else if (ch == ']') 254202719Sgabor count--; 255202719Sgabor if (count == 0) 256202719Sgabor break; 257202719Sgabor } 258202719Sgabor if (ch == '\\' && !escape) 259202719Sgabor escape = true; 260202719Sgabor else { 261202719Sgabor escape = false; 262202719Sgabor if (i == sz) { 263202719Sgabor new_sz = sz * 2; 264202719Sgabor p = brealloc(p, new_sz + 1); 265202719Sgabor sz = new_sz; 266202719Sgabor } 267202719Sgabor p[i++] = ch; 268202719Sgabor } 269202719Sgabor } 270202719Sgabor p[i] = '\0'; 271202719Sgabor return (p); 272202719Sgabor} 273202719Sgabor 274202719Sgaborstatic char * 275202719Sgaborget_digit(u_long num, int digits, u_int base) 276202719Sgabor{ 277203443Sgabor char *p; 278202719Sgabor 279202719Sgabor if (base <= 16) { 280202719Sgabor p = bmalloc(2); 281202719Sgabor p[0] = num >= 10 ? num + 'A' - 10 : num + '0'; 282202719Sgabor p[1] = '\0'; 283202719Sgabor } else { 284202719Sgabor if (asprintf(&p, "%0*lu", digits, num) == -1) 285202719Sgabor err(1, NULL); 286202719Sgabor } 287202719Sgabor return (p); 288202719Sgabor} 289202719Sgabor 290202719Sgaborvoid 291202719Sgaborprintnumber(FILE *f, const struct number *b, u_int base) 292202719Sgabor{ 293203443Sgabor struct number *fract_part, *int_part; 294203443Sgabor struct stack stack; 295203443Sgabor char *p; 296203443Sgabor char buf[11]; 297203443Sgabor size_t sz; 298203443Sgabor unsigned int i; 299203443Sgabor int digits; 300202719Sgabor 301202719Sgabor charcount = 0; 302202719Sgabor lastchar = -1; 303202719Sgabor if (BN_is_zero(b->number)) 304202719Sgabor putcharwrap(f, '0'); 305202719Sgabor 306202719Sgabor int_part = new_number(); 307202719Sgabor fract_part = new_number(); 308202719Sgabor fract_part->scale = b->scale; 309202719Sgabor 310202719Sgabor if (base <= 16) 311202719Sgabor digits = 1; 312202719Sgabor else { 313202719Sgabor digits = snprintf(buf, sizeof(buf), "%u", base-1); 314202719Sgabor } 315202719Sgabor split_number(b, int_part->number, fract_part->number); 316202719Sgabor 317202719Sgabor i = 0; 318202719Sgabor stack_init(&stack); 319202719Sgabor while (!BN_is_zero(int_part->number)) { 320202719Sgabor BN_ULONG rem = BN_div_word(int_part->number, base); 321202719Sgabor stack_pushstring(&stack, get_digit(rem, digits, base)); 322202719Sgabor i++; 323202719Sgabor } 324202719Sgabor sz = i; 325244861Skevlo if (BN_is_negative(b->number)) 326202719Sgabor putcharwrap(f, '-'); 327202719Sgabor for (i = 0; i < sz; i++) { 328202719Sgabor p = stack_popstring(&stack); 329202719Sgabor if (base > 16) 330202719Sgabor putcharwrap(f, ' '); 331202719Sgabor printwrap(f, p); 332202719Sgabor free(p); 333202719Sgabor } 334202719Sgabor stack_clear(&stack); 335202719Sgabor if (b->scale > 0) { 336203443Sgabor struct number *num_base; 337203443Sgabor BIGNUM mult, stop; 338202719Sgabor 339202719Sgabor putcharwrap(f, '.'); 340202719Sgabor num_base = new_number(); 341202719Sgabor bn_check(BN_set_word(num_base->number, base)); 342202719Sgabor BN_init(&mult); 343202719Sgabor bn_check(BN_one(&mult)); 344202719Sgabor BN_init(&stop); 345202719Sgabor bn_check(BN_one(&stop)); 346202719Sgabor scale_number(&stop, b->scale); 347202719Sgabor 348202719Sgabor i = 0; 349202719Sgabor while (BN_cmp(&mult, &stop) < 0) { 350203443Sgabor u_long rem; 351202719Sgabor 352202719Sgabor if (i && base > 16) 353202719Sgabor putcharwrap(f, ' '); 354202719Sgabor i = 1; 355202719Sgabor 356244861Skevlo bmul_number(fract_part, fract_part, num_base, 357244861Skevlo bmachine_scale()); 358202719Sgabor split_number(fract_part, int_part->number, NULL); 359202719Sgabor rem = BN_get_word(int_part->number); 360202719Sgabor p = get_digit(rem, digits, base); 361202719Sgabor int_part->scale = 0; 362202719Sgabor normalize(int_part, fract_part->scale); 363202719Sgabor bn_check(BN_sub(fract_part->number, fract_part->number, 364202719Sgabor int_part->number)); 365202719Sgabor printwrap(f, p); 366202719Sgabor free(p); 367202719Sgabor bn_check(BN_mul_word(&mult, base)); 368202719Sgabor } 369202719Sgabor free_number(num_base); 370202719Sgabor BN_free(&mult); 371202719Sgabor BN_free(&stop); 372202719Sgabor } 373202719Sgabor flushwrap(f); 374202719Sgabor free_number(int_part); 375202719Sgabor free_number(fract_part); 376202719Sgabor} 377202719Sgabor 378202719Sgaborvoid 379202719Sgaborprint_value(FILE *f, const struct value *value, const char *prefix, u_int base) 380202719Sgabor{ 381202719Sgabor 382202719Sgabor fputs(prefix, f); 383202719Sgabor switch (value->type) { 384202719Sgabor case BCODE_NONE: 385202719Sgabor if (value->array != NULL) 386202719Sgabor fputs("<array>", f); 387202719Sgabor break; 388202719Sgabor case BCODE_NUMBER: 389202719Sgabor printnumber(f, value->u.num, base); 390202719Sgabor break; 391202719Sgabor case BCODE_STRING: 392202719Sgabor fputs(value->u.string, f); 393202719Sgabor break; 394202719Sgabor } 395202719Sgabor} 396202719Sgabor 397202719Sgaborvoid 398202719Sgaborprint_ascii(FILE *f, const struct number *n) 399202719Sgabor{ 400203443Sgabor BIGNUM *v; 401203443Sgabor int ch, i, numbits; 402202719Sgabor 403202719Sgabor v = BN_dup(n->number); 404202719Sgabor bn_checkp(v); 405202719Sgabor 406244861Skevlo if (BN_is_negative(v)) 407244861Skevlo BN_set_negative(v, 0); 408202719Sgabor 409202719Sgabor numbits = BN_num_bytes(v) * 8; 410202719Sgabor while (numbits > 0) { 411202719Sgabor ch = 0; 412202719Sgabor for (i = 0; i < 8; i++) 413202719Sgabor ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i); 414202719Sgabor putc(ch, f); 415202719Sgabor numbits -= 8; 416202719Sgabor } 417202719Sgabor BN_free(v); 418202719Sgabor} 419