Index: src/xz/list.c |
=================================================================== |
--- src/xz/list.c (revision 50504) |
+++ src/xz/list.c (working copy) |
@@ -49,32 +49,44 @@ |
uint64_t memusage; |
/// The filter chain of this Block in human-readable form |
- const char *filter_chain; |
+ char filter_chain[FILTERS_STR_SIZE]; |
} block_header_info; |
/// Check ID to string mapping |
static const char check_names[LZMA_CHECK_ID_MAX + 1][12] = { |
- "None", |
+ // TRANSLATORS: Indicates that there is no integrity check. |
+ // This string is used in tables, so the width must not |
+ // exceed ten columns with a fixed-width font. |
+ N_("None"), |
"CRC32", |
- "Unknown-2", |
- "Unknown-3", |
+ // TRANSLATORS: Indicates that integrity check name is not known, |
+ // but the Check ID is known (here 2). This and other "Unknown-N" |
+ // strings are used in tables, so the width must not exceed ten |
+ // columns with a fixed-width font. It's OK to omit the dash if |
+ // you need space for one extra letter, but don't use spaces. |
+ N_("Unknown-2"), |
+ N_("Unknown-3"), |
"CRC64", |
- "Unknown-5", |
- "Unknown-6", |
- "Unknown-7", |
- "Unknown-8", |
- "Unknown-9", |
+ N_("Unknown-5"), |
+ N_("Unknown-6"), |
+ N_("Unknown-7"), |
+ N_("Unknown-8"), |
+ N_("Unknown-9"), |
"SHA-256", |
- "Unknown-11", |
- "Unknown-12", |
- "Unknown-13", |
- "Unknown-14", |
- "Unknown-15", |
+ N_("Unknown-11"), |
+ N_("Unknown-12"), |
+ N_("Unknown-13"), |
+ N_("Unknown-14"), |
+ N_("Unknown-15"), |
}; |
+/// Buffer size for get_check_names(). This may be a bit ridiculous, |
+/// but at least it's enough if some language needs many multibyte chars. |
+#define CHECKS_STR_SIZE 1024 |
+ |
/// Value of the Check field as hexadecimal string. |
/// This is set by parse_check_value(). |
static char check_value[2 * LZMA_CHECK_SIZE_MAX + 1]; |
@@ -203,7 +215,7 @@ |
pos -= index_size; |
// See how much memory we can use for decoding this Index. |
- uint64_t memlimit = hardware_memlimit_get(); |
+ uint64_t memlimit = hardware_memlimit_get(MODE_LIST); |
uint64_t memused = 0; |
if (combined_index != NULL) { |
memused = lzma_index_memused(combined_index); |
@@ -442,7 +454,7 @@ |
xfi->memusage_max = bhi->memusage; |
// Convert the filter chain to human readable form. |
- bhi->filter_chain = message_filters_to_str(filters, false); |
+ message_filters_to_str(bhi->filter_chain, filters, false); |
// Free the memory allocated by lzma_block_header_decode(). |
for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i) |
@@ -533,7 +545,7 @@ |
/// \brief Get the compression ratio |
/// |
-/// This has slightly different format than that is used by in message.c. |
+/// This has slightly different format than that is used in message.c. |
static const char * |
get_ratio(uint64_t compressed_size, uint64_t uncompressed_size) |
{ |
@@ -545,7 +557,7 @@ |
if (ratio > 9.999) |
return "---"; |
- static char buf[6]; |
+ static char buf[16]; |
snprintf(buf, sizeof(buf), "%.3f", ratio); |
return buf; |
} |
@@ -553,19 +565,22 @@ |
/// \brief Get a comma-separated list of Check names |
/// |
+/// The check names are translated with gettext except when in robot mode. |
+/// |
+/// \param buf Buffer to hold the resulting string |
/// \param checks Bit mask of Checks to print |
/// \param space_after_comma |
/// It's better to not use spaces in table-like listings, |
/// but in more verbose formats a space after a comma |
/// is good for readability. |
-static const char * |
-get_check_names(uint32_t checks, bool space_after_comma) |
+static void |
+get_check_names(char buf[CHECKS_STR_SIZE], |
+ uint32_t checks, bool space_after_comma) |
{ |
assert(checks != 0); |
- static char buf[sizeof(check_names)]; |
char *pos = buf; |
- size_t left = sizeof(buf); |
+ size_t left = CHECKS_STR_SIZE; |
const char *sep = space_after_comma ? ", " : ","; |
bool comma = false; |
@@ -573,12 +588,14 @@ |
for (size_t i = 0; i <= LZMA_CHECK_ID_MAX; ++i) { |
if (checks & (UINT32_C(1) << i)) { |
my_snprintf(&pos, &left, "%s%s", |
- comma ? sep : "", check_names[i]); |
+ comma ? sep : "", |
+ opt_robot ? check_names[i] |
+ : _(check_names[i])); |
comma = true; |
} |
} |
- return buf; |
+ return; |
} |
@@ -588,27 +605,38 @@ |
static bool headings_displayed = false; |
if (!headings_displayed) { |
headings_displayed = true; |
- // TRANSLATORS: These are column titles. From Strms (Streams) |
+ // TRANSLATORS: These are column headings. From Strms (Streams) |
// to Ratio, the columns are right aligned. Check and Filename |
// are left aligned. If you need longer words, it's OK to |
- // use two lines here. Test with xz --list. |
+ // use two lines here. Test with "xz -l foo.xz". |
puts(_("Strms Blocks Compressed Uncompressed Ratio " |
"Check Filename")); |
} |
- printf("%5s %7s %11s %11s %5s %-7s %s\n", |
- uint64_to_str(lzma_index_stream_count(xfi->idx), 0), |
- uint64_to_str(lzma_index_block_count(xfi->idx), 1), |
- uint64_to_nicestr(lzma_index_file_size(xfi->idx), |
- NICESTR_B, NICESTR_TIB, false, 2), |
- uint64_to_nicestr( |
- lzma_index_uncompressed_size(xfi->idx), |
- NICESTR_B, NICESTR_TIB, false, 3), |
- get_ratio(lzma_index_file_size(xfi->idx), |
- lzma_index_uncompressed_size(xfi->idx)), |
- get_check_names(lzma_index_checks(xfi->idx), false), |
- pair->src_name); |
+ char checks[CHECKS_STR_SIZE]; |
+ get_check_names(checks, lzma_index_checks(xfi->idx), false); |
+ const char *cols[7] = { |
+ uint64_to_str(lzma_index_stream_count(xfi->idx), 0), |
+ uint64_to_str(lzma_index_block_count(xfi->idx), 1), |
+ uint64_to_nicestr(lzma_index_file_size(xfi->idx), |
+ NICESTR_B, NICESTR_TIB, false, 2), |
+ uint64_to_nicestr(lzma_index_uncompressed_size(xfi->idx), |
+ NICESTR_B, NICESTR_TIB, false, 3), |
+ get_ratio(lzma_index_file_size(xfi->idx), |
+ lzma_index_uncompressed_size(xfi->idx)), |
+ checks, |
+ pair->src_name, |
+ }; |
+ printf("%*s %*s %*s %*s %*s %-*s %s\n", |
+ tuklib_mbstr_fw(cols[0], 5), cols[0], |
+ tuklib_mbstr_fw(cols[1], 7), cols[1], |
+ tuklib_mbstr_fw(cols[2], 11), cols[2], |
+ tuklib_mbstr_fw(cols[3], 11), cols[3], |
+ tuklib_mbstr_fw(cols[4], 5), cols[4], |
+ tuklib_mbstr_fw(cols[5], 7), cols[5], |
+ cols[6]); |
+ |
return false; |
} |
@@ -618,6 +646,9 @@ |
uint64_t compressed_size, uint64_t uncompressed_size, |
uint32_t checks, uint64_t stream_padding) |
{ |
+ char checks_str[CHECKS_STR_SIZE]; |
+ get_check_names(checks_str, checks, true); |
+ |
printf(_(" Streams: %s\n"), |
uint64_to_str(stream_count, 0)); |
printf(_(" Blocks: %s\n"), |
@@ -630,8 +661,7 @@ |
NICESTR_B, NICESTR_TIB, true, 0)); |
printf(_(" Ratio: %s\n"), |
get_ratio(compressed_size, uncompressed_size)); |
- printf(_(" Check: %s\n"), |
- get_check_names(checks, true)); |
+ printf(_(" Check: %s\n"), checks_str); |
printf(_(" Stream padding: %s\n"), |
uint64_to_nicestr(stream_padding, |
NICESTR_B, NICESTR_TIB, true, 0)); |
@@ -656,6 +686,10 @@ |
uint32_t check_max = 0; |
// Print information about the Streams. |
+ // |
+ // TRANSLATORS: The second line is column headings. All except |
+ // Check are right aligned; Check is left aligned. Test with |
+ // "xz -lv foo.xz". |
puts(_(" Streams:\n Stream Blocks" |
" CompOffset UncompOffset" |
" CompSize UncompSize Ratio" |
@@ -665,22 +699,33 @@ |
lzma_index_iter_init(&iter, xfi->idx); |
while (!lzma_index_iter_next(&iter, LZMA_INDEX_ITER_STREAM)) { |
- printf(" %6s %9s %15s %15s ", |
- uint64_to_str(iter.stream.number, 0), |
- uint64_to_str(iter.stream.block_count, 1), |
- uint64_to_str( |
- iter.stream.compressed_offset, 2), |
- uint64_to_str( |
- iter.stream.uncompressed_offset, 3)); |
- printf("%15s %15s %5s %-10s %7s\n", |
- uint64_to_str(iter.stream.compressed_size, 0), |
- uint64_to_str( |
- iter.stream.uncompressed_size, 1), |
- get_ratio(iter.stream.compressed_size, |
- iter.stream.uncompressed_size), |
- check_names[iter.stream.flags->check], |
- uint64_to_str(iter.stream.padding, 2)); |
+ const char *cols1[4] = { |
+ uint64_to_str(iter.stream.number, 0), |
+ uint64_to_str(iter.stream.block_count, 1), |
+ uint64_to_str(iter.stream.compressed_offset, 2), |
+ uint64_to_str(iter.stream.uncompressed_offset, 3), |
+ }; |
+ printf(" %*s %*s %*s %*s ", |
+ tuklib_mbstr_fw(cols1[0], 6), cols1[0], |
+ tuklib_mbstr_fw(cols1[1], 9), cols1[1], |
+ tuklib_mbstr_fw(cols1[2], 15), cols1[2], |
+ tuklib_mbstr_fw(cols1[3], 15), cols1[3]); |
+ const char *cols2[5] = { |
+ uint64_to_str(iter.stream.compressed_size, 0), |
+ uint64_to_str(iter.stream.uncompressed_size, 1), |
+ get_ratio(iter.stream.compressed_size, |
+ iter.stream.uncompressed_size), |
+ _(check_names[iter.stream.flags->check]), |
+ uint64_to_str(iter.stream.padding, 2), |
+ }; |
+ printf("%*s %*s %*s %-*s %*s\n", |
+ tuklib_mbstr_fw(cols2[0], 15), cols2[0], |
+ tuklib_mbstr_fw(cols2[1], 15), cols2[1], |
+ tuklib_mbstr_fw(cols2[2], 5), cols2[2], |
+ tuklib_mbstr_fw(cols2[3], 10), cols2[3], |
+ tuklib_mbstr_fw(cols2[4], 7), cols2[4]); |
+ |
// Update the maximum Check size. |
if (lzma_check_size(iter.stream.flags->check) > check_max) |
check_max = lzma_check_size(iter.stream.flags->check); |
@@ -698,15 +743,24 @@ |
// Calculate the width of the CheckVal field. |
const int checkval_width = my_max(8, 2 * check_max); |
- // Print the headings. |
+ // TRANSLATORS: The second line is column headings. All |
+ // except Check are right aligned; Check is left aligned. |
printf(_(" Blocks:\n Stream Block" |
" CompOffset UncompOffset" |
" TotalSize UncompSize Ratio Check")); |
- if (detailed) |
- printf(_(" %-*s Header Flags CompSize" |
- " MemUsage Filters"), |
- checkval_width, _("CheckVal")); |
+ if (detailed) { |
+ // TRANSLATORS: These are additional column headings |
+ // for the most verbose listing mode. CheckVal |
+ // (Check value), Flags, and Filters are left aligned. |
+ // Header (Block Header Size), CompSize, and MemUsage |
+ // are right aligned. %*s is replaced with 0-120 |
+ // spaces to make the CheckVal column wide enough. |
+ // Test with "xz -lvv foo.xz". |
+ printf(_(" CheckVal %*s Header Flags " |
+ "CompSize MemUsage Filters"), |
+ checkval_width - 8, ""); |
+ } |
putchar('\n'); |
@@ -717,41 +771,63 @@ |
if (detailed && parse_details(pair, &iter, &bhi, xfi)) |
return true; |
- printf(" %6s %9s %15s %15s ", |
+ const char *cols1[4] = { |
uint64_to_str(iter.stream.number, 0), |
uint64_to_str( |
iter.block.number_in_stream, 1), |
uint64_to_str( |
iter.block.compressed_file_offset, 2), |
uint64_to_str( |
- iter.block.uncompressed_file_offset, |
- 3)); |
- printf("%15s %15s %5s %-*s", |
+ iter.block.uncompressed_file_offset, 3) |
+ }; |
+ printf(" %*s %*s %*s %*s ", |
+ tuklib_mbstr_fw(cols1[0], 6), cols1[0], |
+ tuklib_mbstr_fw(cols1[1], 9), cols1[1], |
+ tuklib_mbstr_fw(cols1[2], 15), cols1[2], |
+ tuklib_mbstr_fw(cols1[3], 15), cols1[3]); |
+ |
+ const char *cols2[4] = { |
uint64_to_str(iter.block.total_size, 0), |
uint64_to_str(iter.block.uncompressed_size, |
1), |
get_ratio(iter.block.total_size, |
iter.block.uncompressed_size), |
- detailed ? 11 : 1, |
- check_names[iter.stream.flags->check]); |
+ _(check_names[iter.stream.flags->check]) |
+ }; |
+ printf("%*s %*s %*s %-*s", |
+ tuklib_mbstr_fw(cols2[0], 15), cols2[0], |
+ tuklib_mbstr_fw(cols2[1], 15), cols2[1], |
+ tuklib_mbstr_fw(cols2[2], 5), cols2[2], |
+ tuklib_mbstr_fw(cols2[3], detailed ? 11 : 1), |
+ cols2[3]); |
if (detailed) { |
- // Show MiB for memory usage, because it |
- // is the only size which is not in bytes. |
const lzma_vli compressed_size |
= iter.block.unpadded_size |
- bhi.header_size |
- lzma_check_size( |
iter.stream.flags->check); |
- printf("%-*s %6s %-5s %15s %7s MiB %s", |
- checkval_width, check_value, |
+ |
+ const char *cols3[6] = { |
+ check_value, |
uint64_to_str(bhi.header_size, 0), |
bhi.flags, |
uint64_to_str(compressed_size, 1), |
uint64_to_str( |
round_up_to_mib(bhi.memusage), |
2), |
- bhi.filter_chain); |
+ bhi.filter_chain |
+ }; |
+ // Show MiB for memory usage, because it |
+ // is the only size which is not in bytes. |
+ printf("%-*s %*s %-5s %*s %*s MiB %s", |
+ checkval_width, cols3[0], |
+ tuklib_mbstr_fw(cols3[1], 6), cols3[1], |
+ cols3[2], |
+ tuklib_mbstr_fw(cols3[3], 15), |
+ cols3[3], |
+ tuklib_mbstr_fw(cols3[4], 7), cols3[4], |
+ cols3[5]); |
} |
putchar('\n'); |
@@ -772,6 +848,9 @@ |
static bool |
print_info_robot(xz_file_info *xfi, file_pair *pair) |
{ |
+ char checks[CHECKS_STR_SIZE]; |
+ get_check_names(checks, lzma_index_checks(xfi->idx), false); |
+ |
printf("name\t%s\n", pair->src_name); |
printf("file\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 |
@@ -782,7 +861,7 @@ |
lzma_index_uncompressed_size(xfi->idx), |
get_ratio(lzma_index_file_size(xfi->idx), |
lzma_index_uncompressed_size(xfi->idx)), |
- get_check_names(lzma_index_checks(xfi->idx), false), |
+ checks, |
xfi->stream_padding); |
if (message_verbosity_get() >= V_VERBOSE) { |
@@ -880,6 +959,10 @@ |
line[sizeof(line) - 1] = '\0'; |
puts(line); |
+ // Get the check names. |
+ char checks[CHECKS_STR_SIZE]; |
+ get_check_names(checks, totals.checks, false); |
+ |
// Print the totals except the file count, which needs |
// special handling. |
printf("%5s %7s %11s %11s %5s %-7s ", |
@@ -891,16 +974,16 @@ |
NICESTR_B, NICESTR_TIB, false, 3), |
get_ratio(totals.compressed_size, |
totals.uncompressed_size), |
- get_check_names(totals.checks, false)); |
+ checks); |
// Since we print totals only when there are at least two files, |
// the English message will always use "%s files". But some other |
// languages need different forms for different plurals so we |
- // have to translate this string still. |
+ // have to translate this with ngettext(). |
// |
- // TRANSLATORS: This simply indicates the number of files shown |
- // by --list even though the format string uses %s. |
- printf(N_("%s file", "%s files\n", |
+ // TRANSLATORS: %s is an integer. Only the plural form of this |
+ // message is used (e.g. "2 files"). Test with "xz -l foo.xz bar.xz". |
+ printf(ngettext("%s file\n", "%s files\n", |
totals.files <= ULONG_MAX ? totals.files |
: (totals.files % 1000000) + 1000000), |
uint64_to_str(totals.files, 0)); |
@@ -934,6 +1017,9 @@ |
static void |
print_totals_robot(void) |
{ |
+ char checks[CHECKS_STR_SIZE]; |
+ get_check_names(checks, totals.checks, false); |
+ |
printf("totals\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 "\t%" PRIu64 |
"\t%s\t%s\t%" PRIu64 "\t%" PRIu64, |
totals.streams, |
@@ -942,7 +1028,7 @@ |
totals.uncompressed_size, |
get_ratio(totals.compressed_size, |
totals.uncompressed_size), |
- get_check_names(totals.checks, false), |
+ checks, |
totals.stream_padding, |
totals.files); |