Merge pull request #27 from Leo-Neat/master

Add CIFuzz
diff --git a/doc/changelog.md b/doc/changelog.md
index c6190d6..b6a3061 100644
--- a/doc/changelog.md
+++ b/doc/changelog.md
@@ -16,6 +16,7 @@
 - Added `WUFFS_BASE__PIXEL_FORMAT__BGR_565`.
 - Added interfaces.
 - Added preprocessor.
+- Added single-quoted strings.
 - Added tokens.
 - Changed `gif.decoder_workbuf_len_max_incl_worst_case` from 1 to 0.
 - Made `wuffs_base__pixel_format` a struct.
diff --git a/doc/note/auto-formatting.md b/doc/note/auto-formatting.md
index f6eee02..ad9470a 100644
--- a/doc/note/auto-formatting.md
+++ b/doc/note/auto-formatting.md
@@ -4,3 +4,15 @@
 - `C` code is formatted by `clang-format-5.0 -style=Chromium`.
 - `Go` code is formatted by `gofmt`.
 - `Wuffs` code is formatted by [`wuffsfmt`](/cmd/wuffsfmt).
+
+Some C code has empty `//` line-comments, which look superfluous at first, but
+force clang-format to break the line. This ensures one element per line (in a
+long list) or having a function's name (not just its type) start a line. For
+example, `grep ^wuffs_base__utf_8_ release/c/wuffs-unsupported-snapshot.c` (and
+note the `^`) gives you a rough overview of Wuffs' UTF-8 related functions,
+because of the forced line breaks:
+
+```
+size_t  //
+wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point);
+```
diff --git a/doc/wuffs-the-language.md b/doc/wuffs-the-language.md
index 54c7cb3..1c081b4 100644
--- a/doc/wuffs-the-language.md
+++ b/doc/wuffs-the-language.md
@@ -22,9 +22,6 @@
 - [Iterate loops](/doc/note/iterate-loops.md).
 - Public vs private API is marked with the `pub` and `pri` keywords. Visibility
   boundaries are at the package level, unlike C++ or Java's type level.
-- No string type, only [slices](/doc/note/slices-arrays-and-tables.md) of
-  `base.u8`. Literals like `"#bad checksum"` are actually
-  [statuses](/doc/note/statuses.md).
 - No variable shadowing. All local variables must be declared before any other
   statements in a function body.
 - Like Go, semi-colons can be omitted. Similarly, the `()` parentheses around
@@ -88,6 +85,34 @@
 The `as` operator, e.g. `x as T`, converts an expression `x` to the type `T`.
 
 
+## Strings
+
+There is no string type. There are [arrays and
+slices](/doc/note/slices-arrays-and-tables.md) of bytes (`base.u8`s), but bear
+in mind that Wuffs code cannot [allocate or free
+memory](/doc/note/memory-safety.md).
+
+Double-quoted literals like `"#bad checksum"` are actually
+[statuses](/doc/note/statuses.md), [axiom names](/doc/note/assertions.md) or a
+`use "std/foo"` package name.
+
+Single-quoted literals are actually numerical constants. For example, `'A'` and
+`'\t'` are equivalent to `0x41` and `0x09`. These literals are not restricted
+to a single ASCII byte or even a single Unicode code point, and can decode to
+multiple bytes when finished with a `be` or `le` endianness suffix. For
+example, `'\x01\x02'be` is equivalent to `0x0102`. Similarly, `'\u0394?'le`
+(which can also be written `'Δ?'le`) is equivalent to `0x3F94CE`, because the
+UTF-8 encodings of U+0394 GREEK CAPITAL LETTER DELTA and U+003F QUESTION MARK
+(the ASCII `?`) is `(0xCE, 0x94)` and `(0x3F)`.
+
+Double-quoted literals cannot contain backslashes, as they'd be an unnecessary
+complication. Single-quoted literals can contain backslash-escapes, as they are
+often compared with arbitrary binary data. For example, where other programming
+languages would check if JPEG data starts with the magic _string_ `"\xFF\xD8"`,
+Wuffs would check if its opening 2 bytes, read as a little-endian `base.u16`,
+is a _number_ that equals `'\xFF\xD8'le`.
+
+
 ## Introductory Example
 
 A simple Wuffs the Language program, unrelated to Wuffs the Library, is
diff --git a/example/crc32/crc32.cc b/example/crc32/crc32.cc
index dd4089a..49f4a09 100644
--- a/example/crc32/crc32.cc
+++ b/example/crc32/crc32.cc
@@ -54,7 +54,7 @@
 #define SRC_BUFFER_ARRAY_SIZE (32 * 1024)
 #endif
 
-uint8_t src_buffer_array[SRC_BUFFER_ARRAY_SIZE];
+uint8_t g_src_buffer_array[SRC_BUFFER_ARRAY_SIZE];
 
 int  //
 main(int argc, char** argv) {
@@ -66,10 +66,10 @@
   }
 
   while (true) {
-    size_t n =
-        fread(src_buffer_array, sizeof(uint8_t), SRC_BUFFER_ARRAY_SIZE, stdin);
+    size_t n = fread(g_src_buffer_array, sizeof(uint8_t), SRC_BUFFER_ARRAY_SIZE,
+                     stdin);
     uint32_t checksum =
-        h.update_u32(wuffs_base__make_slice_u8(src_buffer_array, n));
+        h.update_u32(wuffs_base__make_slice_u8(g_src_buffer_array, n));
     if (feof(stdin)) {
       printf("%08" PRIx32 "\n", checksum);
       return 0;
diff --git a/example/gifplayer/gifplayer.c b/example/gifplayer/gifplayer.c
index 01f599c..0ad7154 100644
--- a/example/gifplayer/gifplayer.c
+++ b/example/gifplayer/gifplayer.c
@@ -41,16 +41,16 @@
 #include <unistd.h>
 #define WUFFS_EXAMPLE_USE_TIMERS
 
-bool started = false;
-struct timespec start_time = {0};
+bool g_started = false;
+struct timespec g_start_time = {0};
 
 int64_t  //
 micros_since_start(struct timespec* now) {
-  if (!started) {
+  if (!g_started) {
     return 0;
   }
-  int64_t nanos = (int64_t)(now->tv_sec - start_time.tv_sec) * 1000000000 +
-                  (int64_t)(now->tv_nsec - start_time.tv_nsec);
+  int64_t nanos = (int64_t)(now->tv_sec - g_start_time.tv_sec) * 1000000000 +
+                  (int64_t)(now->tv_nsec - g_start_time.tv_nsec);
   if (nanos < 0) {
     return 0;
   }
@@ -109,29 +109,29 @@
 #define MAX_DIMENSION (4096)
 #endif
 
-uint8_t src_buffer_array[SRC_BUFFER_ARRAY_SIZE] = {0};
-size_t src_len = 0;
+uint8_t g_src_buffer_array[SRC_BUFFER_ARRAY_SIZE] = {0};
+size_t g_src_len = 0;
 
-uint8_t* curr_dst_buffer = NULL;
-uint8_t* prev_dst_buffer = NULL;
-size_t dst_len;  // Length in bytes.
+uint8_t* g_curr_dst_buffer = NULL;
+uint8_t* g_prev_dst_buffer = NULL;
+size_t g_dst_len;  // Length in bytes.
 
-wuffs_base__slice_u8 workbuf = {0};
-wuffs_base__slice_u8 printbuf = {0};
+wuffs_base__slice_u8 g_workbuf = {0};
+wuffs_base__slice_u8 g_printbuf = {0};
 
-bool first_play = true;
-uint32_t num_loops_remaining = 0;
-wuffs_base__image_config ic = {0};
-wuffs_base__pixel_buffer pb = {0};
+bool g_first_play = true;
+uint32_t g_num_loops_remaining = 0;
+wuffs_base__image_config g_ic = {0};
+wuffs_base__pixel_buffer g_pb = {0};
 
-wuffs_base__flicks cumulative_delay_micros = 0;
+wuffs_base__flicks g_cumulative_delay_micros = 0;
 
 const char*  //
 read_stdin() {
-  while (src_len < SRC_BUFFER_ARRAY_SIZE) {
-    size_t n = fread(src_buffer_array + src_len, sizeof(uint8_t),
-                     SRC_BUFFER_ARRAY_SIZE - src_len, stdin);
-    src_len += n;
+  while (g_src_len < SRC_BUFFER_ARRAY_SIZE) {
+    size_t n = fread(g_src_buffer_array + g_src_len, sizeof(uint8_t),
+                     SRC_BUFFER_ARRAY_SIZE - g_src_len, stdin);
+    g_src_len += n;
     if (feof(stdin)) {
       return NULL;
     } else if (ferror(stdin)) {
@@ -149,7 +149,7 @@
 
   bool color;
   bool quirk_honor_background_color;
-} flags = {0};
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
@@ -174,19 +174,19 @@
     }
 
     if (!strcmp(arg, "c") || !strcmp(arg, "color")) {
-      flags.color = true;
+      g_flags.color = true;
       continue;
     }
     if (!strcmp(arg, "quirk_honor_background_color")) {
-      flags.quirk_honor_background_color = true;
+      g_flags.quirk_honor_background_color = true;
       continue;
     }
 
     return "main: unrecognized flag argument";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return NULL;
 }
 
@@ -198,7 +198,7 @@
 // "\xE2\x96\x88" of "█", U+2588 FULL BLOCK.
 #define BYTES_PER_COLOR_PIXEL 32
 
-const char* reset_color = "\x1B[0m";
+const char* g_reset_color = "\x1B[0m";
 
 void  //
 restore_background(wuffs_base__pixel_buffer* pb,
@@ -208,7 +208,7 @@
   size_t y;
   for (y = bounds.min_incl_y; y < bounds.max_excl_y; y++) {
     size_t x;
-    uint8_t* d = curr_dst_buffer + (y * width4) + (bounds.min_incl_x * 4);
+    uint8_t* d = g_curr_dst_buffer + (y * width4) + (bounds.min_incl_x * 4);
     for (x = bounds.min_incl_x; x < bounds.max_excl_x; x++) {
       wuffs_base__store_u32le__no_bounds_check(d, background_color);
       d += sizeof(wuffs_base__color_u32_argb_premul);
@@ -221,8 +221,8 @@
   uint32_t width = wuffs_base__pixel_config__width(&pb->pixcfg);
   uint32_t height = wuffs_base__pixel_config__height(&pb->pixcfg);
 
-  uint8_t* d = curr_dst_buffer;
-  uint8_t* p = printbuf.ptr;
+  uint8_t* d = g_curr_dst_buffer;
+  uint8_t* p = g_printbuf.ptr;
   *p++ = '\n';
   uint32_t y;
   for (y = 0; y < height; y++) {
@@ -242,7 +242,7 @@
     }
     *p++ = '\n';
   }
-  return p - printbuf.ptr;
+  return p - g_printbuf.ptr;
 }
 
 size_t  //
@@ -250,10 +250,10 @@
   uint32_t width = wuffs_base__pixel_config__width(&pb->pixcfg);
   uint32_t height = wuffs_base__pixel_config__height(&pb->pixcfg);
 
-  uint8_t* d = curr_dst_buffer;
-  uint8_t* p = printbuf.ptr;
+  uint8_t* d = g_curr_dst_buffer;
+  uint8_t* p = g_printbuf.ptr;
   *p++ = '\n';
-  p += sprintf((char*)p, "%s", reset_color);
+  p += sprintf((char*)p, "%s", g_reset_color);
   uint32_t y;
   for (y = 0; y < height; y++) {
     uint32_t x;
@@ -270,50 +270,50 @@
     }
     *p++ = '\n';
   }
-  p += sprintf((char*)p, "%s", reset_color);
-  return p - printbuf.ptr;
+  p += sprintf((char*)p, "%s", g_reset_color);
+  return p - g_printbuf.ptr;
 }
 
 // ----
 
 const char*  //
 try_allocate(wuffs_gif__decoder* dec) {
-  uint32_t width = wuffs_base__pixel_config__width(&ic.pixcfg);
-  uint32_t height = wuffs_base__pixel_config__height(&ic.pixcfg);
+  uint32_t width = wuffs_base__pixel_config__width(&g_ic.pixcfg);
+  uint32_t height = wuffs_base__pixel_config__height(&g_ic.pixcfg);
   uint64_t num_pixels = ((uint64_t)width) * ((uint64_t)height);
   if (num_pixels > (SIZE_MAX / sizeof(wuffs_base__color_u32_argb_premul))) {
     return "could not allocate dst buffer";
   }
 
-  dst_len = num_pixels * sizeof(wuffs_base__color_u32_argb_premul);
-  curr_dst_buffer = (uint8_t*)calloc(dst_len, 1);
-  if (!curr_dst_buffer) {
+  g_dst_len = num_pixels * sizeof(wuffs_base__color_u32_argb_premul);
+  g_curr_dst_buffer = (uint8_t*)calloc(g_dst_len, 1);
+  if (!g_curr_dst_buffer) {
     return "could not allocate curr-dst buffer";
   }
 
-  prev_dst_buffer = (uint8_t*)malloc(dst_len);
-  if (!prev_dst_buffer) {
+  g_prev_dst_buffer = (uint8_t*)malloc(g_dst_len);
+  if (!g_prev_dst_buffer) {
     return "could not allocate prev-dst buffer";
   }
 
   uint64_t workbuf_len_max_incl = wuffs_gif__decoder__workbuf_len(dec).max_incl;
   if (workbuf_len_max_incl > 0) {
-    workbuf = wuffs_base__malloc_slice_u8(
+    g_workbuf = wuffs_base__malloc_slice_u8(
         malloc, wuffs_gif__decoder__workbuf_len(dec).max_incl);
-    if (!workbuf.ptr) {
+    if (!g_workbuf.ptr) {
       return "could not allocate work buffer";
     }
   } else {
-    workbuf = wuffs_base__make_slice_u8(NULL, 0);
+    g_workbuf = wuffs_base__make_slice_u8(NULL, 0);
   }
 
   uint64_t plen = 1 + ((uint64_t)(width) + 1) * (uint64_t)(height);
-  uint64_t bytes_per_print_pixel = flags.color ? BYTES_PER_COLOR_PIXEL : 1;
+  uint64_t bytes_per_print_pixel = g_flags.color ? BYTES_PER_COLOR_PIXEL : 1;
   if (plen <= ((uint64_t)SIZE_MAX) / bytes_per_print_pixel) {
-    printbuf =
+    g_printbuf =
         wuffs_base__malloc_slice_u8(malloc, plen * bytes_per_print_pixel);
   }
-  if (!printbuf.ptr) {
+  if (!g_printbuf.ptr) {
     return "could not allocate print buffer";
   }
 
@@ -324,15 +324,15 @@
 allocate(wuffs_gif__decoder* dec) {
   const char* status_msg = try_allocate(dec);
   if (status_msg) {
-    free(printbuf.ptr);
-    printbuf = wuffs_base__make_slice_u8(NULL, 0);
-    free(workbuf.ptr);
-    workbuf = wuffs_base__make_slice_u8(NULL, 0);
-    free(prev_dst_buffer);
-    prev_dst_buffer = NULL;
-    free(curr_dst_buffer);
-    curr_dst_buffer = NULL;
-    dst_len = 0;
+    free(g_printbuf.ptr);
+    g_printbuf = wuffs_base__make_slice_u8(NULL, 0);
+    free(g_workbuf.ptr);
+    g_workbuf = wuffs_base__make_slice_u8(NULL, 0);
+    free(g_prev_dst_buffer);
+    g_prev_dst_buffer = NULL;
+    free(g_curr_dst_buffer);
+    g_curr_dst_buffer = NULL;
+    g_dst_len = 0;
   }
   return status_msg;
 }
@@ -346,36 +346,36 @@
     return wuffs_base__status__message(&status);
   }
 
-  if (flags.quirk_honor_background_color) {
+  if (g_flags.quirk_honor_background_color) {
     wuffs_gif__decoder__set_quirk_enabled(
         &dec, WUFFS_GIF__QUIRK_HONOR_BACKGROUND_COLOR, true);
   }
 
   wuffs_base__io_buffer src;
-  src.data.ptr = src_buffer_array;
-  src.data.len = src_len;
-  src.meta.wi = src_len;
+  src.data.ptr = &g_src_buffer_array[0];
+  src.data.len = g_src_len;
+  src.meta.wi = g_src_len;
   src.meta.ri = 0;
   src.meta.pos = 0;
   src.meta.closed = true;
 
-  if (first_play) {
-    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, &src);
+  if (g_first_play) {
+    status = wuffs_gif__decoder__decode_image_config(&dec, &g_ic, &src);
     if (!wuffs_base__status__is_ok(&status)) {
       return wuffs_base__status__message(&status);
     }
-    if (!wuffs_base__image_config__is_valid(&ic)) {
+    if (!wuffs_base__image_config__is_valid(&g_ic)) {
       return "invalid image configuration";
     }
-    uint32_t width = wuffs_base__pixel_config__width(&ic.pixcfg);
-    uint32_t height = wuffs_base__pixel_config__height(&ic.pixcfg);
+    uint32_t width = wuffs_base__pixel_config__width(&g_ic.pixcfg);
+    uint32_t height = wuffs_base__pixel_config__height(&g_ic.pixcfg);
     if ((width > MAX_DIMENSION) || (height > MAX_DIMENSION)) {
       return "image dimensions are too large";
     }
 
     // Override the source's indexed pixel format to be non-indexed.
     wuffs_base__pixel_config__set(
-        &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
+        &g_ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL,
         WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, width, height);
 
     const char* msg = allocate(&dec);
@@ -383,7 +383,8 @@
       return msg;
     }
     status = wuffs_base__pixel_buffer__set_from_slice(
-        &pb, &ic.pixcfg, wuffs_base__make_slice_u8(curr_dst_buffer, dst_len));
+        &g_pb, &g_ic.pixcfg,
+        wuffs_base__make_slice_u8(g_curr_dst_buffer, g_dst_len));
     if (!wuffs_base__status__is_ok(&status)) {
       return wuffs_base__status__message(&status);
     }
@@ -404,8 +405,8 @@
       wuffs_base__color_u32_argb_premul background_color =
           wuffs_base__frame_config__background_color(&fc);
       size_t i;
-      size_t n = dst_len / sizeof(wuffs_base__color_u32_argb_premul);
-      uint8_t* p = curr_dst_buffer;
+      size_t n = g_dst_len / sizeof(wuffs_base__color_u32_argb_premul);
+      uint8_t* p = g_curr_dst_buffer;
       for (i = 0; i < n; i++) {
         wuffs_base__store_u32le__no_bounds_check(p, background_color);
         p += sizeof(wuffs_base__color_u32_argb_premul);
@@ -414,33 +415,33 @@
 
     switch (wuffs_base__frame_config__disposal(&fc)) {
       case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS: {
-        memcpy(prev_dst_buffer, curr_dst_buffer, dst_len);
+        memcpy(g_prev_dst_buffer, g_curr_dst_buffer, g_dst_len);
         break;
       }
     }
 
     wuffs_base__status decode_frame_status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC_OVER, workbuf, NULL);
+        &dec, &g_pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC_OVER, g_workbuf, NULL);
     if (decode_frame_status.repr == wuffs_base__note__end_of_data) {
       break;
     }
 
-    size_t n = flags.color ? print_color_art(&pb) : print_ascii_art(&pb);
+    size_t n = g_flags.color ? print_color_art(&g_pb) : print_ascii_art(&g_pb);
 
     switch (wuffs_base__frame_config__disposal(&fc)) {
       case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND: {
-        restore_background(&pb, wuffs_base__frame_config__bounds(&fc),
+        restore_background(&g_pb, wuffs_base__frame_config__bounds(&fc),
                            wuffs_base__frame_config__background_color(&fc));
         break;
       }
       case WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS: {
-        uint8_t* swap = curr_dst_buffer;
-        curr_dst_buffer = prev_dst_buffer;
-        prev_dst_buffer = swap;
+        uint8_t* swap = g_curr_dst_buffer;
+        g_curr_dst_buffer = g_prev_dst_buffer;
+        g_prev_dst_buffer = swap;
 
         wuffs_base__status status = wuffs_base__pixel_buffer__set_from_slice(
-            &pb, &ic.pixcfg,
-            wuffs_base__make_slice_u8(curr_dst_buffer, dst_len));
+            &g_pb, &g_ic.pixcfg,
+            wuffs_base__make_slice_u8(g_curr_dst_buffer, g_dst_len));
         if (!wuffs_base__status__is_ok(&status)) {
           return wuffs_base__status__message(&status);
         }
@@ -449,28 +450,28 @@
     }
 
 #if defined(WUFFS_EXAMPLE_USE_TIMERS)
-    if (started) {
+    if (g_started) {
       struct timespec now;
       if (clock_gettime(CLOCK_MONOTONIC, &now)) {
         return strerror(errno);
       }
       int64_t elapsed_micros = micros_since_start(&now);
-      if (cumulative_delay_micros > elapsed_micros) {
-        usleep(cumulative_delay_micros - elapsed_micros);
+      if (g_cumulative_delay_micros > elapsed_micros) {
+        usleep(g_cumulative_delay_micros - elapsed_micros);
       }
 
     } else {
-      if (clock_gettime(CLOCK_MONOTONIC, &start_time)) {
+      if (clock_gettime(CLOCK_MONOTONIC, &g_start_time)) {
         return strerror(errno);
       }
-      started = true;
+      g_started = true;
     }
 #endif
 
-    fwrite(printbuf.ptr, sizeof(uint8_t), n, stdout);
+    fwrite(g_printbuf.ptr, sizeof(uint8_t), n, stdout);
     fflush(stdout);
 
-    cumulative_delay_micros +=
+    g_cumulative_delay_micros +=
         (1000 * wuffs_base__frame_config__duration(&fc)) /
         WUFFS_BASE__FLICKS_PER_MILLISECOND;
 
@@ -481,9 +482,9 @@
     }
   }
 
-  if (first_play) {
-    first_play = false;
-    num_loops_remaining = wuffs_gif__decoder__num_animation_loops(&dec);
+  if (g_first_play) {
+    g_first_play = false;
+    g_num_loops_remaining = wuffs_gif__decoder__num_animation_loops(&dec);
   }
 
   return NULL;
@@ -492,17 +493,17 @@
 const char*  //
 main1(int argc, char** argv) {
   TRY(parse_flags(argc, argv));
-  if (flags.remaining_argc > 0) {
+  if (g_flags.remaining_argc > 0) {
     return "main: bad argument: use \"program < input\", not \"program input\"";
   }
   TRY(read_stdin());
   while (true) {
     TRY(play());
-    if (num_loops_remaining == 0) {
+    if (g_num_loops_remaining == 0) {
       continue;
     }
-    num_loops_remaining--;
-    if (num_loops_remaining == 0) {
+    g_num_loops_remaining--;
+    if (g_num_loops_remaining == 0) {
       break;
     }
   }
diff --git a/example/imageviewer/imageviewer.c b/example/imageviewer/imageviewer.c
index 4b5fe4d..1447cee 100644
--- a/example/imageviewer/imageviewer.c
+++ b/example/imageviewer/imageviewer.c
@@ -69,8 +69,6 @@
 #define NUM_BACKGROUND_COLORS 3
 #define SRC_BUFFER_ARRAY_SIZE (64 * 1024)
 
-// Global variable names start with a "g_" prefix.
-
 wuffs_base__color_u32_argb_premul g_background_colors[NUM_BACKGROUND_COLORS] = {
     0xFF000000,
     0xFFFFFFFF,
diff --git a/example/jsonfindptrs/jsonfindptrs.cc b/example/jsonfindptrs/jsonfindptrs.cc
index e2ead12..325661e 100644
--- a/example/jsonfindptrs/jsonfindptrs.cc
+++ b/example/jsonfindptrs/jsonfindptrs.cc
@@ -18,7 +18,7 @@
 jsonfindptrs reads UTF-8 JSON from stdin and writes every node's JSON Pointer
 (RFC 6901) to stdout.
 
-See the "const char* usage" string below for details.
+See the "const char* g_usage" string below for details.
 
 ----
 
@@ -97,7 +97,7 @@
     }                          \
   } while (false)
 
-static const char* usage =
+static const char* g_usage =
     "Usage: jsonfindptrs -flags input.json\n"
     "\n"
     "Flags:\n"
@@ -177,11 +177,11 @@
 
   uint32_t max_output_depth;
   bool strict_json_pointer_syntax;
-} flags = {0};
+} g_flags = {0};
 
 std::string  //
 parse_flags(int argc, char** argv) {
-  flags.max_output_depth = 0xFFFFFFFF;
+  g_flags.max_output_depth = 0xFFFFFFFF;
 
   int c = (argc > 0) ? 1 : 0;  // Skip argv[0], the program name.
   for (; c < argc; c++) {
@@ -204,7 +204,7 @@
     }
 
     if (!strcmp(arg, "o") || !strcmp(arg, "max-output-depth")) {
-      flags.max_output_depth = 1;
+      g_flags.max_output_depth = 1;
       continue;
     } else if (!strncmp(arg, "o=", 2) ||
                !strncmp(arg, "max-output-depth=", 16)) {
@@ -213,26 +213,29 @@
       wuffs_base__result_u64 u = wuffs_base__parse_number_u64(
           wuffs_base__make_slice_u8((uint8_t*)arg, strlen(arg)));
       if (wuffs_base__status__is_ok(&u.status) && (u.value <= 0xFFFFFFFF)) {
-        flags.max_output_depth = (uint32_t)(u.value);
+        g_flags.max_output_depth = (uint32_t)(u.value);
         continue;
       }
-      return usage;
+      return g_usage;
     }
     if (!strcmp(arg, "s") || !strcmp(arg, "strict-json-pointer-syntax")) {
-      flags.strict_json_pointer_syntax = true;
+      g_flags.strict_json_pointer_syntax = true;
       continue;
     }
 
-    return usage;
+    return g_usage;
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return "";
 }
 
   // ----
 
+#define WORK_BUFFER_ARRAY_SIZE \
+  WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
+
 #ifndef SRC_BUFFER_ARRAY_SIZE
 #define SRC_BUFFER_ARRAY_SIZE (4 * 1024)
 #endif
@@ -272,6 +275,13 @@
         m_curr_token_end_src_index(0) {
     m_status =
         m_dec.initialize(sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0);
+
+    // Uncomment these lines to enable the WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X
+    // option, discussed in a separate comment.
+    //
+    // if (m_status.is_ok()) {
+    //   m_dec.set_quirk_enabled(WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X, true);
+    // }
   }
 
   Result peek() { return peek_or_next(false); }
@@ -298,7 +308,10 @@
         return Result(m_status.message());
       }
 
-      m_status = m_dec.decode_tokens(&m_tok, &m_src);
+      m_status =
+          m_dec.decode_tokens(&m_tok, &m_src,
+                              wuffs_base__make_slice_u8(
+                                  m_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
     }
 
     wuffs_base__token t = m_tok.data.ptr[m_tok.meta.ri];
@@ -348,6 +361,12 @@
 
   wuffs_base__token m_tok_array[TOKEN_BUFFER_ARRAY_SIZE];
   uint8_t m_src_array[SRC_BUFFER_ARRAY_SIZE];
+#if WORK_BUFFER_ARRAY_SIZE > 0
+  uint8_t m_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+#else
+  // Not all C/C++ compilers support 0-length arrays.
+  uint8_t m_work_buffer_array[1];
+#endif
   wuffs_json__decoder m_dec;
 };
 
@@ -584,11 +603,43 @@
       case WUFFS_BASE__TOKEN__VBC__STRING: {
         if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
           // No-op.
+
         } else if (vbd &
                    WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
           const char* ptr =  // Convert from (uint8_t*).
               static_cast<const char*>(static_cast<void*>(tsr.src_data.ptr));
           jt.value.s.append(ptr, tsr.src_data.len);
+
+        } else if (
+            vbd &
+            WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X) {
+          // We shouldn't get here unless we enable the
+          // WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X option. The jsonfindptrs
+          // program doesn't enable that by default, but if you're copy/pasting
+          // this JsonThing code and your program does enable that option,
+          // here's how to handle it.
+          wuffs_base__slice_u8 encoded = tsr.src_data;
+          if (encoded.len & 3) {
+            return Result(
+                "main: internal error: \\x token length not a multiple of 4",
+                JsonThing());
+          }
+          while (encoded.len) {
+            uint8_t decoded[64];
+            size_t len = wuffs_base__hexadecimal__decode4(
+                wuffs_base__make_slice_u8(&decoded[0], 64), encoded);
+            if ((len > 64) || ((len * 4) > encoded.len)) {
+              return Result(
+                  "main: internal error: inconsistent hexadecimal decoding",
+                  JsonThing());
+            }
+            const char* ptr =  // Convert from (uint8_t*).
+                static_cast<const char*>(static_cast<void*>(&decoded[0]));
+            jt.value.s.append(ptr, len);
+            encoded.ptr += len * 4;
+            encoded.len -= len * 4;
+          }
+
         } else {
           return Result(
               "main: internal error: unexpected string-token conversion",
@@ -647,13 +698,13 @@
         e += "~1";
         break;
       case '\n':
-        if (flags.strict_json_pointer_syntax) {
+        if (g_flags.strict_json_pointer_syntax) {
           return "";
         }
         e += "~n";
         break;
       case '\r':
-        if (flags.strict_json_pointer_syntax) {
+        if (g_flags.strict_json_pointer_syntax) {
           return "";
         }
         e += "~r";
@@ -669,7 +720,7 @@
 std::string  //
 print_json_pointers(JsonThing& jt, std::string s, uint32_t depth) {
   std::cout << s << std::endl;
-  if (depth++ >= flags.max_output_depth) {
+  if (depth++ >= g_flags.max_output_depth) {
     return "";
   }
 
@@ -701,10 +752,10 @@
   TRY(parse_flags(argc, argv));
 
   int input_file_descriptor = 0;  // A 0 default means stdin.
-  if (flags.remaining_argc > 1) {
-    return usage;
-  } else if (flags.remaining_argc == 1) {
-    const char* arg = flags.remaining_argv[0];
+  if (g_flags.remaining_argc > 1) {
+    return g_usage;
+  } else if (g_flags.remaining_argc == 1) {
+    const char* arg = g_flags.remaining_argv[0];
     input_file_descriptor = open(arg, O_RDONLY);
     if (input_file_descriptor < 0) {
       return std::string("main: cannot read ") + arg + ": " + strerror(errno);
diff --git a/example/jsonptr/jsonptr.cc b/example/jsonptr/jsonptr.cc
index dad552d..9fd764f 100644
--- a/example/jsonptr/jsonptr.cc
+++ b/example/jsonptr/jsonptr.cc
@@ -19,7 +19,7 @@
 (RFC 6901) query syntax. It reads UTF-8 JSON from stdin and writes
 canonicalized, formatted UTF-8 JSON to stdout.
 
-See the "const char* usage" string below for details.
+See the "const char* g_usage" string below for details.
 
 ----
 
@@ -34,8 +34,8 @@
 use-after-frees.
 
 The core JSON implementation is also written in the Wuffs programming language
-(and then transpiled to C/C++), which is memory-safe but also guards against
-integer arithmetic overflows.
+(and then transpiled to C/C++), which is memory-safe (e.g. array indexing is
+bounds-checked) but also guards against integer arithmetic overflows.
 
 For defense in depth, on Linux, this program also self-imposes a
 SECCOMP_MODE_STRICT sandbox before reading (or otherwise processing) its input
@@ -60,7 +60,7 @@
 This program uses Wuffs' JSON decoder at a relatively low level, processing the
 decoder's token-stream output individually. The core loop, in pseudo-code, is
 "for_each_token { handle_token(etc); }", where the handle_token function
-changes global state (e.g. the `depth` and `context` variables) and prints
+changes global state (e.g. the `g_depth` and `g_ctx` variables) and prints
 output text based on that state and the token's source text. Notably,
 handle_token is not recursive, even though JSON values can nest.
 
@@ -140,9 +140,9 @@
     }                          \
   } while (false)
 
-static const char* eod = "main: end of data";
+static const char* g_eod = "main: end of data";
 
-static const char* usage =
+static const char* g_usage =
     "Usage: jsonptr -flags input.json\n"
     "\n"
     "Flags:\n"
@@ -232,9 +232,20 @@
 
 // ----
 
-bool sandboxed = false;
+// Wuffs allows either statically or dynamically allocated work buffers. This
+// program exercises static allocation.
+#define WORK_BUFFER_ARRAY_SIZE \
+  WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
+#if WORK_BUFFER_ARRAY_SIZE > 0
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+#else
+// Not all C/C++ compilers support 0-length arrays.
+uint8_t g_work_buffer_array[1];
+#endif
 
-int input_file_descriptor = 0;  // A 0 default means stdin.
+bool g_sandboxed = false;
+
+int g_input_file_descriptor = 0;  // A 0 default means stdin.
 
 #define MAX_INDENT 8
 #define INDENT_SPACES_STRING "        "
@@ -250,19 +261,20 @@
 #define TOKEN_BUFFER_ARRAY_SIZE (4 * 1024)
 #endif
 
-uint8_t dst_array[DST_BUFFER_ARRAY_SIZE];
-uint8_t src_array[SRC_BUFFER_ARRAY_SIZE];
-wuffs_base__token tok_array[TOKEN_BUFFER_ARRAY_SIZE];
+uint8_t g_dst_array[DST_BUFFER_ARRAY_SIZE];
+uint8_t g_src_array[SRC_BUFFER_ARRAY_SIZE];
+wuffs_base__token g_tok_array[TOKEN_BUFFER_ARRAY_SIZE];
 
-wuffs_base__io_buffer dst;
-wuffs_base__io_buffer src;
-wuffs_base__token_buffer tok;
+wuffs_base__io_buffer g_dst;
+wuffs_base__io_buffer g_src;
+wuffs_base__token_buffer g_tok;
 
-// curr_token_end_src_index is the src.data.ptr index of the end of the current
-// token. An invariant is that (curr_token_end_src_index <= src.meta.ri).
-size_t curr_token_end_src_index;
+// g_curr_token_end_src_index is the g_src.data.ptr index of the end of the
+// current token. An invariant is that (g_curr_token_end_src_index <=
+// g_src.meta.ri).
+size_t g_curr_token_end_src_index;
 
-uint32_t depth;
+uint32_t g_depth;
 
 enum class context {
   none,
@@ -271,18 +283,18 @@
   in_dict_after_brace,
   in_dict_after_key,
   in_dict_after_value,
-} ctx;
+} g_ctx;
 
 bool  //
 in_dict_before_key() {
-  return (ctx == context::in_dict_after_brace) ||
-         (ctx == context::in_dict_after_value);
+  return (g_ctx == context::in_dict_after_brace) ||
+         (g_ctx == context::in_dict_after_value);
 }
 
-uint32_t suppress_write_dst;
-bool wrote_to_dst;
+uint32_t g_suppress_write_dst;
+bool g_wrote_to_dst;
 
-wuffs_json__decoder dec;
+wuffs_json__decoder g_dec;
 
 // ----
 
@@ -531,7 +543,7 @@
     }
     return !previous_was_tilde;
   }
-} query;
+} g_query;
 
 // ----
 
@@ -546,12 +558,12 @@
   char* query_c_string;
   bool strict_json_pointer_syntax;
   bool tabs;
-} flags = {0};
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
-  flags.indent = 4;
-  flags.max_output_depth = 0xFFFFFFFF;
+  g_flags.indent = 4;
+  g_flags.max_output_depth = 0xFFFFFFFF;
 
   int c = (argc > 0) ? 1 : 0;  // Skip argv[0], the program name.
   for (; c < argc; c++) {
@@ -574,24 +586,24 @@
     }
 
     if (!strcmp(arg, "c") || !strcmp(arg, "compact-output")) {
-      flags.compact_output = true;
+      g_flags.compact_output = true;
       continue;
     }
     if (!strcmp(arg, "fail-if-unsandboxed")) {
-      flags.fail_if_unsandboxed = true;
+      g_flags.fail_if_unsandboxed = true;
       continue;
     }
     if (!strncmp(arg, "i=", 2) || !strncmp(arg, "indent=", 7)) {
       while (*arg++ != '=') {
       }
       if (('0' <= arg[0]) && (arg[0] <= '8') && (arg[1] == '\x00')) {
-        flags.indent = arg[0] - '0';
+        g_flags.indent = arg[0] - '0';
         continue;
       }
-      return usage;
+      return g_usage;
     }
     if (!strcmp(arg, "o") || !strcmp(arg, "max-output-depth")) {
-      flags.max_output_depth = 1;
+      g_flags.max_output_depth = 1;
       continue;
     } else if (!strncmp(arg, "o=", 2) ||
                !strncmp(arg, "max-output-depth=", 16)) {
@@ -600,78 +612,87 @@
       wuffs_base__result_u64 u = wuffs_base__parse_number_u64(
           wuffs_base__make_slice_u8((uint8_t*)arg, strlen(arg)));
       if (wuffs_base__status__is_ok(&u.status) && (u.value <= 0xFFFFFFFF)) {
-        flags.max_output_depth = (uint32_t)(u.value);
+        g_flags.max_output_depth = (uint32_t)(u.value);
         continue;
       }
-      return usage;
+      return g_usage;
     }
     if (!strncmp(arg, "q=", 2) || !strncmp(arg, "query=", 6)) {
       while (*arg++ != '=') {
       }
-      flags.query_c_string = arg;
+      g_flags.query_c_string = arg;
       continue;
     }
     if (!strcmp(arg, "s") || !strcmp(arg, "strict-json-pointer-syntax")) {
-      flags.strict_json_pointer_syntax = true;
+      g_flags.strict_json_pointer_syntax = true;
       continue;
     }
     if (!strcmp(arg, "t") || !strcmp(arg, "tabs")) {
-      flags.tabs = true;
+      g_flags.tabs = true;
       continue;
     }
 
-    return usage;
+    return g_usage;
   }
 
-  if (flags.query_c_string &&
-      !Query::validate(flags.query_c_string, strlen(flags.query_c_string),
-                       flags.strict_json_pointer_syntax)) {
+  if (g_flags.query_c_string &&
+      !Query::validate(g_flags.query_c_string, strlen(g_flags.query_c_string),
+                       g_flags.strict_json_pointer_syntax)) {
     return "main: bad JSON Pointer (RFC 6901) syntax for the -query=STR flag";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return nullptr;
 }
 
 const char*  //
 initialize_globals(int argc, char** argv) {
-  dst = wuffs_base__make_io_buffer(
-      wuffs_base__make_slice_u8(dst_array, DST_BUFFER_ARRAY_SIZE),
+  g_dst = wuffs_base__make_io_buffer(
+      wuffs_base__make_slice_u8(g_dst_array, DST_BUFFER_ARRAY_SIZE),
       wuffs_base__empty_io_buffer_meta());
 
-  src = wuffs_base__make_io_buffer(
-      wuffs_base__make_slice_u8(src_array, SRC_BUFFER_ARRAY_SIZE),
+  g_src = wuffs_base__make_io_buffer(
+      wuffs_base__make_slice_u8(g_src_array, SRC_BUFFER_ARRAY_SIZE),
       wuffs_base__empty_io_buffer_meta());
 
-  tok = wuffs_base__make_token_buffer(
-      wuffs_base__make_slice_token(tok_array, TOKEN_BUFFER_ARRAY_SIZE),
+  g_tok = wuffs_base__make_token_buffer(
+      wuffs_base__make_slice_token(g_tok_array, TOKEN_BUFFER_ARRAY_SIZE),
       wuffs_base__empty_token_buffer_meta());
 
-  curr_token_end_src_index = 0;
+  g_curr_token_end_src_index = 0;
 
-  depth = 0;
+  g_depth = 0;
 
-  ctx = context::none;
+  g_ctx = context::none;
 
   TRY(parse_flags(argc, argv));
-  if (flags.fail_if_unsandboxed && !sandboxed) {
+  if (g_flags.fail_if_unsandboxed && !g_sandboxed) {
     return "main: unsandboxed";
   }
   const int stdin_fd = 0;
-  if (flags.remaining_argc > ((input_file_descriptor != stdin_fd) ? 1 : 0)) {
-    return usage;
+  if (g_flags.remaining_argc >
+      ((g_input_file_descriptor != stdin_fd) ? 1 : 0)) {
+    return g_usage;
   }
 
-  query.reset(flags.query_c_string);
+  g_query.reset(g_flags.query_c_string);
 
   // If the query is non-empty, suprress writing to stdout until we've
   // completed the query.
-  suppress_write_dst = query.next_fragment() ? 1 : 0;
-  wrote_to_dst = false;
+  g_suppress_write_dst = g_query.next_fragment() ? 1 : 0;
+  g_wrote_to_dst = false;
 
-  return dec.initialize(sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0)
-      .message();
+  TRY(g_dec.initialize(sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0)
+          .message());
+
+  // Consume an optional whitespace trailer. This isn't part of the JSON spec,
+  // but it works better with line oriented Unix tools (such as "echo 123 |
+  // jsonptr" where it's "echo", not "echo -n") or hand-edited JSON files which
+  // can accidentally contain trailing whitespace.
+  g_dec.set_quirk_enabled(WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE, true);
+
+  return nullptr;
 }
 
 // ----
@@ -682,19 +703,19 @@
 
 const char*  //
 read_src() {
-  if (src.meta.closed) {
+  if (g_src.meta.closed) {
     return "main: internal error: read requested on a closed source";
   }
-  src.compact();
-  if (src.meta.wi >= src.data.len) {
-    return "main: src buffer is full";
+  g_src.compact();
+  if (g_src.meta.wi >= g_src.data.len) {
+    return "main: g_src buffer is full";
   }
   while (true) {
-    ssize_t n = read(input_file_descriptor, src.data.ptr + src.meta.wi,
-                     src.data.len - src.meta.wi);
+    ssize_t n = read(g_input_file_descriptor, g_src.data.ptr + g_src.meta.wi,
+                     g_src.data.len - g_src.meta.wi);
     if (n >= 0) {
-      src.meta.wi += n;
-      src.meta.closed = n == 0;
+      g_src.meta.wi += n;
+      g_src.meta.closed = n == 0;
       break;
     } else if (errno != EINTR) {
       return strerror(errno);
@@ -706,49 +727,49 @@
 const char*  //
 flush_dst() {
   while (true) {
-    size_t n = dst.meta.wi - dst.meta.ri;
+    size_t n = g_dst.meta.wi - g_dst.meta.ri;
     if (n == 0) {
       break;
     }
     const int stdout_fd = 1;
-    ssize_t i = write(stdout_fd, dst.data.ptr + dst.meta.ri, n);
+    ssize_t i = write(stdout_fd, g_dst.data.ptr + g_dst.meta.ri, n);
     if (i >= 0) {
-      dst.meta.ri += i;
+      g_dst.meta.ri += i;
     } else if (errno != EINTR) {
       return strerror(errno);
     }
   }
-  dst.compact();
+  g_dst.compact();
   return nullptr;
 }
 
 const char*  //
 write_dst(const void* s, size_t n) {
-  if (suppress_write_dst > 0) {
+  if (g_suppress_write_dst > 0) {
     return nullptr;
   }
   const uint8_t* p = static_cast<const uint8_t*>(s);
   while (n > 0) {
-    size_t i = dst.writer_available();
+    size_t i = g_dst.writer_available();
     if (i == 0) {
       const char* z = flush_dst();
       if (z) {
         return z;
       }
-      i = dst.writer_available();
+      i = g_dst.writer_available();
       if (i == 0) {
-        return "main: dst buffer is full";
+        return "main: g_dst buffer is full";
       }
     }
 
     if (i > n) {
       i = n;
     }
-    memcpy(dst.data.ptr + dst.meta.wi, p, i);
-    dst.meta.wi += i;
+    memcpy(g_dst.data.ptr + g_dst.meta.wi, p, i);
+    g_dst.meta.wi += i;
     p += i;
     n -= i;
-    wrote_to_dst = true;
+    g_wrote_to_dst = true;
   }
   return nullptr;
 }
@@ -822,16 +843,16 @@
     // Handle ']' or '}'.
     if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&
         (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {
-      if (query.is_at(depth)) {
+      if (g_query.is_at(g_depth)) {
         return "main: no match for query";
       }
-      if (depth <= 0) {
-        return "main: internal error: inconsistent depth";
+      if (g_depth <= 0) {
+        return "main: internal error: inconsistent g_depth";
       }
-      depth--;
+      g_depth--;
 
-      if (query.matched_all() && (depth >= flags.max_output_depth)) {
-        suppress_write_dst--;
+      if (g_query.matched_all() && (g_depth >= g_flags.max_output_depth)) {
+        g_suppress_write_dst--;
         // '…' is U+2026 HORIZONTAL ELLIPSIS, which is 3 UTF-8 bytes.
         TRY(write_dst((vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST)
                           ? "\"[…]\""
@@ -839,12 +860,14 @@
                       7));
       } else {
         // Write preceding whitespace.
-        if ((ctx != context::in_list_after_bracket) &&
-            (ctx != context::in_dict_after_brace) && !flags.compact_output) {
+        if ((g_ctx != context::in_list_after_bracket) &&
+            (g_ctx != context::in_dict_after_brace) &&
+            !g_flags.compact_output) {
           TRY(write_dst("\n", 1));
-          for (uint32_t i = 0; i < depth; i++) {
-            TRY(write_dst(flags.tabs ? INDENT_TAB_STRING : INDENT_SPACES_STRING,
-                          flags.tabs ? 1 : flags.indent));
+          for (uint32_t i = 0; i < g_depth; i++) {
+            TRY(write_dst(
+                g_flags.tabs ? INDENT_TAB_STRING : INDENT_SPACES_STRING,
+                g_flags.tabs ? 1 : g_flags.indent));
           }
         }
 
@@ -853,40 +876,41 @@
             1));
       }
 
-      ctx = (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST)
-                ? context::in_list_after_value
-                : context::in_dict_after_key;
+      g_ctx = (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST)
+                  ? context::in_list_after_value
+                  : context::in_dict_after_key;
       goto after_value;
     }
 
     // Write preceding whitespace and punctuation, if it wasn't ']', '}' or a
     // continuation of a multi-token chain.
     if (!t.link_prev()) {
-      if (ctx == context::in_dict_after_key) {
-        TRY(write_dst(": ", flags.compact_output ? 1 : 2));
-      } else if (ctx != context::none) {
-        if ((ctx != context::in_list_after_bracket) &&
-            (ctx != context::in_dict_after_brace)) {
+      if (g_ctx == context::in_dict_after_key) {
+        TRY(write_dst(": ", g_flags.compact_output ? 1 : 2));
+      } else if (g_ctx != context::none) {
+        if ((g_ctx != context::in_list_after_bracket) &&
+            (g_ctx != context::in_dict_after_brace)) {
           TRY(write_dst(",", 1));
         }
-        if (!flags.compact_output) {
+        if (!g_flags.compact_output) {
           TRY(write_dst("\n", 1));
-          for (size_t i = 0; i < depth; i++) {
-            TRY(write_dst(flags.tabs ? INDENT_TAB_STRING : INDENT_SPACES_STRING,
-                          flags.tabs ? 1 : flags.indent));
+          for (size_t i = 0; i < g_depth; i++) {
+            TRY(write_dst(
+                g_flags.tabs ? INDENT_TAB_STRING : INDENT_SPACES_STRING,
+                g_flags.tabs ? 1 : g_flags.indent));
           }
         }
       }
 
       bool query_matched_fragment = false;
-      if (query.is_at(depth)) {
-        switch (ctx) {
+      if (g_query.is_at(g_depth)) {
+        switch (g_ctx) {
           case context::in_list_after_bracket:
           case context::in_list_after_value:
-            query_matched_fragment = query.tick();
+            query_matched_fragment = g_query.tick();
             break;
           case context::in_dict_after_key:
-            query_matched_fragment = query.matched_fragment();
+            query_matched_fragment = g_query.matched_fragment();
             break;
           default:
             break;
@@ -894,20 +918,20 @@
       }
       if (!query_matched_fragment) {
         // No-op.
-      } else if (!query.next_fragment()) {
+      } else if (!g_query.next_fragment()) {
         // There is no next fragment. We have matched the complete query, and
         // the upcoming JSON value is the result of that query.
         //
-        // Un-suppress writing to stdout and reset the ctx and depth as if we
-        // were about to decode a top-level value. This makes any subsequent
-        // indentation be relative to this point, and we will return eod after
-        // the upcoming JSON value is complete.
-        if (suppress_write_dst != 1) {
-          return "main: internal error: inconsistent suppress_write_dst";
+        // Un-suppress writing to stdout and reset the g_ctx and g_depth as if
+        // we were about to decode a top-level value. This makes any subsequent
+        // indentation be relative to this point, and we will return g_eod
+        // after the upcoming JSON value is complete.
+        if (g_suppress_write_dst != 1) {
+          return "main: internal error: inconsistent g_suppress_write_dst";
         }
-        suppress_write_dst = 0;
-        ctx = context::none;
-        depth = 0;
+        g_suppress_write_dst = 0;
+        g_ctx = context::none;
+        g_depth = 0;
       } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||
                  !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {
         // The query has moved on to the next fragment but the upcoming JSON
@@ -920,32 +944,33 @@
     // value: string (a chain of raw or escaped parts), literal or number.
     switch (vbc) {
       case WUFFS_BASE__TOKEN__VBC__STRUCTURE:
-        if (query.matched_all() && (depth >= flags.max_output_depth)) {
-          suppress_write_dst++;
+        if (g_query.matched_all() && (g_depth >= g_flags.max_output_depth)) {
+          g_suppress_write_dst++;
         } else {
           TRY(write_dst(
               (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) ? "[" : "{",
               1));
         }
-        depth++;
-        ctx = (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST)
-                  ? context::in_list_after_bracket
-                  : context::in_dict_after_brace;
+        g_depth++;
+        g_ctx = (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST)
+                    ? context::in_list_after_bracket
+                    : context::in_dict_after_brace;
         return nullptr;
 
       case WUFFS_BASE__TOKEN__VBC__STRING:
         if (!t.link_prev()) {
           TRY(write_dst("\"", 1));
-          query.restart_fragment(in_dict_before_key() && query.is_at(depth));
+          g_query.restart_fragment(in_dict_before_key() &&
+                                   g_query.is_at(g_depth));
         }
 
         if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
           // No-op.
         } else if (vbd &
                    WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
-          uint8_t* ptr = src.data.ptr + curr_token_end_src_index - len;
+          uint8_t* ptr = g_src.data.ptr + g_curr_token_end_src_index - len;
           TRY(write_dst(ptr, len));
-          query.incremental_match_slice(ptr, len);
+          g_query.incremental_match_slice(ptr, len);
         } else {
           return "main: internal error: unexpected string-token conversion";
         }
@@ -961,12 +986,12 @@
           return "main: internal error: unexpected unlinked token";
         }
         TRY(handle_unicode_code_point(vbd));
-        query.incremental_match_code_point(vbd);
+        g_query.incremental_match_code_point(vbd);
         return nullptr;
 
       case WUFFS_BASE__TOKEN__VBC__LITERAL:
       case WUFFS_BASE__TOKEN__VBC__NUMBER:
-        TRY(write_dst(src.data.ptr + curr_token_end_src_index - len, len));
+        TRY(write_dst(g_src.data.ptr + g_curr_token_end_src_index - len, len));
         goto after_value;
     }
 
@@ -978,21 +1003,21 @@
   // simple value). Empty parent containers are no longer empty. If the parent
   // container is a "{...}" object, toggle between keys and values.
 after_value:
-  if (depth == 0) {
-    return eod;
+  if (g_depth == 0) {
+    return g_eod;
   }
-  switch (ctx) {
+  switch (g_ctx) {
     case context::in_list_after_bracket:
-      ctx = context::in_list_after_value;
+      g_ctx = context::in_list_after_value;
       break;
     case context::in_dict_after_brace:
-      ctx = context::in_dict_after_key;
+      g_ctx = context::in_dict_after_key;
       break;
     case context::in_dict_after_key:
-      ctx = context::in_dict_after_value;
+      g_ctx = context::in_dict_after_value;
       break;
     case context::in_dict_after_value:
-      ctx = context::in_dict_after_key;
+      g_ctx = context::in_dict_after_key;
       break;
     default:
       break;
@@ -1005,15 +1030,17 @@
   TRY(initialize_globals(argc, argv));
 
   while (true) {
-    wuffs_base__status status = dec.decode_tokens(&tok, &src);
+    wuffs_base__status status = g_dec.decode_tokens(
+        &g_tok, &g_src,
+        wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
 
-    while (tok.meta.ri < tok.meta.wi) {
-      wuffs_base__token t = tok.data.ptr[tok.meta.ri++];
+    while (g_tok.meta.ri < g_tok.meta.wi) {
+      wuffs_base__token t = g_tok.data.ptr[g_tok.meta.ri++];
       uint64_t n = t.length();
-      if ((src.meta.ri - curr_token_end_src_index) < n) {
-        return "main: internal error: inconsistent src indexes";
+      if ((g_src.meta.ri - g_curr_token_end_src_index) < n) {
+        return "main: internal error: inconsistent g_src indexes";
       }
-      curr_token_end_src_index += n;
+      g_curr_token_end_src_index += n;
 
       // Skip filler tokens (e.g. whitespace).
       if (t.value() == 0) {
@@ -1023,7 +1050,7 @@
       const char* z = handle_token(t);
       if (z == nullptr) {
         continue;
-      } else if (z == eod) {
+      } else if (z == g_eod) {
         goto end_of_data;
       }
       return z;
@@ -1032,63 +1059,39 @@
     if (status.repr == nullptr) {
       return "main: internal error: unexpected end of token stream";
     } else if (status.repr == wuffs_base__suspension__short_read) {
-      if (curr_token_end_src_index != src.meta.ri) {
-        return "main: internal error: inconsistent src indexes";
+      if (g_curr_token_end_src_index != g_src.meta.ri) {
+        return "main: internal error: inconsistent g_src indexes";
       }
       TRY(read_src());
-      curr_token_end_src_index = src.meta.ri;
+      g_curr_token_end_src_index = g_src.meta.ri;
     } else if (status.repr == wuffs_base__suspension__short_write) {
-      tok.compact();
+      g_tok.compact();
     } else {
       return status.message();
     }
   }
 end_of_data:
 
-  // With a non-empty query, don't try to consume trailing whitespace or
+  // With a non-empty g_query, don't try to consume trailing whitespace or
   // confirm that we've processed all the tokens.
-  if (flags.query_c_string && *flags.query_c_string) {
+  if (g_flags.query_c_string && *g_flags.query_c_string) {
     return nullptr;
   }
 
-  // Consume an optional whitespace trailer. This isn't part of the JSON spec,
-  // but it works better with line oriented Unix tools (such as "echo 123 |
-  // jsonptr" where it's "echo", not "echo -n") or hand-edited JSON files which
-  // can accidentally contain trailing whitespace.
-  //
-  // A whitespace trailer is zero or more ' ' and then zero or one '\n'.
-  while (true) {
-    if (src.meta.ri < src.meta.wi) {
-      uint8_t c = src.data.ptr[src.meta.ri];
-      if (c == ' ') {
-        src.meta.ri++;
-        continue;
-      } else if (c == '\n') {
-        src.meta.ri++;
-        break;
-      }
-      // The "exhausted the input" check below will fail.
-      break;
-    } else if (src.meta.closed) {
-      break;
-    }
-    TRY(read_src());
-  }
-
   // Check that we've exhausted the input.
-  if ((src.meta.ri == src.meta.wi) && !src.meta.closed) {
+  if ((g_src.meta.ri == g_src.meta.wi) && !g_src.meta.closed) {
     TRY(read_src());
   }
-  if ((src.meta.ri < src.meta.wi) || !src.meta.closed) {
+  if ((g_src.meta.ri < g_src.meta.wi) || !g_src.meta.closed) {
     return "main: valid JSON followed by further (unexpected) data";
   }
 
   // Check that we've used all of the decoded tokens, other than trailing
-  // filler tokens. For example, a bare `"foo"` string is valid JSON, but even
-  // without a trailing '\n', the Wuffs JSON parser emits a filler token for
-  // the final '\"'.
-  for (; tok.meta.ri < tok.meta.wi; tok.meta.ri++) {
-    if (tok.data.ptr[tok.meta.ri].value_base_category() !=
+  // filler tokens. For example, "true\n" is valid JSON (and fully consumed
+  // with WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE enabled) with a trailing
+  // filler token for the "\n".
+  for (; g_tok.meta.ri < g_tok.meta.wi; g_tok.meta.ri++) {
+    if (g_tok.data.ptr[g_tok.meta.ri].value_base_category() !=
         WUFFS_BASE__TOKEN__VBC__FILLER) {
       return "main: internal error: decoded OK but unprocessed tokens remain";
     }
@@ -1103,7 +1106,7 @@
     return 0;
   }
   size_t n;
-  if (status_msg == usage) {
+  if (status_msg == g_usage) {
     n = strlen(status_msg);
   } else {
     n = strnlen(status_msg, 2047);
@@ -1144,8 +1147,8 @@
         dash_dash = (arg[1] == '-') && (arg[2] == '\x00');
         continue;
       }
-      input_file_descriptor = open(arg, O_RDONLY);
-      if (input_file_descriptor < 0) {
+      g_input_file_descriptor = open(arg, O_RDONLY);
+      if (g_input_file_descriptor < 0) {
         fprintf(stderr, "%s: %s\n", arg, strerror(errno));
         return 1;
       }
@@ -1155,11 +1158,11 @@
 
 #if defined(WUFFS_EXAMPLE_USE_SECCOMP)
   prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
-  sandboxed = true;
+  g_sandboxed = true;
 #endif
 
   const char* z = main1(argc, argv);
-  if (wrote_to_dst) {
+  if (g_wrote_to_dst) {
     const char* z1 = write_dst("\n", 1);
     const char* z2 = flush_dst();
     z = z ? z : (z1 ? z1 : z2);
diff --git a/example/library/library.c b/example/library/library.c
index e6162d1..78cab0f 100644
--- a/example/library/library.c
+++ b/example/library/library.c
@@ -48,7 +48,7 @@
 #ifndef DST_BUFFER_ARRAY_SIZE
 #define DST_BUFFER_ARRAY_SIZE 1024
 #endif
-uint8_t dst_buffer_array[DST_BUFFER_ARRAY_SIZE];
+uint8_t g_dst_buffer_array[DST_BUFFER_ARRAY_SIZE];
 
 // src_ptr and src_len hold a gzip-encoded "Hello Wuffs."
 //
@@ -59,28 +59,28 @@
 //
 // Passing --no-name to the gzip command line also means to skip the timestamp,
 // which means that its output is deterministic.
-uint8_t src_ptr[] = {
+uint8_t g_src_ptr[] = {
     0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,  // 00..07
     0x00, 0x03, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57,  // 08..0F
     0x08, 0x2f, 0x4d, 0x4b, 0x2b, 0xd6, 0xe3, 0x02,  // 10..17
     0x00, 0x3c, 0x84, 0x75, 0xbb, 0x0d, 0x00, 0x00,  // 18..1F
     0x00,                                            // 20..20
 };
-size_t src_len = 0x21;
+size_t g_src_len = 0x21;
 
 #define WORK_BUFFER_ARRAY_SIZE \
   WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
 #if WORK_BUFFER_ARRAY_SIZE > 0
-uint8_t work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
 #else
 // Not all C/C++ compilers support 0-length arrays.
-uint8_t work_buffer_array[1];
+uint8_t g_work_buffer_array[1];
 #endif
 
 static const char*  //
 decode() {
   wuffs_base__io_buffer dst;
-  dst.data.ptr = dst_buffer_array;
+  dst.data.ptr = g_dst_buffer_array;
   dst.data.len = DST_BUFFER_ARRAY_SIZE;
   dst.meta.wi = 0;
   dst.meta.ri = 0;
@@ -88,9 +88,9 @@
   dst.meta.closed = false;
 
   wuffs_base__io_buffer src;
-  src.data.ptr = src_ptr;
-  src.data.len = src_len;
-  src.meta.wi = src_len;
+  src.data.ptr = g_src_ptr;
+  src.data.len = g_src_len;
+  src.meta.wi = g_src_len;
   src.meta.ri = 0;
   src.meta.pos = 0;
   src.meta.closed = true;
@@ -109,7 +109,7 @@
   }
   status = wuffs_gzip__decoder__transform_io(
       dec, &dst, &src,
-      wuffs_base__make_slice_u8(work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
+      wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
   if (!wuffs_base__status__is_ok(&status)) {
     free(dec);
     return wuffs_base__status__message(&status);
diff --git a/example/zcat/zcat.c b/example/zcat/zcat.c
index 07f9679..d1cefba 100644
--- a/example/zcat/zcat.c
+++ b/example/zcat/zcat.c
@@ -72,25 +72,25 @@
 #define WORK_BUFFER_ARRAY_SIZE \
   WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
 
-uint8_t dst_buffer_array[DST_BUFFER_ARRAY_SIZE];
-uint8_t src_buffer_array[SRC_BUFFER_ARRAY_SIZE];
+uint8_t g_dst_buffer_array[DST_BUFFER_ARRAY_SIZE];
+uint8_t g_src_buffer_array[SRC_BUFFER_ARRAY_SIZE];
 #if WORK_BUFFER_ARRAY_SIZE > 0
-uint8_t work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
 #else
 // Not all C/C++ compilers support 0-length arrays.
-uint8_t work_buffer_array[1];
+uint8_t g_work_buffer_array[1];
 #endif
 
 // ----
 
-static bool sandboxed = false;
+static bool g_sandboxed = false;
 
 struct {
   int remaining_argc;
   char** remaining_argv;
 
   bool fail_if_unsandboxed;
-} flags = {0};
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
@@ -115,15 +115,15 @@
     }
 
     if (!strcmp(arg, "fail-if-unsandboxed")) {
-      flags.fail_if_unsandboxed = true;
+      g_flags.fail_if_unsandboxed = true;
       continue;
     }
 
     return "main: unrecognized flag argument";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return NULL;
 }
 
@@ -139,7 +139,7 @@
   if (z) {
     return z;
   }
-  if (flags.fail_if_unsandboxed && !sandboxed) {
+  if (g_flags.fail_if_unsandboxed && !g_sandboxed) {
     return "main: unsandboxed";
   }
 
@@ -151,7 +151,7 @@
   }
 
   wuffs_base__io_buffer dst;
-  dst.data.ptr = dst_buffer_array;
+  dst.data.ptr = g_dst_buffer_array;
   dst.data.len = DST_BUFFER_ARRAY_SIZE;
   dst.meta.wi = 0;
   dst.meta.ri = 0;
@@ -159,7 +159,7 @@
   dst.meta.closed = false;
 
   wuffs_base__io_buffer src;
-  src.data.ptr = src_buffer_array;
+  src.data.ptr = g_src_buffer_array;
   src.data.len = SRC_BUFFER_ARRAY_SIZE;
   src.meta.wi = 0;
   src.meta.ri = 0;
@@ -184,12 +184,13 @@
     while (true) {
       status = wuffs_gzip__decoder__transform_io(
           &dec, &dst, &src,
-          wuffs_base__make_slice_u8(work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
+          wuffs_base__make_slice_u8(g_work_buffer_array,
+                                    WORK_BUFFER_ARRAY_SIZE));
 
       if (dst.meta.wi) {
         // TODO: handle EINTR and other write errors; see "man 2 write".
         const int stdout_fd = 1;
-        ignore_return_value(write(stdout_fd, dst_buffer_array, dst.meta.wi));
+        ignore_return_value(write(stdout_fd, g_dst_buffer_array, dst.meta.wi));
         dst.meta.ri = dst.meta.wi;
         wuffs_base__io_buffer__compact(&dst);
       }
@@ -241,7 +242,7 @@
 main(int argc, char** argv) {
 #if defined(WUFFS_EXAMPLE_USE_SECCOMP)
   prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
-  sandboxed = true;
+  g_sandboxed = true;
 #endif
 
   int exit_code = compute_exit_code(main1(argc, argv));
diff --git a/fuzz/c/fuzzlib/fuzzlib.c b/fuzz/c/fuzzlib/fuzzlib.c
index 35b7273..29f9a4a 100644
--- a/fuzz/c/fuzzlib/fuzzlib.c
+++ b/fuzz/c/fuzzlib/fuzzlib.c
@@ -21,11 +21,10 @@
 #error "Wuffs' .h files need to be included before this file"
 #endif
 
-volatile int* intentional_segfault_ptr = NULL;
-
 void  //
 intentional_segfault() {
-  *intentional_segfault_ptr = 0;
+  static volatile int* ptr = NULL;
+  *ptr = 0;
 }
 
 const char*  //
@@ -119,7 +118,7 @@
   char** remaining_argv;
 
   bool color;
-} flags = {0};
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
@@ -144,28 +143,28 @@
     }
 
     if (!strcmp(arg, "c") || !strcmp(arg, "color")) {
-      flags.color = true;
+      g_flags.color = true;
       continue;
     }
 
     return "main: unrecognized flag argument";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return NULL;
 }
 
-static int num_files_processed;
+static int g_num_files_processed;
 
 static struct {
   char buf[PATH_MAX];
   size_t len;
-} relative_cwd;
+} g_relative_cwd;
 
 void  //
 errorf(const char* msg) {
-  if (flags.color) {
+  if (g_flags.color) {
     printf("\e[31m%s\e[0m\n", msg);
   } else {
     printf("%s\n", msg);
@@ -242,7 +241,7 @@
   const char* msg = llvmFuzzerTestOneInput((const uint8_t*)(data), size);
   if (msg) {
     errorf(msg);
-  } else if (flags.color) {
+  } else if (g_flags.color) {
     printf("\e[32mok\e[0m\n");
   } else {
     printf("ok\n");
@@ -261,12 +260,12 @@
 
 static int  //
 visit(char* filename) {
-  num_files_processed++;
+  g_num_files_processed++;
   if (!filename || (filename[0] == '\x00')) {
     fprintf(stderr, "FAIL: invalid filename\n");
     return 1;
   }
-  int n = printf("- %s%s", relative_cwd.buf, filename);
+  int n = printf("- %s%s", g_relative_cwd.buf, filename);
   printf("%*s", (60 > n) ? (60 - n) : 1, "");
   fflush(stdout);
 
@@ -290,7 +289,7 @@
     return 0;
   }
 
-  size_t old_len = relative_cwd.len;
+  size_t old_len = g_relative_cwd.len;
   size_t filename_len = strlen(filename);
   size_t new_len = old_len + strlen(filename);
   bool slash = filename[filename_len - 1] != '/';
@@ -302,25 +301,25 @@
     fprintf(stderr, "FAIL: path is too long\n");
     return 1;
   }
-  memcpy(relative_cwd.buf + old_len, filename, filename_len);
+  memcpy(g_relative_cwd.buf + old_len, filename, filename_len);
 
   if (slash) {
-    relative_cwd.buf[new_len - 1] = '/';
+    g_relative_cwd.buf[new_len - 1] = '/';
   }
-  relative_cwd.buf[new_len] = '\x00';
-  relative_cwd.len = new_len;
+  g_relative_cwd.buf[new_len] = '\x00';
+  g_relative_cwd.len = new_len;
 
   int v = visit_dir(fd);
 
-  relative_cwd.buf[old_len] = '\x00';
-  relative_cwd.len = old_len;
+  g_relative_cwd.buf[old_len] = '\x00';
+  g_relative_cwd.len = old_len;
   return v;
 }
 
 int  //
 main(int argc, char** argv) {
-  num_files_processed = 0;
-  relative_cwd.len = 0;
+  g_num_files_processed = 0;
+  g_relative_cwd.len = 0;
 
   const char* z = parse_flags(argc, argv);
   if (z) {
@@ -328,14 +327,14 @@
     return 1;
   }
   int i;
-  for (i = 0; i < flags.remaining_argc; i++) {
-    int v = visit(flags.remaining_argv[i]);
+  for (i = 0; i < g_flags.remaining_argc; i++) {
+    int v = visit(g_flags.remaining_argv[i]);
     if (v) {
       return v;
     }
   }
 
-  printf("PASS: %d files processed\n", num_files_processed);
+  printf("PASS: %d files processed\n", g_num_files_processed);
   return 0;
 }
 
diff --git a/fuzz/c/std/json_fuzzer.c b/fuzz/c/std/json_fuzzer.c
index e8b99b0..3e76676 100644
--- a/fuzz/c/std/json_fuzzer.c
+++ b/fuzz/c/std/json_fuzzer.c
@@ -62,6 +62,17 @@
 #define TOK_BUFFER_ARRAY_SIZE 4096
 #define STACK_SIZE (WUFFS_JSON__DECODER_DEPTH_MAX_INCL + 1)
 
+// Wuffs allows either statically or dynamically allocated work buffers. This
+// program exercises static allocation.
+#define WORK_BUFFER_ARRAY_SIZE \
+  WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
+#if WORK_BUFFER_ARRAY_SIZE > 0
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+#else
+// Not all C/C++ compilers support 0-length arrays.
+uint8_t g_work_buffer_array[1];
+#endif
+
 // Each stack element is 1 byte. The low 7 bits denote the container:
 //  - 0x01 means no container: we are at the top level.
 //  - 0x02 means a [] list.
@@ -201,19 +212,63 @@
   return NULL;
 }
 
+uint64_t  //
+buffer_limit(uint32_t hash_6_bits, uint64_t min, uint64_t max) {
+  uint64_t n;
+  if (hash_6_bits < 0x20) {
+    n = min + hash_6_bits;
+  } else {
+    n = max - (0x3F - hash_6_bits);
+  }
+  if (n < min) {
+    return min;
+  } else if (n > max) {
+    return max;
+  }
+  return n;
+}
+
+void set_quirks(wuffs_json__decoder* dec, uint32_t hash_12_bits) {
+  uint32_t quirks[] = {
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X,
+      WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO,
+      WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK,
+      WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE,
+      WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA,
+      WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS,
+      WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR,
+      WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK,
+      WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE,
+      WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE,
+      0,
+  };
+
+  uint32_t i;
+  for (i = 0; quirks[i]; i++) {
+    uint32_t bit = 1 << (i % 12);
+    if (hash_12_bits & bit) {
+      wuffs_json__decoder__set_quirk_enabled(dec, quirks[i], true);
+    }
+  }
+}
+
 const char*  //
 fuzz_complex(wuffs_base__io_buffer* full_src, uint32_t hash_24_bits) {
-  uint64_t tok_limit = hash_24_bits & 0x0FFF;  // 4095, or ((1 << 12) - 1).
-  if (tok_limit < WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL) {
-    tok_limit = WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL;
-  }
-  hash_24_bits >>= 12;
+  uint64_t tok_limit = buffer_limit(
+      hash_24_bits & 0x3F, WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL,
+      TOK_BUFFER_ARRAY_SIZE);
+  uint32_t hash_18_bits = hash_24_bits >> 6;
 
-  uint64_t src_limit = hash_24_bits & 0x0FFF;  // 4095, or ((1 << 12) - 1).
-  if (src_limit < WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL) {
-    src_limit = WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL;
-  }
-  hash_24_bits >>= 12;
+  uint64_t src_limit =
+      buffer_limit(hash_18_bits & 0x3F,
+                   WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL, 4096);
+  uint32_t hash_12_bits = hash_18_bits >> 6;
 
   // ----
 
@@ -224,6 +279,7 @@
   if (!wuffs_base__status__is_ok(&status)) {
     return wuffs_base__status__message(&status);
   }
+  set_quirks(&dec, hash_12_bits);
 
   wuffs_base__token tok_array[TOK_BUFFER_ARRAY_SIZE];
   wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
@@ -252,7 +308,9 @@
     size_t old_src_ri = src.meta.ri;
     size_t ti = old_src_ri;
 
-    status = wuffs_json__decoder__decode_tokens(&dec, &tok, &src);
+    status = wuffs_json__decoder__decode_tokens(
+        &dec, &tok, &src,
+        wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
     if ((tok.data.len < tok.meta.wi) ||  //
         (tok.meta.wi < tok.meta.ri) ||   //
         (tok.meta.ri != old_tok_ri)) {
@@ -341,7 +399,9 @@
   });
 
   while (true) {
-    status = wuffs_json__decoder__decode_tokens(&dec, &tok, full_src);
+    status = wuffs_json__decoder__decode_tokens(
+        &dec, &tok, full_src,
+        wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
     if (status.repr == NULL) {
       break;
 
diff --git a/fuzz/c/std/zlib_fuzzer.c b/fuzz/c/std/zlib_fuzzer.c
index 4835c6e..2571b65 100644
--- a/fuzz/c/std/zlib_fuzzer.c
+++ b/fuzz/c/std/zlib_fuzzer.c
@@ -68,10 +68,10 @@
 #define WORK_BUFFER_ARRAY_SIZE \
   WUFFS_ZLIB__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
 #if WORK_BUFFER_ARRAY_SIZE > 0
-uint8_t work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
 #else
 // Not all C/C++ compilers support 0-length arrays.
-uint8_t work_buffer_array[1];
+uint8_t g_work_buffer_array[1];
 #endif
 
 const char*  //
@@ -99,12 +99,9 @@
 
   while (true) {
     dst.meta.wi = 0;
-    status =
-        wuffs_zlib__decoder__transform_io(&dec, &dst, src,
-                                          ((wuffs_base__slice_u8){
-                                              .ptr = work_buffer_array,
-                                              .len = WORK_BUFFER_ARRAY_SIZE,
-                                          }));
+    status = wuffs_zlib__decoder__transform_io(
+        &dec, &dst, src,
+        wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
     if (status.repr != wuffs_base__suspension__short_write) {
       break;
     }
diff --git a/internal/cgen/base/core-public.h b/internal/cgen/base/core-public.h
index accb01a..92ac663 100644
--- a/internal/cgen/base/core-public.h
+++ b/internal/cgen/base/core-public.h
@@ -383,6 +383,80 @@
   return res;
 }
 
+// --------
+
+typedef struct {
+  uint64_t hi;
+  uint64_t lo;
+} wuffs_base__multiply_u64__output;
+
+// wuffs_base__multiply_u64 returns x*y as a 128-bit value.
+//
+// The maximum inclusive output hi_lo is 0xFFFFFFFFFFFFFFFE_0000000000000001.
+static inline wuffs_base__multiply_u64__output  //
+wuffs_base__multiply_u64(uint64_t x, uint64_t y) {
+  uint64_t x0 = x & 0xFFFFFFFF;
+  uint64_t x1 = x >> 32;
+  uint64_t y0 = y & 0xFFFFFFFF;
+  uint64_t y1 = y >> 32;
+  uint64_t w0 = x0 * y0;
+  uint64_t t = (x1 * y0) + (w0 >> 32);
+  uint64_t w1 = t & 0xFFFFFFFF;
+  uint64_t w2 = t >> 32;
+  w1 += x0 * y1;
+  wuffs_base__multiply_u64__output o;
+  o.hi = (x1 * y1) + w2 + (w1 >> 32);
+  o.lo = x * y;
+  return o;
+}
+
+  // --------
+
+#if defined(__GNUC__) && (__SIZEOF_LONG__ == 8)
+
+static inline uint32_t  //
+wuffs_base__count_leading_zeroes_u64(uint64_t u) {
+  return u ? ((uint32_t)(__builtin_clzl(u))) : 64u;
+}
+
+#else
+
+static inline uint32_t  //
+wuffs_base__count_leading_zeroes_u64(uint64_t u) {
+  if (u == 0) {
+    return 64;
+  }
+
+  uint32_t n = 0;
+  if ((u >> 32) == 0) {
+    n |= 32;
+    u <<= 32;
+  }
+  if ((u >> 48) == 0) {
+    n |= 16;
+    u <<= 16;
+  }
+  if ((u >> 56) == 0) {
+    n |= 8;
+    u <<= 8;
+  }
+  if ((u >> 60) == 0) {
+    n |= 4;
+    u <<= 4;
+  }
+  if ((u >> 62) == 0) {
+    n |= 2;
+    u <<= 2;
+  }
+  if ((u >> 63) == 0) {
+    n |= 1;
+    u <<= 1;
+  }
+  return n;
+}
+
+#endif  // defined(__GNUC__) && (__SIZEOF_LONG__ == 8)
+
   // --------
 
 #define wuffs_base__load_u8be__no_bounds_check \
diff --git a/internal/cgen/base/io-public.h b/internal/cgen/base/io-public.h
index d28761d..7b535cd 100644
--- a/internal/cgen/base/io-public.h
+++ b/internal/cgen/base/io-public.h
@@ -36,6 +36,7 @@
   wuffs_base__io_buffer_meta meta;
 
 #ifdef __cplusplus
+  inline bool is_valid() const;
   inline void compact();
   inline uint64_t reader_available() const;
   inline uint64_t reader_io_position() const;
@@ -68,6 +69,30 @@
 }
 
 static inline wuffs_base__io_buffer  //
+wuffs_base__make_io_buffer_reader(wuffs_base__slice_u8 s, bool closed) {
+  wuffs_base__io_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = s.len;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = closed;
+  return ret;
+}
+
+static inline wuffs_base__io_buffer  //
+wuffs_base__make_io_buffer_writer(wuffs_base__slice_u8 s) {
+  wuffs_base__io_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = 0;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = false;
+  return ret;
+}
+
+static inline wuffs_base__io_buffer  //
 wuffs_base__empty_io_buffer() {
   wuffs_base__io_buffer ret;
   ret.data.ptr = NULL;
@@ -89,6 +114,18 @@
   return ret;
 }
 
+static inline bool  //
+wuffs_base__io_buffer__is_valid(const wuffs_base__io_buffer* buf) {
+  if (buf) {
+    if (buf->data.ptr) {
+      return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
+    } else {
+      return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
+    }
+  }
+  return false;
+}
+
 // wuffs_base__io_buffer__compact moves any written but unread bytes to the
 // start of the buffer.
 static inline void  //
@@ -127,6 +164,11 @@
 
 #ifdef __cplusplus
 
+inline bool  //
+wuffs_base__io_buffer::is_valid() const {
+  return wuffs_base__io_buffer__is_valid(this);
+}
+
 inline void  //
 wuffs_base__io_buffer::compact() {
   wuffs_base__io_buffer__compact(this);
diff --git a/internal/cgen/base/strconv-impl.c b/internal/cgen/base/strconv-impl.c
index 1d4dbef..06710a1 100644
--- a/internal/cgen/base/strconv-impl.c
+++ b/internal/cgen/base/strconv-impl.c
@@ -312,6 +312,9 @@
 // fixed precision floating point decimal number, augmented with ±infinity
 // values, but it cannot represent NaN (Not a Number).
 //
+// "High precision" means that the mantissa holds 500 decimal digits. 500 is
+// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.
+//
 // An HPD isn't for general purpose arithmetic, only for conversions to and
 // from IEEE 754 double-precision floating point, where the largest and
 // smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.
@@ -331,7 +334,7 @@
 // For example, if num_digits is 3 and digits is "\x07\x08\x09":
 //   - A decimal_point of -2 means ".00789"
 //   - A decimal_point of -1 means ".0789"
-//   - A decimal_point of -0 means ".789"
+//   - A decimal_point of +0 means ".789"
 //   - A decimal_point of +1 means "7.89"
 //   - A decimal_point of +2 means "78.9"
 //   - A decimal_point of +3 means "789."
@@ -861,6 +864,438 @@
 
 // --------
 
+// The wuffs_base__private_implementation__etc_powers_of_10 tables were printed
+// by script/print-mpb-powers-of-10.go. That script has an optional -comments
+// flag, whose output is not copied here, which prints further detail.
+//
+// These tables are used in
+// wuffs_base__private_implementation__medium_prec_bin__assign_from_hpd.
+
+// wuffs_base__private_implementation__big_powers_of_10 contains approximations
+// to the powers of 10, ranging from 1e-348 to 1e+340, with the exponent
+// stepping by 8: -348, -340, -332, ..., -12, -4, +4, +12, ..., +340. Each step
+// consists of three uint32_t elements. There are 87 triples, 87 * 3 = 261.
+//
+// For example, the third approximation, for 1e-332, consists of the uint32_t
+// triple (0x3055AC76, 0x8B16FB20, 0xFFFFFB72). The first two of that triple
+// are a little-endian uint64_t value: 0x8B16FB203055AC76. The last one is an
+// int32_t value: -1166. Together, they represent the approximation:
+//   1e-332 ≈ 0x8B16FB203055AC76 * (2 ** -1166)
+// Similarly, the (0x00000000, 0x9C400000, 0xFFFFFFCE) uint32_t triple means:
+//   1e+4   ≈ 0x9C40000000000000 * (2 **   -50)  // This approx'n is exact.
+// Similarly, the (0xD4C4FB27, 0xED63A231, 0x000000A2) uint32_t triple means:
+//   1e+68  ≈ 0xED63A231D4C4FB27 * (2 **   162)
+static const uint32_t
+    wuffs_base__private_implementation__big_powers_of_10[261] = {
+        0x081C0288, 0xFA8FD5A0, 0xFFFFFB3C, 0xA23EBF76, 0xBAAEE17F, 0xFFFFFB57,
+        0x3055AC76, 0x8B16FB20, 0xFFFFFB72, 0x5DCE35EA, 0xCF42894A, 0xFFFFFB8C,
+        0x55653B2D, 0x9A6BB0AA, 0xFFFFFBA7, 0x3D1A45DF, 0xE61ACF03, 0xFFFFFBC1,
+        0xC79AC6CA, 0xAB70FE17, 0xFFFFFBDC, 0xBEBCDC4F, 0xFF77B1FC, 0xFFFFFBF6,
+        0x416BD60C, 0xBE5691EF, 0xFFFFFC11, 0x907FFC3C, 0x8DD01FAD, 0xFFFFFC2C,
+        0x31559A83, 0xD3515C28, 0xFFFFFC46, 0xADA6C9B5, 0x9D71AC8F, 0xFFFFFC61,
+        0x23EE8BCB, 0xEA9C2277, 0xFFFFFC7B, 0x4078536D, 0xAECC4991, 0xFFFFFC96,
+        0x5DB6CE57, 0x823C1279, 0xFFFFFCB1, 0x4DFB5637, 0xC2109436, 0xFFFFFCCB,
+        0x3848984F, 0x9096EA6F, 0xFFFFFCE6, 0x25823AC7, 0xD77485CB, 0xFFFFFD00,
+        0x97BF97F4, 0xA086CFCD, 0xFFFFFD1B, 0x172AACE5, 0xEF340A98, 0xFFFFFD35,
+        0x2A35B28E, 0xB23867FB, 0xFFFFFD50, 0xD2C63F3B, 0x84C8D4DF, 0xFFFFFD6B,
+        0x1AD3CDBA, 0xC5DD4427, 0xFFFFFD85, 0xBB25C996, 0x936B9FCE, 0xFFFFFDA0,
+        0x7D62A584, 0xDBAC6C24, 0xFFFFFDBA, 0x0D5FDAF6, 0xA3AB6658, 0xFFFFFDD5,
+        0xDEC3F126, 0xF3E2F893, 0xFFFFFDEF, 0xAAFF80B8, 0xB5B5ADA8, 0xFFFFFE0A,
+        0x6C7C4A8B, 0x87625F05, 0xFFFFFE25, 0x34C13053, 0xC9BCFF60, 0xFFFFFE3F,
+        0x91BA2655, 0x964E858C, 0xFFFFFE5A, 0x70297EBD, 0xDFF97724, 0xFFFFFE74,
+        0xB8E5B88F, 0xA6DFBD9F, 0xFFFFFE8F, 0x88747D94, 0xF8A95FCF, 0xFFFFFEA9,
+        0x8FA89BCF, 0xB9447093, 0xFFFFFEC4, 0xBF0F156B, 0x8A08F0F8, 0xFFFFFEDF,
+        0x653131B6, 0xCDB02555, 0xFFFFFEF9, 0xD07B7FAC, 0x993FE2C6, 0xFFFFFF14,
+        0x2A2B3B06, 0xE45C10C4, 0xFFFFFF2E, 0x697392D3, 0xAA242499, 0xFFFFFF49,
+        0x8300CA0E, 0xFD87B5F2, 0xFFFFFF63, 0x92111AEB, 0xBCE50864, 0xFFFFFF7E,
+        0x6F5088CC, 0x8CBCCC09, 0xFFFFFF99, 0xE219652C, 0xD1B71758, 0xFFFFFFB3,
+        0x00000000, 0x9C400000, 0xFFFFFFCE, 0x00000000, 0xE8D4A510, 0xFFFFFFE8,
+        0xAC620000, 0xAD78EBC5, 0x00000003, 0xF8940984, 0x813F3978, 0x0000001E,
+        0xC90715B3, 0xC097CE7B, 0x00000038, 0x7BEA5C70, 0x8F7E32CE, 0x00000053,
+        0xABE98068, 0xD5D238A4, 0x0000006D, 0x179A2245, 0x9F4F2726, 0x00000088,
+        0xD4C4FB27, 0xED63A231, 0x000000A2, 0x8CC8ADA8, 0xB0DE6538, 0x000000BD,
+        0x1AAB65DB, 0x83C7088E, 0x000000D8, 0x42711D9A, 0xC45D1DF9, 0x000000F2,
+        0xA61BE758, 0x924D692C, 0x0000010D, 0x1A708DEA, 0xDA01EE64, 0x00000127,
+        0x9AEF774A, 0xA26DA399, 0x00000142, 0xB47D6B85, 0xF209787B, 0x0000015C,
+        0x79DD1877, 0xB454E4A1, 0x00000177, 0x5B9BC5C2, 0x865B8692, 0x00000192,
+        0xC8965D3D, 0xC83553C5, 0x000001AC, 0xFA97A0B3, 0x952AB45C, 0x000001C7,
+        0x99A05FE3, 0xDE469FBD, 0x000001E1, 0xDB398C25, 0xA59BC234, 0x000001FC,
+        0xA3989F5C, 0xF6C69A72, 0x00000216, 0x54E9BECE, 0xB7DCBF53, 0x00000231,
+        0xF22241E2, 0x88FCF317, 0x0000024C, 0xD35C78A5, 0xCC20CE9B, 0x00000266,
+        0x7B2153DF, 0x98165AF3, 0x00000281, 0x971F303A, 0xE2A0B5DC, 0x0000029B,
+        0x5CE3B396, 0xA8D9D153, 0x000002B6, 0xA4A7443C, 0xFB9B7CD9, 0x000002D0,
+        0xA7A44410, 0xBB764C4C, 0x000002EB, 0xB6409C1A, 0x8BAB8EEF, 0x00000306,
+        0xA657842C, 0xD01FEF10, 0x00000320, 0xE9913129, 0x9B10A4E5, 0x0000033B,
+        0xA19C0C9D, 0xE7109BFB, 0x00000355, 0x623BF429, 0xAC2820D9, 0x00000370,
+        0x7AA7CF85, 0x80444B5E, 0x0000038B, 0x03ACDD2D, 0xBF21E440, 0x000003A5,
+        0x5E44FF8F, 0x8E679C2F, 0x000003C0, 0x9C8CB841, 0xD433179D, 0x000003DA,
+        0xB4E31BA9, 0x9E19DB92, 0x000003F5, 0xBADF77D9, 0xEB96BF6E, 0x0000040F,
+        0x9BF0EE6B, 0xAF87023B, 0x0000042A,
+};
+
+// wuffs_base__private_implementation__small_powers_of_10 contains
+// approximations to the powers of 10, ranging from 1e+0 to 1e+7, with the
+// exponent stepping by 1. Each step consists of three uint32_t elements.
+//
+// For example, the third approximation, for 1e+2, consists of the uint32_t
+// triple (0x00000000, 0xC8000000, 0xFFFFFFC7). The first two of that triple
+// are a little-endian uint64_t value: 0xC800000000000000. The last one is an
+// int32_t value: -57. Together, they represent the approximation:
+//   1e+2   ≈ 0xC800000000000000 * (2 **   -57)  // This approx'n is exact.
+// Similarly, the (0x00000000, 0x9C400000, 0xFFFFFFCE) uint32_t triple means:
+//   1e+4   ≈ 0x9C40000000000000 * (2 **   -50)  // This approx'n is exact.
+static const uint32_t
+    wuffs_base__private_implementation__small_powers_of_10[24] = {
+        0x00000000, 0x80000000, 0xFFFFFFC1, 0x00000000, 0xA0000000, 0xFFFFFFC4,
+        0x00000000, 0xC8000000, 0xFFFFFFC7, 0x00000000, 0xFA000000, 0xFFFFFFCA,
+        0x00000000, 0x9C400000, 0xFFFFFFCE, 0x00000000, 0xC3500000, 0xFFFFFFD1,
+        0x00000000, 0xF4240000, 0xFFFFFFD4, 0x00000000, 0x98968000, 0xFFFFFFD8,
+};
+
+// wuffs_base__private_implementation__f64_powers_of_10 holds powers of 10 that
+// can be exactly represented by a float64 (what C calls a double).
+static const double wuffs_base__private_implementation__f64_powers_of_10[23] = {
+    1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,  1e10, 1e11,
+    1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
+};
+
+// --------
+
+// wuffs_base__private_implementation__medium_prec_bin (abbreviated as MPB) is
+// a fixed precision floating point binary number. Unlike IEEE 754 Floating
+// Point, it cannot represent infinity or NaN (Not a Number).
+//
+// "Medium precision" means that the mantissa holds 64 binary digits, a little
+// more than "double precision", and sizeof(MPB) > sizeof(double). 64 is
+// obviously the number of bits in a uint64_t.
+//
+// An MPB isn't for general purpose arithmetic, only for conversions to and
+// from IEEE 754 double-precision floating point.
+//
+// There is no implicit mantissa bit. The mantissa field is zero if and only if
+// the overall floating point value is ±0. An MPB is normalized if the mantissa
+// is zero or its high bit (the 1<<63 bit) is set.
+//
+// There is no negative bit. An MPB can only represent non-negative numbers.
+//
+// The "all fields are zero" value is valid, and represents the number +0.
+//
+// This is the "Do It Yourself Floating Point" data structure from Loitsch,
+// "Printing Floating-Point Numbers Quickly and Accurately with Integers"
+// (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
+//
+// Florian Loitsch is also the primary contributor to
+// https://github.com/google/double-conversion
+typedef struct {
+  uint64_t mantissa;
+  int32_t exp2;
+} wuffs_base__private_implementation__medium_prec_bin;
+
+static uint32_t  //
+wuffs_base__private_implementation__medium_prec_bin__normalize(
+    wuffs_base__private_implementation__medium_prec_bin* m) {
+  if (m->mantissa == 0) {
+    return 0;
+  }
+  uint32_t shift = wuffs_base__count_leading_zeroes_u64(m->mantissa);
+  m->mantissa <<= shift;
+  m->exp2 -= (int32_t)shift;
+  return shift;
+}
+
+// wuffs_base__private_implementation__medium_prec_bin__mul_pow_10 sets m to be
+// (m * pow), where pow comes from an etc_powers_of_10 triple starting at p.
+//
+// The result is rounded, but not necessarily normalized.
+//
+// Preconditions:
+//  - m is non-NULL.
+//  - m->mantissa is non-zero.
+//  - m->mantissa's high bit is set (i.e. m is normalized).
+//
+// The etc_powers_of_10 triple is already normalized.
+static void  //
+wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(
+    wuffs_base__private_implementation__medium_prec_bin* m,
+    const uint32_t* p) {
+  uint64_t p_mantissa = ((uint64_t)p[0]) | (((uint64_t)p[1]) << 32);
+  int32_t p_exp2 = (int32_t)p[2];
+
+  wuffs_base__multiply_u64__output o =
+      wuffs_base__multiply_u64(m->mantissa, p_mantissa);
+  // Round the mantissa up. It cannot overflow because the maximum possible
+  // value of o.hi is 0xFFFFFFFFFFFFFFFE.
+  m->mantissa = o.hi + (o.lo >> 63);
+  m->exp2 = m->exp2 + p_exp2 + 64;
+}
+
+// wuffs_base__private_implementation__medium_prec_bin__as_f64 converts m to a
+// double (what C calls a double-precision float64).
+//
+// Preconditions:
+//  - m is non-NULL.
+//  - m->mantissa is non-zero.
+//  - m->mantissa's high bit is set (i.e. m is normalized).
+static double  //
+wuffs_base__private_implementation__medium_prec_bin__as_f64(
+    const wuffs_base__private_implementation__medium_prec_bin* m,
+    bool negative) {
+  uint64_t mantissa64 = m->mantissa;
+  // An mpb's mantissa has the implicit (binary) decimal point at the right
+  // hand end of the mantissa's explicit digits. A double-precision's mantissa
+  // has that decimal point near the left hand end. There's also an explicit
+  // versus implicit leading 1 bit (binary digit). Together, the difference in
+  // semantics corresponds to adding 63.
+  int32_t exp2 = m->exp2 + 63;
+
+  // Ensure that exp2 is at least -1022, the minimum double-precision exponent
+  // for normal (as opposed to subnormal) numbers.
+  if (-1022 > exp2) {
+    uint32_t n = (uint32_t)(-1022 - exp2);
+    mantissa64 >>= n;
+    exp2 += (int32_t)n;
+  }
+
+  // Extract the (1 + 52) bits from the 64-bit mantissa64. 52 is the number of
+  // explicit mantissa bits in a double-precision f64.
+  //
+  // Before, we have 64 bits and due to normalization, the high bit 'H' is 1.
+  // 63        55        47       etc     15        7
+  // H210_9876_5432_1098_7654_etc_etc_etc_5432_1098_7654_3210
+  // ++++_++++_++++_++++_++++_etc_etc_etc_++++_+..._...._....  Kept bits.
+  // ...._...._...H_2109_8765_etc_etc_etc_6543_2109_8765_4321  After shifting.
+  // After, we have 53 bits (and bit #52 is this 'H' bit).
+  uint64_t mantissa53 = mantissa64 >> 11;
+
+  // Round up if the old bit #10 (the highest bit dropped by shifting) was set.
+  // We also fix any overflow from rounding up.
+  if (mantissa64 & 1024) {
+    mantissa53++;
+    if ((mantissa53 >> 53) != 0) {
+      mantissa53 >>= 1;
+      exp2++;
+    }
+  }
+
+  // Handle double-precision infinity (a nominal exponent of 1024) and
+  // subnormals (an exponent of -1023 and no implicit mantissa bit, bit #52).
+  if (exp2 >= 1024) {
+    mantissa53 = 0;
+    exp2 = 1024;
+  } else if ((mantissa53 >> 52) == 0) {
+    exp2 = -1023;
+  }
+
+  // Pack the bits and return.
+  const int32_t f64_bias = -1023;
+  uint64_t exp2_bits =
+      (uint64_t)((exp2 - f64_bias) & 0x07FF);           // (1 << 11) - 1.
+  uint64_t bits = (mantissa53 & 0x000FFFFFFFFFFFFF) |   // (1 << 52) - 1.
+                  (exp2_bits << 52) |                   //
+                  (negative ? 0x8000000000000000 : 0);  // (1 << 63).
+  return wuffs_base__ieee_754_bit_representation__to_f64(bits);
+}
+
+// wuffs_base__private_implementation__medium_prec_bin__parse_number_f64
+// converts from an HPD to a double, using an MPB as scratch space. It returns
+// a NULL status.repr if there is no ambiguity in the truncation or rounding to
+// a float64 (an IEEE 754 double-precision floating point value).
+//
+// It may modify m even if it returns a non-NULL status.repr.
+static wuffs_base__result_f64  //
+wuffs_base__private_implementation__medium_prec_bin__parse_number_f64(
+    wuffs_base__private_implementation__medium_prec_bin* m,
+    const wuffs_base__private_implementation__high_prec_dec* h,
+    bool skip_fast_path_for_tests) {
+  do {
+    // m->mantissa is a uint64_t, which is an integer approximation to a
+    // rational value - h's underlying digits after m's normalization. This
+    // error is an upper bound on the difference between the approximate and
+    // actual value.
+    //
+    // The DiyFpStrtod function in https://github.com/google/double-conversion
+    // uses a finer grain (1/8th of the ULP, Unit in the Last Place) when
+    // tracking error. This implementation is coarser (1 ULP) but simpler.
+    //
+    // It is an error in the "numerical approximation" sense, not in the
+    // typical programming sense (as in "bad input" or "a result type").
+    uint64_t error = 0;
+
+    // Convert up to 19 decimal digits (in h->digits) to 64 binary digits (in
+    // m->mantissa): (1e19 < (1<<64)) and ((1<<64) < 1e20). If we have more
+    // than 19 digits, we're truncating (with error).
+    uint32_t i;
+    uint32_t i_end = h->num_digits;
+    if (i_end > 19) {
+      i_end = 19;
+      error = 1;
+    }
+    uint64_t mantissa = 0;
+    for (i = 0; i < i_end; i++) {
+      mantissa = (10 * mantissa) + h->digits[i];
+    }
+    m->mantissa = mantissa;
+    m->exp2 = 0;
+
+    // Check that exp10 lies in the (big_powers_of_10 + small_powers_of_10)
+    // range, -348 ..= +347, stepping big_powers_of_10 by 8 (which is 87
+    // triples) and small_powers_of_10 by 1 (which is 8 triples).
+    int32_t exp10 = h->decimal_point - ((int32_t)(i_end));
+    if (exp10 < -348) {
+      goto fail;
+    }
+    uint32_t bpo10 = ((uint32_t)(exp10 + 348)) / 8;
+    uint32_t spo10 = ((uint32_t)(exp10 + 348)) % 8;
+    if (bpo10 >= 87) {
+      goto fail;
+    }
+
+    // Try a fast path, if float64 math would be exact.
+    //
+    // 15 is such that 1e15 can be losslessly represented in a float64
+    // mantissa: (1e15 < (1<<53)) and ((1<<53) < 1e16).
+    //
+    // 22 is the maximum valid index for the
+    // wuffs_base__private_implementation__f64_powers_of_10 array.
+    do {
+      if (skip_fast_path_for_tests || ((mantissa >> 52) != 0)) {
+        break;
+      }
+      double d = (double)mantissa;
+
+      if (exp10 == 0) {
+        wuffs_base__result_f64 ret;
+        ret.status.repr = NULL;
+        ret.value = h->negative ? -d : +d;
+        return ret;
+
+      } else if (exp10 > 0) {
+        if (exp10 > 22) {
+          if (exp10 > (15 + 22)) {
+            break;
+          }
+          // If exp10 is in the range 23 ..= 37, try moving a few of the zeroes
+          // from the exponent to the mantissa. If we're still under 1e15, we
+          // haven't truncated any mantissa bits.
+          if (exp10 > 22) {
+            d *= wuffs_base__private_implementation__f64_powers_of_10[exp10 -
+                                                                      22];
+            exp10 = 22;
+            if (d >= 1e15) {
+              break;
+            }
+          }
+        }
+        d *= wuffs_base__private_implementation__f64_powers_of_10[exp10];
+        wuffs_base__result_f64 ret;
+        ret.status.repr = NULL;
+        ret.value = h->negative ? -d : +d;
+        return ret;
+
+      } else {  // "if (exp10 < 0)" is effectively "if (true)" here.
+        if (exp10 < -22) {
+          break;
+        }
+        d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];
+        wuffs_base__result_f64 ret;
+        ret.status.repr = NULL;
+        ret.value = h->negative ? -d : +d;
+        return ret;
+      }
+    } while (0);
+
+    // Normalize (and scale the error).
+    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);
+
+    // Multiplying two MPB values nominally multiplies two mantissas, call them
+    // A and B, which are integer approximations to the precise values (A+a)
+    // and (B+b) for some error terms a and b.
+    //
+    // MPB multiplication calculates (((A+a) * (B+b)) >> 64) to be ((A*B) >>
+    // 64). Shifting (truncating) and rounding introduces further error. The
+    // difference between the calculated result:
+    //  ((A*B                  ) >> 64)
+    // and the true result:
+    //  ((A*B + A*b + a*B + a*b) >> 64)   + rounding_error
+    // is:
+    //  ((      A*b + a*B + a*b) >> 64)   + rounding_error
+    // which can be re-grouped as:
+    //  ((A*b) >> 64) + ((a*(B+b)) >> 64) + rounding_error
+    //
+    // Now, let A and a be "m->mantissa" and "error", and B and b be the
+    // pre-calculated power of 10. A and B are both less than (1 << 64), a is
+    // the "error" local variable and b is less than 1.
+    //
+    // An upper bound (in absolute value) on ((A*b) >> 64) is therefore 1.
+    //
+    // An upper bound on ((a*(B+b)) >> 64) is a, also known as error.
+    //
+    // Finally, the rounding_error is at most 1.
+    //
+    // In total, calling mpb__mul_pow_10 will raise the worst-case error by 2.
+    // The subsequent re-normalization can multiply that by a further factor.
+
+    // Multiply by small_powers_of_10[etc].
+    wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(
+        m, &wuffs_base__private_implementation__small_powers_of_10[3 * spo10]);
+    error += 2;
+    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);
+
+    // Multiply by big_powers_of_10[etc].
+    wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(
+        m, &wuffs_base__private_implementation__big_powers_of_10[3 * bpo10]);
+    error += 2;
+    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);
+
+    // We have a good approximation of h, but we still have to check whether
+    // the error is small enough. Equivalently, whether the number of surplus
+    // mantissa bits (the bits dropped when going from m's 64 mantissa bits to
+    // the smaller number of double-precision mantissa bits) would always round
+    // up or down, even when perturbed by ±error. We start at 11 surplus bits
+    // (m has 64, double-precision has 1+52), but it can be higher for
+    // subnormals.
+    //
+    // In many cases, the error is small enough and we return true.
+    const int32_t f64_bias = -1023;
+    int32_t subnormal_exp2 = f64_bias - 63;
+    uint32_t surplus_bits = 11;
+    if (subnormal_exp2 >= m->exp2) {
+      surplus_bits += 1 + ((uint32_t)(subnormal_exp2 - m->exp2));
+    }
+
+    uint64_t surplus_mask =
+        (((uint64_t)1) << surplus_bits) - 1;  // e.g. 0x07FF.
+    uint64_t surplus = m->mantissa & surplus_mask;
+    uint64_t halfway = ((uint64_t)1) << (surplus_bits - 1);  // e.g. 0x0400.
+
+    // Do the final calculation in *signed* arithmetic.
+    int64_t i_surplus = (int64_t)surplus;
+    int64_t i_halfway = (int64_t)halfway;
+    int64_t i_error = (int64_t)error;
+
+    if ((i_surplus > (i_halfway - i_error)) &&
+        (i_surplus < (i_halfway + i_error))) {
+      goto fail;
+    }
+
+    wuffs_base__result_f64 ret;
+    ret.status.repr = NULL;
+    ret.value = wuffs_base__private_implementation__medium_prec_bin__as_f64(
+        m, h->negative);
+    return ret;
+  } while (0);
+
+fail:
+  do {
+    wuffs_base__result_f64 ret;
+    ret.status.repr = "#base: mpb__parse_number_f64 failed";
+    ret.value = 0;
+    return ret;
+  } while (0);
+}
+
+// --------
+
 wuffs_base__result_f64  //
 wuffs_base__parse_number_f64_special(wuffs_base__slice_u8 s,
                                      const char* fallback_status_repr) {
@@ -964,6 +1399,7 @@
 
 wuffs_base__result_f64  //
 wuffs_base__parse_number_f64(wuffs_base__slice_u8 s) {
+  wuffs_base__private_implementation__medium_prec_bin m;
   wuffs_base__private_implementation__high_prec_dec h;
 
   do {
@@ -990,10 +1426,17 @@
       goto infinity;
     }
 
+    wuffs_base__result_f64 mpb_result =
+        wuffs_base__private_implementation__medium_prec_bin__parse_number_f64(
+            &m, &h, false);
+    if (mpb_result.status.repr == NULL) {
+      return mpb_result;
+    }
+
     // Scale by powers of 2 until we're in the range [½ .. 1], which gives us
     // our exponent (in base-2). First we shift right, possibly a little too
     // far, ending with a value certainly below 1 and possibly below ½...
-    const int32_t bias = -1023;
+    const int32_t f64_bias = -1023;
     int32_t exp2 = 0;
     while (h.decimal_point > 0) {
       uint32_t n = (uint32_t)(+h.decimal_point);
@@ -1037,9 +1480,9 @@
     // We're in the range [½ .. 1] but f64 uses [1 .. 2].
     exp2--;
 
-    // The minimum normal exponent is (bias + 1).
-    while ((bias + 1) > exp2) {
-      uint32_t n = (uint32_t)((bias + 1) - exp2);
+    // The minimum normal exponent is (f64_bias + 1).
+    while ((f64_bias + 1) > exp2) {
+      uint32_t n = (uint32_t)((f64_bias + 1) - exp2);
       if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
         n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
       }
@@ -1048,7 +1491,7 @@
     }
 
     // Check for overflow.
-    if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1.
+    if ((exp2 - f64_bias) >= 0x07FF) {  // (1 << 11) - 1.
       goto infinity;
     }
 
@@ -1061,21 +1504,22 @@
     if ((man2 >> 53) != 0) {
       man2 >>= 1;
       exp2++;
-      if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1.
+      if ((exp2 - f64_bias) >= 0x07FF) {  // (1 << 11) - 1.
         goto infinity;
       }
     }
 
     // Handle subnormal numbers.
     if ((man2 >> 52) == 0) {
-      exp2 = bias;
+      exp2 = f64_bias;
     }
 
     // Pack the bits and return.
-    uint64_t exp2_bits = (uint64_t)((exp2 - bias) & 0x07FF);  // (1 << 11) - 1.
-    uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |             // (1 << 52) - 1.
-                    (exp2_bits << 52) |                       //
-                    (h.negative ? 0x8000000000000000 : 0);    // (1 << 63).
+    uint64_t exp2_bits =
+        (uint64_t)((exp2 - f64_bias) & 0x07FF);             // (1 << 11) - 1.
+    uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |           // (1 << 52) - 1.
+                    (exp2_bits << 52) |                     //
+                    (h.negative ? 0x8000000000000000 : 0);  // (1 << 63).
 
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
@@ -1104,6 +1548,46 @@
   } while (0);
 }
 
+// ---------------- Hexadecimal
+
+size_t  //
+wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src) {
+  size_t src_len2 = src.len / 2;
+  size_t len = dst.len < src_len2 ? dst.len : src_len2;
+  uint8_t* d = dst.ptr;
+  uint8_t* s = src.ptr;
+  size_t n = len;
+
+  while (n--) {
+    *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |
+                   (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));
+    d += 1;
+    s += 2;
+  }
+
+  return len;
+}
+
+size_t  //
+wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src) {
+  size_t src_len4 = src.len / 4;
+  size_t len = dst.len < src_len4 ? dst.len : src_len4;
+  uint8_t* d = dst.ptr;
+  uint8_t* s = src.ptr;
+  size_t n = len;
+
+  while (n--) {
+    *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |
+                   (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F));
+    d += 1;
+    s += 4;
+  }
+
+  return len;
+}
+
 // ---------------- Unicode and UTF-8
 
 size_t  //
diff --git a/internal/cgen/base/strconv-public.h b/internal/cgen/base/strconv-public.h
index 65c60ec..c6f7ad6 100644
--- a/internal/cgen/base/strconv-public.h
+++ b/internal/cgen/base/strconv-public.h
@@ -120,7 +120,35 @@
   return f;
 }
 
-  // ---------------- Unicode and UTF-8
+// ---------------- Hexadecimal
+
+// wuffs_base__hexadecimal__decode2 converts "6A6b" to "jk", where e.g. 'j' is
+// U+006A. There are 2 source bytes for every destination byte.
+//
+// It returns the number of dst bytes written: the minimum of dst.len and
+// (src.len / 2). Excess source bytes are ignored.
+//
+// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
+// repeated. It may write nonsense bytes if not, although it will not read or
+// write out of bounds.
+size_t  //
+wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src);
+
+// wuffs_base__hexadecimal__decode4 converts "\\x6A\\x6b" to "jk", where e.g.
+// 'j' is U+006A. There are 4 source bytes for every destination byte.
+//
+// It returns the number of dst bytes written: the minimum of dst.len and
+// (src.len / 4). Excess source bytes are ignored.
+//
+// It assumes that the src bytes are two ignored bytes and then two hexadecimal
+// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
+// although it will not read or write out of bounds.
+size_t  //
+wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src);
+
+// ---------------- Unicode and UTF-8
 
 #define WUFFS_BASE__UNICODE_CODE_POINT__MIN_INCL 0x00000000
 #define WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL 0x0010FFFF
diff --git a/internal/cgen/base/token-public.h b/internal/cgen/base/token-public.h
index 31f02e7..1c4c7c2 100644
--- a/internal/cgen/base/token-public.h
+++ b/internal/cgen/base/token-public.h
@@ -180,6 +180,11 @@
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004
 
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF 0x00010
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF 0x00020
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN 0x00040
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN 0x00080
+
 // The number 300 might be represented as "\x01\x2C", "\x2C\x01\x00\x00" or
 // "300", which are big-endian, little-endian or text. For binary formats, the
 // token length discriminates e.g. u16 little-endian vs u32 little-endian.
@@ -311,6 +316,7 @@
   wuffs_base__token_buffer_meta meta;
 
 #ifdef __cplusplus
+  inline bool is_valid() const;
   inline void compact();
   inline uint64_t reader_available() const;
   inline uint64_t reader_token_position() const;
@@ -343,6 +349,30 @@
 }
 
 static inline wuffs_base__token_buffer  //
+wuffs_base__make_token_buffer_reader(wuffs_base__slice_token s, bool closed) {
+  wuffs_base__token_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = s.len;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = closed;
+  return ret;
+}
+
+static inline wuffs_base__token_buffer  //
+wuffs_base__make_token_buffer_writer(wuffs_base__slice_token s) {
+  wuffs_base__token_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = 0;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = false;
+  return ret;
+}
+
+static inline wuffs_base__token_buffer  //
 wuffs_base__empty_token_buffer() {
   wuffs_base__token_buffer ret;
   ret.data.ptr = NULL;
@@ -364,6 +394,18 @@
   return ret;
 }
 
+static inline bool  //
+wuffs_base__token_buffer__is_valid(const wuffs_base__token_buffer* buf) {
+  if (buf) {
+    if (buf->data.ptr) {
+      return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
+    } else {
+      return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
+    }
+  }
+  return false;
+}
+
 // wuffs_base__token_buffer__compact moves any written but unread tokens to the
 // start of the buffer.
 static inline void  //
@@ -407,6 +449,11 @@
 
 #ifdef __cplusplus
 
+inline bool  //
+wuffs_base__token_buffer::is_valid() const {
+  return wuffs_base__token_buffer__is_valid(this);
+}
+
 inline void  //
 wuffs_base__token_buffer::compact() {
   wuffs_base__token_buffer__compact(this);
diff --git a/internal/cgen/builtin.go b/internal/cgen/builtin.go
index a6676fc..06cc079 100644
--- a/internal/cgen/builtin.go
+++ b/internal/cgen/builtin.go
@@ -177,6 +177,14 @@
 		b.writeb(')')
 		return nil
 
+	case t.IDPeekU64LEAt:
+		b.printf("wuffs_base__load_u64le__no_bounds_check(%s%s + ", iopPrefix, name)
+		if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
+			return err
+		}
+		b.writeb(')')
+		return nil
+
 	case t.IDPosition:
 		b.printf("wuffs_base__u64__sat_add(%s->meta.pos, ((uint64_t)(%s%s - %s%s)))",
 			name, iopPrefix, name, io0Prefix, name)
@@ -711,12 +719,28 @@
 			scratchName := fmt.Sprintf("self->private_data.%s%s[0].scratch",
 				sPrefix, g.currFunk.astFunc.FuncName().Str(g.tm))
 
+			args := n.Args()
 			b.printf("%s = (((uint64_t)(", scratchName)
-			if err := g.writeExpr(b, n.Args()[0].AsArg().Value(), depth); err != nil {
+			if cv := args[0].AsArg().Value().ConstValue(); (cv == nil) || (cv.Sign() != 0) {
+				if err := g.writeExpr(b, args[0].AsArg().Value(), depth); err != nil {
+					return err
+				}
+				b.writes(")) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) | (((uint64_t)(")
+			}
+
+			if err := g.writeExpr(b, args[1].AsArg().Value(), depth); err != nil {
 				return err
 			}
-			b.writes(")) << WUFFS_BASE__TOKEN__VLL__SHIFT) | (((uint64_t)(")
-			if err := g.writeExpr(b, n.Args()[1].AsArg().Value(), depth); err != nil {
+			b.writes(")) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) | (((uint64_t)(")
+
+			if cv := args[2].AsArg().Value().ConstValue(); (cv == nil) || (cv.Sign() != 0) {
+				if err := g.writeExpr(b, args[2].AsArg().Value(), depth); err != nil {
+					return err
+				}
+				b.writes(")) << WUFFS_BASE__TOKEN__LINK__SHIFT) | (((uint64_t)(")
+			}
+
+			if err := g.writeExpr(b, args[3].AsArg().Value(), depth); err != nil {
 				return err
 			}
 			b.writes(")) << WUFFS_BASE__TOKEN__LENGTH__SHIFT);\n")
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 9d9a653..437a056 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -79,14 +79,14 @@
 	"wuffs_base__parse_number__hexadecimal_digits[*p++];\n    if (v == 0) {\n      goto fail_bad_argument;\n    }\n    v &= 0x0F;\n\n    for (; p < q; p++) {\n      if (*p == '_') {\n        continue;\n      }\n      uint8_t digit = wuffs_base__parse_number__hexadecimal_digits[*p];\n      if (digit == 0) {\n        goto fail_bad_argument;\n      }\n      digit &= 0x0F;\n      if ((v >> 60) != 0) {\n        goto fail_out_of_bounds;\n      }\n      v = (v << 4) | ((uint64_t)(digit));\n    }\n\n    wuffs_base__result_u64 ret;\n    ret.status.repr = NULL;\n    ret.value = v;\n    return ret;\n  } while (0);\n\nok_zero:\n  do {\n    wuffs_base__result_u64 ret;\n    ret.status.repr = NULL;\n    ret.value = 0;\n    return ret;\n  } while (0);\n\nfail_bad_argument:\n  do {\n    wuffs_base__result_u64 ret;\n    ret.status.repr = wuffs_base__error__bad_argument;\n    ret.value = 0;\n    return ret;\n  } while (0);\n\nfail_out_of_bounds:\n  do {\n    wuffs_base__result_u64 ret;\n    ret.status.repr = wuffs_base__error__out_of_bounds;\n    ret.value = 0;\n    return ret;\n " +
 	" } while (0);\n}\n\n  " +
 	"" +
-	"// ---------------- IEEE 754 Floating Point\n\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 1023\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 500\n\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N\n// such that ((10 << N) < (1 << 64)).\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60\n\n// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a\n// fixed precision floating point decimal number, augmented with ±infinity\n// values, but it cannot represent NaN (Not a Number).\n//\n// An HPD isn't for general purpose arithmetic, only for conversions to and\n// from IEEE 754 double-precision floating point, where the largest and\n// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.\n// HPD exponents above +1023 mean infinity, below -1023 mean zero. The ±1023\n// bounds are further away from zero than ±(324 + 500), where 500 and 1023 is\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRE" +
-	"CISION and\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.\n//\n// digits[.. num_digits] are the number's digits in big-endian order. The\n// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7'\n// is the ASCII value 0x37.\n//\n// decimal_point is the index (within digits) of the decimal point. It may be\n// negative or be larger than num_digits, in which case the explicit digits are\n// padded with implicit zeroes.\n//\n// For example, if num_digits is 3 and digits is \"\\x07\\x08\\x09\":\n//   - A decimal_point of -2 means \".00789\"\n//   - A decimal_point of -1 means \".0789\"\n//   - A decimal_point of -0 means \".789\"\n//   - A decimal_point of +1 means \"7.89\"\n//   - A decimal_point of +2 means \"78.9\"\n//   - A decimal_point of +3 means \"789.\"\n//   - A decimal_point of +4 means \"7890.\"\n//   - A decimal_point of +5 means \"78900.\"\n//\n// As above, a decimal_point higher than +1023 means that the overall value is\n// infinity, lower than -1023 means zero.\n//\n// negative is a sign bit. An HP" +
-	"D can distinguish positive and negative zero.\n//\n// truncated is whether there are more than\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at\n// least one of those extra digits are non-zero. The existence of long-tail\n// digits can affect rounding.\n//\n// The \"all fields are zero\" value is valid, and represents the number +0.\ntypedef struct {\n  uint32_t num_digits;\n  int32_t decimal_point;\n  bool negative;\n  bool truncated;\n  uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION];\n} wuffs_base__private_implementation__high_prec_dec;\n\n// wuffs_base__private_implementation__high_prec_dec__trim trims trailing\n// zeroes from the h->digits[.. h->num_digits] slice. They have no benefit,\n// since we explicitly track h->decimal_point.\n//\n// Preconditions:\n//  - h is non-NULL.\nstatic inline void  //\nwuffs_base__private_implementation__high_prec_dec__trim(\n    wuffs_base__private_implementation__high_prec_dec* h) {\n  while ((h->num_digits > 0) && (h->digits[h->num_digits - 1" +
-	"] == 0)) {\n    h->num_digits--;\n  }\n}\n\nstatic wuffs_base__status  //\nwuffs_base__private_implementation__high_prec_dec__parse(\n    wuffs_base__private_implementation__high_prec_dec* h,\n    wuffs_base__slice_u8 s) {\n  if (!h) {\n    return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n  }\n  h->num_digits = 0;\n  h->decimal_point = 0;\n  h->negative = false;\n  h->truncated = false;\n\n  uint8_t* p = s.ptr;\n  uint8_t* q = s.ptr + s.len;\n\n  for (; (p < q) && (*p == '_'); p++) {\n  }\n  if (p >= q) {\n    return wuffs_base__make_status(wuffs_base__error__bad_argument);\n  }\n\n  // Parse sign.\n  do {\n    if (*p == '+') {\n      p++;\n    } else if (*p == '-') {\n      h->negative = true;\n      p++;\n    } else {\n      break;\n    }\n    for (; (p < q) && (*p == '_'); p++) {\n    }\n  } while (0);\n\n  // Parse digits.\n  uint32_t nd = 0;\n  int32_t dp = 0;\n  bool saw_digits = false;\n  bool saw_non_zero_digits = false;\n  bool saw_dot = false;\n  for (; p < q; p++) {\n    if (*p == '_') {\n      // No-op.\n\n    } else if ((*p == '" +
-	".') || (*p == ',')) {\n      // As per https://en.wikipedia.org/wiki/Decimal_separator, both '.' or\n      // ',' are commonly used. We just parse either, regardless of LOCALE.\n      if (saw_dot) {\n        return wuffs_base__make_status(wuffs_base__error__bad_argument);\n      }\n      saw_dot = true;\n      dp = (int32_t)nd;\n\n    } else if ('0' == *p) {\n      if (!saw_dot && !saw_non_zero_digits && saw_digits) {\n        // We don't allow unnecessary leading zeroes: \"000123\" or \"0644\".\n        return wuffs_base__make_status(wuffs_base__error__bad_argument);\n      }\n      saw_digits = true;\n      if (nd == 0) {\n        // Track leading zeroes implicitly.\n        dp--;\n      } else if (nd <\n                 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {\n        h->digits[nd++] = 0;\n      } else {\n        // Long-tail zeroes are ignored.\n      }\n\n    } else if (('0' < *p) && (*p <= '9')) {\n      if (!saw_dot && !saw_non_zero_digits && saw_digits) {\n        // We don't allow unnecessary leading zeroes: \"" +
-	"000123\" or \"0644\".\n        return wuffs_base__make_status(wuffs_base__error__bad_argument);\n      }\n      saw_digits = true;\n      saw_non_zero_digits = true;\n      if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {\n        h->digits[nd++] = (uint8_t)(*p - '0');\n      } else {\n        // Long-tail non-zeroes set the truncated bit.\n        h->truncated = true;\n      }\n\n    } else {\n      break;\n    }\n  }\n\n  if (!saw_digits) {\n    return wuffs_base__make_status(wuffs_base__error__bad_argument);\n  }\n  if (!saw_dot) {\n    dp = (int32_t)nd;\n  }\n\n  // Parse exponent.\n  if ((p < q) && ((*p == 'E') || (*p == 'e'))) {\n    p++;\n    for (; (p < q) && (*p == '_'); p++) {\n    }\n    if (p >= q) {\n      return wuffs_base__make_status(wuffs_base__error__bad_argument);\n    }\n\n    int32_t exp_sign = +1;\n    if (*p == '+') {\n      p++;\n    } else if (*p == '-') {\n      exp_sign = -1;\n      p++;\n    }\n\n    int32_t exp = 0;\n    const int32_t exp_large =\n        WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_P" +
-	"OINT__RANGE +\n        WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;\n    bool saw_exp_digits = false;\n    for (; p < q; p++) {\n      if (*p == '_') {\n        // No-op.\n      } else if (('0' <= *p) && (*p <= '9')) {\n        saw_exp_digits = true;\n        if (exp < exp_large) {\n          exp = (10 * exp) + ((int32_t)(*p - '0'));\n        }\n      } else {\n        break;\n      }\n    }\n    if (!saw_exp_digits) {\n      return wuffs_base__make_status(wuffs_base__error__bad_argument);\n    }\n    dp += exp_sign * exp;\n  }\n\n  // Finish.\n  if (p != q) {\n    return wuffs_base__make_status(wuffs_base__error__bad_argument);\n  }\n  h->num_digits = nd;\n  if (nd == 0) {\n    h->decimal_point = 0;\n  } else if (dp <\n             -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n    h->decimal_point =\n        -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE - 1;\n  } else if (dp >\n             +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n    h->decimal_point =\n        +WU" +
-	"FFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1;\n  } else {\n    h->decimal_point = dp;\n  }\n  wuffs_base__private_implementation__high_prec_dec__trim(h);\n  return wuffs_base__make_status(NULL);\n}\n\n" +
+	"// ---------------- IEEE 754 Floating Point\n\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 1023\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 500\n\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N\n// such that ((10 << N) < (1 << 64)).\n#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60\n\n// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a\n// fixed precision floating point decimal number, augmented with ±infinity\n// values, but it cannot represent NaN (Not a Number).\n//\n// \"High precision\" means that the mantissa holds 500 decimal digits. 500 is\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.\n//\n// An HPD isn't for general purpose arithmetic, only for conversions to and\n// from IEEE 754 double-precision floating point, where the largest and\n// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.\n// HPD exponents above +1023 mean infinity, below -1023 mean zero. Th" +
+	"e ±1023\n// bounds are further away from zero than ±(324 + 500), where 500 and 1023 is\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.\n//\n// digits[.. num_digits] are the number's digits in big-endian order. The\n// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7'\n// is the ASCII value 0x37.\n//\n// decimal_point is the index (within digits) of the decimal point. It may be\n// negative or be larger than num_digits, in which case the explicit digits are\n// padded with implicit zeroes.\n//\n// For example, if num_digits is 3 and digits is \"\\x07\\x08\\x09\":\n//   - A decimal_point of -2 means \".00789\"\n//   - A decimal_point of -1 means \".0789\"\n//   - A decimal_point of +0 means \".789\"\n//   - A decimal_point of +1 means \"7.89\"\n//   - A decimal_point of +2 means \"78.9\"\n//   - A decimal_point of +3 means \"789.\"\n//   - A decimal_point of +4 means \"7890.\"\n//   - A decimal_point of +5 means \"78900.\"\n//\n// As above, a" +
+	" decimal_point higher than +1023 means that the overall value is\n// infinity, lower than -1023 means zero.\n//\n// negative is a sign bit. An HPD can distinguish positive and negative zero.\n//\n// truncated is whether there are more than\n// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at\n// least one of those extra digits are non-zero. The existence of long-tail\n// digits can affect rounding.\n//\n// The \"all fields are zero\" value is valid, and represents the number +0.\ntypedef struct {\n  uint32_t num_digits;\n  int32_t decimal_point;\n  bool negative;\n  bool truncated;\n  uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION];\n} wuffs_base__private_implementation__high_prec_dec;\n\n// wuffs_base__private_implementation__high_prec_dec__trim trims trailing\n// zeroes from the h->digits[.. h->num_digits] slice. They have no benefit,\n// since we explicitly track h->decimal_point.\n//\n// Preconditions:\n//  - h is non-NULL.\nstatic inline void  //\nwuffs_base__private_implementation_" +
+	"_high_prec_dec__trim(\n    wuffs_base__private_implementation__high_prec_dec* h) {\n  while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) {\n    h->num_digits--;\n  }\n}\n\nstatic wuffs_base__status  //\nwuffs_base__private_implementation__high_prec_dec__parse(\n    wuffs_base__private_implementation__high_prec_dec* h,\n    wuffs_base__slice_u8 s) {\n  if (!h) {\n    return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n  }\n  h->num_digits = 0;\n  h->decimal_point = 0;\n  h->negative = false;\n  h->truncated = false;\n\n  uint8_t* p = s.ptr;\n  uint8_t* q = s.ptr + s.len;\n\n  for (; (p < q) && (*p == '_'); p++) {\n  }\n  if (p >= q) {\n    return wuffs_base__make_status(wuffs_base__error__bad_argument);\n  }\n\n  // Parse sign.\n  do {\n    if (*p == '+') {\n      p++;\n    } else if (*p == '-') {\n      h->negative = true;\n      p++;\n    } else {\n      break;\n    }\n    for (; (p < q) && (*p == '_'); p++) {\n    }\n  } while (0);\n\n  // Parse digits.\n  uint32_t nd = 0;\n  int32_t dp = 0;\n  bool saw_digits = false;\n  " +
+	"bool saw_non_zero_digits = false;\n  bool saw_dot = false;\n  for (; p < q; p++) {\n    if (*p == '_') {\n      // No-op.\n\n    } else if ((*p == '.') || (*p == ',')) {\n      // As per https://en.wikipedia.org/wiki/Decimal_separator, both '.' or\n      // ',' are commonly used. We just parse either, regardless of LOCALE.\n      if (saw_dot) {\n        return wuffs_base__make_status(wuffs_base__error__bad_argument);\n      }\n      saw_dot = true;\n      dp = (int32_t)nd;\n\n    } else if ('0' == *p) {\n      if (!saw_dot && !saw_non_zero_digits && saw_digits) {\n        // We don't allow unnecessary leading zeroes: \"000123\" or \"0644\".\n        return wuffs_base__make_status(wuffs_base__error__bad_argument);\n      }\n      saw_digits = true;\n      if (nd == 0) {\n        // Track leading zeroes implicitly.\n        dp--;\n      } else if (nd <\n                 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {\n        h->digits[nd++] = 0;\n      } else {\n        // Long-tail zeroes are ignored.\n      }\n\n    } else if (('" +
+	"0' < *p) && (*p <= '9')) {\n      if (!saw_dot && !saw_non_zero_digits && saw_digits) {\n        // We don't allow unnecessary leading zeroes: \"000123\" or \"0644\".\n        return wuffs_base__make_status(wuffs_base__error__bad_argument);\n      }\n      saw_digits = true;\n      saw_non_zero_digits = true;\n      if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {\n        h->digits[nd++] = (uint8_t)(*p - '0');\n      } else {\n        // Long-tail non-zeroes set the truncated bit.\n        h->truncated = true;\n      }\n\n    } else {\n      break;\n    }\n  }\n\n  if (!saw_digits) {\n    return wuffs_base__make_status(wuffs_base__error__bad_argument);\n  }\n  if (!saw_dot) {\n    dp = (int32_t)nd;\n  }\n\n  // Parse exponent.\n  if ((p < q) && ((*p == 'E') || (*p == 'e'))) {\n    p++;\n    for (; (p < q) && (*p == '_'); p++) {\n    }\n    if (p >= q) {\n      return wuffs_base__make_status(wuffs_base__error__bad_argument);\n    }\n\n    int32_t exp_sign = +1;\n    if (*p == '+') {\n      p++;\n    } else if (*p == '-') {\n      " +
+	"exp_sign = -1;\n      p++;\n    }\n\n    int32_t exp = 0;\n    const int32_t exp_large =\n        WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE +\n        WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;\n    bool saw_exp_digits = false;\n    for (; p < q; p++) {\n      if (*p == '_') {\n        // No-op.\n      } else if (('0' <= *p) && (*p <= '9')) {\n        saw_exp_digits = true;\n        if (exp < exp_large) {\n          exp = (10 * exp) + ((int32_t)(*p - '0'));\n        }\n      } else {\n        break;\n      }\n    }\n    if (!saw_exp_digits) {\n      return wuffs_base__make_status(wuffs_base__error__bad_argument);\n    }\n    dp += exp_sign * exp;\n  }\n\n  // Finish.\n  if (p != q) {\n    return wuffs_base__make_status(wuffs_base__error__bad_argument);\n  }\n  h->num_digits = nd;\n  if (nd == 0) {\n    h->decimal_point = 0;\n  } else if (dp <\n             -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n    h->decimal_point =\n        -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__" +
+	"RANGE - 1;\n  } else if (dp >\n             +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n    h->decimal_point =\n        +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1;\n  } else {\n    h->decimal_point = dp;\n  }\n  wuffs_base__private_implementation__high_prec_dec__trim(h);\n  return wuffs_base__make_status(NULL);\n}\n\n" +
 	"" +
 	"// --------\n\n// The etc__hpd_left_shift and etc__powers_of_5 tables were printed by\n// script/print-hpd-left-shift.go. That script has an optional -comments flag,\n// whose output is not copied here, which prints further detail.\n//\n// These tables are used in\n// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits.\n\n// wuffs_base__private_implementation__hpd_left_shift[i] encodes the number of\n// new digits created after multiplying a positive integer by (1 << i): the\n// additional length in the decimal representation. For example, shifting \"234\"\n// by 3 (equivalent to multiplying by 8) will produce \"1872\". Going from a\n// 3-length string to a 4-length string means that 1 new digit was added (and\n// existing digits may have changed).\n//\n// Shifting by i can add either N or N-1 new digits, depending on whether the\n// original positive integer compares >= or < to the i'th power of 5 (as 10\n// equals 2 * 5). Comparison is lexicographic, not numerical.\n//\n// For example, shifting by 4 (i.e. mul" +
 	"tiplying by 16) can add 1 or 2 new\n// digits, depending on a lexicographic comparison to (5 ** 4), i.e. \"625\":\n//  - (\"1\"      << 4) is \"16\",       which adds 1 new digit.\n//  - (\"5678\"   << 4) is \"90848\",    which adds 1 new digit.\n//  - (\"624\"    << 4) is \"9984\",     which adds 1 new digit.\n//  - (\"62498\"  << 4) is \"999968\",   which adds 1 new digit.\n//  - (\"625\"    << 4) is \"10000\",    which adds 2 new digits.\n//  - (\"625001\" << 4) is \"10000016\", which adds 2 new digits.\n//  - (\"7008\"   << 4) is \"112128\",   which adds 2 new digits.\n//  - (\"99\"     << 4) is \"1584\",     which adds 2 new digits.\n//\n// Thus, when i is 4, N is 2 and (5 ** i) is \"625\". This etc__hpd_left_shift\n// array encodes this as:\n//  - etc__hpd_left_shift[4] is 0x1006 = (2 << 11) | 0x0006.\n//  - etc__hpd_left_shift[5] is 0x1009 = (? << 11) | 0x0009.\n// where the ? isn't relevant for i == 4.\n//\n// The high 5 bits of etc__hpd_left_shift[i] is N, the higher of the two\n// possible number of new digits. The low 11 bits are an offset into the\n//" +
@@ -105,14 +105,39 @@
 	" 0;\n\n  // Pick up enough leading digits to cover the first shift.\n  while ((n >> shift) == 0) {\n    if (rx < h->num_digits) {\n      // Read a digit.\n      n = (10 * n) + h->digits[rx++];\n    } else if (n == 0) {\n      // h's number used to be zero and remains zero.\n      return;\n    } else {\n      // Read sufficient implicit trailing zeroes.\n      while ((n >> shift) == 0) {\n        n = 10 * n;\n        rx++;\n      }\n      break;\n    }\n  }\n  h->decimal_point -= ((int32_t)(rx - 1));\n  if (h->decimal_point <\n      -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n    // After the shift, h's number is effectively zero.\n    h->num_digits = 0;\n    h->decimal_point = 0;\n    h->negative = false;\n    h->truncated = false;\n    return;\n  }\n\n  // Repeat: pick up a digit, put down a digit, left to right.\n  uint64_t mask = (((uint64_t)(1)) << shift) - 1;\n  while (rx < h->num_digits) {\n    uint8_t new_digit = ((uint8_t)(n >> shift));\n    n = (10 * (n & mask)) + h->digits[rx++];\n    h->digits[wx++] = new_digi" +
 	"t;\n  }\n\n  // Put down trailing digits, left to right.\n  while (n > 0) {\n    uint8_t new_digit = ((uint8_t)(n >> shift));\n    n = 10 * (n & mask);\n    if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {\n      h->digits[wx++] = new_digit;\n    } else if (new_digit > 0) {\n      h->truncated = true;\n    }\n  }\n\n  // Finish.\n  h->num_digits = wx;\n  wuffs_base__private_implementation__high_prec_dec__trim(h);\n}\n\n" +
 	"" +
+	"// --------\n\n// The wuffs_base__private_implementation__etc_powers_of_10 tables were printed\n// by script/print-mpb-powers-of-10.go. That script has an optional -comments\n// flag, whose output is not copied here, which prints further detail.\n//\n// These tables are used in\n// wuffs_base__private_implementation__medium_prec_bin__assign_from_hpd.\n\n// wuffs_base__private_implementation__big_powers_of_10 contains approximations\n// to the powers of 10, ranging from 1e-348 to 1e+340, with the exponent\n// stepping by 8: -348, -340, -332, ..., -12, -4, +4, +12, ..., +340. Each step\n// consists of three uint32_t elements. There are 87 triples, 87 * 3 = 261.\n//\n// For example, the third approximation, for 1e-332, consists of the uint32_t\n// triple (0x3055AC76, 0x8B16FB20, 0xFFFFFB72). The first two of that triple\n// are a little-endian uint64_t value: 0x8B16FB203055AC76. The last one is an\n// int32_t value: -1166. Together, they represent the approximation:\n//   1e-332 ≈ 0x8B16FB203055AC76 * (2 ** -1166)\n// Similarly," +
+	" the (0x00000000, 0x9C400000, 0xFFFFFFCE) uint32_t triple means:\n//   1e+4   ≈ 0x9C40000000000000 * (2 **   -50)  // This approx'n is exact.\n// Similarly, the (0xD4C4FB27, 0xED63A231, 0x000000A2) uint32_t triple means:\n//   1e+68  ≈ 0xED63A231D4C4FB27 * (2 **   162)\nstatic const uint32_t\n    wuffs_base__private_implementation__big_powers_of_10[261] = {\n        0x081C0288, 0xFA8FD5A0, 0xFFFFFB3C, 0xA23EBF76, 0xBAAEE17F, 0xFFFFFB57,\n        0x3055AC76, 0x8B16FB20, 0xFFFFFB72, 0x5DCE35EA, 0xCF42894A, 0xFFFFFB8C,\n        0x55653B2D, 0x9A6BB0AA, 0xFFFFFBA7, 0x3D1A45DF, 0xE61ACF03, 0xFFFFFBC1,\n        0xC79AC6CA, 0xAB70FE17, 0xFFFFFBDC, 0xBEBCDC4F, 0xFF77B1FC, 0xFFFFFBF6,\n        0x416BD60C, 0xBE5691EF, 0xFFFFFC11, 0x907FFC3C, 0x8DD01FAD, 0xFFFFFC2C,\n        0x31559A83, 0xD3515C28, 0xFFFFFC46, 0xADA6C9B5, 0x9D71AC8F, 0xFFFFFC61,\n        0x23EE8BCB, 0xEA9C2277, 0xFFFFFC7B, 0x4078536D, 0xAECC4991, 0xFFFFFC96,\n        0x5DB6CE57, 0x823C1279, 0xFFFFFCB1, 0x4DFB5637, 0xC2109436, 0xFFFFFCCB,\n        0x3848984F, 0x909" +
+	"6EA6F, 0xFFFFFCE6, 0x25823AC7, 0xD77485CB, 0xFFFFFD00,\n        0x97BF97F4, 0xA086CFCD, 0xFFFFFD1B, 0x172AACE5, 0xEF340A98, 0xFFFFFD35,\n        0x2A35B28E, 0xB23867FB, 0xFFFFFD50, 0xD2C63F3B, 0x84C8D4DF, 0xFFFFFD6B,\n        0x1AD3CDBA, 0xC5DD4427, 0xFFFFFD85, 0xBB25C996, 0x936B9FCE, 0xFFFFFDA0,\n        0x7D62A584, 0xDBAC6C24, 0xFFFFFDBA, 0x0D5FDAF6, 0xA3AB6658, 0xFFFFFDD5,\n        0xDEC3F126, 0xF3E2F893, 0xFFFFFDEF, 0xAAFF80B8, 0xB5B5ADA8, 0xFFFFFE0A,\n        0x6C7C4A8B, 0x87625F05, 0xFFFFFE25, 0x34C13053, 0xC9BCFF60, 0xFFFFFE3F,\n        0x91BA2655, 0x964E858C, 0xFFFFFE5A, 0x70297EBD, 0xDFF97724, 0xFFFFFE74,\n        0xB8E5B88F, 0xA6DFBD9F, 0xFFFFFE8F, 0x88747D94, 0xF8A95FCF, 0xFFFFFEA9,\n        0x8FA89BCF, 0xB9447093, 0xFFFFFEC4, 0xBF0F156B, 0x8A08F0F8, 0xFFFFFEDF,\n        0x653131B6, 0xCDB02555, 0xFFFFFEF9, 0xD07B7FAC, 0x993FE2C6, 0xFFFFFF14,\n        0x2A2B3B06, 0xE45C10C4, 0xFFFFFF2E, 0x697392D3, 0xAA242499, 0xFFFFFF49,\n        0x8300CA0E, 0xFD87B5F2, 0xFFFFFF63, 0x92111AEB, 0xBCE50864, 0xFFFFFF7E,\n        0" +
+	"x6F5088CC, 0x8CBCCC09, 0xFFFFFF99, 0xE219652C, 0xD1B71758, 0xFFFFFFB3,\n        0x00000000, 0x9C400000, 0xFFFFFFCE, 0x00000000, 0xE8D4A510, 0xFFFFFFE8,\n        0xAC620000, 0xAD78EBC5, 0x00000003, 0xF8940984, 0x813F3978, 0x0000001E,\n        0xC90715B3, 0xC097CE7B, 0x00000038, 0x7BEA5C70, 0x8F7E32CE, 0x00000053,\n        0xABE98068, 0xD5D238A4, 0x0000006D, 0x179A2245, 0x9F4F2726, 0x00000088,\n        0xD4C4FB27, 0xED63A231, 0x000000A2, 0x8CC8ADA8, 0xB0DE6538, 0x000000BD,\n        0x1AAB65DB, 0x83C7088E, 0x000000D8, 0x42711D9A, 0xC45D1DF9, 0x000000F2,\n        0xA61BE758, 0x924D692C, 0x0000010D, 0x1A708DEA, 0xDA01EE64, 0x00000127,\n        0x9AEF774A, 0xA26DA399, 0x00000142, 0xB47D6B85, 0xF209787B, 0x0000015C,\n        0x79DD1877, 0xB454E4A1, 0x00000177, 0x5B9BC5C2, 0x865B8692, 0x00000192,\n        0xC8965D3D, 0xC83553C5, 0x000001AC, 0xFA97A0B3, 0x952AB45C, 0x000001C7,\n        0x99A05FE3, 0xDE469FBD, 0x000001E1, 0xDB398C25, 0xA59BC234, 0x000001FC,\n        0xA3989F5C, 0xF6C69A72, 0x00000216, 0x54E9BECE, 0xB7DCBF53, 0x000" +
+	"00231,\n        0xF22241E2, 0x88FCF317, 0x0000024C, 0xD35C78A5, 0xCC20CE9B, 0x00000266,\n        0x7B2153DF, 0x98165AF3, 0x00000281, 0x971F303A, 0xE2A0B5DC, 0x0000029B,\n        0x5CE3B396, 0xA8D9D153, 0x000002B6, 0xA4A7443C, 0xFB9B7CD9, 0x000002D0,\n        0xA7A44410, 0xBB764C4C, 0x000002EB, 0xB6409C1A, 0x8BAB8EEF, 0x00000306,\n        0xA657842C, 0xD01FEF10, 0x00000320, 0xE9913129, 0x9B10A4E5, 0x0000033B,\n        0xA19C0C9D, 0xE7109BFB, 0x00000355, 0x623BF429, 0xAC2820D9, 0x00000370,\n        0x7AA7CF85, 0x80444B5E, 0x0000038B, 0x03ACDD2D, 0xBF21E440, 0x000003A5,\n        0x5E44FF8F, 0x8E679C2F, 0x000003C0, 0x9C8CB841, 0xD433179D, 0x000003DA,\n        0xB4E31BA9, 0x9E19DB92, 0x000003F5, 0xBADF77D9, 0xEB96BF6E, 0x0000040F,\n        0x9BF0EE6B, 0xAF87023B, 0x0000042A,\n};\n\n// wuffs_base__private_implementation__small_powers_of_10 contains\n// approximations to the powers of 10, ranging from 1e+0 to 1e+7, with the\n// exponent stepping by 1. Each step consists of three uint32_t elements.\n//\n// For example, the third appr" +
+	"oximation, for 1e+2, consists of the uint32_t\n// triple (0x00000000, 0xC8000000, 0xFFFFFFC7). The first two of that triple\n// are a little-endian uint64_t value: 0xC800000000000000. The last one is an\n// int32_t value: -57. Together, they represent the approximation:\n//   1e+2   ≈ 0xC800000000000000 * (2 **   -57)  // This approx'n is exact.\n// Similarly, the (0x00000000, 0x9C400000, 0xFFFFFFCE) uint32_t triple means:\n//   1e+4   ≈ 0x9C40000000000000 * (2 **   -50)  // This approx'n is exact.\nstatic const uint32_t\n    wuffs_base__private_implementation__small_powers_of_10[24] = {\n        0x00000000, 0x80000000, 0xFFFFFFC1, 0x00000000, 0xA0000000, 0xFFFFFFC4,\n        0x00000000, 0xC8000000, 0xFFFFFFC7, 0x00000000, 0xFA000000, 0xFFFFFFCA,\n        0x00000000, 0x9C400000, 0xFFFFFFCE, 0x00000000, 0xC3500000, 0xFFFFFFD1,\n        0x00000000, 0xF4240000, 0xFFFFFFD4, 0x00000000, 0x98968000, 0xFFFFFFD8,\n};\n\n// wuffs_base__private_implementation__f64_powers_of_10 holds powers of 10 that\n// can be exactly represented" +
+	" by a float64 (what C calls a double).\nstatic const double wuffs_base__private_implementation__f64_powers_of_10[23] = {\n    1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,  1e10, 1e11,\n    1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,\n};\n\n" +
+	"" +
+	"// --------\n\n// wuffs_base__private_implementation__medium_prec_bin (abbreviated as MPB) is\n// a fixed precision floating point binary number. Unlike IEEE 754 Floating\n// Point, it cannot represent infinity or NaN (Not a Number).\n//\n// \"Medium precision\" means that the mantissa holds 64 binary digits, a little\n// more than \"double precision\", and sizeof(MPB) > sizeof(double). 64 is\n// obviously the number of bits in a uint64_t.\n//\n// An MPB isn't for general purpose arithmetic, only for conversions to and\n// from IEEE 754 double-precision floating point.\n//\n// There is no implicit mantissa bit. The mantissa field is zero if and only if\n// the overall floating point value is ±0. An MPB is normalized if the mantissa\n// is zero or its high bit (the 1<<63 bit) is set.\n//\n// There is no negative bit. An MPB can only represent non-negative numbers.\n//\n// The \"all fields are zero\" value is valid, and represents the number +0.\n//\n// This is the \"Do It Yourself Floating Point\" data structure from Loitsch,\n// \"Printin" +
+	"g Floating-Point Numbers Quickly and Accurately with Integers\"\n// (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).\n//\n// Florian Loitsch is also the primary contributor to\n// https://github.com/google/double-conversion\ntypedef struct {\n  uint64_t mantissa;\n  int32_t exp2;\n} wuffs_base__private_implementation__medium_prec_bin;\n\nstatic uint32_t  //\nwuffs_base__private_implementation__medium_prec_bin__normalize(\n    wuffs_base__private_implementation__medium_prec_bin* m) {\n  if (m->mantissa == 0) {\n    return 0;\n  }\n  uint32_t shift = wuffs_base__count_leading_zeroes_u64(m->mantissa);\n  m->mantissa <<= shift;\n  m->exp2 -= (int32_t)shift;\n  return shift;\n}\n\n// wuffs_base__private_implementation__medium_prec_bin__mul_pow_10 sets m to be\n// (m * pow), where pow comes from an etc_powers_of_10 triple starting at p.\n//\n// The result is rounded, but not necessarily normalized.\n//\n// Preconditions:\n//  - m is non-NULL.\n//  - m->mantissa is non-zero.\n//  - m->mantissa's high bit is set (i.e. m is " +
+	"normalized).\n//\n// The etc_powers_of_10 triple is already normalized.\nstatic void  //\nwuffs_base__private_implementation__medium_prec_bin__mul_pow_10(\n    wuffs_base__private_implementation__medium_prec_bin* m,\n    const uint32_t* p) {\n  uint64_t p_mantissa = ((uint64_t)p[0]) | (((uint64_t)p[1]) << 32);\n  int32_t p_exp2 = (int32_t)p[2];\n\n  wuffs_base__multiply_u64__output o =\n      wuffs_base__multiply_u64(m->mantissa, p_mantissa);\n  // Round the mantissa up. It cannot overflow because the maximum possible\n  // value of o.hi is 0xFFFFFFFFFFFFFFFE.\n  m->mantissa = o.hi + (o.lo >> 63);\n  m->exp2 = m->exp2 + p_exp2 + 64;\n}\n\n// wuffs_base__private_implementation__medium_prec_bin__as_f64 converts m to a\n// double (what C calls a double-precision float64).\n//\n// Preconditions:\n//  - m is non-NULL.\n//  - m->mantissa is non-zero.\n//  - m->mantissa's high bit is set (i.e. m is normalized).\nstatic double  //\nwuffs_base__private_implementation__medium_prec_bin__as_f64(\n    const wuffs_base__private_implementation__mediu" +
+	"m_prec_bin* m,\n    bool negative) {\n  uint64_t mantissa64 = m->mantissa;\n  // An mpb's mantissa has the implicit (binary) decimal point at the right\n  // hand end of the mantissa's explicit digits. A double-precision's mantissa\n  // has that decimal point near the left hand end. There's also an explicit\n  // versus implicit leading 1 bit (binary digit). Together, the difference in\n  // semantics corresponds to adding 63.\n  int32_t exp2 = m->exp2 + 63;\n\n  // Ensure that exp2 is at least -1022, the minimum double-precision exponent\n  // for normal (as opposed to subnormal) numbers.\n  if (-1022 > exp2) {\n    uint32_t n = (uint32_t)(-1022 - exp2);\n    mantissa64 >>= n;\n    exp2 += (int32_t)n;\n  }\n\n  // Extract the (1 + 52) bits from the 64-bit mantissa64. 52 is the number of\n  // explicit mantissa bits in a double-precision f64.\n  //\n  // Before, we have 64 bits and due to normalization, the high bit 'H' is 1.\n  // 63        55        47       etc     15        7\n  // H210_9876_5432_1098_7654_etc_etc_etc_5432_109" +
+	"8_7654_3210\n  // ++++_++++_++++_++++_++++_etc_etc_etc_++++_+..._...._....  Kept bits.\n  // ...._...._...H_2109_8765_etc_etc_etc_6543_2109_8765_4321  After shifting.\n  // After, we have 53 bits (and bit #52 is this 'H' bit).\n  uint64_t mantissa53 = mantissa64 >> 11;\n\n  // Round up if the old bit #10 (the highest bit dropped by shifting) was set.\n  // We also fix any overflow from rounding up.\n  if (mantissa64 & 1024) {\n    mantissa53++;\n    if ((mantissa53 >> 53) != 0) {\n      mantissa53 >>= 1;\n      exp2++;\n    }\n  }\n\n  // Handle double-precision infinity (a nominal exponent of 1024) and\n  // subnormals (an exponent of -1023 and no implicit mantissa bit, bit #52).\n  if (exp2 >= 1024) {\n    mantissa53 = 0;\n    exp2 = 1024;\n  } else if ((mantissa53 >> 52) == 0) {\n    exp2 = -1023;\n  }\n\n  // Pack the bits and return.\n  const int32_t f64_bias = -1023;\n  uint64_t exp2_bits =\n      (uint64_t)((exp2 - f64_bias) & 0x07FF);           // (1 << 11) - 1.\n  uint64_t bits = (mantissa53 & 0x000FFFFFFFFFFFFF) |   // (1 << 52" +
+	") - 1.\n                  (exp2_bits << 52) |                   //\n                  (negative ? 0x8000000000000000 : 0);  // (1 << 63).\n  return wuffs_base__ieee_754_bit_representation__to_f64(bits);\n}\n\n// wuffs_base__private_implementation__medium_prec_bin__parse_number_f64\n// converts from an HPD to a double, using an MPB as scratch space. It returns\n// a NULL status.repr if there is no ambiguity in the truncation or rounding to\n// a float64 (an IEEE 754 double-precision floating point value).\n//\n// It may modify m even if it returns a non-NULL status.repr.\nstatic wuffs_base__result_f64  //\nwuffs_base__private_implementation__medium_prec_bin__parse_number_f64(\n    wuffs_base__private_implementation__medium_prec_bin* m,\n    const wuffs_base__private_implementation__high_prec_dec* h,\n    bool skip_fast_path_for_tests) {\n  do {\n    // m->mantissa is a uint64_t, which is an integer approximation to a\n    // rational value - h's underlying digits after m's normalization. This\n    // error is an upper bound on th" +
+	"e difference between the approximate and\n    // actual value.\n    //\n    // The DiyFpStrtod function in https://github.com/google/double-conversion\n    // uses a finer grain (1/8th of the ULP, Unit in the Last Place) when\n    // tracking error. This implementation is coarser (1 ULP) but simpler.\n    //\n    // It is an error in the \"numerical approximation\" sense, not in the\n    // typical programming sense (as in \"bad input\" or \"a result type\").\n    uint64_t error = 0;\n\n    // Convert up to 19 decimal digits (in h->digits) to 64 binary digits (in\n    // m->mantissa): (1e19 < (1<<64)) and ((1<<64) < 1e20). If we have more\n    // than 19 digits, we're truncating (with error).\n    uint32_t i;\n    uint32_t i_end = h->num_digits;\n    if (i_end > 19) {\n      i_end = 19;\n      error = 1;\n    }\n    uint64_t mantissa = 0;\n    for (i = 0; i < i_end; i++) {\n      mantissa = (10 * mantissa) + h->digits[i];\n    }\n    m->mantissa = mantissa;\n    m->exp2 = 0;\n\n    // Check that exp10 lies in the (big_powers_of_10 + small_po" +
+	"wers_of_10)\n    // range, -348 ..= +347, stepping big_powers_of_10 by 8 (which is 87\n    // triples) and small_powers_of_10 by 1 (which is 8 triples).\n    int32_t exp10 = h->decimal_point - ((int32_t)(i_end));\n    if (exp10 < -348) {\n      goto fail;\n    }\n    uint32_t bpo10 = ((uint32_t)(exp10 + 348)) / 8;\n    uint32_t spo10 = ((uint32_t)(exp10 + 348)) % 8;\n    if (bpo10 >= 87) {\n      goto fail;\n    }\n\n    // Try a fast path, if float64 math would be exact.\n    //\n    // 15 is such that 1e15 can be losslessly represented in a float64\n    // mantissa: (1e15 < (1<<53)) and ((1<<53) < 1e16).\n    //\n    // 22 is the maximum valid index for the\n    // wuffs_base__private_implementation__f64_powers_of_10 array.\n    do {\n      if (skip_fast_path_for_tests || ((mantissa >> 52) != 0)) {\n        break;\n      }\n      double d = (double)mantissa;\n\n      if (exp10 == 0) {\n        wuffs_base__result_f64 ret;\n        ret.status.repr = NULL;\n        ret.value = h->negative ? -d : +d;\n        return ret;\n\n      } else if (e" +
+	"xp10 > 0) {\n        if (exp10 > 22) {\n          if (exp10 > (15 + 22)) {\n            break;\n          }\n          // If exp10 is in the range 23 ..= 37, try moving a few of the zeroes\n          // from the exponent to the mantissa. If we're still under 1e15, we\n          // haven't truncated any mantissa bits.\n          if (exp10 > 22) {\n            d *= wuffs_base__private_implementation__f64_powers_of_10[exp10 -\n                                                                      22];\n            exp10 = 22;\n            if (d >= 1e15) {\n              break;\n            }\n          }\n        }\n        d *= wuffs_base__private_implementation__f64_powers_of_10[exp10];\n        wuffs_base__result_f64 ret;\n        ret.status.repr = NULL;\n        ret.value = h->negative ? -d : +d;\n        return ret;\n\n      } else {  // \"if (exp10 < 0)\" is effectively \"if (true)\" here.\n        if (exp10 < -22) {\n          break;\n        }\n        d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];\n        wuffs_bas" +
+	"e__result_f64 ret;\n        ret.status.repr = NULL;\n        ret.value = h->negative ? -d : +d;\n        return ret;\n      }\n    } while (0);\n\n    // Normalize (and scale the error).\n    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);\n\n    // Multiplying two MPB values nominally multiplies two mantissas, call them\n    // A and B, which are integer approximations to the precise values (A+a)\n    // and (B+b) for some error terms a and b.\n    //\n    // MPB multiplication calculates (((A+a) * (B+b)) >> 64) to be ((A*B) >>\n    // 64). Shifting (truncating) and rounding introduces further error. The\n    // difference between the calculated result:\n    //  ((A*B                  ) >> 64)\n    // and the true result:\n    //  ((A*B + A*b + a*B + a*b) >> 64)   + rounding_error\n    // is:\n    //  ((      A*b + a*B + a*b) >> 64)   + rounding_error\n    // which can be re-grouped as:\n    //  ((A*b) >> 64) + ((a*(B+b)) >> 64) + rounding_error\n    //\n    // Now, let A and a be \"m->mantissa\" and \"erro" +
+	"r\", and B and b be the\n    // pre-calculated power of 10. A and B are both less than (1 << 64), a is\n    // the \"error\" local variable and b is less than 1.\n    //\n    // An upper bound (in absolute value) on ((A*b) >> 64) is therefore 1.\n    //\n    // An upper bound on ((a*(B+b)) >> 64) is a, also known as error.\n    //\n    // Finally, the rounding_error is at most 1.\n    //\n    // In total, calling mpb__mul_pow_10 will raise the worst-case error by 2.\n    // The subsequent re-normalization can multiply that by a further factor.\n\n    // Multiply by small_powers_of_10[etc].\n    wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(\n        m, &wuffs_base__private_implementation__small_powers_of_10[3 * spo10]);\n    error += 2;\n    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);\n\n    // Multiply by big_powers_of_10[etc].\n    wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(\n        m, &wuffs_base__private_implementation__big_powers_of_10[3 * bpo10]);\n    err" +
+	"or += 2;\n    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);\n\n    // We have a good approximation of h, but we still have to check whether\n    // the error is small enough. Equivalently, whether the number of surplus\n    // mantissa bits (the bits dropped when going from m's 64 mantissa bits to\n    // the smaller number of double-precision mantissa bits) would always round\n    // up or down, even when perturbed by ±error. We start at 11 surplus bits\n    // (m has 64, double-precision has 1+52), but it can be higher for\n    // subnormals.\n    //\n    // In many cases, the error is small enough and we return true.\n    const int32_t f64_bias = -1023;\n    int32_t subnormal_exp2 = f64_bias - 63;\n    uint32_t surplus_bits = 11;\n    if (subnormal_exp2 >= m->exp2) {\n      surplus_bits += 1 + ((uint32_t)(subnormal_exp2 - m->exp2));\n    }\n\n    uint64_t surplus_mask =\n        (((uint64_t)1) << surplus_bits) - 1;  // e.g. 0x07FF.\n    uint64_t surplus = m->mantissa & surplus_mask;\n    uint64_t" +
+	" halfway = ((uint64_t)1) << (surplus_bits - 1);  // e.g. 0x0400.\n\n    // Do the final calculation in *signed* arithmetic.\n    int64_t i_surplus = (int64_t)surplus;\n    int64_t i_halfway = (int64_t)halfway;\n    int64_t i_error = (int64_t)error;\n\n    if ((i_surplus > (i_halfway - i_error)) &&\n        (i_surplus < (i_halfway + i_error))) {\n      goto fail;\n    }\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base__private_implementation__medium_prec_bin__as_f64(\n        m, h->negative);\n    return ret;\n  } while (0);\n\nfail:\n  do {\n    wuffs_base__result_f64 ret;\n    ret.status.repr = \"#base: mpb__parse_number_f64 failed\";\n    ret.value = 0;\n    return ret;\n  } while (0);\n}\n\n" +
+	"" +
 	"// --------\n\nwuffs_base__result_f64  //\nwuffs_base__parse_number_f64_special(wuffs_base__slice_u8 s,\n                                     const char* fallback_status_repr) {\n  do {\n    uint8_t* p = s.ptr;\n    uint8_t* q = s.ptr + s.len;\n\n    for (; (p < q) && (*p == '_'); p++) {\n    }\n    if (p >= q) {\n      goto fallback;\n    }\n\n    // Parse sign.\n    bool negative = false;\n    do {\n      if (*p == '+') {\n        p++;\n      } else if (*p == '-') {\n        negative = true;\n        p++;\n      } else {\n        break;\n      }\n      for (; (p < q) && (*p == '_'); p++) {\n      }\n    } while (0);\n    if (p >= q) {\n      goto fallback;\n    }\n\n    bool nan = false;\n    switch (p[0]) {\n      case 'I':\n      case 'i':\n        if (((q - p) < 3) ||                     //\n            ((p[1] != 'N') && (p[1] != 'n')) ||  //\n            ((p[2] != 'F') && (p[2] != 'f'))) {\n          goto fallback;\n        }\n        p += 3;\n\n        if ((p >= q) || (*p == '_')) {\n          break;\n        } else if (((q - p) < 5) ||           " +
 	"          //\n                   ((p[0] != 'I') && (p[0] != 'i')) ||  //\n                   ((p[1] != 'N') && (p[1] != 'n')) ||  //\n                   ((p[2] != 'I') && (p[2] != 'i')) ||  //\n                   ((p[3] != 'T') && (p[3] != 't')) ||  //\n                   ((p[4] != 'Y') && (p[4] != 'y'))) {\n          goto fallback;\n        }\n        p += 5;\n\n        if ((p >= q) || (*p == '_')) {\n          break;\n        }\n        goto fallback;\n\n      case 'N':\n      case 'n':\n        if (((q - p) < 3) ||                     //\n            ((p[1] != 'A') && (p[1] != 'a')) ||  //\n            ((p[2] != 'N') && (p[2] != 'n'))) {\n          goto fallback;\n        }\n        p += 3;\n\n        if ((p >= q) || (*p == '_')) {\n          nan = true;\n          break;\n        }\n        goto fallback;\n\n      default:\n        goto fallback;\n    }\n\n    // Finish.\n    for (; (p < q) && (*p == '_'); p++) {\n    }\n    if (p != q) {\n      goto fallback;\n    }\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = w" +
-	"uffs_base__ieee_754_bit_representation__to_f64(\n        (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) |\n        (negative ? 0x8000000000000000 : 0));\n    return ret;\n  } while (0);\n\nfallback:\n  do {\n    wuffs_base__result_f64 ret;\n    ret.status.repr = fallback_status_repr;\n    ret.value = 0;\n    return ret;\n  } while (0);\n}\n\nwuffs_base__result_f64  //\nwuffs_base__parse_number_f64(wuffs_base__slice_u8 s) {\n  wuffs_base__private_implementation__high_prec_dec h;\n\n  do {\n    // powers converts decimal powers of 10 to binary powers of 2. For example,\n    // (10000 >> 13) is 1. It stops before the elements exceed 60, also known\n    // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.\n    static const uint32_t num_powers = 19;\n    static const uint8_t powers[19] = {\n        0,  3,  6,  9,  13, 16, 19, 23, 26, 29,  //\n        33, 36, 39, 43, 46, 49, 53, 56, 59,      //\n    };\n\n    wuffs_base__status status =\n        wuffs_base__private_implementation__high_prec_dec__parse(&h, s);\n    if (status.repr) {\n" +
-	"      return wuffs_base__parse_number_f64_special(s, status.repr);\n    }\n\n    // Handle zero and obvious extremes. The largest and smallest positive\n    // finite f64 values are approximately 1.8e+308 and 4.9e-324.\n    if ((h.num_digits == 0) || (h.decimal_point < -326)) {\n      goto zero;\n    } else if (h.decimal_point > 310) {\n      goto infinity;\n    }\n\n    // Scale by powers of 2 until we're in the range [½ .. 1], which gives us\n    // our exponent (in base-2). First we shift right, possibly a little too\n    // far, ending with a value certainly below 1 and possibly below ½...\n    const int32_t bias = -1023;\n    int32_t exp2 = 0;\n    while (h.decimal_point > 0) {\n      uint32_t n = (uint32_t)(+h.decimal_point);\n      uint32_t shift =\n          (n < num_powers)\n              ? powers[n]\n              : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;\n\n      wuffs_base__private_implementation__high_prec_dec__small_rshift(&h,\n                                                                      sh" +
-	"ift);\n      if (h.decimal_point <\n          -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n        goto zero;\n      }\n      exp2 += (int32_t)shift;\n    }\n    // ...then we shift left, putting us in [½ .. 1].\n    while (h.decimal_point <= 0) {\n      uint32_t shift;\n      if (h.decimal_point == 0) {\n        if (h.digits[0] >= 5) {\n          break;\n        }\n        shift = (h.digits[0] <= 2) ? 2 : 1;\n      } else {\n        uint32_t n = (uint32_t)(-h.decimal_point);\n        shift = (n < num_powers)\n                    ? powers[n]\n                    : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;\n      }\n\n      wuffs_base__private_implementation__high_prec_dec__small_lshift(&h,\n                                                                      shift);\n      if (h.decimal_point >\n          +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n        goto infinity;\n      }\n      exp2 -= (int32_t)shift;\n    }\n\n    // We're in the range [½ .. 1] but f64 uses [1 .. 2]." +
-	"\n    exp2--;\n\n    // The minimum normal exponent is (bias + 1).\n    while ((bias + 1) > exp2) {\n      uint32_t n = (uint32_t)((bias + 1) - exp2);\n      if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {\n        n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;\n      }\n      wuffs_base__private_implementation__high_prec_dec__small_rshift(&h, n);\n      exp2 += (int32_t)n;\n    }\n\n    // Check for overflow.\n    if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1.\n      goto infinity;\n    }\n\n    // Extract 53 bits for the mantissa (in base-2).\n    wuffs_base__private_implementation__high_prec_dec__small_lshift(&h, 53);\n    uint64_t man2 =\n        wuffs_base__private_implementation__high_prec_dec__rounded_integer(&h);\n\n    // Rounding might have added one bit. If so, shift and re-check overflow.\n    if ((man2 >> 53) != 0) {\n      man2 >>= 1;\n      exp2++;\n      if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1.\n        goto infinity;\n      }\n    }\n\n    // Handle subnormal numbers.\n    if ((" +
-	"man2 >> 52) == 0) {\n      exp2 = bias;\n    }\n\n    // Pack the bits and return.\n    uint64_t exp2_bits = (uint64_t)((exp2 - bias) & 0x07FF);  // (1 << 11) - 1.\n    uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |             // (1 << 52) - 1.\n                    (exp2_bits << 52) |                       //\n                    (h.negative ? 0x8000000000000000 : 0);    // (1 << 63).\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);\n    return ret;\n  } while (0);\n\nzero:\n  do {\n    uint64_t bits = h.negative ? 0x8000000000000000 : 0;\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);\n    return ret;\n  } while (0);\n\ninfinity:\n  do {\n    uint64_t bits = h.negative ? 0xFFF0000000000000 : 0x7FF0000000000000;\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);\n    return ret;\n  } whi" +
-	"le (0);\n}\n\n" +
+	"uffs_base__ieee_754_bit_representation__to_f64(\n        (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) |\n        (negative ? 0x8000000000000000 : 0));\n    return ret;\n  } while (0);\n\nfallback:\n  do {\n    wuffs_base__result_f64 ret;\n    ret.status.repr = fallback_status_repr;\n    ret.value = 0;\n    return ret;\n  } while (0);\n}\n\nwuffs_base__result_f64  //\nwuffs_base__parse_number_f64(wuffs_base__slice_u8 s) {\n  wuffs_base__private_implementation__medium_prec_bin m;\n  wuffs_base__private_implementation__high_prec_dec h;\n\n  do {\n    // powers converts decimal powers of 10 to binary powers of 2. For example,\n    // (10000 >> 13) is 1. It stops before the elements exceed 60, also known\n    // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.\n    static const uint32_t num_powers = 19;\n    static const uint8_t powers[19] = {\n        0,  3,  6,  9,  13, 16, 19, 23, 26, 29,  //\n        33, 36, 39, 43, 46, 49, 53, 56, 59,      //\n    };\n\n    wuffs_base__status status =\n        wuffs_base__private_implementat" +
+	"ion__high_prec_dec__parse(&h, s);\n    if (status.repr) {\n      return wuffs_base__parse_number_f64_special(s, status.repr);\n    }\n\n    // Handle zero and obvious extremes. The largest and smallest positive\n    // finite f64 values are approximately 1.8e+308 and 4.9e-324.\n    if ((h.num_digits == 0) || (h.decimal_point < -326)) {\n      goto zero;\n    } else if (h.decimal_point > 310) {\n      goto infinity;\n    }\n\n    wuffs_base__result_f64 mpb_result =\n        wuffs_base__private_implementation__medium_prec_bin__parse_number_f64(\n            &m, &h, false);\n    if (mpb_result.status.repr == NULL) {\n      return mpb_result;\n    }\n\n    // Scale by powers of 2 until we're in the range [½ .. 1], which gives us\n    // our exponent (in base-2). First we shift right, possibly a little too\n    // far, ending with a value certainly below 1 and possibly below ½...\n    const int32_t f64_bias = -1023;\n    int32_t exp2 = 0;\n    while (h.decimal_point > 0) {\n      uint32_t n = (uint32_t)(+h.decimal_point);\n      uint32_t " +
+	"shift =\n          (n < num_powers)\n              ? powers[n]\n              : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;\n\n      wuffs_base__private_implementation__high_prec_dec__small_rshift(&h,\n                                                                      shift);\n      if (h.decimal_point <\n          -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n        goto zero;\n      }\n      exp2 += (int32_t)shift;\n    }\n    // ...then we shift left, putting us in [½ .. 1].\n    while (h.decimal_point <= 0) {\n      uint32_t shift;\n      if (h.decimal_point == 0) {\n        if (h.digits[0] >= 5) {\n          break;\n        }\n        shift = (h.digits[0] <= 2) ? 2 : 1;\n      } else {\n        uint32_t n = (uint32_t)(-h.decimal_point);\n        shift = (n < num_powers)\n                    ? powers[n]\n                    : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;\n      }\n\n      wuffs_base__private_implementation__high_prec_dec__small_lshift(&h,\n                          " +
+	"                                            shift);\n      if (h.decimal_point >\n          +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {\n        goto infinity;\n      }\n      exp2 -= (int32_t)shift;\n    }\n\n    // We're in the range [½ .. 1] but f64 uses [1 .. 2].\n    exp2--;\n\n    // The minimum normal exponent is (f64_bias + 1).\n    while ((f64_bias + 1) > exp2) {\n      uint32_t n = (uint32_t)((f64_bias + 1) - exp2);\n      if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {\n        n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;\n      }\n      wuffs_base__private_implementation__high_prec_dec__small_rshift(&h, n);\n      exp2 += (int32_t)n;\n    }\n\n    // Check for overflow.\n    if ((exp2 - f64_bias) >= 0x07FF) {  // (1 << 11) - 1.\n      goto infinity;\n    }\n\n    // Extract 53 bits for the mantissa (in base-2).\n    wuffs_base__private_implementation__high_prec_dec__small_lshift(&h, 53);\n    uint64_t man2 =\n        wuffs_base__private_implementation__high_prec_dec_" +
+	"_rounded_integer(&h);\n\n    // Rounding might have added one bit. If so, shift and re-check overflow.\n    if ((man2 >> 53) != 0) {\n      man2 >>= 1;\n      exp2++;\n      if ((exp2 - f64_bias) >= 0x07FF) {  // (1 << 11) - 1.\n        goto infinity;\n      }\n    }\n\n    // Handle subnormal numbers.\n    if ((man2 >> 52) == 0) {\n      exp2 = f64_bias;\n    }\n\n    // Pack the bits and return.\n    uint64_t exp2_bits =\n        (uint64_t)((exp2 - f64_bias) & 0x07FF);             // (1 << 11) - 1.\n    uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |           // (1 << 52) - 1.\n                    (exp2_bits << 52) |                     //\n                    (h.negative ? 0x8000000000000000 : 0);  // (1 << 63).\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);\n    return ret;\n  } while (0);\n\nzero:\n  do {\n    uint64_t bits = h.negative ? 0x8000000000000000 : 0;\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base" +
+	"__ieee_754_bit_representation__to_f64(bits);\n    return ret;\n  } while (0);\n\ninfinity:\n  do {\n    uint64_t bits = h.negative ? 0xFFF0000000000000 : 0x7FF0000000000000;\n\n    wuffs_base__result_f64 ret;\n    ret.status.repr = NULL;\n    ret.value = wuffs_base__ieee_754_bit_representation__to_f64(bits);\n    return ret;\n  } while (0);\n}\n\n" +
+	"" +
+	"// ---------------- Hexadecimal\n\nsize_t  //\nwuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,\n                                 wuffs_base__slice_u8 src) {\n  size_t src_len2 = src.len / 2;\n  size_t len = dst.len < src_len2 ? dst.len : src_len2;\n  uint8_t* d = dst.ptr;\n  uint8_t* s = src.ptr;\n  size_t n = len;\n\n  while (n--) {\n    *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |\n                   (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));\n    d += 1;\n    s += 2;\n  }\n\n  return len;\n}\n\nsize_t  //\nwuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,\n                                 wuffs_base__slice_u8 src) {\n  size_t src_len4 = src.len / 4;\n  size_t len = dst.len < src_len4 ? dst.len : src_len4;\n  uint8_t* d = dst.ptr;\n  uint8_t* s = src.ptr;\n  size_t n = len;\n\n  while (n--) {\n    *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |\n                   (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F));\n    d += 1;\n    s +" +
+	"= 4;\n  }\n\n  return len;\n}\n\n" +
 	"" +
 	"// ---------------- Unicode and UTF-8\n\nsize_t  //\nwuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point) {\n  if (code_point <= 0x7F) {\n    if (dst.len >= 1) {\n      dst.ptr[0] = (uint8_t)(code_point);\n      return 1;\n    }\n\n  } else if (code_point <= 0x07FF) {\n    if (dst.len >= 2) {\n      dst.ptr[0] = (uint8_t)(0xC0 | ((code_point >> 6)));\n      dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));\n      return 2;\n    }\n\n  } else if (code_point <= 0xFFFF) {\n    if ((dst.len >= 3) && ((code_point < 0xD800) || (0xDFFF < code_point))) {\n      dst.ptr[0] = (uint8_t)(0xE0 | ((code_point >> 12)));\n      dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F));\n      dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));\n      return 3;\n    }\n\n  } else if (code_point <= 0x10FFFF) {\n    if (dst.len >= 4) {\n      dst.ptr[0] = (uint8_t)(0xF0 | ((code_point >> 18)));\n      dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 12) & 0x3F));\n      dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3" +
 	"F));\n      dst.ptr[3] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));\n      return 4;\n    }\n  }\n\n  return 0;\n}\n\n// wuffs_base__utf_8__byte_length_minus_1 is the byte length (minus 1) of a\n// UTF-8 encoded code point, based on the encoding's initial byte.\n//  - 0x00 is 1-byte UTF-8 (ASCII).\n//  - 0x01 is the start of 2-byte UTF-8.\n//  - 0x02 is the start of 3-byte UTF-8.\n//  - 0x03 is the start of 4-byte UTF-8.\n//  - 0x40 is a UTF-8 tail byte.\n//  - 0x80 is invalid UTF-8.\n//\n// RFC 3629 (UTF-8) gives this grammar for valid UTF-8:\n//    UTF8-1      = %x00-7F\n//    UTF8-2      = %xC2-DF UTF8-tail\n//    UTF8-3      = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /\n//                  %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )\n//    UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /\n//                  %xF4 %x80-8F 2( UTF8-tail )\n//    UTF8-tail   = %x80-BF\nstatic const uint8_t wuffs_base__utf_8__byte_length_minus_1[256] = {\n    // 0     1     2     3     4     5     6     7\n    // 8     9" +
@@ -164,7 +189,11 @@
 	"\nstatic inline uint32_t  //\nwuffs_base__u32__max(uint32_t x, uint32_t y) {\n  return x > y ? x : y;\n}\n\nstatic inline uint64_t  //\nwuffs_base__u64__min(uint64_t x, uint64_t y) {\n  return x < y ? x : y;\n}\n\nstatic inline uint64_t  //\nwuffs_base__u64__max(uint64_t x, uint64_t y) {\n  return x > y ? x : y;\n}\n\n" +
 	"" +
 	"// --------\n\n// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms\n// are per https://locklessinc.com/articles/sat_arithmetic/\n//\n// It is important that the underlying types are unsigned integers, as signed\n// integer arithmetic overflow is undefined behavior in C.\n\nstatic inline uint8_t  //\nwuffs_base__u8__sat_add(uint8_t x, uint8_t y) {\n  uint8_t res = (uint8_t)(x + y);\n  res |= (uint8_t)(-(res < x));\n  return res;\n}\n\nstatic inline uint8_t  //\nwuffs_base__u8__sat_sub(uint8_t x, uint8_t y) {\n  uint8_t res = (uint8_t)(x - y);\n  res &= (uint8_t)(-(res <= x));\n  return res;\n}\n\nstatic inline uint16_t  //\nwuffs_base__u16__sat_add(uint16_t x, uint16_t y) {\n  uint16_t res = (uint16_t)(x + y);\n  res |= (uint16_t)(-(res < x));\n  return res;\n}\n\nstatic inline uint16_t  //\nwuffs_base__u16__sat_sub(uint16_t x, uint16_t y) {\n  uint16_t res = (uint16_t)(x - y);\n  res &= (uint16_t)(-(res <= x));\n  return res;\n}\n\nstatic inline uint32_t  //\nwuffs_base__u32__sat_add(uint32_t x, uint32_t y) {\n  uint32" +
-	"_t res = (uint32_t)(x + y);\n  res |= (uint32_t)(-(res < x));\n  return res;\n}\n\nstatic inline uint32_t  //\nwuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {\n  uint32_t res = (uint32_t)(x - y);\n  res &= (uint32_t)(-(res <= x));\n  return res;\n}\n\nstatic inline uint64_t  //\nwuffs_base__u64__sat_add(uint64_t x, uint64_t y) {\n  uint64_t res = (uint64_t)(x + y);\n  res |= (uint64_t)(-(res < x));\n  return res;\n}\n\nstatic inline uint64_t  //\nwuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {\n  uint64_t res = (uint64_t)(x - y);\n  res &= (uint64_t)(-(res <= x));\n  return res;\n}\n\n  " +
+	"_t res = (uint32_t)(x + y);\n  res |= (uint32_t)(-(res < x));\n  return res;\n}\n\nstatic inline uint32_t  //\nwuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {\n  uint32_t res = (uint32_t)(x - y);\n  res &= (uint32_t)(-(res <= x));\n  return res;\n}\n\nstatic inline uint64_t  //\nwuffs_base__u64__sat_add(uint64_t x, uint64_t y) {\n  uint64_t res = (uint64_t)(x + y);\n  res |= (uint64_t)(-(res < x));\n  return res;\n}\n\nstatic inline uint64_t  //\nwuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {\n  uint64_t res = (uint64_t)(x - y);\n  res &= (uint64_t)(-(res <= x));\n  return res;\n}\n\n" +
+	"" +
+	"// --------\n\ntypedef struct {\n  uint64_t hi;\n  uint64_t lo;\n} wuffs_base__multiply_u64__output;\n\n// wuffs_base__multiply_u64 returns x*y as a 128-bit value.\n//\n// The maximum inclusive output hi_lo is 0xFFFFFFFFFFFFFFFE_0000000000000001.\nstatic inline wuffs_base__multiply_u64__output  //\nwuffs_base__multiply_u64(uint64_t x, uint64_t y) {\n  uint64_t x0 = x & 0xFFFFFFFF;\n  uint64_t x1 = x >> 32;\n  uint64_t y0 = y & 0xFFFFFFFF;\n  uint64_t y1 = y >> 32;\n  uint64_t w0 = x0 * y0;\n  uint64_t t = (x1 * y0) + (w0 >> 32);\n  uint64_t w1 = t & 0xFFFFFFFF;\n  uint64_t w2 = t >> 32;\n  w1 += x0 * y1;\n  wuffs_base__multiply_u64__output o;\n  o.hi = (x1 * y1) + w2 + (w1 >> 32);\n  o.lo = x * y;\n  return o;\n}\n\n  " +
+	"" +
+	"// --------\n\n#if defined(__GNUC__) && (__SIZEOF_LONG__ == 8)\n\nstatic inline uint32_t  //\nwuffs_base__count_leading_zeroes_u64(uint64_t u) {\n  return u ? ((uint32_t)(__builtin_clzl(u))) : 64u;\n}\n\n#else\n\nstatic inline uint32_t  //\nwuffs_base__count_leading_zeroes_u64(uint64_t u) {\n  if (u == 0) {\n    return 64;\n  }\n\n  uint32_t n = 0;\n  if ((u >> 32) == 0) {\n    n |= 32;\n    u <<= 32;\n  }\n  if ((u >> 48) == 0) {\n    n |= 16;\n    u <<= 16;\n  }\n  if ((u >> 56) == 0) {\n    n |= 8;\n    u <<= 8;\n  }\n  if ((u >> 60) == 0) {\n    n |= 4;\n    u <<= 4;\n  }\n  if ((u >> 62) == 0) {\n    n |= 2;\n    u <<= 2;\n  }\n  if ((u >> 63) == 0) {\n    n |= 1;\n    u <<= 1;\n  }\n  return n;\n}\n\n#endif  // defined(__GNUC__) && (__SIZEOF_LONG__ == 8)\n\n  " +
 	"" +
 	"// --------\n\n#define wuffs_base__load_u8be__no_bounds_check \\\n  wuffs_base__load_u8__no_bounds_check\n#define wuffs_base__load_u8le__no_bounds_check \\\n  wuffs_base__load_u8__no_bounds_check\n\nstatic inline uint8_t  //\nwuffs_base__load_u8__no_bounds_check(uint8_t* p) {\n  return p[0];\n}\n\nstatic inline uint16_t  //\nwuffs_base__load_u16be__no_bounds_check(uint8_t* p) {\n  return (uint16_t)(((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0));\n}\n\nstatic inline uint16_t  //\nwuffs_base__load_u16le__no_bounds_check(uint8_t* p) {\n  return (uint16_t)(((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8));\n}\n\nstatic inline uint32_t  //\nwuffs_base__load_u24be__no_bounds_check(uint8_t* p) {\n  return ((uint32_t)(p[0]) << 16) | ((uint32_t)(p[1]) << 8) |\n         ((uint32_t)(p[2]) << 0);\n}\n\nstatic inline uint32_t  //\nwuffs_base__load_u24le__no_bounds_check(uint8_t* p) {\n  return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |\n         ((uint32_t)(p[2]) << 16);\n}\n\nstatic inline uint32_t  //\nwuffs_base__load_u32be__no_bounds_check(" +
 	"uint8_t* p) {\n  return ((uint32_t)(p[0]) << 24) | ((uint32_t)(p[1]) << 16) |\n         ((uint32_t)(p[2]) << 8) | ((uint32_t)(p[3]) << 0);\n}\n\nstatic inline uint32_t  //\nwuffs_base__load_u32le__no_bounds_check(uint8_t* p) {\n  return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |\n         ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);\n}\n\nstatic inline uint64_t  //\nwuffs_base__load_u40be__no_bounds_check(uint8_t* p) {\n  return ((uint64_t)(p[0]) << 32) | ((uint64_t)(p[1]) << 24) |\n         ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 8) |\n         ((uint64_t)(p[4]) << 0);\n}\n\nstatic inline uint64_t  //\nwuffs_base__load_u40le__no_bounds_check(uint8_t* p) {\n  return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |\n         ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |\n         ((uint64_t)(p[4]) << 32);\n}\n\nstatic inline uint64_t  //\nwuffs_base__load_u48be__no_bounds_check(uint8_t* p) {\n  return ((uint64_t)(p[0]) << 40) | ((uint64_t)(p[1]) << 32) |\n         ((uint64_t)(p[2]) << 24) | ((uint64_t)" +
@@ -268,10 +297,11 @@
 	""
 
 const baseIOPublicH = "" +
-	"// ---------------- I/O\n//\n// See (/doc/note/io-input-output.md).\n\n// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's\n// data.\ntypedef struct {\n  size_t wi;     // Write index. Invariant: wi <= len.\n  size_t ri;     // Read  index. Invariant: ri <= wi.\n  uint64_t pos;  // Position of the buffer start relative to the stream start.\n  bool closed;   // No further writes are expected.\n} wuffs_base__io_buffer_meta;\n\n// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus\n// additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct {\n  wuffs_base__slice_u8 data;\n  wuffs_base__io_buffer_meta meta;\n\n#ifdef __cplusplus\n  inline void compact();\n  inline uint64_t reader_available() const;\n  inline uint64_t reader_io_position() const;\n  inline uint64_t writer_available() const;\n  inline uint64_t writer_io_position() const;\n#endif  // __cplusplus\n\n} wuffs_base__io_buffer;\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__make_io_buff" +
-	"er(wuffs_base__slice_u8 data,\n                           wuffs_base__io_buffer_meta meta) {\n  wuffs_base__io_buffer ret;\n  ret.data = data;\n  ret.meta = meta;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__make_io_buffer_meta(size_t wi,\n                                size_t ri,\n                                uint64_t pos,\n                                bool closed) {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = wi;\n  ret.ri = ri;\n  ret.pos = pos;\n  ret.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__empty_io_buffer() {\n  wuffs_base__io_buffer ret;\n  ret.data.ptr = NULL;\n  ret.data.len = 0;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__empty_io_buffer_meta() {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = 0;\n  ret.ri = 0;\n  ret.pos = 0;\n  ret.closed = false;\n  return ret;\n}\n\n// wuffs_base__io_buffer__compact moves any written but unr" +
-	"ead bytes to the\n// start of the buffer.\nstatic inline void  //\nwuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {\n  if (!buf || (buf->meta.ri == 0)) {\n    return;\n  }\n  buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n  size_t n = buf->meta.wi - buf->meta.ri;\n  if (n != 0) {\n    memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);\n  }\n  buf->meta.wi = n;\n  buf->meta.ri = 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {\n  return bu" +
-	"f ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus\n\ninline void  //\nwuffs_base__io_buffer::compact() {\n  wuffs_base__io_buffer__compact(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::reader_available() const {\n  return wuffs_base__io_buffer__reader_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::reader_io_position() const {\n  return wuffs_base__io_buffer__reader_io_position(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::writer_available() const {\n  return wuffs_base__io_buffer__writer_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::writer_io_position() const {\n  return wuffs_base__io_buffer__writer_io_position(this);\n}\n\n#endif  // __cplusplus\n" +
+	"// ---------------- I/O\n//\n// See (/doc/note/io-input-output.md).\n\n// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's\n// data.\ntypedef struct {\n  size_t wi;     // Write index. Invariant: wi <= len.\n  size_t ri;     // Read  index. Invariant: ri <= wi.\n  uint64_t pos;  // Position of the buffer start relative to the stream start.\n  bool closed;   // No further writes are expected.\n} wuffs_base__io_buffer_meta;\n\n// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus\n// additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct {\n  wuffs_base__slice_u8 data;\n  wuffs_base__io_buffer_meta meta;\n\n#ifdef __cplusplus\n  inline bool is_valid() const;\n  inline void compact();\n  inline uint64_t reader_available() const;\n  inline uint64_t reader_io_position() const;\n  inline uint64_t writer_available() const;\n  inline uint64_t writer_io_position() const;\n#endif  // __cplusplus\n\n} wuffs_base__io_buffer;\n\nstatic inline wuffs_base__io_buf" +
+	"fer  //\nwuffs_base__make_io_buffer(wuffs_base__slice_u8 data,\n                           wuffs_base__io_buffer_meta meta) {\n  wuffs_base__io_buffer ret;\n  ret.data = data;\n  ret.meta = meta;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__make_io_buffer_meta(size_t wi,\n                                size_t ri,\n                                uint64_t pos,\n                                bool closed) {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = wi;\n  ret.ri = ri;\n  ret.pos = pos;\n  ret.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__make_io_buffer_reader(wuffs_base__slice_u8 s, bool closed) {\n  wuffs_base__io_buffer ret;\n  ret.data.ptr = s.ptr;\n  ret.data.len = s.len;\n  ret.meta.wi = s.len;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__make_io_buffer_writer(wuffs_base__slice_u8 s) {\n  wuffs_base__io_buffer ret;\n  ret.data.ptr = s.ptr;\n  ret.data.len = s.le" +
+	"n;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer  //\nwuffs_base__empty_io_buffer() {\n  wuffs_base__io_buffer ret;\n  ret.data.ptr = NULL;\n  ret.data.len = 0;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__io_buffer_meta  //\nwuffs_base__empty_io_buffer_meta() {\n  wuffs_base__io_buffer_meta ret;\n  ret.wi = 0;\n  ret.ri = 0;\n  ret.pos = 0;\n  ret.closed = false;\n  return ret;\n}\n\nstatic inline bool  //\nwuffs_base__io_buffer__is_valid(const wuffs_base__io_buffer* buf) {\n  if (buf) {\n    if (buf->data.ptr) {\n      return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);\n    } else {\n      return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);\n    }\n  }\n  return false;\n}\n\n// wuffs_base__io_buffer__compact moves any written but unread bytes to the\n// start of the buffer.\nstatic inline void  //\nwuffs_base__io_buffe" +
+	"r__compact(wuffs_base__io_buffer* buf) {\n  if (!buf || (buf->meta.ri == 0)) {\n    return;\n  }\n  buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n  size_t n = buf->meta.wi - buf->meta.ri;\n  if (n != 0) {\n    memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);\n  }\n  buf->meta.wi = n;\n  buf->meta.ri = 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_available(const wuffs_base__io_buffer* buf) {\n  return buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus" +
+	"\n\ninline bool  //\nwuffs_base__io_buffer::is_valid() const {\n  return wuffs_base__io_buffer__is_valid(this);\n}\n\ninline void  //\nwuffs_base__io_buffer::compact() {\n  wuffs_base__io_buffer__compact(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::reader_available() const {\n  return wuffs_base__io_buffer__reader_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::reader_io_position() const {\n  return wuffs_base__io_buffer__reader_io_position(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::writer_available() const {\n  return wuffs_base__io_buffer__writer_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__io_buffer::writer_io_position() const {\n  return wuffs_base__io_buffer__writer_io_position(this);\n}\n\n#endif  // __cplusplus\n" +
 	""
 
 const baseRangePrivateH = "" +
@@ -328,7 +358,10 @@
 	"" +
 	"// ---------------- IEEE 754 Floating Point\n\n// wuffs_base__parse_number_f64 parses the floating point number in s. For\n// example, if s contains the bytes \"1.5\" then it will return the double 1.5.\n//\n// It returns an error if s does not contain a floating point number.\n//\n// It does not necessarily return an error if the conversion is lossy, e.g. if\n// s is \"0.3\", which double-precision floating point cannot represent exactly.\n//\n// Similarly, the returned value may be infinite (and no error returned) even\n// if s was not \"inf\", when the input is nominally finite but sufficiently\n// larger than DBL_MAX, about 1.8e+308.\n//\n// It is similar to the C standard library's strtod function, but:\n//  - Errors are returned in-band (in a result type), not out-of-band (errno).\n//  - It takes a slice (a pointer and length), not a NUL-terminated C string.\n//  - It does not take an optional endptr argument. It does not allow a partial\n//    parse: it returns an error unless all of s is consumed.\n//  - It does not allow whi" +
 	"tespace, leading or otherwise.\n//  - It does not allow unnecessary leading zeroes (\"0\" is valid and its sole\n//    zero is necessary). All of \"00\", \"0644\" and \"00.7\" are invalid.\n//  - It is not affected by i18n / l10n settings such as environment variables.\n//  - Conversely, it always accepts either ',' or '.' as a decimal separator.\n//    In particular, \"3,141,592\" is always invalid but \"3,141\" is always valid\n//    (and approximately π). The caller is responsible for e.g. previously\n//    rejecting or filtering s if it contains a comma, if that is unacceptable\n//    to the caller. For example, JSON numbers always use a dot '.' and never a\n//    comma ',', regardless of the LOCALE environment variable.\n//  - It does allow arbitrary underscores. For example, \"_3.141_592\" would\n//    successfully parse, again approximately π.\n//  - It does allow \"inf\", \"+Infinity\" and \"-NAN\", case insensitive, but it\n//    does not permit \"nan\" to be followed by an integer mantissa.\n//  - It does not allow hexadecimal float" +
-	"ing point numbers.\nwuffs_base__result_f64  //\nwuffs_base__parse_number_f64(wuffs_base__slice_u8 s);\n\n// wuffs_base__ieee_754_bit_representation__etc converts between a double\n// precision numerical value and its IEEE 754 64-bit representation (1 sign\n// bit, 11 exponent bits, 52 explicit significand bits).\n//\n// For example, it converts between:\n//  - +1.0 and 0x3FF0_0000_0000_0000.\n//  - +5.5 and 0x4016_0000_0000_0000.\n//  - -inf and 0xFFF0_0000_0000_0000.\n//\n// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format\n\nstatic inline uint64_t  //\nwuffs_base__ieee_754_bit_representation__from_f64(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  return u;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__to_f64(uint64_t u) {\n  double f = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&f, &u, sizeof(uint64_t));\n  }\n  return f;\n}\n\n  " +
+	"ing point numbers.\nwuffs_base__result_f64  //\nwuffs_base__parse_number_f64(wuffs_base__slice_u8 s);\n\n// wuffs_base__ieee_754_bit_representation__etc converts between a double\n// precision numerical value and its IEEE 754 64-bit representation (1 sign\n// bit, 11 exponent bits, 52 explicit significand bits).\n//\n// For example, it converts between:\n//  - +1.0 and 0x3FF0_0000_0000_0000.\n//  - +5.5 and 0x4016_0000_0000_0000.\n//  - -inf and 0xFFF0_0000_0000_0000.\n//\n// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format\n\nstatic inline uint64_t  //\nwuffs_base__ieee_754_bit_representation__from_f64(double f) {\n  uint64_t u = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&u, &f, sizeof(uint64_t));\n  }\n  return u;\n}\n\nstatic inline double  //\nwuffs_base__ieee_754_bit_representation__to_f64(uint64_t u) {\n  double f = 0;\n  if (sizeof(uint64_t) == sizeof(double)) {\n    memcpy(&f, &u, sizeof(uint64_t));\n  }\n  return f;\n}\n\n" +
+	"" +
+	"// ---------------- Hexadecimal\n\n// wuffs_base__hexadecimal__decode2 converts \"6A6b\" to \"jk\", where e.g. 'j' is\n// U+006A. There are 2 source bytes for every destination byte.\n//\n// It returns the number of dst bytes written: the minimum of dst.len and\n// (src.len / 2). Excess source bytes are ignored.\n//\n// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),\n// repeated. It may write nonsense bytes if not, although it will not read or\n// write out of bounds.\nsize_t  //\nwuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,\n                                 wuffs_base__slice_u8 src);\n\n// wuffs_base__hexadecimal__decode4 converts \"\\\\x6A\\\\x6b\" to \"jk\", where e.g.\n// 'j' is U+006A. There are 4 source bytes for every destination byte.\n//\n// It returns the number of dst bytes written: the minimum of dst.len and\n// (src.len / 4). Excess source bytes are ignored.\n//\n// It assumes that the src bytes are two ignored bytes and then two hexadecimal\n// digits (0-9, A-F, a-f), repeated. It may wri" +
+	"te nonsense bytes if not,\n// although it will not read or write out of bounds.\nsize_t  //\nwuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,\n                                 wuffs_base__slice_u8 src);\n\n" +
 	"" +
 	"// ---------------- Unicode and UTF-8\n\n#define WUFFS_BASE__UNICODE_CODE_POINT__MIN_INCL 0x00000000\n#define WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL 0x0010FFFF\n\n#define WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER 0x0000FFFD\n\n#define WUFFS_BASE__UNICODE_SURROGATE__MIN_INCL 0x0000D800\n#define WUFFS_BASE__UNICODE_SURROGATE__MAX_INCL 0x0000DFFF\n\n#define WUFFS_BASE__ASCII__MIN_INCL 0x00\n#define WUFFS_BASE__ASCII__MAX_INCL 0x7F\n\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MIN_INCL 1\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL 4\n\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MIN_INCL 0x00000000\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MAX_INCL 0x0000007F\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MIN_INCL 0x00000080\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MAX_INCL 0x000007FF\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MIN_INCL 0x00000800\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MAX_INCL 0x0000FFFF\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT_" +
 	"_MIN_INCL 0x00010000\n#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MAX_INCL 0x0010FFFF\n\n" +
@@ -365,8 +398,8 @@
 	"" +
 	"// --------\n\n#define WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED 0x00001\n#define WUFFS_BASE__TOKEN__VBD__LITERAL__NULL 0x00002\n#define WUFFS_BASE__TOKEN__VBD__LITERAL__FALSE 0x00004\n#define WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE 0x00008\n\n  " +
 	"" +
-	"// --------\n\n// For a source string of \"123\" or \"0x9A\", it is valid for a tokenizer to\n// return any one of:\n//  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT.\n//  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED.\n//  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED.\n//\n// For a source string of \"+123\" or \"-0x9A\", only the first two are valid.\n//\n// For a source string of \"123.\", only the first one is valid.\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT 0x00001\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004\n\n// The number 300 might be represented as \"\\x01\\x2C\", \"\\x2C\\x01\\x00\\x00\" or\n// \"300\", which are big-endian, little-endian or text. For binary formats, the\n// token length discriminates e.g. u16 little-endian vs u32 little-endian.\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_LITTLE_END" +
-	"IAN 0x00200\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400\n\n" +
+	"// --------\n\n// For a source string of \"123\" or \"0x9A\", it is valid for a tokenizer to\n// return any one of:\n//  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT.\n//  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED.\n//  - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED.\n//\n// For a source string of \"+123\" or \"-0x9A\", only the first two are valid.\n//\n// For a source string of \"123.\", only the first one is valid.\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT 0x00001\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004\n\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF 0x00010\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF 0x00020\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN 0x00040\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN 0x00080\n\n// The number 300 might be represented as \"\\x01\\x2C\", \"\\x2C\\x01\\x00\\x00\" or\n// \"300\", which are big-endian, li" +
+	"ttle-endian or text. For binary formats, the\n// token length discriminates e.g. u16 little-endian vs u32 little-endian.\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_LITTLE_ENDIAN 0x00200\n#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400\n\n" +
 	"" +
 	"// --------\n\nstatic inline uint64_t  //\nwuffs_base__token__value(const wuffs_base__token* t) {\n  return (t->repr >> WUFFS_BASE__TOKEN__VALUE__SHIFT) &\n         WUFFS_BASE__TOKEN__VALUE__MASK;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token__value_major(const wuffs_base__token* t) {\n  return (t->repr >> WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) &\n         WUFFS_BASE__TOKEN__VALUE_MAJOR__MASK;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token__value_minor(const wuffs_base__token* t) {\n  return (t->repr >> WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) &\n         WUFFS_BASE__TOKEN__VALUE_MINOR__MASK;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token__value_base_category(const wuffs_base__token* t) {\n  return (t->repr >> WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__SHIFT) &\n         WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__MASK;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token__value_base_detail(const wuffs_base__token* t) {\n  return (t->repr >> WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT) &\n         WUFFS_BASE__TOKEN__VALUE_BASE_DETA" +
 	"IL__MASK;\n}\n\nstatic inline bool  //\nwuffs_base__token__link_prev(const wuffs_base__token* t) {\n  return t->repr & WUFFS_BASE__TOKEN__LINK_PREV;\n}\n\nstatic inline bool  //\nwuffs_base__token__link_next(const wuffs_base__token* t) {\n  return t->repr & WUFFS_BASE__TOKEN__LINK_NEXT;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token__length(const wuffs_base__token* t) {\n  return (t->repr >> WUFFS_BASE__TOKEN__LENGTH__SHIFT) &\n         WUFFS_BASE__TOKEN__LENGTH__MASK;\n}\n\n#ifdef __cplusplus\n\ninline uint64_t  //\nwuffs_base__token::value() const {\n  return wuffs_base__token__value(this);\n}\n\ninline uint64_t  //\nwuffs_base__token::value_major() const {\n  return wuffs_base__token__value_major(this);\n}\n\ninline uint64_t  //\nwuffs_base__token::value_minor() const {\n  return wuffs_base__token__value_minor(this);\n}\n\ninline uint64_t  //\nwuffs_base__token::value_base_category() const {\n  return wuffs_base__token__value_base_category(this);\n}\n\ninline uint64_t  //\nwuffs_base__token::value_base_detail() const {\n  return wuffs_base__to" +
@@ -374,10 +407,11 @@
 	"" +
 	"// --------\n\ntypedef WUFFS_BASE__SLICE(wuffs_base__token) wuffs_base__slice_token;\n\nstatic inline wuffs_base__slice_token  //\nwuffs_base__make_slice_token(wuffs_base__token* ptr, size_t len) {\n  wuffs_base__slice_token ret;\n  ret.ptr = ptr;\n  ret.len = len;\n  return ret;\n}\n\n" +
 	"" +
-	"// --------\n\n// wuffs_base__token_buffer_meta is the metadata for a\n// wuffs_base__token_buffer's data.\ntypedef struct {\n  size_t wi;     // Write index. Invariant: wi <= len.\n  size_t ri;     // Read  index. Invariant: ri <= wi.\n  uint64_t pos;  // Position of the buffer start relative to the stream start.\n  bool closed;   // No further writes are expected.\n} wuffs_base__token_buffer_meta;\n\n// wuffs_base__token_buffer is a 1-dimensional buffer (a pointer and length)\n// plus additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct {\n  wuffs_base__slice_token data;\n  wuffs_base__token_buffer_meta meta;\n\n#ifdef __cplusplus\n  inline void compact();\n  inline uint64_t reader_available() const;\n  inline uint64_t reader_token_position() const;\n  inline uint64_t writer_available() const;\n  inline uint64_t writer_token_position() const;\n#endif  // __cplusplus\n\n} wuffs_base__token_buffer;\n\nstatic inline wuffs_base__token_buffer  //\nwuffs_base__make_token_buffer(wuffs_base__slice_" +
-	"token data,\n                              wuffs_base__token_buffer_meta meta) {\n  wuffs_base__token_buffer ret;\n  ret.data = data;\n  ret.meta = meta;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer_meta  //\nwuffs_base__make_token_buffer_meta(size_t wi,\n                                   size_t ri,\n                                   uint64_t pos,\n                                   bool closed) {\n  wuffs_base__token_buffer_meta ret;\n  ret.wi = wi;\n  ret.ri = ri;\n  ret.pos = pos;\n  ret.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer  //\nwuffs_base__empty_token_buffer() {\n  wuffs_base__token_buffer ret;\n  ret.data.ptr = NULL;\n  ret.data.len = 0;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer_meta  //\nwuffs_base__empty_token_buffer_meta() {\n  wuffs_base__token_buffer_meta ret;\n  ret.wi = 0;\n  ret.ri = 0;\n  ret.pos = 0;\n  ret.closed = false;\n  return ret;\n}\n\n// wuffs_base__token_buffer__com" +
-	"pact moves any written but unread tokens to the\n// start of the buffer.\nstatic inline void  //\nwuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) {\n  if (!buf || (buf->meta.ri == 0)) {\n    return;\n  }\n  buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n  size_t n = buf->meta.wi - buf->meta.ri;\n  if (n != 0) {\n    memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri,\n            n * sizeof(wuffs_base__token));\n  }\n  buf->meta.wi = n;\n  buf->meta.ri = 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__reader_available(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__reader_token_position(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__writer_available(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nsta" +
-	"tic inline uint64_t  //\nwuffs_base__token_buffer__writer_token_position(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus\n\ninline void  //\nwuffs_base__token_buffer::compact() {\n  wuffs_base__token_buffer__compact(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::reader_available() const {\n  return wuffs_base__token_buffer__reader_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::reader_token_position() const {\n  return wuffs_base__token_buffer__reader_token_position(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::writer_available() const {\n  return wuffs_base__token_buffer__writer_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::writer_token_position() const {\n  return wuffs_base__token_buffer__writer_token_position(this);\n}\n\n#endif  // __cplusplus\n" +
+	"// --------\n\n// wuffs_base__token_buffer_meta is the metadata for a\n// wuffs_base__token_buffer's data.\ntypedef struct {\n  size_t wi;     // Write index. Invariant: wi <= len.\n  size_t ri;     // Read  index. Invariant: ri <= wi.\n  uint64_t pos;  // Position of the buffer start relative to the stream start.\n  bool closed;   // No further writes are expected.\n} wuffs_base__token_buffer_meta;\n\n// wuffs_base__token_buffer is a 1-dimensional buffer (a pointer and length)\n// plus additional metadata.\n//\n// A value with all fields zero is a valid, empty buffer.\ntypedef struct {\n  wuffs_base__slice_token data;\n  wuffs_base__token_buffer_meta meta;\n\n#ifdef __cplusplus\n  inline bool is_valid() const;\n  inline void compact();\n  inline uint64_t reader_available() const;\n  inline uint64_t reader_token_position() const;\n  inline uint64_t writer_available() const;\n  inline uint64_t writer_token_position() const;\n#endif  // __cplusplus\n\n} wuffs_base__token_buffer;\n\nstatic inline wuffs_base__token_buffer  //\nwuffs_base__make" +
+	"_token_buffer(wuffs_base__slice_token data,\n                              wuffs_base__token_buffer_meta meta) {\n  wuffs_base__token_buffer ret;\n  ret.data = data;\n  ret.meta = meta;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer_meta  //\nwuffs_base__make_token_buffer_meta(size_t wi,\n                                   size_t ri,\n                                   uint64_t pos,\n                                   bool closed) {\n  wuffs_base__token_buffer_meta ret;\n  ret.wi = wi;\n  ret.ri = ri;\n  ret.pos = pos;\n  ret.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer  //\nwuffs_base__make_token_buffer_reader(wuffs_base__slice_token s, bool closed) {\n  wuffs_base__token_buffer ret;\n  ret.data.ptr = s.ptr;\n  ret.data.len = s.len;\n  ret.meta.wi = s.len;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = closed;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer  //\nwuffs_base__make_token_buffer_writer(wuffs_base__slice_token s) {\n  wuffs_base__token_buffer ret;\n  ret.data.p" +
+	"tr = s.ptr;\n  ret.data.len = s.len;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer  //\nwuffs_base__empty_token_buffer() {\n  wuffs_base__token_buffer ret;\n  ret.data.ptr = NULL;\n  ret.data.len = 0;\n  ret.meta.wi = 0;\n  ret.meta.ri = 0;\n  ret.meta.pos = 0;\n  ret.meta.closed = false;\n  return ret;\n}\n\nstatic inline wuffs_base__token_buffer_meta  //\nwuffs_base__empty_token_buffer_meta() {\n  wuffs_base__token_buffer_meta ret;\n  ret.wi = 0;\n  ret.ri = 0;\n  ret.pos = 0;\n  ret.closed = false;\n  return ret;\n}\n\nstatic inline bool  //\nwuffs_base__token_buffer__is_valid(const wuffs_base__token_buffer* buf) {\n  if (buf) {\n    if (buf->data.ptr) {\n      return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);\n    } else {\n      return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);\n    }\n  }\n  return false;\n}\n\n// wuffs_base__token_buffer__compact moves any written but unread tokens to the\n// sta" +
+	"rt of the buffer.\nstatic inline void  //\nwuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) {\n  if (!buf || (buf->meta.ri == 0)) {\n    return;\n  }\n  buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);\n  size_t n = buf->meta.wi - buf->meta.ri;\n  if (n != 0) {\n    memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri,\n            n * sizeof(wuffs_base__token));\n  }\n  buf->meta.wi = n;\n  buf->meta.ri = 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__reader_available(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? buf->meta.wi - buf->meta.ri : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__reader_token_position(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__writer_available(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? buf->data.len - buf->meta.wi : 0;\n}\n\nstatic inline uint64_t  //\nwuffs_base__token_buffer__writ" +
+	"er_token_position(\n    const wuffs_base__token_buffer* buf) {\n  return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;\n}\n\n#ifdef __cplusplus\n\ninline bool  //\nwuffs_base__token_buffer::is_valid() const {\n  return wuffs_base__token_buffer__is_valid(this);\n}\n\ninline void  //\nwuffs_base__token_buffer::compact() {\n  wuffs_base__token_buffer__compact(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::reader_available() const {\n  return wuffs_base__token_buffer__reader_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::reader_token_position() const {\n  return wuffs_base__token_buffer__reader_token_position(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::writer_available() const {\n  return wuffs_base__token_buffer__writer_available(this);\n}\n\ninline uint64_t  //\nwuffs_base__token_buffer::writer_token_position() const {\n  return wuffs_base__token_buffer__writer_token_position(this);\n}\n\n#endif  // __cplusplus\n" +
 	""
 
 const baseCopyright = "" +
diff --git a/internal/cgen/expr.go b/internal/cgen/expr.go
index 7c2874d..3dd3898 100644
--- a/internal/cgen/expr.go
+++ b/internal/cgen/expr.go
@@ -70,7 +70,7 @@
 				b.writes("false")
 			}
 
-		} else if ident.IsStrLiteral(g.tm) {
+		} else if ident.IsDQStrLiteral(g.tm) {
 			if z := g.statusMap[n.StatusQID()]; z.cName != "" {
 				b.writes("wuffs_base__make_status(")
 				b.writes(z.cName)
diff --git a/internal/cgen/func.go b/internal/cgen/func.go
index 13df2ca..1d5bd58 100644
--- a/internal/cgen/func.go
+++ b/internal/cgen/func.go
@@ -374,11 +374,17 @@
 		// TODO: don't hard-code [0], and allow recursive coroutines.
 		b.printf("uint32_t coro_susp_point = self->private_impl.%s%s[0];\n",
 			pPrefix, g.currFunk.astFunc.FuncName().Str(g.tm))
-		b.printf("if (coro_susp_point) {\n")
-		if err := g.writeResumeSuspend(b, &g.currFunk, false); err != nil {
+
+		resumeBuffer := buffer{}
+		if err := g.writeResumeSuspend(&resumeBuffer, &g.currFunk, false); err != nil {
 			return err
 		}
-		b.writes("}\n")
+		if len(resumeBuffer) > 0 {
+			b.writes("if (coro_susp_point) {\n")
+			b.writex(resumeBuffer)
+			b.writes("}\n")
+		}
+
 		// Generate a coroutine switch similiar to the technique in
 		// https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
 		//
diff --git a/internal/cgen/statement.go b/internal/cgen/statement.go
index b141b64..fd19ad3 100644
--- a/internal/cgen/statement.go
+++ b/internal/cgen/statement.go
@@ -441,7 +441,7 @@
 			b.writes("wuffs_base__make_status(NULL)")
 			isComplete = true
 		} else {
-			if retExpr.Ident().IsStrLiteral(g.tm) {
+			if retExpr.Ident().IsDQStrLiteral(g.tm) {
 				msg, _ := t.Unescape(retExpr.Ident().Str(g.tm))
 				isComplete = statusMsgIsNote(msg)
 			}
diff --git a/lang/ast/ast.go b/lang/ast/ast.go
index 7779f6e..03ee9ce 100644
--- a/lang/ast/ast.go
+++ b/lang/ast/ast.go
@@ -236,6 +236,13 @@
 	return nil
 }
 
+func dropExprCachedMBounds(n *Node) error {
+	if n.kind == KExpr {
+		n.mBounds = interval.IntRange{nil, nil}
+	}
+	return nil
+}
+
 type Loop interface {
 	AsNode() *Node
 	HasBreak() bool
@@ -379,7 +386,7 @@
 
 // Assert is "assert RHS via ID2(args)", "pre etc", "inv etc" or "post etc":
 //  - ID0:   <IDAssert|IDPre|IDInv|IDPost>
-//  - ID2:   <string literal> reason
+//  - ID2:   <"-string literal> reason
 //  - RHS:   <Expr>
 //  - List0: <Arg> reason arguments
 type Assert Node
@@ -390,6 +397,8 @@
 func (n *Assert) Condition() *Expr { return n.rhs.AsExpr() }
 func (n *Assert) Args() []*Node    { return n.list0 }
 
+func (n *Assert) DropExprCachedMBounds() error { return n.AsNode().Walk(dropExprCachedMBounds) }
+
 func NewAssert(keyword t.ID, condition *Expr, reason t.ID, args []*Node) *Assert {
 	return &Assert{
 		kind:  KAssert,
@@ -539,7 +548,7 @@
 	}
 }
 
-// While is "while.ID1 MHS, List1 { List2 }":
+// While is "while.ID1 MHS, List1 { List2 } endwhile.ID1":
 //  - FlagsHasBreak    is the while has an explicit break
 //  - FlagsHasContinue is the while has an explicit continue
 //  - ID1:   <0|label>
@@ -948,7 +957,7 @@
 }
 
 // Use is "use ID2":
-//  - ID2:   <string literal> package path
+//  - ID2:   <"-string literal> package path
 type Use Node
 
 func (n *Use) AsNode() *Node    { return (*Node)(n) }
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index 2ec2221..06ca6e8 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -248,6 +248,11 @@
 	"io_reader.peek_u64be() u64",
 	"io_reader.peek_u64le() u64",
 
+	// As an implementation restriction, we require that offset has a constant
+	// value. The (0x1_0000 - sizeof(u64)) limit is arbitrary, but high enough
+	// in practice.
+	"io_reader.peek_u64le_at(offset: u32[..= 0xFFF8]) u64",
+
 	"io_reader.available() u64",
 	"io_reader.count_since(mark: u64) u64",
 	"io_reader.is_closed() bool",
@@ -417,7 +422,8 @@
 
 	// ---- token_decoder
 
-	"token_decoder.decode_tokens?(dst: token_writer, src: io_reader)",
+	"token_decoder.decode_tokens?(dst: token_writer, src: io_reader, workbuf: slice u8)",
+	"token_decoder.workbuf_len() range_ii_u64",
 }
 
 // The "T1" and "T2" types here are placeholders for generic "slice T" or
diff --git a/lang/check/bounds.go b/lang/check/bounds.go
index 2bdfa85..48ce697 100644
--- a/lang/check/bounds.go
+++ b/lang/check/bounds.go
@@ -357,6 +357,10 @@
 }
 
 func (q *checker) bcheckAssert(n *a.Assert) error {
+	if err := n.DropExprCachedMBounds(); err != nil {
+		return err
+	}
+
 	condition := n.Condition()
 	if _, err := q.bcheckExpr(condition, 0); err != nil {
 		return err
@@ -1068,10 +1072,22 @@
 			} else if err != nil {
 				return bounds{}, err
 			}
-			advance, update = worstCase.ConstValue(), true
-			if advance == nil {
+			if worstCase.ConstValue() == nil {
 				return bounds{}, fmt.Errorf("check: skip_fast worst_case is not a constant value")
 			}
+			advance, update = worstCase.ConstValue(), true
+
+		} else if method == t.IDPeekU64LEAt {
+			args := n.Args()
+			if len(args) != 1 {
+				return bounds{}, fmt.Errorf("check: internal error: bad peek_u64le_at arguments")
+			}
+			offset := args[0].AsArg().Value()
+			if offset.ConstValue() == nil {
+				return bounds{}, fmt.Errorf("check: peek_u64le_at offset is not a constant value")
+			}
+			advance, update = big.NewInt(8), false
+			advance.Add(advance, offset.ConstValue())
 
 		} else if method >= t.IDPeekU8 {
 			if m := method - t.IDPeekU8; m < t.ID(len(ioMethodAdvances)) {
diff --git a/lang/check/type.go b/lang/check/type.go
index 50da53a..7a0da26 100644
--- a/lang/check/type.go
+++ b/lang/check/type.go
@@ -364,7 +364,28 @@
 			n.SetMType(typeExprIdeal)
 			return nil
 
-		} else if id1.IsStrLiteral(q.tm) {
+		} else if id1.IsSQStrLiteral(q.tm) {
+			s := id1.Str(q.tm)
+			unescaped, ok := t.Unescape(id1.Str(q.tm))
+			if !ok {
+				return fmt.Errorf("check: invalid '-string literal %q", s)
+			}
+
+			z := big.NewInt(0)
+			i, iEnd, iDelta := 0, len(unescaped), +1 // Big-endian.
+			if (len(s) > 2) && (s[len(s)-2] == 'l') {
+				i, iEnd, iDelta = len(unescaped)-1, -1, -1 // Little-endian.
+			}
+			for ; i != iEnd; i += iDelta {
+				z.Lsh(z, 8)
+				z.Or(z, big.NewInt(int64(unescaped[i])))
+			}
+
+			n.SetConstValue(z)
+			n.SetMType(typeExprIdeal)
+			return nil
+
+		} else if id1.IsDQStrLiteral(q.tm) {
 			if _, ok := q.c.statuses[n.StatusQID()]; !ok {
 				return fmt.Errorf("check: unrecognized status %s", n.StatusQID().Str(q.tm))
 			}
diff --git a/lang/parse/parse.go b/lang/parse/parse.go
index ab54a69..3a931cb 100644
--- a/lang/parse/parse.go
+++ b/lang/parse/parse.go
@@ -113,9 +113,9 @@
 	case t.IDUse:
 		p.src = p.src[1:]
 		path := p.peek1()
-		if !path.IsStrLiteral(p.tm) {
+		if !path.IsDQStrLiteral(p.tm) {
 			got := p.tm.ByID(path)
-			return nil, fmt.Errorf(`parse: expected string literal, got %q at %s:%d`, got, p.filename, p.line())
+			return nil, fmt.Errorf(`parse: expected "-string literal, got %q at %s:%d`, got, p.filename, p.line())
 		}
 		p.src = p.src[1:]
 		if x := p.peek1(); x != t.IDSemicolon {
@@ -224,9 +224,9 @@
 			p.src = p.src[1:]
 
 			message := p.peek1()
-			if !message.IsStrLiteral(p.tm) {
+			if !message.IsDQStrLiteral(p.tm) {
 				got := p.tm.ByID(message)
-				return nil, fmt.Errorf(`parse: expected string literal, got %q at %s:%d`, got, p.filename, p.line())
+				return nil, fmt.Errorf(`parse: expected "-string literal, got %q at %s:%d`, got, p.filename, p.line())
 			}
 			if s, _ := t.Unescape(p.tm.ByID(message)); !isStatusMessage(s) {
 				return nil, fmt.Errorf(`parse: status message %q does not start with `+
@@ -604,9 +604,9 @@
 		if p.peek1() == t.IDVia {
 			p.src = p.src[1:]
 			reason = p.peek1()
-			if !reason.IsStrLiteral(p.tm) {
+			if !reason.IsDQStrLiteral(p.tm) {
 				got := p.tm.ByID(reason)
-				return nil, fmt.Errorf(`parse: expected string literal, got %q at %s:%d`, got, p.filename, p.line())
+				return nil, fmt.Errorf(`parse: expected "-string literal, got %q at %s:%d`, got, p.filename, p.line())
 			}
 			p.src = p.src[1:]
 			args, err = p.parseList(t.IDCloseParen, (*parser).parseArgNode)
@@ -649,14 +649,16 @@
 		return false
 	}
 	p.src = p.src[1:]
-	if p.peek1() != t.IDDot {
-		return false
+	if label != 0 {
+		if p.peek1() != t.IDDot {
+			return false
+		}
+		p.src = p.src[1:]
+		if p.peek1() != label {
+			return false
+		}
+		p.src = p.src[1:]
 	}
-	p.src = p.src[1:]
-	if p.peek1() != label {
-		return false
-	}
-	p.src = p.src[1:]
 	return true
 }
 
@@ -737,9 +739,13 @@
 		if err != nil {
 			return nil, err
 		}
-		if (label != 0) && !p.parseEndwhile(label) {
-			return nil, fmt.Errorf(`parse: expected endwhile.%s at %s:%d`,
-				label.Str(p.tm), p.filename, p.line())
+		if !p.parseEndwhile(label) {
+			dotLabel := ""
+			if label != 0 {
+				dotLabel = "." + label.Str(p.tm)
+			}
+			return nil, fmt.Errorf(`parse: expected endwhile%s at %s:%d`,
+				dotLabel, p.filename, p.line())
 		}
 		return a.NewWhile(label, condition, asserts, body).AsNode(), nil
 	}
@@ -1254,11 +1260,11 @@
 			p.src = p.src[1:]
 
 			if x := p.peek1(); x.IsLiteral(p.tm) {
-				if x.IsNumLiteral(p.tm) {
-					return nil, fmt.Errorf(`parse: dot followed by numeric literal at %s:%d`, p.filename, p.line())
+				if !x.IsDQStrLiteral(p.tm) {
+					return nil, fmt.Errorf(`parse: dot followed by non-"-string literal at %s:%d`, p.filename, p.line())
 				}
 				if !first {
-					return nil, fmt.Errorf(`parse: string literal %s has too many package qualifiers at %s:%d`,
+					return nil, fmt.Errorf(`parse: "-string literal %s has too many package qualifiers at %s:%d`,
 						x.Str(p.tm), p.filename, p.line())
 				}
 				p.src = p.src[1:]
diff --git a/lang/render/render.go b/lang/render/render.go
index a42ec18..2efa21b 100644
--- a/lang/render/render.go
+++ b/lang/render/render.go
@@ -291,7 +291,8 @@
 }
 
 func isCloseIdentStrLiteralQuestion(tm *t.Map, x t.ID) bool {
-	return x.IsClose() || x.IsIdent(tm) || x.IsStrLiteral(tm) || (x == t.IDQuestion)
+	return x.IsClose() || x.IsIdent(tm) || x.IsDQStrLiteral(tm) ||
+		x.IsSQStrLiteral(tm) || (x == t.IDQuestion)
 }
 
 func measureVarNameLength(tm *t.Map, lineTokens []t.Token, remaining []t.Token) uint32 {
diff --git a/lang/token/list.go b/lang/token/list.go
index ea2e069..d585c60 100644
--- a/lang/token/list.go
+++ b/lang/token/list.go
@@ -81,7 +81,8 @@
 	return false
 }
 
-func (x ID) IsStrLiteral(m *Map) bool {
+// IsDQStrLiteral returns whether x is a double-quote string literal.
+func (x ID) IsDQStrLiteral(m *Map) bool {
 	if x < nBuiltInIDs {
 		return false
 	} else if s := m.ByID(x); s != "" {
@@ -90,6 +91,16 @@
 	return false
 }
 
+// IsSQStrLiteral returns whether x is a single-quote string literal.
+func (x ID) IsSQStrLiteral(m *Map) bool {
+	if x < nBuiltInIDs {
+		return false
+	} else if s := m.ByID(x); s != "" {
+		return s[0] == '\''
+	}
+	return false
+}
+
 func (x ID) IsIdent(m *Map) bool {
 	if x < nBuiltInIDs {
 		return minBuiltInIdent <= x && x <= maxBuiltInIdent
@@ -544,6 +555,8 @@
 
 	// --------
 
+	IDPeekU64LEAt = ID(0x1A0)
+
 	IDPeekU8 = ID(0x1A1)
 
 	IDPeekU16BE = ID(0x1A2)
@@ -899,6 +912,8 @@
 
 	// --------
 
+	IDPeekU64LEAt: "peek_u64le_at",
+
 	IDPeekU8: "peek_u8",
 
 	IDPeekU16BE: "peek_u16be",
diff --git a/lang/token/token.go b/lang/token/token.go
index b46e4dc..0d821e9 100644
--- a/lang/token/token.go
+++ b/lang/token/token.go
@@ -17,6 +17,7 @@
 import (
 	"errors"
 	"fmt"
+	"unicode/utf8"
 )
 
 const (
@@ -25,11 +26,115 @@
 	maxTokenSize = 1023
 )
 
+var backslashes = [256]byte{
+	'"':  0x22 | 0x80,
+	'\'': 0x27 | 0x80,
+	'/':  0x2F | 0x80,
+	'0':  0x00 | 0x80,
+	'?':  0x3F | 0x80,
+	'\\': 0x5C | 0x80,
+	'a':  0x07 | 0x80,
+	'b':  0x08 | 0x80,
+	'e':  0x1B | 0x80,
+	'f':  0x0C | 0x80,
+	'n':  0x0A | 0x80,
+	'r':  0x0D | 0x80,
+	't':  0x09 | 0x80,
+	'v':  0x0B | 0x80,
+}
+
 func Unescape(s string) (unescaped string, ok bool) {
-	if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+	if len(s) < 2 {
 		return "", false
 	}
-	return s[1 : len(s)-1], true
+	switch s[0] {
+	case '"':
+		if s[len(s)-1] == '"' {
+			s = s[1 : len(s)-1]
+		} else {
+			return "", false
+		}
+	case '\'':
+		if s[len(s)-1] == '\'' {
+			s = s[1 : len(s)-1]
+		} else if (len(s) >= 4) && (s[len(s)-3] == '\'') &&
+			((s[len(s)-2] == 'b') || (s[len(s)-2] == 'l')) &&
+			(s[len(s)-1] == 'e') { // "be" or "le" suffix.
+			s = s[1 : len(s)-3]
+		} else {
+			return "", false
+		}
+	default:
+		return "", false
+	}
+
+	for i := 0; ; i++ {
+		if i == len(s) {
+			// There were no backslashes.
+			return s, true
+		}
+		if s[i] == '\\' {
+			break
+		}
+	}
+
+	// There were backslashes.
+	b := make([]byte, 0, len(s))
+	for i := 0; i < len(s); {
+		if s[i] != '\\' {
+			b = append(b, s[i])
+			i += 1
+			continue
+		} else if i >= (len(s) - 1) {
+			// No-op.
+		} else if x := backslashes[s[i+1]]; x != 0 {
+			b = append(b, x&0x7F)
+			i += 2
+			continue
+		} else if (s[i+1] == 'x') && (i < (len(s) - 3)) {
+			u0 := unhex(s[i+2])
+			u1 := unhex(s[i+3])
+			u := (u0 << 4) | u1
+			if 0 <= u {
+				b = append(b, uint8(u))
+				i += 4
+				continue
+			}
+		} else if (s[i+1] == 'u') && (i < (len(s) - 5)) {
+			u0 := unhex(s[i+2])
+			u1 := unhex(s[i+3])
+			u2 := unhex(s[i+4])
+			u3 := unhex(s[i+5])
+			u := (u0 << 12) | (u1 << 8) | (u2 << 4) | u3
+			if (u >= 0) && utf8.ValidRune(u) {
+				e := [utf8.UTFMax]byte{}
+				n := utf8.EncodeRune(e[:], u)
+				b = append(b, e[:n]...)
+				i += 6
+				continue
+			}
+		} else if (s[i+1] == 'U') && (i < (len(s) - 9)) {
+			u0 := unhex(s[i+2])
+			u1 := unhex(s[i+3])
+			u2 := unhex(s[i+4])
+			u3 := unhex(s[i+5])
+			u4 := unhex(s[i+6])
+			u5 := unhex(s[i+7])
+			u6 := unhex(s[i+8])
+			u7 := unhex(s[i+9])
+			u := (u0 << 28) | (u1 << 24) | (u2 << 20) | (u3 << 16) |
+				(u4 << 12) | (u5 << 8) | (u6 << 4) | u7
+			if (u >= 0) && utf8.ValidRune(u) {
+				e := [utf8.UTFMax]byte{}
+				n := utf8.EncodeRune(e[:], u)
+				b = append(b, e[:n]...)
+				i += 10
+				continue
+			}
+		}
+		return "", false
+	}
+	return string(b), true
 }
 
 type Map struct {
@@ -81,6 +186,18 @@
 	return ""
 }
 
+func unhex(c byte) int32 {
+	switch {
+	case 'A' <= c && c <= 'F':
+		return int32(c) - ('A' - 10)
+	case 'a' <= c && c <= 'f':
+		return int32(c) - ('a' - 10)
+	case '0' <= c && c <= '9':
+		return int32(c) - '0'
+	}
+	return -1
+}
+
 func alpha(c byte) bool {
 	return ('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || (c == '_')
 }
@@ -150,32 +267,45 @@
 			continue
 		}
 
-		// TODO: recognize escapes such as `\t`, `\"` and `\\`. For now, we
-		// assume that strings don't contain control bytes or backslashes.
-		// Neither should be necessary to parse `use "foo/bar"` lines.
-		if c == '"' {
+		if (c == '"') || (c == '\'') {
+			quote := c
 			j := i + 1
-			for ; j < len(src); j++ {
+			for j < len(src) {
 				c = src[j]
-				if c == '"' {
-					j++
+				j++
+				if c == quote {
 					break
-				}
-				if c == '\\' {
-					return nil, nil, fmt.Errorf("token: backslash in string at %s:%d", filename, line)
-				}
-				if c == '\n' {
-					return nil, nil, fmt.Errorf("token: expected final '\"' in string at %s:%d", filename, line)
-				}
-				if c < ' ' {
+				} else if c == '\\' {
+					if quote == '"' {
+						return nil, nil, fmt.Errorf("token: backslash in \"-string at %s:%d", filename, line)
+					}
+				} else if c == '\n' {
+					return nil, nil, fmt.Errorf("token: expected final %c in string at %s:%d", quote, filename, line)
+				} else if c < ' ' {
 					return nil, nil, fmt.Errorf("token: control character in string at %s:%d", filename, line)
 				}
-				// The -1 is because we still haven't seen the final '"'.
-				if j-i == maxTokenSize-1 {
-					return nil, nil, fmt.Errorf("token: string too long at %s:%d", filename, line)
+			}
+
+			hasEndian := (quote == '\'') && (j < (len(src) - 2)) &&
+				((src[j] == 'b') || (src[j] == 'l')) &&
+				(src[j+1] == 'e')
+			if hasEndian {
+				j += 2
+			}
+
+			if j-i > maxTokenSize {
+				return nil, nil, fmt.Errorf("token: string too long at %s:%d", filename, line)
+			}
+			s := string(src[i:j])
+			if quote == '\'' {
+				if unescaped, ok := Unescape(s); !ok {
+					return nil, nil, fmt.Errorf("token: invalid '-string at %s:%d", filename, line)
+				} else if (len(unescaped) > 1) && !hasEndian {
+					return nil, nil, fmt.Errorf("token: multi-byte '-string needs be or le suffix at %s:%d", filename, line)
 				}
 			}
-			id, err := m.Insert(string(src[i:j]))
+
+			id, err := m.Insert(s)
 			if err != nil {
 				return nil, nil, err
 			}
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index c7559dd..e139fb5 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -433,6 +433,80 @@
   return res;
 }
 
+// --------
+
+typedef struct {
+  uint64_t hi;
+  uint64_t lo;
+} wuffs_base__multiply_u64__output;
+
+// wuffs_base__multiply_u64 returns x*y as a 128-bit value.
+//
+// The maximum inclusive output hi_lo is 0xFFFFFFFFFFFFFFFE_0000000000000001.
+static inline wuffs_base__multiply_u64__output  //
+wuffs_base__multiply_u64(uint64_t x, uint64_t y) {
+  uint64_t x0 = x & 0xFFFFFFFF;
+  uint64_t x1 = x >> 32;
+  uint64_t y0 = y & 0xFFFFFFFF;
+  uint64_t y1 = y >> 32;
+  uint64_t w0 = x0 * y0;
+  uint64_t t = (x1 * y0) + (w0 >> 32);
+  uint64_t w1 = t & 0xFFFFFFFF;
+  uint64_t w2 = t >> 32;
+  w1 += x0 * y1;
+  wuffs_base__multiply_u64__output o;
+  o.hi = (x1 * y1) + w2 + (w1 >> 32);
+  o.lo = x * y;
+  return o;
+}
+
+  // --------
+
+#if defined(__GNUC__) && (__SIZEOF_LONG__ == 8)
+
+static inline uint32_t  //
+wuffs_base__count_leading_zeroes_u64(uint64_t u) {
+  return u ? ((uint32_t)(__builtin_clzl(u))) : 64u;
+}
+
+#else
+
+static inline uint32_t  //
+wuffs_base__count_leading_zeroes_u64(uint64_t u) {
+  if (u == 0) {
+    return 64;
+  }
+
+  uint32_t n = 0;
+  if ((u >> 32) == 0) {
+    n |= 32;
+    u <<= 32;
+  }
+  if ((u >> 48) == 0) {
+    n |= 16;
+    u <<= 16;
+  }
+  if ((u >> 56) == 0) {
+    n |= 8;
+    u <<= 8;
+  }
+  if ((u >> 60) == 0) {
+    n |= 4;
+    u <<= 4;
+  }
+  if ((u >> 62) == 0) {
+    n |= 2;
+    u <<= 2;
+  }
+  if ((u >> 63) == 0) {
+    n |= 1;
+    u <<= 1;
+  }
+  return n;
+}
+
+#endif  // defined(__GNUC__) && (__SIZEOF_LONG__ == 8)
+
   // --------
 
 #define wuffs_base__load_u8be__no_bounds_check \
@@ -1613,6 +1687,7 @@
   wuffs_base__io_buffer_meta meta;
 
 #ifdef __cplusplus
+  inline bool is_valid() const;
   inline void compact();
   inline uint64_t reader_available() const;
   inline uint64_t reader_io_position() const;
@@ -1645,6 +1720,30 @@
 }
 
 static inline wuffs_base__io_buffer  //
+wuffs_base__make_io_buffer_reader(wuffs_base__slice_u8 s, bool closed) {
+  wuffs_base__io_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = s.len;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = closed;
+  return ret;
+}
+
+static inline wuffs_base__io_buffer  //
+wuffs_base__make_io_buffer_writer(wuffs_base__slice_u8 s) {
+  wuffs_base__io_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = 0;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = false;
+  return ret;
+}
+
+static inline wuffs_base__io_buffer  //
 wuffs_base__empty_io_buffer() {
   wuffs_base__io_buffer ret;
   ret.data.ptr = NULL;
@@ -1666,6 +1765,18 @@
   return ret;
 }
 
+static inline bool  //
+wuffs_base__io_buffer__is_valid(const wuffs_base__io_buffer* buf) {
+  if (buf) {
+    if (buf->data.ptr) {
+      return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
+    } else {
+      return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
+    }
+  }
+  return false;
+}
+
 // wuffs_base__io_buffer__compact moves any written but unread bytes to the
 // start of the buffer.
 static inline void  //
@@ -1704,6 +1815,11 @@
 
 #ifdef __cplusplus
 
+inline bool  //
+wuffs_base__io_buffer::is_valid() const {
+  return wuffs_base__io_buffer__is_valid(this);
+}
+
 inline void  //
 wuffs_base__io_buffer::compact() {
   wuffs_base__io_buffer__compact(this);
@@ -1897,6 +2013,11 @@
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002
 #define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004
 
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF 0x00010
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF 0x00020
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN 0x00040
+#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN 0x00080
+
 // The number 300 might be represented as "\x01\x2C", "\x2C\x01\x00\x00" or
 // "300", which are big-endian, little-endian or text. For binary formats, the
 // token length discriminates e.g. u16 little-endian vs u32 little-endian.
@@ -2028,6 +2149,7 @@
   wuffs_base__token_buffer_meta meta;
 
 #ifdef __cplusplus
+  inline bool is_valid() const;
   inline void compact();
   inline uint64_t reader_available() const;
   inline uint64_t reader_token_position() const;
@@ -2060,6 +2182,30 @@
 }
 
 static inline wuffs_base__token_buffer  //
+wuffs_base__make_token_buffer_reader(wuffs_base__slice_token s, bool closed) {
+  wuffs_base__token_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = s.len;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = closed;
+  return ret;
+}
+
+static inline wuffs_base__token_buffer  //
+wuffs_base__make_token_buffer_writer(wuffs_base__slice_token s) {
+  wuffs_base__token_buffer ret;
+  ret.data.ptr = s.ptr;
+  ret.data.len = s.len;
+  ret.meta.wi = 0;
+  ret.meta.ri = 0;
+  ret.meta.pos = 0;
+  ret.meta.closed = false;
+  return ret;
+}
+
+static inline wuffs_base__token_buffer  //
 wuffs_base__empty_token_buffer() {
   wuffs_base__token_buffer ret;
   ret.data.ptr = NULL;
@@ -2081,6 +2227,18 @@
   return ret;
 }
 
+static inline bool  //
+wuffs_base__token_buffer__is_valid(const wuffs_base__token_buffer* buf) {
+  if (buf) {
+    if (buf->data.ptr) {
+      return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
+    } else {
+      return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
+    }
+  }
+  return false;
+}
+
 // wuffs_base__token_buffer__compact moves any written but unread tokens to the
 // start of the buffer.
 static inline void  //
@@ -2124,6 +2282,11 @@
 
 #ifdef __cplusplus
 
+inline bool  //
+wuffs_base__token_buffer::is_valid() const {
+  return wuffs_base__token_buffer__is_valid(this);
+}
+
 inline void  //
 wuffs_base__token_buffer::compact() {
   wuffs_base__token_buffer__compact(this);
@@ -3507,7 +3670,35 @@
   return f;
 }
 
-  // ---------------- Unicode and UTF-8
+// ---------------- Hexadecimal
+
+// wuffs_base__hexadecimal__decode2 converts "6A6b" to "jk", where e.g. 'j' is
+// U+006A. There are 2 source bytes for every destination byte.
+//
+// It returns the number of dst bytes written: the minimum of dst.len and
+// (src.len / 2). Excess source bytes are ignored.
+//
+// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
+// repeated. It may write nonsense bytes if not, although it will not read or
+// write out of bounds.
+size_t  //
+wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src);
+
+// wuffs_base__hexadecimal__decode4 converts "\\x6A\\x6b" to "jk", where e.g.
+// 'j' is U+006A. There are 4 source bytes for every destination byte.
+//
+// It returns the number of dst bytes written: the minimum of dst.len and
+// (src.len / 4). Excess source bytes are ignored.
+//
+// It assumes that the src bytes are two ignored bytes and then two hexadecimal
+// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
+// although it will not read or write out of bounds.
+size_t  //
+wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src);
+
+// ---------------- Unicode and UTF-8
 
 #define WUFFS_BASE__UNICODE_CODE_POINT__MIN_INCL 0x00000000
 #define WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL 0x0010FFFF
@@ -3922,7 +4113,9 @@
 typedef struct {
   wuffs_base__status (*decode_tokens)(void* self,
                                       wuffs_base__token_buffer* a_dst,
-                                      wuffs_base__io_buffer* a_src);
+                                      wuffs_base__io_buffer* a_src,
+                                      wuffs_base__slice_u8 a_workbuf);
+  wuffs_base__range_ii_u64 (*workbuf_len)(const void* self);
 } wuffs_base__token_decoder__func_ptrs;
 
 typedef struct wuffs_base__token_decoder__struct wuffs_base__token_decoder;
@@ -3930,7 +4123,11 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_base__token_decoder__decode_tokens(wuffs_base__token_decoder* self,
                                          wuffs_base__token_buffer* a_dst,
-                                         wuffs_base__io_buffer* a_src);
+                                         wuffs_base__io_buffer* a_src,
+                                         wuffs_base__slice_u8 a_workbuf);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64  //
+wuffs_base__token_decoder__workbuf_len(const wuffs_base__token_decoder* self);
 
 #if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
 
@@ -3944,8 +4141,16 @@
 #ifdef __cplusplus
 
   inline wuffs_base__status  //
-  decode_tokens(wuffs_base__token_buffer* a_dst, wuffs_base__io_buffer* a_src) {
-    return wuffs_base__token_decoder__decode_tokens(this, a_dst, a_src);
+  decode_tokens(wuffs_base__token_buffer* a_dst,
+                wuffs_base__io_buffer* a_src,
+                wuffs_base__slice_u8 a_workbuf) {
+    return wuffs_base__token_decoder__decode_tokens(this, a_dst, a_src,
+                                                    a_workbuf);
+  }
+
+  inline wuffs_base__range_ii_u64  //
+  workbuf_len() const {
+    return wuffs_base__token_decoder__workbuf_len(this);
   }
 
 #endif  // __cplusplus
@@ -5791,6 +5996,8 @@
 
 // ---------------- Public Consts
 
+#define WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
+
 #define WUFFS_JSON__DECODER_DEPTH_MAX_INCL 1024
 
 #define WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 1
@@ -5817,7 +6024,7 @@
 
 #define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364489
 
-#define WUFFS_JSON__QUIRK_ALLOW_FINAL_COMMA 1225364490
+#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364490
 
 #define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364491
 
@@ -5827,7 +6034,7 @@
 
 #define WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE 1225364494
 
-#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UTF_8 1225364495
+#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364495
 
 // ---------------- Struct Declarations
 
@@ -5860,10 +6067,19 @@
 
 // ---------------- Public Function Prototypes
 
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct  //
+wuffs_json__decoder__set_quirk_enabled(wuffs_json__decoder* self,
+                                       uint32_t a_quirk,
+                                       bool a_enabled);
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64  //
+wuffs_json__decoder__workbuf_len(const wuffs_json__decoder* self);
+
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_json__decoder__decode_tokens(wuffs_json__decoder* self,
                                    wuffs_base__token_buffer* a_dst,
-                                   wuffs_base__io_buffer* a_src);
+                                   wuffs_base__io_buffer* a_src,
+                                   wuffs_base__slice_u8 a_workbuf);
 
 // ---------------- Struct Definitions
 
@@ -5888,7 +6104,26 @@
     wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
     wuffs_base__vtable null_vtable;
 
+    bool f_quirk_enabled_allow_backslash_etc[8];
+    bool f_quirk_enabled_allow_backslash_capital_u;
+    bool f_quirk_enabled_allow_backslash_x;
+    bool f_quirk_enabled_allow_comment_block;
+    bool f_quirk_enabled_allow_comment_line;
+    bool f_quirk_enabled_allow_extra_comma;
+    bool f_quirk_enabled_allow_inf_nan_numbers;
+    bool f_quirk_enabled_allow_leading_ascii_record_separator;
+    bool f_quirk_enabled_allow_leading_unicode_byte_order_mark;
+    bool f_quirk_enabled_allow_trailing_new_line;
+    bool f_quirk_enabled_replace_invalid_unicode;
+    bool f_allow_leading_ars;
+    bool f_allow_leading_ubom;
+    bool f_end_of_data;
+
     uint32_t p_decode_tokens[1];
+    uint32_t p_decode_leading[1];
+    uint32_t p_decode_comment[1];
+    uint32_t p_decode_inf_nan[1];
+    uint32_t p_decode_trailing_new_line[1];
   } private_impl;
 
   struct {
@@ -5899,6 +6134,12 @@
       uint32_t v_expect;
       uint32_t v_expect_after_value;
     } s_decode_tokens[1];
+    struct {
+      uint32_t v_link_prev;
+    } s_decode_comment[1];
+    struct {
+      uint32_t v_neg;
+    } s_decode_inf_nan[1];
   } private_data;
 
 #ifdef __cplusplus
@@ -5943,9 +6184,21 @@
     return (wuffs_base__token_decoder*)this;
   }
 
+  inline wuffs_base__empty_struct  //
+  set_quirk_enabled(uint32_t a_quirk, bool a_enabled) {
+    return wuffs_json__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
+  }
+
+  inline wuffs_base__range_ii_u64  //
+  workbuf_len() const {
+    return wuffs_json__decoder__workbuf_len(this);
+  }
+
   inline wuffs_base__status  //
-  decode_tokens(wuffs_base__token_buffer* a_dst, wuffs_base__io_buffer* a_src) {
-    return wuffs_json__decoder__decode_tokens(this, a_dst, a_src);
+  decode_tokens(wuffs_base__token_buffer* a_dst,
+                wuffs_base__io_buffer* a_src,
+                wuffs_base__slice_u8 a_workbuf) {
+    return wuffs_json__decoder__decode_tokens(this, a_dst, a_src, a_workbuf);
   }
 
 #endif  // __cplusplus
@@ -7468,7 +7721,8 @@
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_base__token_decoder__decode_tokens(wuffs_base__token_decoder* self,
                                          wuffs_base__token_buffer* a_dst,
-                                         wuffs_base__io_buffer* a_src) {
+                                         wuffs_base__io_buffer* a_src,
+                                         wuffs_base__slice_u8 a_workbuf) {
   if (!self) {
     return wuffs_base__make_status(wuffs_base__error__bad_receiver);
   }
@@ -7485,7 +7739,7 @@
     if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
       const wuffs_base__token_decoder__func_ptrs* func_ptrs =
           (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
-      return (*func_ptrs->decode_tokens)(self, a_dst, a_src);
+      return (*func_ptrs->decode_tokens)(self, a_dst, a_src, a_workbuf);
     } else if (v->vtable_name == NULL) {
       break;
     }
@@ -7495,6 +7749,32 @@
   return wuffs_base__make_status(wuffs_base__error__bad_vtable);
 }
 
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64  //
+wuffs_base__token_decoder__workbuf_len(const wuffs_base__token_decoder* self) {
+  if (!self) {
+    return wuffs_base__utility__empty_range_ii_u64();
+  }
+  if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+      (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+    return wuffs_base__utility__empty_range_ii_u64();
+  }
+
+  const wuffs_base__vtable* v = &self->private_impl.first_vtable;
+  int i;
+  for (i = 0; i < 63; i++) {
+    if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
+      const wuffs_base__token_decoder__func_ptrs* func_ptrs =
+          (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
+      return (*func_ptrs->workbuf_len)(self);
+    } else if (v->vtable_name == NULL) {
+      break;
+    }
+    v++;
+  }
+
+  return wuffs_base__utility__empty_range_ii_u64();
+}
+
 // ---------------- Images
 
 const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
@@ -8739,6 +9019,9 @@
 // fixed precision floating point decimal number, augmented with ±infinity
 // values, but it cannot represent NaN (Not a Number).
 //
+// "High precision" means that the mantissa holds 500 decimal digits. 500 is
+// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.
+//
 // An HPD isn't for general purpose arithmetic, only for conversions to and
 // from IEEE 754 double-precision floating point, where the largest and
 // smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.
@@ -8758,7 +9041,7 @@
 // For example, if num_digits is 3 and digits is "\x07\x08\x09":
 //   - A decimal_point of -2 means ".00789"
 //   - A decimal_point of -1 means ".0789"
-//   - A decimal_point of -0 means ".789"
+//   - A decimal_point of +0 means ".789"
 //   - A decimal_point of +1 means "7.89"
 //   - A decimal_point of +2 means "78.9"
 //   - A decimal_point of +3 means "789."
@@ -9288,6 +9571,438 @@
 
 // --------
 
+// The wuffs_base__private_implementation__etc_powers_of_10 tables were printed
+// by script/print-mpb-powers-of-10.go. That script has an optional -comments
+// flag, whose output is not copied here, which prints further detail.
+//
+// These tables are used in
+// wuffs_base__private_implementation__medium_prec_bin__assign_from_hpd.
+
+// wuffs_base__private_implementation__big_powers_of_10 contains approximations
+// to the powers of 10, ranging from 1e-348 to 1e+340, with the exponent
+// stepping by 8: -348, -340, -332, ..., -12, -4, +4, +12, ..., +340. Each step
+// consists of three uint32_t elements. There are 87 triples, 87 * 3 = 261.
+//
+// For example, the third approximation, for 1e-332, consists of the uint32_t
+// triple (0x3055AC76, 0x8B16FB20, 0xFFFFFB72). The first two of that triple
+// are a little-endian uint64_t value: 0x8B16FB203055AC76. The last one is an
+// int32_t value: -1166. Together, they represent the approximation:
+//   1e-332 ≈ 0x8B16FB203055AC76 * (2 ** -1166)
+// Similarly, the (0x00000000, 0x9C400000, 0xFFFFFFCE) uint32_t triple means:
+//   1e+4   ≈ 0x9C40000000000000 * (2 **   -50)  // This approx'n is exact.
+// Similarly, the (0xD4C4FB27, 0xED63A231, 0x000000A2) uint32_t triple means:
+//   1e+68  ≈ 0xED63A231D4C4FB27 * (2 **   162)
+static const uint32_t
+    wuffs_base__private_implementation__big_powers_of_10[261] = {
+        0x081C0288, 0xFA8FD5A0, 0xFFFFFB3C, 0xA23EBF76, 0xBAAEE17F, 0xFFFFFB57,
+        0x3055AC76, 0x8B16FB20, 0xFFFFFB72, 0x5DCE35EA, 0xCF42894A, 0xFFFFFB8C,
+        0x55653B2D, 0x9A6BB0AA, 0xFFFFFBA7, 0x3D1A45DF, 0xE61ACF03, 0xFFFFFBC1,
+        0xC79AC6CA, 0xAB70FE17, 0xFFFFFBDC, 0xBEBCDC4F, 0xFF77B1FC, 0xFFFFFBF6,
+        0x416BD60C, 0xBE5691EF, 0xFFFFFC11, 0x907FFC3C, 0x8DD01FAD, 0xFFFFFC2C,
+        0x31559A83, 0xD3515C28, 0xFFFFFC46, 0xADA6C9B5, 0x9D71AC8F, 0xFFFFFC61,
+        0x23EE8BCB, 0xEA9C2277, 0xFFFFFC7B, 0x4078536D, 0xAECC4991, 0xFFFFFC96,
+        0x5DB6CE57, 0x823C1279, 0xFFFFFCB1, 0x4DFB5637, 0xC2109436, 0xFFFFFCCB,
+        0x3848984F, 0x9096EA6F, 0xFFFFFCE6, 0x25823AC7, 0xD77485CB, 0xFFFFFD00,
+        0x97BF97F4, 0xA086CFCD, 0xFFFFFD1B, 0x172AACE5, 0xEF340A98, 0xFFFFFD35,
+        0x2A35B28E, 0xB23867FB, 0xFFFFFD50, 0xD2C63F3B, 0x84C8D4DF, 0xFFFFFD6B,
+        0x1AD3CDBA, 0xC5DD4427, 0xFFFFFD85, 0xBB25C996, 0x936B9FCE, 0xFFFFFDA0,
+        0x7D62A584, 0xDBAC6C24, 0xFFFFFDBA, 0x0D5FDAF6, 0xA3AB6658, 0xFFFFFDD5,
+        0xDEC3F126, 0xF3E2F893, 0xFFFFFDEF, 0xAAFF80B8, 0xB5B5ADA8, 0xFFFFFE0A,
+        0x6C7C4A8B, 0x87625F05, 0xFFFFFE25, 0x34C13053, 0xC9BCFF60, 0xFFFFFE3F,
+        0x91BA2655, 0x964E858C, 0xFFFFFE5A, 0x70297EBD, 0xDFF97724, 0xFFFFFE74,
+        0xB8E5B88F, 0xA6DFBD9F, 0xFFFFFE8F, 0x88747D94, 0xF8A95FCF, 0xFFFFFEA9,
+        0x8FA89BCF, 0xB9447093, 0xFFFFFEC4, 0xBF0F156B, 0x8A08F0F8, 0xFFFFFEDF,
+        0x653131B6, 0xCDB02555, 0xFFFFFEF9, 0xD07B7FAC, 0x993FE2C6, 0xFFFFFF14,
+        0x2A2B3B06, 0xE45C10C4, 0xFFFFFF2E, 0x697392D3, 0xAA242499, 0xFFFFFF49,
+        0x8300CA0E, 0xFD87B5F2, 0xFFFFFF63, 0x92111AEB, 0xBCE50864, 0xFFFFFF7E,
+        0x6F5088CC, 0x8CBCCC09, 0xFFFFFF99, 0xE219652C, 0xD1B71758, 0xFFFFFFB3,
+        0x00000000, 0x9C400000, 0xFFFFFFCE, 0x00000000, 0xE8D4A510, 0xFFFFFFE8,
+        0xAC620000, 0xAD78EBC5, 0x00000003, 0xF8940984, 0x813F3978, 0x0000001E,
+        0xC90715B3, 0xC097CE7B, 0x00000038, 0x7BEA5C70, 0x8F7E32CE, 0x00000053,
+        0xABE98068, 0xD5D238A4, 0x0000006D, 0x179A2245, 0x9F4F2726, 0x00000088,
+        0xD4C4FB27, 0xED63A231, 0x000000A2, 0x8CC8ADA8, 0xB0DE6538, 0x000000BD,
+        0x1AAB65DB, 0x83C7088E, 0x000000D8, 0x42711D9A, 0xC45D1DF9, 0x000000F2,
+        0xA61BE758, 0x924D692C, 0x0000010D, 0x1A708DEA, 0xDA01EE64, 0x00000127,
+        0x9AEF774A, 0xA26DA399, 0x00000142, 0xB47D6B85, 0xF209787B, 0x0000015C,
+        0x79DD1877, 0xB454E4A1, 0x00000177, 0x5B9BC5C2, 0x865B8692, 0x00000192,
+        0xC8965D3D, 0xC83553C5, 0x000001AC, 0xFA97A0B3, 0x952AB45C, 0x000001C7,
+        0x99A05FE3, 0xDE469FBD, 0x000001E1, 0xDB398C25, 0xA59BC234, 0x000001FC,
+        0xA3989F5C, 0xF6C69A72, 0x00000216, 0x54E9BECE, 0xB7DCBF53, 0x00000231,
+        0xF22241E2, 0x88FCF317, 0x0000024C, 0xD35C78A5, 0xCC20CE9B, 0x00000266,
+        0x7B2153DF, 0x98165AF3, 0x00000281, 0x971F303A, 0xE2A0B5DC, 0x0000029B,
+        0x5CE3B396, 0xA8D9D153, 0x000002B6, 0xA4A7443C, 0xFB9B7CD9, 0x000002D0,
+        0xA7A44410, 0xBB764C4C, 0x000002EB, 0xB6409C1A, 0x8BAB8EEF, 0x00000306,
+        0xA657842C, 0xD01FEF10, 0x00000320, 0xE9913129, 0x9B10A4E5, 0x0000033B,
+        0xA19C0C9D, 0xE7109BFB, 0x00000355, 0x623BF429, 0xAC2820D9, 0x00000370,
+        0x7AA7CF85, 0x80444B5E, 0x0000038B, 0x03ACDD2D, 0xBF21E440, 0x000003A5,
+        0x5E44FF8F, 0x8E679C2F, 0x000003C0, 0x9C8CB841, 0xD433179D, 0x000003DA,
+        0xB4E31BA9, 0x9E19DB92, 0x000003F5, 0xBADF77D9, 0xEB96BF6E, 0x0000040F,
+        0x9BF0EE6B, 0xAF87023B, 0x0000042A,
+};
+
+// wuffs_base__private_implementation__small_powers_of_10 contains
+// approximations to the powers of 10, ranging from 1e+0 to 1e+7, with the
+// exponent stepping by 1. Each step consists of three uint32_t elements.
+//
+// For example, the third approximation, for 1e+2, consists of the uint32_t
+// triple (0x00000000, 0xC8000000, 0xFFFFFFC7). The first two of that triple
+// are a little-endian uint64_t value: 0xC800000000000000. The last one is an
+// int32_t value: -57. Together, they represent the approximation:
+//   1e+2   ≈ 0xC800000000000000 * (2 **   -57)  // This approx'n is exact.
+// Similarly, the (0x00000000, 0x9C400000, 0xFFFFFFCE) uint32_t triple means:
+//   1e+4   ≈ 0x9C40000000000000 * (2 **   -50)  // This approx'n is exact.
+static const uint32_t
+    wuffs_base__private_implementation__small_powers_of_10[24] = {
+        0x00000000, 0x80000000, 0xFFFFFFC1, 0x00000000, 0xA0000000, 0xFFFFFFC4,
+        0x00000000, 0xC8000000, 0xFFFFFFC7, 0x00000000, 0xFA000000, 0xFFFFFFCA,
+        0x00000000, 0x9C400000, 0xFFFFFFCE, 0x00000000, 0xC3500000, 0xFFFFFFD1,
+        0x00000000, 0xF4240000, 0xFFFFFFD4, 0x00000000, 0x98968000, 0xFFFFFFD8,
+};
+
+// wuffs_base__private_implementation__f64_powers_of_10 holds powers of 10 that
+// can be exactly represented by a float64 (what C calls a double).
+static const double wuffs_base__private_implementation__f64_powers_of_10[23] = {
+    1e0,  1e1,  1e2,  1e3,  1e4,  1e5,  1e6,  1e7,  1e8,  1e9,  1e10, 1e11,
+    1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
+};
+
+// --------
+
+// wuffs_base__private_implementation__medium_prec_bin (abbreviated as MPB) is
+// a fixed precision floating point binary number. Unlike IEEE 754 Floating
+// Point, it cannot represent infinity or NaN (Not a Number).
+//
+// "Medium precision" means that the mantissa holds 64 binary digits, a little
+// more than "double precision", and sizeof(MPB) > sizeof(double). 64 is
+// obviously the number of bits in a uint64_t.
+//
+// An MPB isn't for general purpose arithmetic, only for conversions to and
+// from IEEE 754 double-precision floating point.
+//
+// There is no implicit mantissa bit. The mantissa field is zero if and only if
+// the overall floating point value is ±0. An MPB is normalized if the mantissa
+// is zero or its high bit (the 1<<63 bit) is set.
+//
+// There is no negative bit. An MPB can only represent non-negative numbers.
+//
+// The "all fields are zero" value is valid, and represents the number +0.
+//
+// This is the "Do It Yourself Floating Point" data structure from Loitsch,
+// "Printing Floating-Point Numbers Quickly and Accurately with Integers"
+// (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
+//
+// Florian Loitsch is also the primary contributor to
+// https://github.com/google/double-conversion
+typedef struct {
+  uint64_t mantissa;
+  int32_t exp2;
+} wuffs_base__private_implementation__medium_prec_bin;
+
+static uint32_t  //
+wuffs_base__private_implementation__medium_prec_bin__normalize(
+    wuffs_base__private_implementation__medium_prec_bin* m) {
+  if (m->mantissa == 0) {
+    return 0;
+  }
+  uint32_t shift = wuffs_base__count_leading_zeroes_u64(m->mantissa);
+  m->mantissa <<= shift;
+  m->exp2 -= (int32_t)shift;
+  return shift;
+}
+
+// wuffs_base__private_implementation__medium_prec_bin__mul_pow_10 sets m to be
+// (m * pow), where pow comes from an etc_powers_of_10 triple starting at p.
+//
+// The result is rounded, but not necessarily normalized.
+//
+// Preconditions:
+//  - m is non-NULL.
+//  - m->mantissa is non-zero.
+//  - m->mantissa's high bit is set (i.e. m is normalized).
+//
+// The etc_powers_of_10 triple is already normalized.
+static void  //
+wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(
+    wuffs_base__private_implementation__medium_prec_bin* m,
+    const uint32_t* p) {
+  uint64_t p_mantissa = ((uint64_t)p[0]) | (((uint64_t)p[1]) << 32);
+  int32_t p_exp2 = (int32_t)p[2];
+
+  wuffs_base__multiply_u64__output o =
+      wuffs_base__multiply_u64(m->mantissa, p_mantissa);
+  // Round the mantissa up. It cannot overflow because the maximum possible
+  // value of o.hi is 0xFFFFFFFFFFFFFFFE.
+  m->mantissa = o.hi + (o.lo >> 63);
+  m->exp2 = m->exp2 + p_exp2 + 64;
+}
+
+// wuffs_base__private_implementation__medium_prec_bin__as_f64 converts m to a
+// double (what C calls a double-precision float64).
+//
+// Preconditions:
+//  - m is non-NULL.
+//  - m->mantissa is non-zero.
+//  - m->mantissa's high bit is set (i.e. m is normalized).
+static double  //
+wuffs_base__private_implementation__medium_prec_bin__as_f64(
+    const wuffs_base__private_implementation__medium_prec_bin* m,
+    bool negative) {
+  uint64_t mantissa64 = m->mantissa;
+  // An mpb's mantissa has the implicit (binary) decimal point at the right
+  // hand end of the mantissa's explicit digits. A double-precision's mantissa
+  // has that decimal point near the left hand end. There's also an explicit
+  // versus implicit leading 1 bit (binary digit). Together, the difference in
+  // semantics corresponds to adding 63.
+  int32_t exp2 = m->exp2 + 63;
+
+  // Ensure that exp2 is at least -1022, the minimum double-precision exponent
+  // for normal (as opposed to subnormal) numbers.
+  if (-1022 > exp2) {
+    uint32_t n = (uint32_t)(-1022 - exp2);
+    mantissa64 >>= n;
+    exp2 += (int32_t)n;
+  }
+
+  // Extract the (1 + 52) bits from the 64-bit mantissa64. 52 is the number of
+  // explicit mantissa bits in a double-precision f64.
+  //
+  // Before, we have 64 bits and due to normalization, the high bit 'H' is 1.
+  // 63        55        47       etc     15        7
+  // H210_9876_5432_1098_7654_etc_etc_etc_5432_1098_7654_3210
+  // ++++_++++_++++_++++_++++_etc_etc_etc_++++_+..._...._....  Kept bits.
+  // ...._...._...H_2109_8765_etc_etc_etc_6543_2109_8765_4321  After shifting.
+  // After, we have 53 bits (and bit #52 is this 'H' bit).
+  uint64_t mantissa53 = mantissa64 >> 11;
+
+  // Round up if the old bit #10 (the highest bit dropped by shifting) was set.
+  // We also fix any overflow from rounding up.
+  if (mantissa64 & 1024) {
+    mantissa53++;
+    if ((mantissa53 >> 53) != 0) {
+      mantissa53 >>= 1;
+      exp2++;
+    }
+  }
+
+  // Handle double-precision infinity (a nominal exponent of 1024) and
+  // subnormals (an exponent of -1023 and no implicit mantissa bit, bit #52).
+  if (exp2 >= 1024) {
+    mantissa53 = 0;
+    exp2 = 1024;
+  } else if ((mantissa53 >> 52) == 0) {
+    exp2 = -1023;
+  }
+
+  // Pack the bits and return.
+  const int32_t f64_bias = -1023;
+  uint64_t exp2_bits =
+      (uint64_t)((exp2 - f64_bias) & 0x07FF);           // (1 << 11) - 1.
+  uint64_t bits = (mantissa53 & 0x000FFFFFFFFFFFFF) |   // (1 << 52) - 1.
+                  (exp2_bits << 52) |                   //
+                  (negative ? 0x8000000000000000 : 0);  // (1 << 63).
+  return wuffs_base__ieee_754_bit_representation__to_f64(bits);
+}
+
+// wuffs_base__private_implementation__medium_prec_bin__parse_number_f64
+// converts from an HPD to a double, using an MPB as scratch space. It returns
+// a NULL status.repr if there is no ambiguity in the truncation or rounding to
+// a float64 (an IEEE 754 double-precision floating point value).
+//
+// It may modify m even if it returns a non-NULL status.repr.
+static wuffs_base__result_f64  //
+wuffs_base__private_implementation__medium_prec_bin__parse_number_f64(
+    wuffs_base__private_implementation__medium_prec_bin* m,
+    const wuffs_base__private_implementation__high_prec_dec* h,
+    bool skip_fast_path_for_tests) {
+  do {
+    // m->mantissa is a uint64_t, which is an integer approximation to a
+    // rational value - h's underlying digits after m's normalization. This
+    // error is an upper bound on the difference between the approximate and
+    // actual value.
+    //
+    // The DiyFpStrtod function in https://github.com/google/double-conversion
+    // uses a finer grain (1/8th of the ULP, Unit in the Last Place) when
+    // tracking error. This implementation is coarser (1 ULP) but simpler.
+    //
+    // It is an error in the "numerical approximation" sense, not in the
+    // typical programming sense (as in "bad input" or "a result type").
+    uint64_t error = 0;
+
+    // Convert up to 19 decimal digits (in h->digits) to 64 binary digits (in
+    // m->mantissa): (1e19 < (1<<64)) and ((1<<64) < 1e20). If we have more
+    // than 19 digits, we're truncating (with error).
+    uint32_t i;
+    uint32_t i_end = h->num_digits;
+    if (i_end > 19) {
+      i_end = 19;
+      error = 1;
+    }
+    uint64_t mantissa = 0;
+    for (i = 0; i < i_end; i++) {
+      mantissa = (10 * mantissa) + h->digits[i];
+    }
+    m->mantissa = mantissa;
+    m->exp2 = 0;
+
+    // Check that exp10 lies in the (big_powers_of_10 + small_powers_of_10)
+    // range, -348 ..= +347, stepping big_powers_of_10 by 8 (which is 87
+    // triples) and small_powers_of_10 by 1 (which is 8 triples).
+    int32_t exp10 = h->decimal_point - ((int32_t)(i_end));
+    if (exp10 < -348) {
+      goto fail;
+    }
+    uint32_t bpo10 = ((uint32_t)(exp10 + 348)) / 8;
+    uint32_t spo10 = ((uint32_t)(exp10 + 348)) % 8;
+    if (bpo10 >= 87) {
+      goto fail;
+    }
+
+    // Try a fast path, if float64 math would be exact.
+    //
+    // 15 is such that 1e15 can be losslessly represented in a float64
+    // mantissa: (1e15 < (1<<53)) and ((1<<53) < 1e16).
+    //
+    // 22 is the maximum valid index for the
+    // wuffs_base__private_implementation__f64_powers_of_10 array.
+    do {
+      if (skip_fast_path_for_tests || ((mantissa >> 52) != 0)) {
+        break;
+      }
+      double d = (double)mantissa;
+
+      if (exp10 == 0) {
+        wuffs_base__result_f64 ret;
+        ret.status.repr = NULL;
+        ret.value = h->negative ? -d : +d;
+        return ret;
+
+      } else if (exp10 > 0) {
+        if (exp10 > 22) {
+          if (exp10 > (15 + 22)) {
+            break;
+          }
+          // If exp10 is in the range 23 ..= 37, try moving a few of the zeroes
+          // from the exponent to the mantissa. If we're still under 1e15, we
+          // haven't truncated any mantissa bits.
+          if (exp10 > 22) {
+            d *= wuffs_base__private_implementation__f64_powers_of_10[exp10 -
+                                                                      22];
+            exp10 = 22;
+            if (d >= 1e15) {
+              break;
+            }
+          }
+        }
+        d *= wuffs_base__private_implementation__f64_powers_of_10[exp10];
+        wuffs_base__result_f64 ret;
+        ret.status.repr = NULL;
+        ret.value = h->negative ? -d : +d;
+        return ret;
+
+      } else {  // "if (exp10 < 0)" is effectively "if (true)" here.
+        if (exp10 < -22) {
+          break;
+        }
+        d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];
+        wuffs_base__result_f64 ret;
+        ret.status.repr = NULL;
+        ret.value = h->negative ? -d : +d;
+        return ret;
+      }
+    } while (0);
+
+    // Normalize (and scale the error).
+    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);
+
+    // Multiplying two MPB values nominally multiplies two mantissas, call them
+    // A and B, which are integer approximations to the precise values (A+a)
+    // and (B+b) for some error terms a and b.
+    //
+    // MPB multiplication calculates (((A+a) * (B+b)) >> 64) to be ((A*B) >>
+    // 64). Shifting (truncating) and rounding introduces further error. The
+    // difference between the calculated result:
+    //  ((A*B                  ) >> 64)
+    // and the true result:
+    //  ((A*B + A*b + a*B + a*b) >> 64)   + rounding_error
+    // is:
+    //  ((      A*b + a*B + a*b) >> 64)   + rounding_error
+    // which can be re-grouped as:
+    //  ((A*b) >> 64) + ((a*(B+b)) >> 64) + rounding_error
+    //
+    // Now, let A and a be "m->mantissa" and "error", and B and b be the
+    // pre-calculated power of 10. A and B are both less than (1 << 64), a is
+    // the "error" local variable and b is less than 1.
+    //
+    // An upper bound (in absolute value) on ((A*b) >> 64) is therefore 1.
+    //
+    // An upper bound on ((a*(B+b)) >> 64) is a, also known as error.
+    //
+    // Finally, the rounding_error is at most 1.
+    //
+    // In total, calling mpb__mul_pow_10 will raise the worst-case error by 2.
+    // The subsequent re-normalization can multiply that by a further factor.
+
+    // Multiply by small_powers_of_10[etc].
+    wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(
+        m, &wuffs_base__private_implementation__small_powers_of_10[3 * spo10]);
+    error += 2;
+    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);
+
+    // Multiply by big_powers_of_10[etc].
+    wuffs_base__private_implementation__medium_prec_bin__mul_pow_10(
+        m, &wuffs_base__private_implementation__big_powers_of_10[3 * bpo10]);
+    error += 2;
+    error <<= wuffs_base__private_implementation__medium_prec_bin__normalize(m);
+
+    // We have a good approximation of h, but we still have to check whether
+    // the error is small enough. Equivalently, whether the number of surplus
+    // mantissa bits (the bits dropped when going from m's 64 mantissa bits to
+    // the smaller number of double-precision mantissa bits) would always round
+    // up or down, even when perturbed by ±error. We start at 11 surplus bits
+    // (m has 64, double-precision has 1+52), but it can be higher for
+    // subnormals.
+    //
+    // In many cases, the error is small enough and we return true.
+    const int32_t f64_bias = -1023;
+    int32_t subnormal_exp2 = f64_bias - 63;
+    uint32_t surplus_bits = 11;
+    if (subnormal_exp2 >= m->exp2) {
+      surplus_bits += 1 + ((uint32_t)(subnormal_exp2 - m->exp2));
+    }
+
+    uint64_t surplus_mask =
+        (((uint64_t)1) << surplus_bits) - 1;  // e.g. 0x07FF.
+    uint64_t surplus = m->mantissa & surplus_mask;
+    uint64_t halfway = ((uint64_t)1) << (surplus_bits - 1);  // e.g. 0x0400.
+
+    // Do the final calculation in *signed* arithmetic.
+    int64_t i_surplus = (int64_t)surplus;
+    int64_t i_halfway = (int64_t)halfway;
+    int64_t i_error = (int64_t)error;
+
+    if ((i_surplus > (i_halfway - i_error)) &&
+        (i_surplus < (i_halfway + i_error))) {
+      goto fail;
+    }
+
+    wuffs_base__result_f64 ret;
+    ret.status.repr = NULL;
+    ret.value = wuffs_base__private_implementation__medium_prec_bin__as_f64(
+        m, h->negative);
+    return ret;
+  } while (0);
+
+fail:
+  do {
+    wuffs_base__result_f64 ret;
+    ret.status.repr = "#base: mpb__parse_number_f64 failed";
+    ret.value = 0;
+    return ret;
+  } while (0);
+}
+
+// --------
+
 wuffs_base__result_f64  //
 wuffs_base__parse_number_f64_special(wuffs_base__slice_u8 s,
                                      const char* fallback_status_repr) {
@@ -9391,6 +10106,7 @@
 
 wuffs_base__result_f64  //
 wuffs_base__parse_number_f64(wuffs_base__slice_u8 s) {
+  wuffs_base__private_implementation__medium_prec_bin m;
   wuffs_base__private_implementation__high_prec_dec h;
 
   do {
@@ -9417,10 +10133,17 @@
       goto infinity;
     }
 
+    wuffs_base__result_f64 mpb_result =
+        wuffs_base__private_implementation__medium_prec_bin__parse_number_f64(
+            &m, &h, false);
+    if (mpb_result.status.repr == NULL) {
+      return mpb_result;
+    }
+
     // Scale by powers of 2 until we're in the range [½ .. 1], which gives us
     // our exponent (in base-2). First we shift right, possibly a little too
     // far, ending with a value certainly below 1 and possibly below ½...
-    const int32_t bias = -1023;
+    const int32_t f64_bias = -1023;
     int32_t exp2 = 0;
     while (h.decimal_point > 0) {
       uint32_t n = (uint32_t)(+h.decimal_point);
@@ -9464,9 +10187,9 @@
     // We're in the range [½ .. 1] but f64 uses [1 .. 2].
     exp2--;
 
-    // The minimum normal exponent is (bias + 1).
-    while ((bias + 1) > exp2) {
-      uint32_t n = (uint32_t)((bias + 1) - exp2);
+    // The minimum normal exponent is (f64_bias + 1).
+    while ((f64_bias + 1) > exp2) {
+      uint32_t n = (uint32_t)((f64_bias + 1) - exp2);
       if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
         n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
       }
@@ -9475,7 +10198,7 @@
     }
 
     // Check for overflow.
-    if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1.
+    if ((exp2 - f64_bias) >= 0x07FF) {  // (1 << 11) - 1.
       goto infinity;
     }
 
@@ -9488,21 +10211,22 @@
     if ((man2 >> 53) != 0) {
       man2 >>= 1;
       exp2++;
-      if ((exp2 - bias) >= 0x07FF) {  // (1 << 11) - 1.
+      if ((exp2 - f64_bias) >= 0x07FF) {  // (1 << 11) - 1.
         goto infinity;
       }
     }
 
     // Handle subnormal numbers.
     if ((man2 >> 52) == 0) {
-      exp2 = bias;
+      exp2 = f64_bias;
     }
 
     // Pack the bits and return.
-    uint64_t exp2_bits = (uint64_t)((exp2 - bias) & 0x07FF);  // (1 << 11) - 1.
-    uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |             // (1 << 52) - 1.
-                    (exp2_bits << 52) |                       //
-                    (h.negative ? 0x8000000000000000 : 0);    // (1 << 63).
+    uint64_t exp2_bits =
+        (uint64_t)((exp2 - f64_bias) & 0x07FF);             // (1 << 11) - 1.
+    uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) |           // (1 << 52) - 1.
+                    (exp2_bits << 52) |                     //
+                    (h.negative ? 0x8000000000000000 : 0);  // (1 << 63).
 
     wuffs_base__result_f64 ret;
     ret.status.repr = NULL;
@@ -9531,6 +10255,46 @@
   } while (0);
 }
 
+// ---------------- Hexadecimal
+
+size_t  //
+wuffs_base__hexadecimal__decode2(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src) {
+  size_t src_len2 = src.len / 2;
+  size_t len = dst.len < src_len2 ? dst.len : src_len2;
+  uint8_t* d = dst.ptr;
+  uint8_t* s = src.ptr;
+  size_t n = len;
+
+  while (n--) {
+    *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |
+                   (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));
+    d += 1;
+    s += 2;
+  }
+
+  return len;
+}
+
+size_t  //
+wuffs_base__hexadecimal__decode4(wuffs_base__slice_u8 dst,
+                                 wuffs_base__slice_u8 src) {
+  size_t src_len4 = src.len / 4;
+  size_t len = dst.len < src_len4 ? dst.len : src_len4;
+  uint8_t* d = dst.ptr;
+  uint8_t* s = src.ptr;
+  size_t n = len;
+
+  while (n--) {
+    *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |
+                   (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F));
+    d += 1;
+    s += 4;
+  }
+
+  return len;
+}
+
 // ---------------- Unicode and UTF-8
 
 size_t  //
@@ -10611,8 +11375,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -11011,8 +11773,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -12628,8 +13388,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -14429,8 +15187,6 @@
   uint32_t v_i = 0;
 
   uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -14724,8 +15480,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_write_to[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -15214,8 +15968,6 @@
   bool v_ffio = false;
 
   uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -15342,8 +16094,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_ack_metadata_chunk[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -15737,8 +16487,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -15895,8 +16643,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -16299,8 +17045,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_extension[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -16395,8 +17139,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_skip_blocks[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -16509,7 +17251,7 @@
           goto suspend;
         }
         iop_a_src += self->private_data.s_decode_ae[0].scratch;
-        goto label__0__break;
+        goto label__goto_done__break;
       }
       v_is_animexts = true;
       v_is_netscape = true;
@@ -16568,7 +17310,7 @@
             goto suspend;
           }
           iop_a_src += self->private_data.s_decode_ae[0].scratch;
-          goto label__0__break;
+          goto label__goto_done__break;
         }
         {
           WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
@@ -16593,7 +17335,7 @@
             goto suspend;
           }
           iop_a_src += self->private_data.s_decode_ae[0].scratch;
-          goto label__0__break;
+          goto label__goto_done__break;
         }
         {
           WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
@@ -16669,9 +17411,9 @@
         status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
         goto ok;
       }
-      goto label__0__break;
+      goto label__goto_done__break;
     }
-  label__0__break:;
+  label__goto_done__break:;
     if (a_src) {
       a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
     }
@@ -16732,8 +17474,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_gc[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -16862,8 +17602,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_id_part0[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -17083,8 +17821,6 @@
   bool v_ffio = false;
 
   uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -17211,8 +17947,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_ack_metadata_chunk[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -17608,8 +18342,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -17720,8 +18452,6 @@
   wuffs_base__status status = wuffs_base__make_status(NULL);
 
   uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -17809,8 +18539,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -18213,8 +18941,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_extension[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -18309,8 +19035,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_skip_blocks[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -18423,7 +19147,7 @@
           goto suspend;
         }
         iop_a_src += self->private_data.s_decode_ae[0].scratch;
-        goto label__0__break;
+        goto label__goto_done__break;
       }
       v_is_animexts = true;
       v_is_netscape = true;
@@ -18482,7 +19206,7 @@
             goto suspend;
           }
           iop_a_src += self->private_data.s_decode_ae[0].scratch;
-          goto label__0__break;
+          goto label__goto_done__break;
         }
         {
           WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
@@ -18507,7 +19231,7 @@
             goto suspend;
           }
           iop_a_src += self->private_data.s_decode_ae[0].scratch;
-          goto label__0__break;
+          goto label__goto_done__break;
         }
         {
           WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
@@ -18583,9 +19307,9 @@
         status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
         goto ok;
       }
-      goto label__0__break;
+      goto label__goto_done__break;
     }
-  label__0__break:;
+  label__goto_done__break:;
     if (a_src) {
       a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
     }
@@ -18646,8 +19370,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_gc[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -18776,8 +19498,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_id_part0[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -20063,11 +20783,11 @@
     WUFFS_BASE__POTENTIALLY_UNUSED = {
         0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
         0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 162, 0,   0, 0,
-        0,   0, 0,   0,   0, 0, 0, 0,   0, 175, 0, 0, 0, 0, 0, 0,   0,   0, 0,
-        0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
+        0,   4, 0,   0,   0, 0, 0, 0,   0, 175, 6, 0, 0, 0, 0, 0,   0,   0, 0,
+        0,   0, 0,   0,   0, 0, 3, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
         0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   220, 0, 0,
-        0,   0, 0,   136, 0, 0, 0, 140, 0, 0,   0, 0, 0, 0, 0, 138, 0,   0, 0,
-        141, 0, 137, 0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
+        0,   0, 1,   136, 0, 0, 2, 140, 0, 0,   0, 0, 0, 0, 0, 138, 0,   0, 0,
+        141, 0, 137, 0,   5, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
         0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
         0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
         0,   0, 0,   0,   0, 0, 0, 0,   0, 0,   0, 0, 0, 0, 0, 0,   0,   0, 0,
@@ -20077,6 +20797,12 @@
         0,   0, 0,   0,   0, 0, 0, 0,   0,
 };
 
+static const uint8_t                       //
+    wuffs_json__lut_quirky_backslashes[8]  //
+    WUFFS_BASE__POTENTIALLY_UNUSED = {
+        0, 7, 27, 63, 39, 11, 0, 0,
+};
+
 static const uint8_t            //
     wuffs_json__lut_chars[256]  //
     WUFFS_BASE__POTENTIALLY_UNUSED = {
@@ -20106,10 +20832,10 @@
     WUFFS_BASE__POTENTIALLY_UNUSED = {
         15, 15, 15, 15, 15, 15, 15, 15, 15, 0,  0,  15, 15, 0,  15, 15, 15, 15,
         15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0,  15, 1,  15,
-        15, 15, 15, 15, 15, 15, 15, 15, 2,  4,  15, 15, 4,  4,  4,  4,  4,  4,
+        15, 15, 15, 15, 15, 15, 15, 11, 2,  4,  15, 12, 4,  4,  4,  4,  4,  4,
         4,  4,  4,  4,  3,  15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-        15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
-        15, 7,  15, 8,  15, 15, 15, 15, 15, 15, 15, 15, 9,  15, 15, 15, 15, 15,
+        15, 11, 15, 15, 15, 15, 11, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+        15, 7,  15, 8,  15, 15, 15, 15, 15, 15, 15, 15, 9,  15, 15, 11, 15, 15,
         15, 15, 11, 15, 15, 15, 15, 15, 10, 15, 15, 15, 15, 15, 15, 5,  15, 6,
         15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
         15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
@@ -20176,14 +20902,37 @@
                                    wuffs_base__io_buffer* a_src,
                                    uint32_t a_n);
 
+static wuffs_base__status  //
+wuffs_json__decoder__decode_leading(wuffs_json__decoder* self,
+                                    wuffs_base__token_buffer* a_dst,
+                                    wuffs_base__io_buffer* a_src);
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_comment(wuffs_json__decoder* self,
+                                    wuffs_base__token_buffer* a_dst,
+                                    wuffs_base__io_buffer* a_src);
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_inf_nan(wuffs_json__decoder* self,
+                                    wuffs_base__token_buffer* a_dst,
+                                    wuffs_base__io_buffer* a_src);
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_trailing_new_line(wuffs_json__decoder* self,
+                                              wuffs_base__token_buffer* a_dst,
+                                              wuffs_base__io_buffer* a_src);
+
 // ---------------- VTables
 
 const wuffs_base__token_decoder__func_ptrs
     wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder = {
         (wuffs_base__status(*)(void*,
                                wuffs_base__token_buffer*,
-                               wuffs_base__io_buffer*))(
+                               wuffs_base__io_buffer*,
+                               wuffs_base__slice_u8))(
             &wuffs_json__decoder__decode_tokens),
+        (wuffs_base__range_ii_u64(*)(const void*))(
+            &wuffs_json__decoder__workbuf_len),
 };
 
 // ---------------- Initializer Implementations
@@ -20243,12 +20992,79 @@
 
 // ---------------- Function Implementations
 
+// -------- func json.decoder.set_quirk_enabled
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct  //
+wuffs_json__decoder__set_quirk_enabled(wuffs_json__decoder* self,
+                                       uint32_t a_quirk,
+                                       bool a_enabled) {
+  if (!self) {
+    return wuffs_base__make_empty_struct();
+  }
+  if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
+    return wuffs_base__make_empty_struct();
+  }
+
+  if (a_quirk == 1225364480) {
+    self->private_impl.f_quirk_enabled_allow_backslash_etc[1] = a_enabled;
+  } else if (a_quirk == 1225364481) {
+    self->private_impl.f_quirk_enabled_allow_backslash_capital_u = a_enabled;
+  } else if (a_quirk == 1225364482) {
+    self->private_impl.f_quirk_enabled_allow_backslash_etc[2] = a_enabled;
+  } else if (a_quirk == 1225364483) {
+    self->private_impl.f_quirk_enabled_allow_backslash_etc[3] = a_enabled;
+  } else if (a_quirk == 1225364484) {
+    self->private_impl.f_quirk_enabled_allow_backslash_etc[4] = a_enabled;
+  } else if (a_quirk == 1225364485) {
+    self->private_impl.f_quirk_enabled_allow_backslash_etc[5] = a_enabled;
+  } else if (a_quirk == 1225364486) {
+    self->private_impl.f_quirk_enabled_allow_backslash_x = a_enabled;
+  } else if (a_quirk == 1225364487) {
+    self->private_impl.f_quirk_enabled_allow_backslash_etc[6] = a_enabled;
+  } else if (a_quirk == 1225364488) {
+    self->private_impl.f_quirk_enabled_allow_comment_block = a_enabled;
+  } else if (a_quirk == 1225364489) {
+    self->private_impl.f_quirk_enabled_allow_comment_line = a_enabled;
+  } else if (a_quirk == 1225364490) {
+    self->private_impl.f_quirk_enabled_allow_extra_comma = a_enabled;
+  } else if (a_quirk == 1225364491) {
+    self->private_impl.f_quirk_enabled_allow_inf_nan_numbers = a_enabled;
+  } else if (a_quirk == 1225364492) {
+    self->private_impl.f_quirk_enabled_allow_leading_ascii_record_separator =
+        a_enabled;
+  } else if (a_quirk == 1225364493) {
+    self->private_impl.f_quirk_enabled_allow_leading_unicode_byte_order_mark =
+        a_enabled;
+  } else if (a_quirk == 1225364494) {
+    self->private_impl.f_quirk_enabled_allow_trailing_new_line = a_enabled;
+  } else if (a_quirk == 1225364495) {
+    self->private_impl.f_quirk_enabled_replace_invalid_unicode = a_enabled;
+  }
+  return wuffs_base__make_empty_struct();
+}
+
+// -------- func json.decoder.workbuf_len
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64  //
+wuffs_json__decoder__workbuf_len(const wuffs_json__decoder* self) {
+  if (!self) {
+    return wuffs_base__utility__empty_range_ii_u64();
+  }
+  if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
+      (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
+    return wuffs_base__utility__empty_range_ii_u64();
+  }
+
+  return wuffs_base__utility__empty_range_ii_u64();
+}
+
 // -------- func json.decoder.decode_tokens
 
 WUFFS_BASE__MAYBE_STATIC wuffs_base__status  //
 wuffs_json__decoder__decode_tokens(wuffs_json__decoder* self,
                                    wuffs_base__token_buffer* a_dst,
-                                   wuffs_base__io_buffer* a_src) {
+                                   wuffs_base__io_buffer* a_src,
+                                   wuffs_base__slice_u8 a_workbuf) {
   if (!self) {
     return wuffs_base__make_status(wuffs_base__error__bad_receiver);
   }
@@ -20280,17 +21096,22 @@
   uint32_t v_stack_byte = 0;
   uint32_t v_stack_bit = 0;
   uint32_t v_match = 0;
-  uint32_t v_c_by_4 = 0;
+  uint32_t v_c4 = 0;
   uint8_t v_c = 0;
   uint8_t v_backslash = 0;
   uint8_t v_char = 0;
   uint8_t v_class = 0;
   uint32_t v_multi_byte_utf8 = 0;
+  uint32_t v_backslash_x_length = 0;
+  uint8_t v_backslash_x_ok = 0;
+  uint32_t v_backslash_x_string = 0;
   uint8_t v_uni4_ok = 0;
   uint64_t v_uni4_string = 0;
   uint32_t v_uni4_value = 0;
   uint32_t v_uni4_high_surrogate = 0;
-  uint32_t v_uni4_rollback = 0;
+  uint8_t v_uni8_ok = 0;
+  uint64_t v_uni8_string = 0;
+  uint32_t v_uni8_value = 0;
   uint32_t v_expect = 0;
   uint32_t v_expect_after_value = 0;
 
@@ -20328,13 +21149,39 @@
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
-    v_expect = 3762;
+    while (self->private_impl.f_end_of_data) {
+      status = wuffs_base__make_status(wuffs_base__note__end_of_data);
+      goto ok;
+    }
+    if (self->private_impl
+            .f_quirk_enabled_allow_leading_ascii_record_separator ||
+        self->private_impl
+            .f_quirk_enabled_allow_leading_unicode_byte_order_mark) {
+      if (a_dst) {
+        a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+      }
+      if (a_src) {
+        a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+      }
+      WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
+      status = wuffs_json__decoder__decode_leading(self, a_dst, a_src);
+      if (a_dst) {
+        iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
+      }
+      if (a_src) {
+        iop_a_src = a_src->data.ptr + a_src->meta.ri;
+      }
+      if (status.repr) {
+        goto suspend;
+      }
+    }
+    v_expect = 7858;
   label__outer__continue:;
     while (true) {
       while (true) {
         if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
           status = wuffs_base__make_status(wuffs_base__suspension__short_write);
-          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
           goto label__outer__continue;
         }
         v_whitespace_length = 0;
@@ -20355,7 +21202,7 @@
             }
             status =
                 wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
             v_whitespace_length = 0;
             goto label__outer__continue;
           }
@@ -20400,7 +21247,7 @@
             if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
               status =
                   wuffs_base__make_status(wuffs_base__suspension__short_write);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
               goto label__string_loop_outer__continue;
             }
             v_string_length = 0;
@@ -20423,16 +21270,16 @@
                 }
                 status =
                     wuffs_base__make_status(wuffs_base__suspension__short_read);
-                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
                 v_string_length = 0;
                 goto label__string_loop_outer__continue;
               }
               while (((uint64_t)(io2_a_src - iop_a_src)) > 4) {
-                v_c_by_4 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
-                if (0 != (wuffs_json__lut_chars[(255 & (v_c_by_4 >> 0))] |
-                          wuffs_json__lut_chars[(255 & (v_c_by_4 >> 8))] |
-                          wuffs_json__lut_chars[(255 & (v_c_by_4 >> 16))] |
-                          wuffs_json__lut_chars[(255 & (v_c_by_4 >> 24))])) {
+                v_c4 = wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+                if (0 != (wuffs_json__lut_chars[(255 & (v_c4 >> 0))] |
+                          wuffs_json__lut_chars[(255 & (v_c4 >> 8))] |
+                          wuffs_json__lut_chars[(255 & (v_c4 >> 16))] |
+                          wuffs_json__lut_chars[(255 & (v_c4 >> 24))])) {
                   goto label__0__break;
                 }
                 (iop_a_src += 4, wuffs_base__make_empty_struct());
@@ -20497,7 +21344,7 @@
                   }
                   status = wuffs_base__make_status(
                       wuffs_base__suspension__short_read);
-                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
+                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
                   v_string_length = 0;
                   v_char = 0;
                   goto label__string_loop_outer__continue;
@@ -20505,7 +21352,7 @@
                 v_c = ((uint8_t)(
                     (wuffs_base__load_u16le__no_bounds_check(iop_a_src) >> 8)));
                 v_backslash = wuffs_json__lut_backslashes[v_c];
-                if (v_backslash > 0) {
+                if ((v_backslash & 128) != 0) {
                   (iop_a_src += 2, wuffs_base__make_empty_struct());
                   *iop_a_dst++ = wuffs_base__make_token(
                       (((uint64_t)(
@@ -20514,6 +21361,20 @@
                       (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
                       (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                   goto label__string_loop_outer__continue;
+                } else if (v_backslash != 0) {
+                  if (self->private_impl.f_quirk_enabled_allow_backslash_etc[(
+                          v_backslash & 7)]) {
+                    (iop_a_src += 2, wuffs_base__make_empty_struct());
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)(
+                             (6291456 |
+                              ((uint32_t)(wuffs_json__lut_quirky_backslashes[(
+                                  v_backslash & 7)])))))
+                         << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                        (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    goto label__string_loop_outer__continue;
+                  }
                 } else if (v_c == 117) {
                   if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
                     if (a_src && a_src->meta.closed) {
@@ -20523,7 +21384,7 @@
                     }
                     status = wuffs_base__make_status(
                         wuffs_base__suspension__short_read);
-                    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
+                    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
                     v_string_length = 0;
                     v_char = 0;
                     goto label__string_loop_outer__continue;
@@ -20563,22 +21424,33 @@
                   } else {
                     if (((uint64_t)(io2_a_src - iop_a_src)) < 12) {
                       if (a_src && a_src->meta.closed) {
+                        if (self->private_impl
+                                .f_quirk_enabled_replace_invalid_unicode) {
+                          (iop_a_src += 6, wuffs_base__make_empty_struct());
+                          *iop_a_dst++ = wuffs_base__make_token(
+                              (((uint64_t)(6356989))
+                               << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                              (((uint64_t)(3))
+                               << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                              (((uint64_t)(6))
+                               << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                          goto label__string_loop_outer__continue;
+                        }
                         status = wuffs_base__make_status(
                             wuffs_json__error__bad_backslash_escape);
                         goto exit;
                       }
                       status = wuffs_base__make_status(
                           wuffs_base__suspension__short_read);
-                      WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
+                      WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
                       v_string_length = 0;
                       v_uni4_value = 0;
                       v_char = 0;
                       goto label__string_loop_outer__continue;
                     }
-                    (iop_a_src += 4, wuffs_base__make_empty_struct());
-                    v_uni4_string =
-                        (wuffs_base__load_u64le__no_bounds_check(iop_a_src) >>
-                         16);
+                    v_uni4_string = (wuffs_base__load_u64le__no_bounds_check(
+                                         iop_a_src + 4) >>
+                                     16);
                     if (((255 & (v_uni4_string >> 0)) != 92) ||
                         ((255 & (v_uni4_string >> 8)) != 117)) {
                       v_uni4_high_surrogate = 0;
@@ -20610,7 +21482,7 @@
                     if ((v_uni4_ok != 0) && (56320 <= v_uni4_value) &&
                         (v_uni4_value <= 57343)) {
                       v_uni4_value -= 56320;
-                      (iop_a_src += 8, wuffs_base__make_empty_struct());
+                      (iop_a_src += 12, wuffs_base__make_empty_struct());
                       *iop_a_dst++ = wuffs_base__make_token(
                           (((uint64_t)((6291456 | v_uni4_high_surrogate |
                                         v_uni4_value)))
@@ -20619,20 +21491,144 @@
                           (((uint64_t)(12))
                            << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                       goto label__string_loop_outer__continue;
-                    } else {
-                      v_uni4_rollback = 4;
-                      while (v_uni4_rollback > 0) {
-                        v_uni4_rollback -= 1;
-                        if (iop_a_src > io1_a_src) {
-                          (iop_a_src--, wuffs_base__make_empty_struct());
-                        } else {
-                          status = wuffs_base__make_status(
-                              wuffs_json__error__internal_error_inconsistent_i_o);
-                          goto exit;
-                        }
-                      }
                     }
                   }
+                  if (self->private_impl
+                          .f_quirk_enabled_replace_invalid_unicode) {
+                    if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
+                      status = wuffs_base__make_status(
+                          wuffs_json__error__internal_error_inconsistent_i_o);
+                      goto exit;
+                    }
+                    (iop_a_src += 6, wuffs_base__make_empty_struct());
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)(6356989))
+                         << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                        (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    goto label__string_loop_outer__continue;
+                  }
+                } else if ((v_c == 85) &&
+                           self->private_impl
+                               .f_quirk_enabled_allow_backslash_capital_u) {
+                  if (((uint64_t)(io2_a_src - iop_a_src)) < 10) {
+                    if (a_src && a_src->meta.closed) {
+                      status = wuffs_base__make_status(
+                          wuffs_json__error__bad_backslash_escape);
+                      goto exit;
+                    }
+                    status = wuffs_base__make_status(
+                        wuffs_base__suspension__short_read);
+                    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
+                    v_string_length = 0;
+                    v_char = 0;
+                    goto label__string_loop_outer__continue;
+                  }
+                  v_uni8_string =
+                      wuffs_base__load_u64le__no_bounds_check(iop_a_src + 2);
+                  v_uni8_value = 0;
+                  v_uni8_ok = 128;
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 0))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 28);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 8))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 24);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 16))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 20);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 24))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 16);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 32))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 12);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 40))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 8);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 48))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 4);
+                  v_c = wuffs_json__lut_hexadecimal_digits[(
+                      255 & (v_uni8_string >> 56))];
+                  v_uni8_ok &= v_c;
+                  v_uni8_value |= (((uint32_t)((v_c & 15))) << 0);
+                  if (v_uni8_ok == 0) {
+                  } else if ((v_uni8_value < 55296) ||
+                             ((57343 < v_uni8_value) &&
+                              (v_uni8_value <= 1114111))) {
+                    (iop_a_src += 10, wuffs_base__make_empty_struct());
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)((6291456 | (v_uni8_value & 2097151))))
+                         << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                        (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    goto label__string_loop_outer__continue;
+                  } else if (self->private_impl
+                                 .f_quirk_enabled_replace_invalid_unicode) {
+                    (iop_a_src += 10, wuffs_base__make_empty_struct());
+                    *iop_a_dst++ = wuffs_base__make_token(
+                        (((uint64_t)(6356989))
+                         << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                        (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                        (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                    goto label__string_loop_outer__continue;
+                  }
+                } else if ((v_c == 120) &&
+                           self->private_impl
+                               .f_quirk_enabled_allow_backslash_x) {
+                  if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
+                    if (a_src && a_src->meta.closed) {
+                      status = wuffs_base__make_status(
+                          wuffs_json__error__bad_backslash_escape);
+                      goto exit;
+                    }
+                    status = wuffs_base__make_status(
+                        wuffs_base__suspension__short_read);
+                    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
+                    v_string_length = 0;
+                    v_char = 0;
+                    goto label__string_loop_outer__continue;
+                  }
+                  v_backslash_x_length = 0;
+                  while ((v_backslash_x_length <= 65531) &&
+                         (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
+                    v_backslash_x_string =
+                        wuffs_base__load_u32le__no_bounds_check(iop_a_src);
+                    v_backslash_x_ok = 128;
+                    v_c = wuffs_json__lut_hexadecimal_digits[(
+                        255 & (v_backslash_x_string >> 16))];
+                    v_backslash_x_ok &= v_c;
+                    v_c = wuffs_json__lut_hexadecimal_digits[(
+                        255 & (v_backslash_x_string >> 24))];
+                    v_backslash_x_ok &= v_c;
+                    if ((v_backslash_x_ok == 0) ||
+                        ((v_backslash_x_string & 65535) != 30812)) {
+                      goto label__1__break;
+                    }
+                    (iop_a_src += 4, wuffs_base__make_empty_struct());
+                    v_backslash_x_length += 4;
+                  }
+                label__1__break:;
+                  if (v_backslash_x_length == 0) {
+                    status = wuffs_base__make_status(
+                        wuffs_json__error__bad_backslash_escape);
+                    goto exit;
+                  }
+                  *iop_a_dst++ = wuffs_base__make_token(
+                      (((uint64_t)(4194432))
+                       << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                      (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                      (((uint64_t)(v_backslash_x_length))
+                       << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                  goto label__string_loop_outer__continue;
                 }
                 status = wuffs_base__make_status(
                     wuffs_json__error__bad_backslash_escape);
@@ -20647,15 +21643,29 @@
                         (((uint64_t)(v_string_length))
                          << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     v_string_length = 0;
+                    if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                      goto label__string_loop_outer__continue;
+                    }
                   }
                   if (a_src && a_src->meta.closed) {
+                    if (self->private_impl
+                            .f_quirk_enabled_replace_invalid_unicode) {
+                      *iop_a_dst++ = wuffs_base__make_token(
+                          (((uint64_t)(6356989))
+                           << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                          (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                          (((uint64_t)(1))
+                           << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                      (iop_a_src += 1, wuffs_base__make_empty_struct());
+                      goto label__string_loop_outer__continue;
+                    }
                     status =
                         wuffs_base__make_status(wuffs_json__error__bad_utf_8);
                     goto exit;
                   }
                   status = wuffs_base__make_status(
                       wuffs_base__suspension__short_read);
-                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
+                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
                   v_string_length = 0;
                   v_char = 0;
                   goto label__string_loop_outer__continue;
@@ -20689,15 +21699,29 @@
                         (((uint64_t)(v_string_length))
                          << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     v_string_length = 0;
+                    if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                      goto label__string_loop_outer__continue;
+                    }
                   }
                   if (a_src && a_src->meta.closed) {
+                    if (self->private_impl
+                            .f_quirk_enabled_replace_invalid_unicode) {
+                      *iop_a_dst++ = wuffs_base__make_token(
+                          (((uint64_t)(6356989))
+                           << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                          (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                          (((uint64_t)(1))
+                           << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                      (iop_a_src += 1, wuffs_base__make_empty_struct());
+                      goto label__string_loop_outer__continue;
+                    }
                     status =
                         wuffs_base__make_status(wuffs_json__error__bad_utf_8);
                     goto exit;
                   }
                   status = wuffs_base__make_status(
                       wuffs_base__suspension__short_read);
-                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
+                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
                   v_string_length = 0;
                   v_char = 0;
                   goto label__string_loop_outer__continue;
@@ -20736,15 +21760,29 @@
                         (((uint64_t)(v_string_length))
                          << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                     v_string_length = 0;
+                    if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                      goto label__string_loop_outer__continue;
+                    }
                   }
                   if (a_src && a_src->meta.closed) {
+                    if (self->private_impl
+                            .f_quirk_enabled_replace_invalid_unicode) {
+                      *iop_a_dst++ = wuffs_base__make_token(
+                          (((uint64_t)(6356989))
+                           << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                          (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                          (((uint64_t)(1))
+                           << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                      (iop_a_src += 1, wuffs_base__make_empty_struct());
+                      goto label__string_loop_outer__continue;
+                    }
                     status =
                         wuffs_base__make_status(wuffs_json__error__bad_utf_8);
                     goto exit;
                   }
                   status = wuffs_base__make_status(
                       wuffs_base__suspension__short_read);
-                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
+                  WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13);
                   v_string_length = 0;
                   v_char = 0;
                   goto label__string_loop_outer__continue;
@@ -20782,18 +21820,30 @@
                     (((uint64_t)(v_string_length))
                      << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
                 v_string_length = 0;
+                if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+                  goto label__string_loop_outer__continue;
+                }
               }
               if (v_char == 128) {
                 status = wuffs_base__make_status(
                     wuffs_json__error__bad_c0_control_code);
                 goto exit;
               }
+              if (self->private_impl.f_quirk_enabled_replace_invalid_unicode) {
+                *iop_a_dst++ = wuffs_base__make_token(
+                    (((uint64_t)(6356989))
+                     << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                    (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                    (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+                (iop_a_src += 1, wuffs_base__make_empty_struct());
+                goto label__string_loop_outer__continue;
+              }
               status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
               goto exit;
             }
           }
         label__string_loop_outer__break:;
-        label__1__continue:;
+        label__2__continue:;
           while (true) {
             if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
               if (a_src && a_src->meta.closed) {
@@ -20802,14 +21852,14 @@
               }
               status =
                   wuffs_base__make_status(wuffs_base__suspension__short_read);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
-              goto label__1__continue;
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
+              goto label__2__continue;
             }
             if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
               status =
                   wuffs_base__make_status(wuffs_base__suspension__short_write);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
-              goto label__1__continue;
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
+              goto label__2__continue;
             }
             (iop_a_src += 1, wuffs_base__make_empty_struct());
             *iop_a_dst++ = wuffs_base__make_token(
@@ -20817,11 +21867,11 @@
                  << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
                 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-            goto label__1__break;
+            goto label__2__break;
           }
-        label__1__break:;
+        label__2__break:;
           if (0 == (v_expect & 16)) {
-            v_expect = 8;
+            v_expect = 4104;
             goto label__outer__continue;
           }
           goto label__goto_parsed_a_leaf_value__break;
@@ -20831,9 +21881,17 @@
               (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
           if (0 == (v_expect & 256)) {
-            v_expect = 2;
+            if (self->private_impl.f_quirk_enabled_allow_extra_comma) {
+              v_expect = 4162;
+            } else {
+              v_expect = 4098;
+            }
           } else {
-            v_expect = 3762;
+            if (self->private_impl.f_quirk_enabled_allow_extra_comma) {
+              v_expect = 8114;
+            } else {
+              v_expect = 7858;
+            }
           }
           goto label__outer__continue;
         } else if (v_class == 3) {
@@ -20841,7 +21899,7 @@
           *iop_a_dst++ = wuffs_base__make_token(
               (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-          v_expect = 3762;
+          v_expect = 7858;
           goto label__outer__continue;
         } else if (v_class == 4) {
           while (true) {
@@ -20864,7 +21922,7 @@
                    << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                   (((uint64_t)(v_number_length))
                    << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-              goto label__2__break;
+              goto label__3__break;
             }
             while (v_number_length > 0) {
               v_number_length -= 1;
@@ -20877,6 +21935,27 @@
               }
             }
             if (v_number_status == 1) {
+              if (self->private_impl.f_quirk_enabled_allow_inf_nan_numbers) {
+                if (a_dst) {
+                  a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+                }
+                if (a_src) {
+                  a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+                }
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
+                status =
+                    wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
+                if (a_dst) {
+                  iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
+                }
+                if (a_src) {
+                  iop_a_src = a_src->data.ptr + a_src->meta.ri;
+                }
+                if (status.repr) {
+                  goto suspend;
+                }
+                goto label__3__break;
+              }
               status = wuffs_base__make_status(wuffs_json__error__bad_input);
               goto exit;
             } else if (v_number_status == 2) {
@@ -20886,15 +21965,15 @@
             } else {
               status =
                   wuffs_base__make_status(wuffs_base__suspension__short_read);
-              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13);
+              WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
               while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
                 status = wuffs_base__make_status(
                     wuffs_base__suspension__short_write);
-                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
+                WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18);
               }
             }
           }
-        label__2__break:;
+        label__3__break:;
           goto label__goto_parsed_a_leaf_value__break;
         } else if (v_class == 5) {
           v_vminor = 2113553;
@@ -20919,8 +21998,8 @@
               (((uint64_t)(v_vminor))
                << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-          v_expect = 66;
-          v_expect_after_value = 68;
+          v_expect = 4162;
+          v_expect_after_value = 4164;
           goto label__outer__continue;
         } else if (v_class == 6) {
           (iop_a_src += 1, wuffs_base__make_empty_struct());
@@ -20940,15 +22019,15 @@
                 (((uint64_t)(2105410))
                  << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-            v_expect = 260;
-            v_expect_after_value = 260;
+            v_expect = 4356;
+            v_expect_after_value = 4356;
           } else {
             *iop_a_dst++ = wuffs_base__make_token(
                 (((uint64_t)(2113602))
                  << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-            v_expect = 68;
-            v_expect_after_value = 68;
+            v_expect = 4164;
+            v_expect_after_value = 4164;
           }
           goto label__outer__continue;
         } else if (v_class == 7) {
@@ -20974,8 +22053,8 @@
               (((uint64_t)(v_vminor))
                << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
               (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-          v_expect = 4018;
-          v_expect_after_value = 260;
+          v_expect = 8114;
+          v_expect_after_value = 4356;
           goto label__outer__continue;
         } else if (v_class == 8) {
           (iop_a_src += 1, wuffs_base__make_empty_struct());
@@ -20995,15 +22074,15 @@
                 (((uint64_t)(2105378))
                  << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-            v_expect = 260;
-            v_expect_after_value = 260;
+            v_expect = 4356;
+            v_expect_after_value = 4356;
           } else {
             *iop_a_dst++ = wuffs_base__make_token(
                 (((uint64_t)(2113570))
                  << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
                 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
-            v_expect = 68;
-            v_expect_after_value = 68;
+            v_expect = 4164;
+            v_expect_after_value = 4164;
           }
           goto label__outer__continue;
         } else if (v_class == 9) {
@@ -21024,7 +22103,7 @@
           } else if (v_match == 1) {
             status =
                 wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19);
             goto label__outer__continue;
           }
         } else if (v_class == 10) {
@@ -21045,7 +22124,7 @@
           } else if (v_match == 1) {
             status =
                 wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(16);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20);
             goto label__outer__continue;
           }
         } else if (v_class == 11) {
@@ -21066,7 +22145,49 @@
           } else if (v_match == 1) {
             status =
                 wuffs_base__make_status(wuffs_base__suspension__short_read);
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21);
+            goto label__outer__continue;
+          }
+          if (self->private_impl.f_quirk_enabled_allow_inf_nan_numbers) {
+            if (a_dst) {
+              a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+            }
+            if (a_src) {
+              a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+            }
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
+            status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
+            if (a_dst) {
+              iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
+            }
+            if (a_src) {
+              iop_a_src = a_src->data.ptr + a_src->meta.ri;
+            }
+            if (status.repr) {
+              goto suspend;
+            }
+            goto label__goto_parsed_a_leaf_value__break;
+          }
+        } else if (v_class == 12) {
+          if (self->private_impl.f_quirk_enabled_allow_comment_block ||
+              self->private_impl.f_quirk_enabled_allow_comment_line) {
+            if (a_dst) {
+              a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+            }
+            if (a_src) {
+              a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+            }
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
+            status = wuffs_json__decoder__decode_comment(self, a_dst, a_src);
+            if (a_dst) {
+              iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
+            }
+            if (a_src) {
+              iop_a_src = a_src->data.ptr + a_src->meta.ri;
+            }
+            if (status.repr) {
+              goto suspend;
+            }
             goto label__outer__continue;
           }
         }
@@ -21080,6 +22201,27 @@
       v_expect = v_expect_after_value;
     }
   label__outer__break:;
+    if (self->private_impl.f_quirk_enabled_allow_trailing_new_line) {
+      if (a_dst) {
+        a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+      }
+      if (a_src) {
+        a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+      }
+      WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
+      status =
+          wuffs_json__decoder__decode_trailing_new_line(self, a_dst, a_src);
+      if (a_dst) {
+        iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
+      }
+      if (a_src) {
+        iop_a_src = a_src->data.ptr + a_src->meta.ri;
+      }
+      if (status.repr) {
+        goto suspend;
+      }
+    }
+    self->private_impl.f_end_of_data = true;
 
     goto ok;
   ok:
@@ -21296,6 +22438,607 @@
   return v_n;
 }
 
+// -------- func json.decoder.decode_leading
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_leading(wuffs_json__decoder* self,
+                                    wuffs_base__token_buffer* a_dst,
+                                    wuffs_base__io_buffer* a_src) {
+  wuffs_base__status status = wuffs_base__make_status(NULL);
+
+  uint8_t v_c = 0;
+  uint32_t v_u = 0;
+
+  wuffs_base__token* iop_a_dst = NULL;
+  wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_dst) {
+    io0_a_dst = a_dst->data.ptr;
+    io1_a_dst = io0_a_dst + a_dst->meta.wi;
+    iop_a_dst = io1_a_dst;
+    io2_a_dst = io0_a_dst + a_dst->data.len;
+    if (a_dst->meta.closed) {
+      io2_a_dst = iop_a_dst;
+    }
+  }
+  uint8_t* iop_a_src = NULL;
+  uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_src) {
+    io0_a_src = a_src->data.ptr;
+    io1_a_src = io0_a_src + a_src->meta.ri;
+    iop_a_src = io1_a_src;
+    io2_a_src = io0_a_src + a_src->meta.wi;
+  }
+
+  uint32_t coro_susp_point = self->private_impl.p_decode_leading[0];
+  switch (coro_susp_point) {
+    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+    self->private_impl.f_allow_leading_ars =
+        self->private_impl.f_quirk_enabled_allow_leading_ascii_record_separator;
+    self->private_impl.f_allow_leading_ubom =
+        self->private_impl
+            .f_quirk_enabled_allow_leading_unicode_byte_order_mark;
+  label__0__continue:;
+    while (self->private_impl.f_allow_leading_ars ||
+           self->private_impl.f_allow_leading_ubom) {
+      if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+        status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+        goto label__0__continue;
+      }
+      if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+        if (a_src && a_src->meta.closed) {
+          goto label__0__break;
+        }
+        status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+        goto label__0__continue;
+      }
+      v_c = wuffs_base__load_u8be__no_bounds_check(iop_a_src);
+      if ((v_c == 30) && self->private_impl.f_allow_leading_ars) {
+        self->private_impl.f_allow_leading_ars = false;
+        (iop_a_src += 1, wuffs_base__make_empty_struct());
+        *iop_a_dst++ = wuffs_base__make_token(
+            (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+            (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+        goto label__0__continue;
+      } else if ((v_c == 239) && self->private_impl.f_allow_leading_ubom) {
+        if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
+          if (a_src && a_src->meta.closed) {
+            goto label__0__break;
+          }
+          status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+          goto label__0__continue;
+        }
+        v_u = ((uint32_t)(wuffs_base__load_u24le__no_bounds_check(iop_a_src)));
+        if (v_u == 12565487) {
+          self->private_impl.f_allow_leading_ubom = false;
+          (iop_a_src += 3, wuffs_base__make_empty_struct());
+          *iop_a_dst++ = wuffs_base__make_token(
+              (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+              (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+          goto label__0__continue;
+        }
+      }
+      goto label__0__break;
+    }
+  label__0__break:;
+
+    goto ok;
+  ok:
+    self->private_impl.p_decode_leading[0] = 0;
+    goto exit;
+  }
+
+  goto suspend;
+suspend:
+  self->private_impl.p_decode_leading[0] =
+      wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+
+  goto exit;
+exit:
+  if (a_dst) {
+    a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+  }
+  if (a_src) {
+    a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+  }
+
+  return status;
+}
+
+// -------- func json.decoder.decode_comment
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_comment(wuffs_json__decoder* self,
+                                    wuffs_base__token_buffer* a_dst,
+                                    wuffs_base__io_buffer* a_src) {
+  wuffs_base__status status = wuffs_base__make_status(NULL);
+
+  uint8_t v_c = 0;
+  uint16_t v_c2 = 0;
+  uint32_t v_link_prev = 0;
+  uint32_t v_length = 0;
+
+  wuffs_base__token* iop_a_dst = NULL;
+  wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_dst) {
+    io0_a_dst = a_dst->data.ptr;
+    io1_a_dst = io0_a_dst + a_dst->meta.wi;
+    iop_a_dst = io1_a_dst;
+    io2_a_dst = io0_a_dst + a_dst->data.len;
+    if (a_dst->meta.closed) {
+      io2_a_dst = iop_a_dst;
+    }
+  }
+  uint8_t* iop_a_src = NULL;
+  uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_src) {
+    io0_a_src = a_src->data.ptr;
+    io1_a_src = io0_a_src + a_src->meta.ri;
+    iop_a_src = io1_a_src;
+    io2_a_src = io0_a_src + a_src->meta.wi;
+  }
+
+  uint32_t coro_susp_point = self->private_impl.p_decode_comment[0];
+  if (coro_susp_point) {
+    v_link_prev = self->private_data.s_decode_comment[0].v_link_prev;
+  }
+  switch (coro_susp_point) {
+    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+  label__0__continue:;
+    while ((((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) ||
+           (((uint64_t)(io2_a_src - iop_a_src)) <= 1)) {
+      if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+        status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+        goto label__0__continue;
+      }
+      if (a_src && a_src->meta.closed) {
+        status = wuffs_base__make_status(wuffs_json__error__bad_input);
+        goto exit;
+      }
+      status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+      WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+    }
+    v_c2 = wuffs_base__load_u16le__no_bounds_check(iop_a_src);
+    if ((v_c2 == 10799) &&
+        self->private_impl.f_quirk_enabled_allow_comment_block) {
+      (iop_a_src += 2, wuffs_base__make_empty_struct());
+      v_length = 2;
+    label__comment_block__continue:;
+      while (true) {
+        if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+          status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+          v_length = 0;
+          goto label__comment_block__continue;
+        }
+        while (true) {
+          if (((uint64_t)(io2_a_src - iop_a_src)) <= 1) {
+            if (v_length > 0) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)((1 | v_link_prev)))
+                   << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                  (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              v_link_prev = 2;
+            }
+            if (a_src && a_src->meta.closed) {
+              status = wuffs_base__make_status(wuffs_json__error__bad_input);
+              goto exit;
+            }
+            status =
+                wuffs_base__make_status(wuffs_base__suspension__short_read);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
+            v_length = 0;
+            goto label__comment_block__continue;
+          }
+          v_c2 = wuffs_base__load_u16le__no_bounds_check(iop_a_src);
+          if (v_c2 == 12074) {
+            (iop_a_src += 2, wuffs_base__make_empty_struct());
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(v_link_prev)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                (((uint64_t)((v_length + 2)))
+                 << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            status = wuffs_base__make_status(NULL);
+            goto ok;
+          }
+          (iop_a_src += 1, wuffs_base__make_empty_struct());
+          if (v_length >= 65533) {
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)((1 | v_link_prev)))
+                 << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                (((uint64_t)((v_length + 1)))
+                 << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            v_length = 0;
+            v_link_prev = 2;
+            goto label__comment_block__continue;
+          }
+          v_length += 1;
+        }
+      }
+    } else if ((v_c2 == 12079) &&
+               self->private_impl.f_quirk_enabled_allow_comment_line) {
+      (iop_a_src += 2, wuffs_base__make_empty_struct());
+      v_length = 2;
+    label__comment_line__continue:;
+      while (true) {
+        if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+          status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
+          v_length = 0;
+          goto label__comment_line__continue;
+        }
+        while (true) {
+          if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+            if (v_length > 0) {
+              *iop_a_dst++ = wuffs_base__make_token(
+                  (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                  (((uint64_t)((1 | v_link_prev)))
+                   << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                  (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+              v_link_prev = 2;
+            }
+            if (a_src && a_src->meta.closed) {
+              status = wuffs_base__make_status(wuffs_json__error__bad_input);
+              goto exit;
+            }
+            status =
+                wuffs_base__make_status(wuffs_base__suspension__short_read);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
+            v_length = 0;
+            goto label__comment_line__continue;
+          }
+          v_c = wuffs_base__load_u8be__no_bounds_check(iop_a_src);
+          if (v_c == 10) {
+            (iop_a_src += 1, wuffs_base__make_empty_struct());
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(v_link_prev)) << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                (((uint64_t)((v_length + 1)))
+                 << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            status = wuffs_base__make_status(NULL);
+            goto ok;
+          }
+          (iop_a_src += 1, wuffs_base__make_empty_struct());
+          if (v_length >= 65533) {
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)((1 | v_link_prev)))
+                 << WUFFS_BASE__TOKEN__LINK__SHIFT) |
+                (((uint64_t)((v_length + 1)))
+                 << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            v_length = 0;
+            v_link_prev = 2;
+            goto label__comment_line__continue;
+          }
+          v_length += 1;
+        }
+      }
+    }
+    status = wuffs_base__make_status(wuffs_json__error__bad_input);
+    goto exit;
+    goto ok;
+  ok:
+    self->private_impl.p_decode_comment[0] = 0;
+    goto exit;
+  }
+
+  goto suspend;
+suspend:
+  self->private_impl.p_decode_comment[0] =
+      wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+  self->private_data.s_decode_comment[0].v_link_prev = v_link_prev;
+
+  goto exit;
+exit:
+  if (a_dst) {
+    a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+  }
+  if (a_src) {
+    a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+  }
+
+  return status;
+}
+
+// -------- func json.decoder.decode_inf_nan
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_inf_nan(wuffs_json__decoder* self,
+                                    wuffs_base__token_buffer* a_dst,
+                                    wuffs_base__io_buffer* a_src) {
+  wuffs_base__status status = wuffs_base__make_status(NULL);
+
+  uint32_t v_c4 = 0;
+  uint32_t v_neg = 0;
+
+  wuffs_base__token* iop_a_dst = NULL;
+  wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_dst) {
+    io0_a_dst = a_dst->data.ptr;
+    io1_a_dst = io0_a_dst + a_dst->meta.wi;
+    iop_a_dst = io1_a_dst;
+    io2_a_dst = io0_a_dst + a_dst->data.len;
+    if (a_dst->meta.closed) {
+      io2_a_dst = iop_a_dst;
+    }
+  }
+  uint8_t* iop_a_src = NULL;
+  uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_src) {
+    io0_a_src = a_src->data.ptr;
+    io1_a_src = io0_a_src + a_src->meta.ri;
+    iop_a_src = io1_a_src;
+    io2_a_src = io0_a_src + a_src->meta.wi;
+  }
+
+  uint32_t coro_susp_point = self->private_impl.p_decode_inf_nan[0];
+  if (coro_susp_point) {
+    v_neg = self->private_data.s_decode_inf_nan[0].v_neg;
+  }
+  switch (coro_susp_point) {
+    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+  label__0__continue:;
+    while (true) {
+      if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+        status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+        goto label__0__continue;
+      }
+      if (((uint64_t)(io2_a_src - iop_a_src)) <= 2) {
+        if (a_src && a_src->meta.closed) {
+          status = wuffs_base__make_status(wuffs_json__error__bad_input);
+          goto exit;
+        }
+        status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+        goto label__0__continue;
+      }
+      v_c4 = ((uint32_t)(wuffs_base__load_u24le__no_bounds_check(iop_a_src)));
+      if ((v_c4 | 2105376) == 6712937) {
+        if (((uint64_t)(io2_a_src - iop_a_src)) > 7) {
+          if ((wuffs_base__load_u64le__no_bounds_check(iop_a_src) |
+               2314885530818453536) == 8751735898823356009) {
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(10485792))
+                 << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(8)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            (iop_a_src += 8, wuffs_base__make_empty_struct());
+            status = wuffs_base__make_status(NULL);
+            goto ok;
+          }
+        } else if (!(a_src && a_src->meta.closed)) {
+          status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
+          goto label__0__continue;
+        }
+        *iop_a_dst++ = wuffs_base__make_token(
+            (((uint64_t)(10485792)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+            (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+        (iop_a_src += 3, wuffs_base__make_empty_struct());
+        status = wuffs_base__make_status(NULL);
+        goto ok;
+      } else if ((v_c4 | 2105376) == 7233902) {
+        *iop_a_dst++ = wuffs_base__make_token(
+            (((uint64_t)(10485888)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+            (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+        (iop_a_src += 3, wuffs_base__make_empty_struct());
+        status = wuffs_base__make_status(NULL);
+        goto ok;
+      } else if ((v_c4 & 255) == 43) {
+        v_neg = 0;
+      } else if ((v_c4 & 255) == 45) {
+        v_neg = 1;
+      } else {
+        status = wuffs_base__make_status(wuffs_json__error__bad_input);
+        goto exit;
+      }
+      if (((uint64_t)(io2_a_src - iop_a_src)) <= 3) {
+        if (a_src && a_src->meta.closed) {
+          status = wuffs_base__make_status(wuffs_json__error__bad_input);
+          goto exit;
+        }
+        status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
+        goto label__0__continue;
+      }
+      v_c4 = (wuffs_base__load_u32le__no_bounds_check(iop_a_src) >> 8);
+      if ((v_c4 | 2105376) == 6712937) {
+        if (((uint64_t)(io2_a_src - iop_a_src)) > 8) {
+          if ((wuffs_base__load_u64le__no_bounds_check(iop_a_src + 1) |
+               2314885530818453536) == 8751735898823356009) {
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)((10485760 | (((uint32_t)(32)) >> v_neg))))
+                 << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(9)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            (iop_a_src += 9, wuffs_base__make_empty_struct());
+            status = wuffs_base__make_status(NULL);
+            goto ok;
+          }
+        } else if (!(a_src && a_src->meta.closed)) {
+          status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
+          goto label__0__continue;
+        }
+        *iop_a_dst++ = wuffs_base__make_token(
+            (((uint64_t)((10485760 | (((uint32_t)(32)) >> v_neg))))
+             << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+            (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+        (iop_a_src += 4, wuffs_base__make_empty_struct());
+        status = wuffs_base__make_status(NULL);
+        goto ok;
+      } else if ((v_c4 | 2105376) == 7233902) {
+        *iop_a_dst++ = wuffs_base__make_token(
+            (((uint64_t)((10485760 | (((uint32_t)(128)) >> v_neg))))
+             << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+            (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+        (iop_a_src += 4, wuffs_base__make_empty_struct());
+        status = wuffs_base__make_status(NULL);
+        goto ok;
+      }
+      status = wuffs_base__make_status(wuffs_json__error__bad_input);
+      goto exit;
+    }
+
+    goto ok;
+  ok:
+    self->private_impl.p_decode_inf_nan[0] = 0;
+    goto exit;
+  }
+
+  goto suspend;
+suspend:
+  self->private_impl.p_decode_inf_nan[0] =
+      wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+  self->private_data.s_decode_inf_nan[0].v_neg = v_neg;
+
+  goto exit;
+exit:
+  if (a_dst) {
+    a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+  }
+  if (a_src) {
+    a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+  }
+
+  return status;
+}
+
+// -------- func json.decoder.decode_trailing_new_line
+
+static wuffs_base__status  //
+wuffs_json__decoder__decode_trailing_new_line(wuffs_json__decoder* self,
+                                              wuffs_base__token_buffer* a_dst,
+                                              wuffs_base__io_buffer* a_src) {
+  wuffs_base__status status = wuffs_base__make_status(NULL);
+
+  uint8_t v_c = 0;
+  uint32_t v_whitespace_length = 0;
+
+  wuffs_base__token* iop_a_dst = NULL;
+  wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_dst) {
+    io0_a_dst = a_dst->data.ptr;
+    io1_a_dst = io0_a_dst + a_dst->meta.wi;
+    iop_a_dst = io1_a_dst;
+    io2_a_dst = io0_a_dst + a_dst->data.len;
+    if (a_dst->meta.closed) {
+      io2_a_dst = iop_a_dst;
+    }
+  }
+  uint8_t* iop_a_src = NULL;
+  uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
+  if (a_src) {
+    io0_a_src = a_src->data.ptr;
+    io1_a_src = io0_a_src + a_src->meta.ri;
+    iop_a_src = io1_a_src;
+    io2_a_src = io0_a_src + a_src->meta.wi;
+  }
+
+  uint32_t coro_susp_point = self->private_impl.p_decode_trailing_new_line[0];
+  switch (coro_susp_point) {
+    WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
+
+  label__outer__continue:;
+    while (true) {
+      if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
+        status = wuffs_base__make_status(wuffs_base__suspension__short_write);
+        WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
+        v_whitespace_length = 0;
+        goto label__outer__continue;
+      }
+      while (true) {
+        if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
+          if (v_whitespace_length > 0) {
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(v_whitespace_length))
+                 << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            v_whitespace_length = 0;
+          }
+          if (a_src && a_src->meta.closed) {
+            goto label__outer__break;
+          }
+          status = wuffs_base__make_status(wuffs_base__suspension__short_read);
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
+          v_whitespace_length = 0;
+          goto label__outer__continue;
+        }
+        v_c = wuffs_base__load_u8be__no_bounds_check(iop_a_src);
+        if (wuffs_json__lut_classes[v_c] != 0) {
+          if (v_whitespace_length > 0) {
+            *iop_a_dst++ = wuffs_base__make_token(
+                (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+                (((uint64_t)(v_whitespace_length))
+                 << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+            v_whitespace_length = 0;
+          }
+          status = wuffs_base__make_status(wuffs_json__error__bad_input);
+          goto exit;
+        }
+        (iop_a_src += 1, wuffs_base__make_empty_struct());
+        if ((v_whitespace_length >= 65534) || (v_c == 10)) {
+          *iop_a_dst++ = wuffs_base__make_token(
+              (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
+              (((uint64_t)((v_whitespace_length + 1)))
+               << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
+          v_whitespace_length = 0;
+          if (v_c == 10) {
+            goto label__outer__break;
+          }
+          goto label__outer__continue;
+        }
+        v_whitespace_length += 1;
+      }
+    }
+  label__outer__break:;
+
+    goto ok;
+  ok:
+    self->private_impl.p_decode_trailing_new_line[0] = 0;
+    goto exit;
+  }
+
+  goto suspend;
+suspend:
+  self->private_impl.p_decode_trailing_new_line[0] =
+      wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
+
+  goto exit;
+exit:
+  if (a_dst) {
+    a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
+  }
+  if (a_src) {
+    a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
+  }
+
+  return status;
+}
+
 #endif  // !defined(WUFFS_CONFIG__MODULES) ||
         // defined(WUFFS_CONFIG__MODULE__JSON)
 
@@ -21592,8 +23335,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
@@ -21853,8 +23594,6 @@
   }
 
   uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
-  if (coro_susp_point) {
-  }
   switch (coro_susp_point) {
     WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
 
diff --git a/script/adler32-standalone.c b/script/adler32-standalone.c
index 6726083..805b212 100644
--- a/script/adler32-standalone.c
+++ b/script/adler32-standalone.c
@@ -40,17 +40,17 @@
 
 // The order matters here. Clang also defines "__GNUC__".
 #if defined(__clang__)
-const char* cc = "clang";
-const char* cc_version = __clang_version__;
+const char* g_cc = "clang";
+const char* g_cc_version = __clang_version__;
 #elif defined(__GNUC__)
-const char* cc = "gcc";
-const char* cc_version = __VERSION__;
+const char* g_cc = "gcc";
+const char* g_cc_version = __VERSION__;
 #elif defined(_MSC_VER)
-const char* cc = "cl";
-const char* cc_version = "???";
+const char* g_cc = "cl";
+const char* g_cc_version = "???";
 #else
-const char* cc = "cc";
-const char* cc_version = "???";
+const char* g_cc = "cc";
+const char* g_cc_version = "???";
 #endif
 
 struct {
@@ -58,7 +58,7 @@
   char** remaining_argv;
 
   bool no_check;
-} flags = {0};
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
@@ -83,15 +83,15 @@
     }
 
     if (!strcmp(arg, "no-check")) {
-      flags.no_check = true;
+      g_flags.no_check = true;
       continue;
     }
 
     return "main: unrecognized flag argument";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return NULL;
 }
 
@@ -156,7 +156,7 @@
   return (s2 << 16) | s1;
 }
 
-uint8_t buffer[BUFFER_SIZE] = {0};
+uint8_t g_buffer[BUFFER_SIZE] = {0};
 
 int  //
 main(int argc, char** argv) {
@@ -178,8 +178,8 @@
   int i;
   int num_bad = 0;
   for (i = 0; i < num_reps; i++) {
-    uint32_t actual_hash = calculate_hash(buffer, BUFFER_SIZE);
-    if (!flags.no_check && (actual_hash != expected_hash_of_1mib_of_zeroes)) {
+    uint32_t actual_hash = calculate_hash(g_buffer, BUFFER_SIZE);
+    if (!g_flags.no_check && (actual_hash != expected_hash_of_1mib_of_zeroes)) {
       num_bad++;
     }
   }
@@ -198,6 +198,6 @@
   int64_t denom = micros * ONE_MIBIBYTE;
   int64_t mib_per_s = denom ? numer / denom : 0;
 
-  printf("%8d MiB/s, %s %s\n", (int)mib_per_s, cc, cc_version);
+  printf("%8d MiB/s, %s %s\n", (int)mib_per_s, g_cc, g_cc_version);
   return 0;
 }
diff --git a/script/bench-c-deflate-fragmentation.c b/script/bench-c-deflate-fragmentation.c
index be6f7aa..37b7c1e 100644
--- a/script/bench-c-deflate-fragmentation.c
+++ b/script/bench-c-deflate-fragmentation.c
@@ -75,17 +75,17 @@
 
 // The order matters here. Clang also defines "__GNUC__".
 #if defined(__clang__)
-const char* cc = "clang";
-const char* cc_version = __clang_version__;
+const char* g_cc = "clang";
+const char* g_cc_version = __clang_version__;
 #elif defined(__GNUC__)
-const char* cc = "gcc";
-const char* cc_version = __VERSION__;
+const char* g_cc = "gcc";
+const char* g_cc_version = __VERSION__;
 #elif defined(_MSC_VER)
-const char* cc = "cl";
-const char* cc_version = "???";
+const char* g_cc = "cl";
+const char* g_cc_version = "???";
 #else
-const char* cc = "cc";
-const char* cc_version = "???";
+const char* g_cc = "cc";
+const char* g_cc_version = "???";
 #endif
 
 static inline uint32_t  //
@@ -103,39 +103,40 @@
 #define MAX_DIMENSION (16384)
 #define MAX_IDAT_CHUNKS (1024)
 
-uint8_t dst_buffer_array[DST_BUFFER_ARRAY_SIZE] = {0};
-size_t dst_len = 0;
-uint8_t src_buffer_array[SRC_BUFFER_ARRAY_SIZE] = {0};
-size_t src_len = 0;
-uint8_t idat_buffer_array[SRC_BUFFER_ARRAY_SIZE] = {0};
+uint8_t g_dst_buffer_array[DST_BUFFER_ARRAY_SIZE] = {0};
+size_t g_dst_len = 0;
+uint8_t g_src_buffer_array[SRC_BUFFER_ARRAY_SIZE] = {0};
+size_t g_src_len = 0;
+uint8_t g_idat_buffer_array[SRC_BUFFER_ARRAY_SIZE] = {0};
 // The n'th IDAT chunk data (where n is a zero-based count) is in
-// idat_buffer_array[i:j], where i = idat_splits[n+0] and j = idat_splits[n+1].
-size_t idat_splits[MAX_IDAT_CHUNKS + 1] = {0};
-uint32_t num_idat_chunks = 0;
+// g_idat_buffer_array[i:j], where i = g_idat_splits[n+0] and j =
+// g_idat_splits[n+1].
+size_t g_idat_splits[MAX_IDAT_CHUNKS + 1] = {0};
+uint32_t g_num_idat_chunks = 0;
 
 #define WORK_BUFFER_ARRAY_SIZE \
   WUFFS_ZLIB__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
 #if WORK_BUFFER_ARRAY_SIZE > 0
-uint8_t work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
 #else
 // Not all C/C++ compilers support 0-length arrays.
-uint8_t work_buffer_array[1];
+uint8_t g_work_buffer_array[1];
 #endif
 
-uint32_t width = 0;
-uint32_t height = 0;
-uint64_t bytes_per_pixel = 0;
-uint64_t bytes_per_row = 0;
-uint64_t bytes_per_frame = 0;
+uint32_t g_width = 0;
+uint32_t g_height = 0;
+uint64_t g_bytes_per_pixel = 0;
+uint64_t g_bytes_per_row = 0;
+uint64_t g_bytes_per_frame = 0;
 
 const char*  //
 read_stdin() {
-  while (src_len < SRC_BUFFER_ARRAY_SIZE) {
+  while (g_src_len < SRC_BUFFER_ARRAY_SIZE) {
     const int stdin_fd = 0;
-    ssize_t n = read(stdin_fd, src_buffer_array + src_len,
-                     SRC_BUFFER_ARRAY_SIZE - src_len);
+    ssize_t n = read(stdin_fd, g_src_buffer_array + g_src_len,
+                     SRC_BUFFER_ARRAY_SIZE - g_src_len);
     if (n > 0) {
-      src_len += n;
+      g_src_len += n;
     } else if (n == 0) {
       return NULL;
     } else if (errno == EINTR) {
@@ -168,36 +169,36 @@
         if (chunk_len != 13) {
           return "invalid PNG IDAT chunk";
         }
-        width = load_u32be(p + 0);
-        height = load_u32be(p + 4);
-        if ((width == 0) || (height == 0)) {
+        g_width = load_u32be(p + 0);
+        g_height = load_u32be(p + 4);
+        if ((g_width == 0) || (g_height == 0)) {
           return "image dimensions are too small";
         }
-        if ((width > MAX_DIMENSION) || (height > MAX_DIMENSION)) {
+        if ((g_width > MAX_DIMENSION) || (g_height > MAX_DIMENSION)) {
           return "image dimensions are too large";
         }
         if (p[8] != 8) {
           return "unsupported PNG bit depth";
         }
-        if (bytes_per_pixel != 0) {
+        if (g_bytes_per_pixel != 0) {
           return "duplicate PNG IHDR chunk";
         }
         // Process the color type, as per the PNG spec table 11.1.
         switch (p[9]) {
           case 0:
-            bytes_per_pixel = 1;
+            g_bytes_per_pixel = 1;
             break;
           case 2:
-            bytes_per_pixel = 3;
+            g_bytes_per_pixel = 3;
             break;
           case 3:
-            bytes_per_pixel = 1;
+            g_bytes_per_pixel = 1;
             break;
           case 4:
-            bytes_per_pixel = 2;
+            g_bytes_per_pixel = 2;
             break;
           case 6:
-            bytes_per_pixel = 4;
+            g_bytes_per_pixel = 4;
             break;
           default:
             return "unsupported PNG color type";
@@ -208,13 +209,14 @@
         break;
 
       case 0x49444154:  // "IDAT"
-        if (num_idat_chunks == MAX_IDAT_CHUNKS - 1) {
+        if (g_num_idat_chunks == MAX_IDAT_CHUNKS - 1) {
           return "too many IDAT chunks";
         }
-        memcpy(idat_buffer_array + idat_splits[num_idat_chunks], p, chunk_len);
-        idat_splits[num_idat_chunks + 1] =
-            idat_splits[num_idat_chunks] + chunk_len;
-        num_idat_chunks++;
+        memcpy(g_idat_buffer_array + g_idat_splits[g_num_idat_chunks], p,
+               chunk_len);
+        g_idat_splits[g_num_idat_chunks + 1] =
+            g_idat_splits[g_num_idat_chunks] + chunk_len;
+        g_num_idat_chunks++;
         break;
     }
     p += chunk_len;
@@ -241,17 +243,17 @@
 
   wuffs_base__io_buffer dst = ((wuffs_base__io_buffer){
       .data = ((wuffs_base__slice_u8){
-          .ptr = dst_buffer_array,
-          .len = bytes_per_frame,
+          .ptr = g_dst_buffer_array,
+          .len = g_bytes_per_frame,
       }),
   });
   wuffs_base__io_buffer idat = ((wuffs_base__io_buffer){
       .data = ((wuffs_base__slice_u8){
-          .ptr = idat_buffer_array,
+          .ptr = g_idat_buffer_array,
           .len = SRC_BUFFER_ARRAY_SIZE,
       }),
       .meta = ((wuffs_base__io_buffer_meta){
-          .wi = idat_splits[num_idat_chunks],
+          .wi = g_idat_splits[g_num_idat_chunks],
           .ri = 0,
           .pos = 0,
           .closed = true,
@@ -260,20 +262,20 @@
 
   uint32_t i = 0;  // Number of dst fragments processed, if frag_dst.
   if (frag_dst) {
-    dst.data.len = bytes_per_row;
+    dst.data.len = g_bytes_per_row;
   }
 
   uint32_t j = 0;  // Number of IDAT fragments processed, if frag_idat.
   if (frag_idat) {
-    idat.meta.wi = idat_splits[1];
-    idat.meta.closed = (num_idat_chunks == 1);
+    idat.meta.wi = g_idat_splits[1];
+    idat.meta.closed = (g_num_idat_chunks == 1);
   }
 
   while (true) {
     status =
         wuffs_zlib__decoder__transform_io(&dec, &dst, &idat,
                                           ((wuffs_base__slice_u8){
-                                              .ptr = work_buffer_array,
+                                              .ptr = g_work_buffer_array,
                                               .len = WORK_BUFFER_ARRAY_SIZE,
                                           }));
 
@@ -281,22 +283,22 @@
       break;
     }
     if ((status.repr == wuffs_base__suspension__short_write) && frag_dst &&
-        (i < height - 1)) {
+        (i < g_height - 1)) {
       i++;
-      dst.data.len = bytes_per_row * (i + 1);
+      dst.data.len = g_bytes_per_row * (i + 1);
       continue;
     }
     if ((status.repr == wuffs_base__suspension__short_read) && frag_idat &&
-        (j < num_idat_chunks - 1)) {
+        (j < g_num_idat_chunks - 1)) {
       j++;
-      idat.meta.wi = idat_splits[j + 1];
-      idat.meta.closed = (num_idat_chunks == j + 1);
+      idat.meta.wi = g_idat_splits[j + 1];
+      idat.meta.closed = (g_num_idat_chunks == j + 1);
       continue;
     }
     return wuffs_base__status__message(&status);
   }
 
-  if (dst.meta.wi != bytes_per_frame) {
+  if (dst.meta.wi != g_bytes_per_frame) {
     return "unexpected number of bytes decoded";
   }
   return NULL;
@@ -305,11 +307,11 @@
 const char*  //
 decode(bool frag_dst, bool frag_idat) {
   int reps;
-  if (bytes_per_frame < 100000) {
+  if (g_bytes_per_frame < 100000) {
     reps = 1000;
-  } else if (bytes_per_frame < 1000000) {
+  } else if (g_bytes_per_frame < 1000000) {
     reps = 100;
-  } else if (bytes_per_frame < 10000000) {
+  } else if (g_bytes_per_frame < 10000000) {
     reps = 10;
   } else {
     reps = 1;
@@ -339,7 +341,7 @@
   printf("Benchmark%sDst%sIDAT/%s\t%8d\t%8" PRIu64 " ns/op\n",
          frag_dst ? "Frag" : "Full",   //
          frag_idat ? "Frag" : "Full",  //
-         cc, reps, nanos / reps);
+         g_cc, reps, nanos / reps);
 
   return NULL;
 }
@@ -358,28 +360,28 @@
   if (msg) {
     return fail(msg);
   }
-  if ((src_len < 8) ||
-      strncmp((const char*)(src_buffer_array), "\x89PNG\x0D\x0A\x1A\x0A", 8)) {
+  if ((g_src_len < 8) || strncmp((const char*)(g_src_buffer_array),
+                                 "\x89PNG\x0D\x0A\x1A\x0A", 8)) {
     return fail("invalid PNG");
   }
-  msg = process_png_chunks(src_buffer_array + 8, src_len - 8);
+  msg = process_png_chunks(g_src_buffer_array + 8, g_src_len - 8);
   if (msg) {
     return fail(msg);
   }
-  if (bytes_per_pixel == 0) {
+  if (g_bytes_per_pixel == 0) {
     return fail("missing PNG IHDR chunk");
   }
-  if (num_idat_chunks == 0) {
+  if (g_num_idat_chunks == 0) {
     return fail("missing PNG IDAT chunk");
   }
   // The +1 here is for the per-row filter byte.
-  bytes_per_row = (uint64_t)width * bytes_per_pixel + 1;
-  bytes_per_frame = (uint64_t)height * bytes_per_row;
-  if (bytes_per_frame > DST_BUFFER_ARRAY_SIZE) {
+  g_bytes_per_row = (uint64_t)g_width * g_bytes_per_pixel + 1;
+  g_bytes_per_frame = (uint64_t)g_height * g_bytes_per_row;
+  if (g_bytes_per_frame > DST_BUFFER_ARRAY_SIZE) {
     return fail("decompressed data is too large");
   }
 
-  printf("# %s version %s\n#\n", cc, cc_version);
+  printf("# %s version %s\n#\n", g_cc, g_cc_version);
   printf(
       "# The output format, including the \"Benchmark\" prefixes, is "
       "compatible with the\n"
diff --git a/script/print-hpd-left-shift.go b/script/print-hpd-left-shift.go
index 47141bd..09b175a 100644
--- a/script/print-hpd-left-shift.go
+++ b/script/print-hpd-left-shift.go
@@ -27,6 +27,7 @@
 	"fmt"
 	"math"
 	"math/big"
+	"os"
 )
 
 var (
@@ -48,6 +49,13 @@
 }
 
 func main() {
+	if err := main1(); err != nil {
+		os.Stderr.WriteString(err.Error() + "\n")
+		os.Exit(1)
+	}
+}
+
+func main1() error {
 	flag.Parse()
 
 	const WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL = 60
@@ -111,4 +119,5 @@
 		fmt.Printf("             // offset=0x%04X\n", len(data)&^15)
 	}
 	fmt.Printf("};\n")
+	return nil
 }
diff --git a/script/print-json-token-debug-format.c b/script/print-json-token-debug-format.c
index 7d4827f..e140e45 100644
--- a/script/print-json-token-debug-format.c
+++ b/script/print-json-token-debug-format.c
@@ -84,6 +84,17 @@
 // program to generate a stand-alone C++ file.
 #include "../release/c/wuffs-unsupported-snapshot.c"
 
+// Wuffs allows either statically or dynamically allocated work buffers. This
+// program exercises static allocation.
+#define WORK_BUFFER_ARRAY_SIZE \
+  WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE
+#if WORK_BUFFER_ARRAY_SIZE > 0
+uint8_t g_work_buffer_array[WORK_BUFFER_ARRAY_SIZE];
+#else
+// Not all C/C++ compilers support 0-length arrays.
+uint8_t g_work_buffer_array[1];
+#endif
+
 #ifndef SRC_BUFFER_ARRAY_SIZE
 #define SRC_BUFFER_ARRAY_SIZE (64 * 1024 * 1024)
 #endif
@@ -91,14 +102,14 @@
 #define TOKEN_BUFFER_ARRAY_SIZE (128 * 1024)
 #endif
 
-uint8_t src_buffer_array[SRC_BUFFER_ARRAY_SIZE];
-wuffs_base__token tok_buffer_array[TOKEN_BUFFER_ARRAY_SIZE];
+uint8_t g_src_buffer_array[SRC_BUFFER_ARRAY_SIZE];
+wuffs_base__token g_tok_buffer_array[TOKEN_BUFFER_ARRAY_SIZE];
 
-wuffs_base__io_buffer src;
-wuffs_base__token_buffer tok;
+wuffs_base__io_buffer g_src;
+wuffs_base__token_buffer g_tok;
 
-wuffs_json__decoder dec;
-wuffs_base__status dec_status;
+wuffs_json__decoder g_dec;
+wuffs_base__status g_dec_status;
 
 #define TRY(error_msg)         \
   do {                         \
@@ -114,18 +125,18 @@
 
 const char*  //
 read_src() {
-  if (src.meta.closed) {
+  if (g_src.meta.closed) {
     return "main: internal error: read requested on a closed source";
   }
-  wuffs_base__io_buffer__compact(&src);
-  if (src.meta.wi >= src.data.len) {
-    return "main: src buffer is full";
+  wuffs_base__io_buffer__compact(&g_src);
+  if (g_src.meta.wi >= g_src.data.len) {
+    return "main: g_src buffer is full";
   }
-  size_t n = fread(src.data.ptr + src.meta.wi, sizeof(uint8_t),
-                   src.data.len - src.meta.wi, stdin);
-  src.meta.wi += n;
-  src.meta.closed = feof(stdin);
-  if ((n == 0) && !src.meta.closed) {
+  size_t n = fread(g_src.data.ptr + g_src.meta.wi, sizeof(uint8_t),
+                   g_src.data.len - g_src.meta.wi, stdin);
+  g_src.meta.wi += n;
+  g_src.meta.closed = feof(stdin);
+  if ((n == 0) && !g_src.meta.closed) {
     return "main: read error";
   }
   return NULL;
@@ -139,7 +150,8 @@
 
   bool all_tokens;
   bool human_readable;
-} flags = {0};
+  bool quirks;
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
@@ -164,23 +176,27 @@
     }
 
     if (!strcmp(arg, "a") || !strcmp(arg, "all-tokens")) {
-      flags.all_tokens = true;
+      g_flags.all_tokens = true;
       continue;
     }
     if (!strcmp(arg, "h") || !strcmp(arg, "human-readable")) {
-      flags.human_readable = true;
+      g_flags.human_readable = true;
+      continue;
+    }
+    if (!strcmp(arg, "q") || !strcmp(arg, "quirks")) {
+      g_flags.quirks = true;
       continue;
     }
 
     return "main: unrecognized flag argument";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return NULL;
 }
 
-const char* vbc_names[8] = {
+const char* g_vbc_names[8] = {
     "0:Filler..........",  //
     "1:Structure.......",  //
     "2:String..........",  //
@@ -191,7 +207,7 @@
     "7:Reserved........",  //
 };
 
-const int base38_decode[38] = {
+const int g_base38_decode[38] = {
     ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '?',       //
     'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',  //
     'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',  //
@@ -200,34 +216,61 @@
 const char*  //
 main1(int argc, char** argv) {
   TRY(parse_flags(argc, argv));
-  if (flags.remaining_argc > 0) {
+  if (g_flags.remaining_argc > 0) {
     return "main: bad argument: use \"program < input\", not \"program input\"";
   }
 
-  src = wuffs_base__make_io_buffer(
-      wuffs_base__make_slice_u8(src_buffer_array, SRC_BUFFER_ARRAY_SIZE),
+  g_src = wuffs_base__make_io_buffer(
+      wuffs_base__make_slice_u8(g_src_buffer_array, SRC_BUFFER_ARRAY_SIZE),
       wuffs_base__empty_io_buffer_meta());
 
-  tok = wuffs_base__make_token_buffer(
-      wuffs_base__make_slice_token(tok_buffer_array, TOKEN_BUFFER_ARRAY_SIZE),
+  g_tok = wuffs_base__make_token_buffer(
+      wuffs_base__make_slice_token(g_tok_buffer_array, TOKEN_BUFFER_ARRAY_SIZE),
       wuffs_base__empty_token_buffer_meta());
 
   wuffs_base__status init_status = wuffs_json__decoder__initialize(
-      &dec, sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0);
+      &g_dec, sizeof__wuffs_json__decoder(), WUFFS_VERSION, 0);
   if (!wuffs_base__status__is_ok(&init_status)) {
     return wuffs_base__status__message(&init_status);
   }
 
+  if (g_flags.quirks) {
+    uint32_t quirks[] = {
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO,
+        WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK,
+        WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE,
+        WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA,
+        WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS,
+        WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR,
+        WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK,
+        WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE,
+        WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE,
+        0,
+    };
+    uint32_t i;
+    for (i = 0; quirks[i]; i++) {
+      wuffs_json__decoder__set_quirk_enabled(&g_dec, quirks[i], true);
+    }
+  }
+
   uint64_t pos = 0;
   while (true) {
-    wuffs_base__status status =
-        wuffs_json__decoder__decode_tokens(&dec, &tok, &src);
+    wuffs_base__status status = wuffs_json__decoder__decode_tokens(
+        &g_dec, &g_tok, &g_src,
+        wuffs_base__make_slice_u8(g_work_buffer_array, WORK_BUFFER_ARRAY_SIZE));
 
-    while (tok.meta.ri < tok.meta.wi) {
-      wuffs_base__token* t = &tok.data.ptr[tok.meta.ri++];
+    while (g_tok.meta.ri < g_tok.meta.wi) {
+      wuffs_base__token* t = &g_tok.data.ptr[g_tok.meta.ri++];
       uint16_t len = wuffs_base__token__length(t);
 
-      if (flags.all_tokens || (wuffs_base__token__value(t) != 0)) {
+      if (g_flags.all_tokens || (wuffs_base__token__value(t) != 0)) {
         uint8_t lp = wuffs_base__token__link_prev(t) ? 1 : 0;
         uint8_t ln = wuffs_base__token__link_next(t) ? 1 : 0;
         uint32_t vmajor = wuffs_base__token__value_major(t);
@@ -235,7 +278,7 @@
         uint8_t vbc = wuffs_base__token__value_base_category(t);
         uint32_t vbd = wuffs_base__token__value_base_detail(t);
 
-        if (flags.human_readable) {
+        if (g_flags.human_readable) {
           printf("pos=0x%08" PRIX32 "  len=0x%04" PRIX16 "  link=0b%d%d  ",
                  (uint32_t)(pos), len, (int)(lp), (int)(ln));
 
@@ -250,10 +293,10 @@
             uint32_t m3 = m;
 
             printf("vmajor=0x%06" PRIX32 ":%c%c%c%c  vminor=0x%06" PRIX32 "\n",
-                   vmajor, base38_decode[m0], base38_decode[m1],
-                   base38_decode[m2], base38_decode[m3], vminor);
+                   vmajor, g_base38_decode[m0], g_base38_decode[m1],
+                   g_base38_decode[m2], g_base38_decode[m3], vminor);
           } else {
-            printf("vbc=%s.  vbd=0x%06" PRIX32 "\n", vbc_names[vbc & 7], vbd);
+            printf("vbc=%s.  vbd=0x%06" PRIX32 "\n", g_vbc_names[vbc & 7], vbd);
           }
 
         } else {
@@ -285,7 +328,7 @@
     } else if (status.repr == wuffs_base__suspension__short_read) {
       TRY(read_src());
     } else if (status.repr == wuffs_base__suspension__short_write) {
-      wuffs_base__token_buffer__compact(&tok);
+      wuffs_base__token_buffer__compact(&g_tok);
     } else {
       return wuffs_base__status__message(&status);
     }
diff --git a/script/print-lzw-example.go b/script/print-lzw-example.go
index ab09d6a..0d588ee 100644
--- a/script/print-lzw-example.go
+++ b/script/print-lzw-example.go
@@ -33,6 +33,7 @@
 
 import (
 	"fmt"
+	"os"
 )
 
 const (
@@ -74,6 +75,13 @@
 }
 
 func main() {
+	if err := main1(); err != nil {
+		os.Stderr.WriteString(err.Error() + "\n")
+		os.Exit(1)
+	}
+}
+
+func main1() error {
 	n, s, q := new(naive), new(suf1), new(sufQ)
 	decode(n)
 	decode(s)
@@ -109,6 +117,7 @@
 		fmt.Println()
 		key++
 	}
+	return nil
 }
 
 type implementation interface {
diff --git a/script/print-mpb-powers-of-10.go b/script/print-mpb-powers-of-10.go
new file mode 100644
index 0000000..6a55fe5
--- /dev/null
+++ b/script/print-mpb-powers-of-10.go
@@ -0,0 +1,113 @@
+// Copyright 2020 The Wuffs Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// +build ignore
+
+package main
+
+// print-mpb-powers-of-10.go prints the
+// wuffs_base__private_implementation__medium_prec_bin__powers_of_10 tables.
+//
+// Usage: go run print-mpb-powers-of-10.go -comments
+
+import (
+	"flag"
+	"fmt"
+	"math/big"
+	"os"
+)
+
+var (
+	comments = flag.Bool("comments", false, "whether to print comments")
+)
+
+func main() {
+	if err := main1(); err != nil {
+		os.Stderr.WriteString(err.Error() + "\n")
+		os.Exit(1)
+	}
+}
+
+func main1() error {
+	flag.Parse()
+
+	const bigCount = 1 + ((+340 - -348) / 8)
+	fmt.Printf("static const uint32_t "+
+		"wuffs_base__private_implementation__big_powers_of_10[%d] = {\n", 3*bigCount)
+	for e := -348; e <= +340; e += 8 {
+		if err := do(e); err != nil {
+			return err
+		}
+	}
+	fmt.Printf("};\n\n")
+
+	fmt.Printf("static const uint32_t " +
+		"wuffs_base__private_implementation__small_powers_of_10[24] = {\n")
+	for e := 0; e <= 7; e += 1 {
+		if err := do(e); err != nil {
+			return err
+		}
+	}
+	fmt.Printf("};\n")
+
+	return nil
+}
+
+var (
+	one   = big.NewInt(1)
+	ten   = big.NewInt(10)
+	two64 = big.NewInt(0).Lsh(one, 64)
+)
+
+// N is large enough so that (1<<N) is bigger than 1e348.
+const N = 2048
+
+func do(e int) error {
+	z := big.NewInt(0).Lsh(one, N)
+	if e >= 0 {
+		exp := big.NewInt(0).Exp(ten, big.NewInt(int64(+e)), nil)
+		z.Mul(z, exp)
+	} else {
+		exp := big.NewInt(0).Exp(ten, big.NewInt(int64(-e)), nil)
+		z.Div(z, exp)
+	}
+
+	roundUp := false
+	n := int32(-N)
+	for z.Cmp(two64) >= 0 {
+		roundUp = z.Bit(0) > 0
+		z.Rsh(z, 1)
+		n++
+	}
+	if roundUp {
+		z.Add(z, one)
+	}
+	hex := fmt.Sprintf("%X", z)
+	if len(hex) != 16 {
+		return fmt.Errorf("invalid hexadecimal representation %q", hex)
+	}
+
+	fmt.Printf("    0x%s, 0x%s, 0x%08X,", hex[8:], hex[:8], uint32(n))
+	if *comments {
+		fmt.Printf("  // 1e%-04d ≈ (0x%s ", e, hex)
+		if n >= 0 {
+			fmt.Printf("<< %4d)", +n)
+		} else {
+			fmt.Printf(">> %4d)", -n)
+		}
+	}
+
+	fmt.Println()
+	return nil
+}
diff --git a/std/adler32/common_adler32.wuffs b/std/adler32/common_adler32.wuffs
index b336617..9c18fe0 100644
--- a/std/adler32/common_adler32.wuffs
+++ b/std/adler32/common_adler32.wuffs
@@ -51,7 +51,7 @@
 		s2 %= 65521
 
 		args.x = remaining
-	}
+	} endwhile
 
 	this.state = ((s2 & 0xFFFF) << 16) | (s1 & 0xFFFF)
 	return this.state
diff --git a/std/bmp/decode_bmp.wuffs b/std/bmp/decode_bmp.wuffs
index 032f798..e0f6658 100644
--- a/std/bmp/decode_bmp.wuffs
+++ b/std/bmp/decode_bmp.wuffs
@@ -70,7 +70,7 @@
 	// Read the BITMAPFILEHEADER (14 bytes).
 
 	magic = args.src.read_u16le_as_u32?()
-	if magic <> 0x4D42 {  // "BM" little-endian.
+	if magic <> 'BM'le {
 		return "#bad header"
 	}
 
@@ -277,7 +277,7 @@
 			} else {
 				return status
 			}
-		}
+		} endwhile
 	}
 
 	this.call_sequence = 3
@@ -314,7 +314,7 @@
 		}
 		this.pending_pad -= 1
 		args.src = args.src[1 ..]
-	}
+	} endwhile
 
 	// Handle the case where the I/O suspension occurred in the middle of a
 	// source pixel.
@@ -327,7 +327,7 @@
 			this.stash[this.num_stashed] = args.src[0]
 			this.num_stashed += 1
 			args.src = args.src[1 ..]
-		}
+		} endwhile
 
 		// Write the single pixel.
 		dst = tab.row(y: this.dst_y)
@@ -393,10 +393,10 @@
 				this.stash[this.num_stashed] = args.src[0]
 				this.num_stashed += 1
 				args.src = args.src[1 ..]
-			}
+			} endwhile
 			return base."$short read"
 		}
-	}
+	} endwhile
 
 	return ok
 }
diff --git a/std/deflate/decode_deflate.wuffs b/std/deflate/decode_deflate.wuffs
index 97ffe6d..d99ee6d 100644
--- a/std/deflate/decode_deflate.wuffs
+++ b/std/deflate/decode_deflate.wuffs
@@ -211,7 +211,7 @@
 		// can change the veracity of any args.dst assertions?
 		this.add_history!(hist: args.dst.since(mark: mark))
 		yield? status
-	}
+	} endwhile
 }
 
 pri func decoder.decode_blocks?(dst: base.io_writer, src: base.io_reader) {
@@ -227,7 +227,7 @@
 			b0 = args.src.read_u8_as_u32?()
 			this.bits |= b0 << this.n_bits
 			this.n_bits += 8
-		}
+		} endwhile
 		final = this.bits & 0x01
 		type = (this.bits >> 1) & 0x03
 		this.bits >>= 3
@@ -266,7 +266,7 @@
 			if this.end_of_block {
 				continue.outer
 			}
-		}
+		} endwhile
 	} endwhile.outer
 }
 
@@ -301,7 +301,7 @@
 		} else {
 			yield? base."$short read"
 		}
-	}
+	} endwhile
 }
 
 // init_fixed_huffman initializes this.huffs as per the RFC section 3.2.6.
@@ -312,23 +312,23 @@
 	while i < 144 {
 		this.code_lengths[i] = 8
 		i += 1
-	}
+	} endwhile
 	while i < 256 {
 		this.code_lengths[i] = 9
 		i += 1
-	}
+	} endwhile
 	while i < 280 {
 		this.code_lengths[i] = 7
 		i += 1
-	}
+	} endwhile
 	while i < 288 {
 		this.code_lengths[i] = 8
 		i += 1
-	}
+	} endwhile
 	while i < 320 {
 		this.code_lengths[i] = 5
 		i += 1
-	}
+	} endwhile
 
 	status = this.init_huff!(which: 0, n_codes0: 0, n_codes1: 288, base_symbol: 257)
 	if status.is_error() {
@@ -369,7 +369,7 @@
 		b0 = args.src.read_u8_as_u32?()
 		bits |= b0 << n_bits
 		n_bits += 8
-	}
+	} endwhile
 	n_lit = bits.low_bits(n: 5) + 257
 	if n_lit > 286 {
 		return "#bad literal/length code count"
@@ -394,17 +394,17 @@
 			b1 = args.src.read_u8_as_u32?()
 			bits |= b1 << n_bits
 			n_bits += 8
-		}
+		} endwhile
 		assert i < 19 via "a < b: a < c; c <= b"(c: n_clen)
 		this.code_lengths[code_order[i]] = (bits & 0x07) as base.u8
 		bits >>= 3
 		n_bits -= 3
 		i += 1
-	}
+	} endwhile
 	while i < 19 {
 		this.code_lengths[code_order[i]] = 0
 		i += 1
-	}
+	} endwhile
 	status = this.init_huff!(which: 0, n_codes0: 0, n_codes1: 19, base_symbol: 0xFFF)
 	if status.is_error() {
 		return status
@@ -431,7 +431,7 @@
 			b2 = args.src.read_u8_as_u32?()
 			bits |= b2 << n_bits
 			n_bits += 8
-		}
+		} endwhile
 		// For H-CL, there should be no redirections and all symbols should be
 		// literals.
 		if (table_entry >> 24) <> 0x80 {
@@ -480,7 +480,7 @@
 			b3 = args.src.read_u8_as_u32?()
 			bits |= b3 << n_bits
 			n_bits += 8
-		}
+		} endwhile
 		rep_count += bits.low_bits(n: n_extra_bits)
 		bits >>= n_extra_bits
 		n_bits -= n_extra_bits
@@ -494,8 +494,8 @@
 			this.code_lengths[i] = rep_symbol
 			i += 1
 			rep_count -= 1
-		}
-	}
+		} endwhile
+	} endwhile
 
 	if i <> (n_lit + n_dist) {
 		return "#bad Huffman code length count"
@@ -588,7 +588,7 @@
 		}
 		counts[this.code_lengths[i] & 15] += 1
 		i += 1
-	}
+	} endwhile
 	if ((counts[0] as base.u32) + args.n_codes0) == args.n_codes1 {
 		return "#no Huffman codes"
 	}
@@ -607,7 +607,7 @@
 		}
 		remaining -= counts[i] as base.u32
 		i += 1
-	}
+	} endwhile
 	if remaining <> 0 {
 		// As a special case, allow a degenerate H-D Huffman table, with only
 		// one 1-bit code, for the smallest possible distance.
@@ -648,7 +648,7 @@
 		// bounds checking can handle it.
 		n_symbols = n_symbols + count
 		i += 1
-	}
+	} endwhile
 	if n_symbols > 288 {
 		return "#internal error: inconsistent Huffman decoder state"
 	}
@@ -688,7 +688,7 @@
 			offsets[this.code_lengths[i] & 15] += 1
 		}
 		i += 1
-	}
+	} endwhile
 
 	// Calculate min_cl and max_cl.
 	//
@@ -706,7 +706,7 @@
 			return "#bad Huffman minimum code length"
 		}
 		min_cl += 1
-	}
+	} endwhile
 	max_cl = 15
 	while true,
 		inv n_symbols <= 288,
@@ -718,7 +718,7 @@
 			return "#no Huffman codes"
 		}
 		max_cl -= 1
-	}
+	} endwhile
 	if max_cl <= 9 {
 		this.n_huffs_bits[args.which] = max_cl
 	} else {
@@ -806,7 +806,7 @@
 					}
 					remaining <<= 1
 					j += 1
-				}
+				} endwhile
 				if (j <= 9) or (15 < j) {
 					return "#internal error: inconsistent Huffman decoder state"
 				}
@@ -867,7 +867,7 @@
 			}
 			assert (top + ((high_bits | reversed_key) & 511)) < 1024 via "a < b: a < c; c <= b"(c: huffs_table_size)
 			this.huffs[args.which][top + ((high_bits | reversed_key) & 511)] = value
-		}
+		} endwhile
 
 		i += 1
 		if i >= n_symbols {
@@ -878,6 +878,6 @@
 		if code >= (1 << 15) {
 			return "#internal error: inconsistent Huffman decoder state"
 		}
-	}
+	} endwhile
 	return ok
 }
diff --git a/std/deflate/decode_huffman_fast.wuffs b/std/deflate/decode_huffman_fast.wuffs
index a803456..c9f7e0a 100644
--- a/std/deflate/decode_huffman_fast.wuffs
+++ b/std/deflate/decode_huffman_fast.wuffs
@@ -341,7 +341,7 @@
 			// Copy from args.dst.
 			args.dst.copy_n32_from_history_fast!(n: length, distance: (dist_minus_1 + 1))
 			break
-		}
+		} endwhile
 	} endwhile.loop
 
 	// Ensure n_bits < 8 by rewindng args.src, if we loaded too many of its
@@ -363,7 +363,7 @@
 		} else {
 			return "#internal error: inconsistent I/O"
 		}
-	}
+	} endwhile
 
 	this.bits = bits & (((1 as base.u32) << n_bits) - 1)
 	this.n_bits = n_bits
diff --git a/std/deflate/decode_huffman_slow.wuffs b/std/deflate/decode_huffman_slow.wuffs
index 934964e..1166fd5 100644
--- a/std/deflate/decode_huffman_slow.wuffs
+++ b/std/deflate/decode_huffman_slow.wuffs
@@ -62,7 +62,7 @@
 			b0 = args.src.read_u8_as_u32?()
 			bits |= b0 << n_bits
 			n_bits += 8
-		}
+		} endwhile
 
 		if (table_entry >> 31) <> 0 {
 			// Literal.
@@ -90,7 +90,7 @@
 				b1 = args.src.read_u8_as_u32?()
 				bits |= b1 << n_bits
 				n_bits += 8
-			}
+			} endwhile
 
 			if (table_entry >> 31) <> 0 {
 				// Literal.
@@ -130,7 +130,7 @@
 				b2 = args.src.read_u8_as_u32?()
 				bits |= b2 << n_bits
 				n_bits += 8
-			}
+			} endwhile
 			// The "+ 253" is the same as "- 3", after the "& 0xFF", but the
 			// plus form won't require an underflow check.
 			length = ((length + 253 + bits.low_bits(n: table_entry_n_bits)) & 0xFF) + 3
@@ -151,7 +151,7 @@
 			b3 = args.src.read_u8_as_u32?()
 			bits |= b3 << n_bits
 			n_bits += 8
-		}
+		} endwhile
 		// Check for a redirect.
 		if (table_entry >> 28) == 1 {
 			redir_top = (table_entry >> 8) & 0xFFFF
@@ -168,7 +168,7 @@
 				b4 = args.src.read_u8_as_u32?()
 				bits |= b4 << n_bits
 				n_bits += 8
-			}
+			} endwhile
 		}
 
 		// For H-D, all symbols should be base_number + extra_bits.
@@ -195,7 +195,7 @@
 				b5 = args.src.read_u8_as_u32?()
 				bits |= b5 << n_bits
 				n_bits += 8
-			}
+			} endwhile
 			dist_minus_1 = (dist_minus_1 + bits.low_bits(n: table_entry_n_bits)) & 0x7FFF
 			bits >>= table_entry_n_bits
 			n_bits -= table_entry_n_bits
@@ -241,7 +241,7 @@
 						}
 					}
 					yield? base."$short write"
-				}
+				} endwhile
 				// Copy from the start of this.history, if we wrapped around.
 				if hlen > 0 {
 					while true {
@@ -254,7 +254,7 @@
 						hlen -= n_copied
 						hdist ~mod+= n_copied
 						yield? base."$short write"
-					}
+					} endwhile
 				}
 
 				if length == 0 {
@@ -271,7 +271,7 @@
 			}
 			length -= n_copied
 			yield? base."$short write"
-		}
+		} endwhile
 	} endwhile.loop
 
 	// TODO: "assert n_bits < 8"? What about (bits >> n_bits)?
diff --git a/std/gif/decode_config.wuffs b/std/gif/decode_config.wuffs
index 235bdf8..f86ec9c 100644
--- a/std/gif/decode_config.wuffs
+++ b/std/gif/decode_config.wuffs
@@ -180,9 +180,9 @@
 }
 
 pub func config_decoder.set_report_metadata!(fourcc: base.u32, report: base.bool) {
-	if args.fourcc == 0x4943_4350 {  // "ICCP"
+	if args.fourcc == 'ICCP'be {
 		this.report_metadata_iccp = args.report
-	} else if args.fourcc == 0x584D_5020 {  // "XMP "
+	} else if args.fourcc == 'XMP 'be {
 		this.report_metadata_xmp = args.report
 	}
 }
@@ -200,11 +200,11 @@
 			post args.src.available() > 0,
 		{
 			yield? base."$short read"
-		}
+		} endwhile
 
 		this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
 		if this.metadata_chunk_length_value > 0 {
-			if this.metadata_fourcc_value == 0x584D_5020 {  // "XMP "
+			if this.metadata_fourcc_value == 'XMP 'be {
 				// The +1 is because XMP metadata's encoding includes each
 				// block's leading byte (the block size) as part of the
 				// metadata passed to the caller.
@@ -308,7 +308,7 @@
 				post args.src.available() > 0,
 			{
 				yield? base."$short read"
-			}
+			} endwhile
 			flags = args.src.peek_u8()
 			if (flags & 0x80) <> 0 {
 				background_color = this.black_color_u32_argb_premul
@@ -413,7 +413,7 @@
 		} else {
 			return "#bad block"
 		}
-	}
+	} endwhile
 }
 
 // decode_header reads either "GIF87a" or "GIF89a".
@@ -426,9 +426,9 @@
 	while i < 6 {
 		c[i] = args.src.read_u8?()
 		i += 1
-	}
-	if (c[0] <> 0x47) or (c[1] <> 0x49) or (c[2] <> 0x46) or (c[3] <> 0x38) or
-		((c[4] <> 0x37) and (c[4] <> 0x39)) or (c[5] <> 0x61) {
+	} endwhile
+	if (c[0] <> 'G') or (c[1] <> 'I') or (c[2] <> 'F') or (c[3] <> '8') or
+		((c[4] <> '7') and (c[4] <> '9')) or (c[5] <> 'a') {
 		return "#bad header"
 	}
 }
@@ -467,7 +467,7 @@
 			this.palettes[0][(4 * i) + 2] = ((argb >> 16) & 0xFF) as base.u8
 			this.palettes[0][(4 * i) + 3] = ((argb >> 24) & 0xFF) as base.u8
 			i += 1
-		}
+		} endwhile
 
 		if this.quirk_enabled_honor_background_color {
 			if (background_color_index <> 0) and
@@ -496,7 +496,7 @@
 		this.palettes[0][(4 * i) + 2] = 0x00
 		this.palettes[0][(4 * i) + 3] = 0xFF
 		i += 1
-	}
+	} endwhile
 }
 
 // decode_extension reads an extension. The Extension Introducer byte has
@@ -532,7 +532,7 @@
 			return ok
 		}
 		args.src.skip32?(n: block_size as base.u32)
-	}
+	} endwhile
 }
 
 // decode_ae reads an Application Extension.
@@ -544,9 +544,7 @@
 	var is_iccp     : base.bool
 	var is_xmp      : base.bool
 
-	// This "while true" always executes exactly once, as it ends with a
-	// "break", but using "break"s throughout simplifies the control flow.
-	while true {
+	while.goto_done true {
 		block_size = args.src.read_u8?()
 		if block_size == 0 {
 			return ok
@@ -560,7 +558,7 @@
 		// Other extensions include XMP metadata.
 		if block_size <> 11 {
 			args.src.skip32?(n: block_size as base.u32)
-			break
+			break.goto_done
 		}
 		is_animexts = true
 		is_netscape = true
@@ -574,7 +572,7 @@
 			is_iccp = is_iccp and (c == iccrgbg1012[block_size])
 			is_xmp = is_xmp and (c == xmpdataxmp[block_size])
 			block_size += 1
-		}
+		} endwhile
 
 		if is_animexts or is_netscape {
 			// Those 11 bytes should be followed by 0x03, 0x01 and then the loop
@@ -582,12 +580,12 @@
 			block_size = args.src.read_u8?()
 			if block_size <> 3 {
 				args.src.skip32?(n: block_size as base.u32)
-				break
+				break.goto_done
 			}
 			c = args.src.read_u8?()
 			if c <> 0x01 {
 				args.src.skip32?(n: 2)
-				break
+				break.goto_done
 			}
 			this.num_loops = args.src.read_u16le_as_u32?()
 			this.seen_num_loops = true
@@ -614,10 +612,10 @@
 				post args.src.available() > 0,
 			{
 				yield? base."$short read"
-			}
+			} endwhile
 			this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
 			args.src.skip32_fast!(actual: 1, worst_case: 1)
-			this.metadata_fourcc_value = 0x4943_4350  // "ICCP"
+			this.metadata_fourcc_value = 'ICCP'be
 			this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
 			this.call_sequence = 1
 			return base."@metadata reported"
@@ -627,7 +625,7 @@
 				post args.src.available() > 0,
 			{
 				yield? base."$short read"
-			}
+			} endwhile
 			this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
 			if this.metadata_chunk_length_value > 0 {
 				// The +1 is because XMP metadata's encoding includes each
@@ -637,14 +635,14 @@
 			} else {
 				args.src.skip32_fast!(actual: 1, worst_case: 1)
 			}
-			this.metadata_fourcc_value = 0x584D_5020  // "XMP "
+			this.metadata_fourcc_value = 'XMP 'be
 			this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
 			this.call_sequence = 1
 			return base."@metadata reported"
 		}
 
-		break
-	}
+		break.goto_done
+	} endwhile.goto_done
 	this.skip_blocks?(src: args.src)
 }
 
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 4f98771..0d56bda 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -219,9 +219,9 @@
 }
 
 pub func decoder.set_report_metadata!(fourcc: base.u32, report: base.bool) {
-	if args.fourcc == 0x4943_4350 {  // "ICCP"
+	if args.fourcc == 'ICCP'be {
 		this.report_metadata_iccp = args.report
-	} else if args.fourcc == 0x584D_5020 {  // "XMP "
+	} else if args.fourcc == 'XMP 'be {
 		this.report_metadata_xmp = args.report
 	}
 }
@@ -239,11 +239,11 @@
 			post args.src.available() > 0,
 		{
 			yield? base."$short read"
-		}
+		} endwhile
 
 		this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
 		if this.metadata_chunk_length_value > 0 {
-			if this.metadata_fourcc_value == 0x584D_5020 {  // "XMP "
+			if this.metadata_fourcc_value == 'XMP 'be {
 				// The +1 is because XMP metadata's encoding includes each
 				// block's leading byte (the block size) as part of the
 				// metadata passed to the caller.
@@ -367,7 +367,7 @@
 				post args.src.available() > 0,
 			{
 				yield? base."$short read"
-			}
+			} endwhile
 			flags = args.src.peek_u8()
 			if (flags & 0x80) <> 0 {
 				background_color = this.black_color_u32_argb_premul
@@ -488,7 +488,7 @@
 		} else {
 			return "#bad block"
 		}
-	}
+	} endwhile
 }
 
 // decode_header reads either "GIF87a" or "GIF89a".
@@ -501,9 +501,9 @@
 	while i < 6 {
 		c[i] = args.src.read_u8?()
 		i += 1
-	}
-	if (c[0] <> 0x47) or (c[1] <> 0x49) or (c[2] <> 0x46) or (c[3] <> 0x38) or
-		((c[4] <> 0x37) and (c[4] <> 0x39)) or (c[5] <> 0x61) {
+	} endwhile
+	if (c[0] <> 'G') or (c[1] <> 'I') or (c[2] <> 'F') or (c[3] <> '8') or
+		((c[4] <> '7') and (c[4] <> '9')) or (c[5] <> 'a') {
 		return "#bad header"
 	}
 }
@@ -542,7 +542,7 @@
 			this.palettes[0][(4 * i) + 2] = ((argb >> 16) & 0xFF) as base.u8
 			this.palettes[0][(4 * i) + 3] = ((argb >> 24) & 0xFF) as base.u8
 			i += 1
-		}
+		} endwhile
 
 		if this.quirk_enabled_honor_background_color {
 			if (background_color_index <> 0) and
@@ -571,7 +571,7 @@
 		this.palettes[0][(4 * i) + 2] = 0x00
 		this.palettes[0][(4 * i) + 3] = 0xFF
 		i += 1
-	}
+	} endwhile
 }
 
 // decode_extension reads an extension. The Extension Introducer byte has
@@ -607,7 +607,7 @@
 			return ok
 		}
 		args.src.skip32?(n: block_size as base.u32)
-	}
+	} endwhile
 }
 
 // decode_ae reads an Application Extension.
@@ -619,9 +619,7 @@
 	var is_iccp     : base.bool
 	var is_xmp      : base.bool
 
-	// This "while true" always executes exactly once, as it ends with a
-	// "break", but using "break"s throughout simplifies the control flow.
-	while true {
+	while.goto_done true {
 		block_size = args.src.read_u8?()
 		if block_size == 0 {
 			return ok
@@ -635,7 +633,7 @@
 		// Other extensions include XMP metadata.
 		if block_size <> 11 {
 			args.src.skip32?(n: block_size as base.u32)
-			break
+			break.goto_done
 		}
 		is_animexts = true
 		is_netscape = true
@@ -649,7 +647,7 @@
 			is_iccp = is_iccp and (c == iccrgbg1012[block_size])
 			is_xmp = is_xmp and (c == xmpdataxmp[block_size])
 			block_size += 1
-		}
+		} endwhile
 
 		if is_animexts or is_netscape {
 			// Those 11 bytes should be followed by 0x03, 0x01 and then the loop
@@ -657,12 +655,12 @@
 			block_size = args.src.read_u8?()
 			if block_size <> 3 {
 				args.src.skip32?(n: block_size as base.u32)
-				break
+				break.goto_done
 			}
 			c = args.src.read_u8?()
 			if c <> 0x01 {
 				args.src.skip32?(n: 2)
-				break
+				break.goto_done
 			}
 			this.num_loops = args.src.read_u16le_as_u32?()
 			this.seen_num_loops = true
@@ -689,10 +687,10 @@
 				post args.src.available() > 0,
 			{
 				yield? base."$short read"
-			}
+			} endwhile
 			this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
 			args.src.skip32_fast!(actual: 1, worst_case: 1)
-			this.metadata_fourcc_value = 0x4943_4350  // "ICCP"
+			this.metadata_fourcc_value = 'ICCP'be
 			this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
 			this.call_sequence = 1
 			return base."@metadata reported"
@@ -702,7 +700,7 @@
 				post args.src.available() > 0,
 			{
 				yield? base."$short read"
-			}
+			} endwhile
 			this.metadata_chunk_length_value = args.src.peek_u8_as_u64()
 			if this.metadata_chunk_length_value > 0 {
 				// The +1 is because XMP metadata's encoding includes each
@@ -712,14 +710,14 @@
 			} else {
 				args.src.skip32_fast!(actual: 1, worst_case: 1)
 			}
-			this.metadata_fourcc_value = 0x584D_5020  // "XMP "
+			this.metadata_fourcc_value = 'XMP 'be
 			this.metadata_io_position = args.src.position() ~sat+ this.metadata_chunk_length_value
 			this.call_sequence = 1
 			return base."@metadata reported"
 		}
 
-		break
-	}
+		break.goto_done
+	} endwhile.goto_done
 	this.skip_blocks?(src: args.src)
 }
 
@@ -836,7 +834,7 @@
 			this.palettes[1][(4 * i) + 2] = ((argb >> 16) & 0xFF) as base.u8
 			this.palettes[1][(4 * i) + 3] = ((argb >> 24) & 0xFF) as base.u8
 			i += 1
-		}
+		} endwhile
 		// Set the remaining palette entries to opaque black.
 		while i < 256 {
 			this.palettes[1][(4 * i) + 0] = 0x00
@@ -844,7 +842,7 @@
 			this.palettes[1][(4 * i) + 2] = 0x00
 			this.palettes[1][(4 * i) + 3] = 0xFF
 			i += 1
-		}
+		} endwhile
 	} else if this.quirk_enabled_reject_empty_palette and (not this.has_global_palette) {
 		return "#bad palette"
 	} else if this.gc_has_transparent_index {
@@ -931,7 +929,7 @@
 		}
 		while args.src.available() == 0 {
 			yield? base."$short read"
-		}
+		} endwhile
 
 		if this.compressed_ri == this.compressed_wi {
 			this.compressed_ri = 0
@@ -955,7 +953,7 @@
 			}
 			block_size = args.src.peek_u8_as_u64()
 			args.src.skip32_fast!(actual: 1, worst_case: 1)
-		}
+		} endwhile
 
 		while.inner true {
 			if (this.compressed_ri > this.compressed_wi) or (this.compressed_wi > 4096) {
@@ -1098,7 +1096,7 @@
 					replicate_dst = tab.row(y: replicate_y0)
 					replicate_dst.copy_from_slice!(s: replicate_src)
 					replicate_y0 += 1
-				}
+				} endwhile
 				this.dirty_max_excl_y = this.dirty_max_excl_y.max(a: replicate_y1)
 			}
 
@@ -1106,7 +1104,7 @@
 			while (this.interlace > 0) and (this.dst_y >= this.frame_rect_y1) {
 				this.interlace -= 1
 				this.dst_y = this.frame_rect_y0 ~sat+ interlace_start[this.interlace]
-			}
+			} endwhile
 			continue
 		}
 
@@ -1132,7 +1130,7 @@
 			while (this.interlace > 0) and (this.dst_y >= this.frame_rect_y1) {
 				this.interlace -= 1
 				this.dst_y = this.frame_rect_y0 ~sat+ interlace_start[this.interlace]
-			}
+			} endwhile
 			continue
 		}
 
@@ -1140,7 +1138,7 @@
 			return "#internal error: inconsistent ri/wi"
 		}
 		break
-	}
+	} endwhile
 	return ok
 }
 //#DONE PREPROC900
diff --git a/std/gzip/decode_gzip.wuffs b/std/gzip/decode_gzip.wuffs
index c5dfb76..0664003 100644
--- a/std/gzip/decode_gzip.wuffs
+++ b/std/gzip/decode_gzip.wuffs
@@ -87,7 +87,7 @@
 			if c == 0 {
 				break
 			}
-		}
+		} endwhile
 	}
 
 	// Handle FCOMMENT.
@@ -97,7 +97,7 @@
 			if c == 0 {
 				break
 			}
-		}
+		} endwhile
 	}
 
 	// Handle FHCRC.
@@ -122,7 +122,7 @@
 			break
 		}
 		yield? status
-	}
+	} endwhile
 	checksum_want = args.src.read_u32le?()
 	decoded_length_want = args.src.read_u32le?()
 	if (not this.ignore_checksum) and
diff --git a/std/json/common_consts.wuffs b/std/json/common_consts.wuffs
index 553768d..10c7efe 100644
--- a/std/json/common_consts.wuffs
+++ b/std/json/common_consts.wuffs
@@ -21,6 +21,8 @@
 
 pri status "#internal error: inconsistent I/O"
 
+pub const decoder_workbuf_len_max_incl_worst_case base.u64 = 0
+
 // decoder_depth_max_incl is the maximum supported recursion depth: how deeply
 // nested [] arrays and {} objects can be.
 //
@@ -56,6 +58,24 @@
 
 // Look-Up Tables (LUTs).
 
+// lut_backslashes[i] helps decode "\i", for various 'i's.
+//
+// If the element's 0x80 bit is set then "\i" is unconditionally a valid
+// single-output-byte backslash-escape. The low 7 bits are the unescaped value.
+// For example, lut_backslashes['n'] is (0x80 | 0x0A), because "\n" is U+000A.
+//
+// If the element is non-zero (but the 0x80 bit is not set) then "\i"'s
+// validity depends on the relevant quirk. The element's value is an enum:
+//  - 1: "\a", U+0007, quirk_allow_backslash_a.
+//  - 2: "\e", U+001B, quirk_allow_backslash_e.
+//  - 3: "\?", U+003F, quirk_allow_backslash_question_mark.
+//  - 4: "\'", U+0027, quirk_allow_backslash_single_quote.
+//  - 5: "\v", U+000B, quirk_allow_backslash_v.
+//  - 6: "\0", U+0000, quirk_allow_backslash_zero.
+// The U+1234 values are held in lut_quirky_backslashes, below.
+//
+// If the element is zero then "\i" is invalid, or it is a special case, the
+// start of "\x12", "\u1234" or "\U12345678".
 pri const lut_backslashes array[256] base.u8 = [
 	// 0     1     2     3     4     5     6     7
 	// 8     9     A     B     C     D     E     F
@@ -63,18 +83,18 @@
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x08 ..= 0x0F.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x10 ..= 0x17.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x18 ..= 0x1F.
-	0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x20 ..= 0x27. '"'.
+	0x00, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, 0x04,  // 0x20 ..= 0x27. '"', '\''.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAF,  // 0x28 ..= 0x2F. '/'.
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x30 ..= 0x37.
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x38 ..= 0x3F.
+	0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x30 ..= 0x37. '0'.
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,  // 0x38 ..= 0x3F. '?'
 
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x40 ..= 0x47.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x48 ..= 0x4F.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x50 ..= 0x57.
 	0x00, 0x00, 0x00, 0x00, 0xDC, 0x00, 0x00, 0x00,  // 0x58 ..= 0x5F. '\\'.
-	0x00, 0x00, 0x88, 0x00, 0x00, 0x00, 0x8C, 0x00,  // 0x60 ..= 0x67. 'b', 'f'.
+	0x00, 0x01, 0x88, 0x00, 0x00, 0x02, 0x8C, 0x00,  // 0x60 ..= 0x67. 'a', 'b', 'e', 'f'.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00,  // 0x68 ..= 0x6F. 'n'.
-	0x00, 0x00, 0x8D, 0x00, 0x89, 0x00, 0x00, 0x00,  // 0x70 ..= 0x77. 'r', 't'.
+	0x00, 0x00, 0x8D, 0x00, 0x89, 0x00, 0x05, 0x00,  // 0x70 ..= 0x77. 'r', 't', 'v'.
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x78 ..= 0x7F.
 
 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // 0x80 ..= 0x87.
@@ -98,6 +118,13 @@
 	// 8     9     A     B     C     D     E     F
 ]
 
+// lut_quirky_backslashes is discussed in the lut_backslashes comment. The
+// first and last elements (indexes 0 and 7) are not used, but 8 is a round
+// power of 2, so enforcing index-in-bounds is a simple "&7" operation.
+pri const lut_quirky_backslashes array[8] base.u8 = [
+	0x00, 0x07, 0x1B, 0x3F, 0x27, 0x0B, 0x00, 0x00,
+]
+
 // lut_chars helps decode bytes within a string:
 //  - 0x00 is 1-byte UTF-8 (ASCII) but not '"', '\\' or a C0 control code.
 //  - 0x01 is '"'.
@@ -171,8 +198,8 @@
 //  - 0x08 (bitmask 0x0100) is CLASS_CLOSE_SQUARE_BRACKET.
 //  - 0x09 (bitmask 0x0200) is CLASS_FALSE.
 //  - 0x0A (bitmask 0x0400) is CLASS_TRUE.
-//  - 0x0B (bitmask 0x0800) is CLASS_NULL.
-//  - 0x0C (bitmask 0x1000) is reserved.
+//  - 0x0B (bitmask 0x0800) is CLASS_NULL_NAN_INF.
+//  - 0x0C (bitmask 0x1000) is CLASS_COMMENT.
 //  - 0x0D (bitmask 0x2000) is reserved.
 //  - 0x0E (bitmask 0x4000) is reserved.
 //  - 0x0F (bitmask 0x8000) is CLASS_BAD_INPUT.
@@ -180,26 +207,29 @@
 // The bitmasks are used by the "expect" variable: what the next character
 // class can be.
 //
-//  - 0x0002 is EXPECT_STRING.
-//  - 0x0EB0 is EXPECT_NON_STRING_VALUE.
-//  - 0x0004 is EXPECT_COMMA.
-//  - 0x0008 is EXPECT_COLON.
-//  - 0x0040 is EXPECT_CLOSE_CURLY_BRACE.
-//  - 0x0100 is EXPECT_CLOSE_SQUARE_BRACKET.
+//  - 0x1002 is EXPECT_STRING.
+//  - 0x1EB0 is EXPECT_NON_STRING_VALUE.
+//  - 0x1004 is EXPECT_COMMA.
+//  - 0x1008 is EXPECT_COLON.
+//  - 0x1040 is EXPECT_CLOSE_CURLY_BRACE.
+//  - 0x1100 is EXPECT_CLOSE_SQUARE_BRACKET.
 //
 // Bitwise or'ing these together gives 0x0FFE. Whitespace is never expected, as
 // it is handled separately.
 //
-// EXPECT_VALUE is also defined to be 0x0EB2, equivalent to (EXPECT_STRING |
+// EXPECT_VALUE is also defined to be 0x1EB2, equivalent to (EXPECT_STRING |
 // EXPECT_NON_STRING_VALUE).
 //
-// EXPECT_NUMBER is also defined to be 0x0010. Testing for EXPECT_NUMBER's
+// EXPECT_NUMBER is also defined to be 0x1010. Testing for EXPECT_NUMBER's
 // presence is equivalent to testing for EXPECT_NON_STRING_VALUE.
 //
 // "Non-string value" includes literals (false, true, null), numbers, arrays
 // and objects.
 //
 // "String value" includes "this" and "th\u0061t".
+//
+// Comments are always expected. Whether the relevant quirks are enabled are
+// checked elsewhere.
 pri const lut_classes array[256] base.u8[..= 0x0F] = [
 	// 0     1     2     3     4     5     6     7
 	// 8     9     A     B     C     D     E     F
@@ -208,16 +238,16 @@
 	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x10 ..= 0x17.
 	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x18 ..= 0x1F.
 	0x00, 0x0F, 0x01, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x20 ..= 0x27. ' ', '"'.
-	0x0F, 0x0F, 0x0F, 0x0F, 0x02, 0x04, 0x0F, 0x0F,  // 0x28 ..= 0x2F. ',', '-'.
+	0x0F, 0x0F, 0x0F, 0x0B, 0x02, 0x04, 0x0F, 0x0C,  // 0x28 ..= 0x2F. '+', ',', '-', '/'.
 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,  // 0x30 ..= 0x37. '0'-'7'.
 	0x04, 0x04, 0x03, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x38 ..= 0x3F. '8'-'9', ':'.
 
 	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x40 ..= 0x47.
-	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x48 ..= 0x4F.
+	0x0F, 0x0B, 0x0F, 0x0F, 0x0F, 0x0F, 0x0B, 0x0F,  // 0x48 ..= 0x4F. 'I', 'N'.
 	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,  // 0x50 ..= 0x57.
 	0x0F, 0x0F, 0x0F, 0x07, 0x0F, 0x08, 0x0F, 0x0F,  // 0x58 ..= 0x5F. '[', ']'.
 	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x09, 0x0F,  // 0x60 ..= 0x67. 'f'.
-	0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0B, 0x0F,  // 0x68 ..= 0x6F. 'n'.
+	0x0F, 0x0B, 0x0F, 0x0F, 0x0F, 0x0F, 0x0B, 0x0F,  // 0x68 ..= 0x6F. 'i', 'n'.
 	0x0F, 0x0F, 0x0F, 0x0F, 0x0A, 0x0F, 0x0F, 0x0F,  // 0x70 ..= 0x77. 't'.
 	0x0F, 0x0F, 0x0F, 0x05, 0x0F, 0x06, 0x0F, 0x0F,  // 0x78 ..= 0x7F. '{', '}'.
 
diff --git a/std/json/decode_json.wuffs b/std/json/decode_json.wuffs
index 36aa2db..f2465fd 100644
--- a/std/json/decode_json.wuffs
+++ b/std/json/decode_json.wuffs
@@ -13,6 +13,27 @@
 // limitations under the License.
 
 pub struct decoder? implements base.token_decoder(
+	// quirk_enabled_allow_backslash_etc, an 8-element array, is indexed by the
+	// same enum as lut_quirky_backslashes.
+	quirk_enabled_allow_backslash_etc : array[8] base.bool,
+
+	quirk_enabled_allow_backslash_capital_u             : base.bool,
+	quirk_enabled_allow_backslash_x                     : base.bool,
+	quirk_enabled_allow_comment_block                   : base.bool,
+	quirk_enabled_allow_comment_line                    : base.bool,
+	quirk_enabled_allow_extra_comma                     : base.bool,
+	quirk_enabled_allow_inf_nan_numbers                 : base.bool,
+	quirk_enabled_allow_leading_ascii_record_separator  : base.bool,
+	quirk_enabled_allow_leading_unicode_byte_order_mark : base.bool,
+	quirk_enabled_allow_trailing_new_line               : base.bool,
+	quirk_enabled_replace_invalid_unicode               : base.bool,
+
+	allow_leading_ars  : base.bool,
+	allow_leading_ubom : base.bool,
+
+	end_of_data : base.bool,
+
+	util : base.utility,
 )(
 	// stack is conceptually an array of bits, implemented as an array of u32.
 	// The N'th bit being 0 or 1 means that we're in an array or object, where
@@ -45,7 +66,47 @@
 	stack : array[1024 / 32] base.u32,
 )
 
-pub func decoder.decode_tokens?(dst: base.token_writer, src: base.io_reader) {
+pub func decoder.set_quirk_enabled!(quirk: base.u32, enabled: base.bool) {
+	if args.quirk == quirk_allow_backslash_a {
+		this.quirk_enabled_allow_backslash_etc[1] = args.enabled
+	} else if args.quirk == quirk_allow_backslash_capital_u {
+		this.quirk_enabled_allow_backslash_capital_u = args.enabled
+	} else if args.quirk == quirk_allow_backslash_e {
+		this.quirk_enabled_allow_backslash_etc[2] = args.enabled
+	} else if args.quirk == quirk_allow_backslash_question_mark {
+		this.quirk_enabled_allow_backslash_etc[3] = args.enabled
+	} else if args.quirk == quirk_allow_backslash_single_quote {
+		this.quirk_enabled_allow_backslash_etc[4] = args.enabled
+	} else if args.quirk == quirk_allow_backslash_v {
+		this.quirk_enabled_allow_backslash_etc[5] = args.enabled
+	} else if args.quirk == quirk_allow_backslash_x {
+		this.quirk_enabled_allow_backslash_x = args.enabled
+	} else if args.quirk == quirk_allow_backslash_zero {
+		this.quirk_enabled_allow_backslash_etc[6] = args.enabled
+	} else if args.quirk == quirk_allow_comment_block {
+		this.quirk_enabled_allow_comment_block = args.enabled
+	} else if args.quirk == quirk_allow_comment_line {
+		this.quirk_enabled_allow_comment_line = args.enabled
+	} else if args.quirk == quirk_allow_extra_comma {
+		this.quirk_enabled_allow_extra_comma = args.enabled
+	} else if args.quirk == quirk_allow_inf_nan_numbers {
+		this.quirk_enabled_allow_inf_nan_numbers = args.enabled
+	} else if args.quirk == quirk_allow_leading_ascii_record_separator {
+		this.quirk_enabled_allow_leading_ascii_record_separator = args.enabled
+	} else if args.quirk == quirk_allow_leading_unicode_byte_order_mark {
+		this.quirk_enabled_allow_leading_unicode_byte_order_mark = args.enabled
+	} else if args.quirk == quirk_allow_trailing_new_line {
+		this.quirk_enabled_allow_trailing_new_line = args.enabled
+	} else if args.quirk == quirk_replace_invalid_unicode {
+		this.quirk_enabled_replace_invalid_unicode = args.enabled
+	}
+}
+
+pub func decoder.workbuf_len() base.range_ii_u64 {
+	return this.util.empty_range_ii_u64()
+}
+
+pub func decoder.decode_tokens?(dst: base.token_writer, src: base.io_reader, workbuf: slice base.u8) {
 	var vminor            : base.u32[..= 0xFF_FFFF]
 	var number_length     : base.u32[..= 0x3FF]
 	var number_status     : base.u32[..= 0x3]
@@ -55,18 +116,25 @@
 	var stack_byte        : base.u32[..= (1024 / 32) - 1]
 	var stack_bit         : base.u32[..= 31]
 	var match             : base.u32[..= 2]
-	var c_by_4            : base.u32
+	var c4                : base.u32
 	var c                 : base.u8
 	var backslash         : base.u8
 	var char              : base.u8
 	var class             : base.u8[..= 0x0F]
 	var multi_byte_utf8   : base.u32
 
+	var backslash_x_length : base.u32[..= 0xFFFF]
+	var backslash_x_ok     : base.u8
+	var backslash_x_string : base.u32
+
 	var uni4_ok             : base.u8
 	var uni4_string         : base.u64
 	var uni4_value          : base.u32[..= 0xFFFF]
 	var uni4_high_surrogate : base.u32[..= 0x10_FC00]
-	var uni4_rollback       : base.u32
+
+	var uni8_ok     : base.u8
+	var uni8_string : base.u64
+	var uni8_value  : base.u32[..= 0xFFFF_FFFF]
 
 	// expect is a bitmask of what the next character class can be.
 	//
@@ -77,7 +145,16 @@
 	var expect             : base.u32
 	var expect_after_value : base.u32
 
-	expect = 0x0EB2  // EXPECT_VALUE
+	while this.end_of_data {
+		return base."@end of data"
+	} endwhile
+
+	if this.quirk_enabled_allow_leading_ascii_record_separator or
+		this.quirk_enabled_allow_leading_unicode_byte_order_mark {
+		this.decode_leading?(dst: args.dst, src: args.src)
+	}
+
+	expect = 0x1EB2  // EXPECT_VALUE
 
 	while.outer true {
 		while.goto_parsed_a_leaf_value true {
@@ -197,11 +274,11 @@
 							inv args.dst.available() > 0,
 							inv args.src.available() > 0,
 						{
-							c_by_4 = args.src.peek_u32le()
-							if 0x00 <> (lut_chars[0xFF & (c_by_4 >> 0)] |
-								lut_chars[0xFF & (c_by_4 >> 8)] |
-								lut_chars[0xFF & (c_by_4 >> 16)] |
-								lut_chars[0xFF & (c_by_4 >> 24)]) {
+							c4 = args.src.peek_u32le()
+							if 0x00 <> (lut_chars[0xFF & (c4 >> 0)] |
+								lut_chars[0xFF & (c4 >> 8)] |
+								lut_chars[0xFF & (c4 >> 16)] |
+								lut_chars[0xFF & (c4 >> 24)]) {
 								break
 							}
 							args.src.skip32_fast!(actual: 4, worst_case: 4)
@@ -215,7 +292,7 @@
 								continue.string_loop_outer
 							}
 							string_length += 4
-						}
+						} endwhile
 
 						c = args.src.peek_u8()
 						char = lut_chars[c]
@@ -270,7 +347,7 @@
 							}
 							c = (args.src.peek_u16le() >> 8) as base.u8
 							backslash = lut_backslashes[c]
-							if backslash > 0 {
+							if (backslash & 0x80) <> 0 {
 								args.src.skip32_fast!(actual: 2, worst_case: 2)
 								args.dst.write_fast_token!(
 									value_major: 0,
@@ -279,7 +356,18 @@
 									length: 2)
 								continue.string_loop_outer
 
-							} else if c == 0x75 {  // 0x75 is 'u'.
+							} else if backslash <> 0 {
+								if this.quirk_enabled_allow_backslash_etc[backslash & 7] {
+									args.src.skip32_fast!(actual: 2, worst_case: 2)
+									args.dst.write_fast_token!(
+										value_major: 0,
+										value_minor: 0x60_0000 | (lut_quirky_backslashes[backslash & 7] as base.u32),
+										link: 0x3,
+										length: 2)
+									continue.string_loop_outer
+								}
+
+							} else if c == 'u' {
 								// -------- BEGIN backslash-u.
 								if args.src.available() < 6 {
 									if args.src.is_closed() {
@@ -331,9 +419,19 @@
 									// High surrogate, which needs to be
 									// followed by a "\\u1234" low surrogate.
 									// We've already peeked 6 bytes for the
-									// high surrogate. We need another 6.
+									// high surrogate. We need 12 in total:
+									// another 8 bytes at an offset of 4.
 									if args.src.available() < 12 {
 										if args.src.is_closed() {
+											if this.quirk_enabled_replace_invalid_unicode {
+												args.src.skip32_fast!(actual: 6, worst_case: 6)
+												args.dst.write_fast_token!(
+													value_major: 0,
+													value_minor: 0x60_FFFD,
+													link: 0x3,
+													length: 6)
+												continue.string_loop_outer
+											}
 											return "#bad backslash-escape"
 										}
 										yield? base."$short read"
@@ -342,16 +440,11 @@
 										char = 0
 										continue.string_loop_outer
 									}
-
-									// Roll forward 4 bytes, so that calling
-									// peek_u64le will pick up the last 8.
-									args.src.skip32_fast!(actual: 4, worst_case: 4)
-
-									uni4_string = args.src.peek_u64le() >> 16
+									uni4_string = args.src.peek_u64le_at(offset: 4) >> 16
 
 									// Look for the low surrogate's "\\u".
-									if ((0xFF & (uni4_string >> 0)) <> 0x5C) or
-										((0xFF & (uni4_string >> 8)) <> 0x75) {
+									if ((0xFF & (uni4_string >> 0)) <> '\\') or
+										((0xFF & (uni4_string >> 8)) <> 'u') {
 										uni4_high_surrogate = 0
 										uni4_value = 0
 										uni4_ok = 0
@@ -381,30 +474,142 @@
 
 										// Emit a single token for the surrogate pair.
 										uni4_value -= 0xDC00
-										args.src.skip32_fast!(actual: 8, worst_case: 8)
+										args.src.skip32_fast!(actual: 12, worst_case: 12)
 										args.dst.write_fast_token!(
 											value_major: 0,
 											value_minor: 0x60_0000 | uni4_high_surrogate | uni4_value,
 											link: 0x3,
 											length: 12)
 										continue.string_loop_outer
-
-									} else {
-										// Roll back the 4 bytes, then fall
-										// through to "#invalid
-										// backslash-escape".
-										uni4_rollback = 4
-										while uni4_rollback > 0 {
-											uni4_rollback -= 1
-											if args.src.can_undo_byte() {
-												args.src.undo_byte!()
-											} else {
-												return "#internal error: inconsistent I/O"
-											}
-										}
 									}
 								}
+
+								if this.quirk_enabled_replace_invalid_unicode {
+									if args.src.available() < 6 {
+										return "#internal error: inconsistent I/O"
+									}
+									args.src.skip32_fast!(actual: 6, worst_case: 6)
+									args.dst.write_fast_token!(
+										value_major: 0,
+										value_minor: 0x60_FFFD,
+										link: 0x3,
+										length: 6)
+									continue.string_loop_outer
+								}
 								// -------- END   backslash-u.
+
+							} else if (c == 'U') and
+								this.quirk_enabled_allow_backslash_capital_u {
+								// -------- BEGIN backslash-capital-u.
+								if args.src.available() < 10 {
+									if args.src.is_closed() {
+										return "#bad backslash-escape"
+									}
+									yield? base."$short read"
+									string_length = 0
+									char = 0
+									continue.string_loop_outer
+								}
+								uni8_string = args.src.peek_u64le_at(offset: 2)
+								uni8_value = 0
+								uni8_ok = 0x80
+
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 0)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 28
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 8)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 24
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 16)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 20
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 24)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 16
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 32)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 12
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 40)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 8
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 48)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 4
+								c = lut_hexadecimal_digits[0xFF & (uni8_string >> 56)]
+								uni8_ok &= c
+								uni8_value |= ((c & 0x0F) as base.u32) << 0
+
+								if uni8_ok == 0 {
+									// It wasn't 8 hexadecimal digits. No-op
+									// (and fall through to "#bad
+									// backslash-escape").
+
+								} else if (uni8_value < 0xD800) or (
+									(0xDFFF < uni8_value) and (uni8_value <= 0x10_FFFF)) {
+									// Not a Unicode surrogate. We're good.
+									args.src.skip32_fast!(actual: 10, worst_case: 10)
+									args.dst.write_fast_token!(
+										value_major: 0,
+										value_minor: 0x60_0000 | (uni8_value & 0x1F_FFFF),
+										link: 0x3,
+										length: 10)
+									continue.string_loop_outer
+								} else if this.quirk_enabled_replace_invalid_unicode {
+									args.src.skip32_fast!(actual: 10, worst_case: 10)
+									args.dst.write_fast_token!(
+										value_major: 0,
+										value_minor: 0x60_FFFD,
+										link: 0x3,
+										length: 10)
+									continue.string_loop_outer
+								}
+								// -------- END   backslash-capital-u.
+
+							} else if (c == 'x') and
+								this.quirk_enabled_allow_backslash_x {
+								// -------- BEGIN backslash-x
+								if args.src.available() < 4 {
+									if args.src.is_closed() {
+										return "#bad backslash-escape"
+									}
+									yield? base."$short read"
+									string_length = 0
+									char = 0
+									continue.string_loop_outer
+								}
+
+								backslash_x_length = 0
+								while (backslash_x_length <= 0xFFFB) and (args.src.available() >= 4),
+									inv args.dst.available() > 0,
+								{
+									backslash_x_string = args.src.peek_u32le()
+									backslash_x_ok = 0x80
+
+									c = lut_hexadecimal_digits[0xFF & (backslash_x_string >> 16)]
+									backslash_x_ok &= c
+									c = lut_hexadecimal_digits[0xFF & (backslash_x_string >> 24)]
+									backslash_x_ok &= c
+
+									if (backslash_x_ok == 0) or
+										((backslash_x_string & 0xFFFF) <> 0x785C) {
+										// It wasn't "\\x34", for some
+										// hexadecimal digits "34".
+										break
+									}
+									args.src.skip32_fast!(actual: 4, worst_case: 4)
+									backslash_x_length += 4
+								} endwhile
+
+								if backslash_x_length == 0 {
+									return "#bad backslash-escape"
+								}
+								args.dst.write_fast_token!(
+									value_major: 0,
+									value_minor: 0x40_0080,
+									link: 0x3,
+									length: backslash_x_length)
+								continue.string_loop_outer
+								// -------- END   backslash-x
 							}
 
 							return "#bad backslash-escape"
@@ -418,8 +623,20 @@
 										link: 0x3,
 										length: string_length)
 									string_length = 0
+									if args.dst.available() <= 0 {
+										continue.string_loop_outer
+									}
 								}
 								if args.src.is_closed() {
+									if this.quirk_enabled_replace_invalid_unicode {
+										args.dst.write_fast_token!(
+											value_major: 0,
+											value_minor: 0x60_FFFD,
+											link: 0x3,
+											length: 1)
+										args.src.skip32_fast!(actual: 1, worst_case: 1)
+										continue.string_loop_outer
+									}
 									return "#bad UTF-8"
 								}
 								yield? base."$short read"
@@ -454,8 +671,20 @@
 										link: 0x3,
 										length: string_length)
 									string_length = 0
+									if args.dst.available() <= 0 {
+										continue.string_loop_outer
+									}
 								}
 								if args.src.is_closed() {
+									if this.quirk_enabled_replace_invalid_unicode {
+										args.dst.write_fast_token!(
+											value_major: 0,
+											value_minor: 0x60_FFFD,
+											link: 0x3,
+											length: 1)
+										args.src.skip32_fast!(actual: 1, worst_case: 1)
+										continue.string_loop_outer
+									}
 									return "#bad UTF-8"
 								}
 								yield? base."$short read"
@@ -495,8 +724,20 @@
 										link: 0x3,
 										length: string_length)
 									string_length = 0
+									if args.dst.available() <= 0 {
+										continue.string_loop_outer
+									}
 								}
 								if args.src.is_closed() {
+									if this.quirk_enabled_replace_invalid_unicode {
+										args.dst.write_fast_token!(
+											value_major: 0,
+											value_minor: 0x60_FFFD,
+											link: 0x3,
+											length: 1)
+										args.src.skip32_fast!(actual: 1, worst_case: 1)
+										continue.string_loop_outer
+									}
 									return "#bad UTF-8"
 								}
 								yield? base."$short read"
@@ -534,10 +775,22 @@
 								link: 0x3,
 								length: string_length)
 							string_length = 0
+							if args.dst.available() <= 0 {
+								continue.string_loop_outer
+							}
 						}
 						if char == 0x80 {
 							return "#bad C0 control code"
 						}
+						if this.quirk_enabled_replace_invalid_unicode {
+							args.dst.write_fast_token!(
+								value_major: 0,
+								value_minor: 0x60_FFFD,
+								link: 0x3,
+								length: 1)
+							args.src.skip32_fast!(actual: 1, worst_case: 1)
+							continue.string_loop_outer
+						}
 						return "#bad UTF-8"
 					} endwhile.string_loop_inner
 				} endwhile.string_loop_outer
@@ -562,13 +815,13 @@
 						link: 0x2,
 						length: 1)
 					break
-				}
+				} endwhile
 
 				// As above, expect must have contained EXPECT_STRING. If it
 				// didn't also contain EXPECT_NUMBER then we were parsing an
 				// object key and the next token should be ':'.
-				if 0 == (expect & 0x0010) {  // 0x0010 is EXPECT_NUMBER.
-					expect = 0x0008  // 0x0008 is EXPECT_COLON.
+				if 0 == (expect & 0x0010) {  // 0x0010 is (1 << CLASS_NUMBER).
+					expect = 0x1008  // 0x1008 is EXPECT_COLON.
 					continue.outer
 				}
 				break.goto_parsed_a_leaf_value
@@ -584,10 +837,18 @@
 					length: 1)
 				// What's valid after a comma depends on whether or not we're
 				// in an array or an object.
-				if 0 == (expect & 0x0100) {  // 0x0100 is EXPECT_CLOSE_SQUARE_BRACKET
-					expect = 0x0002  // 0x0002 is EXPECT_STRING.
+				if 0 == (expect & 0x0100) {  // 0x0100 is (1 << CLASS_CLOSE_SQUARE_BRACKET).
+					if this.quirk_enabled_allow_extra_comma {
+						expect = 0x1042  // 0x1042 is EXPECT_STRING | EXPECT_CLOSE_CURLY_BRACE.
+					} else {
+						expect = 0x1002  // 0x1002 is EXPECT_STRING.
+					}
 				} else {
-					expect = 0x0EB2  // 0x0EB2 is EXPECT_VALUE.
+					if this.quirk_enabled_allow_extra_comma {
+						expect = 0x1FB2  // 0x0FB2 is EXPECT_VALUE | EXPECT_CLOSE_SQUARE_BRACKET.
+					} else {
+						expect = 0x1EB2  // 0x0EB2 is EXPECT_VALUE.
+					}
 				}
 				continue.outer
 
@@ -599,7 +860,7 @@
 					value_minor: 0,
 					link: 0x0,
 					length: 1)
-				expect = 0x0EB2  // 0x0EB2 is EXPECT_VALUE.
+				expect = 0x1EB2  // 0x1EB2 is EXPECT_VALUE.
 				continue.outer
 
 			} else if class == 0x04 {  // 0x04 is CLASS_NUMBER.
@@ -630,9 +891,13 @@
 						} else {
 							return "#internal error: inconsistent I/O"
 						}
-					}
+					} endwhile
 
 					if number_status == 1 {
+						if this.quirk_enabled_allow_inf_nan_numbers {
+							this.decode_inf_nan?(dst: args.dst, src: args.src)
+							break
+						}
 						return "#bad input"
 					} else if number_status == 2 {
 						return "#unsupported number length"
@@ -642,9 +907,9 @@
 							post args.dst.available() > 0,
 						{
 							yield? base."$short write"
-						}
+						} endwhile
 					}
-				}
+				} endwhile
 				break.goto_parsed_a_leaf_value
 				// -------- END   parse numbers.
 
@@ -652,7 +917,7 @@
 				vminor = 0x20_4011
 				if depth == 0 {
 					// No-op.
-				} else if 0 <> (expect_after_value & 0x0040) {  // 0x0040 is EXPECT_CLOSE_CURLY_BRACE.
+				} else if 0 <> (expect_after_value & 0x0040) {  // 0x0040 is (1 << CLASS_CLOSE_CURLY_BRACE).
 					vminor = 0x20_4041
 				} else {
 					vminor = 0x20_4021
@@ -671,8 +936,8 @@
 					value_minor: vminor,
 					link: 0x0,
 					length: 1)
-				expect = 0x0042  // 0x0042 is (EXPECT_CLOSE_CURLY_BRACE | EXPECT_STRING).
-				expect_after_value = 0x0044  // 0x0044 is (EXPECT_CURLY_CLOSE_BRACE | EXPECT_COMMA).
+				expect = 0x1042  // 0x1042 is (EXPECT_CLOSE_CURLY_BRACE | EXPECT_STRING).
+				expect_after_value = 0x1044  // 0x1044 is (EXPECT_CURLY_CLOSE_BRACE | EXPECT_COMMA).
 				continue.outer
 
 			} else if class == 0x06 {  // 0x06 is CLASS_CLOSE_CURLY_BRACE.
@@ -694,18 +959,18 @@
 						value_minor: 0x20_2042,
 						link: 0x0,
 						length: 1)
-					// 0x0104 is (EXPECT_SQUARE_CLOSE_BRACKET | EXPECT_COMMA).
-					expect = 0x0104
-					expect_after_value = 0x0104
+					// 0x1104 is (EXPECT_SQUARE_CLOSE_BRACKET | EXPECT_COMMA).
+					expect = 0x1104
+					expect_after_value = 0x1104
 				} else {
 					args.dst.write_fast_token!(
 						value_major: 0,
 						value_minor: 0x20_4042,
 						link: 0x0,
 						length: 1)
-					// 0x0044 is (EXPECT_CURLY_CLOSE_BRACE | EXPECT_COMMA).
-					expect = 0x0044
-					expect_after_value = 0x0044
+					// 0x1044 is (EXPECT_CURLY_CLOSE_BRACE | EXPECT_COMMA).
+					expect = 0x1044
+					expect_after_value = 0x1044
 				}
 				continue.outer
 
@@ -713,7 +978,7 @@
 				vminor = 0x20_2011
 				if depth == 0 {
 					// No-op.
-				} else if 0 <> (expect_after_value & 0x0040) {  // 0x0040 is EXPECT_CLOSE_CURLY_BRACE.
+				} else if 0 <> (expect_after_value & 0x0040) {  // 0x0040 is (1 << CLASS_CLOSE_CURLY_BRACE).
 					vminor = 0x20_2041
 				} else {
 					vminor = 0x20_2021
@@ -732,8 +997,8 @@
 					value_minor: vminor,
 					link: 0x0,
 					length: 1)
-				expect = 0x0FB2  // 0x0FB2 is (EXPECT_CLOSE_SQUARE_BRACKET | EXPECT_VALUE).
-				expect_after_value = 0x0104  // 0x0104 is (EXPECT_CLOSE_SQUARE_BRACKET | EXPECT_COMMA).
+				expect = 0x1FB2  // 0x1FB2 is (EXPECT_CLOSE_SQUARE_BRACKET | EXPECT_VALUE).
+				expect_after_value = 0x1104  // 0x1104 is (EXPECT_CLOSE_SQUARE_BRACKET | EXPECT_COMMA).
 				continue.outer
 
 			} else if class == 0x08 {  // 0x08 is CLASS_CLOSE_SQUARE_BRACKET.
@@ -755,23 +1020,23 @@
 						value_minor: 0x20_2022,
 						link: 0x0,
 						length: 1)
-					// 0x0104 is (EXPECT_CLOSE_SQUARE_BRACKET | EXPECT_COMMA).
-					expect = 0x0104
-					expect_after_value = 0x0104
+					// 0x1104 is (EXPECT_CLOSE_SQUARE_BRACKET | EXPECT_COMMA).
+					expect = 0x1104
+					expect_after_value = 0x1104
 				} else {
 					args.dst.write_fast_token!(
 						value_major: 0,
 						value_minor: 0x20_4022,
 						link: 0x0,
 						length: 1)
-					// 0x0044 is (EXPECT_CLOSE_CURLY_BRACE | EXPECT_COMMA).
-					expect = 0x0044
-					expect_after_value = 0x0044
+					// 0x1044 is (EXPECT_CLOSE_CURLY_BRACE | EXPECT_COMMA).
+					expect = 0x1044
+					expect_after_value = 0x1044
 				}
 				continue.outer
 
 			} else if class == 0x09 {  // 0x09 is CLASS_FALSE.
-				match = args.src.match7(a: 0x6573_6C61_6605)  // 5 bytes "false".
+				match = args.src.match7(a: '\x05false'le)
 				if match == 0 {
 					args.dst.write_fast_token!(
 						value_major: 0,
@@ -789,7 +1054,7 @@
 				}
 
 			} else if class == 0x0A {  // 0x0A is CLASS_TRUE.
-				match = args.src.match7(a: 0x65_7572_7404)  // 4 bytes "true".
+				match = args.src.match7(a: '\x04true'le)
 				if match == 0 {
 					args.dst.write_fast_token!(
 						value_major: 0,
@@ -806,8 +1071,8 @@
 					continue.outer
 				}
 
-			} else if class == 0x0B {  // 0x0B is CLASS_NULL.
-				match = args.src.match7(a: 0x6C_6C75_6E04)  // 4 bytes "null".
+			} else if class == 0x0B {  // 0x0B is CLASS_NULL_NAN_INF.
+				match = args.src.match7(a: '\x04null'le)
 				if match == 0 {
 					args.dst.write_fast_token!(
 						value_major: 0,
@@ -823,6 +1088,17 @@
 					yield? base."$short read"
 					continue.outer
 				}
+
+				if this.quirk_enabled_allow_inf_nan_numbers {
+					this.decode_inf_nan?(dst: args.dst, src: args.src)
+					break.goto_parsed_a_leaf_value
+				}
+
+			} else if class == 0x0C {  // 0x0C is CLASS_COMMENT.
+				if this.quirk_enabled_allow_comment_block or this.quirk_enabled_allow_comment_line {
+					this.decode_comment?(dst: args.dst, src: args.src)
+					continue.outer
+				}
 			}
 
 			return "#bad input"
@@ -835,6 +1111,12 @@
 		}
 		expect = expect_after_value
 	} endwhile.outer
+
+	if this.quirk_enabled_allow_trailing_new_line {
+		this.decode_trailing_new_line?(dst: args.dst, src: args.src)
+	}
+
+	this.end_of_data = true
 }
 
 pri func decoder.decode_number!(src: base.io_reader) base.u32[..= 0x3FF] {
@@ -855,7 +1137,7 @@
 		c = args.src.peek_u8()
 
 		// Scan the optional minus sign.
-		if c <> 0x2D {  // 0x2D is '-'.
+		if c <> '-' {
 			assert args.src.available() > 0
 			assert n <= 1
 		} else {
@@ -877,7 +1159,7 @@
 		}
 
 		// Scan the opening digits.
-		if c == 0x30 {  // 0x30 is '0'.
+		if c == '0' {
 			n += 1
 			args.src.skip32_fast!(actual: 1, worst_case: 1)
 			assert n <= 99
@@ -899,7 +1181,7 @@
 		c = args.src.peek_u8()
 
 		// Scan the optional fraction.
-		if c <> 0x2E {  // 0x2E is '.'.
+		if c <> '.' {
 			assert args.src.available() > 0
 			assert n <= 99
 		} else {
@@ -930,7 +1212,7 @@
 		}
 
 		// Scan the optional 'E' or 'e'.
-		if (c <> 0x45) and (c <> 0x65) {  // 0x45 and 0x65 are 'E' and 'e'.
+		if (c <> 'E') and (c <> 'e') {
 			break.goto_done
 		}
 		if n >= 99 {
@@ -953,7 +1235,7 @@
 		c = args.src.peek_u8()
 
 		// Scan the optional '+' or '-'.
-		if (c <> 0x2B) and (c <> 0x2D) {  // 0x2B and 0x2D are '+' and '-'.
+		if (c <> '+') and (c <> '-') {
 			assert n <= 99
 		} else {
 			if n >= 99 {
@@ -1004,9 +1286,353 @@
 		}
 		n += 1
 		args.src.skip32_fast!(actual: 1, worst_case: 1)
-	}
+	} endwhile
 	if n == args.n {
 		n |= 0x100
 	}
 	return n
 }
+
+pri func decoder.decode_leading?(dst: base.token_writer, src: base.io_reader) {
+	var c : base.u8
+	var u : base.u32
+
+	this.allow_leading_ars = this.quirk_enabled_allow_leading_ascii_record_separator
+	this.allow_leading_ubom = this.quirk_enabled_allow_leading_unicode_byte_order_mark
+	while this.allow_leading_ars or this.allow_leading_ubom {
+		if args.dst.available() <= 0 {
+			yield? base."$short write"
+			continue
+		}
+		if args.src.available() <= 0 {
+			if args.src.is_closed() {
+				break
+			}
+			yield? base."$short read"
+			continue
+		}
+		c = args.src.peek_u8()
+		if (c == 0x1E) and this.allow_leading_ars {
+			this.allow_leading_ars = false
+			args.src.skip32_fast!(actual: 1, worst_case: 1)
+			args.dst.write_fast_token!(
+				value_major: 0, value_minor: 0, link: 0x0, length: 1)
+			continue
+		} else if (c == 0xEF) and this.allow_leading_ubom {
+			if args.src.available() < 3 {
+				if args.src.is_closed() {
+					break
+				}
+				yield? base."$short read"
+				continue
+			}
+			u = args.src.peek_u24le_as_u32()
+			if u == 0xBF_BBEF {
+				this.allow_leading_ubom = false
+				args.src.skip32_fast!(actual: 3, worst_case: 3)
+				args.dst.write_fast_token!(
+					value_major: 0, value_minor: 0, link: 0x0, length: 3)
+				continue
+			}
+		}
+		break
+	} endwhile
+}
+
+pri func decoder.decode_comment?(dst: base.token_writer, src: base.io_reader) {
+	var c         : base.u8
+	var c2        : base.u16
+	var link_prev : base.u32[..= 0x2]
+	var length    : base.u32[..= 0xFFFD]
+
+	while (args.dst.available() <= 0) or (args.src.available() <= 1),
+		post args.dst.available() > 0,
+		post args.src.available() > 1,
+	{
+		if args.dst.available() <= 0 {
+			yield? base."$short write"
+			continue
+		}
+		if args.src.is_closed() {
+			return "#bad input"
+		}
+		yield? base."$short read"
+	} endwhile
+	c2 = args.src.peek_u16le()
+
+	if (c2 == '/*'le) and this.quirk_enabled_allow_comment_block {
+		args.src.skip32_fast!(actual: 2, worst_case: 2)
+		length = 2
+
+		while.comment_block true {
+			if args.dst.available() <= 0 {
+				yield? base."$short write"
+				length = 0
+				continue.comment_block
+			}
+
+			while true,
+				pre args.dst.available() > 0,
+			{
+				if args.src.available() <= 1 {
+					if length > 0 {
+						args.dst.write_fast_token!(
+							value_major: 0,
+							value_minor: 0x2,
+							link: 0x1 | link_prev,
+							length: length)
+						link_prev = 0x2
+					}
+					if args.src.is_closed() {
+						return "#bad input"
+					}
+					yield? base."$short read"
+					length = 0
+					continue.comment_block
+				}
+
+				c2 = args.src.peek_u16le()
+				if c2 == '*/'le {
+					args.src.skip32_fast!(actual: 2, worst_case: 2)
+					args.dst.write_fast_token!(
+						value_major: 0,
+						value_minor: 0x2,
+						link: link_prev,
+						length: length + 2)
+					return ok
+				}
+
+				args.src.skip32_fast!(actual: 1, worst_case: 1)
+				if length >= 0xFFFD {
+					args.dst.write_fast_token!(
+						value_major: 0,
+						value_minor: 0x2,
+						link: 0x1 | link_prev,
+						length: length + 1)
+					length = 0
+					link_prev = 0x2
+					continue.comment_block
+				}
+				length += 1
+			} endwhile
+		} endwhile.comment_block
+
+	} else if (c2 == '//'le) and this.quirk_enabled_allow_comment_line {
+		args.src.skip32_fast!(actual: 2, worst_case: 2)
+		length = 2
+
+		while.comment_line true {
+			if args.dst.available() <= 0 {
+				yield? base."$short write"
+				length = 0
+				continue.comment_line
+			}
+
+			while true,
+				pre args.dst.available() > 0,
+			{
+				if args.src.available() <= 0 {
+					if length > 0 {
+						args.dst.write_fast_token!(
+							value_major: 0,
+							value_minor: 0x1,
+							link: 0x1 | link_prev,
+							length: length)
+						link_prev = 0x2
+					}
+					if args.src.is_closed() {
+						return "#bad input"
+					}
+					yield? base."$short read"
+					length = 0
+					continue.comment_line
+				}
+
+				c = args.src.peek_u8()
+				if c == '\n' {
+					args.src.skip32_fast!(actual: 1, worst_case: 1)
+					args.dst.write_fast_token!(
+						value_major: 0,
+						value_minor: 0x1,
+						link: link_prev,
+						length: length + 1)
+					return ok
+				}
+
+				args.src.skip32_fast!(actual: 1, worst_case: 1)
+				if length >= 0xFFFD {
+					args.dst.write_fast_token!(
+						value_major: 0,
+						value_minor: 0x1,
+						link: 0x1 | link_prev,
+						length: length + 1)
+					length = 0
+					link_prev = 0x2
+					continue.comment_line
+				}
+				length += 1
+			} endwhile
+		} endwhile.comment_line
+	}
+
+	return "#bad input"
+}
+
+pri func decoder.decode_inf_nan?(dst: base.token_writer, src: base.io_reader) {
+	var c4  : base.u32
+	var neg : base.u32[..= 1]
+
+	while true {
+		if args.dst.available() <= 0 {
+			yield? base."$short write"
+			continue
+		}
+		if args.src.available() <= 2 {
+			if args.src.is_closed() {
+				return "#bad input"
+			}
+			yield? base."$short read"
+			continue
+		}
+
+		// Bitwise or'ing with 0x20 converts upper case ASCII to lower case.
+
+		c4 = args.src.peek_u24le_as_u32()
+		if (c4 | 0x20_2020) == 'inf'le {
+			if args.src.available() > 7 {
+				if (args.src.peek_u64le() | 0x2020_2020_2020_2020) == 'infinity'le {
+					args.dst.write_fast_token!(
+						value_major: 0,
+						value_minor: 0xA0_0020,
+						link: 0x0,
+						length: 8)
+					args.src.skip32_fast!(actual: 8, worst_case: 8)
+					return ok
+				}
+			} else if not args.src.is_closed() {
+				yield? base."$short read"
+				continue
+			}
+			args.dst.write_fast_token!(
+				value_major: 0,
+				value_minor: 0xA0_0020,
+				link: 0x0,
+				length: 3)
+			args.src.skip32_fast!(actual: 3, worst_case: 3)
+			return ok
+
+		} else if (c4 | 0x20_2020) == 'nan'le {
+			args.dst.write_fast_token!(
+				value_major: 0,
+				value_minor: 0xA0_0080,
+				link: 0x0,
+				length: 3)
+			args.src.skip32_fast!(actual: 3, worst_case: 3)
+			return ok
+		} else if (c4 & 0xFF) == '+' {
+			neg = 0
+		} else if (c4 & 0xFF) == '-' {
+			neg = 1
+		} else {
+			return "#bad input"
+		}
+
+		if args.src.available() <= 3 {
+			if args.src.is_closed() {
+				return "#bad input"
+			}
+			yield? base."$short read"
+			continue
+		}
+
+		c4 = args.src.peek_u32le() >> 8
+		if (c4 | 0x20_2020) == 'inf'le {
+			if args.src.available() > 8 {
+				if (args.src.peek_u64le_at(offset: 1) | 0x2020_2020_2020_2020) == 'infinity'le {
+					args.dst.write_fast_token!(
+						value_major: 0,
+						value_minor: 0xA0_0000 | ((0x20 as base.u32) >> neg),
+						link: 0x0,
+						length: 9)
+					args.src.skip32_fast!(actual: 9, worst_case: 9)
+					return ok
+				}
+			} else if not args.src.is_closed() {
+				yield? base."$short read"
+				continue
+			}
+			args.dst.write_fast_token!(
+				value_major: 0,
+				value_minor: 0xA0_0000 | ((0x20 as base.u32) >> neg),
+				link: 0x0,
+				length: 4)
+			args.src.skip32_fast!(actual: 4, worst_case: 4)
+			return ok
+
+		} else if (c4 | 0x20_2020) == 'nan'le {
+			args.dst.write_fast_token!(
+				value_major: 0,
+				value_minor: 0xA0_0000 | ((0x80 as base.u32) >> neg),
+				link: 0x0,
+				length: 4)
+			args.src.skip32_fast!(actual: 4, worst_case: 4)
+			return ok
+		}
+
+		return "#bad input"
+	} endwhile
+}
+
+pri func decoder.decode_trailing_new_line?(dst: base.token_writer, src: base.io_reader) {
+	var c                 : base.u8
+	var whitespace_length : base.u32[..= 0xFFFE]
+
+	while.outer true {
+		if args.dst.available() <= 0 {
+			yield? base."$short write"
+			whitespace_length = 0
+			continue.outer
+		}
+
+		while.inner true,
+			pre args.dst.available() > 0,
+		{
+			if args.src.available() <= 0 {
+				if whitespace_length > 0 {
+					args.dst.write_fast_token!(
+						value_major: 0, value_minor: 0, link: 0x0, length: whitespace_length)
+					whitespace_length = 0
+				}
+				if args.src.is_closed() {
+					break.outer
+				}
+				yield? base."$short read"
+				whitespace_length = 0
+				continue.outer
+			}
+
+			c = args.src.peek_u8()
+			if lut_classes[c] <> 0x00 {  // 0x00 is CLASS_WHITESPACE.
+				if whitespace_length > 0 {
+					args.dst.write_fast_token!(
+						value_major: 0, value_minor: 0, link: 0x0, length: whitespace_length)
+					whitespace_length = 0
+				}
+				return "#bad input"
+			}
+
+			args.src.skip32_fast!(actual: 1, worst_case: 1)
+			if (whitespace_length >= 0xFFFE) or (c == '\n') {
+				args.dst.write_fast_token!(
+					value_major: 0, value_minor: 0, link: 0x0, length: whitespace_length + 1)
+				whitespace_length = 0
+				if c == '\n' {
+					break.outer
+				}
+				continue.outer
+			}
+			whitespace_length += 1
+		} endwhile.inner
+	} endwhile.outer
+
+}
diff --git a/std/json/decode_quirks.wuffs b/std/json/decode_quirks.wuffs
index c354505..e8eee13 100644
--- a/std/json/decode_quirks.wuffs
+++ b/std/json/decode_quirks.wuffs
@@ -28,6 +28,8 @@
 // When this quirk is enabled, e.g. "abc\U0001F4A9z" is accepted as a JSON
 // string, equivalent to "abc\uD83D\uDCA9z", containing the U+0001F4A9 PILE OF
 // POO Unicode code point. There are exactly 8 encoded bytes after each "\U".
+//
+// This quirk can combine with quirk_replace_invalid_unicode.
 pub const quirk_allow_backslash_capital_u base.u32 = 0x4909_9400 | 0x01
 
 // When this quirk is enabled, e.g. "abc\ez" is accepted as a JSON string,
@@ -51,7 +53,9 @@
 // decoding to 5 bytes: 0x61, 0x62, 0x63, 0xEF and 0x7A. There are exactly 2
 // encoded bytes after each "\x".
 //
-// Decoded strings are byte strings, no longer guaranteed to be valid UTF-8.
+// Decoded strings are byte strings, no longer guaranteed to be valid UTF-8 and
+// even if the overall byte string is valid UTF-8, tokens are also no longer
+// guaranteed to split on UTF-8 boundaries.
 //
 // "\x", "\x9", "\x9$" and "\X99" are all still rejected.
 pub const quirk_allow_backslash_x base.u32 = 0x4909_9400 | 0x06
@@ -64,18 +68,23 @@
 // anywhere whitespace would be, although see the quirk_allow_trailing_new_line
 // comment for additional interaction when combining multiple quirks.
 //
-// They produce WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_BLOCK tokens.
+// They produce WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_BLOCK tokens. The token
+// chain's source bytes includes the starting "/*" and the ending "*/".
 pub const quirk_allow_comment_block base.u32 = 0x4909_9400 | 0x08
 
 // When this quirk is enabled, "// C/C++ style line comments\n" are accepted
 // anywhere whitespace would be, although see the quirk_allow_trailing_new_line
 // comment for additional interaction when combining multiple quirks.
 //
-// A line comment may omit the trailing '\n' if there is no input afterwards
-// (i.e. the line comment ends with the end-of-file), but note the
-// quirk_allow_trailing_new_line interaction already mentioned.
+// A line comment may not omit the ending "\n", even if there is no input
+// afterwards (i.e. the prospective line comment ends with the end-of-file).
 //
-// They produce WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_LINE tokens.
+// They produce WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_LINE tokens. The token
+// chain's source bytes includes the starting "//" and the ending "\n".
+//
+// Even if the line comments are on consecutive lines, each line comment is a
+// separate token chain. There may be whitespace tokens between one line
+// comment's ending "\n" and the next one's starting "//".
 pub const quirk_allow_comment_line base.u32 = 0x4909_9400 | 0x09
 
 // When this quirk is enabled, there may be a comma after the final array
@@ -85,7 +94,7 @@
 //
 // For example, `[1,]`, `[1,2,3,]` and `{"k":"v",}` all become acceptable, but
 // `[,]`, `{,}` and `{"k",:"v"}` are still rejected.
-pub const quirk_allow_final_comma base.u32 = 0x4909_9400 | 0x0A
+pub const quirk_allow_extra_comma base.u32 = 0x4909_9400 | 0x0A
 
 // When this quirk is enabled, "inf", "Infinity", "NAN" and their
 // case-insensitive variants, optionally preceded immediately by "-" or "+",
@@ -149,10 +158,16 @@
 
 // When this quirk is enabled, invalid UTF-8 inside a JSON string is accepted.
 // Each byte of invalid UTF-8 is equivalent to "\uFFFD", the Unicode
-// Replacement Character. Invalid UTF-8 outside a JSON string remains an error.
+// Replacement Character. The UTF-8 encoding of U+FFFD is "\xEF\xBF\xBD".
+//
+// Invalid UTF-8 outside a JSON string remains an error.
 //
 // Similarly, for backslash-u escapes featuring incorrectly paired Unicode
 // surrogates, each backslash-u 6-byte unit is replaced. For example,
 // "abc\uDC00z" and "ijk\uD800\uDBFFz" are equivalent to "abc\uFFFDz" and
 // "ijk\uFFFD\uFFFDz".
-pub const quirk_replace_invalid_utf_8 base.u32 = 0x4909_9400 | 0x0F
+//
+// When combined with quirk_allow_backslash_capital_u, a "\U12345678" 10-byte
+// unit that is an invalid Unicode code point (i.e. in the range U+D800 ..=
+// U+DFFF or above U+10FFFF) is similarly replaced with U+FFFD.
+pub const quirk_replace_invalid_unicode base.u32 = 0x4909_9400 | 0x0F
diff --git a/std/lzw/decode_lzw.wuffs b/std/lzw/decode_lzw.wuffs
index 58317b4..4ec5d3d 100644
--- a/std/lzw/decode_lzw.wuffs
+++ b/std/lzw/decode_lzw.wuffs
@@ -100,7 +100,7 @@
 		this.lm1s[i] = 0
 		this.suffixes[i][0] = i as base.u8
 		i += 1
-	}
+	} endwhile
 
 	while true {
 		this.read_from!(src: args.src)
@@ -120,7 +120,7 @@
 		} else {
 			return "#internal error: inconsistent I/O"
 		}
-	}
+	} endwhile
 }
 
 pri func decoder.read_from!(src: base.io_reader) {
@@ -265,7 +265,7 @@
 				// in practice, but is necessary for the overflow checker.
 				o = (o ~mod- 8) & 8191
 				c = this.prefixes[c] as base.u32
-			}
+			} endwhile
 			first_byte = this.suffixes[c][0]
 
 			if code == save_code {
@@ -306,7 +306,7 @@
 			this.read_from_return_value = 1
 			break
 		}
-	}
+	} endwhile
 
 	// Rewind args.src, if we're not in "$short read" and we've read too many
 	// bits.
@@ -319,7 +319,7 @@
 				this.read_from_return_value = 4
 				break
 			}
-		}
+		} endwhile
 	}
 
 	this.save_code = save_code
@@ -347,7 +347,7 @@
 		}
 		this.output_ri = (this.output_ri ~mod+ ((n & 0xFFFF_FFFF) as base.u32)) & 8191
 		yield? base."$short write"
-	}
+	} endwhile
 }
 
 pub func decoder.flush!() slice base.u8 {
diff --git a/std/wbmp/decode_wbmp.wuffs b/std/wbmp/decode_wbmp.wuffs
index 683d0d8..cef9c53 100644
--- a/std/wbmp/decode_wbmp.wuffs
+++ b/std/wbmp/decode_wbmp.wuffs
@@ -46,7 +46,7 @@
 			return "#bad header"
 		}
 		i += 1
-	}
+	} endwhile
 
 	// Width, height.
 	i = 0
@@ -66,7 +66,7 @@
 				return "#bad header"
 			}
 			x32 = x64 as base.u32
-		}
+		} endwhile
 
 		if i == 0 {
 			this.width = x32
@@ -74,7 +74,7 @@
 			this.height = x32
 		}
 		i += 1
-	}
+	} endwhile
 
 	this.frame_config_io_position = args.src.position()
 
@@ -190,9 +190,9 @@
 				}
 
 				dst_x += 1
-			}
+			} endwhile
 			dst_y += 1
-		}
+		} endwhile
 	}
 
 	this.call_sequence = 3
diff --git a/std/zlib/decode_zlib.wuffs b/std/zlib/decode_zlib.wuffs
index 4e9d8d7..9db5ff1 100644
--- a/std/zlib/decode_zlib.wuffs
+++ b/std/zlib/decode_zlib.wuffs
@@ -117,7 +117,7 @@
 			break
 		}
 		yield? status
-	}
+	} endwhile
 	checksum_want = args.src.read_u32be?()
 	if (not this.ignore_checksum) and (checksum_got <> checksum_want) {
 		return "#bad checksum"
diff --git a/test/c/std/adler32.c b/test/c/std/adler32.c
index 767f948..69485ac 100644
--- a/test/c/std/adler32.c
+++ b/test/c/std/adler32.c
@@ -69,12 +69,12 @@
 
 // ---------------- Golden Tests
 
-golden_test adler32_midsummer_gt = {
-    .src_filename = "test/data/midsummer.txt",  //
+golden_test g_adler32_midsummer_gt = {
+    .src_filename = "test/data/midsummer.txt",
 };
 
-golden_test adler32_pi_gt = {
-    .src_filename = "test/data/pi.txt",  //
+golden_test g_adler32_pi_gt = {
+    .src_filename = "test/data/pi.txt",
 };
 
 // ---------------- Adler32 Tests
@@ -134,7 +134,7 @@
   int tc;
   for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
     wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-        .data = global_src_slice,
+        .data = g_src_slice_u8,
     });
     CHECK_STRING(read_file(&src, test_cases[tc].filename));
 
@@ -230,7 +230,7 @@
 
 // ---------------- Adler32 Benches
 
-uint32_t global_wuffs_adler32_unused_u32;
+uint32_t g_wuffs_adler32_unused_u32;
 
 const char*  //
 wuffs_bench_adler32(wuffs_base__io_buffer* dst,
@@ -246,7 +246,7 @@
   CHECK_STATUS("initialize", wuffs_adler32__hasher__initialize(
                                  &checksum, sizeof checksum, WUFFS_VERSION,
                                  wuffs_initialize_flags));
-  global_wuffs_adler32_unused_u32 = wuffs_adler32__hasher__update_u32(
+  g_wuffs_adler32_unused_u32 = wuffs_adler32__hasher__update_u32(
       &checksum, ((wuffs_base__slice_u8){
                      .ptr = src->data.ptr + src->meta.ri,
                      .len = len,
@@ -261,7 +261,7 @@
   return do_bench_io_buffers(
       wuffs_bench_adler32,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_src,
-      &adler32_midsummer_gt, UINT64_MAX, UINT64_MAX, 1500);
+      &g_adler32_midsummer_gt, UINT64_MAX, UINT64_MAX, 1500);
 }
 
 const char*  //
@@ -270,7 +270,7 @@
   return do_bench_io_buffers(
       wuffs_bench_adler32,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_src,
-      &adler32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
+      &g_adler32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
 }
 
   // ---------------- Mimic Benches
@@ -281,7 +281,7 @@
 bench_mimic_adler32_10k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_bench_adler32, 0, tcounter_src,
-                             &adler32_midsummer_gt, UINT64_MAX, UINT64_MAX,
+                             &g_adler32_midsummer_gt, UINT64_MAX, UINT64_MAX,
                              1500);
 }
 
@@ -289,7 +289,7 @@
 bench_mimic_adler32_100k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_bench_adler32, 0, tcounter_src,
-                             &adler32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
+                             &g_adler32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
 }
 
 #endif  // WUFFS_MIMIC
@@ -299,26 +299,24 @@
 // Note that the adler32 mimic tests and benches don't work with
 // WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB.
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_adler32_golden,     //
-    test_wuffs_adler32_interface,  //
-    test_wuffs_adler32_pi,         //
+    test_wuffs_adler32_golden,
+    test_wuffs_adler32_interface,
+    test_wuffs_adler32_pi,
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_adler32_10k,   //
-    bench_wuffs_adler32_100k,  //
+    bench_wuffs_adler32_10k,
+    bench_wuffs_adler32_100k,
 
 #ifdef WUFFS_MIMIC
 
-    bench_mimic_adler32_10k,   //
-    bench_mimic_adler32_100k,  //
+    bench_mimic_adler32_10k,
+    bench_mimic_adler32_100k,
 
 #endif  // WUFFS_MIMIC
 
@@ -327,6 +325,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/adler32";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/adler32";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/bmp.c b/test/c/std/bmp.c
index 6f90c25..bb6a6e9 100644
--- a/test/c/std/bmp.c
+++ b/test/c/std/bmp.c
@@ -69,7 +69,7 @@
 
 // ---------------- BMP Tests
 
-const char* //
+const char*  //
 test_wuffs_bmp_decode_interface() {
   CHECK_FOCUS(__func__);
   wuffs_bmp__decoder dec;
@@ -82,7 +82,7 @@
       "test/data/hippopotamus.bmp", 0, SIZE_MAX, 36, 28, 0xFFF5F5F5);
 }
 
-const char* //
+const char*  //
 test_wuffs_bmp_decode_frame_config() {
   CHECK_FOCUS(__func__);
   wuffs_bmp__decoder dec;
@@ -93,7 +93,7 @@
 
   wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/hat.bmp"));
   CHECK_STATUS("decode_frame_config #0",
@@ -134,11 +134,10 @@
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_bmp_decode_frame_config,  //
-    test_wuffs_bmp_decode_interface,     //
+    test_wuffs_bmp_decode_frame_config,
+    test_wuffs_bmp_decode_interface,
 
 #ifdef WUFFS_MIMIC
 
@@ -149,8 +148,7 @@
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
 // No BMP benches.
 
@@ -163,8 +161,8 @@
     NULL,
 };
 
-int //
+int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/bmp";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/bmp";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/crc32.c b/test/c/std/crc32.c
index 2a4be10..1d60def 100644
--- a/test/c/std/crc32.c
+++ b/test/c/std/crc32.c
@@ -69,12 +69,12 @@
 
 // ---------------- Golden Tests
 
-golden_test crc32_midsummer_gt = {
-    .src_filename = "test/data/midsummer.txt",  //
+golden_test g_crc32_midsummer_gt = {
+    .src_filename = "test/data/midsummer.txt",
 };
 
-golden_test crc32_pi_gt = {
-    .src_filename = "test/data/pi.txt",  //
+golden_test g_crc32_pi_gt = {
+    .src_filename = "test/data/pi.txt",
 };
 
 // ---------------- CRC32 Tests
@@ -134,7 +134,7 @@
   int tc;
   for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
     wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-        .data = global_src_slice,
+        .data = g_src_slice_u8,
     });
     CHECK_STRING(read_file(&src, test_cases[tc].filename));
 
@@ -267,7 +267,7 @@
 
 // ---------------- CRC32 Benches
 
-uint32_t global_wuffs_crc32_unused_u32;
+uint32_t g_wuffs_crc32_unused_u32;
 
 const char*  //
 wuffs_bench_crc32_ieee(wuffs_base__io_buffer* dst,
@@ -283,7 +283,7 @@
   CHECK_STATUS("initialize", wuffs_crc32__ieee_hasher__initialize(
                                  &checksum, sizeof checksum, WUFFS_VERSION,
                                  wuffs_initialize_flags));
-  global_wuffs_crc32_unused_u32 = wuffs_crc32__ieee_hasher__update_u32(
+  g_wuffs_crc32_unused_u32 = wuffs_crc32__ieee_hasher__update_u32(
       &checksum, ((wuffs_base__slice_u8){
                      .ptr = src->data.ptr + src->meta.ri,
                      .len = len,
@@ -298,7 +298,7 @@
   return do_bench_io_buffers(
       wuffs_bench_crc32_ieee,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_src,
-      &crc32_midsummer_gt, UINT64_MAX, UINT64_MAX, 1500);
+      &g_crc32_midsummer_gt, UINT64_MAX, UINT64_MAX, 1500);
 }
 
 const char*  //
@@ -307,7 +307,7 @@
   return do_bench_io_buffers(
       wuffs_bench_crc32_ieee,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_src,
-      &crc32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
+      &g_crc32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
 }
 
   // ---------------- Mimic Benches
@@ -318,14 +318,15 @@
 bench_mimic_crc32_ieee_10k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_bench_crc32_ieee, 0, tcounter_src,
-                             &crc32_midsummer_gt, UINT64_MAX, UINT64_MAX, 1500);
+                             &g_crc32_midsummer_gt, UINT64_MAX, UINT64_MAX,
+                             1500);
 }
 
 const char*  //
 bench_mimic_crc32_ieee_100k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_bench_crc32_ieee, 0, tcounter_src,
-                             &crc32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
+                             &g_crc32_pi_gt, UINT64_MAX, UINT64_MAX, 150);
 }
 
 #endif  // WUFFS_MIMIC
@@ -335,32 +336,30 @@
 // Note that the crc32 mimic tests and benches don't work with
 // WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB.
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_crc32_ieee_golden,     //
-    test_wuffs_crc32_ieee_interface,  //
-    test_wuffs_crc32_ieee_pi,         //
+    test_wuffs_crc32_ieee_golden,
+    test_wuffs_crc32_ieee_interface,
+    test_wuffs_crc32_ieee_pi,
 
 #ifdef WUFFS_MIMIC
 
-    test_mimic_crc32_ieee_pi,  //
+    test_mimic_crc32_ieee_pi,
 
 #endif  // WUFFS_MIMIC
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_crc32_ieee_10k,   //
-    bench_wuffs_crc32_ieee_100k,  //
+    bench_wuffs_crc32_ieee_10k,
+    bench_wuffs_crc32_ieee_100k,
 
 #ifdef WUFFS_MIMIC
 
-    bench_mimic_crc32_ieee_10k,   //
-    bench_mimic_crc32_ieee_100k,  //
+    bench_mimic_crc32_ieee_10k,
+    bench_mimic_crc32_ieee_100k,
 
 #endif  // WUFFS_MIMIC
 
@@ -369,6 +368,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/crc32";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/crc32";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/deflate.c b/test/c/std/deflate.c
index 2aaa430..e9e9530 100644
--- a/test/c/std/deflate.c
+++ b/test/c/std/deflate.c
@@ -72,17 +72,15 @@
 // The src_offset0 and src_offset1 magic numbers come from:
 //
 // go run script/extract-flate-offsets.go test/data/*.gz
-//
-// The empty comments forces clang-format to place one element per line.
 
-golden_test deflate_256_bytes_gt = {
-    .want_filename = "test/data/artificial/256.bytes",    //
-    .src_filename = "test/data/artificial/256.bytes.gz",  //
-    .src_offset0 = 20,                                    //
-    .src_offset1 = 281,                                   //
+golden_test g_deflate_256_bytes_gt = {
+    .want_filename = "test/data/artificial/256.bytes",
+    .src_filename = "test/data/artificial/256.bytes.gz",
+    .src_offset0 = 20,
+    .src_offset1 = 281,
 };
 
-golden_test deflate_deflate_backref_crosses_blocks_gt = {
+golden_test g_deflate_deflate_backref_crosses_blocks_gt = {
     .want_filename =
         "test/data/artificial/"
         "deflate-backref-crosses-blocks.deflate.decompressed",
@@ -91,7 +89,7 @@
         "deflate-backref-crosses-blocks.deflate",
 };
 
-golden_test deflate_deflate_degenerate_huffman_unused_gt = {
+golden_test g_deflate_deflate_degenerate_huffman_unused_gt = {
     .want_filename =
         "test/data/artificial/"
         "deflate-degenerate-huffman-unused.deflate.decompressed",
@@ -100,7 +98,7 @@
         "deflate-degenerate-huffman-unused.deflate",
 };
 
-golden_test deflate_deflate_distance_32768_gt = {
+golden_test g_deflate_deflate_distance_32768_gt = {
     .want_filename =
         "test/data/artificial/"
         "deflate-distance-32768.deflate.decompressed",
@@ -109,7 +107,7 @@
         "deflate-distance-32768.deflate",
 };
 
-golden_test deflate_deflate_distance_code_31_gt = {
+golden_test g_deflate_deflate_distance_code_31_gt = {
     .want_filename =
         "test/data/artificial/"
         "qdeflate-distance-code-31.deflate.decompressed",
@@ -118,7 +116,7 @@
         "deflate-distance-code-31.deflate",
 };
 
-golden_test deflate_deflate_huffman_primlen_9_gt = {
+golden_test g_deflate_deflate_huffman_primlen_9_gt = {
     .want_filename =
         "test/data/artificial/"
         "deflate-huffman-primlen-9.deflate.decompressed",
@@ -127,30 +125,30 @@
         "deflate-huffman-primlen-9.deflate",
 };
 
-golden_test deflate_midsummer_gt = {
-    .want_filename = "test/data/midsummer.txt",    //
-    .src_filename = "test/data/midsummer.txt.gz",  //
-    .src_offset0 = 24,                             //
-    .src_offset1 = 5166,                           //
+golden_test g_deflate_midsummer_gt = {
+    .want_filename = "test/data/midsummer.txt",
+    .src_filename = "test/data/midsummer.txt.gz",
+    .src_offset0 = 24,
+    .src_offset1 = 5166,
 };
 
-golden_test deflate_pi_gt = {
-    .want_filename = "test/data/pi.txt",    //
-    .src_filename = "test/data/pi.txt.gz",  //
-    .src_offset0 = 17,                      //
-    .src_offset1 = 48335,                   //
+golden_test g_deflate_pi_gt = {
+    .want_filename = "test/data/pi.txt",
+    .src_filename = "test/data/pi.txt.gz",
+    .src_offset0 = 17,
+    .src_offset1 = 48335,
 };
 
-golden_test deflate_romeo_gt = {
-    .want_filename = "test/data/romeo.txt",    //
-    .src_filename = "test/data/romeo.txt.gz",  //
-    .src_offset0 = 20,                         //
-    .src_offset1 = 550,                        //
+golden_test g_deflate_romeo_gt = {
+    .want_filename = "test/data/romeo.txt",
+    .src_filename = "test/data/romeo.txt.gz",
+    .src_offset0 = 20,
+    .src_offset1 = 550,
 };
 
-golden_test deflate_romeo_fixed_gt = {
-    .want_filename = "test/data/romeo.txt",                    //
-    .src_filename = "test/data/romeo.txt.fixed-huff.deflate",  //
+golden_test g_deflate_romeo_fixed_gt = {
+    .want_filename = "test/data/romeo.txt",
+    .src_filename = "test/data/romeo.txt.fixed-huff.deflate",
 };
 
 // ---------------- Deflate Tests
@@ -184,7 +182,7 @@
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
 
     wuffs_base__status status = wuffs_deflate__decoder__transform_io(
-        &dec, &limited_dst, &limited_src, global_work_slice);
+        &dec, &limited_dst, &limited_src, g_work_slice_u8);
 
     dst->meta.wi += limited_dst.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -202,7 +200,7 @@
 const char*  //
 test_wuffs_deflate_decode_256_bytes() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_256_bytes_gt,
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_256_bytes_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -210,7 +208,7 @@
 test_wuffs_deflate_decode_deflate_backref_crosses_blocks() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(wuffs_deflate_decode,
-                            &deflate_deflate_backref_crosses_blocks_gt,
+                            &g_deflate_deflate_backref_crosses_blocks_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -218,7 +216,7 @@
 test_wuffs_deflate_decode_deflate_degenerate_huffman_unused() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(wuffs_deflate_decode,
-                            &deflate_deflate_degenerate_huffman_unused_gt,
+                            &g_deflate_deflate_degenerate_huffman_unused_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -226,7 +224,7 @@
 test_wuffs_deflate_decode_deflate_distance_32768() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(wuffs_deflate_decode,
-                            &deflate_deflate_distance_32768_gt, UINT64_MAX,
+                            &g_deflate_deflate_distance_32768_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
@@ -234,7 +232,7 @@
 test_wuffs_deflate_decode_deflate_distance_code_31() {
   CHECK_FOCUS(__func__);
   const char* have = do_test_io_buffers(wuffs_deflate_decode,
-                                        &deflate_deflate_distance_code_31_gt,
+                                        &g_deflate_deflate_distance_code_31_gt,
                                         UINT64_MAX, UINT64_MAX);
   if (have != wuffs_deflate__error__bad_huffman_code) {
     RETURN_FAIL("have \"%s\", want \"%s\"", have,
@@ -249,19 +247,19 @@
 
   // First, treat this like any other compare-to-golden test.
   CHECK_STRING(do_test_io_buffers(wuffs_deflate_decode,
-                                  &deflate_deflate_huffman_primlen_9_gt,
+                                  &g_deflate_deflate_huffman_primlen_9_gt,
                                   UINT64_MAX, UINT64_MAX));
 
   // Second, check that the decoder's huffman table sizes match those predicted
   // by the script/print-deflate-huff-table-size.go program.
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
 
-  golden_test* gt = &deflate_deflate_huffman_primlen_9_gt;
+  golden_test* gt = &g_deflate_deflate_huffman_primlen_9_gt;
   CHECK_STRING(read_file(&src, gt->src_filename));
 
   wuffs_deflate__decoder dec;
@@ -269,7 +267,7 @@
                                  &dec, sizeof dec, WUFFS_VERSION,
                                  WUFFS_INITIALIZE__DEFAULT_OPTIONS));
   CHECK_STATUS("transform_io", wuffs_deflate__decoder__transform_io(
-                                   &dec, &have, &src, global_work_slice));
+                                   &dec, &have, &src, g_work_slice_u8));
 
   int i;
   for (i = 0; i < 2; i++) {
@@ -293,48 +291,48 @@
 const char*  //
 test_wuffs_deflate_decode_midsummer() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_midsummer_gt,
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_midsummer_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
 const char*  //
 test_wuffs_deflate_decode_pi_just_one_read() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_pi_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_wuffs_deflate_decode_pi_many_big_reads() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_pi_gt, UINT64_MAX,
                             4096);
 }
 
 const char*  //
 test_wuffs_deflate_decode_pi_many_medium_reads() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_pi_gt, UINT64_MAX,
                             599);
 }
 
 const char*  //
 test_wuffs_deflate_decode_pi_many_small_writes_reads() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_pi_gt, 59, 61);
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_pi_gt, 59, 61);
 }
 
 const char*  //
 test_wuffs_deflate_decode_romeo() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_romeo_gt, UINT64_MAX,
-                            UINT64_MAX);
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_romeo_gt,
+                            UINT64_MAX, UINT64_MAX);
 }
 
 const char*  //
 test_wuffs_deflate_decode_romeo_fixed() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_deflate_decode, &deflate_romeo_fixed_gt,
+  return do_test_io_buffers(wuffs_deflate_decode, &g_deflate_romeo_fixed_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -343,16 +341,16 @@
   CHECK_FOCUS(__func__);
 
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
 
-  golden_test* gt = &deflate_256_bytes_gt;
+  golden_test* gt = &g_deflate_256_bytes_gt;
   CHECK_STRING(read_file(&src, gt->src_filename));
   CHECK_STRING(read_file(&want, gt->want_filename));
 
@@ -374,13 +372,13 @@
     src.meta.ri = gt->src_offset0;
     src.meta.wi = split;
     wuffs_base__status z0 = wuffs_deflate__decoder__transform_io(
-        &dec, &have, &src, global_work_slice);
+        &dec, &have, &src, g_work_slice_u8);
 
     src.meta.closed = true;
     src.meta.ri = split;
     src.meta.wi = gt->src_offset1;
     wuffs_base__status z1 = wuffs_deflate__decoder__transform_io(
-        &dec, &have, &src, global_work_slice);
+        &dec, &have, &src, g_work_slice_u8);
 
     if (z0.repr != wuffs_base__suspension__short_read) {
       RETURN_FAIL("i=%d: z0: have \"%s\", want \"%s\"", i, z0.repr,
@@ -417,7 +415,7 @@
   dec->private_impl.f_history_index = starting_history_index;
 
   wuffs_base__status have_z = wuffs_deflate__decoder__transform_io(
-      dec, &limited_have, src, global_work_slice);
+      dec, &limited_have, src, g_work_slice_u8);
   have->meta.wi += limited_have.meta.wi;
   if (have_z.repr != want_z) {
     RETURN_FAIL("i=%d: starting_history_index=0x%04" PRIX32
@@ -456,16 +454,16 @@
   CHECK_FOCUS(__func__);
 
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
 
-  golden_test* gt = &deflate_pi_gt;
+  golden_test* gt = &g_deflate_pi_gt;
   CHECK_STRING(read_file(&src, gt->src_filename));
   CHECK_STRING(read_file(&want, gt->want_filename));
 
@@ -503,7 +501,7 @@
     }
     wuffs_base__io_buffer history_want = ((wuffs_base__io_buffer){
         .data = ((wuffs_base__slice_u8){
-            .ptr = global_want_array + want.meta.wi - (full_history_size - i),
+            .ptr = g_want_array_u8 + want.meta.wi - (full_history_size - i),
             .len = full_history_size,
         }),
     });
@@ -519,13 +517,13 @@
   CHECK_FOCUS(__func__);
 
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
 
-  golden_test* gt = &deflate_pi_gt;
+  golden_test* gt = &g_deflate_pi_gt;
   CHECK_STRING(read_file(&src, gt->src_filename));
 
   uint32_t starting_history_indexes[] = {
@@ -717,7 +715,7 @@
 const char*  //
 test_mimic_deflate_decode_256_bytes() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_deflate_decode, &deflate_256_bytes_gt,
+  return do_test_io_buffers(mimic_deflate_decode, &g_deflate_256_bytes_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -725,7 +723,7 @@
 test_mimic_deflate_decode_deflate_backref_crosses_blocks() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(mimic_deflate_decode,
-                            &deflate_deflate_backref_crosses_blocks_gt,
+                            &g_deflate_deflate_backref_crosses_blocks_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -733,7 +731,7 @@
 test_mimic_deflate_decode_deflate_degenerate_huffman_unused() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(mimic_deflate_decode,
-                            &deflate_deflate_degenerate_huffman_unused_gt,
+                            &g_deflate_deflate_degenerate_huffman_unused_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -741,7 +739,7 @@
 test_mimic_deflate_decode_deflate_distance_32768() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(mimic_deflate_decode,
-                            &deflate_deflate_distance_32768_gt, UINT64_MAX,
+                            &g_deflate_deflate_distance_32768_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
@@ -749,7 +747,7 @@
 test_mimic_deflate_decode_deflate_distance_code_31() {
   CHECK_FOCUS(__func__);
   const char* have = do_test_io_buffers(mimic_deflate_decode,
-                                        &deflate_deflate_distance_code_31_gt,
+                                        &g_deflate_deflate_distance_code_31_gt,
                                         UINT64_MAX, UINT64_MAX);
   const char* want = "inflate failed (data error)";
   if ((have != want) &&
@@ -763,42 +761,42 @@
 test_mimic_deflate_decode_deflate_huffman_primlen_9() {
   CHECK_FOCUS(__func__);
   return do_test_io_buffers(mimic_deflate_decode,
-                            &deflate_deflate_huffman_primlen_9_gt, UINT64_MAX,
+                            &g_deflate_deflate_huffman_primlen_9_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_mimic_deflate_decode_midsummer() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_deflate_decode, &deflate_midsummer_gt,
+  return do_test_io_buffers(mimic_deflate_decode, &g_deflate_midsummer_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
 const char*  //
 test_mimic_deflate_decode_pi_just_one_read() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_deflate_decode, &deflate_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(mimic_deflate_decode, &g_deflate_pi_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_mimic_deflate_decode_pi_many_big_reads() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_deflate_decode, &deflate_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(mimic_deflate_decode, &g_deflate_pi_gt, UINT64_MAX,
                             4096);
 }
 
 const char*  //
 test_mimic_deflate_decode_romeo() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_deflate_decode, &deflate_romeo_gt, UINT64_MAX,
-                            UINT64_MAX);
+  return do_test_io_buffers(mimic_deflate_decode, &g_deflate_romeo_gt,
+                            UINT64_MAX, UINT64_MAX);
 }
 
 const char*  //
 test_mimic_deflate_decode_romeo_fixed() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_deflate_decode, &deflate_romeo_fixed_gt,
+  return do_test_io_buffers(mimic_deflate_decode, &g_deflate_romeo_fixed_gt,
                             UINT64_MAX, UINT64_MAX);
 }
 
@@ -811,7 +809,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(wuffs_deflate_decode,
                              WUFFS_INITIALIZE__DEFAULT_OPTIONS, tcounter_dst,
-                             &deflate_romeo_gt, UINT64_MAX, UINT64_MAX, 2000);
+                             &g_deflate_romeo_gt, UINT64_MAX, UINT64_MAX, 2000);
 }
 
 const char*  //
@@ -820,7 +818,7 @@
   return do_bench_io_buffers(
       wuffs_deflate_decode,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
-      &deflate_romeo_gt, UINT64_MAX, UINT64_MAX, 2000);
+      &g_deflate_romeo_gt, UINT64_MAX, UINT64_MAX, 2000);
 }
 
 const char*  //
@@ -828,7 +826,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(
       wuffs_deflate_decode, WUFFS_INITIALIZE__DEFAULT_OPTIONS, tcounter_dst,
-      &deflate_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+      &g_deflate_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
@@ -837,7 +835,7 @@
   return do_bench_io_buffers(
       wuffs_deflate_decode,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
-      &deflate_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+      &g_deflate_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
@@ -846,7 +844,7 @@
   return do_bench_io_buffers(
       wuffs_deflate_decode,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
-      &deflate_pi_gt, UINT64_MAX, UINT64_MAX, 30);
+      &g_deflate_pi_gt, UINT64_MAX, UINT64_MAX, 30);
 }
 
 const char*  //
@@ -855,7 +853,7 @@
   return do_bench_io_buffers(
       wuffs_deflate_decode,
       WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, tcounter_dst,
-      &deflate_pi_gt, UINT64_MAX, 4096, 30);
+      &g_deflate_pi_gt, UINT64_MAX, 4096, 30);
 }
 
   // ---------------- Mimic Benches
@@ -866,14 +864,14 @@
 bench_mimic_deflate_decode_1k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_deflate_decode, 0, tcounter_dst,
-                             &deflate_romeo_gt, UINT64_MAX, UINT64_MAX, 2000);
+                             &g_deflate_romeo_gt, UINT64_MAX, UINT64_MAX, 2000);
 }
 
 const char*  //
 bench_mimic_deflate_decode_10k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_deflate_decode, 0, tcounter_dst,
-                             &deflate_midsummer_gt, UINT64_MAX, UINT64_MAX,
+                             &g_deflate_midsummer_gt, UINT64_MAX, UINT64_MAX,
                              300);
 }
 
@@ -881,77 +879,75 @@
 bench_mimic_deflate_decode_100k_just_one_read() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_deflate_decode, 0, tcounter_dst,
-                             &deflate_pi_gt, UINT64_MAX, UINT64_MAX, 30);
+                             &g_deflate_pi_gt, UINT64_MAX, UINT64_MAX, 30);
 }
 
 const char*  //
 bench_mimic_deflate_decode_100k_many_big_reads() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_deflate_decode, 0, tcounter_dst,
-                             &deflate_pi_gt, UINT64_MAX, 4096, 30);
+                             &g_deflate_pi_gt, UINT64_MAX, 4096, 30);
 }
 
 #endif  // WUFFS_MIMIC
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_deflate_decode_256_bytes,                          //
-    test_wuffs_deflate_decode_deflate_backref_crosses_blocks,     //
-    test_wuffs_deflate_decode_deflate_degenerate_huffman_unused,  //
-    test_wuffs_deflate_decode_deflate_distance_32768,             //
-    test_wuffs_deflate_decode_deflate_distance_code_31,           //
-    test_wuffs_deflate_decode_deflate_huffman_primlen_9,          //
-    test_wuffs_deflate_decode_interface,                          //
-    test_wuffs_deflate_decode_midsummer,                          //
-    test_wuffs_deflate_decode_pi_just_one_read,                   //
-    test_wuffs_deflate_decode_pi_many_big_reads,                  //
-    test_wuffs_deflate_decode_pi_many_medium_reads,               //
-    test_wuffs_deflate_decode_pi_many_small_writes_reads,         //
-    test_wuffs_deflate_decode_romeo,                              //
-    test_wuffs_deflate_decode_romeo_fixed,                        //
-    test_wuffs_deflate_decode_split_src,                          //
-    test_wuffs_deflate_history_full,                              //
-    test_wuffs_deflate_history_partial,                           //
-    test_wuffs_deflate_table_redirect,                            //
+    test_wuffs_deflate_decode_256_bytes,
+    test_wuffs_deflate_decode_deflate_backref_crosses_blocks,
+    test_wuffs_deflate_decode_deflate_degenerate_huffman_unused,
+    test_wuffs_deflate_decode_deflate_distance_32768,
+    test_wuffs_deflate_decode_deflate_distance_code_31,
+    test_wuffs_deflate_decode_deflate_huffman_primlen_9,
+    test_wuffs_deflate_decode_interface,
+    test_wuffs_deflate_decode_midsummer,
+    test_wuffs_deflate_decode_pi_just_one_read,
+    test_wuffs_deflate_decode_pi_many_big_reads,
+    test_wuffs_deflate_decode_pi_many_medium_reads,
+    test_wuffs_deflate_decode_pi_many_small_writes_reads,
+    test_wuffs_deflate_decode_romeo,
+    test_wuffs_deflate_decode_romeo_fixed,
+    test_wuffs_deflate_decode_split_src,
+    test_wuffs_deflate_history_full,
+    test_wuffs_deflate_history_partial,
+    test_wuffs_deflate_table_redirect,
 
 #ifdef WUFFS_MIMIC
 
-    test_mimic_deflate_decode_256_bytes,                          //
-    test_mimic_deflate_decode_deflate_backref_crosses_blocks,     //
-    test_mimic_deflate_decode_deflate_degenerate_huffman_unused,  //
-    test_mimic_deflate_decode_deflate_distance_32768,             //
-    test_mimic_deflate_decode_deflate_distance_code_31,           //
-    test_mimic_deflate_decode_deflate_huffman_primlen_9,          //
-    test_mimic_deflate_decode_midsummer,                          //
-    test_mimic_deflate_decode_pi_just_one_read,                   //
-    test_mimic_deflate_decode_pi_many_big_reads,                  //
-    test_mimic_deflate_decode_romeo,                              //
-    test_mimic_deflate_decode_romeo_fixed,                        //
+    test_mimic_deflate_decode_256_bytes,
+    test_mimic_deflate_decode_deflate_backref_crosses_blocks,
+    test_mimic_deflate_decode_deflate_degenerate_huffman_unused,
+    test_mimic_deflate_decode_deflate_distance_32768,
+    test_mimic_deflate_decode_deflate_distance_code_31,
+    test_mimic_deflate_decode_deflate_huffman_primlen_9,
+    test_mimic_deflate_decode_midsummer,
+    test_mimic_deflate_decode_pi_just_one_read,
+    test_mimic_deflate_decode_pi_many_big_reads,
+    test_mimic_deflate_decode_romeo,
+    test_mimic_deflate_decode_romeo_fixed,
 
 #endif  // WUFFS_MIMIC
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_deflate_decode_1k_full_init,         //
-    bench_wuffs_deflate_decode_1k_part_init,         //
-    bench_wuffs_deflate_decode_10k_full_init,        //
-    bench_wuffs_deflate_decode_10k_part_init,        //
-    bench_wuffs_deflate_decode_100k_just_one_read,   //
-    bench_wuffs_deflate_decode_100k_many_big_reads,  //
+    bench_wuffs_deflate_decode_1k_full_init,
+    bench_wuffs_deflate_decode_1k_part_init,
+    bench_wuffs_deflate_decode_10k_full_init,
+    bench_wuffs_deflate_decode_10k_part_init,
+    bench_wuffs_deflate_decode_100k_just_one_read,
+    bench_wuffs_deflate_decode_100k_many_big_reads,
 
 #ifdef WUFFS_MIMIC
 
-    bench_mimic_deflate_decode_1k,                   //
-    bench_mimic_deflate_decode_10k,                  //
-    bench_mimic_deflate_decode_100k_just_one_read,   //
-    bench_mimic_deflate_decode_100k_many_big_reads,  //
+    bench_mimic_deflate_decode_1k,
+    bench_mimic_deflate_decode_10k,
+    bench_mimic_deflate_decode_100k_just_one_read,
+    bench_mimic_deflate_decode_100k_many_big_reads,
 
 #endif  // WUFFS_MIMIC
 
@@ -960,6 +956,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/deflate";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/deflate";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index 7b365e1..65911c4 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -217,7 +217,7 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
 
   while (true) {
     wuffs_base__status status =
@@ -230,7 +230,7 @@
     CHECK_STATUS("decode_frame",
                  wuffs_gif__decoder__decode_frame(&dec, &pb, src,
                                                   WUFFS_BASE__PIXEL_BLEND__SRC,
-                                                  global_work_slice, NULL));
+                                                  g_work_slice_u8, NULL));
 
     CHECK_STRING(copy_to_io_buffer_from_pixel_buffer(
         dst, &pb, wuffs_base__frame_config__bounds(&fc)));
@@ -245,10 +245,10 @@
                          uint64_t rlimit,
                          wuffs_base__pixel_format dst_pixfmt) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, filename));
 
@@ -290,7 +290,7 @@
                                   120);
 
     CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                       &pb, &ic.pixcfg, global_pixel_slice));
+                                       &pb, &ic.pixcfg, g_pixel_slice_u8));
 
     uint32_t have = wuffs_gif__decoder__num_animation_loops(&dec);
     if (have != 1) {
@@ -330,8 +330,8 @@
     size_t old_ri = src.meta.ri;
 
     wuffs_base__status status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &limited_src, WUFFS_BASE__PIXEL_BLEND__SRC,
-        global_work_slice, NULL);
+        &dec, &pb, &limited_src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8,
+        NULL);
     src.meta.ri += limited_src.meta.ri;
 
     if (wuffs_base__status__is_ok(&status)) {
@@ -380,14 +380,14 @@
   }
 
   wuffs_base__io_buffer ind_want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
   CHECK_STRING(read_file(&ind_want, indexes_filename));
   if (dst_pixfmt.repr == WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) {
     CHECK_STRING(check_io_buffers_equal("indexes ", &have, &ind_want));
   } else {
     wuffs_base__io_buffer expanded_want = ((wuffs_base__io_buffer){
-        .data = global_work_slice,
+        .data = g_work_slice_u8,
     });
     if (ind_want.meta.wi > (expanded_want.data.len / 4)) {
       RETURN_FAIL("indexes are too long to expand into the work buffer");
@@ -455,7 +455,7 @@
       RETURN_FAIL("decode_frame returned \"ok\" but src was exhausted");
     }
     wuffs_base__status status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, global_work_slice, NULL);
+        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
     if (status.repr != wuffs_base__note__end_of_data) {
       RETURN_FAIL("decode_frame: have \"%s\", want \"%s\"", status.repr,
                   wuffs_base__note__end_of_data);
@@ -489,10 +489,10 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
 
   wuffs_base__status status = wuffs_gif__decoder__decode_frame(
-      &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, global_work_slice, NULL);
+      &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
   if (status.repr != want_status) {
     RETURN_FAIL("decode_frame: have \"%s\", want \"%s\"", status.repr,
                 want_status);
@@ -512,7 +512,7 @@
 test_wuffs_gif_call_interleaved() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/bricks-dither.gif"));
 
@@ -553,7 +553,7 @@
 test_wuffs_gif_call_sequence() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/bricks-dither.gif"));
 
@@ -582,7 +582,7 @@
     uint32_t want_num_frames,
     wuffs_base__rect_ie_u32* want_frame_config_bounds) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, filename));
 
@@ -605,7 +605,7 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
 
   uint32_t i;
   for (i = 0; i < want_num_frames; i++) {
@@ -630,7 +630,7 @@
     }
 
     status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, global_work_slice, NULL);
+        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
     if (!wuffs_base__status__is_ok(&status)) {
       RETURN_FAIL("decode_frame #%" PRIu32 ": \"%s\"", i, status.repr);
     }
@@ -647,7 +647,7 @@
   // decode_frame.
   for (i = 0; i < 3; i++) {
     wuffs_base__status status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, global_work_slice, NULL);
+        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
     if (status.repr != wuffs_base__note__end_of_data) {
       RETURN_FAIL("decode_frame: have \"%s\", want \"%s\"", status.repr,
                   wuffs_base__note__end_of_data);
@@ -700,7 +700,7 @@
 test_wuffs_gif_decode_delay_num_frames_decoded() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/animated-red-blue.gif"));
   if (src.meta.wi < 1) {
@@ -750,7 +750,7 @@
 test_wuffs_gif_decode_empty_palette() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/artificial/gif-empty-palette.gif"));
   int q;
@@ -774,16 +774,15 @@
 
     wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
     status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg,
-                                                      global_pixel_slice);
+                                                      g_pixel_slice_u8);
     if (!wuffs_base__status__is_ok(&status)) {
       RETURN_FAIL("q=%d: set_from_slice: \"%s\"", q, status.repr);
     }
 
     int i;
     for (i = 0; i < 2; i++) {
-      status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
-                                                WUFFS_BASE__PIXEL_BLEND__SRC,
-                                                global_work_slice, NULL);
+      status = wuffs_gif__decoder__decode_frame(
+          &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
       if ((q == 1) && (i == 1)) {
         if (status.repr != wuffs_gif__error__bad_palette) {
           RETURN_FAIL("q=%d: i=%d: decode_frame: have \"%s\", want \"%s\"", q,
@@ -818,7 +817,7 @@
 test_wuffs_gif_decode_background_color() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-background-color.gif"));
@@ -857,7 +856,7 @@
 test_wuffs_gif_decode_first_frame_is_opaque() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-frame-out-of-bounds.gif"));
@@ -895,7 +894,7 @@
 test_wuffs_gif_decode_frame_out_of_bounds() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-frame-out-of-bounds.gif"));
@@ -941,7 +940,7 @@
         wuffs_base__pixel_config__pixel_subsampling(&ic.pixcfg).repr, 5, 5);
     wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
     status = wuffs_base__pixel_buffer__set_from_slice(&pb, &five_by_five,
-                                                      global_pixel_slice);
+                                                      g_pixel_slice_u8);
     if (!wuffs_base__status__is_ok(&status)) {
       RETURN_FAIL("q=%d: set_from_slice: \"%s\"", q, status.repr);
     }
@@ -1010,7 +1009,7 @@
 
         status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                                   WUFFS_BASE__PIXEL_BLEND__SRC,
-                                                  global_work_slice, NULL);
+                                                  g_work_slice_u8, NULL);
         if (!wuffs_base__status__is_ok(&status)) {
           RETURN_FAIL("q=%d: decode_frame #%" PRIu32 ": \"%s\"", q, i,
                       status.repr);
@@ -1065,7 +1064,7 @@
 test_wuffs_gif_decode_zero_width_frame() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-zero-width-frame.gif"));
@@ -1105,13 +1104,13 @@
 
     wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
     status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg,
-                                                      global_pixel_slice);
+                                                      g_pixel_slice_u8);
     if (!wuffs_base__status__is_ok(&status)) {
       RETURN_FAIL("q=%d: set_from_slice: \"%s\"", q, status.repr);
     }
 
     wuffs_base__status have = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, global_work_slice, NULL);
+        &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
     if (have.repr != want) {
       RETURN_FAIL("q=%d: decode_frame: have \"%s\", want \"%s\"", q, have.repr,
                   want);
@@ -1213,7 +1212,7 @@
 test_wuffs_gif_decode_input_is_a_png() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/bricks-dither.png"));
 
@@ -1237,7 +1236,7 @@
 test_wuffs_gif_decode_interlaced_truncated() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/hippopotamus.interlaced.truncated.gif"));
@@ -1269,7 +1268,7 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
   uint8_t* pixel_ptr = wuffs_base__pixel_buffer__plane(&pb, 0).ptr;
   memset(pixel_ptr, 0xEE, num_pixel_indexes);
 
@@ -1279,7 +1278,7 @@
   }
 
   wuffs_base__status status = wuffs_gif__decoder__decode_frame(
-      &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, global_work_slice, NULL);
+      &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
   if (status.repr != wuffs_base__suspension__short_read) {
     RETURN_FAIL("decode_frame: have \"%s\", want \"%s\"", status.repr,
                 wuffs_base__suspension__short_read);
@@ -1300,9 +1299,10 @@
   return NULL;
 }
 
-const char* do_test_wuffs_gif_decode_metadata(bool full) {
+const char*  //
+do_test_wuffs_gif_decode_metadata(bool full) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, full ? "test/data/artificial/gif-metadata-full.gif"
@@ -1472,7 +1472,7 @@
 test_wuffs_gif_decode_missing_two_src_bytes() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/pjw-thumbnail.gif"));
 
@@ -1490,7 +1490,7 @@
 test_wuffs_gif_decode_multiple_graphic_controls() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(
       &src, "test/data/artificial/gif-multiple-graphic-controls.gif"));
@@ -1517,7 +1517,7 @@
 test_wuffs_gif_decode_multiple_loop_counts() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-multiple-loop-counts.gif"));
@@ -1579,7 +1579,7 @@
 test_wuffs_gif_decode_pixel_data_none() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/artificial/gif-pixel-data-none.gif"));
 
@@ -1591,7 +1591,7 @@
 test_wuffs_gif_decode_pixel_data_not_enough() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-pixel-data-not-enough.gif"));
@@ -1604,7 +1604,7 @@
 test_wuffs_gif_decode_pixel_data_too_much_sans_quirk() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-pixel-data-too-much.gif"));
@@ -1617,7 +1617,7 @@
 test_wuffs_gif_decode_pixel_data_too_much_with_quirk() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-pixel-data-too-much.gif"));
@@ -1630,7 +1630,7 @@
 test_wuffs_gif_frame_dirty_rect() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/hippopotamus.interlaced.gif"));
 
@@ -1646,7 +1646,7 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
 
   // The hippopotamus.interlaced.gif image is 28 pixels high. As we decode rows
   // of pixels, interlacing means that we decode rows 0, 8, 16, 24, 4, 12, 20,
@@ -1661,8 +1661,8 @@
     wuffs_base__io_buffer limited_src = make_limited_reader(src, 1);
 
     wuffs_base__status status = wuffs_gif__decoder__decode_frame(
-        &dec, &pb, &limited_src, WUFFS_BASE__PIXEL_BLEND__SRC,
-        global_work_slice, NULL);
+        &dec, &pb, &limited_src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8,
+        NULL);
     src.meta.ri += limited_src.meta.ri;
 
     wuffs_base__rect_ie_u32 r = wuffs_gif__decoder__frame_dirty_rect(&dec);
@@ -1685,9 +1685,10 @@
   return NULL;
 }
 
-const char* do_test_wuffs_gif_num_decoded(bool frame_config) {
+const char*  //
+do_test_wuffs_gif_num_decoded(bool frame_config) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/animated-red-blue.gif"));
 
@@ -1704,7 +1705,7 @@
                  wuffs_gif__decoder__decode_image_config(&dec, &ic, &src));
 
     CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                       &pb, &ic.pixcfg, global_pixel_slice));
+                                       &pb, &ic.pixcfg, g_pixel_slice_u8));
   }
 
   const char* method = frame_config ? "decode_frame_config" : "decode_frame";
@@ -1728,9 +1729,8 @@
     if (frame_config) {
       status = wuffs_gif__decoder__decode_frame_config(&dec, NULL, &src);
     } else {
-      status = wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
-                                                WUFFS_BASE__PIXEL_BLEND__SRC,
-                                                global_work_slice, NULL);
+      status = wuffs_gif__decoder__decode_frame(
+          &dec, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC, g_work_slice_u8, NULL);
     }
 
     if (wuffs_base__status__is_ok(&status)) {
@@ -1761,9 +1761,10 @@
   return do_test_wuffs_gif_num_decoded(false);
 }
 
-const char* do_test_wuffs_gif_io_position(bool chunked) {
+const char*  //
+do_test_wuffs_gif_io_position(bool chunked) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/animated-red-blue.gif"));
 
@@ -1929,7 +1930,7 @@
 test_wuffs_gif_small_frame_interlaced() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(
       read_file(&src, "test/data/artificial/gif-small-frame-interlaced.gif"));
@@ -1954,7 +1955,7 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
 
   wuffs_base__frame_config fc;
   CHECK_STATUS("decode_frame_config",
@@ -1969,7 +1970,7 @@
   CHECK_STATUS("decode_frame",
                wuffs_gif__decoder__decode_frame(&dec, &pb, &src,
                                                 WUFFS_BASE__PIXEL_BLEND__SRC,
-                                                global_work_slice, NULL));
+                                                g_work_slice_u8, NULL));
 
   wuffs_base__rect_ie_u32 dr = wuffs_gif__decoder__frame_dirty_rect(&dec);
   if (dr.max_excl_y != 3) {
@@ -1999,15 +2000,16 @@
 
 #ifdef WUFFS_MIMIC
 
-const char* do_test_mimic_gif_decode(const char* filename) {
+const char*  //
+do_test_mimic_gif_decode(const char* filename) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, filename));
 
   src.meta.ri = 0;
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   CHECK_STRING(
       wuffs_gif_decode(&have, 0,
@@ -2017,7 +2019,7 @@
 
   src.meta.ri = 0;
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
   CHECK_STRING(
       mimic_gif_decode(&want, 0,
@@ -2125,17 +2127,17 @@
                     wuffs_base__pixel_format pixfmt,
                     uint64_t iters_unscaled) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, filename));
 
   bench_start();
   uint64_t n_bytes = 0;
   uint64_t i;
-  uint64_t iters = iters_unscaled * flags.iterscale;
+  uint64_t iters = iters_unscaled * g_flags.iterscale;
   for (i = 0; i < iters; i++) {
     have.meta.wi = 0;
     src.meta.ri = 0;
@@ -2354,106 +2356,104 @@
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
     // These basic tests are really testing the Wuffs compiler. They aren't
     // specific to the std/gif code, but putting them here is as good as any
     // other place.
-    test_basic_bad_receiver,            //
-    test_basic_bad_sizeof_receiver,     //
-    test_basic_bad_wuffs_version,       //
-    test_basic_initialize_not_called,   //
-    test_basic_status_is_error,         //
-    test_basic_sub_struct_initializer,  //
+    test_basic_bad_receiver,
+    test_basic_bad_sizeof_receiver,
+    test_basic_bad_wuffs_version,
+    test_basic_initialize_not_called,
+    test_basic_status_is_error,
+    test_basic_sub_struct_initializer,
 
-    test_wuffs_gif_call_interleaved,                         //
-    test_wuffs_gif_call_sequence,                            //
-    test_wuffs_gif_decode_animated_big,                      //
-    test_wuffs_gif_decode_animated_medium,                   //
-    test_wuffs_gif_decode_animated_small,                    //
-    test_wuffs_gif_decode_background_color,                  //
-    test_wuffs_gif_decode_delay_num_frames_decoded,          //
-    test_wuffs_gif_decode_empty_palette,                     //
-    test_wuffs_gif_decode_first_frame_is_opaque,             //
-    test_wuffs_gif_decode_frame_out_of_bounds,               //
-    test_wuffs_gif_decode_input_is_a_gif_just_one_read,      //
-    test_wuffs_gif_decode_input_is_a_gif_many_big_reads,     //
-    test_wuffs_gif_decode_input_is_a_gif_many_medium_reads,  //
-    test_wuffs_gif_decode_input_is_a_gif_many_small_reads,   //
-    test_wuffs_gif_decode_input_is_a_png,                    //
-    test_wuffs_gif_decode_interface_image_config_decoder,    //
-    test_wuffs_gif_decode_interface_image_decoder,           //
-    test_wuffs_gif_decode_interlaced_truncated,              //
-    test_wuffs_gif_decode_metadata_empty,                    //
-    test_wuffs_gif_decode_metadata_full,                     //
-    test_wuffs_gif_decode_missing_two_src_bytes,             //
-    test_wuffs_gif_decode_multiple_graphic_controls,         //
-    test_wuffs_gif_decode_multiple_loop_counts,              //
-    test_wuffs_gif_decode_pixel_data_none,                   //
-    test_wuffs_gif_decode_pixel_data_not_enough,             //
-    test_wuffs_gif_decode_pixel_data_too_much_sans_quirk,    //
-    test_wuffs_gif_decode_pixel_data_too_much_with_quirk,    //
-    test_wuffs_gif_decode_pixfmt_bgr,                        //
-    test_wuffs_gif_decode_pixfmt_bgr_565,                    //
-    test_wuffs_gif_decode_pixfmt_bgra_nonpremul,             //
-    test_wuffs_gif_decode_pixfmt_rgb,                        //
-    test_wuffs_gif_decode_pixfmt_rgba_nonpremul,             //
-    test_wuffs_gif_decode_zero_width_frame,                  //
-    test_wuffs_gif_frame_dirty_rect,                         //
-    test_wuffs_gif_num_decoded_frame_configs,                //
-    test_wuffs_gif_num_decoded_frames,                       //
-    test_wuffs_gif_io_position_one_chunk,                    //
-    test_wuffs_gif_io_position_two_chunks,                   //
-    test_wuffs_gif_small_frame_interlaced,                   //
-    test_wuffs_gif_sizeof,                                   //
+    test_wuffs_gif_call_interleaved,
+    test_wuffs_gif_call_sequence,
+    test_wuffs_gif_decode_animated_big,
+    test_wuffs_gif_decode_animated_medium,
+    test_wuffs_gif_decode_animated_small,
+    test_wuffs_gif_decode_background_color,
+    test_wuffs_gif_decode_delay_num_frames_decoded,
+    test_wuffs_gif_decode_empty_palette,
+    test_wuffs_gif_decode_first_frame_is_opaque,
+    test_wuffs_gif_decode_frame_out_of_bounds,
+    test_wuffs_gif_decode_input_is_a_gif_just_one_read,
+    test_wuffs_gif_decode_input_is_a_gif_many_big_reads,
+    test_wuffs_gif_decode_input_is_a_gif_many_medium_reads,
+    test_wuffs_gif_decode_input_is_a_gif_many_small_reads,
+    test_wuffs_gif_decode_input_is_a_png,
+    test_wuffs_gif_decode_interface_image_config_decoder,
+    test_wuffs_gif_decode_interface_image_decoder,
+    test_wuffs_gif_decode_interlaced_truncated,
+    test_wuffs_gif_decode_metadata_empty,
+    test_wuffs_gif_decode_metadata_full,
+    test_wuffs_gif_decode_missing_two_src_bytes,
+    test_wuffs_gif_decode_multiple_graphic_controls,
+    test_wuffs_gif_decode_multiple_loop_counts,
+    test_wuffs_gif_decode_pixel_data_none,
+    test_wuffs_gif_decode_pixel_data_not_enough,
+    test_wuffs_gif_decode_pixel_data_too_much_sans_quirk,
+    test_wuffs_gif_decode_pixel_data_too_much_with_quirk,
+    test_wuffs_gif_decode_pixfmt_bgr,
+    test_wuffs_gif_decode_pixfmt_bgr_565,
+    test_wuffs_gif_decode_pixfmt_bgra_nonpremul,
+    test_wuffs_gif_decode_pixfmt_rgb,
+    test_wuffs_gif_decode_pixfmt_rgba_nonpremul,
+    test_wuffs_gif_decode_zero_width_frame,
+    test_wuffs_gif_frame_dirty_rect,
+    test_wuffs_gif_num_decoded_frame_configs,
+    test_wuffs_gif_num_decoded_frames,
+    test_wuffs_gif_io_position_one_chunk,
+    test_wuffs_gif_io_position_two_chunks,
+    test_wuffs_gif_small_frame_interlaced,
+    test_wuffs_gif_sizeof,
 
 #ifdef WUFFS_MIMIC
 
-    test_mimic_gif_decode_animated_small,           //
-    test_mimic_gif_decode_bricks_dither,            //
-    test_mimic_gif_decode_bricks_gray,              //
-    test_mimic_gif_decode_bricks_nodither,          //
-    test_mimic_gif_decode_gifplayer_muybridge,      //
-    test_mimic_gif_decode_harvesters,               //
-    test_mimic_gif_decode_hat,                      //
-    test_mimic_gif_decode_hibiscus_primitive,       //
-    test_mimic_gif_decode_hibiscus_regular,         //
-    test_mimic_gif_decode_hippopotamus_interlaced,  //
-    test_mimic_gif_decode_hippopotamus_regular,     //
-    test_mimic_gif_decode_muybridge,                //
-    test_mimic_gif_decode_pjw_thumbnail,            //
+    test_mimic_gif_decode_animated_small,
+    test_mimic_gif_decode_bricks_dither,
+    test_mimic_gif_decode_bricks_gray,
+    test_mimic_gif_decode_bricks_nodither,
+    test_mimic_gif_decode_gifplayer_muybridge,
+    test_mimic_gif_decode_harvesters,
+    test_mimic_gif_decode_hat,
+    test_mimic_gif_decode_hibiscus_primitive,
+    test_mimic_gif_decode_hibiscus_regular,
+    test_mimic_gif_decode_hippopotamus_interlaced,
+    test_mimic_gif_decode_hippopotamus_regular,
+    test_mimic_gif_decode_muybridge,
+    test_mimic_gif_decode_pjw_thumbnail,
 
 #endif  // WUFFS_MIMIC
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_gif_decode_1k_bw,               //
-    bench_wuffs_gif_decode_1k_color_full_init,  //
-    bench_wuffs_gif_decode_1k_color_part_init,  //
-    bench_wuffs_gif_decode_10k_bgra,            //
-    bench_wuffs_gif_decode_10k_indexed,         //
-    bench_wuffs_gif_decode_20k,                 //
-    bench_wuffs_gif_decode_100k_artificial,     //
-    bench_wuffs_gif_decode_100k_realistic,      //
-    bench_wuffs_gif_decode_1000k_full_init,     //
-    bench_wuffs_gif_decode_1000k_part_init,     //
-    bench_wuffs_gif_decode_anim_screencap,      //
+    bench_wuffs_gif_decode_1k_bw,
+    bench_wuffs_gif_decode_1k_color_full_init,
+    bench_wuffs_gif_decode_1k_color_part_init,
+    bench_wuffs_gif_decode_10k_bgra,
+    bench_wuffs_gif_decode_10k_indexed,
+    bench_wuffs_gif_decode_20k,
+    bench_wuffs_gif_decode_100k_artificial,
+    bench_wuffs_gif_decode_100k_realistic,
+    bench_wuffs_gif_decode_1000k_full_init,
+    bench_wuffs_gif_decode_1000k_part_init,
+    bench_wuffs_gif_decode_anim_screencap,
 
 #ifdef WUFFS_MIMIC
 
-    bench_mimic_gif_decode_1k_bw,            //
-    bench_mimic_gif_decode_1k_color,         //
-    bench_mimic_gif_decode_10k_indexed,      //
-    bench_mimic_gif_decode_20k,              //
-    bench_mimic_gif_decode_100k_artificial,  //
-    bench_mimic_gif_decode_100k_realistic,   //
-    bench_mimic_gif_decode_1000k,            //
-    bench_mimic_gif_decode_anim_screencap,   //
+    bench_mimic_gif_decode_1k_bw,
+    bench_mimic_gif_decode_1k_color,
+    bench_mimic_gif_decode_10k_indexed,
+    bench_mimic_gif_decode_20k,
+    bench_mimic_gif_decode_100k_artificial,
+    bench_mimic_gif_decode_100k_realistic,
+    bench_mimic_gif_decode_1000k,
+    bench_mimic_gif_decode_anim_screencap,
 
 #endif  // WUFFS_MIMIC
 
@@ -2462,6 +2462,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/gif";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/gif";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/gzip.c b/test/c/std/gzip.c
index 5be741f..9a7318d 100644
--- a/test/c/std/gzip.c
+++ b/test/c/std/gzip.c
@@ -71,14 +71,14 @@
 
 // ---------------- Golden Tests
 
-golden_test gzip_midsummer_gt = {
-    .want_filename = "test/data/midsummer.txt",    //
-    .src_filename = "test/data/midsummer.txt.gz",  //
+golden_test g_gzip_midsummer_gt = {
+    .want_filename = "test/data/midsummer.txt",
+    .src_filename = "test/data/midsummer.txt.gz",
 };
 
-golden_test gzip_pi_gt = {
-    .want_filename = "test/data/pi.txt",    //
-    .src_filename = "test/data/pi.txt.gz",  //
+golden_test g_gzip_pi_gt = {
+    .want_filename = "test/data/pi.txt",
+    .src_filename = "test/data/pi.txt.gz",
 };
 
 // ---------------- Gzip Tests
@@ -112,7 +112,7 @@
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
 
     wuffs_base__status status = wuffs_gzip__decoder__transform_io(
-        &dec, &limited_dst, &limited_src, global_work_slice);
+        &dec, &limited_dst, &limited_src, g_work_slice_u8);
 
     dst->meta.wi += limited_dst.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -130,13 +130,13 @@
 const char*  //
 do_test_wuffs_gzip_checksum(bool ignore_checksum, uint32_t bad_checksum) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
-  CHECK_STRING(read_file(&src, gzip_midsummer_gt.src_filename));
+  CHECK_STRING(read_file(&src, g_gzip_midsummer_gt.src_filename));
 
   // Flip a bit in the gzip checksum, which is in the last 8 bytes of the file.
   if (src.meta.wi < 8) {
@@ -180,7 +180,7 @@
 
       wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
       wuffs_base__status have_z = wuffs_gzip__decoder__transform_io(
-          &dec, &have, &limited_src, global_work_slice);
+          &dec, &have, &limited_src, g_work_slice_u8);
       src.meta.ri += limited_src.meta.ri;
       if (have_z.repr != want_z) {
         RETURN_FAIL("end_limit=%d: have \"%s\", want \"%s\"", end_limit,
@@ -218,14 +218,14 @@
 const char*  //
 test_wuffs_gzip_decode_midsummer() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_gzip_decode, &gzip_midsummer_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_gzip_decode, &g_gzip_midsummer_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_wuffs_gzip_decode_pi() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_gzip_decode, &gzip_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_gzip_decode, &g_gzip_pi_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
@@ -236,14 +236,14 @@
 const char*  //
 test_mimic_gzip_decode_midsummer() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_gzip_decode, &gzip_midsummer_gt, UINT64_MAX,
+  return do_test_io_buffers(mimic_gzip_decode, &g_gzip_midsummer_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_mimic_gzip_decode_pi() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_gzip_decode, &gzip_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(mimic_gzip_decode, &g_gzip_pi_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
@@ -256,7 +256,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(
       wuffs_gzip_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_dst, &gzip_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+      tcounter_dst, &g_gzip_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
@@ -264,7 +264,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(
       wuffs_gzip_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_dst, &gzip_pi_gt, UINT64_MAX, UINT64_MAX, 30);
+      tcounter_dst, &g_gzip_pi_gt, UINT64_MAX, UINT64_MAX, 30);
 }
 
   // ---------------- Mimic Benches
@@ -275,13 +275,13 @@
 bench_mimic_gzip_decode_10k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_gzip_decode, 0, tcounter_dst,
-                             &gzip_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+                             &g_gzip_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
 bench_mimic_gzip_decode_100k() {
   CHECK_FOCUS(__func__);
-  return do_bench_io_buffers(mimic_gzip_decode, 0, tcounter_dst, &gzip_pi_gt,
+  return do_bench_io_buffers(mimic_gzip_decode, 0, tcounter_dst, &g_gzip_pi_gt,
                              UINT64_MAX, UINT64_MAX, 30);
 }
 
@@ -292,37 +292,35 @@
 // Note that the gzip mimic tests and benches don't work with
 // WUFFS_MIMICLIB_USE_MINIZ_INSTEAD_OF_ZLIB.
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_gzip_checksum_ignore,       //
-    test_wuffs_gzip_checksum_verify_bad0,  //
-    test_wuffs_gzip_checksum_verify_bad7,  //
-    test_wuffs_gzip_checksum_verify_good,  //
-    test_wuffs_gzip_decode_interface,      //
-    test_wuffs_gzip_decode_midsummer,      //
-    test_wuffs_gzip_decode_pi,             //
+    test_wuffs_gzip_checksum_ignore,
+    test_wuffs_gzip_checksum_verify_bad0,
+    test_wuffs_gzip_checksum_verify_bad7,
+    test_wuffs_gzip_checksum_verify_good,
+    test_wuffs_gzip_decode_interface,
+    test_wuffs_gzip_decode_midsummer,
+    test_wuffs_gzip_decode_pi,
 
 #ifdef WUFFS_MIMIC
 
-    test_mimic_gzip_decode_midsummer,  //
-    test_mimic_gzip_decode_pi,         //
+    test_mimic_gzip_decode_midsummer,
+    test_mimic_gzip_decode_pi,
 
 #endif  // WUFFS_MIMIC
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_gzip_decode_10k,   //
-    bench_wuffs_gzip_decode_100k,  //
+    bench_wuffs_gzip_decode_10k,
+    bench_wuffs_gzip_decode_100k,
 
 #ifdef WUFFS_MIMIC
 
-    bench_mimic_gzip_decode_10k,   //
-    bench_mimic_gzip_decode_100k,  //
+    bench_mimic_gzip_decode_10k,
+    bench_mimic_gzip_decode_100k,
 
 #endif  // WUFFS_MIMIC
 
@@ -331,6 +329,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/gzip";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/gzip";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/json.c b/test/c/std/json.c
index ae52f56..5352664 100644
--- a/test/c/std/json.c
+++ b/test/c/std/json.c
@@ -67,6 +67,77 @@
 // No mimic library.
 #endif
 
+// ---------------- Numeric Types Tests
+
+const char*  //
+test_wuffs_core_count_leading_zeroes_u64() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    uint64_t num;
+    uint32_t want;
+  } test_cases[] = {
+      {.num = 0x0000000000000000, .want = 64},
+      {.num = 0x0000000000000001, .want = 63},
+      {.num = 0x0000000000008001, .want = 48},
+      {.num = 0x0000000040302010, .want = 33},
+      {.num = 0x0123456789ABCDEF, .want = 7},
+      {.num = 0x8000000000000001, .want = 0},
+      {.num = 0xFFFFFFFFFFFFFFFF, .want = 0},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    uint32_t have = wuffs_base__count_leading_zeroes_u64(test_cases[tc].num);
+    if (have != test_cases[tc].want) {
+      RETURN_FAIL("0x%" PRIX64 ": have %" PRIu32 ", want %" PRIu32,
+                  test_cases[tc].num, have, test_cases[tc].want);
+    }
+  }
+
+  return NULL;
+}
+
+const char*  //
+test_wuffs_core_multiply_u64() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    uint64_t x;
+    uint64_t y;
+    uint64_t want_hi;
+    uint64_t want_lo;
+  } test_cases[] = {
+      {.x = 0x0000000000005678,
+       .y = 0x0000000000001001,
+       .want_hi = 0x0000000000000000,
+       .want_lo = 0x000000000567D678},
+      {.x = 0x00000000DEADBEEF,
+       .y = 0x000000BEEEEEEEEF,
+       .want_hi = 0x00000000000000A6,
+       .want_lo = 0x14C912411FE97321},
+      {.x = 0x0123456789ABCDEF,
+       .y = 0x8080707066554321,
+       .want_hi = 0x009234D666DAD50F,
+       .want_lo = 0x89B3DE09506618CF},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    wuffs_base__multiply_u64__output have =
+        wuffs_base__multiply_u64(test_cases[tc].x, test_cases[tc].y);
+    if ((have.hi != test_cases[tc].want_hi) ||
+        (have.lo != test_cases[tc].want_lo)) {
+      RETURN_FAIL("0x%" PRIX64 " * 0x%" PRIX64 ": have (0x%" PRIX64
+                  ", 0x%" PRIX64 "), want (0x%" PRIX64 ", 0x%" PRIX64 ")",
+                  test_cases[tc].x, test_cases[tc].y, have.hi, have.lo,
+                  test_cases[tc].want_hi, test_cases[tc].want_lo);
+    }
+  }
+
+  return NULL;
+}
+
 // ---------------- String Conversions Tests
 
 // wuffs_base__private_implementation__high_prec_dec__to_debug_string converts
@@ -217,39 +288,39 @@
     uint64_t want;
     const char* str;
   } test_cases[] = {
-      {.want = 4, .str = "-3.9"},          //
-      {.want = 3, .str = "-3.14159"},      //
-      {.want = 0, .str = "+0"},            //
-      {.want = 0, .str = "0.0000000009"},  //
-      {.want = 0, .str = "0.1"},           //
-      {.want = 1, .str = "0.9"},           //
-      {.want = 12, .str = "1234e-2"},      //
-      {.want = 57, .str = "5678e-2"},      //
-      {.want = 60, .str = "60.0"},         //
-      {.want = 60, .str = "60.4999"},      //
-      {.want = 60, .str = "60.5"},         //
-      {.want = 60, .str = "60.5000"},      //
-      {.want = 61, .str = "60.5001"},      //
-      {.want = 61, .str = "60.6"},         //
-      {.want = 61, .str = "61.0"},         //
-      {.want = 61, .str = "61.4999"},      //
-      {.want = 62, .str = "61.5"},         //
-      {.want = 62, .str = "61.5000"},      //
-      {.want = 62, .str = "61.5001"},      //
-      {.want = 62, .str = "61.6"},         //
-      {.want = 62, .str = "62.0"},         //
-      {.want = 62, .str = "62.4999"},      //
-      {.want = 62, .str = "62.5"},         //
-      {.want = 62, .str = "62.5000"},      //
-      {.want = 63, .str = "62.5001"},      //
-      {.want = 63, .str = "62.6"},         //
-      {.want = 1000, .str = "999.999"},    //
-      {.want = 4560000, .str = "456e+4"},  //
+      {.want = 4, .str = "-3.9"},
+      {.want = 3, .str = "-3.14159"},
+      {.want = 0, .str = "+0"},
+      {.want = 0, .str = "0.0000000009"},
+      {.want = 0, .str = "0.1"},
+      {.want = 1, .str = "0.9"},
+      {.want = 12, .str = "1234e-2"},
+      {.want = 57, .str = "5678e-2"},
+      {.want = 60, .str = "60.0"},
+      {.want = 60, .str = "60.4999"},
+      {.want = 60, .str = "60.5"},
+      {.want = 60, .str = "60.5000"},
+      {.want = 61, .str = "60.5001"},
+      {.want = 61, .str = "60.6"},
+      {.want = 61, .str = "61.0"},
+      {.want = 61, .str = "61.4999"},
+      {.want = 62, .str = "61.5"},
+      {.want = 62, .str = "61.5000"},
+      {.want = 62, .str = "61.5001"},
+      {.want = 62, .str = "61.6"},
+      {.want = 62, .str = "62.0"},
+      {.want = 62, .str = "62.4999"},
+      {.want = 62, .str = "62.5"},
+      {.want = 62, .str = "62.5000"},
+      {.want = 63, .str = "62.5001"},
+      {.want = 63, .str = "62.6"},
+      {.want = 1000, .str = "999.999"},
+      {.want = 4560000, .str = "456e+4"},
 
       // With round-to-even, ½ rounds to 0 but "a tiny bit more than ½" rounds
       // to 1, even if the HPD struct truncates that "1" digit.
-      {.want = 0, .str = "0.5"},  //
-      {.want = 1,                 // 50 '0's per row.
+      {.want = 0, .str = "0.5"},
+      {.want = 1,  // 50 '0's per row.
        .str = "0.500000000000000000000000000000000000000000000000"
               "00000000000000000000000000000000000000000000000000"
               "00000000000000000000000000000000000000000000000000"
@@ -262,14 +333,14 @@
               "00000000000000000000000000000000000000000000000000"
               "00000000000000000000000000000000000000000000000000"
               "00000000000000000000000000000000000000000000000000"
-              "00000000000000000000000000000000000000000000000001"},  //
+              "00000000000000000000000000000000000000000000000001"},
 
       // Inputs with exactly 18 decimal digits before the decimal point.
-      {.want = 123456789012345679, .str = "123456789012345678.9"},   //
-      {.want = 1000000000000000000, .str = "999999999999999999.9"},  //
+      {.want = 123456789012345679, .str = "123456789012345678.9"},
+      {.want = 1000000000000000000, .str = "999999999999999999.9"},
 
       // Inputs with exactly 19 decimal digits before the decimal point.
-      {.want = UINT64_MAX, .str = "1234567890123456789"},  //
+      {.want = UINT64_MAX, .str = "1234567890123456789"},
   };
 
   int tc;
@@ -300,21 +371,21 @@
     int32_t shift;  // -ve means left shift, +ve means right shift.
     const char* want;
   } test_cases[] = {
-      {.str = "0", .shift = +2, .want = "+0"},                  //
-      {.str = "1", .shift = +3, .want = "+.125"},               //
-      {.str = "12e3", .shift = +5, .want = "+375."},            //
-      {.str = "-0.007", .shift = +8, .want = "-.00002734375"},  //
+      {.str = "0", .shift = +2, .want = "+0"},
+      {.str = "1", .shift = +3, .want = "+.125"},
+      {.str = "12e3", .shift = +5, .want = "+375."},
+      {.str = "-0.007", .shift = +8, .want = "-.00002734375"},
       {.str = "3.14159E+26",
        .shift = +60,
-       .want = "+272489496.244698869986677891574800014495849609375"},  //
+       .want = "+272489496.244698869986677891574800014495849609375"},
 
-      {.str = "0", .shift = -2, .want = "+0"},                //
-      {.str = ".125", .shift = -3, .want = "+1."},            //
-      {.str = "3750e-1", .shift = -5, .want = "+12000."},     //
-      {.str = "-2.734375e-5", .shift = -8, .want = "-.007"},  //
+      {.str = "0", .shift = -2, .want = "+0"},
+      {.str = ".125", .shift = -3, .want = "+1."},
+      {.str = "3750e-1", .shift = -5, .want = "+12000."},
+      {.str = "-2.734375e-5", .shift = -8, .want = "-.007"},
       {.str = "+272489496.244698869986677891574800014495849609375",
        .shift = -60,
-       .want = "+314159000000000000000000000."},  //
+       .want = "+314159000000000000000000000."},
   };
 
   int tc;
@@ -349,6 +420,184 @@
 }
 
 const char*  //
+test_strconv_mpb_assign_from_hpd() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    const char* str;
+    int32_t decimal_point;
+    uint64_t want_mantissa;
+    int32_t want_exp2;
+    double want_f64;
+  } test_cases[] = {
+
+      // (0x818995CE7AA0E1B2 * (2 ** -1136)) is roughly 1e-323
+      //
+      // 1e-323 is roughly twice 4.94066e-324, the minimum subnormal positive
+      // double-precision floating point number.
+      {.str = "1",
+       .decimal_point = -322,
+       .want_mantissa = 0x818995CE7AA0E1B2,
+       .want_exp2 = -1136,
+       .want_f64 = 1e-323},
+
+      // (0xD1B71758E219652C * (2 **   -77)) is roughly .0001
+      {.str = "1",
+       .decimal_point = -3,
+       .want_mantissa = 0xD1B71758E219652C,
+       .want_exp2 = -77,
+       .want_f64 = .0001},
+
+      // (0xCCCCCCCCCCCCCCCD * (2 **   -67)) is roughly .1
+      {.str = "1",
+       .decimal_point = +0,
+       .want_mantissa = 0xCCCCCCCCCCCCCCCD,
+       .want_exp2 = -67,
+       .want_f64 = .1},
+
+      // (0x8000000000000000 * (2 **   -63)) is         1.
+      {.str = "1",
+       .decimal_point = +1,
+       .want_mantissa = 0x8000000000000000,
+       .want_exp2 = -63,
+       .want_f64 = 1},
+
+      // (0xA000000000000000 * (2 **   -60)) is         10.
+      {.str = "1",
+       .decimal_point = +2,
+       .want_mantissa = 0xA000000000000000,
+       .want_exp2 = -60,
+       .want_f64 = 10},
+
+      // (0xC9F2C9CD04674EDE * (2 **   +36)) is roughly 1e30.
+      {.str = "1",
+       .decimal_point = +31,
+       .want_mantissa = 0xC9F2C9CD04674EDE,
+       .want_exp2 = +36,
+       .want_f64 = 1e30},
+
+      // (0xDE81E40A034BCF50 * (2 **  +966)) is roughly 1e310.
+      //
+      // 1e310 is almost 50 times larger than DBL_MAX (roughly 1.8e308), so it
+      // should be converted to +infinity.
+      {.str = "1",
+       .decimal_point = +311,
+       .want_mantissa = 0xDE81E40A034BCF50,
+       .want_exp2 = +966,
+       .want_f64 = (1.0 / 0.0)},
+
+      // (0x9A40000000000000 * (2 **   -53)) is         1234.
+      {.str = "1234",
+       .decimal_point = +4,
+       .want_mantissa = 0x9A40000000000000,
+       .want_exp2 = -53,
+       .want_f64 = 1234},
+
+      // (0xC90FCF80DC33721E * (2 **   -62)) is roughly 3.14159
+      {.str = "314159",
+       .decimal_point = +1,
+       .want_mantissa = 0xC90FCF80DC33721E,
+       .want_exp2 = -62,
+       .want_f64 = 3.14159},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    wuffs_base__private_implementation__high_prec_dec hpd;
+
+    // Initialize hpd.
+    uint32_t i;
+    for (i = 0; test_cases[tc].str[i]; i++) {
+      hpd.digits[i] = test_cases[tc].str[i] - '0';
+    }
+    hpd.num_digits = i;
+    hpd.decimal_point = test_cases[tc].decimal_point;
+    hpd.negative = false;
+    hpd.truncated = false;
+
+    static const bool skip_fast_path_for_tests = true;
+    wuffs_base__private_implementation__medium_prec_bin mpb;
+    wuffs_base__private_implementation__medium_prec_bin__parse_number_f64(
+        &mpb, &hpd, skip_fast_path_for_tests);
+
+    uint64_t have_mantissa = mpb.mantissa;
+    if (have_mantissa != test_cases[tc].want_mantissa) {
+      RETURN_FAIL("%s@%d: mantissa: have 0x%" PRIX64 ", want 0x%" PRIX64,
+                  test_cases[tc].str, test_cases[tc].decimal_point,
+                  have_mantissa, test_cases[tc].want_mantissa);
+    }
+
+    int32_t have_exp2 = mpb.exp2;
+    if (have_exp2 != test_cases[tc].want_exp2) {
+      RETURN_FAIL("%s@%d: exp2: have %" PRId32 ", want %" PRId32,
+                  test_cases[tc].str, test_cases[tc].decimal_point, have_exp2,
+                  test_cases[tc].want_exp2);
+    }
+
+    double have_f64 =
+        wuffs_base__private_implementation__medium_prec_bin__as_f64(&mpb,
+                                                                    false);
+    if (have_f64 != test_cases[tc].want_f64) {
+      RETURN_FAIL("%s@%d: f64: have %g, want %g", test_cases[tc].str,
+                  test_cases[tc].decimal_point, have_f64,
+                  test_cases[tc].want_f64);
+    }
+  }
+  return NULL;
+}
+
+// ----------------
+
+const char*  //
+test_strconv_hexadecimal() {
+  CHECK_FOCUS(__func__);
+
+  {
+    const char* str = "6A6b7";  // The "7" should be ignored.
+    wuffs_base__slice_u8 dst = g_have_slice_u8;
+    wuffs_base__slice_u8 src =
+        wuffs_base__make_slice_u8((void*)str, strlen(str));
+    size_t have = wuffs_base__hexadecimal__decode2(dst, src);
+    if (have != 2) {
+      RETURN_FAIL("decode2: have %zu, want 2", have);
+    }
+    if (g_have_array_u8[0] != 0x6A) {
+      RETURN_FAIL("decode2: dst[0]: have 0x%02X, want 0x6A",
+                  (int)(g_have_array_u8[0]));
+    }
+    if (g_have_array_u8[1] != 0x6B) {
+      RETURN_FAIL("decode2: dst[1]: have 0x%02X, want 0x6B",
+                  (int)(g_have_array_u8[1]));
+    }
+  }
+
+  {
+    const char* str = "\\xa9\\x00\\xFe";
+    wuffs_base__slice_u8 dst = g_have_slice_u8;
+    wuffs_base__slice_u8 src =
+        wuffs_base__make_slice_u8((void*)str, strlen(str));
+    size_t have = wuffs_base__hexadecimal__decode4(dst, src);
+    if (have != 3) {
+      RETURN_FAIL("decode4: have %zu, want 3", have);
+    }
+    if (g_have_array_u8[0] != 0xA9) {
+      RETURN_FAIL("decode4: dst[0]: have 0x%02X, want 0xA9",
+                  (int)(g_have_array_u8[0]));
+    }
+    if (g_have_array_u8[1] != 0x00) {
+      RETURN_FAIL("decode4: dst[1]: have 0x%02X, want 0x00",
+                  (int)(g_have_array_u8[1]));
+    }
+    if (g_have_array_u8[2] != 0xFE) {
+      RETURN_FAIL("decode4: dst[2]: have 0x%02X, want 0xFE",
+                  (int)(g_have_array_u8[2]));
+    }
+  }
+
+  return NULL;
+}
+
+const char*  //
 test_strconv_parse_number_f64() {
   CHECK_FOCUS(__func__);
 
@@ -361,6 +610,7 @@
       {.want = 0x0000000000000000, .str = "+0.0"},
       {.want = 0x0000000000000000, .str = "0"},
       {.want = 0x0000000000000000, .str = "0e0"},
+      {.want = 0x0000000000000000, .str = "1e-332"},
       {.want = 0x0000000000000001, .str = "4.9406564584124654e-324"},
       {.want = 0x000FFFFFFFFFFFFF, .str = "2.2250738585072009E-308"},
       {.want = 0x0010000000000000, .str = "2.2250738585072014E-308"},
@@ -382,7 +632,10 @@
       {.want = 0x3FF0000000000002, .str = "1.0000000000000004"},
       {.want = 0x3FF4000000000000, .str = "1.25"},
       {.want = 0x3FF8000000000000, .str = "+1.5"},
-      {.want = 0x4000000000000000, .str = "2"},
+      {.want = 0x4008000000000000, .str = "3"},
+      {.want = 0x400921F9F01B866E, .str = "3.14159"},
+      {.want = 0x400921FB54442D11, .str = "3.14159265358979"},
+      {.want = 0x400921FB54442D18, .str = "3.141592653589793"},
       {.want = 0x400921FB54442D18, .str = "3.141592653589793238462643383279"},
       {.want = 0x400C000000000000, .str = "3.5"},
       {.want = 0x4014000000000000, .str = "5"},
@@ -395,6 +648,7 @@
       {.want = 0x4038000000000000, .str = "24"},
       {.want = 0x4038000000000000, .str = "2400_00000_00000.00000_e-_1_2"},
       {.want = 0x40FE240C9FCB0C02, .str = "123456.789012"},
+      {.want = 0x4202A05F20000000, .str = "1e10"},
       {.want = 0x4330000000000000, .str = "4503599627370496"},  // 1 << 52.
       {.want = 0x4330000000000000, .str = "4503599627370496.5"},
       {.want = 0x4330000000000001, .str = "4503599627370497"},
@@ -406,10 +660,13 @@
       {.want = 0x4340000000000002, .str = "9007199254740995"},
       {.want = 0x4340000000000002, .str = "9007199254740996"},
       {.want = 0x4340000000000002, .str = "9_007__199_254__740_996"},
+      {.want = 0x4415AF1D78B58C40, .str = "1e20"},
+      {.want = 0x46293E5939A08CEA, .str = "1e30"},
       {.want = 0x54B249AD2594C37D, .str = "+1E+100"},
       {.want = 0x54B249AD2594C37D, .str = "+_1_E_+_1_0_0_"},
       {.want = 0x7FEFFFFFFFFFFFFF, .str = "1.7976931348623157e308"},
       {.want = 0x7FF0000000000000, .str = "1.8e308"},
+      {.want = 0x7FF0000000000000, .str = "1e+316"},
       {.want = 0x7FF0000000000000, .str = "1e999"},
       {.want = 0x7FF0000000000000, .str = "__InFinity__"},
       {.want = 0x7FF0000000000000, .str = "inf"},
@@ -712,26 +969,31 @@
 
 // ---------------- Golden Tests
 
-golden_test json_australian_abc_gt = {
-    .want_filename = "test/data/australian-abc-local-stations.tokens",  //
-    .src_filename = "test/data/australian-abc-local-stations.json",     //
+golden_test g_json_australian_abc_gt = {
+    .want_filename = "test/data/australian-abc-local-stations.tokens",
+    .src_filename = "test/data/australian-abc-local-stations.json",
 };
 
-golden_test json_file_sizes_gt = {
-    .src_filename = "test/data/file-sizes.json",  //
+golden_test g_json_file_sizes_gt = {
+    .src_filename = "test/data/file-sizes.json",
 };
 
-golden_test json_github_tags_gt = {
-    .src_filename = "test/data/github-tags.json",  //
+golden_test g_json_github_tags_gt = {
+    .src_filename = "test/data/github-tags.json",
 };
 
-golden_test json_json_things_unformatted_gt = {
-    .want_filename = "test/data/json-things.unformatted.tokens",  //
-    .src_filename = "test/data/json-things.unformatted.json",     //
+golden_test g_json_json_things_unformatted_gt = {
+    .want_filename = "test/data/json-things.unformatted.tokens",
+    .src_filename = "test/data/json-things.unformatted.json",
 };
 
-golden_test json_nobel_prizes_gt = {
-    .src_filename = "test/data/nobel-prizes.json",  //
+golden_test g_json_json_quirks_gt = {
+    .want_filename = "test/data/json-quirks.tokens",
+    .src_filename = "test/data/json-quirks.json",
+};
+
+golden_test g_json_nobel_prizes_gt = {
+    .src_filename = "test/data/nobel-prizes.json",
 };
 
 // ---------------- JSON Tests
@@ -748,7 +1010,7 @@
                      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
     CHECK_STRING(do_test__wuffs_base__token_decoder(
         wuffs_json__decoder__upcast_as__wuffs_base__token_decoder(&dec),
-        &json_json_things_unformatted_gt));
+        &g_json_json_things_unformatted_gt));
   }
 
   {
@@ -759,7 +1021,42 @@
                      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
     CHECK_STRING(do_test__wuffs_base__token_decoder(
         wuffs_json__decoder__upcast_as__wuffs_base__token_decoder(&dec),
-        &json_australian_abc_gt));
+        &g_json_australian_abc_gt));
+  }
+
+  {
+    uint32_t quirks[] = {
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X,
+        WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO,
+        WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK,
+        WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE,
+        WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA,
+        WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS,
+        WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR,
+        WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK,
+        WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE,
+        WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE,
+        0,
+    };
+
+    wuffs_json__decoder dec;
+    CHECK_STATUS("initialize",
+                 wuffs_json__decoder__initialize(
+                     &dec, sizeof dec, WUFFS_VERSION,
+                     WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+    uint32_t i;
+    for (i = 0; quirks[i]; i++) {
+      wuffs_json__decoder__set_quirk_enabled(&dec, quirks[i], true);
+    }
+    CHECK_STRING(do_test__wuffs_base__token_decoder(
+        wuffs_json__decoder__upcast_as__wuffs_base__token_decoder(&dec),
+        &g_json_json_quirks_gt));
   }
 
   return NULL;
@@ -781,8 +1078,8 @@
         make_limited_token_writer(*tok, wlimit);
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
 
-    wuffs_base__status status =
-        wuffs_json__decoder__decode_tokens(&dec, &limited_tok, &limited_src);
+    wuffs_base__status status = wuffs_json__decoder__decode_tokens(
+        &dec, &limited_tok, &limited_src, g_work_slice_u8);
 
     tok->meta.wi += limited_tok.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -798,6 +1095,45 @@
 }
 
 const char*  //
+test_wuffs_json_decode_end_of_data() {
+  CHECK_FOCUS(__func__);
+
+  int i;
+  for (i = 0; i < 2; i++) {
+    uint8_t* src_ptr = (uint8_t*)("123null89");
+    size_t src_len = i ? 3 : 9;
+
+    wuffs_json__decoder dec;
+    CHECK_STATUS("initialize",
+                 wuffs_json__decoder__initialize(
+                     &dec, sizeof dec, WUFFS_VERSION,
+                     WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
+
+    wuffs_base__token_buffer tok =
+        wuffs_base__make_token_buffer_writer(g_have_slice_token);
+    wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+        wuffs_base__make_slice_u8(src_ptr, src_len), true);
+    CHECK_STATUS("decode_tokens", wuffs_json__decoder__decode_tokens(
+                                      &dec, &tok, &src, g_work_slice_u8));
+    if (src.meta.ri != 3) {
+      RETURN_FAIL("src.meta.ri: have %zu, want 3", src.meta.ri);
+    }
+
+    const char* have =
+        wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+            .repr;
+    if (have != wuffs_base__note__end_of_data) {
+      RETURN_FAIL("decode_tokens: have \"%s\", want \"%s\"", have,
+                  wuffs_base__note__end_of_data);
+    }
+    if (src.meta.ri != 3) {
+      RETURN_FAIL("src.meta.ri: have %zu, want 3", src.meta.ri);
+    }
+  }
+  return NULL;
+}
+
+const char*  //
 test_wuffs_json_decode_long_numbers() {
   CHECK_FOCUS(__func__);
 
@@ -816,30 +1152,30 @@
     bool valid;
     const char* suffix;
   } test_cases[] = {
-      {.valid = true, .suffix = ""},           //
-      {.valid = true, .suffix = " "},          //
-      {.valid = fals, .suffix = "."},          //
-      {.valid = fals, .suffix = ". "},         //
-      {.valid = fals, .suffix = "E"},          //
-      {.valid = fals, .suffix = "E "},         //
-      {.valid = fals, .suffix = "E-"},         //
-      {.valid = fals, .suffix = "E- "},        //
-      {.valid = true, .suffix = "e2"},         //
-      {.valid = true, .suffix = "e2 "},        //
-      {.valid = true, .suffix = "e+34"},       //
-      {.valid = true, .suffix = "e+34 "},      //
-      {.valid = true, .suffix = ".2"},         //
-      {.valid = true, .suffix = ".2 "},        //
-      {.valid = fals, .suffix = ".2e"},        //
-      {.valid = fals, .suffix = ".2e "},       //
-      {.valid = fals, .suffix = ".2e+"},       //
-      {.valid = fals, .suffix = ".2e+ "},      //
-      {.valid = true, .suffix = ".2e4"},       //
-      {.valid = true, .suffix = ".2e4 "},      //
-      {.valid = true, .suffix = ".2E+5"},      //
-      {.valid = true, .suffix = ".2E+5 "},     //
-      {.valid = true, .suffix = ".2e-5678"},   //
-      {.valid = true, .suffix = ".2e-5678 "},  //
+      {.valid = true, .suffix = ""},
+      {.valid = true, .suffix = " "},
+      {.valid = fals, .suffix = "."},
+      {.valid = fals, .suffix = ". "},
+      {.valid = fals, .suffix = "E"},
+      {.valid = fals, .suffix = "E "},
+      {.valid = fals, .suffix = "E-"},
+      {.valid = fals, .suffix = "E- "},
+      {.valid = true, .suffix = "e2"},
+      {.valid = true, .suffix = "e2 "},
+      {.valid = true, .suffix = "e+34"},
+      {.valid = true, .suffix = "e+34 "},
+      {.valid = true, .suffix = ".2"},
+      {.valid = true, .suffix = ".2 "},
+      {.valid = fals, .suffix = ".2e"},
+      {.valid = fals, .suffix = ".2e "},
+      {.valid = fals, .suffix = ".2e+"},
+      {.valid = fals, .suffix = ".2e+ "},
+      {.valid = true, .suffix = ".2e4"},
+      {.valid = true, .suffix = ".2e4 "},
+      {.valid = true, .suffix = ".2E+5"},
+      {.valid = true, .suffix = ".2E+5 "},
+      {.valid = true, .suffix = ".2e-5678"},
+      {.valid = true, .suffix = ".2e-5678 "},
   };
 
   // src_array holds the overall test string. 119 is arbitrary but long enough.
@@ -885,18 +1221,13 @@
                 &dec, sizeof dec, WUFFS_VERSION,
                 WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
 
-        wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
-            .data = global_have_token_slice,
-        });
-
-        wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-            .data = src_data,
-            .meta = wuffs_base__make_io_buffer_meta(src_data.len, 0, 0,
-                                                    closed != 0),
-        });
-
-        const char* have =
-            wuffs_json__decoder__decode_tokens(&dec, &tok, &src).repr;
+        wuffs_base__token_buffer tok =
+            wuffs_base__make_token_buffer_writer(g_have_slice_token);
+        wuffs_base__io_buffer src =
+            wuffs_base__make_io_buffer_reader(src_data, closed != 0);
+        const char* have = wuffs_json__decoder__decode_tokens(&dec, &tok, &src,
+                                                              g_work_slice_u8)
+                               .repr;
 
         size_t total_length = 0;
         while (tok.meta.ri < tok.meta.wi) {
@@ -1020,7 +1351,7 @@
         // mark, where prefix and suffix are the number of 'p's and 's's and
         // test_cases[tc] is the "MIDDLE".
         wuffs_base__slice_u8 src_data = ((wuffs_base__slice_u8){
-            .ptr = global_src_array,
+            .ptr = &g_src_array_u8[0],
             .len = 1 + prefix + n + suffix,
         });
         if (src_data.len > IO_BUFFER_ARRAY_SIZE) {
@@ -1036,17 +1367,11 @@
           CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
                                          &dec, sizeof dec, WUFFS_VERSION, 0));
 
-          wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
-              .data = global_have_token_slice,
-          });
-
-          wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-              .data = src_data,
-              .meta = wuffs_base__make_io_buffer_meta(src_data.len, 0, 0,
-                                                      closed != 0),
-          });
-
-          wuffs_json__decoder__decode_tokens(&dec, &tok, &src);
+          wuffs_base__token_buffer tok =
+              wuffs_base__make_token_buffer_writer(g_have_slice_token);
+          wuffs_base__io_buffer src =
+              wuffs_base__make_io_buffer_reader(src_data, closed != 0);
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8);
 
           size_t have = 0;
           while (tok.meta.ri < tok.meta.wi) {
@@ -1080,6 +1405,694 @@
 }
 
 const char*  //
+test_wuffs_json_decode_quirk_allow_backslash_etc() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    uint32_t want;
+    const char* str;
+    uint32_t quirk;
+  } test_cases[] = {
+      {
+          .want = 0x07,
+          .str = "\"\\a\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A,
+      },
+      {
+          .want = 0x0001F4A9,
+          .str = "\"\\U0001F4A9\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U,
+      },
+      {
+          .want = 0x1B,
+          .str = "\"\\e\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E,
+      },
+      {
+          .want = 0x3F,
+          .str = "\"\\?\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK,
+      },
+      {
+          .want = 0x27,
+          .str = "\"\\'\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE,
+      },
+      {
+          .want = 0x0B,
+          .str = "\"\\v\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V,
+      },
+      {
+          .want = 0x00,
+          .str = "\"\\0\"",
+          .quirk = WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO,
+      },
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    int q;
+    for (q = 0; q < 2; q++) {
+      wuffs_json__decoder dec;
+      CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                     &dec, sizeof dec, WUFFS_VERSION,
+                                     WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+      wuffs_json__decoder__set_quirk_enabled(&dec, test_cases[tc].quirk, q);
+
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+          wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                    strlen(test_cases[tc].str)),
+          true);
+
+      const char* have_status_repr =
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+              .repr;
+      const char* want_status_repr =
+          q ? NULL : wuffs_json__error__bad_backslash_escape;
+      if (have_status_repr != want_status_repr) {
+        RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                    q, have_status_repr, want_status_repr);
+      }
+      if (want_status_repr != NULL) {
+        continue;
+      }
+
+      uint32_t have = 0;
+      while (tok.meta.ri < tok.meta.wi) {
+        wuffs_base__token* t = &tok.data.ptr[tok.meta.ri++];
+        uint64_t vbc = wuffs_base__token__value_base_category(t);
+        uint64_t vbd = wuffs_base__token__value_base_detail(t);
+        if (vbc == WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT) {
+          have = vbd;
+          break;
+        }
+      }
+      if (have != test_cases[tc].want) {
+        RETURN_FAIL("tc=%d, q=%d: Unicode code point: have U+%04" PRIX32
+                    ", want U+%04" PRIX32,
+                    tc, q, have, test_cases[tc].want);
+      }
+    }
+  }
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_allow_backslash_x() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    uint64_t want_bytes;
+    const char* want_status_repr;
+    const char* str;
+  } test_cases[] = {
+      {.want_bytes = 0x12789A,
+       .want_status_repr = NULL,
+       .str = "\"\\x12\\u3456\\x78\\x9A\""},
+      {.want_bytes = 0x00,
+       .want_status_repr = wuffs_json__error__bad_backslash_escape,
+       .str = "\"a\\X6A\""},
+      {.want_bytes = 0x6A6B,
+       .want_status_repr = NULL,
+       .str = "\"a\\x6A\\x6bz\""},
+      {.want_bytes = 0x6A,
+       .want_status_repr = wuffs_json__error__bad_backslash_escape,
+       .str = "\"a\\x6A\\x6yz\""},
+      {.want_bytes = 0x00,
+       .want_status_repr = wuffs_json__error__bad_backslash_escape,
+       .str = "\"a\\x\""},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    wuffs_json__decoder dec;
+    CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                   &dec, sizeof dec, WUFFS_VERSION,
+                                   WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+    wuffs_json__decoder__set_quirk_enabled(
+        &dec, WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X, true);
+
+    wuffs_base__token_buffer tok =
+        wuffs_base__make_token_buffer_writer(g_have_slice_token);
+    wuffs_base__slice_u8 src_slice = wuffs_base__make_slice_u8(
+        (void*)(test_cases[tc].str), strlen(test_cases[tc].str));
+    wuffs_base__io_buffer src =
+        wuffs_base__make_io_buffer_reader(src_slice, true);
+    const char* have_status_repr =
+        wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+            .repr;
+    if (have_status_repr != test_cases[tc].want_status_repr) {
+      RETURN_FAIL("tc=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                  have_status_repr, test_cases[tc].want_status_repr);
+    }
+
+    uint64_t src_index = 0;
+    uint64_t have_bytes = 0;
+    while (tok.meta.ri < tok.meta.wi) {
+      wuffs_base__token* t = &tok.data.ptr[tok.meta.ri++];
+      uint64_t vbc = wuffs_base__token__value_base_category(t);
+      uint64_t vbd = wuffs_base__token__value_base_detail(t);
+      uint64_t token_length = wuffs_base__token__length(t);
+      if ((vbc == WUFFS_BASE__TOKEN__VBC__STRING) &&
+          (vbd ==
+           WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X)) {
+        uint8_t b[8] = {0};
+        size_t n = wuffs_base__hexadecimal__decode4(
+            wuffs_base__make_slice_u8(&b[0], 8),
+            wuffs_base__make_slice_u8(src_slice.ptr + src_index, token_length));
+        size_t i = 0;
+        for (; i < n; i++) {
+          have_bytes <<= 8;
+          have_bytes |= b[i];
+        }
+      }
+
+      src_index += token_length;
+    }
+    if (have_bytes != test_cases[tc].want_bytes) {
+      RETURN_FAIL("tc=%d: have U+%08" PRIX64 ", want U+%08" PRIX64, tc,
+                  have_bytes, test_cases[tc].want_bytes);
+    }
+  }
+
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_allow_extra_comma() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    // want has 2 bytes, one for each possible q:
+    //  - q&1 sets WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA.
+    // An 'X', '+' or '-' means that decoding should succeed (and consume the
+    // entire input), succeed (without consuming the entire input) or fail.
+    const char* want;
+    const char* str;
+  } test_cases[] = {
+      {.want = "-X", .str = "[0,]"},
+      {.want = "-X", .str = "[[], {},{\"k\":\"v\",\n}\n,\n]"},
+      {.want = "--", .str = "[,]"},
+      {.want = "--", .str = "{,}"},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    int q;
+    for (q = 0; q < 2; q++) {
+      wuffs_json__decoder dec;
+      CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                     &dec, sizeof dec, WUFFS_VERSION,
+                                     WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA, q & 1);
+
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+          wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                    strlen(test_cases[tc].str)),
+          true);
+      const char* have =
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+              .repr;
+      const char* want =
+          (test_cases[tc].want[q] != '-') ? NULL : wuffs_json__error__bad_input;
+      if (have != want) {
+        RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                    q, have, want);
+      }
+
+      size_t total_length = 0;
+      while (tok.meta.ri < tok.meta.wi) {
+        total_length += wuffs_base__token__length(&tok.data.ptr[tok.meta.ri++]);
+      }
+      if (total_length != src.meta.ri) {
+        RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                    total_length, src.meta.ri);
+      }
+      if (test_cases[tc].want[q] == 'X') {
+        if (total_length != src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      } else if (test_cases[tc].want[q] == '+') {
+        if (total_length >= src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want < %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_allow_inf_nan_numbers() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    // want has 2 bytes, one for each possible q:
+    //  - q&1 sets WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS.
+    // An 'X', '+' or '-' means that decoding should succeed (and consume the
+    // entire input), succeed (without consuming the entire input) or fail.
+    const char* want;
+    const char* str;
+  } test_cases[] = {
+      {.want = "-X", .str = "InFiniTy"},
+      {.want = "-X", .str = "[+inf, -infinity, +nan,-NaN,NAN]"},
+      {.want = "-X", .str = "inf"},
+      {.want = "-+", .str = "infinit"},
+      {.want = "-+", .str = "infiQity"},
+      {.want = "-+", .str = "nana"},
+      {.want = "--", .str = "+-inf"},
+      {.want = "--", .str = "-+inf"},
+      {.want = "--", .str = "[infinit,"},
+      {.want = "--", .str = "[infiQity,"},
+      {.want = "--", .str = "[nana,"},
+      {.want = "--", .str = "∞"},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    int q;
+    for (q = 0; q < 2; q++) {
+      wuffs_json__decoder dec;
+      CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                     &dec, sizeof dec, WUFFS_VERSION,
+                                     WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS, q & 1);
+
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+          wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                    strlen(test_cases[tc].str)),
+          true);
+      const char* have =
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+              .repr;
+      const char* want =
+          (test_cases[tc].want[q] != '-') ? NULL : wuffs_json__error__bad_input;
+      if (have != want) {
+        RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                    q, have, want);
+      }
+
+      size_t total_length = 0;
+      while (tok.meta.ri < tok.meta.wi) {
+        total_length += wuffs_base__token__length(&tok.data.ptr[tok.meta.ri++]);
+      }
+      if (total_length != src.meta.ri) {
+        RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                    total_length, src.meta.ri);
+      }
+      if (test_cases[tc].want[q] == 'X') {
+        if (total_length != src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      } else if (test_cases[tc].want[q] == '+') {
+        if (total_length >= src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want < %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_allow_comment_etc() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    // want has 4 bytes, one for each possible q:
+    //  - q&1 sets WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK.
+    //  - q&2 sets WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE.
+    // An 'X', '+' or '-' means that decoding should succeed (and consume the
+    // entire input), succeed (without consuming the entire input) or fail.
+    const char* want;
+    const char* str;
+  } test_cases[] = {
+      {.want = "-X-X", .str = "[ /*com*/ 0]"},
+      {.want = "--XX", .str = "//l\n  //m\n0"},
+      {.want = "---X", .str = "[ 0, /*com*/ 1 //l\n\n]"},
+      {.want = "----", .str = "/*/0"},   // Not a valid slash-star comment.
+      {.want = "----", .str = "[4/5]"},  // Lone slash.
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    int q;
+    for (q = 0; q < 4; q++) {
+      wuffs_json__decoder dec;
+      CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                     &dec, sizeof dec, WUFFS_VERSION,
+                                     WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK, q & 1);
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE, q & 2);
+
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+          wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                    strlen(test_cases[tc].str)),
+          true);
+      const char* have =
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+              .repr;
+      const char* want =
+          (test_cases[tc].want[q] != '-') ? NULL : wuffs_json__error__bad_input;
+      if (have != want) {
+        RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                    q, have, want);
+      }
+
+      size_t total_length = 0;
+      while (tok.meta.ri < tok.meta.wi) {
+        total_length += wuffs_base__token__length(&tok.data.ptr[tok.meta.ri++]);
+      }
+      if (total_length != src.meta.ri) {
+        RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                    total_length, src.meta.ri);
+      }
+      if (test_cases[tc].want[q] == 'X') {
+        if (total_length != src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      } else if (test_cases[tc].want[q] == '+') {
+        if (total_length >= src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want < %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_allow_leading_etc() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    // want has 4 bytes, one for each possible q:
+    //  - q&1 sets WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR.
+    //  - q&2 sets WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK.
+    // An 'X', '+' or '-' means that decoding should succeed (and consume the
+    // entire input), succeed (without consuming the entire input) or fail.
+    const char* want;
+    const char* str;
+  } test_cases[] = {
+      {.want = "-X-X", .str = "\x1Etrue"},
+      {.want = "--XX", .str = "\xEF\xBB\xBFtrue"},
+      {.want = "---X", .str = "\x1E\xEF\xBB\xBFtrue"},
+      {.want = "---X", .str = "\xEF\xBB\xBF\x1Etrue"},
+      {.want = "----", .str = " \x1Etrue"},
+      {.want = "----", .str = "\x1E \xEF\xBB\xBFtrue"},
+      {.want = "----", .str = "\x1E\x1Etrue"},
+      {.want = "----", .str = "\xEF\xBB"},
+      {.want = "----", .str = "\xEF\xBB\xBF"},
+      {.want = "----", .str = "\xEF\xBB\xBF$"},
+      {.want = "----", .str = "\xEFtrue"},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    int q;
+    for (q = 0; q < 4; q++) {
+      wuffs_json__decoder dec;
+      CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                     &dec, sizeof dec, WUFFS_VERSION,
+                                     WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR, q & 1);
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK, q & 2);
+
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+          wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                    strlen(test_cases[tc].str)),
+          true);
+      const char* have =
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+              .repr;
+      const char* want =
+          (test_cases[tc].want[q] != '-') ? NULL : wuffs_json__error__bad_input;
+      if (have != want) {
+        RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                    q, have, want);
+      }
+
+      size_t total_length = 0;
+      while (tok.meta.ri < tok.meta.wi) {
+        total_length += wuffs_base__token__length(&tok.data.ptr[tok.meta.ri++]);
+      }
+      if (total_length != src.meta.ri) {
+        RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                    total_length, src.meta.ri);
+      }
+      if (test_cases[tc].want[q] == 'X') {
+        if (total_length != src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      } else if (test_cases[tc].want[q] == '+') {
+        if (total_length >= src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want < %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_allow_trailing_etc() {
+  CHECK_FOCUS(__func__);
+
+  struct {
+    // want has 2 bytes, one for each possible q:
+    //  - q&1 sets WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE.
+    // An 'X', '+' or '-' means that decoding should succeed (and consume the
+    // entire input), succeed (without consuming the entire input) or fail.
+    const char* want;
+    const char* str;
+  } test_cases[] = {
+      {.want = "++", .str = "0 \n "},      //
+      {.want = "++", .str = "0 \n\n"},     //
+      {.want = "++", .str = "0\n\n"},      //
+      {.want = "+-", .str = "0 true \n"},  //
+      {.want = "+-", .str = "007"},        //
+      {.want = "+-", .str = "007\n"},      //
+      {.want = "+-", .str = "0true "},     //
+      {.want = "+-", .str = "0true"},      //
+      {.want = "+X", .str = "0 "},         //
+      {.want = "+X", .str = "0 \n"},       //
+      {.want = "+X", .str = "0\n"},        //
+      {.want = "+X", .str = "0\t\r\n"},    //
+      {.want = "--", .str = "\n"},         //
+      {.want = "XX", .str = "0"},          //
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    int q;
+    for (q = 0; q < 2; q++) {
+      wuffs_json__decoder dec;
+      CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                     &dec, sizeof dec, WUFFS_VERSION,
+                                     WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+      wuffs_json__decoder__set_quirk_enabled(
+          &dec, WUFFS_JSON__QUIRK_ALLOW_TRAILING_NEW_LINE, q & 1);
+
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+          wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                    strlen(test_cases[tc].str)),
+          true);
+      const char* have =
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8)
+              .repr;
+      const char* want =
+          (test_cases[tc].want[q] != '-') ? NULL : wuffs_json__error__bad_input;
+      if (have != want) {
+        RETURN_FAIL("tc=%d, q=%d: decode_tokens: have \"%s\", want \"%s\"", tc,
+                    q, have, want);
+      }
+
+      size_t total_length = 0;
+      while (tok.meta.ri < tok.meta.wi) {
+        total_length += wuffs_base__token__length(&tok.data.ptr[tok.meta.ri++]);
+      }
+      if (total_length != src.meta.ri) {
+        RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                    total_length, src.meta.ri);
+      }
+      if (test_cases[tc].want[q] == 'X') {
+        if (total_length != src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      } else if (test_cases[tc].want[q] == '+') {
+        if (total_length >= src.data.len) {
+          RETURN_FAIL("tc=%d, q=%d: total_length: have %zu, want < %zu", tc, q,
+                      total_length, src.data.len);
+        }
+      }
+    }
+  }
+  return NULL;
+}
+
+const char*  //
+test_wuffs_json_decode_quirk_replace_invalid_unicode() {
+  CHECK_FOCUS(__func__);
+
+  // Decoding str should produce want, with invalid UTF-8 replaced by "?". A
+  // proper JSON decoder (with the quirk enabled) would replace with
+  // "\xEF\xBF\xBD", the UTF-8 encoding of U+FFFD, but using "?" leads to
+  // clearer, shorter test cases.
+  struct {
+    const char* want;
+    const char* str;
+  } test_cases[] = {
+      // Valid UTF-8.
+      {.want = "abc", .str = "\"abc\""},
+      {.want = "del\xCE\x94ta", .str = "\"del\\u0394ta\""},
+      {.want = "del\xCE\x94ta", .str = "\"del\xCE\x94ta\""},
+
+      // Invalid UTF-8: right byte lengths, wrong bytes.
+      {.want = "1byte?yz", .str = "\"1byte\xFFyz\""},
+      {.want = "2byte??yz", .str = "\"2byte\xCE\xFFyz\""},
+      {.want = "3byte???yz", .str = "\"3byte\xE2\x98\xFFyz\""},
+      {.want = "4byte????yz", .str = "\"4byte\xF0\x9F\x92\xFFyz\""},
+
+      // Invalid UTF-8: wrong byte lengths.
+      {.want = "?", .str = "\"\xCE\""},
+      {.want = "?g", .str = "\"\xCEg\""},
+      {.want = "?gh", .str = "\"\xCEgh\""},
+      {.want = "j?", .str = "\"j\xE2\""},
+      {.want = "j?l", .str = "\"j\xE2l\""},
+      {.want = "j?lm", .str = "\"j\xE2lm\""},
+      {.want = "?", .str = "\"\xF0\""},
+      {.want = "?r", .str = "\"\xF0r\""},
+      {.want = "?rs", .str = "\"\xF0rs\""},
+
+      // U+DC00 (as an unpaired surrogate) is either 1 or 3 '?'s depending on
+      // whether it's backslash-u or backslash-x.
+      {.want = "a?z", .str = "\"a\\uDC00z\""},
+      {.want = "a?zzzzzz", .str = "\"a\\uDC00zzzzzz\""},
+      {.want = "a???z", .str = "\"a\xED\xB0\x80z\""},
+      {.want = "a???zzzzzz", .str = "\"a\xED\xB0\x80zzzzzz\""},
+
+      // 1 or 2 unpaired surrogates each become '?'s, but for 3 surrogates
+      // where consecutive surrogates make a valid pair, there's only 1 '?'.
+      {.want = "a?z", .str = "\"a\\uD800z\""},
+      {.want = "a??z", .str = "\"a\\uD800\\uDBFFz\""},
+      {.want = "a?\xF4\x8F\xBF\xBFz", .str = "\"a\\uD800\\uDBFF\\uDFFFz\""},
+      {.want = "a\xF0\x90\x80\x80?z", .str = "\"a\\uD800\\uDC00\\uDFFFz\""},
+  };
+
+  int tc;
+  for (tc = 0; tc < WUFFS_TESTLIB_ARRAY_SIZE(test_cases); tc++) {
+    wuffs_json__decoder dec;
+    CHECK_STATUS("initialize", wuffs_json__decoder__initialize(
+                                   &dec, sizeof dec, WUFFS_VERSION,
+                                   WUFFS_INITIALIZE__DEFAULT_OPTIONS));
+    wuffs_json__decoder__set_quirk_enabled(
+        &dec, WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE, true);
+
+    wuffs_base__io_buffer have =
+        wuffs_base__make_io_buffer_writer(g_have_slice_u8);
+    wuffs_base__token_buffer tok =
+        wuffs_base__make_token_buffer_writer(g_have_slice_token);
+    wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+        wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                  strlen(test_cases[tc].str)),
+        true);
+    CHECK_STATUS("decode_tokens", wuffs_json__decoder__decode_tokens(
+                                      &dec, &tok, &src, g_work_slice_u8));
+
+    uint64_t src_index = 0;
+    while (tok.meta.ri < tok.meta.wi) {
+      wuffs_base__token* t = &tok.data.ptr[tok.meta.ri++];
+      uint64_t vbc = wuffs_base__token__value_base_category(t);
+      uint64_t vbd = wuffs_base__token__value_base_detail(t);
+      uint64_t token_length = wuffs_base__token__length(t);
+
+      if (vbc == WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT) {
+        uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
+        size_t n = wuffs_base__utf_8__encode(
+            wuffs_base__make_slice_u8(&u[0],
+                                      WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
+            vbd);
+        if (vbd == 0xFFFD) {
+          u[0] = '?';
+          n = 1;
+        }
+        if ((have.data.len - have.meta.wi) < n) {
+          RETURN_FAIL("tc=%d: token too long", tc);
+        }
+        memcpy(&have.data.ptr[have.meta.wi], &u[0], n);
+        have.meta.wi += n;
+
+      } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRING) {
+        if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
+          // No-op.
+        } else if (vbd &
+                   WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
+          if ((have.data.len - have.meta.wi) < token_length) {
+            RETURN_FAIL("tc=%d: token too long", tc);
+          }
+          memcpy(&have.data.ptr[have.meta.wi], &test_cases[tc].str[src_index],
+                 token_length);
+          have.meta.wi += token_length;
+        } else {
+          RETURN_FAIL("tc=%d: unexpected string-token conversion", tc);
+        }
+
+      } else {
+        RETURN_FAIL("tc=%d: unexpected token", tc);
+      }
+
+      src_index += token_length;
+    }
+
+    if (src_index != src.meta.ri) {
+      RETURN_FAIL("tc=%d: src_index: have %zu, want %zu", tc, src_index,
+                  src.meta.ri);
+    }
+
+    if (have.meta.wi >= have.data.len) {
+      RETURN_FAIL("tc=%d: too many have bytes", tc);
+    }
+    have.data.ptr[have.meta.wi] = '\x00';
+    size_t len = strlen(test_cases[tc].want);
+    if ((len != have.meta.wi) ||
+        (memcmp(have.data.ptr, test_cases[tc].want, len) != 0)) {
+      RETURN_FAIL("tc=%d: have \"%s\", want \"%s\"", tc, have.data.ptr,
+                  test_cases[tc].want);
+    }
+  }
+
+  return NULL;
+}
+
+const char*  //
 test_wuffs_json_decode_unicode4_escapes() {
   CHECK_FOCUS(__func__);
 
@@ -1139,16 +2152,13 @@
                      &dec, sizeof dec, WUFFS_VERSION,
                      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
 
-    wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
-        .data = global_have_token_slice,
-    });
-    size_t n = strlen(test_cases[tc].str);
-    wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-        .data = wuffs_base__make_slice_u8((void*)(test_cases[tc].str), n),
-        .meta = wuffs_base__make_io_buffer_meta(n, 0, 0, true),
-    });
-
-    wuffs_json__decoder__decode_tokens(&dec, &tok, &src);
+    wuffs_base__token_buffer tok =
+        wuffs_base__make_token_buffer_writer(g_have_slice_token);
+    wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+        wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                  strlen(test_cases[tc].str)),
+        true);
+    wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8);
 
     uint32_t have = fail;
     uint64_t total_length = 0;
@@ -1231,21 +2241,17 @@
 
     int closed;
     for (closed = 0; closed < 2; closed++) {
-      wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
-          .data = global_have_token_slice,
-      });
-      wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-          .data = src_data,
-          .meta =
-              wuffs_base__make_io_buffer_meta(src_data.len, 0, 0, closed != 0),
-      });
+      wuffs_base__token_buffer tok =
+          wuffs_base__make_token_buffer_writer(g_have_slice_token);
+      wuffs_base__io_buffer src =
+          wuffs_base__make_io_buffer_reader(src_data, closed != 0);
       CHECK_STATUS("initialize",
                    wuffs_json__decoder__initialize(
                        &dec, sizeof dec, WUFFS_VERSION,
                        WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
 
       wuffs_base__status have =
-          wuffs_json__decoder__decode_tokens(&dec, &tok, &src);
+          wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8);
       const char* want =
           (i > WUFFS_JSON__DECODER_NUMBER_LENGTH_MAX_INCL)
               ? wuffs_json__error__unsupported_number_length
@@ -1338,17 +2344,14 @@
                      &dec, sizeof dec, WUFFS_VERSION,
                      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
 
-    wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
-        .data = global_have_token_slice,
-    });
-    size_t n = strlen(test_cases[tc].str);
-    wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-        .data = wuffs_base__make_slice_u8((void*)(test_cases[tc].str), n),
-        .meta = wuffs_base__make_io_buffer_meta(n, 0, 0, true),
-    });
-
+    wuffs_base__token_buffer tok =
+        wuffs_base__make_token_buffer_writer(g_have_slice_token);
+    wuffs_base__io_buffer src = wuffs_base__make_io_buffer_reader(
+        wuffs_base__make_slice_u8((void*)(test_cases[tc].str),
+                                  strlen(test_cases[tc].str)),
+        true);
     wuffs_base__status have_status =
-        wuffs_json__decoder__decode_tokens(&dec, &tok, &src);
+        wuffs_json__decoder__decode_tokens(&dec, &tok, &src, g_work_slice_u8);
 
     uint64_t total_length = 0;
     size_t i;
@@ -1380,6 +2383,50 @@
 
 #endif  // WUFFS_MIMIC
 
+// ---------------- String Conversions Benches
+
+const char*  //
+do_bench_strconv_parse_number_f64(const char* str, uint64_t iters_unscaled) {
+  wuffs_base__slice_u8 s = wuffs_base__make_slice_u8((void*)str, strlen(str));
+
+  bench_start();
+  uint64_t i;
+  uint64_t iters = iters_unscaled * g_flags.iterscale;
+  for (i = 0; i < iters; i++) {
+    CHECK_STATUS("", wuffs_base__parse_number_f64(s).status);
+  }
+  bench_finish(iters, 0);
+
+  return NULL;
+}
+
+const char*  //
+bench_strconv_parse_number_f64_1_lsh53_add0() {
+  CHECK_FOCUS(__func__);
+  // 9007_199254_740992 is 0x20_0000_0000_0000, aka ((1<<53) + 0).
+  return do_bench_strconv_parse_number_f64("9007199254740992", 1000);
+}
+
+const char*  //
+bench_strconv_parse_number_f64_1_lsh53_add1() {
+  CHECK_FOCUS(__func__);
+  // 9007_199254_740993 is 0x20_0000_0000_0001, aka ((1<<53) + 1).
+  return do_bench_strconv_parse_number_f64("9007199254740993", 1000);
+}
+
+const char*  //
+bench_strconv_parse_number_f64_pi_long() {
+  CHECK_FOCUS(__func__);
+  return do_bench_strconv_parse_number_f64("3.141592653589793238462643383279",
+                                           1000);
+}
+
+const char*  //
+bench_strconv_parse_number_f64_pi_short() {
+  CHECK_FOCUS(__func__);
+  return do_bench_strconv_parse_number_f64("3.14159", 1000);
+}
+
 // ---------------- JSON Benches
 
 const char*  //
@@ -1387,7 +2434,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_token_decoder(
       wuffs_json_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_src, &json_github_tags_gt, UINT64_MAX, UINT64_MAX, 10000);
+      tcounter_src, &g_json_github_tags_gt, UINT64_MAX, UINT64_MAX, 10000);
 }
 
 const char*  //
@@ -1395,7 +2442,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_token_decoder(
       wuffs_json_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_src, &json_file_sizes_gt, UINT64_MAX, UINT64_MAX, 300);
+      tcounter_src, &g_json_file_sizes_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
@@ -1403,7 +2450,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_token_decoder(
       wuffs_json_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_src, &json_australian_abc_gt, UINT64_MAX, UINT64_MAX, 250);
+      tcounter_src, &g_json_australian_abc_gt, UINT64_MAX, UINT64_MAX, 250);
 }
 
 const char*  //
@@ -1411,7 +2458,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_token_decoder(
       wuffs_json_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_src, &json_nobel_prizes_gt, UINT64_MAX, UINT64_MAX, 25);
+      tcounter_src, &g_json_nobel_prizes_gt, UINT64_MAX, UINT64_MAX, 25);
 }
 
   // ---------------- Mimic Benches
@@ -1424,25 +2471,37 @@
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    // These strconv tests are really testing the Wuffs base library. They
-    // aren't specific to the std/json code, but putting them here is as good
-    // as any other place.
-    test_strconv_hpd_rounded_integer,  //
-    test_strconv_hpd_shift,            //
-    test_strconv_parse_number_f64,     //
-    test_strconv_parse_number_i64,     //
-    test_strconv_parse_number_u64,     //
-    test_strconv_utf_8_next,           //
+    // These core and strconv tests are really testing the Wuffs base library.
+    // They aren't specific to the std/json code, but putting them here is as
+    // good as any other place.
+    test_wuffs_core_count_leading_zeroes_u64,
+    test_wuffs_core_multiply_u64,
+    test_strconv_hexadecimal,
+    test_strconv_hpd_rounded_integer,
+    test_strconv_hpd_shift,
+    test_strconv_mpb_assign_from_hpd,
+    test_strconv_parse_number_f64,
+    test_strconv_parse_number_i64,
+    test_strconv_parse_number_u64,
+    test_strconv_utf_8_next,
 
-    test_wuffs_json_decode_interface,             //
-    test_wuffs_json_decode_long_numbers,          //
-    test_wuffs_json_decode_prior_valid_utf_8,     //
-    test_wuffs_json_decode_src_io_buffer_length,  //
-    test_wuffs_json_decode_string,                //
-    test_wuffs_json_decode_unicode4_escapes,      //
+    test_wuffs_json_decode_end_of_data,
+    test_wuffs_json_decode_interface,
+    test_wuffs_json_decode_long_numbers,
+    test_wuffs_json_decode_prior_valid_utf_8,
+    test_wuffs_json_decode_quirk_allow_backslash_etc,
+    test_wuffs_json_decode_quirk_allow_backslash_x,
+    test_wuffs_json_decode_quirk_allow_comment_etc,
+    test_wuffs_json_decode_quirk_allow_extra_comma,
+    test_wuffs_json_decode_quirk_allow_inf_nan_numbers,
+    test_wuffs_json_decode_quirk_allow_leading_etc,
+    test_wuffs_json_decode_quirk_allow_trailing_etc,
+    test_wuffs_json_decode_quirk_replace_invalid_unicode,
+    test_wuffs_json_decode_src_io_buffer_length,
+    test_wuffs_json_decode_string,
+    test_wuffs_json_decode_unicode4_escapes,
 
 #ifdef WUFFS_MIMIC
 
@@ -1453,13 +2512,17 @@
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_json_decode_1k,             //
-    bench_wuffs_json_decode_21k_formatted,  //
-    bench_wuffs_json_decode_26k_compact,    //
-    bench_wuffs_json_decode_217k_stringy,   //
+    bench_strconv_parse_number_f64_1_lsh53_add0,
+    bench_strconv_parse_number_f64_1_lsh53_add1,
+    bench_strconv_parse_number_f64_pi_long,
+    bench_strconv_parse_number_f64_pi_short,
+
+    bench_wuffs_json_decode_1k,
+    bench_wuffs_json_decode_21k_formatted,
+    bench_wuffs_json_decode_26k_compact,
+    bench_wuffs_json_decode_217k_stringy,
 
 #ifdef WUFFS_MIMIC
 
@@ -1472,6 +2535,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/json";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/json";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/lzw.c b/test/c/std/lzw.c
index afad397..53df1b8 100644
--- a/test/c/std/lzw.c
+++ b/test/c/std/lzw.c
@@ -87,13 +87,13 @@
                          uint64_t wlimit,
                          uint64_t rlimit) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
   CHECK_STRING(read_file(&src, src_filename));
@@ -130,7 +130,7 @@
     size_t old_ri = src.meta.ri;
 
     wuffs_base__status status = wuffs_lzw__decoder__transform_io(
-        &dec, &limited_have, &limited_src, global_work_slice);
+        &dec, &limited_have, &limited_src, g_work_slice_u8);
     have.meta.wi += limited_have.meta.wi;
     src.meta.ri += limited_src.meta.ri;
     if (wuffs_base__status__is_ok(&status)) {
@@ -215,10 +215,10 @@
   CHECK_FOCUS(__func__);
 
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
   // Set up src to be 20 bytes long, starting with three 8-bit literal codes
@@ -242,7 +242,7 @@
   wuffs_lzw__decoder__set_literal_width(&dec, 7);
 
   wuffs_base__status status =
-      wuffs_lzw__decoder__transform_io(&dec, &have, &src, global_work_slice);
+      wuffs_lzw__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
   if (status.repr != wuffs_lzw__error__bad_code) {
     RETURN_FAIL("transform_io: have \"%s\", want \"%s\"", status.repr,
                 wuffs_lzw__error__bad_code);
@@ -262,10 +262,10 @@
   CHECK_FOCUS(__func__);
 
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
   // Set up src to be 20 bytes long, starting with the 9-bit end code 0x101.
@@ -286,7 +286,7 @@
   wuffs_lzw__decoder__set_literal_width(&dec, 8);
 
   CHECK_STATUS("transform_io", wuffs_lzw__decoder__transform_io(
-                                   &dec, &have, &src, global_work_slice));
+                                   &dec, &have, &src, g_work_slice_u8));
 
   if (have.meta.wi != 0) {
     RETURN_FAIL("have.meta.wi: have %d, want 0", (int)(have.meta.wi));
@@ -309,10 +309,10 @@
   wuffs_lzw__decoder__set_literal_width(&dec, width);
 
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   CHECK_STATUS("transform_io", wuffs_lzw__decoder__transform_io(
-                                   &dec, &have, &src, global_work_slice));
+                                   &dec, &have, &src, g_work_slice_u8));
 
   return check_io_buffers_equal("", &have, &want);
 }
@@ -333,14 +333,14 @@
   // 0b...._..00_0..._....  0x000 Literal "0".
   // 0b...0_10.._...._....  0x010 End code.
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   src.meta.wi = 2;
   src.data.ptr[0] = 0x4D;
   src.data.ptr[1] = 0x08;
 
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
   want.meta.wi = 7;
   want.data.ptr[0] = 0x00;
@@ -364,14 +364,14 @@
   // 0b...._..10_0..._....  0x100 Back-ref "01".
   // 0b...0_11.._...._....  0x011 End code.
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   src.meta.wi = 2;
   src.data.ptr[0] = 0x12;
   src.data.ptr[1] = 0x0E;
 
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
   want.meta.wi = 4;
   want.data.ptr[0] = 0x00;
@@ -387,10 +387,10 @@
 const char*  //
 do_bench_wuffs_lzw_decode(const char* filename, uint64_t iters_unscaled) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
   CHECK_STRING(read_file(&src, filename));
@@ -406,7 +406,7 @@
   bench_start();
   uint64_t n_bytes = 0;
   uint64_t i;
-  uint64_t iters = iters_unscaled * flags.iterscale;
+  uint64_t iters = iters_unscaled * g_flags.iterscale;
   for (i = 0; i < iters; i++) {
     have.meta.wi = 0;
     src.meta.ri = 1;  // Skip the literal width.
@@ -416,7 +416,7 @@
                      &dec, sizeof dec, WUFFS_VERSION,
                      WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
     CHECK_STATUS("transform_io", wuffs_lzw__decoder__transform_io(
-                                     &dec, &have, &src, global_work_slice));
+                                     &dec, &have, &src, g_work_slice_u8));
     n_bytes += have.meta.wi;
   }
   bench_finish(iters, n_bytes);
@@ -437,34 +437,32 @@
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_lzw_decode_bricks_dither,            //
-    test_wuffs_lzw_decode_bricks_nodither,          //
-    test_wuffs_lzw_decode_interface,                //
-    test_wuffs_lzw_decode_many_big_reads,           //
-    test_wuffs_lzw_decode_many_small_writes_reads,  //
-    test_wuffs_lzw_decode_output_bad,               //
-    test_wuffs_lzw_decode_output_empty,             //
-    test_wuffs_lzw_decode_pi,                       //
-    test_wuffs_lzw_decode_width_0,                  //
-    test_wuffs_lzw_decode_width_1,                  //
+    test_wuffs_lzw_decode_bricks_dither,
+    test_wuffs_lzw_decode_bricks_nodither,
+    test_wuffs_lzw_decode_interface,
+    test_wuffs_lzw_decode_many_big_reads,
+    test_wuffs_lzw_decode_many_small_writes_reads,
+    test_wuffs_lzw_decode_output_bad,
+    test_wuffs_lzw_decode_output_empty,
+    test_wuffs_lzw_decode_pi,
+    test_wuffs_lzw_decode_width_0,
+    test_wuffs_lzw_decode_width_1,
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_lzw_decode_20k,   //
-    bench_wuffs_lzw_decode_100k,  //
+    bench_wuffs_lzw_decode_20k,
+    bench_wuffs_lzw_decode_100k,
 
     NULL,
 };
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/lzw";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/lzw";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/wbmp.c b/test/c/std/wbmp.c
index f7b718e..1678943 100644
--- a/test/c/std/wbmp.c
+++ b/test/c/std/wbmp.c
@@ -93,7 +93,7 @@
 
   wuffs_base__frame_config fc = ((wuffs_base__frame_config){});
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/hat.wbmp"));
   CHECK_STATUS("decode_frame_config #0",
@@ -123,7 +123,7 @@
 
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file(&src, "test/data/bricks-nodither.wbmp"));
   CHECK_STATUS("decode_image_config",
@@ -166,12 +166,11 @@
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_wbmp_decode_frame_config,  //
-    test_wuffs_wbmp_decode_image_config,  //
-    test_wuffs_wbmp_decode_interface,     //
+    test_wuffs_wbmp_decode_frame_config,
+    test_wuffs_wbmp_decode_image_config,
+    test_wuffs_wbmp_decode_interface,
 
 #ifdef WUFFS_MIMIC
 
@@ -182,8 +181,7 @@
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
 // No WBMP benches.
 
@@ -198,6 +196,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/wbmp";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/wbmp";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/std/zlib.c b/test/c/std/zlib.c
index 1721f4d..19ed404 100644
--- a/test/c/std/zlib.c
+++ b/test/c/std/zlib.c
@@ -71,26 +71,26 @@
 
 // ---------------- Golden Tests
 
-golden_test zlib_midsummer_gt = {
-    .want_filename = "test/data/midsummer.txt",      //
-    .src_filename = "test/data/midsummer.txt.zlib",  //
+golden_test g_zlib_midsummer_gt = {
+    .want_filename = "test/data/midsummer.txt",
+    .src_filename = "test/data/midsummer.txt.zlib",
 };
 
-golden_test zlib_pi_gt = {
-    .want_filename = "test/data/pi.txt",      //
-    .src_filename = "test/data/pi.txt.zlib",  //
+golden_test g_zlib_pi_gt = {
+    .want_filename = "test/data/pi.txt",
+    .src_filename = "test/data/pi.txt.zlib",
 };
 
 // This dictionary-using zlib-encoded data comes from
 // https://play.golang.org/p/Jh9Wyp6PLID, also mentioned in the RAC spec.
-const char* zlib_sheep_src_ptr =
+const char* g_zlib_sheep_src_ptr =
     "\x78\xf9\x0b\xe0\x02\x6e\x0a\x29\xcf\x87\x31\x01\x01\x00\x00\xff\xff\x18"
     "\x0c\x03\xa8";
-const size_t zlib_sheep_src_len = 21;
-const char* zlib_sheep_dict_ptr = " sheep.\n";
-const size_t zlib_sheep_dict_len = 8;
-const char* zlib_sheep_want_ptr = "Two sheep.\n";
-const size_t zlib_sheep_want_len = 11;
+const size_t g_zlib_sheep_src_len = 21;
+const char* g_zlib_sheep_dict_ptr = " sheep.\n";
+const size_t g_zlib_sheep_dict_len = 8;
+const char* g_zlib_sheep_want_ptr = "Two sheep.\n";
+const size_t g_zlib_sheep_want_len = 11;
 
 // ---------------- Zlib Tests
 
@@ -123,7 +123,7 @@
     wuffs_base__io_buffer limited_src = make_limited_reader(*src, rlimit);
 
     wuffs_base__status status = wuffs_zlib__decoder__transform_io(
-        &dec, &limited_dst, &limited_src, global_work_slice);
+        &dec, &limited_dst, &limited_src, g_work_slice_u8);
 
     dst->meta.wi += limited_dst.meta.wi;
     src->meta.ri += limited_src.meta.ri;
@@ -141,13 +141,13 @@
 const char*  //
 do_test_wuffs_zlib_checksum(bool ignore_checksum, uint32_t bad_checksum) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
-  CHECK_STRING(read_file(&src, zlib_midsummer_gt.src_filename));
+  CHECK_STRING(read_file(&src, g_zlib_midsummer_gt.src_filename));
   // Flip a bit in the zlib checksum, which is in the last 4 bytes of the file.
   if (src.meta.wi < 4) {
     RETURN_FAIL("source file was too short");
@@ -191,7 +191,7 @@
       wuffs_base__io_buffer limited_src = make_limited_reader(src, rlimit);
 
       wuffs_base__status have_z = wuffs_zlib__decoder__transform_io(
-          &dec, &have, &limited_src, global_work_slice);
+          &dec, &have, &limited_src, g_work_slice_u8);
       src.meta.ri += limited_src.meta.ri;
       if (have_z.repr != want_z) {
         RETURN_FAIL("end_limit=%d: have \"%s\", want \"%s\"", end_limit,
@@ -229,14 +229,14 @@
 const char*  //
 test_wuffs_zlib_decode_midsummer() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_zlib_decode, &zlib_midsummer_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_zlib_decode, &g_zlib_midsummer_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_wuffs_zlib_decode_pi() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(wuffs_zlib_decode, &zlib_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(wuffs_zlib_decode, &g_zlib_pi_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
@@ -244,10 +244,10 @@
 test_wuffs_zlib_decode_sheep() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src =
-      make_io_buffer_from_string(zlib_sheep_src_ptr, zlib_sheep_src_len);
+      make_io_buffer_from_string(g_zlib_sheep_src_ptr, g_zlib_sheep_src_len);
 
   wuffs_zlib__decoder dec;
   CHECK_STATUS("initialize", wuffs_zlib__decoder__initialize(
@@ -257,7 +257,7 @@
   int i;
   for (i = 0; i < 3; i++) {
     wuffs_base__status status =
-        wuffs_zlib__decoder__transform_io(&dec, &have, &src, global_work_slice);
+        wuffs_zlib__decoder__transform_io(&dec, &have, &src, g_work_slice_u8);
 
     if (status.repr != wuffs_zlib__note__dictionary_required) {
       RETURN_FAIL("transform_io (before dict): have \"%s\", want \"%s\"",
@@ -274,16 +274,16 @@
 
   wuffs_zlib__decoder__add_dictionary(
       &dec, ((wuffs_base__slice_u8){
-                .ptr = ((uint8_t*)(zlib_sheep_dict_ptr)),
-                .len = zlib_sheep_dict_len,
+                .ptr = ((uint8_t*)(g_zlib_sheep_dict_ptr)),
+                .len = g_zlib_sheep_dict_len,
             }));
 
   CHECK_STATUS(
       "transform_io (after dict)",
-      wuffs_zlib__decoder__transform_io(&dec, &have, &src, global_work_slice));
+      wuffs_zlib__decoder__transform_io(&dec, &have, &src, g_work_slice_u8));
 
   wuffs_base__io_buffer want =
-      make_io_buffer_from_string(zlib_sheep_want_ptr, zlib_sheep_want_len);
+      make_io_buffer_from_string(g_zlib_sheep_want_ptr, g_zlib_sheep_want_len);
   return check_io_buffers_equal("", &have, &want);
 }
 
@@ -294,14 +294,14 @@
 const char*  //
 test_mimic_zlib_decode_midsummer() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_zlib_decode, &zlib_midsummer_gt, UINT64_MAX,
+  return do_test_io_buffers(mimic_zlib_decode, &g_zlib_midsummer_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
 const char*  //
 test_mimic_zlib_decode_pi() {
   CHECK_FOCUS(__func__);
-  return do_test_io_buffers(mimic_zlib_decode, &zlib_pi_gt, UINT64_MAX,
+  return do_test_io_buffers(mimic_zlib_decode, &g_zlib_pi_gt, UINT64_MAX,
                             UINT64_MAX);
 }
 
@@ -309,20 +309,20 @@
 test_mimic_zlib_decode_sheep() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src =
-      make_io_buffer_from_string(zlib_sheep_src_ptr, zlib_sheep_src_len);
+      make_io_buffer_from_string(g_zlib_sheep_src_ptr, g_zlib_sheep_src_len);
   wuffs_base__slice_u8 dict = ((wuffs_base__slice_u8){
-      .ptr = ((uint8_t*)(zlib_sheep_dict_ptr)),
-      .len = zlib_sheep_dict_len,
+      .ptr = ((uint8_t*)(g_zlib_sheep_dict_ptr)),
+      .len = g_zlib_sheep_dict_len,
   });
   const char* status = mimic_zlib_decode_with_dictionary(&have, &src, dict);
   if (status) {
     return status;
   }
   wuffs_base__io_buffer want =
-      make_io_buffer_from_string(zlib_sheep_want_ptr, zlib_sheep_want_len);
+      make_io_buffer_from_string(g_zlib_sheep_want_ptr, g_zlib_sheep_want_len);
   return check_io_buffers_equal("", &have, &want);
 }
 
@@ -335,7 +335,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(
       wuffs_zlib_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_dst, &zlib_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+      tcounter_dst, &g_zlib_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
@@ -343,7 +343,7 @@
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(
       wuffs_zlib_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED,
-      tcounter_dst, &zlib_pi_gt, UINT64_MAX, UINT64_MAX, 30);
+      tcounter_dst, &g_zlib_pi_gt, UINT64_MAX, UINT64_MAX, 30);
 }
 
   // ---------------- Mimic Benches
@@ -354,13 +354,13 @@
 bench_mimic_zlib_decode_10k() {
   CHECK_FOCUS(__func__);
   return do_bench_io_buffers(mimic_zlib_decode, 0, tcounter_dst,
-                             &zlib_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
+                             &g_zlib_midsummer_gt, UINT64_MAX, UINT64_MAX, 300);
 }
 
 const char*  //
 bench_mimic_zlib_decode_100k() {
   CHECK_FOCUS(__func__);
-  return do_bench_io_buffers(mimic_zlib_decode, 0, tcounter_dst, &zlib_pi_gt,
+  return do_bench_io_buffers(mimic_zlib_decode, 0, tcounter_dst, &g_zlib_pi_gt,
                              UINT64_MAX, UINT64_MAX, 30);
 }
 
@@ -368,39 +368,37 @@
 
 // ---------------- Manifest
 
-// The empty comments forces clang-format to place one element per line.
-proc tests[] = {
+proc g_tests[] = {
 
-    test_wuffs_zlib_checksum_ignore,       //
-    test_wuffs_zlib_checksum_verify_bad0,  //
-    test_wuffs_zlib_checksum_verify_bad3,  //
-    test_wuffs_zlib_checksum_verify_good,  //
-    test_wuffs_zlib_decode_interface,      //
-    test_wuffs_zlib_decode_midsummer,      //
-    test_wuffs_zlib_decode_pi,             //
-    test_wuffs_zlib_decode_sheep,          //
+    test_wuffs_zlib_checksum_ignore,
+    test_wuffs_zlib_checksum_verify_bad0,
+    test_wuffs_zlib_checksum_verify_bad3,
+    test_wuffs_zlib_checksum_verify_good,
+    test_wuffs_zlib_decode_interface,
+    test_wuffs_zlib_decode_midsummer,
+    test_wuffs_zlib_decode_pi,
+    test_wuffs_zlib_decode_sheep,
 
 #ifdef WUFFS_MIMIC
 
-    test_mimic_zlib_decode_midsummer,  //
-    test_mimic_zlib_decode_pi,         //
-    test_mimic_zlib_decode_sheep,      //
+    test_mimic_zlib_decode_midsummer,
+    test_mimic_zlib_decode_pi,
+    test_mimic_zlib_decode_sheep,
 
 #endif  // WUFFS_MIMIC
 
     NULL,
 };
 
-// The empty comments forces clang-format to place one element per line.
-proc benches[] = {
+proc g_benches[] = {
 
-    bench_wuffs_zlib_decode_10k,   //
-    bench_wuffs_zlib_decode_100k,  //
+    bench_wuffs_zlib_decode_10k,
+    bench_wuffs_zlib_decode_100k,
 
 #ifdef WUFFS_MIMIC
 
-    bench_mimic_zlib_decode_10k,   //
-    bench_mimic_zlib_decode_100k,  //
+    bench_mimic_zlib_decode_10k,
+    bench_mimic_zlib_decode_100k,
 
 #endif  // WUFFS_MIMIC
 
@@ -409,6 +407,6 @@
 
 int  //
 main(int argc, char** argv) {
-  proc_package_name = "std/zlib";
-  return test_main(argc, argv, tests, benches);
+  g_proc_package_name = "std/zlib";
+  return test_main(argc, argv, g_tests, g_benches);
 }
diff --git a/test/c/testlib/testlib.c b/test/c/testlib/testlib.c
index 7a4ac1a..a815cfc 100644
--- a/test/c/testlib/testlib.c
+++ b/test/c/testlib/testlib.c
@@ -26,67 +26,68 @@
 
 #define WUFFS_TESTLIB_ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
-uint8_t global_have_array[IO_BUFFER_ARRAY_SIZE];
-uint8_t global_want_array[IO_BUFFER_ARRAY_SIZE];
-uint8_t global_work_array[IO_BUFFER_ARRAY_SIZE];
-uint8_t global_src_array[IO_BUFFER_ARRAY_SIZE];
+uint8_t g_have_array_u8[IO_BUFFER_ARRAY_SIZE];
+uint8_t g_want_array_u8[IO_BUFFER_ARRAY_SIZE];
+uint8_t g_work_array_u8[IO_BUFFER_ARRAY_SIZE];
+uint8_t g_src_array_u8[IO_BUFFER_ARRAY_SIZE];
 
-uint8_t global_pixel_array[PIXEL_BUFFER_ARRAY_SIZE];
+uint8_t g_pixel_array_u8[PIXEL_BUFFER_ARRAY_SIZE];
 
-wuffs_base__token global_have_token_array[TOKEN_BUFFER_ARRAY_SIZE];
-wuffs_base__token global_want_token_array[TOKEN_BUFFER_ARRAY_SIZE];
+wuffs_base__token g_have_array_token[TOKEN_BUFFER_ARRAY_SIZE];
+wuffs_base__token g_want_array_token[TOKEN_BUFFER_ARRAY_SIZE];
 
-wuffs_base__slice_u8 global_have_slice;
-wuffs_base__slice_u8 global_want_slice;
-wuffs_base__slice_u8 global_work_slice;
-wuffs_base__slice_u8 global_src_slice;
+wuffs_base__slice_u8 g_have_slice_u8;
+wuffs_base__slice_u8 g_want_slice_u8;
+wuffs_base__slice_u8 g_work_slice_u8;
+wuffs_base__slice_u8 g_src_slice_u8;
 
-wuffs_base__slice_u8 global_pixel_slice;
+wuffs_base__slice_u8 g_pixel_slice_u8;
 
-wuffs_base__slice_token global_have_token_slice;
-wuffs_base__slice_token global_want_token_slice;
+wuffs_base__slice_token g_have_slice_token;
+wuffs_base__slice_token g_want_slice_token;
 
-void wuffs_testlib__initialize_global_xxx_slices() {
-  global_have_slice = ((wuffs_base__slice_u8){
-      .ptr = global_have_array,
+void  //
+wuffs_testlib__initialize_global_xxx_slices() {
+  g_have_slice_u8 = ((wuffs_base__slice_u8){
+      .ptr = g_have_array_u8,
       .len = IO_BUFFER_ARRAY_SIZE,
   });
-  global_want_slice = ((wuffs_base__slice_u8){
-      .ptr = global_want_array,
+  g_want_slice_u8 = ((wuffs_base__slice_u8){
+      .ptr = g_want_array_u8,
       .len = IO_BUFFER_ARRAY_SIZE,
   });
-  global_work_slice = ((wuffs_base__slice_u8){
-      .ptr = global_work_array,
+  g_work_slice_u8 = ((wuffs_base__slice_u8){
+      .ptr = g_work_array_u8,
       .len = IO_BUFFER_ARRAY_SIZE,
   });
-  global_src_slice = ((wuffs_base__slice_u8){
-      .ptr = global_src_array,
+  g_src_slice_u8 = ((wuffs_base__slice_u8){
+      .ptr = g_src_array_u8,
       .len = IO_BUFFER_ARRAY_SIZE,
   });
-  global_pixel_slice = ((wuffs_base__slice_u8){
-      .ptr = global_pixel_array,
+  g_pixel_slice_u8 = ((wuffs_base__slice_u8){
+      .ptr = g_pixel_array_u8,
       .len = PIXEL_BUFFER_ARRAY_SIZE,
   });
 
-  global_have_token_slice = ((wuffs_base__slice_token){
-      .ptr = global_have_token_array,
+  g_have_slice_token = ((wuffs_base__slice_token){
+      .ptr = g_have_array_token,
       .len = TOKEN_BUFFER_ARRAY_SIZE,
   });
-  global_want_token_slice = ((wuffs_base__slice_token){
-      .ptr = global_want_token_array,
+  g_want_slice_token = ((wuffs_base__slice_token){
+      .ptr = g_want_array_token,
       .len = TOKEN_BUFFER_ARRAY_SIZE,
   });
 }
 
-char fail_msg[65536] = {0};
+char g_fail_msg[65536] = {0};
 
-#define RETURN_FAIL(...)                                            \
-  return (snprintf(fail_msg, sizeof(fail_msg), ##__VA_ARGS__) >= 0) \
-             ? fail_msg                                             \
+#define RETURN_FAIL(...)                                                \
+  return (snprintf(g_fail_msg, sizeof(g_fail_msg), ##__VA_ARGS__) >= 0) \
+             ? g_fail_msg                                               \
              : "unknown failure (snprintf-related)"
 
 #define INCR_FAIL(msg, ...) \
-  msg += snprintf(msg, sizeof(fail_msg) - (msg - fail_msg), ##__VA_ARGS__)
+  msg += snprintf(msg, sizeof(g_fail_msg) - (msg - g_fail_msg), ##__VA_ARGS__)
 
 #define CHECK_STATUS(prefix, status)             \
   do {                                           \
@@ -104,7 +105,7 @@
     }                        \
   } while (0)
 
-int tests_run = 0;
+int g_tests_run = 0;
 
 struct {
   int remaining_argc;
@@ -114,12 +115,12 @@
   const char* focus;
   uint64_t iterscale;
   int reps;
-} flags = {0};
+} g_flags = {0};
 
 const char*  //
 parse_flags(int argc, char** argv) {
-  flags.iterscale = 100;
-  flags.reps = 5;
+  g_flags.iterscale = 100;
+  g_flags.reps = 5;
 
   int c = (argc > 0) ? 1 : 0;  // Skip argv[0], the program name.
   for (; c < argc; c++) {
@@ -142,12 +143,12 @@
     }
 
     if (!strcmp(arg, "bench")) {
-      flags.bench = true;
+      g_flags.bench = true;
       continue;
     }
 
     if (!strncmp(arg, "focus=", 6)) {
-      flags.focus = arg + 6;
+      g_flags.focus = arg + 6;
       continue;
     }
 
@@ -164,7 +165,7 @@
       if ((n < 0) || (1000000 < n)) {
         return "out-of-range -iterscale=N value";
       }
-      flags.iterscale = n;
+      g_flags.iterscale = n;
       continue;
     }
 
@@ -181,36 +182,36 @@
       if ((n < 0) || (1000000 < n)) {
         return "out-of-range -reps=N value";
       }
-      flags.reps = n;
+      g_flags.reps = n;
       continue;
     }
 
     return "unrecognized flag argument";
   }
 
-  flags.remaining_argc = argc - c;
-  flags.remaining_argv = argv + c;
+  g_flags.remaining_argc = argc - c;
+  g_flags.remaining_argv = argv + c;
   return NULL;
 }
 
-const char* proc_package_name = "unknown_package_name";
-const char* proc_func_name = "unknown_func_name";
-bool in_focus = false;
+const char* g_proc_package_name = "unknown_package_name";
+const char* g_proc_func_name = "unknown_func_name";
+bool g_in_focus = false;
 
-#define CHECK_FOCUS(func_name) \
-  proc_func_name = func_name;  \
-  in_focus = check_focus();    \
-  if (!in_focus) {             \
-    return NULL;               \
+#define CHECK_FOCUS(func_name)  \
+  g_proc_func_name = func_name; \
+  g_in_focus = check_focus();   \
+  if (!g_in_focus) {            \
+    return NULL;                \
   }
 
 bool  //
 check_focus() {
-  const char* p = flags.focus;
+  const char* p = g_flags.focus;
   if (!p || !*p) {
     return true;
   }
-  size_t n = strlen(proc_func_name);
+  size_t n = strlen(g_proc_func_name);
 
   // On each iteration of the loop, set p and q so that p (inclusive) and q
   // (exclusive) bracket the interesting fragment of the comma-separated
@@ -246,18 +247,18 @@
         p += 9;
       }
 
-      // See if proc_func_name (with or without a "test_" or "bench_" prefix)
+      // See if g_proc_func_name (with or without a "test_" or "bench_" prefix)
       // starts with the [p, q) string.
-      if ((n >= q - p) && !strncmp(proc_func_name, p, q - p)) {
+      if ((n >= q - p) && !strncmp(g_proc_func_name, p, q - p)) {
         return true;
       }
       const char* unprefixed_proc_func_name = NULL;
       size_t unprefixed_n = 0;
-      if ((n >= q - p) && !strncmp(proc_func_name, "test_", 5)) {
-        unprefixed_proc_func_name = proc_func_name + 5;
+      if ((n >= q - p) && !strncmp(g_proc_func_name, "test_", 5)) {
+        unprefixed_proc_func_name = g_proc_func_name + 5;
         unprefixed_n = n - 5;
-      } else if ((n >= q - p) && !strncmp(proc_func_name, "bench_", 6)) {
-        unprefixed_proc_func_name = proc_func_name + 6;
+      } else if ((n >= q - p) && !strncmp(g_proc_func_name, "bench_", 6)) {
+        unprefixed_proc_func_name = g_proc_func_name + 6;
         unprefixed_n = n - 6;
       }
       if (unprefixed_proc_func_name && (unprefixed_n >= q - p) &&
@@ -280,17 +281,17 @@
 
 // The order matters here. Clang also defines "__GNUC__".
 #if defined(__clang__)
-const char* cc = "clang" WUFFS_TESTLIB_QUOTE(__clang_major__);
-const char* cc_version = __clang_version__;
+const char* g_cc = "clang" WUFFS_TESTLIB_QUOTE(__clang_major__);
+const char* g_cc_version = __clang_version__;
 #elif defined(__GNUC__)
-const char* cc = "gcc" WUFFS_TESTLIB_QUOTE(__GNUC__);
-const char* cc_version = __VERSION__;
+const char* g_cc = "gcc" WUFFS_TESTLIB_QUOTE(__GNUC__);
+const char* g_cc_version = __VERSION__;
 #elif defined(_MSC_VER)
-const char* cc = "cl";
-const char* cc_version = "???";
+const char* g_cc = "cl";
+const char* g_cc_version = "???";
 #else
-const char* cc = "cc";
-const char* cc_version = "???";
+const char* g_cc = "cc";
+const char* g_cc_version = "???";
 #endif
 
 typedef struct {
@@ -300,12 +301,12 @@
   size_t src_offset1;
 } golden_test;
 
-bool bench_warm_up;
-struct timeval bench_start_tv;
+bool g_bench_warm_up;
+struct timeval g_bench_start_tv;
 
 void  //
 bench_start() {
-  gettimeofday(&bench_start_tv, NULL);
+  gettimeofday(&g_bench_start_tv, NULL);
 }
 
 void  //
@@ -313,28 +314,28 @@
   struct timeval bench_finish_tv;
   gettimeofday(&bench_finish_tv, NULL);
   int64_t micros =
-      (int64_t)(bench_finish_tv.tv_sec - bench_start_tv.tv_sec) * 1000000 +
-      (int64_t)(bench_finish_tv.tv_usec - bench_start_tv.tv_usec);
+      (int64_t)(bench_finish_tv.tv_sec - g_bench_start_tv.tv_sec) * 1000000 +
+      (int64_t)(bench_finish_tv.tv_usec - g_bench_start_tv.tv_usec);
   uint64_t nanos = 1;
   if (micros > 0) {
     nanos = (uint64_t)(micros)*1000;
   }
   uint64_t kb_per_s = n_bytes * 1000000 / nanos;
 
-  const char* name = proc_func_name;
+  const char* name = g_proc_func_name;
   if ((strlen(name) >= 6) && !strncmp(name, "bench_", 6)) {
     name += 6;
   }
-  if (bench_warm_up) {
+  if (g_bench_warm_up) {
     printf("# (warm up) %s/%s\t%8" PRIu64 ".%06" PRIu64 " seconds\n",  //
-           name, cc, nanos / 1000000000, (nanos % 1000000000) / 1000);
+           name, g_cc, nanos / 1000000000, (nanos % 1000000000) / 1000);
   } else if (!n_bytes) {
     printf("Benchmark%s/%s\t%8" PRIu64 "\t%8" PRIu64 " ns/op\n",  //
-           name, cc, iters, nanos / iters);
+           name, g_cc, iters, nanos / iters);
   } else {
     printf("Benchmark%s/%s\t%8" PRIu64 "\t%8" PRIu64
-           " ns/op\t%8d.%03d MB/s\n",       //
-           name, cc, iters, nanos / iters,  //
+           " ns/op\t%8d.%03d MB/s\n",         //
+           name, g_cc, iters, nanos / iters,  //
            (int)(kb_per_s / 1000), (int)(kb_per_s % 1000));
   }
   // Flush stdout so that "wuffs bench | tee etc" still prints its numbers as
@@ -384,17 +385,18 @@
     fprintf(stderr, "%s\n", status);
     return 1;
   }
-  if (flags.remaining_argc > 0) {
+  if (g_flags.remaining_argc > 0) {
     fprintf(stderr, "unexpected (non-flag) argument\n");
     return 1;
   }
 
   int reps = 1;
   proc* procs = tests;
-  if (flags.bench) {
-    reps = flags.reps + 1;  // +1 for the warm up run.
+  if (g_flags.bench) {
+    reps = g_flags.reps + 1;  // +1 for the warm up run.
     procs = benches;
-    printf("# %s\n# %s version %s\n#\n", proc_package_name, cc, cc_version);
+    printf("# %s\n# %s version %s\n#\n", g_proc_package_name, g_cc,
+           g_cc_version);
     printf(
         "# The output format, including the \"Benchmark\" prefixes, is "
         "compatible with the\n"
@@ -405,33 +407,34 @@
 
   int i;
   for (i = 0; i < reps; i++) {
-    bench_warm_up = i == 0;
+    g_bench_warm_up = i == 0;
     proc* p;
     for (p = procs; *p; p++) {
-      proc_func_name = "unknown_func_name";
-      fail_msg[0] = 0;
-      in_focus = false;
+      g_proc_func_name = "unknown_func_name";
+      g_fail_msg[0] = 0;
+      g_in_focus = false;
       const char* status = (*p)();
-      if (!in_focus) {
+      if (!g_in_focus) {
         continue;
       }
       if (status) {
-        printf("%-16s%-8sFAIL %s: %s\n", proc_package_name, cc, proc_func_name,
-               status);
+        printf("%-16s%-8sFAIL %s: %s\n", g_proc_package_name, g_cc,
+               g_proc_func_name, status);
         return 1;
       }
       if (i == 0) {
-        tests_run++;
+        g_tests_run++;
       }
     }
     if (i != 0) {
       continue;
     }
-    if (flags.bench) {
+    if (g_flags.bench) {
       printf("# %d benchmarks, 1+%d reps per benchmark, iterscale=%d\n",
-             tests_run, flags.reps, (int)(flags.iterscale));
+             g_tests_run, g_flags.reps, (int)(g_flags.iterscale));
     } else {
-      printf("%-16s%-8sPASS (%d tests)\n", proc_package_name, cc, tests_run);
+      printf("%-16s%-8sPASS (%d tests)\n", g_proc_package_name, g_cc,
+             g_tests_run);
     }
   }
   return 0;
@@ -693,7 +696,7 @@
   if (!have || !want) {
     RETURN_FAIL("%sio_buffers_equal: NULL argument", prefix);
   }
-  char* msg = fail_msg;
+  char* msg = g_fail_msg;
   size_t i;
   size_t n = have->meta.wi < want->meta.wi ? have->meta.wi : want->meta.wi;
   for (i = 0; i < n; i++) {
@@ -713,7 +716,7 @@
   msg = hex_dump(msg, have, i);
   INCR_FAIL(msg, "excerpts of have (above) versus want (below):\n");
   msg = hex_dump(msg, want, i);
-  return fail_msg;
+  return g_fail_msg;
 }
 
 // throughput_counter is whether to count dst or src bytes, or neither, when
@@ -748,13 +751,13 @@
   }
 
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
 
   if (!gt->src_filename) {
@@ -837,10 +840,10 @@
   }
 
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   wuffs_base__token_buffer have = ((wuffs_base__token_buffer){
-      .data = global_have_token_slice,
+      .data = g_have_slice_token,
   });
 
   if (!gt->src_filename) {
@@ -905,7 +908,7 @@
                     uint64_t rlimit,
                     uint64_t iters_unscaled) {
   return proc_io_buffers(codec_func, wuffs_initialize_flags, tcounter, gt,
-                         wlimit, rlimit, iters_unscaled * flags.iterscale,
+                         wlimit, rlimit, iters_unscaled * g_flags.iterscale,
                          true);
 }
 
@@ -922,7 +925,7 @@
                        uint64_t rlimit,
                        uint64_t iters_unscaled) {
   return proc_token_decoder(codec_func, wuffs_initialize_flags, tcounter, gt,
-                            wlimit, rlimit, iters_unscaled * flags.iterscale,
+                            wlimit, rlimit, iters_unscaled * g_flags.iterscale,
                             true);
 }
 
@@ -949,7 +952,7 @@
                                 size_t src_wi,
                                 uint32_t want) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file_fragment(&src, src_filename, src_ri, src_wi));
   uint32_t have = wuffs_base__hasher_u32__update_u32(
@@ -970,7 +973,7 @@
                                           size_t src_wi,
                                           uint64_t want_num_frames) {
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file_fragment(&src, src_filename, src_ri, src_wi));
 
@@ -1008,7 +1011,7 @@
 
   wuffs_base__image_config ic = ((wuffs_base__image_config){});
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file_fragment(&src, src_filename, src_ri, src_wi));
   CHECK_STATUS("decode_image_config",
@@ -1030,10 +1033,10 @@
 
   wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
   CHECK_STATUS("set_from_slice", wuffs_base__pixel_buffer__set_from_slice(
-                                     &pb, &ic.pixcfg, global_pixel_slice));
+                                     &pb, &ic.pixcfg, g_pixel_slice_u8));
   CHECK_STATUS("decode_frame", wuffs_base__image_decoder__decode_frame(
                                    b, &pb, &src, WUFFS_BASE__PIXEL_BLEND__SRC,
-                                   global_work_slice, NULL));
+                                   g_work_slice_u8, NULL));
 
   uint64_t n = wuffs_base__pixel_config__pixbuf_len(&ic.pixcfg);
   if (n < 4) {
@@ -1042,7 +1045,7 @@
     RETURN_FAIL("pixbuf_len too large");
   } else {
     wuffs_base__color_u32_argb_premul have_final_pixel =
-        wuffs_base__load_u32le__no_bounds_check(&global_pixel_array[n - 4]);
+        wuffs_base__load_u32le__no_bounds_check(&g_pixel_array_u8[n - 4]);
     if (have_final_pixel != want_final_pixel) {
       RETURN_FAIL("final pixel: have 0x%08" PRIX32 ", want 0x%08" PRIX32,
                   have_final_pixel, want_final_pixel);
@@ -1081,14 +1084,14 @@
   }
 
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
   CHECK_STRING(read_file_fragment(&src, src_filename, src_ri, src_wi));
   CHECK_STATUS("transform_io", wuffs_base__io_transformer__transform_io(
-                                   b, &have, &src, global_work_slice));
+                                   b, &have, &src, g_work_slice_u8));
   if (have.meta.wi != want_wi) {
     RETURN_FAIL("dst wi: have %zu, want %zu", have.meta.wi, want_wi);
   }
@@ -1104,16 +1107,16 @@
 do_test__wuffs_base__token_decoder(wuffs_base__token_decoder* b,
                                    golden_test* gt) {
   wuffs_base__io_buffer have = ((wuffs_base__io_buffer){
-      .data = global_have_slice,
+      .data = g_have_slice_u8,
   });
   wuffs_base__io_buffer want = ((wuffs_base__io_buffer){
-      .data = global_want_slice,
+      .data = g_want_slice_u8,
   });
   wuffs_base__token_buffer tok = ((wuffs_base__token_buffer){
-      .data = global_have_token_slice,
+      .data = g_have_slice_token,
   });
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
-      .data = global_src_slice,
+      .data = g_src_slice_u8,
   });
 
   if (gt->src_filename) {
@@ -1124,8 +1127,8 @@
     src.meta.closed = true;
   }
 
-  CHECK_STATUS("decode_tokens",
-               wuffs_base__token_decoder__decode_tokens(b, &tok, &src));
+  CHECK_STATUS("decode_tokens", wuffs_base__token_decoder__decode_tokens(
+                                    b, &tok, &src, g_work_slice_u8));
 
   uint64_t pos = 0;
   while (tok.meta.ri < tok.meta.wi) {
diff --git a/test/data/json-quirks.json b/test/data/json-quirks.json
new file mode 100644
index 0000000..5d3a877
--- /dev/null
+++ b/test/data/json-quirks.json
@@ -0,0 +1,16 @@
+[
+	123,
+	nan,
+	+INFINITY,
+	"escaped \a\b\e\f\n\r\t\v\0\'\"\?\\\/ things",
+	{
+		"ABC\u0394E": // U+00000394 GREEK CAPITAL LETTER DELTA.
+		"mno\U0001F4A9q", /* U+0001F4A9 PILE OF POO. */
+		/* And now for some
+		 * invalid Unicode. */
+		"ABC\uD800E": // Unpaired surrogate.
+		"mno\U12345678q", // Out of range.
+	},
+	"w\x58\x59z",
+	"invÿlid UTF-8",
+]
diff --git a/test/data/json-quirks.tokens b/test/data/json-quirks.tokens
new file mode 100644
index 0000000..d8feab9
--- /dev/null
+++ b/test/data/json-quirks.tokens
Binary files differ