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