verbose error report in CLI

PiperOrigin-RevId: 546833411
diff --git a/c/dec/decode.c b/c/dec/decode.c
index de46eb4..953523f 100644
--- a/c/dec/decode.c
+++ b/c/dec/decode.c
@@ -2831,7 +2831,7 @@
 const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c) {
   switch (c) {
 #define BROTLI_ERROR_CODE_CASE_(PREFIX, NAME, CODE) \
-    case BROTLI_DECODER ## PREFIX ## NAME: return #NAME;
+    case BROTLI_DECODER ## PREFIX ## NAME: return #PREFIX #NAME;
 #define BROTLI_NOTHING_
     BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_CASE_, BROTLI_NOTHING_)
 #undef BROTLI_ERROR_CODE_CASE_
diff --git a/c/tools/brotli.c b/c/tools/brotli.c
index 102a87a..b7afae3 100644
--- a/c/tools/brotli.c
+++ b/c/tools/brotli.c
@@ -988,6 +988,22 @@
   fprintf(stderr, " in %1.2f sec", (double)(context->end_time - context->start_time) / CLOCKS_PER_SEC);
 }
 
+static const char* PrettyDecoderErrorString(BrotliDecoderErrorCode code) {
+  /* "_ERROR_domain_" is in only added in newer versions. If CLI is linked
+     against older shared library, return error string as is; result might be
+     a bit confusing, e.g. "RESERVED" instead of "FORMAT_RESERVED" */
+  const char* prefix = "_ERROR_";
+  size_t prefix_len = strlen(prefix);
+  const char* error_str = BrotliDecoderErrorString(code);
+  size_t error_len = strlen(error_str);
+  if (error_len > prefix_len) {
+    if (strncmp(error_str, prefix, prefix_len) == 0) {
+      error_str += prefix_len;
+    }
+  }
+  return error_str;
+}
+
 static BROTLI_BOOL DecompressFile(Context* context, BrotliDecoderState* s) {
   BrotliDecoderResult result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
   InitializeBuffers(context);
@@ -996,6 +1012,9 @@
       if (!HasMoreInput(context)) {
         fprintf(stderr, "corrupt input [%s]\n",
                 PrintablePath(context->current_input_path));
+        if (context->verbosity > 0) {
+          fprintf(stderr, "reason: truncated input\n");
+        }
         return BROTLI_FALSE;
       }
       if (!ProvideInput(context)) return BROTLI_FALSE;
@@ -1008,6 +1027,9 @@
       if (has_more_input) {
         fprintf(stderr, "corrupt input [%s]\n",
                 PrintablePath(context->current_input_path));
+        if (context->verbosity > 0) {
+          fprintf(stderr, "reason: extra input\n");
+        }
         return BROTLI_FALSE;
       }
       if (context->verbosity > 0) {
@@ -1017,9 +1039,14 @@
         fprintf(stderr, "\n");
       }
       return BROTLI_TRUE;
-    } else {
+    } else {  /* result == BROTLI_DECODER_RESULT_ERROR */
       fprintf(stderr, "corrupt input [%s]\n",
               PrintablePath(context->current_input_path));
+      if (context->verbosity > 0) {
+        BrotliDecoderErrorCode error = BrotliDecoderGetErrorCode(s);
+        const char* error_str = PrettyDecoderErrorString(error);
+        fprintf(stderr, "reason: %s (%d)\n", error_str, error);
+      }
       return BROTLI_FALSE;
     }