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