kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

trace.c (46195B)


      1 #include "trace.h"
      2 
      3 #include <stdio.h>
      4 #include <string.h>
      5 
      6 static int set_err(char* err, size_t errcap, const char* msg) {
      7   if (err && errcap) snprintf(err, errcap, "%s", msg);
      8   return BUILD_ERR;
      9 }
     10 
     11 static int emit_bytes(KitWriter* out, const char* s) {
     12   return kit_writer_write(out, s, strlen(s)) == KIT_OK ? BUILD_OK : BUILD_ERR;
     13 }
     14 
     15 static void hex_encode(char out[BUILD_HEX_LEN],
     16                        const uint8_t in[BUILD_HASH_LEN]) {
     17   size_t i;
     18   for (i = 0; i < BUILD_HASH_LEN; ++i) {
     19     unsigned hi = (unsigned)(in[i] >> 4);
     20     unsigned lo = (unsigned)(in[i] & 0x0fu);
     21     out[2u * i] = (char)(hi < 10u ? '0' + hi : 'a' + (hi - 10u));
     22     out[2u * i + 1u] = (char)(lo < 10u ? '0' + lo : 'a' + (lo - 10u));
     23   }
     24   out[2u * BUILD_HASH_LEN] = '\0';
     25 }
     26 
     27 static int hex_val(char c, unsigned* out) {
     28   if (c >= '0' && c <= '9') {
     29     *out = (unsigned)(c - '0');
     30     return BUILD_OK;
     31   }
     32   if (c >= 'a' && c <= 'f') {
     33     *out = (unsigned)(c - 'a') + 10u;
     34     return BUILD_OK;
     35   }
     36   return BUILD_ERR;
     37 }
     38 
     39 static int hex_decode_strict(const char* s, uint8_t out[BUILD_HASH_LEN]) {
     40   size_t i;
     41   if (!s || strlen(s) != 2u * BUILD_HASH_LEN) return BUILD_ERR;
     42   for (i = 0; i < BUILD_HASH_LEN; ++i) {
     43     unsigned hi, lo;
     44     if (hex_val(s[2u * i], &hi) != BUILD_OK) return BUILD_ERR;
     45     if (hex_val(s[2u * i + 1u], &lo) != BUILD_OK) return BUILD_ERR;
     46     out[i] = (uint8_t)((hi << 4) | lo);
     47   }
     48   return BUILD_OK;
     49 }
     50 
     51 static int is_token_char(unsigned char c) {
     52   return c > 0x20u && c < 0x7fu;
     53 }
     54 
     55 static int valid_token(const char* s, size_t cap) {
     56   size_t i;
     57   if (!s || !s[0]) return 0;
     58   for (i = 0; s[i]; ++i) {
     59     if (i + 1u >= cap) return 0;
     60     if (!is_token_char((unsigned char)s[i])) return 0;
     61   }
     62   return 1;
     63 }
     64 
     65 static int valid_target(const char* s) { return valid_token(s, BUILD_TARGET_MAX); }
     66 
     67 static int valid_key(const char* s) { return valid_token(s, BUILD_KEY_MAX); }
     68 
     69 static int valid_path(const char* s) { return valid_token(s, BUILD_PATH_MAX); }
     70 
     71 static int valid_pattern(const char* s) {
     72   return valid_token(s, BUILD_PATTERN_MAX);
     73 }
     74 
     75 static int copy_field(char* dst, size_t cap, const char* src, char* err,
     76                       size_t errcap) {
     77   if (!valid_token(src, cap)) return set_err(err, errcap, "bad field value");
     78   snprintf(dst, cap, "%s", src);
     79   return BUILD_OK;
     80 }
     81 
     82 static int emit_kv(KitWriter* out, const char* key,
     83                    const uint8_t h[BUILD_HASH_LEN]) {
     84   char hex[BUILD_HEX_LEN];
     85   char line[96];
     86   hex_encode(hex, h);
     87   snprintf(line, sizeof line, "%s %s\n", key, hex);
     88   return emit_bytes(out, line);
     89 }
     90 
     91 static int emit_text_kv(KitWriter* out, const char* key, const char* val) {
     92   char line[BUILD_TARGET_MAX + 32u];
     93   snprintf(line, sizeof line, "%s %s\n", key, val);
     94   return emit_bytes(out, line);
     95 }
     96 
     97 static int id_cmp(const uint8_t a[BUILD_HASH_LEN],
     98                   const uint8_t b[BUILD_HASH_LEN]) {
     99   return memcmp(a, b, BUILD_HASH_LEN);
    100 }
    101 
    102 static int source_cmp(const BuildSourceLeaf* a, const BuildSourceLeaf* b) {
    103   return strcmp(a->path, b->path);
    104 }
    105 
    106 static int glob_cmp(const BuildGlobLeaf* a, const BuildGlobLeaf* b) {
    107   return strcmp(a->pattern, b->pattern);
    108 }
    109 
    110 static int blob_cmp(const BuildBlobLeaf* a, const BuildBlobLeaf* b) {
    111   return id_cmp(a->blob, b->blob);
    112 }
    113 
    114 static int config_cmp(const BuildConfigLeaf* a, const BuildConfigLeaf* b) {
    115   int c = strcmp(a->key, b->key);
    116   if (c != 0) return c;
    117   if (a->present != b->present) return a->present < b->present ? -1 : 1;
    118   if (a->has_default != b->has_default)
    119     return a->has_default < b->has_default ? -1 : 1;
    120   c = id_cmp(a->value_hash, b->value_hash);
    121   if (c != 0) return c;
    122   return id_cmp(a->default_hash, b->default_hash);
    123 }
    124 
    125 static int dep_cmp(const BuildDepEdge* a, const BuildDepEdge* b) {
    126   int c = strcmp(a->name, b->name);
    127   if (c != 0) return c;
    128   c = id_cmp(a->overlay_id, b->overlay_id);
    129   if (c != 0) return c;
    130   return id_cmp(a->argv_id, b->argv_id);
    131 }
    132 
    133 static int emit_section(KitWriter* out, const char* name) {
    134   char line[32];
    135   snprintf(line, sizeof line, "[%s]\n", name);
    136   return emit_bytes(out, line);
    137 }
    138 
    139 static int emit_hash_or_dash(KitWriter* out, int has_hash,
    140                              const uint8_t h[BUILD_HASH_LEN]) {
    141   char hex[BUILD_HEX_LEN];
    142   if (!has_hash) return emit_bytes(out, "-");
    143   hex_encode(hex, h);
    144   return emit_bytes(out, hex);
    145 }
    146 
    147 static int emit_config_row(KitWriter* out, const BuildConfigLeaf* row) {
    148   if (emit_bytes(out, row->key) != BUILD_OK) return BUILD_ERR;
    149   if (emit_bytes(out, row->present ? " present " : " unset ") != BUILD_OK)
    150     return BUILD_ERR;
    151   if (emit_hash_or_dash(out, row->present || row->has_default,
    152                         row->value_hash) != BUILD_OK)
    153     return BUILD_ERR;
    154   if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR;
    155   if (emit_hash_or_dash(out, row->has_default, row->default_hash) != BUILD_OK)
    156     return BUILD_ERR;
    157   return emit_bytes(out, "\n");
    158 }
    159 
    160 static int emit_sorted_configs(const BuildConfigLeaf* rows, size_t n,
    161                                KitWriter* out, char* err, size_t errcap) {
    162   const BuildConfigLeaf* prev = NULL;
    163   size_t emitted = 0;
    164   if (n && !rows) return set_err(err, errcap, "missing config rows");
    165   if (emit_section(out, "config") != BUILD_OK) return BUILD_ERR;
    166   while (emitted < n) {
    167     const BuildConfigLeaf* best = NULL;
    168     size_t i;
    169     for (i = 0; i < n; ++i) {
    170       const BuildConfigLeaf* cur = &rows[i];
    171       int after_prev;
    172       if (!valid_key(cur->key))
    173         return set_err(err, errcap, "bad config key");
    174       if ((cur->present != 0 && cur->present != 1) ||
    175           (cur->has_default != 0 && cur->has_default != 1))
    176         return set_err(err, errcap, "bad config flags");
    177       after_prev = !prev || config_cmp(prev, cur) < 0;
    178       if (after_prev && (!best || config_cmp(cur, best) < 0)) best = cur;
    179     }
    180     if (!best) return set_err(err, errcap, "duplicate config key");
    181     if (emit_config_row(out, best) != BUILD_OK) return BUILD_ERR;
    182     prev = best;
    183     ++emitted;
    184   }
    185   return BUILD_OK;
    186 }
    187 
    188 static int emit_source_row(KitWriter* out, const BuildSourceLeaf* row) {
    189   char hex[BUILD_HEX_LEN];
    190   if (emit_bytes(out, row->path) != BUILD_OK) return BUILD_ERR;
    191   if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR;
    192   if (row->absent) {
    193     if (emit_bytes(out, "-") != BUILD_OK) return BUILD_ERR;
    194   } else {
    195     hex_encode(hex, row->blob);
    196     if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR;
    197   }
    198   return emit_bytes(out, "\n");
    199 }
    200 
    201 static int emit_sorted_sources(const BuildSourceLeaf* rows, size_t n,
    202                                KitWriter* out, char* err, size_t errcap) {
    203   const BuildSourceLeaf* prev = NULL;
    204   size_t emitted = 0;
    205   if (n && !rows) return set_err(err, errcap, "missing source rows");
    206   if (emit_section(out, "source") != BUILD_OK) return BUILD_ERR;
    207   while (emitted < n) {
    208     const BuildSourceLeaf* best = NULL;
    209     size_t i;
    210     for (i = 0; i < n; ++i) {
    211       const BuildSourceLeaf* cur = &rows[i];
    212       int after_prev;
    213       if (!valid_path(cur->path)) return set_err(err, errcap, "bad source path");
    214       if (cur->absent != 0 && cur->absent != 1)
    215         return set_err(err, errcap, "bad source absent flag");
    216       after_prev = !prev || source_cmp(prev, cur) < 0;
    217       if (after_prev && (!best || source_cmp(cur, best) < 0)) best = cur;
    218     }
    219     if (!best) return set_err(err, errcap, "duplicate source path");
    220     if (emit_source_row(out, best) != BUILD_OK) return BUILD_ERR;
    221     prev = best;
    222     ++emitted;
    223   }
    224   return BUILD_OK;
    225 }
    226 
    227 static int emit_glob_row(KitWriter* out, const BuildGlobLeaf* row) {
    228   char hex[BUILD_HEX_LEN];
    229   hex_encode(hex, row->result_hash);
    230   if (emit_bytes(out, row->pattern) != BUILD_OK) return BUILD_ERR;
    231   if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR;
    232   if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR;
    233   return emit_bytes(out, "\n");
    234 }
    235 
    236 static int emit_sorted_globs(const BuildGlobLeaf* rows, size_t n, KitWriter* out,
    237                              char* err, size_t errcap) {
    238   const BuildGlobLeaf* prev = NULL;
    239   size_t emitted = 0;
    240   if (n && !rows) return set_err(err, errcap, "missing glob rows");
    241   if (emit_section(out, "glob") != BUILD_OK) return BUILD_ERR;
    242   while (emitted < n) {
    243     const BuildGlobLeaf* best = NULL;
    244     size_t i;
    245     for (i = 0; i < n; ++i) {
    246       const BuildGlobLeaf* cur = &rows[i];
    247       int after_prev;
    248       if (!valid_pattern(cur->pattern))
    249         return set_err(err, errcap, "bad glob pattern");
    250       after_prev = !prev || glob_cmp(prev, cur) < 0;
    251       if (after_prev && (!best || glob_cmp(cur, best) < 0)) best = cur;
    252     }
    253     if (!best) return set_err(err, errcap, "duplicate glob pattern");
    254     if (emit_glob_row(out, best) != BUILD_OK) return BUILD_ERR;
    255     prev = best;
    256     ++emitted;
    257   }
    258   return BUILD_OK;
    259 }
    260 
    261 static int emit_blob_row(KitWriter* out, const BuildBlobLeaf* row) {
    262   char hex[BUILD_HEX_LEN];
    263   hex_encode(hex, row->blob);
    264   if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR;
    265   return emit_bytes(out, "\n");
    266 }
    267 
    268 static int emit_sorted_blobs(const BuildBlobLeaf* rows, size_t n,
    269                                KitWriter* out, char* err, size_t errcap) {
    270   const BuildBlobLeaf* prev = NULL;
    271   size_t emitted = 0;
    272   if (n && !rows) return set_err(err, errcap, "missing blob rows");
    273   if (emit_section(out, "blob") != BUILD_OK) return BUILD_ERR;
    274   while (emitted < n) {
    275     const BuildBlobLeaf* best = NULL;
    276     size_t i;
    277     for (i = 0; i < n; ++i) {
    278       const BuildBlobLeaf* cur = &rows[i];
    279       int after_prev = !prev || blob_cmp(prev, cur) < 0;
    280       if (after_prev && (!best || blob_cmp(cur, best) < 0)) best = cur;
    281     }
    282     if (!best) return set_err(err, errcap, "duplicate blob row");
    283     if (emit_blob_row(out, best) != BUILD_OK) return BUILD_ERR;
    284     prev = best;
    285     ++emitted;
    286   }
    287   return BUILD_OK;
    288 }
    289 
    290 static int emit_dep_row(KitWriter* out, const BuildDepEdge* row) {
    291   char ovr[BUILD_HEX_LEN], argv[BUILD_HEX_LEN], tree[BUILD_HEX_LEN];
    292   hex_encode(ovr, row->overlay_id);
    293   hex_encode(argv, row->argv_id);
    294   hex_encode(tree, row->output_tree);
    295   if (emit_bytes(out, row->name) != BUILD_OK) return BUILD_ERR;
    296   if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR;
    297   if (emit_bytes(out, ovr) != BUILD_OK) return BUILD_ERR;
    298   if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR;
    299   if (emit_bytes(out, argv) != BUILD_OK) return BUILD_ERR;
    300   if (emit_bytes(out, " ") != BUILD_OK) return BUILD_ERR;
    301   if (emit_bytes(out, tree) != BUILD_OK) return BUILD_ERR;
    302   return emit_bytes(out, "\n");
    303 }
    304 
    305 static int emit_sorted_deps(const BuildDepEdge* rows, size_t n, KitWriter* out,
    306                             char* err, size_t errcap) {
    307   const BuildDepEdge* prev = NULL;
    308   size_t emitted = 0;
    309   if (n && !rows) return set_err(err, errcap, "missing dep rows");
    310   if (emit_section(out, "dep") != BUILD_OK) return BUILD_ERR;
    311   while (emitted < n) {
    312     const BuildDepEdge* best = NULL;
    313     size_t i;
    314     for (i = 0; i < n; ++i) {
    315       const BuildDepEdge* cur = &rows[i];
    316       int after_prev;
    317       if (!valid_target(cur->name)) return set_err(err, errcap, "bad dep name");
    318       after_prev = !prev || dep_cmp(prev, cur) < 0;
    319       if (after_prev && (!best || dep_cmp(cur, best) < 0)) best = cur;
    320     }
    321     if (!best) return set_err(err, errcap, "duplicate dep row");
    322     if (emit_dep_row(out, best) != BUILD_OK) return BUILD_ERR;
    323     prev = best;
    324     ++emitted;
    325   }
    326   return BUILD_OK;
    327 }
    328 
    329 static int emit_child_row(KitWriter* out, const uint8_t id[BUILD_HASH_LEN]) {
    330   char hex[BUILD_HEX_LEN];
    331   hex_encode(hex, id);
    332   if (emit_bytes(out, hex) != BUILD_OK) return BUILD_ERR;
    333   return emit_bytes(out, "\n");
    334 }
    335 
    336 /* Use a flat byte view here: strict C11 cannot add const through a
    337  * pointer-to-array conversion (that becomes well-defined only in C23). */
    338 static int emit_sorted_children(const uint8_t* rows, size_t n, KitWriter* out,
    339                                 char* err, size_t errcap) {
    340   const uint8_t* prev = NULL;
    341   size_t emitted = 0;
    342   if (n && !rows) return set_err(err, errcap, "missing child rows");
    343   if (emit_section(out, "child") != BUILD_OK) return BUILD_ERR;
    344   while (emitted < n) {
    345     const uint8_t* best = NULL;
    346     size_t i;
    347     for (i = 0; i < n; ++i) {
    348       const uint8_t* cur = rows + i * BUILD_HASH_LEN;
    349       int after_prev = !prev || id_cmp(prev, cur) < 0;
    350       if (after_prev && (!best || id_cmp(cur, best) < 0)) best = cur;
    351     }
    352     if (!best) return set_err(err, errcap, "duplicate child row");
    353     if (emit_child_row(out, best) != BUILD_OK) return BUILD_ERR;
    354     prev = best;
    355     ++emitted;
    356   }
    357   return BUILD_OK;
    358 }
    359 
    360 static int check_record_kind(uint8_t kind) {
    361   return kind == (uint8_t)BUILD_TRACE_DEEP ||
    362          kind == (uint8_t)BUILD_TRACE_SHALLOW;
    363 }
    364 
    365 static const char* record_kind_name(uint8_t kind) {
    366   if (kind == (uint8_t)BUILD_TRACE_DEEP) return "deep";
    367   if (kind == (uint8_t)BUILD_TRACE_SHALLOW) return "shallow";
    368   return NULL;
    369 }
    370 
    371 static int record_kind_parse(const char* s, uint8_t* out) {
    372   if (strcmp(s, "deep") == 0) {
    373     *out = (uint8_t)BUILD_TRACE_DEEP;
    374     return BUILD_OK;
    375   }
    376   if (strcmp(s, "shallow") == 0) {
    377     *out = (uint8_t)BUILD_TRACE_SHALLOW;
    378     return BUILD_OK;
    379   }
    380   return BUILD_ERR;
    381 }
    382 
    383 static int emit_record_rows(const BuildRecordRow* rows, size_t n, KitWriter* out,
    384                             char* err, size_t errcap) {
    385   size_t i, j;
    386   size_t deep = 0, shallow = 0;
    387   if (n && !rows) return set_err(err, errcap, "missing record rows");
    388   for (i = 0; i < n; ++i) {
    389     const char* kind = record_kind_name(rows[i].kind);
    390     char hex[BUILD_HEX_LEN];
    391     if (!kind) return set_err(err, errcap, "bad record kind");
    392     if (rows[i].kind == (uint8_t)BUILD_TRACE_DEEP) {
    393       if (++deep > KIT_BUILD_RECORD_CAP)
    394         return set_err(err, errcap, "too many deep records");
    395     } else {
    396       if (++shallow > KIT_BUILD_RECORD_CAP)
    397         return set_err(err, errcap, "too many shallow records");
    398     }
    399     for (j = 0; j < i; ++j) {
    400       if (rows[j].kind == rows[i].kind &&
    401           build_id_eq(rows[j].trace_id, rows[i].trace_id))
    402         return set_err(err, errcap, "duplicate record row");
    403     }
    404     hex_encode(hex, rows[i].trace_id);
    405     if (emit_text_kv(out, kind, hex) != BUILD_OK) return BUILD_ERR;
    406   }
    407   return BUILD_OK;
    408 }
    409 
    410 static int shallow_emit_like(const BuildShallowTrace* t, KitWriter* out,
    411                              char* err, size_t errcap, const char* magic,
    412                              const char* result_key) {
    413   if (!t || !out) return set_err(err, errcap, "missing shallow trace");
    414   if (!valid_target(t->target)) return set_err(err, errcap, "bad target");
    415   if (emit_bytes(out, magic) != BUILD_OK || emit_bytes(out, "\n") != BUILD_OK)
    416     return BUILD_ERR;
    417   if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR;
    418   if (emit_kv(out, "recipe", t->recipe) != BUILD_OK) return BUILD_ERR;
    419   if (emit_kv(out, result_key, t->output) != BUILD_OK) return BUILD_ERR;
    420   if (emit_kv(out, "argv", t->argv) != BUILD_OK) return BUILD_ERR;
    421   if (emit_sorted_configs(t->configs, t->n_configs, out, err, errcap) !=
    422       BUILD_OK)
    423     return BUILD_ERR;
    424   if (emit_sorted_sources(t->sources, t->n_sources, out, err, errcap) !=
    425       BUILD_OK)
    426     return BUILD_ERR;
    427   if (emit_sorted_globs(t->globs, t->n_globs, out, err, errcap) != BUILD_OK)
    428     return BUILD_ERR;
    429   if (emit_sorted_blobs(t->blobs, t->n_blobs, out, err, errcap) !=
    430       BUILD_OK)
    431     return BUILD_ERR;
    432   if (emit_sorted_deps(t->deps, t->n_deps, out, err, errcap) != BUILD_OK)
    433     return BUILD_ERR;
    434   return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR;
    435 }
    436 
    437 int build_shallow_emit(const BuildShallowTrace* t, KitWriter* out, char* err,
    438                        size_t errcap) {
    439   return shallow_emit_like(t, out, err, errcap, BUILD_SHALLOW_MAGIC, "output");
    440 }
    441 
    442 int build_test_shallow_emit(const BuildShallowTrace* t, KitWriter* out,
    443                             char* err, size_t errcap) {
    444   return shallow_emit_like(t, out, err, errcap, BUILD_TEST_SHALLOW_MAGIC,
    445                            "result");
    446 }
    447 
    448 static int deep_emit_like(const BuildDeepTrace* t, KitWriter* out, char* err,
    449                           size_t errcap, const char* magic,
    450                           const char* result_key) {
    451   if (!t || !out) return set_err(err, errcap, "missing deep trace");
    452   if (!valid_target(t->target)) return set_err(err, errcap, "bad target");
    453   if (emit_bytes(out, magic) != BUILD_OK || emit_bytes(out, "\n") != BUILD_OK)
    454     return BUILD_ERR;
    455   if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR;
    456   if (emit_kv(out, "recipe", t->recipe) != BUILD_OK) return BUILD_ERR;
    457   if (emit_kv(out, result_key, t->output) != BUILD_OK) return BUILD_ERR;
    458   if (emit_kv(out, "argv", t->argv) != BUILD_OK) return BUILD_ERR;
    459   if (emit_kv(out, "deepset", t->deepset) != BUILD_OK) return BUILD_ERR;
    460   return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR;
    461 }
    462 
    463 int build_deep_emit(const BuildDeepTrace* t, KitWriter* out, char* err,
    464                     size_t errcap) {
    465   return deep_emit_like(t, out, err, errcap, BUILD_DEEP_MAGIC, "output");
    466 }
    467 
    468 int build_test_deep_emit(const BuildDeepTrace* t, KitWriter* out, char* err,
    469                          size_t errcap) {
    470   return deep_emit_like(t, out, err, errcap, BUILD_TEST_DEEP_MAGIC, "result");
    471 }
    472 
    473 int build_deepset_emit(const BuildDeepSet* t, KitWriter* out, char* err,
    474                        size_t errcap) {
    475   if (!t || !out) return set_err(err, errcap, "missing deepset");
    476   if (!valid_target(t->target)) return set_err(err, errcap, "bad target");
    477   if (emit_bytes(out, BUILD_DEEPSET_MAGIC "\n") != BUILD_OK) return BUILD_ERR;
    478   if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR;
    479   if (emit_kv(out, "recipe", t->recipe) != BUILD_OK) return BUILD_ERR;
    480   if (emit_sorted_configs(t->configs, t->n_configs, out, err, errcap) !=
    481       BUILD_OK)
    482     return BUILD_ERR;
    483   if (emit_sorted_sources(t->sources, t->n_sources, out, err, errcap) !=
    484       BUILD_OK)
    485     return BUILD_ERR;
    486   if (emit_sorted_globs(t->globs, t->n_globs, out, err, errcap) != BUILD_OK)
    487     return BUILD_ERR;
    488   if (emit_sorted_blobs(t->blobs, t->n_blobs, out, err, errcap) !=
    489       BUILD_OK)
    490     return BUILD_ERR;
    491   if (emit_sorted_children(t->children ? t->children[0] : NULL, t->n_children,
    492                            out, err, errcap) != BUILD_OK)
    493     return BUILD_ERR;
    494   return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR;
    495 }
    496 
    497 int build_record_emit(const BuildTargetRecord* t, KitWriter* out, char* err,
    498                       size_t errcap) {
    499   if (!t || !out) return set_err(err, errcap, "missing target record");
    500   if (!valid_target(t->target)) return set_err(err, errcap, "bad target");
    501   if (emit_bytes(out, BUILD_RECORD_MAGIC "\n") != BUILD_OK) return BUILD_ERR;
    502   if (emit_text_kv(out, "target", t->target) != BUILD_OK) return BUILD_ERR;
    503   if (emit_record_rows(t->rows, t->n_rows, out, err, errcap) != BUILD_OK)
    504     return BUILD_ERR;
    505   return kit_writer_status(out) == KIT_OK ? BUILD_OK : BUILD_ERR;
    506 }
    507 
    508 typedef enum TraceSection {
    509   TRACE_SEC_TOP = 0,
    510   TRACE_SEC_CONFIG,
    511   TRACE_SEC_SOURCE,
    512   TRACE_SEC_GLOB,
    513   TRACE_SEC_BLOB,
    514   TRACE_SEC_DEP,
    515   TRACE_SEC_CHILD,
    516   TRACE_SEC_RECORD_ROWS
    517 } TraceSection;
    518 
    519 typedef struct TraceParser {
    520   const uint8_t* data;
    521   size_t len;
    522   size_t pos;
    523   int first;
    524   char line[BUILD_PATH_MAX + 5u * BUILD_HEX_LEN + BUILD_TARGET_MAX + 16u];
    525 } TraceParser;
    526 
    527 static int parser_next(TraceParser* p, char** line, char* err, size_t errcap) {
    528   size_t end, n, i;
    529   if (p->pos >= p->len) return 0;
    530   end = p->pos;
    531   while (end < p->len && p->data[end] != '\n') ++end;
    532   if (end == p->len) {
    533     set_err(err, errcap, "missing final newline");
    534     return -1;
    535   }
    536   n = end - p->pos;
    537   if (n >= sizeof p->line) {
    538     set_err(err, errcap, "line too long");
    539     return -1;
    540   }
    541   for (i = p->pos; i < end; ++i) {
    542     if (p->data[i] == 0 || p->data[i] == '\r') {
    543       set_err(err, errcap, "bad byte in trace");
    544       return -1;
    545     }
    546   }
    547   memcpy(p->line, p->data + p->pos, n);
    548   p->line[n] = '\0';
    549   p->pos = end + 1u;
    550   *line = p->line;
    551   return 1;
    552 }
    553 
    554 static int split_line(char* line, char** fields, size_t cap, size_t* nout) {
    555   char* p = line;
    556   size_t n = 0;
    557   if (!line || !line[0]) return BUILD_ERR;
    558   while (*p) {
    559     if (*p == ' ') return BUILD_ERR;
    560     if (n >= cap) return BUILD_ERR;
    561     fields[n++] = p;
    562     while (*p && *p != ' ') {
    563       if (!is_token_char((unsigned char)*p)) return BUILD_ERR;
    564       ++p;
    565     }
    566     if (*p == ' ') {
    567       *p++ = '\0';
    568       if (!*p) return BUILD_ERR;
    569     }
    570   }
    571   *nout = n;
    572   return BUILD_OK;
    573 }
    574 
    575 static int expect_field_count(size_t got, size_t want, char* err,
    576                               size_t errcap) {
    577   if (got != want) return set_err(err, errcap, "bad trace row");
    578   return BUILD_OK;
    579 }
    580 
    581 static int parse_top_text(char** fields, size_t n, const char* key, char* dst,
    582                           size_t cap, uint32_t* seen, uint32_t flag, char* err,
    583                           size_t errcap) {
    584   if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR;
    585   if (strcmp(fields[0], key) != 0) return set_err(err, errcap, "bad field order");
    586   if (*seen & flag) return set_err(err, errcap, "duplicate field");
    587   if (copy_field(dst, cap, fields[1], err, errcap) != BUILD_OK) return BUILD_ERR;
    588   *seen |= flag;
    589   return BUILD_OK;
    590 }
    591 
    592 static int parse_top_hash(char** fields, size_t n, const char* key,
    593                           uint8_t dst[BUILD_HASH_LEN], uint32_t* seen,
    594                           uint32_t flag, char* err, size_t errcap) {
    595   if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR;
    596   if (strcmp(fields[0], key) != 0) return set_err(err, errcap, "bad field order");
    597   if (*seen & flag) return set_err(err, errcap, "duplicate field");
    598   if (hex_decode_strict(fields[1], dst) != BUILD_OK)
    599     return set_err(err, errcap, "bad hash");
    600   *seen |= flag;
    601   return BUILD_OK;
    602 }
    603 
    604 static int parse_hash_or_dash(const char* s, int has_hash,
    605                               uint8_t out[BUILD_HASH_LEN], char* err,
    606                               size_t errcap) {
    607   if (!has_hash) {
    608     if (strcmp(s, "-") != 0) return set_err(err, errcap, "bad config hash");
    609     memset(out, 0, BUILD_HASH_LEN);
    610     return BUILD_OK;
    611   }
    612   if (hex_decode_strict(s, out) != BUILD_OK)
    613     return set_err(err, errcap, "bad config hash");
    614   return BUILD_OK;
    615 }
    616 
    617 static int parse_config_leaf(char** fields, size_t n, BuildConfigLeaf* row,
    618                              char* err, size_t errcap) {
    619   if (expect_field_count(n, 4u, err, errcap) != BUILD_OK) return BUILD_ERR;
    620   if (!valid_key(fields[0])) return set_err(err, errcap, "bad config key");
    621   snprintf(row->key, sizeof row->key, "%s", fields[0]);
    622   if (strcmp(fields[1], "present") == 0) {
    623     row->present = 1;
    624   } else if (strcmp(fields[1], "unset") == 0) {
    625     row->present = 0;
    626   } else {
    627     return set_err(err, errcap, "bad config presence");
    628   }
    629   row->has_default = strcmp(fields[3], "-") != 0;
    630   if (parse_hash_or_dash(fields[2], row->present || row->has_default,
    631                          row->value_hash, err, errcap) != BUILD_OK ||
    632       parse_hash_or_dash(fields[3], row->has_default, row->default_hash, err,
    633                          errcap) != BUILD_OK)
    634     return BUILD_ERR;
    635   if (!row->present && !row->has_default && strcmp(fields[2], "-") != 0)
    636     return set_err(err, errcap, "bad unset config value");
    637   if (!row->present && row->has_default &&
    638       !build_id_eq(row->value_hash, row->default_hash))
    639     return set_err(err, errcap, "bad default config value");
    640   return BUILD_OK;
    641 }
    642 
    643 static int append_shallow_config(BuildShallowTrace* out, char** fields,
    644                                  size_t n, char* err, size_t errcap) {
    645   BuildConfigLeaf* row;
    646   if (out->n_configs >= out->cap_configs)
    647     return set_err(err, errcap, "too many config rows");
    648   row = &out->configs[out->n_configs];
    649   if (parse_config_leaf(fields, n, row, err, errcap) != BUILD_OK)
    650     return BUILD_ERR;
    651   if (out->n_configs && config_cmp(&out->configs[out->n_configs - 1u], row) >= 0)
    652     return set_err(err, errcap, "non-canonical config rows");
    653   ++out->n_configs;
    654   return BUILD_OK;
    655 }
    656 
    657 static int append_deepset_config(BuildDeepSet* out, char** fields, size_t n,
    658                                  char* err, size_t errcap) {
    659   BuildConfigLeaf* row;
    660   if (out->n_configs >= out->cap_configs)
    661     return set_err(err, errcap, "too many config rows");
    662   row = &out->configs[out->n_configs];
    663   if (parse_config_leaf(fields, n, row, err, errcap) != BUILD_OK)
    664     return BUILD_ERR;
    665   if (out->n_configs && config_cmp(&out->configs[out->n_configs - 1u], row) >= 0)
    666     return set_err(err, errcap, "non-canonical config rows");
    667   ++out->n_configs;
    668   return BUILD_OK;
    669 }
    670 
    671 static int parse_source_leaf(char** fields, size_t n, BuildSourceLeaf* row,
    672                              char* err, size_t errcap) {
    673   if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR;
    674   if (!valid_path(fields[0])) return set_err(err, errcap, "bad source path");
    675   snprintf(row->path, sizeof row->path, "%s", fields[0]);
    676   if (strcmp(fields[1], "-") == 0) {
    677     memset(row->blob, 0, sizeof row->blob);
    678     row->absent = 1;
    679   } else {
    680     if (hex_decode_strict(fields[1], row->blob) != BUILD_OK)
    681       return set_err(err, errcap, "bad source hash");
    682     row->absent = 0;
    683   }
    684   return BUILD_OK;
    685 }
    686 
    687 static int append_shallow_source(BuildShallowTrace* out, char** fields, size_t n,
    688                                  char* err, size_t errcap) {
    689   BuildSourceLeaf* row;
    690   if (out->n_sources >= out->cap_sources)
    691     return set_err(err, errcap, "too many source rows");
    692   row = &out->sources[out->n_sources];
    693   if (parse_source_leaf(fields, n, row, err, errcap) != BUILD_OK)
    694     return BUILD_ERR;
    695   if (out->n_sources && source_cmp(&out->sources[out->n_sources - 1u], row) >= 0)
    696     return set_err(err, errcap, "non-canonical source rows");
    697   ++out->n_sources;
    698   return BUILD_OK;
    699 }
    700 
    701 static int append_deepset_source(BuildDeepSet* out, char** fields, size_t n,
    702                                  char* err, size_t errcap) {
    703   BuildSourceLeaf* row;
    704   if (out->n_sources >= out->cap_sources)
    705     return set_err(err, errcap, "too many source rows");
    706   row = &out->sources[out->n_sources];
    707   if (parse_source_leaf(fields, n, row, err, errcap) != BUILD_OK)
    708     return BUILD_ERR;
    709   if (out->n_sources && source_cmp(&out->sources[out->n_sources - 1u], row) >= 0)
    710     return set_err(err, errcap, "non-canonical source rows");
    711   ++out->n_sources;
    712   return BUILD_OK;
    713 }
    714 
    715 static int parse_glob_leaf(char** fields, size_t n, BuildGlobLeaf* row,
    716                            char* err, size_t errcap) {
    717   if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR;
    718   if (!valid_pattern(fields[0])) return set_err(err, errcap, "bad glob pattern");
    719   snprintf(row->pattern, sizeof row->pattern, "%s", fields[0]);
    720   if (hex_decode_strict(fields[1], row->result_hash) != BUILD_OK)
    721     return set_err(err, errcap, "bad glob hash");
    722   return BUILD_OK;
    723 }
    724 
    725 static int append_shallow_glob(BuildShallowTrace* out, char** fields, size_t n,
    726                                char* err, size_t errcap) {
    727   BuildGlobLeaf* row;
    728   if (out->n_globs >= out->cap_globs)
    729     return set_err(err, errcap, "too many glob rows");
    730   row = &out->globs[out->n_globs];
    731   if (parse_glob_leaf(fields, n, row, err, errcap) != BUILD_OK)
    732     return BUILD_ERR;
    733   if (out->n_globs && glob_cmp(&out->globs[out->n_globs - 1u], row) >= 0)
    734     return set_err(err, errcap, "non-canonical glob rows");
    735   ++out->n_globs;
    736   return BUILD_OK;
    737 }
    738 
    739 static int append_deepset_glob(BuildDeepSet* out, char** fields, size_t n,
    740                                char* err, size_t errcap) {
    741   BuildGlobLeaf* row;
    742   if (out->n_globs >= out->cap_globs)
    743     return set_err(err, errcap, "too many glob rows");
    744   row = &out->globs[out->n_globs];
    745   if (parse_glob_leaf(fields, n, row, err, errcap) != BUILD_OK)
    746     return BUILD_ERR;
    747   if (out->n_globs && glob_cmp(&out->globs[out->n_globs - 1u], row) >= 0)
    748     return set_err(err, errcap, "non-canonical glob rows");
    749   ++out->n_globs;
    750   return BUILD_OK;
    751 }
    752 
    753 static int parse_blob_leaf(char** fields, size_t n, BuildBlobLeaf* row,
    754                             char* err, size_t errcap) {
    755   if (expect_field_count(n, 1u, err, errcap) != BUILD_OK) return BUILD_ERR;
    756   if (hex_decode_strict(fields[0], row->blob) != BUILD_OK)
    757     return set_err(err, errcap, "bad blob hash");
    758   return BUILD_OK;
    759 }
    760 
    761 static int append_shallow_blob(BuildShallowTrace* out, char** fields, size_t n,
    762                                 char* err, size_t errcap) {
    763   BuildBlobLeaf* row;
    764   if (out->n_blobs >= out->cap_blobs)
    765     return set_err(err, errcap, "too many blob rows");
    766   row = &out->blobs[out->n_blobs];
    767   if (parse_blob_leaf(fields, n, row, err, errcap) != BUILD_OK)
    768     return BUILD_ERR;
    769   if (out->n_blobs && blob_cmp(&out->blobs[out->n_blobs - 1u], row) >= 0)
    770     return set_err(err, errcap, "non-canonical blob rows");
    771   ++out->n_blobs;
    772   return BUILD_OK;
    773 }
    774 
    775 static int append_deepset_blob(BuildDeepSet* out, char** fields, size_t n,
    776                                 char* err, size_t errcap) {
    777   BuildBlobLeaf* row;
    778   if (out->n_blobs >= out->cap_blobs)
    779     return set_err(err, errcap, "too many blob rows");
    780   row = &out->blobs[out->n_blobs];
    781   if (parse_blob_leaf(fields, n, row, err, errcap) != BUILD_OK)
    782     return BUILD_ERR;
    783   if (out->n_blobs && blob_cmp(&out->blobs[out->n_blobs - 1u], row) >= 0)
    784     return set_err(err, errcap, "non-canonical blob rows");
    785   ++out->n_blobs;
    786   return BUILD_OK;
    787 }
    788 
    789 static int append_dep(BuildShallowTrace* out, char** fields, size_t n, char* err,
    790                       size_t errcap) {
    791   BuildDepEdge* row;
    792   if (expect_field_count(n, 4u, err, errcap) != BUILD_OK) return BUILD_ERR;
    793   if (out->n_deps >= out->cap_deps)
    794     return set_err(err, errcap, "too many dep rows");
    795   if (!valid_target(fields[0])) return set_err(err, errcap, "bad dep target");
    796   row = &out->deps[out->n_deps];
    797   snprintf(row->name, sizeof row->name, "%s", fields[0]);
    798   if (hex_decode_strict(fields[1], row->overlay_id) != BUILD_OK ||
    799       hex_decode_strict(fields[2], row->argv_id) != BUILD_OK ||
    800       hex_decode_strict(fields[3], row->output_tree) != BUILD_OK)
    801     return set_err(err, errcap, "bad dep hash");
    802   if (out->n_deps && dep_cmp(&out->deps[out->n_deps - 1u], row) >= 0)
    803     return set_err(err, errcap, "non-canonical dep rows");
    804   ++out->n_deps;
    805   return BUILD_OK;
    806 }
    807 
    808 static int append_child(BuildDeepSet* out, char** fields, size_t n, char* err,
    809                         size_t errcap) {
    810   uint8_t* row;
    811   if (expect_field_count(n, 1u, err, errcap) != BUILD_OK) return BUILD_ERR;
    812   if (out->n_children >= out->cap_children)
    813     return set_err(err, errcap, "too many child rows");
    814   row = out->children[out->n_children];
    815   if (hex_decode_strict(fields[0], row) != BUILD_OK)
    816     return set_err(err, errcap, "bad child hash");
    817   if (out->n_children && id_cmp(out->children[out->n_children - 1u], row) >= 0)
    818     return set_err(err, errcap, "non-canonical child rows");
    819   ++out->n_children;
    820   return BUILD_OK;
    821 }
    822 
    823 static int append_record_row(BuildTargetRecord* out, char** fields, size_t n,
    824                              char* err, size_t errcap) {
    825   BuildRecordRow* row;
    826   size_t i;
    827   size_t same_kind = 0;
    828   if (expect_field_count(n, 2u, err, errcap) != BUILD_OK) return BUILD_ERR;
    829   if (out->n_rows >= out->cap_rows)
    830     return set_err(err, errcap, "too many record rows");
    831   row = &out->rows[out->n_rows];
    832   if (record_kind_parse(fields[0], &row->kind) != BUILD_OK)
    833     return set_err(err, errcap, "bad record kind");
    834   if (hex_decode_strict(fields[1], row->trace_id) != BUILD_OK)
    835     return set_err(err, errcap, "bad record hash");
    836   for (i = 0; i < out->n_rows; ++i) {
    837     if (out->rows[i].kind == row->kind) {
    838       ++same_kind;
    839       if (build_id_eq(out->rows[i].trace_id, row->trace_id))
    840         return set_err(err, errcap, "duplicate record row");
    841     }
    842   }
    843   if (same_kind >= KIT_BUILD_RECORD_CAP)
    844     return set_err(err, errcap, "too many record rows for kind");
    845   ++out->n_rows;
    846   return BUILD_OK;
    847 }
    848 
    849 #define F_TARGET 0x01u
    850 #define F_RECIPE 0x02u
    851 #define F_OUTPUT 0x04u
    852 #define F_ARGV 0x08u
    853 #define F_DEEPSET 0x10u
    854 
    855 static int shallow_parse_like(const uint8_t* data, size_t len,
    856                               BuildShallowTrace* out, char* err,
    857                               size_t errcap, const char* magic,
    858                               const char* result_key) {
    859   TraceParser p;
    860   TraceSection sec = TRACE_SEC_TOP;
    861   uint32_t seen = 0;
    862   if (!data || !out) return set_err(err, errcap, "missing shallow trace");
    863   if ((out->cap_configs && !out->configs) ||
    864       (out->cap_sources && !out->sources) || (out->cap_globs && !out->globs) ||
    865       (out->cap_blobs && !out->blobs) ||
    866       (out->cap_deps && !out->deps))
    867     return set_err(err, errcap, "missing trace storage");
    868   memset(out->target, 0, sizeof out->target);
    869   out->n_configs = 0;
    870   out->n_sources = 0;
    871   out->n_globs = 0;
    872   out->n_blobs = 0;
    873   out->n_deps = 0;
    874   memset(&p, 0, sizeof p);
    875   p.data = data;
    876   p.len = len;
    877   p.first = 1;
    878   for (;;) {
    879     char* line;
    880     char* fields[4];
    881     size_t n = 0;
    882     int r = parser_next(&p, &line, err, errcap);
    883     if (r < 0) return BUILD_ERR;
    884     if (r == 0) break;
    885     if (p.first) {
    886       p.first = 0;
    887       if (strcmp(line, magic) != 0)
    888         return set_err(err, errcap, "bad shallow magic/version");
    889       continue;
    890     }
    891     if (line[0] == '[') {
    892       if (strcmp(line, "[config]") == 0 && sec == TRACE_SEC_TOP) {
    893         if (seen != (F_TARGET | F_RECIPE | F_OUTPUT | F_ARGV))
    894           return set_err(err, errcap, "missing shallow field");
    895         sec = TRACE_SEC_CONFIG;
    896       } else if (strcmp(line, "[source]") == 0 && sec == TRACE_SEC_CONFIG) {
    897         sec = TRACE_SEC_SOURCE;
    898       } else if (strcmp(line, "[glob]") == 0 && sec == TRACE_SEC_SOURCE) {
    899         sec = TRACE_SEC_GLOB;
    900       } else if (strcmp(line, "[blob]") == 0 && sec == TRACE_SEC_GLOB) {
    901         sec = TRACE_SEC_BLOB;
    902       } else if (strcmp(line, "[dep]") == 0 &&
    903                  (sec == TRACE_SEC_GLOB || sec == TRACE_SEC_BLOB)) {
    904         sec = TRACE_SEC_DEP;
    905       } else {
    906         return set_err(err, errcap, "bad shallow section");
    907       }
    908       continue;
    909     }
    910     if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) !=
    911         BUILD_OK)
    912       return set_err(err, errcap, "bad shallow row");
    913     if (sec == TRACE_SEC_TOP) {
    914       if (!(seen & F_TARGET)) {
    915         if (parse_top_text(fields, n, "target", out->target, sizeof out->target,
    916                            &seen, F_TARGET, err, errcap) != BUILD_OK)
    917           return BUILD_ERR;
    918       } else if (!(seen & F_RECIPE)) {
    919         if (parse_top_hash(fields, n, "recipe", out->recipe, &seen, F_RECIPE,
    920                            err, errcap) != BUILD_OK)
    921           return BUILD_ERR;
    922       } else if (!(seen & F_OUTPUT)) {
    923         if (parse_top_hash(fields, n, result_key, out->output, &seen,
    924                            F_OUTPUT, err, errcap) != BUILD_OK)
    925           return BUILD_ERR;
    926       } else if (!(seen & F_ARGV)) {
    927         if (parse_top_hash(fields, n, "argv", out->argv, &seen, F_ARGV, err,
    928                            errcap) != BUILD_OK)
    929           return BUILD_ERR;
    930       } else {
    931         return set_err(err, errcap, "unexpected shallow field");
    932       }
    933     } else if (sec == TRACE_SEC_CONFIG) {
    934       if (append_shallow_config(out, fields, n, err, errcap) != BUILD_OK)
    935         return BUILD_ERR;
    936     } else if (sec == TRACE_SEC_SOURCE) {
    937       if (append_shallow_source(out, fields, n, err, errcap) != BUILD_OK)
    938         return BUILD_ERR;
    939     } else if (sec == TRACE_SEC_GLOB) {
    940       if (append_shallow_glob(out, fields, n, err, errcap) != BUILD_OK)
    941         return BUILD_ERR;
    942     } else if (sec == TRACE_SEC_BLOB) {
    943       if (append_shallow_blob(out, fields, n, err, errcap) != BUILD_OK)
    944         return BUILD_ERR;
    945     } else if (sec == TRACE_SEC_DEP) {
    946       if (append_dep(out, fields, n, err, errcap) != BUILD_OK) return BUILD_ERR;
    947     } else {
    948       return set_err(err, errcap, "bad shallow row");
    949     }
    950   }
    951   if (p.first) return set_err(err, errcap, "bad shallow magic/version");
    952   if (sec != TRACE_SEC_DEP) return set_err(err, errcap, "missing shallow section");
    953   return BUILD_OK;
    954 }
    955 
    956 int build_shallow_parse(const uint8_t* data, size_t len, BuildShallowTrace* out,
    957                         char* err, size_t errcap) {
    958   return shallow_parse_like(data, len, out, err, errcap, BUILD_SHALLOW_MAGIC,
    959                             "output");
    960 }
    961 
    962 int build_test_shallow_parse(const uint8_t* data, size_t len,
    963                              BuildShallowTrace* out, char* err,
    964                              size_t errcap) {
    965   return shallow_parse_like(data, len, out, err, errcap,
    966                             BUILD_TEST_SHALLOW_MAGIC, "result");
    967 }
    968 
    969 static int deep_parse_like(const uint8_t* data, size_t len,
    970                            BuildDeepTrace* out, char* err, size_t errcap,
    971                            const char* magic, const char* result_key) {
    972   TraceParser p;
    973   uint32_t seen = 0;
    974   if (!data || !out) return set_err(err, errcap, "missing deep trace");
    975   memset(out->target, 0, sizeof out->target);
    976   memset(&p, 0, sizeof p);
    977   p.data = data;
    978   p.len = len;
    979   p.first = 1;
    980   for (;;) {
    981     char* line;
    982     char* fields[2];
    983     size_t n = 0;
    984     int r = parser_next(&p, &line, err, errcap);
    985     if (r < 0) return BUILD_ERR;
    986     if (r == 0) break;
    987     if (p.first) {
    988       p.first = 0;
    989       if (strcmp(line, magic) != 0)
    990         return set_err(err, errcap, "bad deep magic/version");
    991       continue;
    992     }
    993     if (line[0] == '[') return set_err(err, errcap, "bad deep section");
    994     if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) !=
    995         BUILD_OK)
    996       return set_err(err, errcap, "bad deep row");
    997     if (!(seen & F_TARGET)) {
    998       if (parse_top_text(fields, n, "target", out->target, sizeof out->target,
    999                          &seen, F_TARGET, err, errcap) != BUILD_OK)
   1000         return BUILD_ERR;
   1001     } else if (!(seen & F_RECIPE)) {
   1002       if (parse_top_hash(fields, n, "recipe", out->recipe, &seen, F_RECIPE,
   1003                          err, errcap) != BUILD_OK)
   1004         return BUILD_ERR;
   1005     } else if (!(seen & F_OUTPUT)) {
   1006       if (parse_top_hash(fields, n, result_key, out->output, &seen, F_OUTPUT,
   1007                          err, errcap) != BUILD_OK)
   1008         return BUILD_ERR;
   1009     } else if (!(seen & F_ARGV)) {
   1010       if (parse_top_hash(fields, n, "argv", out->argv, &seen, F_ARGV, err,
   1011                          errcap) != BUILD_OK)
   1012         return BUILD_ERR;
   1013     } else if (!(seen & F_DEEPSET)) {
   1014       if (parse_top_hash(fields, n, "deepset", out->deepset, &seen, F_DEEPSET,
   1015                          err, errcap) != BUILD_OK)
   1016         return BUILD_ERR;
   1017     } else {
   1018       return set_err(err, errcap, "unexpected deep field");
   1019     }
   1020   }
   1021   if (p.first) return set_err(err, errcap, "bad deep magic/version");
   1022   if (seen != (F_TARGET | F_RECIPE | F_OUTPUT | F_ARGV | F_DEEPSET))
   1023     return set_err(err, errcap, "missing deep field");
   1024   return BUILD_OK;
   1025 }
   1026 
   1027 int build_deep_parse(const uint8_t* data, size_t len, BuildDeepTrace* out,
   1028                      char* err, size_t errcap) {
   1029   return deep_parse_like(data, len, out, err, errcap, BUILD_DEEP_MAGIC,
   1030                          "output");
   1031 }
   1032 
   1033 int build_test_deep_parse(const uint8_t* data, size_t len, BuildDeepTrace* out,
   1034                           char* err, size_t errcap) {
   1035   return deep_parse_like(data, len, out, err, errcap, BUILD_TEST_DEEP_MAGIC,
   1036                          "result");
   1037 }
   1038 
   1039 int build_deepset_parse(const uint8_t* data, size_t len, BuildDeepSet* out,
   1040                         char* err, size_t errcap) {
   1041   TraceParser p;
   1042   TraceSection sec = TRACE_SEC_TOP;
   1043   uint32_t seen = 0;
   1044   if (!data || !out) return set_err(err, errcap, "missing deepset");
   1045   if ((out->cap_configs && !out->configs) ||
   1046       (out->cap_sources && !out->sources) || (out->cap_globs && !out->globs) ||
   1047       (out->cap_blobs && !out->blobs) ||
   1048       (out->cap_children && !out->children))
   1049     return set_err(err, errcap, "missing deepset storage");
   1050   memset(out->target, 0, sizeof out->target);
   1051   out->n_configs = 0;
   1052   out->n_sources = 0;
   1053   out->n_globs = 0;
   1054   out->n_blobs = 0;
   1055   out->n_children = 0;
   1056   memset(&p, 0, sizeof p);
   1057   p.data = data;
   1058   p.len = len;
   1059   p.first = 1;
   1060   for (;;) {
   1061     char* line;
   1062     char* fields[4];
   1063     size_t n = 0;
   1064     int r = parser_next(&p, &line, err, errcap);
   1065     if (r < 0) return BUILD_ERR;
   1066     if (r == 0) break;
   1067     if (p.first) {
   1068       p.first = 0;
   1069       if (strcmp(line, BUILD_DEEPSET_MAGIC) != 0)
   1070         return set_err(err, errcap, "bad deepset magic/version");
   1071       continue;
   1072     }
   1073     if (line[0] == '[') {
   1074       if (strcmp(line, "[config]") == 0 && sec == TRACE_SEC_TOP) {
   1075         if (seen != (F_TARGET | F_RECIPE))
   1076           return set_err(err, errcap, "missing deepset field");
   1077         sec = TRACE_SEC_CONFIG;
   1078       } else if (strcmp(line, "[source]") == 0 && sec == TRACE_SEC_CONFIG) {
   1079         sec = TRACE_SEC_SOURCE;
   1080       } else if (strcmp(line, "[glob]") == 0 && sec == TRACE_SEC_SOURCE) {
   1081         sec = TRACE_SEC_GLOB;
   1082       } else if (strcmp(line, "[blob]") == 0 && sec == TRACE_SEC_GLOB) {
   1083         sec = TRACE_SEC_BLOB;
   1084       } else if (strcmp(line, "[child]") == 0 &&
   1085                  (sec == TRACE_SEC_GLOB || sec == TRACE_SEC_BLOB)) {
   1086         sec = TRACE_SEC_CHILD;
   1087       } else {
   1088         return set_err(err, errcap, "bad deepset section");
   1089       }
   1090       continue;
   1091     }
   1092     if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) !=
   1093         BUILD_OK)
   1094       return set_err(err, errcap, "bad deepset row");
   1095     if (sec == TRACE_SEC_TOP) {
   1096       if (!(seen & F_TARGET)) {
   1097         if (parse_top_text(fields, n, "target", out->target, sizeof out->target,
   1098                            &seen, F_TARGET, err, errcap) != BUILD_OK)
   1099           return BUILD_ERR;
   1100       } else if (!(seen & F_RECIPE)) {
   1101         if (parse_top_hash(fields, n, "recipe", out->recipe, &seen, F_RECIPE,
   1102                            err, errcap) != BUILD_OK)
   1103           return BUILD_ERR;
   1104       } else {
   1105         return set_err(err, errcap, "unexpected deepset field");
   1106       }
   1107     } else if (sec == TRACE_SEC_CONFIG) {
   1108       if (append_deepset_config(out, fields, n, err, errcap) != BUILD_OK)
   1109         return BUILD_ERR;
   1110     } else if (sec == TRACE_SEC_SOURCE) {
   1111       if (append_deepset_source(out, fields, n, err, errcap) != BUILD_OK)
   1112         return BUILD_ERR;
   1113     } else if (sec == TRACE_SEC_GLOB) {
   1114       if (append_deepset_glob(out, fields, n, err, errcap) != BUILD_OK)
   1115         return BUILD_ERR;
   1116     } else if (sec == TRACE_SEC_BLOB) {
   1117       if (append_deepset_blob(out, fields, n, err, errcap) != BUILD_OK)
   1118         return BUILD_ERR;
   1119     } else if (sec == TRACE_SEC_CHILD) {
   1120       if (append_child(out, fields, n, err, errcap) != BUILD_OK)
   1121         return BUILD_ERR;
   1122     } else {
   1123       return set_err(err, errcap, "bad deepset row");
   1124     }
   1125   }
   1126   if (p.first) return set_err(err, errcap, "bad deepset magic/version");
   1127   if (sec != TRACE_SEC_CHILD)
   1128     return set_err(err, errcap, "missing deepset section");
   1129   return BUILD_OK;
   1130 }
   1131 
   1132 int build_record_parse(const uint8_t* data, size_t len, BuildTargetRecord* out,
   1133                        char* err, size_t errcap) {
   1134   TraceParser p;
   1135   uint32_t seen = 0;
   1136   if (!data || !out) return set_err(err, errcap, "missing target record");
   1137   if (out->cap_rows && !out->rows)
   1138     return set_err(err, errcap, "missing record storage");
   1139   memset(out->target, 0, sizeof out->target);
   1140   out->n_rows = 0;
   1141   memset(&p, 0, sizeof p);
   1142   p.data = data;
   1143   p.len = len;
   1144   p.first = 1;
   1145   for (;;) {
   1146     char* line;
   1147     char* fields[2];
   1148     size_t n = 0;
   1149     int r = parser_next(&p, &line, err, errcap);
   1150     if (r < 0) return BUILD_ERR;
   1151     if (r == 0) break;
   1152     if (p.first) {
   1153       p.first = 0;
   1154       if (strcmp(line, BUILD_RECORD_MAGIC) != 0)
   1155         return set_err(err, errcap, "bad record magic/version");
   1156       continue;
   1157     }
   1158     if (line[0] == '[') return set_err(err, errcap, "bad record section");
   1159     if (split_line(line, fields, sizeof fields / sizeof fields[0], &n) !=
   1160         BUILD_OK)
   1161       return set_err(err, errcap, "bad record row");
   1162     if (!(seen & F_TARGET)) {
   1163       if (parse_top_text(fields, n, "target", out->target, sizeof out->target,
   1164                          &seen, F_TARGET, err, errcap) != BUILD_OK)
   1165         return BUILD_ERR;
   1166     } else {
   1167       if (append_record_row(out, fields, n, err, errcap) != BUILD_OK)
   1168         return BUILD_ERR;
   1169     }
   1170   }
   1171   if (p.first) return set_err(err, errcap, "bad record magic/version");
   1172   if (seen != F_TARGET) return set_err(err, errcap, "missing record target");
   1173   return BUILD_OK;
   1174 }
   1175 
   1176 void build_trace_id(const uint8_t* body, size_t len,
   1177                     uint8_t out[BUILD_HASH_LEN]) {
   1178   KitBlobInfo bi;
   1179   kit_blob_info(&bi, body, len);
   1180   memcpy(out, bi.id, BUILD_HASH_LEN);
   1181 }
   1182 
   1183 void build_deepset_id(const uint8_t* body, size_t len,
   1184                       uint8_t out[BUILD_HASH_LEN]) {
   1185   build_trace_id(body, len, out);
   1186 }
   1187 
   1188 int build_record_prepend(BuildTargetRecord* rec, const BuildRecordRow* row) {
   1189   size_t read, write, count, i;
   1190   if (!rec || !row) return BUILD_ERR;
   1191   if (!check_record_kind(row->kind)) return BUILD_ERR;
   1192   if (rec->cap_rows && !rec->rows) return BUILD_ERR;
   1193   if (rec->n_rows > rec->cap_rows) return BUILD_ERR;
   1194   write = 0;
   1195   for (read = 0; read < rec->n_rows; ++read) {
   1196     if (rec->rows[read].kind == row->kind &&
   1197         build_id_eq(rec->rows[read].trace_id, row->trace_id))
   1198       continue;
   1199     if (write != read) rec->rows[write] = rec->rows[read];
   1200     ++write;
   1201   }
   1202   rec->n_rows = write;
   1203   if (rec->n_rows >= rec->cap_rows) {
   1204     size_t last_same = rec->n_rows;
   1205     count = 0;
   1206     for (i = 0; i < rec->n_rows; ++i) {
   1207       if (rec->rows[i].kind == row->kind) {
   1208         ++count;
   1209         last_same = i;
   1210       }
   1211     }
   1212     if (count < KIT_BUILD_RECORD_CAP || last_same == rec->n_rows)
   1213       return BUILD_ERR;
   1214     for (i = last_same + 1u; i < rec->n_rows; ++i)
   1215       rec->rows[i - 1u] = rec->rows[i];
   1216     --rec->n_rows;
   1217   }
   1218   for (i = rec->n_rows; i > 0; --i) rec->rows[i] = rec->rows[i - 1u];
   1219   rec->rows[0] = *row;
   1220   ++rec->n_rows;
   1221 
   1222   count = 0;
   1223   write = 0;
   1224   for (read = 0; read < rec->n_rows; ++read) {
   1225     if (rec->rows[read].kind == row->kind) {
   1226       ++count;
   1227       if (count > KIT_BUILD_RECORD_CAP) continue;
   1228     }
   1229     if (write != read) rec->rows[write] = rec->rows[read];
   1230     ++write;
   1231   }
   1232   rec->n_rows = write;
   1233   return BUILD_OK;
   1234 }