aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
Diffstat (limited to 'libbb')
-rw-r--r--libbb/dump.c102
1 files changed, 68 insertions, 34 deletions
diff --git a/libbb/dump.c b/libbb/dump.c
index d24057325..ffc46f6a7 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -50,8 +50,10 @@ typedef struct priv_dumper_t {
50static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789"; 50static const char dot_flags_width_chars[] ALIGN1 = ".#-+ 0123456789";
51 51
52static const char size_conv_str[] ALIGN1 = 52static const char size_conv_str[] ALIGN1 =
53"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG"; 53"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\x8""cdiouxXeEfgG";
54 54/* c d i o u x X e E f g G - bytes contain 'bcnt' for the type */
55#define SCS_OFS 12
56#define float_convs (size_conv_str + SCS_OFS + sizeof("cdiouxX")-1)
55static const char int_convs[] ALIGN1 = "diouxX"; 57static const char int_convs[] ALIGN1 = "diouxX";
56 58
57dumper_t* FAST_FUNC alloc_dumper(void) 59dumper_t* FAST_FUNC alloc_dumper(void)
@@ -94,7 +96,7 @@ static NOINLINE int bb_dump_size(FS *fs)
94 while (isdigit(*++fmt)) 96 while (isdigit(*++fmt))
95 continue; 97 continue;
96 } 98 }
97 p = strchr(size_conv_str + 12, *fmt); 99 p = strchr(size_conv_str + SCS_OFS, *fmt);
98 if (!p) { 100 if (!p) {
99 if (*fmt == 's') { 101 if (*fmt == 's') {
100 bcnt += prec; 102 bcnt += prec;
@@ -106,7 +108,7 @@ static NOINLINE int bb_dump_size(FS *fs)
106 } 108 }
107 } 109 }
108 } else { 110 } else {
109 bcnt += p[-12]; 111 bcnt += p[-SCS_OFS];
110 } 112 }
111 } 113 }
112 cur_size += bcnt * fu->reps; 114 cur_size += bcnt * fu->reps;
@@ -193,6 +195,10 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
193 195
194 ++p2; 196 ++p2;
195 ++p1; 197 ++p1;
198 if (*p1 == 'l') { /* %lld etc */
199 ++p2;
200 ++p1;
201 }
196 DO_INT_CONV: 202 DO_INT_CONV:
197 e = strchr(int_convs, *p1); /* "diouxX"? */ 203 e = strchr(int_convs, *p1); /* "diouxX"? */
198 if (!e) 204 if (!e)
@@ -200,13 +206,13 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
200 pr->flags = F_INT; 206 pr->flags = F_INT;
201 if (e > int_convs + 1) /* not d or i? */ 207 if (e > int_convs + 1) /* not d or i? */
202 pr->flags = F_UINT; 208 pr->flags = F_UINT;
203 byte_count_str = "\004\002\001"; 209 byte_count_str = "\010\004\002\001";
204 goto DO_BYTE_COUNT; 210 goto DO_BYTE_COUNT;
205 } else 211 } else
206 if (strchr(int_convs, *p1)) { /* %d etc */ 212 if (strchr(int_convs, *p1)) { /* %d etc */
207 goto DO_INT_CONV; 213 goto DO_INT_CONV;
208 } else 214 } else
209 if (strchr("eEfgG", *p1)) { /* floating point */ 215 if (strchr(float_convs, *p1)) { /* floating point */
210 pr->flags = F_DBL; 216 pr->flags = F_DBL;
211 byte_count_str = "\010\004"; 217 byte_count_str = "\010\004";
212 goto DO_BYTE_COUNT; 218 goto DO_BYTE_COUNT;
@@ -244,7 +250,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
244 pr->flags = F_P; 250 pr->flags = F_P;
245 *p1 = 'c'; 251 *p1 = 'c';
246 goto DO_BYTE_COUNT_1; 252 goto DO_BYTE_COUNT_1;
247 case 'u': /* %_p: chars, 'nul', 'esc' etc for nonprintable */ 253 case 'u': /* %_u: chars, 'nul', 'esc' etc for nonprintable */
248 pr->flags = F_U; 254 pr->flags = F_U;
249 /* *p1 = 'c'; set in conv_u */ 255 /* *p1 = 'c'; set in conv_u */
250 goto DO_BYTE_COUNT_1; 256 goto DO_BYTE_COUNT_1;
@@ -324,8 +330,7 @@ static NOINLINE void rewrite(priv_dumper_t *dumper, FS *fs)
324 p2 = NULL; 330 p2 = NULL;
325 for (p1 = pr->fmt; *p1; ++p1) 331 for (p1 = pr->fmt; *p1; ++p1)
326 p2 = isspace(*p1) ? p1 : NULL; 332 p2 = isspace(*p1) ? p1 : NULL;
327 if (p2) 333 pr->nospace = p2;
328 pr->nospace = p2;
329 } 334 }
330 } 335 }
331} 336}
@@ -509,7 +514,7 @@ static void bpad(PR *pr)
509 514
510static const char conv_str[] ALIGN1 = 515static const char conv_str[] ALIGN1 =
511 "\0" "\\""0""\0" 516 "\0" "\\""0""\0"
512 "\007""\\""a""\0" /* \a */ 517 "\007""\\""a""\0"
513 "\b" "\\""b""\0" 518 "\b" "\\""b""\0"
514 "\f" "\\""f""\0" 519 "\f" "\\""f""\0"
515 "\n" "\\""n""\0" 520 "\n" "\\""n""\0"
@@ -549,10 +554,12 @@ static void conv_u(PR *pr, unsigned char *p)
549 static const char list[] ALIGN1 = 554 static const char list[] ALIGN1 =
550 "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0" 555 "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0"
551 "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_" 556 "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_"
552 "dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0" 557 "dle\0dc1\0dc2\0dc3\0dc4\0nak\0syn\0etb\0"
553 "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us"; 558 "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us";
559 /* NB: bug: od uses %_u to implement -a,
560 * but it should use "nl", not "lf", for char #10.
561 */
554 562
555 /* od used nl, not lf */
556 if (*p <= 0x1f) { 563 if (*p <= 0x1f) {
557 *pr->cchar = 's'; 564 *pr->cchar = 's';
558 printf(pr->fmt, list + (4 * (int)*p)); 565 printf(pr->fmt, list + (4 * (int)*p));
@@ -571,7 +578,6 @@ static void conv_u(PR *pr, unsigned char *p)
571static NOINLINE void display(priv_dumper_t* dumper) 578static NOINLINE void display(priv_dumper_t* dumper)
572{ 579{
573 unsigned char *bp; 580 unsigned char *bp;
574 unsigned char savech = '\0';
575 581
576 while ((bp = get(dumper)) != NULL) { 582 while ((bp = get(dumper)) != NULL) {
577 FS *fs; 583 FS *fs;
@@ -592,24 +598,41 @@ static NOINLINE void display(priv_dumper_t* dumper)
592 PR *pr; 598 PR *pr;
593 for (pr = fu->nextpr; pr; dumper->pub.address += pr->bcnt, 599 for (pr = fu->nextpr; pr; dumper->pub.address += pr->bcnt,
594 bp += pr->bcnt, pr = pr->nextpr) { 600 bp += pr->bcnt, pr = pr->nextpr) {
601 unsigned char savech;
602
595 if (dumper->eaddress 603 if (dumper->eaddress
596 && dumper->pub.address >= dumper->eaddress 604 && dumper->pub.address >= dumper->eaddress
597 ) { 605 ) {
606#if ENABLE_XXD
598 if (dumper->pub.xxd_eofstring) { 607 if (dumper->pub.xxd_eofstring) {
599 /* xxd support: requested to not pad incomplete blocks */ 608 /* xxd support: requested to not pad incomplete blocks */
600 fputs_stdout(dumper->pub.xxd_eofstring); 609 fputs_stdout(dumper->pub.xxd_eofstring);
601 return; 610 return;
602 } 611 }
612#endif
613#if ENABLE_OD
614 if (dumper->pub.od_eofstring) {
615 /* od support: requested to not pad incomplete blocks */
616 /* ... but do print final offset */
617 fputs_stdout(dumper->pub.od_eofstring);
618 goto endfu;
619 }
620#endif
603 if (!(pr->flags & (F_TEXT | F_BPAD))) 621 if (!(pr->flags & (F_TEXT | F_BPAD)))
604 bpad(pr); 622 bpad(pr);
605 } 623 }
624 savech = '\0';
606 if (cnt == 1 && pr->nospace) { 625 if (cnt == 1 && pr->nospace) {
607 savech = *pr->nospace; 626 savech = *pr->nospace;
608 *pr->nospace = '\0'; 627 *pr->nospace = '\0';
609 } 628 }
610 switch (pr->flags) { 629 switch (pr->flags) {
611 case F_ADDRESS: 630 case F_ADDRESS:
612 printf(pr->fmt, (unsigned long long) dumper->pub.address + dumper->pub.xxd_displayoff); 631 printf(pr->fmt, (unsigned long long) dumper->pub.address
632#if ENABLE_XXD
633 + dumper->pub.xxd_displayoff
634#endif
635 );
613 break; 636 break;
614 case F_BPAD: 637 case F_BPAD:
615 printf(pr->fmt, ""); 638 printf(pr->fmt, "");
@@ -637,22 +660,32 @@ static NOINLINE void display(priv_dumper_t* dumper)
637 break; 660 break;
638 } 661 }
639 case F_INT: { 662 case F_INT: {
640 int ival; 663 union {
641 short sval; 664 int16_t ival16;
665 int32_t ival32;
666 int64_t ival64;
667 } u;
668 int value = (signed char)*bp;
642 669
643 switch (pr->bcnt) { 670 switch (pr->bcnt) {
644 case 1: 671 case 1:
645 printf(pr->fmt, (int) *bp);
646 break; 672 break;
647 case 2: 673 case 2:
648 memcpy(&sval, bp, sizeof(sval)); 674 move_from_unaligned16(u.ival16, bp);
649 printf(pr->fmt, (int) sval); 675 value = u.ival16;
650 break; 676 break;
651 case 4: 677 case 4:
652 memcpy(&ival, bp, sizeof(ival)); 678 move_from_unaligned32(u.ival32, bp);
653 printf(pr->fmt, ival); 679 value = u.ival32;
654 break; 680 break;
681 case 8:
682 move_from_unaligned64(u.ival64, bp);
683//A hack. Users _must_ use %llX formats to not truncate high bits
684 printf(pr->fmt, (long long)u.ival64);
685 goto skip;
655 } 686 }
687 printf(pr->fmt, value);
688 skip:
656 break; 689 break;
657 } 690 }
658 case F_P: 691 case F_P:
@@ -662,32 +695,29 @@ static NOINLINE void display(priv_dumper_t* dumper)
662 printf(pr->fmt, (char *) bp); 695 printf(pr->fmt, (char *) bp);
663 break; 696 break;
664 case F_TEXT: 697 case F_TEXT:
665 printf(pr->fmt); 698 fputs_stdout(pr->fmt);
666 break; 699 break;
667 case F_U: 700 case F_U:
668 conv_u(pr, bp); 701 conv_u(pr, bp);
669 break; 702 break;
670 case F_UINT: { 703 case F_UINT: {
671 unsigned ival; 704 unsigned value = (unsigned char)*bp;
672 unsigned short sval;
673
674 switch (pr->bcnt) { 705 switch (pr->bcnt) {
675 case 1: 706 case 1:
676 printf(pr->fmt, (unsigned) *bp);
677 break; 707 break;
678 case 2: 708 case 2:
679 memcpy(&sval, bp, sizeof(sval)); 709 move_from_unaligned16(value, bp);
680 printf(pr->fmt, (unsigned) sval);
681 break; 710 break;
682 case 4: 711 case 4:
683 memcpy(&ival, bp, sizeof(ival)); 712 move_from_unaligned32(value, bp);
684 printf(pr->fmt, ival);
685 break; 713 break;
714 /* case 8: no users yet */
686 } 715 }
716 printf(pr->fmt, value);
687 break; 717 break;
688 } 718 }
689 } 719 }
690 if (cnt == 1 && pr->nospace) { 720 if (savech) {
691 *pr->nospace = savech; 721 *pr->nospace = savech;
692 } 722 }
693 } 723 }
@@ -695,7 +725,7 @@ static NOINLINE void display(priv_dumper_t* dumper)
695 } 725 }
696 } 726 }
697 } 727 }
698 728 IF_OD(endfu:)
699 if (dumper->endfu) { 729 if (dumper->endfu) {
700 PR *pr; 730 PR *pr;
701 /* 731 /*
@@ -711,10 +741,14 @@ static NOINLINE void display(priv_dumper_t* dumper)
711 for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) { 741 for (pr = dumper->endfu->nextpr; pr; pr = pr->nextpr) {
712 switch (pr->flags) { 742 switch (pr->flags) {
713 case F_ADDRESS: 743 case F_ADDRESS:
714 printf(pr->fmt, (unsigned long long) dumper->eaddress + dumper->pub.xxd_displayoff); 744 printf(pr->fmt, (unsigned long long) dumper->eaddress
745#if ENABLE_XXD
746 + dumper->pub.xxd_displayoff
747#endif
748 );
715 break; 749 break;
716 case F_TEXT: 750 case F_TEXT:
717 printf(pr->fmt); 751 fputs_stdout(pr->fmt);
718 break; 752 break;
719 } 753 }
720 } 754 }