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