Add wuffs_base__status__message
diff --git a/doc/note/statuses.md b/doc/note/statuses.md
index 0a48cfc..f7e2b59 100644
--- a/doc/note/statuses.md
+++ b/doc/note/statuses.md
@@ -86,3 +86,7 @@
 const char* wuffs_deflate__error__bad_huffman_code =
     "#deflate: bad Huffman code";
 ```
+
+When printing a status message, the `wuffs_base__status__message` function will
+advance a (non null) pointer by 1 byte, skipping that leading `'@'`, `'#'` or
+`'$'`.
diff --git a/example/crc32/crc32.cc b/example/crc32/crc32.cc
index c1850d6..92c964b 100644
--- a/example/crc32/crc32.cc
+++ b/example/crc32/crc32.cc
@@ -58,9 +58,9 @@
 
 int main(int argc, char** argv) {
   wuffs_crc32__ieee_hasher h;
-  const char* status = h.initialize(sizeof h, WUFFS_VERSION, 0);
+  wuffs_base__status status = h.initialize(sizeof h, WUFFS_VERSION, 0);
   if (status) {
-    fprintf(stderr, "%s\n", status);
+    fprintf(stderr, "%s\n", wuffs_base__status__message(status));
     return 1;
   }
 
diff --git a/example/gifplayer/gifplayer.c b/example/gifplayer/gifplayer.c
index 19ccade..1b787ac 100644
--- a/example/gifplayer/gifplayer.c
+++ b/example/gifplayer/gifplayer.c
@@ -295,7 +295,7 @@
   wuffs_base__status status =
       wuffs_gif__decoder__initialize(&dec, sizeof dec, WUFFS_VERSION, 0);
   if (status) {
-    return status;
+    return wuffs_base__status__message(status);
   }
 
   if (quirk_honor_background_color_flag) {
@@ -315,7 +315,7 @@
     wuffs_base__image_config ic = {0};
     status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
     if (status) {
-      return status;
+      return wuffs_base__status__message(status);
     }
     if (!wuffs_base__image_config__is_valid(&ic)) {
       return "invalid image configuration";
@@ -337,7 +337,7 @@
     }
     status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg, pixbuf);
     if (status) {
-      return status;
+      return wuffs_base__status__message(status);
     }
     memset(pixbuf.ptr, 0, pixbuf.len);
   }
@@ -350,7 +350,7 @@
       if (status == wuffs_base__warning__end_of_data) {
         break;
       }
-      return status;
+      return wuffs_base__status__message(status);
     }
 
     if (wuffs_base__frame_config__index(&fc) == 0) {
@@ -423,7 +423,7 @@
     // TODO: should a zero duration mean to show this frame forever?
 
     if (decode_frame_status) {
-      return decode_frame_status;
+      return wuffs_base__status__message(decode_frame_status);
     }
   }
 
diff --git a/example/library/library.c b/example/library/library.c
index f8e258a..deb6530 100644
--- a/example/library/library.c
+++ b/example/library/library.c
@@ -98,19 +98,19 @@
   if (!dec) {
     return "out of memory";
   }
-  const char* status = wuffs_gzip__decoder__initialize(
+  wuffs_base__status status = wuffs_gzip__decoder__initialize(
       dec, sizeof__wuffs_gzip__decoder(), WUFFS_VERSION,
       WUFFS_INITIALIZE__ALREADY_ZEROED);
   if (status) {
     free(dec);
-    return status;
+    return wuffs_base__status__message(status);
   }
   status = wuffs_gzip__decoder__decode_io_writer(
       dec, &dst, &src,
       wuffs_base__make_slice_u8(work_buffer, WORK_BUFFER_SIZE));
   if (status) {
     free(dec);
-    return status;
+    return wuffs_base__status__message(status);
   }
   fwrite(dst.data.ptr, sizeof(uint8_t), dst.meta.wi, stdout);
   free(dec);
diff --git a/example/zcat/zcat.c b/example/zcat/zcat.c
index 20d7fe4..87ab3ce 100644
--- a/example/zcat/zcat.c
+++ b/example/zcat/zcat.c
@@ -85,10 +85,10 @@
 
 static const char* decode() {
   wuffs_gzip__decoder dec;
-  const char* status =
+  wuffs_base__status status =
       wuffs_gzip__decoder__initialize(&dec, sizeof dec, WUFFS_VERSION, 0);
   if (status) {
-    return status;
+    return wuffs_base__status__message(status);
   }
 
   wuffs_base__io_buffer dst;
@@ -141,7 +141,7 @@
       if (status == wuffs_base__suspension__short_write) {
         continue;
       }
-      return status;
+      return wuffs_base__status__message(status);
     }
 
     wuffs_base__io_buffer__compact(&src);
diff --git a/internal/cgen/base/core-public.h b/internal/cgen/base/core-public.h
index 67681e2..06fd96c 100644
--- a/internal/cgen/base/core-public.h
+++ b/internal/cgen/base/core-public.h
@@ -164,6 +164,17 @@
   return z && (*z != '$') && (*z != '#');
 }
 
+// wuffs_base__status__message strips the leading '$', '#' or '@'.
+static inline const char*  //
+wuffs_base__status__message(wuffs_base__status z) {
+  if (z) {
+    if ((*z == '$') || (*z == '#') || (*z == '@')) {
+      return z + 1;
+    }
+  }
+  return z;
+}
+
 // --------
 
 // FourCC constants.
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index d097061..639ca88 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -69,7 +69,7 @@
 	"// --------\n\n// wuffs_base__empty_struct is used when a Wuffs function returns an empty\n// struct. In C, if a function f returns void, you can't say \"x = f()\", but in\n// Wuffs, if a function g returns empty, you can say \"y = g()\".\ntypedef struct {\n  // private_impl is a placeholder field. It isn't explicitly used, except that\n  // without it, the sizeof a struct with no fields can differ across C/C++\n  // compilers, and it is undefined behavior in C99. For example, gcc says that\n  // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to\n  // ABI incompatibility if a Wuffs .c file is processed by one compiler and\n  // its .h file with another compiler.\n  //\n  // Instead, we explicitly insert an otherwise unused field, so that the\n  // sizeof this struct is always 1.\n  uint8_t private_impl;\n} wuffs_base__empty_struct;\n\nstatic inline wuffs_base__empty_struct  //\nwuffs_base__make_empty_struct() {\n  wuffs_base__empty_struct ret;\n  ret.private_impl = 0;\n  return ret;\n}\n\n// wuffs_base__utility is" +
 	" a placeholder receiver type. It enables what Java\n// calls static methods, as opposed to regular methods.\ntypedef struct {\n  // private_impl is a placeholder field. It isn't explicitly used, except that\n  // without it, the sizeof a struct with no fields can differ across C/C++\n  // compilers, and it is undefined behavior in C99. For example, gcc says that\n  // the sizeof an empty struct is 0, and g++ says that it is 1. This leads to\n  // ABI incompatibility if a Wuffs .c file is processed by one compiler and\n  // its .h file with another compiler.\n  //\n  // Instead, we explicitly insert an otherwise unused field, so that the\n  // sizeof this struct is always 1.\n  uint8_t private_impl;\n} wuffs_base__utility;\n\n" +
 	"" +
-	"// --------\n\n// See https://github.com/google/wuffs/blob/master/doc/note/statuses.md\ntypedef const char* wuffs_base__status;\n\n// !! INSERT wuffs_base__status names.\n\nstatic inline bool  //\nwuffs_base__status__is_complete(wuffs_base__status z) {\n  return (z == NULL) || ((*z != '$') && (*z != '#'));\n}\n\nstatic inline bool  //\nwuffs_base__status__is_error(wuffs_base__status z) {\n  return z && (*z == '#');\n}\n\nstatic inline bool  //\nwuffs_base__status__is_ok(wuffs_base__status z) {\n  return z == NULL;\n}\n\nstatic inline bool  //\nwuffs_base__status__is_suspension(wuffs_base__status z) {\n  return z && (*z == '$');\n}\n\nstatic inline bool  //\nwuffs_base__status__is_warning(wuffs_base__status z) {\n  return z && (*z != '$') && (*z != '#');\n}\n\n" +
+	"// --------\n\n// See https://github.com/google/wuffs/blob/master/doc/note/statuses.md\ntypedef const char* wuffs_base__status;\n\n// !! INSERT wuffs_base__status names.\n\nstatic inline bool  //\nwuffs_base__status__is_complete(wuffs_base__status z) {\n  return (z == NULL) || ((*z != '$') && (*z != '#'));\n}\n\nstatic inline bool  //\nwuffs_base__status__is_error(wuffs_base__status z) {\n  return z && (*z == '#');\n}\n\nstatic inline bool  //\nwuffs_base__status__is_ok(wuffs_base__status z) {\n  return z == NULL;\n}\n\nstatic inline bool  //\nwuffs_base__status__is_suspension(wuffs_base__status z) {\n  return z && (*z == '$');\n}\n\nstatic inline bool  //\nwuffs_base__status__is_warning(wuffs_base__status z) {\n  return z && (*z != '$') && (*z != '#');\n}\n\n// wuffs_base__status__message strips the leading '$', '#' or '@'.\nstatic inline const char*  //\nwuffs_base__status__message(wuffs_base__status z) {\n  if (z) {\n    if ((*z == '$') || (*z == '#') || (*z == '@')) {\n      return z + 1;\n    }\n  }\n  return z;\n}\n\n" +
 	"" +
 	"// --------\n\n// FourCC constants.\n\n// !! INSERT FourCCs.\n\n" +
 	"" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index cccf291..1973067 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -206,6 +206,17 @@
   return z && (*z != '$') && (*z != '#');
 }
 
+// wuffs_base__status__message strips the leading '$', '#' or '@'.
+static inline const char*  //
+wuffs_base__status__message(wuffs_base__status z) {
+  if (z) {
+    if ((*z == '$') || (*z == '#') || (*z == '@')) {
+      return z + 1;
+    }
+  }
+  return z;
+}
+
 // --------
 
 // FourCC constants.