Changeset 3621 in MondoRescue for branches/3.3/mindi-busybox/coreutils/od_bloaty.c
- Timestamp:
- Dec 20, 2016, 4:07:32 PM (7 years ago)
- Location:
- branches/3.3
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
branches/3.3/mindi-busybox/coreutils/od_bloaty.c
r3232 r3621 21 21 22 22 /* #include "libbb.h" - done in od.c */ 23 #include "common_bufsiz.h" 23 24 #define assert(a) ((void)0) 24 25 … … 67 68 /* but in coreutils 6.3 it was renamed and now has */ \ 68 69 /* _mandatory_ parameter */ \ 69 &str_A, &str_N, &str_j, &lst_t, &str_S, & bytes_per_block)70 &str_A, &str_N, &str_j, &lst_t, &str_S, &G.bytes_per_block) 70 71 71 72 … … 175 176 }; 176 177 177 static smallint exit_code; 178 179 static unsigned string_min; 180 181 /* An array of specs describing how to format each input block. */ 182 static size_t n_specs; 183 static struct tspec *spec; 184 185 /* Function that accepts an address and an optional following char, 186 and prints the address and char to stdout. */ 187 static void (*format_address)(off_t, char); 188 /* The difference between the old-style pseudo starting address and 189 the number of bytes to skip. */ 178 struct globals { 179 smallint exit_code; 180 181 unsigned string_min; 182 183 /* An array of specs describing how to format each input block. */ 184 unsigned n_specs; 185 struct tspec *spec; 186 187 /* Function that accepts an address and an optional following char, 188 and prints the address and char to stdout. */ 189 void (*format_address)(off_t, char); 190 191 /* The difference between the old-style pseudo starting address and 192 the number of bytes to skip. */ 190 193 #if ENABLE_LONG_OPTS 191 static off_t pseudo_offset; 192 #else 193 enum { pseudo_offset = 0 }; 194 #endif 195 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all 196 input is formatted. */ 197 198 /* The number of input bytes formatted per output line. It must be 199 a multiple of the least common multiple of the sizes associated with 200 the specified output types. It should be as large as possible, but 201 no larger than 16 -- unless specified with the -w option. */ 202 static unsigned bytes_per_block = 32; /* have to use unsigned, not size_t */ 203 204 /* A NULL-terminated list of the file-arguments from the command line. */ 205 static const char *const *file_list; 206 207 /* The input stream associated with the current file. */ 208 static FILE *in_stream; 194 off_t pseudo_offset; 195 # define G_pseudo_offset G.pseudo_offset 196 #endif 197 /* When zero, MAX_BYTES_TO_FORMAT and END_OFFSET are ignored, and all 198 input is formatted. */ 199 200 /* The number of input bytes formatted per output line. It must be 201 a multiple of the least common multiple of the sizes associated with 202 the specified output types. It should be as large as possible, but 203 no larger than 16 -- unless specified with the -w option. */ 204 unsigned bytes_per_block; /* have to use unsigned, not size_t */ 205 206 /* A NULL-terminated list of the file-arguments from the command line. */ 207 const char *const *file_list; 208 209 /* The input stream associated with the current file. */ 210 FILE *in_stream; 211 212 bool not_first; 213 bool prev_pair_equal; 214 } FIX_ALIASING; 215 #if !ENABLE_LONG_OPTS 216 enum { G_pseudo_offset = 0 }; 217 #endif 218 #define G (*(struct globals*)bb_common_bufsiz1) 219 #define INIT_G() do { \ 220 setup_common_bufsiz(); \ 221 BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ 222 G.bytes_per_block = 32; \ 223 } while (0) 224 209 225 210 226 #define MAX_INTEGRAL_TYPE_SIZE sizeof(ulonglong_t) … … 388 404 }; 389 405 // buf[N] pos: 01234 56789 390 char buf[12] = " x\0 0xx\0"; 391 // actually " x\0 xxx\0", but want to share string with print_ascii. 406 char buf[12] = " x\0 xxx\0"; 392 407 // [12] because we take three 32bit stack slots anyway, and 393 408 // gcc is too dumb to initialize with constant stores, 394 409 // it copies initializer from rodata. Oh well. 410 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65410 395 411 396 412 while (n_bytes--) { … … 420 436 { 421 437 // buf[N] pos: 01234 56789 422 char buf[12] = " x\0 0xx\0";438 char buf[12] = " x\0 xxx\0"; 423 439 424 440 while (n_bytes--) { … … 456 472 s = " \\v"; 457 473 break; 458 case '\x7f': 459 s = " 177"; 460 break; 461 default: /* c is never larger than 040 */ 462 buf[7] = (c >> 3) + '0'; 474 default: 475 buf[6] = (c >> 6 & 3) + '0'; 476 buf[7] = (c >> 3 & 7) + '0'; 463 477 buf[8] = (c & 7) + '0'; 464 478 s = buf + 5; … … 479 493 { 480 494 while (1) { 481 if (!* file_list)495 if (!*G.file_list) 482 496 return; 483 in_stream = fopen_or_warn_stdin(*file_list++);484 if ( in_stream) {485 break; 486 } 487 exit_code = 1;497 G.in_stream = fopen_or_warn_stdin(*G.file_list++); 498 if (G.in_stream) { 499 break; 500 } 501 G.exit_code = 1; 488 502 } 489 503 490 504 if ((option_mask32 & (OPT_N|OPT_S)) == OPT_N) 491 setbuf( in_stream, NULL);505 setbuf(G.in_stream, NULL); 492 506 } 493 507 … … 502 516 check_and_close(void) 503 517 { 504 if ( in_stream) {505 if (ferror( in_stream)) {506 bb_error_msg("%s: read error", ( in_stream == stdin)518 if (G.in_stream) { 519 if (ferror(G.in_stream)) { 520 bb_error_msg("%s: read error", (G.in_stream == stdin) 507 521 ? bb_msg_standard_input 508 : file_list[-1]522 : G.file_list[-1] 509 523 ); 510 exit_code = 1;511 } 512 fclose_if_not_stdin( in_stream);513 in_stream = NULL;524 G.exit_code = 1; 525 } 526 fclose_if_not_stdin(G.in_stream); 527 G.in_stream = NULL; 514 528 } 515 529 … … 747 761 assert(s != next); 748 762 s = next; 749 spec = xrealloc_vector(spec, 4,n_specs);750 memcpy(& spec[n_specs], &tspec, sizeof(spec[0]));751 n_specs++;763 G.spec = xrealloc_vector(G.spec, 4, G.n_specs); 764 memcpy(&G.spec[G.n_specs], &tspec, sizeof(G.spec[0])); 765 G.n_specs++; 752 766 } 753 767 } … … 766 780 return; 767 781 768 while ( in_stream) { /* !EOF */782 while (G.in_stream) { /* !EOF */ 769 783 struct stat file_stats; 770 784 … … 784 798 as large as the size of the current file, we can 785 799 decrement n_skip and go on to the next file. */ 786 if (fstat(fileno( in_stream), &file_stats) == 0800 if (fstat(fileno(G.in_stream), &file_stats) == 0 787 801 && S_ISREG(file_stats.st_mode) && file_stats.st_size > 0 788 802 ) { … … 791 805 /* take "check & close / open_next" route */ 792 806 } else { 793 if (fseeko( in_stream, n_skip, SEEK_CUR) != 0)794 exit_code = 1;807 if (fseeko(G.in_stream, n_skip, SEEK_CUR) != 0) 808 G.exit_code = 1; 795 809 return; 796 810 } … … 805 819 if (n_skip < n_bytes_to_read) 806 820 n_bytes_to_read = n_skip; 807 n_bytes_read = fread(buf, 1, n_bytes_to_read, in_stream);821 n_bytes_read = fread(buf, 1, n_bytes_to_read, G.in_stream); 808 822 n_skip -= n_bytes_read; 809 823 if (n_bytes_read != n_bytes_to_read) … … 858 872 { 859 873 format_address_std(address, ' '); 860 format_address_paren(address + pseudo_offset, c);874 format_address_paren(address + G_pseudo_offset, c); 861 875 } 862 876 #endif … … 889 903 const char *prev_block, const char *curr_block) 890 904 { 891 static char first = 1; 892 static char prev_pair_equal = 0; 893 size_t i; 905 unsigned i; 894 906 895 907 if (!(option_mask32 & OPT_v) 896 && !first897 && n_bytes == bytes_per_block898 && memcmp(prev_block, curr_block, bytes_per_block) == 0908 && G.not_first 909 && n_bytes == G.bytes_per_block 910 && memcmp(prev_block, curr_block, G.bytes_per_block) == 0 899 911 ) { 900 if ( prev_pair_equal) {912 if (G.prev_pair_equal) { 901 913 /* The two preceding blocks were equal, and the current 902 914 block is the same as the last one, so print nothing. */ 903 915 } else { 904 916 puts("*"); 905 prev_pair_equal = 1;917 G.prev_pair_equal = 1; 906 918 } 907 919 } else { 908 first = 0;909 prev_pair_equal = 0;910 for (i = 0; i < n_specs; i++) {920 G.not_first = 1; 921 G.prev_pair_equal = 0; 922 for (i = 0; i < G.n_specs; i++) { 911 923 if (i == 0) 912 format_address(current_offset, '\0');924 G.format_address(current_offset, '\0'); 913 925 else 914 926 printf("%*s", address_pad_len_char - '0', ""); 915 (* spec[i].print_function) (n_bytes, curr_block,spec[i].fmt_string);916 if ( spec[i].hexl_mode_trailer) {927 (*G.spec[i].print_function) (n_bytes, curr_block, G.spec[i].fmt_string); 928 if (G.spec[i].hexl_mode_trailer) { 917 929 /* space-pad out to full line width, then dump the trailer */ 918 unsigned datum_width = width_bytes[ spec[i].size];919 unsigned blank_fields = ( bytes_per_block - n_bytes) / datum_width;920 unsigned field_width = spec[i].field_width + 1;930 unsigned datum_width = width_bytes[G.spec[i].size]; 931 unsigned blank_fields = (G.bytes_per_block - n_bytes) / datum_width; 932 unsigned field_width = G.spec[i].field_width + 1; 921 933 printf("%*s", blank_fields * field_width, ""); 922 934 dump_hexl_mode_trailer(n_bytes, curr_block); … … 930 942 read_block(size_t n, char *block, size_t *n_bytes_in_buffer) 931 943 { 932 assert(0 < n && n <= bytes_per_block);944 assert(0 < n && n <= G.bytes_per_block); 933 945 934 946 *n_bytes_in_buffer = 0; … … 937 949 return; 938 950 939 while ( in_stream != NULL) { /* EOF. */951 while (G.in_stream != NULL) { /* EOF. */ 940 952 size_t n_needed; 941 953 size_t n_read; 942 954 943 955 n_needed = n - *n_bytes_in_buffer; 944 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, in_stream);956 n_read = fread(block + *n_bytes_in_buffer, 1, n_needed, G.in_stream); 945 957 *n_bytes_in_buffer += n_read; 946 958 if (n_read == n_needed) … … 961 973 int l_c_m = 1; 962 974 963 for (i = 0; i < n_specs; i++)964 l_c_m = lcm(l_c_m, width_bytes[(int) spec[i].size]);975 for (i = 0; i < G.n_specs; i++) 976 l_c_m = lcm(l_c_m, width_bytes[(int) G.spec[i].size]); 965 977 return l_c_m; 966 978 } … … 983 995 size_t n_bytes_read; 984 996 985 block[0] = xmalloc(2 * bytes_per_block);986 block[1] = block[0] + bytes_per_block;997 block[0] = xmalloc(2 * G.bytes_per_block); 998 block[1] = block[0] + G.bytes_per_block; 987 999 988 1000 idx = 0; … … 994 1006 break; 995 1007 } 996 n_needed = MIN(end_offset - current_offset, (off_t) bytes_per_block);1008 n_needed = MIN(end_offset - current_offset, (off_t) G.bytes_per_block); 997 1009 read_block(n_needed, block[idx], &n_bytes_read); 998 if (n_bytes_read < bytes_per_block)1010 if (n_bytes_read < G.bytes_per_block) 999 1011 break; 1000 assert(n_bytes_read == bytes_per_block);1012 assert(n_bytes_read == G.bytes_per_block); 1001 1013 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]); 1002 1014 current_offset += n_bytes_read; … … 1005 1017 } else { 1006 1018 while (1) { 1007 read_block( bytes_per_block, block[idx], &n_bytes_read);1008 if (n_bytes_read < bytes_per_block)1019 read_block(G.bytes_per_block, block[idx], &n_bytes_read); 1020 if (n_bytes_read < G.bytes_per_block) 1009 1021 break; 1010 assert(n_bytes_read == bytes_per_block);1022 assert(n_bytes_read == G.bytes_per_block); 1011 1023 write_block(current_offset, n_bytes_read, block[idx ^ 1], block[idx]); 1012 1024 current_offset += n_bytes_read; … … 1031 1043 } 1032 1044 1033 format_address(current_offset, '\n');1045 G.format_address(current_offset, '\n'); 1034 1046 1035 1047 if ((option_mask32 & OPT_N) && current_offset >= end_offset) … … 1062 1074 dump_strings(off_t address, off_t end_offset) 1063 1075 { 1064 unsigned bufsize = MAX(100, string_min);1076 unsigned bufsize = MAX(100, G.string_min); 1065 1077 unsigned char *buf = xmalloc(bufsize); 1066 1078 … … 1069 1081 int c; 1070 1082 1071 /* See if the next ' string_min' chars are all printing chars. */1083 /* See if the next 'G.string_min' chars are all printing chars. */ 1072 1084 tryline: 1073 if ((option_mask32 & OPT_N) && (end_offset - string_min <= address))1085 if ((option_mask32 & OPT_N) && (end_offset - G.string_min <= address)) 1074 1086 break; 1075 1087 i = 0; … … 1080 1092 } 1081 1093 1082 while ( in_stream) { /* !EOF */1083 c = fgetc( in_stream);1094 while (G.in_stream) { /* !EOF */ 1095 c = fgetc(G.in_stream); 1084 1096 if (c != EOF) 1085 1097 goto got_char; … … 1098 1110 } 1099 1111 1100 if (i < string_min) /* Too short! */1112 if (i < G.string_min) /* Too short! */ 1101 1113 goto tryline; 1102 1114 1103 1115 /* If we get here, the string is all printable and NUL-terminated */ 1104 1116 buf[i] = 0; 1105 format_address(address - i - 1, ' ');1117 G.format_address(address - i - 1, ' '); 1106 1118 1107 1119 for (i = 0; (c = buf[i]); i++) { … … 1121 1133 1122 1134 /* We reach this point only if we search through 1123 (max_bytes_to_format - string_min) bytes before reaching EOF. */1135 (max_bytes_to_format - G.string_min) bytes before reaching EOF. */ 1124 1136 check_and_close(); 1125 1137 ret: … … 1167 1179 int od_main(int argc UNUSED_PARAM, char **argv) 1168 1180 { 1169 static const struct suffix_mult bkm[] = {1170 { "b", 512 },1171 { "k", 1024 },1172 { "m", 1024*1024 },1173 { "", 0 }1174 };1175 1181 #if ENABLE_LONG_OPTS 1176 1182 static const char od_longopts[] ALIGN1 = … … 1199 1205 off_t max_bytes_to_format = 0; 1200 1206 1201 spec = NULL; 1202 format_address = format_address_std; 1207 INIT_G(); 1208 1209 /*G.spec = NULL; - already is */ 1210 G.format_address = format_address_std; 1203 1211 address_base_char = 'o'; 1204 1212 address_pad_len_char = '7'; … … 1226 1234 "'%c' (must be [doxn])", str_A[0]); 1227 1235 pos = p - doxn; 1228 if (pos == 3) format_address = format_address_none;1236 if (pos == 3) G.format_address = format_address_none; 1229 1237 address_base_char = doxn_address_base_char[pos]; 1230 1238 address_pad_len_char = doxn_address_pad_len_char[pos]; 1231 1239 } 1232 1240 if (opt & OPT_N) { 1233 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm );1241 max_bytes_to_format = xstrtooff_sfx(str_N, 0, bkm_suffixes); 1234 1242 } 1235 1243 if (opt & OPT_a) decode_format_string("a"); … … 1240 1248 if (opt & OPT_h) decode_format_string("x2"); 1241 1249 if (opt & OPT_i) decode_format_string("d2"); 1242 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm );1250 if (opt & OPT_j) n_bytes_to_skip = xstrtooff_sfx(str_j, 0, bkm_suffixes); 1243 1251 if (opt & OPT_l) decode_format_string("d4"); 1244 1252 if (opt & OPT_o) decode_format_string("o2"); … … 1249 1257 if (opt & OPT_s) decode_format_string("d2"); 1250 1258 if (opt & OPT_S) { 1251 string_min = xstrtou_sfx(str_S, 0, bkm);1259 G.string_min = xstrtou_sfx(str_S, 0, bkm_suffixes); 1252 1260 } 1253 1261 1254 1262 // Bloat: 1255 //if ((option_mask32 & OPT_S) && n_specs > 0)1263 //if ((option_mask32 & OPT_S) && G.n_specs > 0) 1256 1264 // bb_error_msg_and_die("no type may be specified when dumping strings"); 1257 1265 … … 1309 1317 1310 1318 if (pseudo_start >= 0) { 1311 if ( format_address == format_address_none) {1319 if (G.format_address == format_address_none) { 1312 1320 address_base_char = 'o'; 1313 1321 address_pad_len_char = '7'; 1314 format_address = format_address_paren;1322 G.format_address = format_address_paren; 1315 1323 } else { 1316 format_address = format_address_label;1324 G.format_address = format_address_label; 1317 1325 } 1318 pseudo_offset = pseudo_start - n_bytes_to_skip;1326 G_pseudo_offset = pseudo_start - n_bytes_to_skip; 1319 1327 } 1320 1328 } … … 1329 1337 } 1330 1338 1331 if ( n_specs == 0) {1339 if (G.n_specs == 0) { 1332 1340 decode_format_string("o2"); 1333 /* n_specs = 1; - done by decode_format_string */1341 /*G.n_specs = 1; - done by decode_format_string */ 1334 1342 } 1335 1343 … … 1337 1345 set the global pointer FILE_LIST so that it 1338 1346 references the null-terminated list of one name: "-". */ 1339 file_list = bb_argv_dash;1347 G.file_list = bb_argv_dash; 1340 1348 if (argv[0]) { 1341 1349 /* Set the global pointer FILE_LIST so that it 1342 1350 references the first file-argument on the command-line. */ 1343 file_list = (char const *const *) argv;1351 G.file_list = (char const *const *) argv; 1344 1352 } 1345 1353 … … 1348 1356 /* Skip over any unwanted header bytes */ 1349 1357 skip(n_bytes_to_skip); 1350 if (! in_stream)1358 if (!G.in_stream) 1351 1359 return EXIT_FAILURE; 1352 1360 … … 1355 1363 1356 1364 if (opt & OPT_w) { /* -w: width */ 1357 if (! bytes_per_block ||bytes_per_block % l_c_m != 0) {1365 if (!G.bytes_per_block || G.bytes_per_block % l_c_m != 0) { 1358 1366 bb_error_msg("warning: invalid width %u; using %d instead", 1359 (unsigned) bytes_per_block, l_c_m);1360 bytes_per_block = l_c_m;1367 (unsigned)G.bytes_per_block, l_c_m); 1368 G.bytes_per_block = l_c_m; 1361 1369 } 1362 1370 } else { 1363 bytes_per_block = l_c_m;1371 G.bytes_per_block = l_c_m; 1364 1372 if (l_c_m < DEFAULT_BYTES_PER_BLOCK) 1365 bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m;1373 G.bytes_per_block *= DEFAULT_BYTES_PER_BLOCK / l_c_m; 1366 1374 } 1367 1375 1368 1376 #ifdef DEBUG 1369 for (i = 0; i < n_specs; i++) {1377 for (i = 0; i < G.n_specs; i++) { 1370 1378 printf("%d: fmt=\"%s\" width=%d\n", 1371 1379 i, spec[i].fmt_string, width_bytes[spec[i].size]); … … 1381 1389 bb_perror_msg_and_die(bb_msg_standard_input); 1382 1390 1383 return exit_code;1384 } 1391 return G.exit_code; 1392 }
Note:
See TracChangeset
for help on using the changeset viewer.