27 #include "libavutil/ffversion.h" 
  102 #define SECTION_MAX_NB_CHILDREN 10 
  108 #define SECTION_FLAG_IS_WRAPPER      1  
  109 #define SECTION_FLAG_IS_ARRAY        2 
 
  110 #define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 
 
  229     union { 
double d; 
long long int i; } 
val;
 
  243         vald = vali = uv.
val.
i;
 
  250         mins  = (int)secs / 60;
 
  251         secs  = secs - mins * 60;
 
  254         snprintf(buf, buf_size, 
"%d:%02d:%09.6f", hours, mins, secs);
 
  256         const char *prefix_string = 
"";
 
  262                 index = (
long long int) (
log2(vald)) / 10;
 
  264                 vald /= 
exp2(index * 10);
 
  267                 index = (
long long int) (log10(vald)) / 3;
 
  269                 vald /= pow(10, index * 3);
 
  276             snprintf(buf, buf_size, 
"%f", vald);
 
  278             snprintf(buf, buf_size, 
"%lld", vali);
 
  290 #define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1 
  291 #define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2 
  316 #define SECTION_MAX_NB_LEVELS 10 
  352 #define OFFSET(x) offsetof(WriterContext, x) 
  355     { 
"string_validation", 
"set string validation mode",
 
  357     { 
"sv", 
"set string validation mode",
 
  362     { 
"string_validation_replacement", 
"set string validation replacement string", 
OFFSET(string_validation_replacement), 
AV_OPT_TYPE_STRING, {.str=
""}},
 
  363     { 
"svr", 
"set string validation replacement string", 
OFFSET(string_validation_replacement), 
AV_OPT_TYPE_STRING, {.str=
"\xEF\xBF\xBD"}},
 
  390     if ((*wctx)->writer->uninit)
 
  391         (*wctx)->writer->uninit(*wctx);
 
  394     if ((*wctx)->writer->priv_class)
 
  405     for (i = 0; i < ubuf_size; i++)
 
  411                        const struct section *sections, 
int nb_sections)
 
  426     (*wctx)->writer = writer;
 
  429     (*wctx)->nb_sections = nb_sections;
 
  434         void *priv_ctx = (*wctx)->priv;
 
  445             av_log(*wctx, 
AV_LOG_ERROR, 
"Failed to parse option string '%s' provided to writer context\n", args);
 
  452                 av_log(*wctx, 
AV_LOG_ERROR, 
"Failed to set option '%s' with value '%s' provided to writer context\n",
 
  464         const uint8_t *p = (*wctx)->string_validation_replacement;
 
  465         const uint8_t *endp = p + strlen(p);
 
  469             ret = 
av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
 
  475                            "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
 
  476                            bp.str, (*wctx)->string_validation_replacement);
 
  485     if ((*wctx)->writer->init)
 
  486         ret = (*wctx)->writer->init(*wctx);
 
  500     int parent_section_id;
 
  503     parent_section_id = wctx->
level ?
 
  524     int parent_section_id = wctx->
level ?
 
  539                                         const char *key, 
long long int val)
 
  553     int invalid_chars_nb = 0, 
ret = 0;
 
  557     endp = src + strlen(src);
 
  558     for (p = (
uint8_t *)src; *p;) {
 
  568                    "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
 
  578                        "Invalid UTF-8 sequence found in string '%s'\n", src);
 
  595                "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
 
  604 #define PRINT_STRING_OPT      1 
  605 #define PRINT_STRING_VALIDATE 2 
  608                                       const char *key, 
const char *
val, 
int flags)
 
  619             char *key1 = NULL, *val1 = NULL;
 
  621             if (ret < 0) 
goto end;
 
  623             if (ret < 0) 
goto end;
 
  628                        "Invalid key=value string combination %s=%s in section %s\n",
 
  653                               int64_t ts, 
const AVRational *time_base, 
int is_duration)
 
  657     if ((!is_duration && ts == 
AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
 
  660         double d = ts * 
av_q2d(*time_base);
 
  671     if ((!is_duration && ts == 
AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
 
  689         for (i = 0; i < l; i++) {
 
  695         for (i = 0; i < l; i++)
 
  716     p = buf + strlen(buf);
 
  721 #define MAX_REGISTERED_WRITERS_NB 64 
  727     static int next_registered_writer_idx = 0;
 
  732     registered_writers[next_registered_writer_idx++] = writer;
 
  740     for (i = 0; registered_writers[
i]; i++)
 
  741         if (!strcmp(registered_writers[i]->name, name))
 
  742             return registered_writers[
i];
 
  750 #define DEFINE_WRITER_CLASS(name)                   \ 
  751 static const char *name##_get_name(void *ctx)       \ 
  755 static const AVClass name##_class = {               \ 
  756     .class_name = #name,                            \ 
  757     .item_name  = name##_get_name,                  \ 
  758     .option     = name##_options                    \ 
  771 #define OFFSET(x) offsetof(DefaultContext, x) 
  774     { 
"noprint_wrappers", 
"do not print headers and footers", 
OFFSET(noprint_wrappers), 
AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
 
  775     { 
"nw",               
"do not print headers and footers", 
OFFSET(noprint_wrappers), 
AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
 
  787     for (i = 0; src[i] && i < dst_size-1; i++)
 
  798     const struct section *parent_section = wctx->
level ?
 
  802     if (parent_section &&
 
  837     printf(
"%s\n", value);
 
  846     printf(
"%lld\n", value);
 
  857     .priv_class            = &default_class,
 
  865 static const char *
c_escape_str(AVBPrint *dst, 
const char *
src, 
const char sep, 
void *log_ctx)
 
  869     for (p = src; *p; p++) {
 
  871         case '\b': 
av_bprintf(dst, 
"%s", 
"\\b");  
break;
 
  872         case '\f': 
av_bprintf(dst, 
"%s", 
"\\f");  
break;
 
  873         case '\n': 
av_bprintf(dst, 
"%s", 
"\\n");  
break;
 
  874         case '\r': 
av_bprintf(dst, 
"%s", 
"\\r");  
break;
 
  875         case '\\': 
av_bprintf(dst, 
"%s", 
"\\\\"); 
break;
 
  888 static const char *
csv_escape_str(AVBPrint *dst, 
const char *
src, 
const char sep, 
void *log_ctx)
 
  890     char meta_chars[] = { sep, 
'"', 
'\n', 
'\r', 
'\0' };
 
  891     int needs_quoting = !!src[strcspn(src, meta_chars)];
 
  896     for (; *
src; src++) {
 
  918     const char * (*escape_str)(AVBPrint *dst, 
const char *
src, 
const char sep, 
void *log_ctx);
 
  925 #define OFFSET(x) offsetof(CompactContext, x) 
  946         av_log(wctx, 
AV_LOG_ERROR, 
"Item separator '%s' specified, but must contain a single character\n",
 
  967     const struct section *parent_section = wctx->
level ?
 
 1009     if (!compact->
nokey)
 
 1021     if (!compact->
nokey)
 
 1023     printf(
"%lld", value);
 
 1035     .priv_class           = &compact_class,
 
 1041 #define OFFSET(x) offsetof(CompactContext, x) 
 1066     .priv_class           = &csv_class,
 
 1079 #define OFFSET(x) offsetof(FlatContext, x) 
 1084     {
"hierarchical", 
"specify if the section specification should be hierarchical", 
OFFSET(hierarchical), 
AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
 
 1085     {
"h",           
"specify if the section specification should be hierarchical", 
OFFSET(hierarchical), 
AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
 
 1095     if (strlen(flat->
sep_str) != 1) {
 
 1096         av_log(wctx, 
AV_LOG_ERROR, 
"Item separator '%s' specified, but must contain a single character\n",
 
 1109     for (p = src; *p; p++) {
 
 1110         if (!((*p >= 
'0' && *p <= 
'9') ||
 
 1111               (*p >= 
'a' && *p <= 
'z') ||
 
 1112               (*p >= 
'A' && *p <= 
'Z')))
 
 1124     for (p = src; *p; p++) {
 
 1126         case '\n': 
av_bprintf(dst, 
"%s", 
"\\n");  
break;
 
 1127         case '\r': 
av_bprintf(dst, 
"%s", 
"\\r");  
break;
 
 1128         case '\\': 
av_bprintf(dst, 
"%s", 
"\\\\"); 
break;
 
 1129         case '"':  
av_bprintf(dst, 
"%s", 
"\\\""); 
break;
 
 1130         case '`':  
av_bprintf(dst, 
"%s", 
"\\`");  
break;
 
 1131         case '$':  
av_bprintf(dst, 
"%s", 
"\\$");  
break;
 
 1143     const struct section *parent_section = wctx->
level ?
 
 1148     if (!parent_section)
 
 1190     .priv_class            = &flat_class,
 
 1201 #define OFFSET(x) offsetof(INIContext, x) 
 1204     {
"hierarchical", 
"specify if the section specification should be hierarchical", 
OFFSET(hierarchical), 
AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
 
 1205     {
"h",           
"specify if the section specification should be hierarchical", 
OFFSET(hierarchical), 
AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
 
 1216     while (c = src[i++]) {
 
 1218         case '\b': 
av_bprintf(dst, 
"%s", 
"\\b"); 
break;
 
 1219         case '\f': 
av_bprintf(dst, 
"%s", 
"\\f"); 
break;
 
 1220         case '\n': 
av_bprintf(dst, 
"%s", 
"\\n"); 
break;
 
 1221         case '\r': 
av_bprintf(dst, 
"%s", 
"\\r"); 
break;
 
 1222         case '\t': 
av_bprintf(dst, 
"%s", 
"\\t"); 
break;
 
 1228             if ((
unsigned char)c < 32)
 
 1243     const struct section *parent_section = wctx->
level ?
 
 1247     if (!parent_section) {
 
 1248         printf(
"# ffprobe output\n\n");
 
 1268         printf(
"[%s]\n", buf->str);
 
 1284     printf(
"%s=%lld\n", key, value);
 
 1294     .priv_class            = &ini_class,
 
 1307 #define OFFSET(x) offsetof(JSONContext, x) 
 1329     static const char json_escape[] = {
'"', 
'\\', 
'\b', 
'\f', 
'\n', 
'\r', 
'\t', 0};
 
 1330     static const char json_subst[]  = {
'"', 
'\\',  
'b',  
'f',  
'n',  
'r',  
't', 0};
 
 1333     for (p = src; *p; p++) {
 
 1334         char *
s = strchr(json_escape, *p);
 
 1338         } 
else if ((
unsigned char)*p < 32) {
 
 1347 #define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ') 
 1354     const struct section *parent_section = wctx->
level ?
 
 1370             printf(
"\"%s\": [\n", buf.str);
 
 1380                 printf(
"\"type\": \"%s\"%s", section->
name, json->
item_sep);
 
 1392     if (wctx->
level == 0) {
 
 1410                                        const char *key, 
const char *
value)
 
 1456     .priv_class           = &json_class,
 
 1470 #define OFFSET(x) offsetof(XMLContext, x) 
 1473     {
"fully_qualified", 
"specify if the output should be fully qualified", 
OFFSET(fully_qualified), 
AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
 
 1474     {
"q",               
"specify if the output should be fully qualified", 
OFFSET(fully_qualified), 
AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
 
 1475     {
"xsd_strict",      
"ensure that the output is XSD compliant",         
OFFSET(xsd_strict),      
AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
 
 1476     {
"x",               
"ensure that the output is XSD compliant",         
OFFSET(xsd_strict),      
AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
 
 1488 #define CHECK_COMPLIANCE(opt, opt_name)                                 \ 
 1490             av_log(wctx, AV_LOG_ERROR,                                  \ 
 1491                    "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \ 
 1492                    "You need to disable such option with '-no%s'\n", opt_name, opt_name); \ 
 1493             return AVERROR(EINVAL);                                     \ 
 1501                    "Interleaved frames and packets are not allowed in XSD. " 
 1502                    "Select only one between the -show_frames and the -show_packets options.\n");
 
 1514     for (p = src; *p; p++) {
 
 1516         case '&' : 
av_bprintf(dst, 
"%s", 
"&");  
break;
 
 1517         case '<' : 
av_bprintf(dst, 
"%s", 
"<");   
break;
 
 1518         case '>' : 
av_bprintf(dst, 
"%s", 
">");   
break;
 
 1519         case '"' : 
av_bprintf(dst, 
"%s", 
"""); 
break;
 
 1520         case '\'': 
av_bprintf(dst, 
"%s", 
"'"); 
break;
 
 1528 #define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ') 
 1534     const struct section *parent_section = wctx->
level ?
 
 1537     if (wctx->
level == 0) {
 
 1538         const char *qual = 
" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " 
 1539             "xmlns:ffprobe='http://www.ffmpeg.org/schema/ffprobe' " 
 1540             "xsi:schemaLocation='http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd'";
 
 1542         printf(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 
 1543         printf(
"<%sffprobe%s>\n",
 
 1575     if (wctx->
level == 0) {
 
 1599         printf(
"<%s key=\"%s\"",
 
 1616     printf(
"%s=\"%lld\"", key, value);
 
 1628     .priv_class           = &xml_class,
 
 1633     static int initialized;
 
 1648 #define print_fmt(k, f, ...) do {              \ 
 1649     av_bprint_clear(&pbuf);                    \ 
 1650     av_bprintf(&pbuf, f, __VA_ARGS__);         \ 
 1651     writer_print_string(w, k, pbuf.str, 0);    \ 
 1654 #define print_int(k, v)         writer_print_integer(w, k, v) 
 1655 #define print_q(k, v, s)        writer_print_rational(w, k, v, s) 
 1656 #define print_str(k, v)         writer_print_string(w, k, v, 0) 
 1657 #define print_str_opt(k, v)     writer_print_string(w, k, v, PRINT_STRING_OPT) 
 1658 #define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE) 
 1659 #define print_time(k, v, tb)    writer_print_time(w, k, v, tb, 0) 
 1660 #define print_ts(k, v)          writer_print_ts(w, k, v, 0) 
 1661 #define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1) 
 1662 #define print_duration_ts(k, v)       writer_print_ts(w, k, v, 1) 
 1663 #define print_val(k, v, u) do {                                     \ 
 1664     struct unit_value uv;                                           \ 
 1667     writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \ 
 1670 #define print_section_header(s) writer_print_section_header(w, s) 
 1671 #define print_section_footer(s) writer_print_section_footer(w, s) 
 1673 #define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n)                        \ 
 1675     ret = av_reallocp_array(&(ptr), (new_n), sizeof(*(ptr)));           \ 
 1678     memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \ 
 1797             print_q(
"sample_aspect_ratio", sar, 
':');
 
 1834             print_str(
"side_data_type", name ? name : 
"unknown");
 
 1853     int ret = 0, got_frame = 0;
 
 1855     if (dec_ctx->
codec) {
 
 1892     av_log(log_ctx, log_level, 
"id:%d", interval->
id);
 
 1898         av_log(log_ctx, log_level, 
" start:N/A");
 
 1904             av_log(log_ctx, log_level, 
"#%"PRId64, interval->
end);
 
 1908         av_log(log_ctx, log_level, 
" end:N/A");
 
 1911     av_log(log_ctx, log_level, 
"\n");
 
 1919     int ret = 0, i = 0, frame_count = 0;
 
 1933                        "Could not seek to relative position since current " 
 1934                        "timestamp is not defined\n");
 
 1938             target = *cur_ts + interval->
start;
 
 1940             target = interval->
start;
 
 1976                 end = start + interval->
end;
 
 1981                 if (frame_count >= interval->
end)
 
 1983             } 
else if (has_end && *cur_ts != 
AV_NOPTS_VALUE && *cur_ts >= end) {
 
 2056     if ((dec_ctx = stream->
codec)) {
 
 2058         dec = dec_ctx->
codec;
 
 2100                 print_q(
"sample_aspect_ratio", sar, 
':');
 
 2105                 print_q(
"display_aspect_ratio", dar, 
':');
 
 2182             if (opt->
flags) 
continue;
 
 2218 #define PRINT_DISPOSITION(flagname, name) do {                                \ 
 2219         print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \ 
 2372     const char *errbuf_ptr = errbuf;
 
 2385     int err, i, orig_nb_streams;
 
 2389     int scan_all_pmts_set = 0;
 
 2393         scan_all_pmts_set = 1;
 
 2400     if (scan_all_pmts_set)
 
 2415     for (i = 0; i < orig_nb_streams; i++)
 
 2428                    "Failed to probe codec for input stream %d\n",
 
 2432                     "Unsupported codec with id %d for input stream %d\n",
 
 2436                                                    fmt_ctx, stream, codec);
 
 2479 #define CHECK_END if (ret < 0) goto end 
 2557     print_fmt(
"copyright", 
"Copyright (c) %d-%d the FFmpeg developers",
 
 2562     print_str(
"configuration", FFMPEG_CONFIGURATION);
 
 2568 #define SHOW_LIB_VERSION(libname, LIBNAME)                              \ 
 2570         if (CONFIG_##LIBNAME) {                                         \ 
 2571             unsigned int version = libname##_version();                 \ 
 2572             writer_print_section_header(w, SECTION_ID_LIBRARY_VERSION); \ 
 2573             print_str("name",    "lib" #libname);                       \ 
 2574             print_int("major",   LIB##LIBNAME##_VERSION_MAJOR);         \ 
 2575             print_int("minor",   LIB##LIBNAME##_VERSION_MINOR);         \ 
 2576             print_int("micro",   LIB##LIBNAME##_VERSION_MICRO);         \ 
 2577             print_int("version", version);                              \ 
 2578             print_str("ident",   LIB##LIBNAME##_IDENT);                 \ 
 2579             writer_print_section_footer(w);                             \ 
 2597 #define PRINT_PIX_FMT_FLAG(flagname, name)                                \ 
 2599         print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \ 
 2665     if (show_all_entries) {
 
 2681         if (!strcmp(section_name, section->
name) ||
 
 2684                    "'%s' matches section with unique name '%s'\n", section_name,
 
 2695     const char *p = 
arg;
 
 2703         if (!section_name) {
 
 2705                    "Missing section name for option '%s'\n", opt);
 
 2711             while (*p && *p != 
':') {
 
 2716                        "Adding '%s' to the entries to show in section '%s'\n",
 
 2717                        entry, section_name);
 
 2723             show_all_entries = 1;
 
 2726         ret = 
match_section(section_name, show_all_entries, entries);
 
 2749            "Option '%s' is deprecated, use '-show_entries format=%s' instead\n",
 
 2760                 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
 
 2764     if (!strcmp(arg, 
"-"))
 
 2794     char *next, *p, *spec = 
av_strdup(interval_spec);
 
 2805     next = strchr(spec, 
'%');
 
 2847             lli = strtoll(p, &tail, 10);
 
 2848             if (*tail || lli < 0) {
 
 2850                        "Invalid or negative value '%s' for duration number of frames\n", p);
 
 2853             interval->
end = lli;
 
 2874     char *p, *spec = 
av_strdup(intervals_spec);
 
 2879     for (n = 0, p = spec; *p; p++)
 
 2885     if (!read_intervals) {
 
 2893     for (i = 0; p; i++) {
 
 2897         next = strchr(p, 
',');
 
 2901         read_intervals[i].
id = i;
 
 2941     printf(
"%*c  %s", level * 4, 
' ', section->
name);
 
 2952     printf(
"Sections:\n" 
 2953            "W.. = Section is a wrapper (contains other sections, no local entries)\n" 
 2954            ".A. = Section contains an array of elements of the same type\n" 
 2955            "..V = Section may contain a variable number of fields with variable keys\n" 
 2956            "FLAGS NAME/UNIQUE_NAME\n" 
 2969 #define DEFINE_OPT_SHOW_SECTION(section, target_section_id)             \ 
 2970     static int opt_show_##section(const char *opt, const char *arg)     \ 
 2972         mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \ 
 2993       "use binary prefixes for byte units" },
 
 2995       "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
 
 2997       "prettify the format of displayed values, make it more human readable" },
 
 2999       "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", 
"format" },
 
 3002     { 
"sections", 
OPT_EXIT, {.func_arg = 
opt_sections}, 
"print sections structure and section information, and exit" },
 
 3005     { 
"show_error",   0, {(
void*)&opt_show_error},  
"show probing error" },
 
 3006     { 
"show_format",  0, {(
void*)&opt_show_format}, 
"show format/container info" },
 
 3007     { 
"show_frames",  0, {(
void*)&opt_show_frames}, 
"show frames info" },
 
 3009       "show a particular entry from the format/container info", 
"entry" },
 
 3011       "show a set of specified entries", 
"entry_list" },
 
 3012     { 
"show_packets", 0, {(
void*)&opt_show_packets}, 
"show packets info" },
 
 3013     { 
"show_programs", 0, {(
void*)&opt_show_programs}, 
"show programs info" },
 
 3014     { 
"show_streams", 0, {(
void*)&opt_show_streams}, 
"show streams info" },
 
 3015     { 
"show_chapters", 0, {(
void*)&opt_show_chapters}, 
"show chapters info" },
 
 3018     { 
"show_program_version",  0, {(
void*)&opt_show_program_version},  
"show ffprobe version" },
 
 3019     { 
"show_library_versions", 0, {(
void*)&opt_show_library_versions}, 
"show library versions" },
 
 3020     { 
"show_versions",         0, {(
void*)&
opt_show_versions}, 
"show program and library versions" },
 
 3021     { 
"show_pixel_formats", 0, {(
void*)&opt_show_pixel_formats}, 
"show pixel format descriptions" },
 
 3043 #define SET_DO_SHOW(id, varname) do {                                   \ 
 3044         if (check_section_show_entries(SECTION_ID_##id))                \ 
 3045             do_show_##varname = 1;                                      \ 
 3053     char *w_name = NULL, *w_args = NULL;
 
 3079     SET_DO_SHOW(PIXEL_FORMAT_FLAGS, pixel_format_flags);
 
 3080     SET_DO_SHOW(PIXEL_FORMAT_COMPONENTS, pixel_format_components);
 
 3084     SET_DO_SHOW(STREAM_DISPOSITION, stream_disposition);
 
 3085     SET_DO_SHOW(PROGRAM_STREAM_DISPOSITION, stream_disposition);
 
 3095                "-bitexact and -show_program_version or -show_library_versions " 
 3096                "options are incompatible\n");
 
 3117                        "Unknown hash algorithm '%s'\nKnown algorithms:",
 
 3136         if (w == &xml_writer)