1 /* 2 * $OpenBSD: inout.c,v 1.17 2012/11/07 11:06:14 otto Exp $ 3 * $DragonFly: src/usr.bin/dc/inout.c,v 1.2 2005/04/21 18:50:50 swildner Exp $ 4 */ 5 6 /* 7 * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <openssl/ssl.h> 23 #include <ctype.h> 24 #include <err.h> 25 #include <string.h> 26 27 #include "extern.h" 28 29 #define MAX_CHARS_PER_LINE 68 30 31 static int lastchar; 32 static int charcount; 33 34 static int src_getcharstream(struct source *); 35 static void src_ungetcharstream(struct source *); 36 static char *src_getlinestream(struct source *); 37 static void src_freestream(struct source *); 38 static int src_getcharstring(struct source *); 39 static void src_ungetcharstring(struct source *); 40 static char *src_getlinestring(struct source *); 41 static void src_freestring(struct source *); 42 static void flushwrap(FILE *); 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 void 83 src_ungetcharstream(struct source *src) 84 { 85 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 void 116 src_ungetcharstring(struct source *src) 117 { 118 if (src->u.string.pos > 0) { 119 if (src->lastchar != '\0') 120 --src->u.string.pos; 121 } 122 } 123 124 static char * 125 src_getlinestring(struct source *src) 126 { 127 char buf[BUFSIZ]; 128 int ch, i; 129 130 i = 0; 131 while (i < BUFSIZ-1) { 132 ch = src_getcharstring(src); 133 if (ch == EOF) 134 break; 135 buf[i++] = ch; 136 if (ch == '\n') 137 break; 138 } 139 buf[i] = '\0'; 140 return bstrdup(buf); 141 } 142 143 static void 144 src_freestring(struct source *src) 145 { 146 free(src->u.string.buf); 147 } 148 149 static void 150 flushwrap(FILE *f) 151 { 152 if (lastchar != -1) 153 putc(lastchar, f); 154 } 155 156 static void 157 putcharwrap(FILE *f, int ch) 158 { 159 if (charcount >= MAX_CHARS_PER_LINE) { 160 charcount = 0; 161 fputs("\\\n", f); 162 } 163 if (lastchar != -1) { 164 charcount++; 165 putc(lastchar, f); 166 } 167 lastchar = ch; 168 } 169 170 static void 171 printwrap(FILE *f, const char *p) 172 { 173 char buf[12]; 174 char *q = buf; 175 176 strlcpy(buf, p, sizeof(buf)); 177 while (*q) 178 putcharwrap(f, *q++); 179 } 180 181 struct number * 182 readnumber(struct source *src, u_int base) 183 { 184 struct number *n; 185 int ch; 186 bool sign = false; 187 bool dot = false; 188 BN_ULONG v; 189 190 n = new_number(); 191 bn_check(BN_zero(n->number)); 192 193 while ((ch = (*src->vtable->readchar)(src)) != EOF) { 194 195 if ('0' <= ch && ch <= '9') 196 v = ch - '0'; 197 else if ('A' <= ch && ch <= 'F') 198 v = ch - 'A' + 10; 199 else if (ch == '_') { 200 sign = true; 201 continue; 202 } else if (ch == '.') { 203 if (dot) 204 break; 205 dot = true; 206 continue; 207 } else { 208 (*src->vtable->unreadchar)(src); 209 break; 210 } 211 if (dot) 212 n->scale++; 213 214 bn_check(BN_mul_word(n->number, base)); 215 216 #if 0 217 /* work around a bug in BN_add_word: 0 += 0 is buggy.... */ 218 if (v > 0) 219 #endif 220 bn_check(BN_add_word(n->number, v)); 221 } 222 if (sign) 223 negate(n); 224 return n; 225 } 226 227 char * 228 read_string(struct source *src) 229 { 230 int count, i, sz, new_sz, ch; 231 char *p; 232 bool escape; 233 234 escape = false; 235 count = 1; 236 i = 0; 237 sz = 15; 238 p = bmalloc(sz + 1); 239 240 while ((ch = (*src->vtable->readchar)(src)) != EOF) { 241 if (!escape) { 242 if (ch == '[') 243 count++; 244 else if (ch == ']') 245 count--; 246 if (count == 0) 247 break; 248 } 249 if (ch == '\\' && !escape) 250 escape = true; 251 else { 252 escape = false; 253 if (i == sz) { 254 new_sz = sz * 2; 255 p = brealloc(p, new_sz + 1); 256 sz = new_sz; 257 } 258 p[i++] = ch; 259 } 260 } 261 p[i] = '\0'; 262 return p; 263 } 264 265 static char * 266 get_digit(u_long num, int digits, u_int base) 267 { 268 char *p; 269 270 if (base <= 16) { 271 p = bmalloc(2); 272 p[0] = num >= 10 ? num + 'A' - 10 : num + '0'; 273 p[1] = '\0'; 274 } else { 275 if (asprintf(&p, "%0*lu", digits, num) == -1) 276 err(1, NULL); 277 } 278 return p; 279 } 280 281 void 282 printnumber(FILE *f, const struct number *b, u_int base) 283 { 284 struct number *int_part, *fract_part; 285 int digits; 286 char buf[11]; 287 size_t sz; 288 int i; 289 struct stack stack; 290 char *p; 291 292 charcount = 0; 293 lastchar = -1; 294 if (BN_is_zero(b->number)) 295 putcharwrap(f, '0'); 296 297 int_part = new_number(); 298 fract_part = new_number(); 299 fract_part->scale = b->scale; 300 301 if (base <= 16) 302 digits = 1; 303 else { 304 digits = snprintf(buf, sizeof(buf), "%u", base-1); 305 } 306 split_number(b, int_part->number, fract_part->number); 307 308 i = 0; 309 stack_init(&stack); 310 while (!BN_is_zero(int_part->number)) { 311 BN_ULONG rem = BN_div_word(int_part->number, base); 312 stack_pushstring(&stack, get_digit(rem, digits, base)); 313 i++; 314 } 315 sz = i; 316 if (BN_is_negative(b->number)) 317 putcharwrap(f, '-'); 318 for (i = 0; i < sz; i++) { 319 p = stack_popstring(&stack); 320 if (base > 16) 321 putcharwrap(f, ' '); 322 printwrap(f, p); 323 free(p); 324 } 325 stack_clear(&stack); 326 if (b->scale > 0) { 327 struct number *num_base; 328 BIGNUM mult, stop; 329 330 putcharwrap(f, '.'); 331 num_base = new_number(); 332 bn_check(BN_set_word(num_base->number, base)); 333 BN_init(&mult); 334 bn_check(BN_one(&mult)); 335 BN_init(&stop); 336 bn_check(BN_one(&stop)); 337 scale_number(&stop, b->scale); 338 339 i = 0; 340 while (BN_cmp(&mult, &stop) < 0) { 341 u_long rem; 342 343 if (i && base > 16) 344 putcharwrap(f, ' '); 345 i = 1; 346 347 bmul_number(fract_part, fract_part, num_base, 348 bmachine_scale()); 349 split_number(fract_part, int_part->number, NULL); 350 rem = BN_get_word(int_part->number); 351 p = get_digit(rem, digits, base); 352 int_part->scale = 0; 353 normalize(int_part, fract_part->scale); 354 bn_check(BN_sub(fract_part->number, fract_part->number, 355 int_part->number)); 356 printwrap(f, p); 357 free(p); 358 bn_check(BN_mul_word(&mult, base)); 359 } 360 free_number(num_base); 361 BN_free(&mult); 362 BN_free(&stop); 363 } 364 flushwrap(f); 365 free_number(int_part); 366 free_number(fract_part); 367 } 368 369 void 370 print_value(FILE *f, const struct value *value, const char *prefix, u_int base) 371 { 372 fputs(prefix, f); 373 switch (value->type) { 374 case BCODE_NONE: 375 if (value->array != NULL) 376 fputs("<array>", f); 377 break; 378 case BCODE_NUMBER: 379 printnumber(f, value->u.num, base); 380 break; 381 case BCODE_STRING: 382 fputs(value->u.string, f); 383 break; 384 } 385 } 386 387 void 388 print_ascii(FILE *f, const struct number *n) 389 { 390 BIGNUM *v; 391 int numbits, i, ch; 392 393 v = BN_dup(n->number); 394 bn_checkp(v); 395 396 if (BN_is_negative(v)) 397 BN_set_negative(v, 0); 398 399 numbits = BN_num_bytes(v) * 8; 400 while (numbits > 0) { 401 ch = 0; 402 for (i = 0; i < 8; i++) 403 ch |= BN_is_bit_set(v, numbits-i-1) << (7 - i); 404 putc(ch, f); 405 numbits -= 8; 406 } 407 BN_free(v); 408 } 409