LCOV - code coverage report
Current view: top level - src/compiler - codegen_c_builder.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 528 555 95.1 %
Date: 2016-11-30 13:12:14 Functions: 25 25 100.0 %
Branches: 214 236 90.7 %

           Branch data     Line data    Source code
       1                 :            : #include <string.h>
       2                 :            : 
       3                 :            : #include "codegen_c.h"
       4                 :            : 
       5                 :            : #define llu(x) (long long unsigned int)(x)
       6                 :            : #define lld(x) (long long int)(x)
       7                 :            : 
       8                 :         10 : int fb_gen_common_c_builder_header(fb_output_t *out)
       9                 :            : {
      10                 :         10 :     const char *nsc = out->nsc;
      11                 :         10 :     const char *nscup = out->nscup;
      12                 :            : 
      13                 :         10 :     fprintf(out->fp, "#ifndef %s_COMMON_BUILDER_H\n", nscup);
      14                 :         10 :     fprintf(out->fp, "#define %s_COMMON_BUILDER_H\n", nscup);
      15                 :         10 :     fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n");
      16                 :         10 :     fprintf(out->fp, "/* Common FlatBuffers build functionality for C. */\n\n");
      17                 :            :     gen_pragma_push(out);
      18                 :            : 
      19                 :         10 :     fprintf(out->fp, "#ifndef FLATBUILDER_H\n");
      20                 :         10 :     fprintf(out->fp, "#include \"flatcc/flatcc_builder.h\"\n");
      21                 :         10 :     fprintf(out->fp, "#endif\n");
      22         [ +  - ]:         10 :     if (strcmp(nsc, "flatcc_builder_")) {
      23                 :         10 :         fprintf(out->fp, "typedef flatcc_builder_t %sbuilder_t;\n", nsc);
      24                 :         10 :         fprintf(out->fp, "typedef flatcc_builder_ref_t %sref_t;\n", nsc);
      25                 :         10 :         fprintf(out->fp, "typedef flatcc_builder_ref_t %svec_ref_t;\n", nsc);
      26                 :         10 :         fprintf(out->fp, "/* integer return code (ref and ptr always fail on 0) */\n"
      27                 :            :                 "#define %sfailed(x) ((x) < 0)\n", nsc);
      28                 :            :     }
      29                 :         10 :     fprintf(out->fp, "typedef %sref_t %sroot_t;\n", nsc, nsc);
      30                 :         10 :     fprintf(out->fp, "#define %sroot(ref) ((%sroot_t)(ref))\n", nsc, nsc);
      31         [ -  + ]:         10 :     if (strcmp(nsc, "flatbuffers_")) {
      32                 :          0 :         fprintf(out->fp, "#define %sis_native_pe flatbuffers_is_native_pe\n", nsc);
      33                 :          0 :         fprintf(out->fp, "typedef flatbuffers_fid_t %sfid_t;\n", nsc);
      34                 :            :     }
      35                 :         10 :     fprintf(out->fp, "\n");
      36                 :         10 :     fprintf(out->fp,
      37                 :            :         "#define __%sbuild_buffer(NS)\\\n"
      38                 :            :         "typedef NS ## ref_t NS ## buffer_ref_t;\\\n"
      39                 :            :         "static inline int NS ## buffer_start(NS ## builder_t *B, NS ##fid_t fid)\\\n"
      40                 :            :         "{ return flatcc_builder_start_buffer(B, fid, 0, 0); }\\\n"
      41                 :            :         "static inline int NS ## buffer_start_with_size(NS ## builder_t *B, NS ##fid_t fid)\\\n"
      42                 :            :         "{ return flatcc_builder_start_buffer(B, fid, 0, flatcc_builder_with_size); }\\\n"
      43                 :            :         "static inline int NS ## buffer_start_aligned(NS ## builder_t *B, NS ##fid_t fid, uint16_t block_align)\\\n"
      44                 :            :         "{ return flatcc_builder_start_buffer(B, fid, block_align, 0); }\\\n"
      45                 :            :         "static inline int NS ## buffer_start_aligned_with_size(NS ## builder_t *B, NS ##fid_t fid, uint16_t block_align)\\\n"
      46                 :            :         "{ return flatcc_builder_start_buffer(B, fid, block_align, flatcc_builder_with_size); }\\\n"
      47                 :            :         "static inline NS ## buffer_ref_t NS ## buffer_end(NS ## builder_t *B, NS ## ref_t root)\\\n"
      48                 :            :         "{ return flatcc_builder_end_buffer(B, root); }\n"
      49                 :            :         "\n",
      50                 :            :         nsc);
      51                 :            : 
      52                 :         10 :     fprintf(out->fp,
      53                 :            :         "#define __%sbuild_table_root(NS, N, FID, TFID)\\\n"
      54                 :            :         "static inline int N ## _start_as_root(NS ## builder_t *B)\\\n"
      55                 :            :         "{ return NS ## buffer_start(B, FID) ? -1 : N ## _start(B); }\\\n"
      56                 :            :         "static inline int N ## _start_as_root_with_size(NS ## builder_t *B)\\\n"
      57                 :            :         "{ return NS ## buffer_start_with_size(B, FID) ? -1 : N ## _start(B); }\\\n"
      58                 :            :         "static inline int N ## _start_as_typed_root(NS ## builder_t *B)\\\n"
      59                 :            :         "{ return NS ## buffer_start(B, TFID) ? -1 : N ## _start(B); }\\\n"
      60                 :            :         "static inline int N ## _start_as_typed_root_with_size(NS ## builder_t *B)\\\n"
      61                 :            :         "{ return NS ## buffer_start_with_size(B, TFID) ? -1 : N ## _start(B); }\\\n"
      62                 :            :         "static inline NS ## buffer_ref_t N ## _end_as_root(NS ## builder_t *B)\\\n"
      63                 :            :         "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n"
      64                 :            :         "static inline NS ## buffer_ref_t N ## _end_as_typed_root(NS ## builder_t *B)\\\n"
      65                 :            :         "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n"
      66                 :            :         /*
      67                 :            :          * Unlike structs, we do no use flatcc_builder_create_buffer
      68                 :            :          * because we would have to manage alignment, and we save very
      69                 :            :          * little because tables require stack allocations in any case.
      70                 :            :          */
      71                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
      72                 :            :         "{ if (NS ## buffer_start(B, FID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n"
      73                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
      74                 :            :         "{ if (NS ## buffer_start_with_size(B, FID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n"
      75                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_typed_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
      76                 :            :         "{ if (NS ## buffer_start(B, TFID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n"
      77                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_typed_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
      78                 :            :         "{ if (NS ## buffer_start_with_size(B, TFID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\n"
      79                 :            :         "\n",
      80                 :            :         nsc);
      81                 :            : 
      82                 :         10 :     fprintf(out->fp,
      83                 :            :         "#define __%sbuild_table_prolog(NS, N, FID, TFID)\\\n"
      84                 :            :         "__%sbuild_table_vector_ops(NS, N ## _vec, N)\\\n"
      85                 :            :         "__%sbuild_table_root(NS, N, FID, TFID)\n"
      86                 :            :         "\n",
      87                 :            :         nsc, nsc, nsc);
      88                 :            : 
      89                 :            : 
      90                 :         10 :     fprintf(out->fp,
      91                 :            :         "#define __%sbuild_struct_root(NS, N, A, FID, TFID)\\\n"
      92                 :            :         "static inline N ## _t *N ## _start_as_root(NS ## builder_t *B)\\\n"
      93                 :            :         "{ return NS ## buffer_start(B, FID) ? 0 : N ## _start(B); }\\\n"
      94                 :            :         "static inline N ## _t *N ## _start_as_root_with_size(NS ## builder_t *B)\\\n"
      95                 :            :         "{ return NS ## buffer_start_with_size(B, FID) ? 0 : N ## _start(B); }\\\n"
      96                 :            :         "static inline N ## _t *N ## _start_as_typed_root(NS ## builder_t *B)\\\n"
      97                 :            :         "{ return NS ## buffer_start(B, TFID) ? 0 : N ## _start(B); }\\\n"
      98                 :            :         "static inline N ## _t *N ## _start_as_typed_root_with_size(NS ## builder_t *B)\\\n"
      99                 :            :         "{ return NS ## buffer_start_with_size(B, TFID) ? 0 : N ## _start(B); }\\\n"
     100                 :            :         "static inline NS ## buffer_ref_t N ## _end_as_root(NS ## builder_t *B)\\\n"
     101                 :            :         "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n"
     102                 :            :         "static inline NS ## buffer_ref_t N ## _end_as_typed_root(NS ## builder_t *B)\\\n"
     103                 :            :         "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n"
     104                 :            :         "static inline NS ## buffer_ref_t N ## _end_pe_as_root(NS ## builder_t *B)\\\n"
     105                 :            :         "{ return NS ## buffer_end(B, N ## _end_pe(B)); }\\\n"
     106                 :            :         "static inline NS ## buffer_ref_t N ## _end_pe_as_typed_root(NS ## builder_t *B)\\\n"
     107                 :            :         "{ return NS ## buffer_end(B, N ## _end_pe(B)); }\\\n"
     108                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
     109                 :            :         "{ return flatcc_builder_create_buffer(B, FID, 0,\\\n"
     110                 :            :         "  N ## _create(B __ ## N ## _call_args), A, 0); }\\\n"
     111                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
     112                 :            :         "{ return flatcc_builder_create_buffer(B, FID, 0,\\\n"
     113                 :            :         "  N ## _create(B __ ## N ## _call_args), A, flatcc_builder_with_size); }\\\n"
     114                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_typed_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
     115                 :            :         "{ return flatcc_builder_create_buffer(B, TFID, 0,\\\n"
     116                 :            :         "  N ## _create(B __ ## N ## _call_args), A, 0); }\\\n"
     117                 :            :         "static inline NS ## buffer_ref_t N ## _create_as_typed_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
     118                 :            :         "{ return flatcc_builder_create_buffer(B, TFID, 0,\\\n"
     119                 :            :         "  N ## _create(B __ ## N ## _call_args), A, flatcc_builder_with_size); }\n"
     120                 :            :         "\n",
     121                 :            :         nsc);
     122                 :            : 
     123                 :         10 :     fprintf(out->fp,
     124                 :            :         "#define __%sbuild_nested_table_root(NS, N, TN, FID, TFID)\\\n"
     125                 :            :         "static inline int N ## _start_as_root(NS ## builder_t *B)\\\n"
     126                 :            :         "{ return NS ## buffer_start(B, FID) ? -1 : TN ## _start(B); }\\\n"
     127                 :            :         "static inline int N ## _start_as_typed_root(NS ## builder_t *B)\\\n"
     128                 :            :         "{ return NS ## buffer_start(B, TFID) ? -1 : TN ## _start(B); }\\\n"
     129                 :            :         "static inline int N ## _end_as_root(NS ## builder_t *B)\\\n"
     130                 :            :         "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n"
     131                 :            :         "static inline int N ## _end_as_typed_root(NS ## builder_t *B)\\\n"
     132                 :            :         "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n"
     133                 :            :         "static inline int N ## _nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n"
     134                 :            :         "{ if (NS ## buffer_start(B, FID)) return -1;\\\n"
     135                 :            :         "  return N ## _add(B, NS ## buffer_end(B, flatcc_builder_create_vector(B, data, size, 1,\\\n"
     136                 :            :         "  align ? align : 8, FLATBUFFERS_COUNT_MAX(1)))); }\\\n"
     137                 :            :         "static inline int N ## _typed_nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n"
     138                 :            :         "{ if (NS ## buffer_start(B, TFID)) return -1;\\\n"
     139                 :            :         "  return N ## _add(B, NS ## buffer_end(B, flatcc_builder_create_vector(B, data, size, 1,\\\n"
     140                 :            :         "  align ? align : 8, FLATBUFFERS_COUNT_MAX(1)))); }\n"
     141                 :            :         "\n",
     142                 :            :         nsc);
     143                 :            : 
     144                 :         10 :     fprintf(out->fp,
     145                 :            :         "#define __%sbuild_nested_struct_root(NS, N, TN, A, FID, TFID)\\\n"
     146                 :            :         "static inline TN ## _t *N ## _start_as_root(NS ## builder_t *B)\\\n"
     147                 :            :         "{ return NS ## buffer_start(B, FID) ? 0 : TN ## _start(B); }\\\n"
     148                 :            :         "static inline TN ## _t *N ## _start_as_typed_root(NS ## builder_t *B)\\\n"
     149                 :            :         "{ return NS ## buffer_start(B, FID) ? 0 : TN ## _start(B); }\\\n"
     150                 :            :         "static inline int N ## _end_as_root(NS ## builder_t *B)\\\n"
     151                 :            :         "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n"
     152                 :            :         "static inline int N ## _end_as_typed_root(NS ## builder_t *B)\\\n"
     153                 :            :         "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n"
     154                 :            :         "static inline int N ## _end_pe_as_root(NS ## builder_t *B)\\\n"
     155                 :            :         "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end_pe(B))); }\\\n"
     156                 :            :         "static inline int N ## _create_as_root(NS ## builder_t *B __ ## TN ## _formal_args)\\\n"
     157                 :            :         "{ return N ## _add(B, flatcc_builder_create_buffer(B, FID, 0,\\\n"
     158                 :            :         "  TN ## _create(B __ ## TN ## _call_args), A, flatcc_builder_is_nested)); }\\\n"
     159                 :            :         "static inline int N ## _create_as_typed_root(NS ## builder_t *B __ ## TN ## _formal_args)\\\n"
     160                 :            :         "{ return N ## _add(B, flatcc_builder_create_buffer(B, TFID, 0,\\\n"
     161                 :            :         "  TN ## _create(B __ ## TN ## _call_args), A, flatcc_builder_is_nested)); }\\\n"
     162                 :            :         "static inline int N ## _nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n"
     163                 :            :         "{ if (NS ## buffer_start(B, FID)) return -1;\\\n"
     164                 :            :         "  return N ## _add(B, NS ## buffer_end(B, flatcc_builder_create_vector(B, data, size, 1,\\\n"
     165                 :            :         "  align < A ? A : align, FLATBUFFERS_COUNT_MAX(1)))); }\\\n"
     166                 :            :         "static inline int N ## _typed_nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n"
     167                 :            :         "{ if (NS ## buffer_start(B, TFID)) return -1;\\\n"
     168                 :            :         "  return N ## _add(B, NS ## buffer_end(B, flatcc_builder_create_vector(B, data, size, 1,\\\n"
     169                 :            :         "  align < A ? A : align, FLATBUFFERS_COUNT_MAX(1)))); }\n"
     170                 :            :         "\n",
     171                 :            :         nsc);
     172                 :            : 
     173                 :         10 :     fprintf(out->fp,
     174                 :            :         "#define __%sbuild_vector_ops(NS, V, N, TN, T)\\\n"
     175                 :            :         "static inline T *V ## _extend(NS ## builder_t *B, size_t len)\\\n"
     176                 :            :         "{ return flatcc_builder_extend_vector(B, len); }\\\n"
     177                 :            :         "static inline T *V ## _append(NS ## builder_t *B, const T *data, size_t len)\\\n"
     178                 :            :         "{ return flatcc_builder_append_vector(B, data, len); }\\\n"
     179                 :            :         "static inline int V ## _truncate(NS ## builder_t *B, size_t len)\\\n"
     180                 :            :         "{ return flatcc_builder_truncate_vector(B, len); }\\\n"
     181                 :            :         "static inline T *V ## _edit(NS ## builder_t *B)\\\n"
     182                 :            :         "{ return flatcc_builder_vector_edit(B); }\\\n"
     183                 :            :         "static inline size_t V ## _reserved_len(NS ## builder_t *B)\\\n"
     184                 :            :         "{ return flatcc_builder_vector_count(B); }\\\n"
     185                 :            :         "static inline T *V ## _push(NS ## builder_t *B, const T *p)\\\n"
     186                 :            :         "{ T *_p; return (_p = flatcc_builder_extend_vector(B, 1)) ? (memcpy(_p, p, TN ## __size()), _p) : 0; }\\\n"
     187                 :            :         "static inline T *V ## _push_copy(NS ## builder_t *B, const T *p)\\\n"
     188                 :            :         "{ T *_p; return (_p = flatcc_builder_extend_vector(B, 1)) ? TN ## _copy(_p, p) : 0; }\\\n"
     189                 :            :         "static inline T *V ## _push_create(NS ## builder_t *B __ ## TN ## _formal_args)\\\n"
     190                 :            :         "{ T *_p; return (_p = flatcc_builder_extend_vector(B, 1)) ? TN ## _assign(_p __ ## TN ## _call_args) : 0; }\n"
     191                 :            :         "\n",
     192                 :            :         nsc);
     193                 :            : 
     194                 :         10 :     fprintf(out->fp,
     195                 :            :         /* NS: common namespace, N: typename, T: element type, S: elem size, A: alignment */
     196                 :            :         "#define __%sbuild_vector(NS, N, T, S, A)\\\n"
     197                 :            :         "typedef NS ## ref_t N ## _vec_ref_t;\\\n"
     198                 :            :         "static inline int N ## _vec_start(NS ## builder_t *B)\\\n"
     199                 :            :         "{ return flatcc_builder_start_vector(B, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n"
     200                 :            :         "static inline N ## _vec_ref_t N ## _vec_end_pe(NS ## builder_t *B)\\\n"
     201                 :            :         "{ return flatcc_builder_end_vector(B); }\\\n"
     202                 :            :         "static inline N ## _vec_ref_t N ## _vec_end(NS ## builder_t *B)\\\n"
     203                 :            :         "{ if (!NS ## is_native_pe()) { size_t i, n; T *p = flatcc_builder_vector_edit(B);\\\n"
     204                 :            :         "    for (i = 0, n = flatcc_builder_vector_count(B); i < n; ++i)\\\n"
     205                 :            :         "    { N ## _to_pe(N ## __ptr_add(p, i)); }} return flatcc_builder_end_vector(B); }\\\n"
     206                 :            :         "static inline N ## _vec_ref_t N ## _vec_create_pe(NS ## builder_t *B, const T *data, size_t len)\\\n"
     207                 :            :         "{ return flatcc_builder_create_vector(B, data, len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n"
     208                 :            :         "static inline N ## _vec_ref_t N ## _vec_create(NS ## builder_t *B, const T *data, size_t len)\\\n"
     209                 :            :         "{ if (!NS ## is_native_pe()) { size_t i; T *p; int ret = flatcc_builder_start_vector(B, S, A, FLATBUFFERS_COUNT_MAX(S)); if (ret) { return ret; }\\\n"
     210                 :            :         "  p = flatcc_builder_extend_vector(B, len); if (!p) return 0;\\\n"
     211                 :            :         "  for (i = 0; i < len; ++i) { N ## _copy_to_pe(N ## __ptr_add(p, i), N ## __const_ptr_add(data, i)); }\\\n"
     212                 :            :         "  return flatcc_builder_end_vector(B); } else return flatcc_builder_create_vector(B, data, len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n"
     213                 :            :         "static inline N ## _vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_vec_t vec)\\\n"
     214                 :            :         "{ return flatcc_builder_create_vector(B, vec, N ## _vec_len(vec), S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n"
     215                 :            :         "static inline N ## _vec_ref_t N ## _vec_slice(NS ## builder_t *B, N ##_vec_t vec, size_t index, size_t len)\\\n"
     216                 :            :         "{ size_t n = N ## _vec_len(vec); if (index >= n) index = n; n -= index; if (len > n) len = n;\\\n"
     217                 :            :         "  return flatcc_builder_create_vector(B, N ## __const_ptr_add(vec, index), len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n"
     218                 :            :         "__%sbuild_vector_ops(NS, N ## _vec, N, N, T)\n"
     219                 :            :         "\n",
     220                 :            :         nsc, nsc);
     221                 :            : 
     222                 :            :     /* In addtion to offset_vector_ops... */
     223                 :         10 :     fprintf(out->fp,
     224                 :            :         "#define __%sbuild_string_vector_ops(NS, N)\\\n"
     225                 :            :         "static inline int N ## _push_start(NS ## builder_t *B)\\\n"
     226                 :            :         "{ return NS ## string_start(B); }\\\n"
     227                 :            :         "static inline NS ## string_ref_t *N ## _push_end(NS ## builder_t *B)\\\n"
     228                 :            :         "{ return NS ## string_vec_push(B, NS ## string_end(B)); }\\\n"
     229                 :            :         "static inline NS ## string_ref_t *N ## _push_create(NS ## builder_t *B, const char *s, size_t len)\\\n"
     230                 :            :         "{ return NS ## string_vec_push(B, NS ## string_create(B, s, len)); }\\\n"
     231                 :            :         "static inline NS ## string_ref_t *N ## _push_create_str(NS ## builder_t *B, const char *s)\\\n"
     232                 :            :         "{ return NS ## string_vec_push(B, NS ## string_create_str(B, s)); }\\\n"
     233                 :            :         "static inline NS ## string_ref_t *N ## _push_create_strn(NS ## builder_t *B, const char *s, size_t max_len)\\\n"
     234                 :            :         "{ return NS ## string_vec_push(B, NS ## string_create_strn(B, s, max_len)); }\\\n"
     235                 :            :         "static inline NS ## string_ref_t *N ## _push_clone(NS ## builder_t *B, NS ## string_t string)\\\n"
     236                 :            :         "{ return NS ## string_vec_push(B, NS ## string_clone(B, string)); }\\\n"
     237                 :            :         "static inline NS ## string_ref_t *N ## _push_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n"
     238                 :            :         "{ return NS ## string_vec_push(B, NS ## string_slice(B, string, index, len)); }\n"
     239                 :            :         "\n",
     240                 :            :         nsc);
     241                 :            : 
     242                 :            :     /* In addtion to offset_vector_ops... */
     243                 :         10 :     fprintf(out->fp,
     244                 :            :         "#define __%sbuild_table_vector_ops(NS, N, TN)\\\n"
     245                 :            :         "static inline int N ## _push_start(NS ## builder_t *B)\\\n"
     246                 :            :         "{ return TN ## _start(B); }\\\n"
     247                 :            :         "static inline TN ## _ref_t *N ## _push_end(NS ## builder_t *B)\\\n"
     248                 :            :         "{ return N ## _push(B, TN ## _end(B)); }\\\n"
     249                 :            :         "static inline TN ## _ref_t *N ## _push_create(NS ## builder_t *B __ ## TN ##_formal_args)\\\n"
     250                 :            :         "{ return N ## _push(B, TN ## _create(B __ ## TN ## _call_args)); }\n"
     251                 :            :         "\n",
     252                 :            :         nsc);
     253                 :            : 
     254                 :         10 :     fprintf(out->fp,
     255                 :            :         "#define __%sbuild_offset_vector_ops(NS, V, N, TN)\\\n"
     256                 :            :         "static inline TN ## _ref_t *V ## _extend(NS ## builder_t *B, size_t len)\\\n"
     257                 :            :         "{ return flatcc_builder_extend_offset_vector(B, len); }\\\n"
     258                 :            :         "static inline TN ## _ref_t *V ## _append(NS ## builder_t *B, const TN ## _ref_t *data, size_t len)\\\n"
     259                 :            :         "{ return flatcc_builder_append_offset_vector(B, data, len); }\\\n"
     260                 :            :         "static inline int V ## _truncate(NS ## builder_t *B, size_t len)\\\n"
     261                 :            :         "{ return flatcc_builder_truncate_offset_vector(B, len); }\\\n"
     262                 :            :         "static inline TN ## _ref_t *V ## _edit(NS ## builder_t *B)\\\n"
     263                 :            :         "{ return flatcc_builder_offset_vector_edit(B); }\\\n"
     264                 :            :         "static inline size_t V ## _reserved_len(NS ## builder_t *B)\\\n"
     265                 :            :         "{ return flatcc_builder_offset_vector_count(B); }\\\n"
     266                 :            :         "static inline TN ## _ref_t *V ## _push(NS ## builder_t *B, const TN ## _ref_t ref)\\\n"
     267                 :            :         "{ return ref ? flatcc_builder_offset_vector_push(B, ref) : 0; }\n"
     268                 :            :         "\n",
     269                 :            :         nsc);
     270                 :            : 
     271                 :         10 :     fprintf(out->fp,
     272                 :            :         "#define __%sbuild_offset_vector(NS, N)\\\n"
     273                 :            :         "typedef NS ## ref_t N ## _vec_ref_t;\\\n"
     274                 :            :         "static inline int N ## _vec_start(NS ## builder_t *B)\\\n"
     275                 :            :         "{ return flatcc_builder_start_offset_vector(B); }\\\n"
     276                 :            :         "static inline N ## _vec_ref_t N ## _vec_end(NS ## builder_t *B)\\\n"
     277                 :            :         "{ return flatcc_builder_end_offset_vector(B); }\\\n"
     278                 :            :         "static inline N ## _vec_ref_t N ## _vec_create(NS ## builder_t *B, const N ## _ref_t *data, size_t len)\\\n"
     279                 :            :         "{ return flatcc_builder_create_offset_vector(B, data, len); }\\\n"
     280                 :            :         "__%sbuild_offset_vector_ops(NS, N ## _vec, N, N)\n"
     281                 :            :         "\n",
     282                 :            :         nsc, nsc);
     283                 :            : 
     284                 :         10 :     fprintf(out->fp,
     285                 :            :         "#define __%sbuild_string_ops(NS, N)\\\n"
     286                 :            :         "static inline char *N ## _append(NS ## builder_t *B, const char *s, size_t len)\\\n"
     287                 :            :         "{ return flatcc_builder_append_string(B, s, len); }\\\n"
     288                 :            :         "static inline char *N ## _append_str(NS ## builder_t *B, const char *s)\\\n"
     289                 :            :         "{ return flatcc_builder_append_string_str(B, s); }\\\n"
     290                 :            :         "static inline char *N ## _append_strn(NS ## builder_t *B, const char *s, size_t len)\\\n"
     291                 :            :         "{ return flatcc_builder_append_string_strn(B, s, len); }\\\n"
     292                 :            :         "static inline size_t N ## _reserved_len(NS ## builder_t *B)\\\n"
     293                 :            :         "{ return flatcc_builder_string_len(B); }\\\n"
     294                 :            :         "static inline char *N ## _extend(NS ## builder_t *B, size_t len)\\\n"
     295                 :            :         "{ return flatcc_builder_extend_string(B, len); }\\\n"
     296                 :            :         "static inline char *N ## _edit(NS ## builder_t *B)\\\n"
     297                 :            :         "{ return flatcc_builder_string_edit(B); }\\\n"
     298                 :            :         "static inline int N ## _truncate(NS ## builder_t *B, size_t len)\\\n"
     299                 :            :         "{ return flatcc_builder_truncate_string(B, len); }\n"
     300                 :            :         "\n",
     301                 :            :         nsc);
     302                 :            : 
     303                 :         10 :     fprintf(out->fp,
     304                 :            :         "#define __%sbuild_string(NS)\\\n"
     305                 :            :         "typedef NS ## ref_t NS ## string_ref_t;\\\n"
     306                 :            :         "static inline int NS ## string_start(NS ## builder_t *B)\\\n"
     307                 :            :         "{ return flatcc_builder_start_string(B); }\\\n"
     308                 :            :         "static inline NS ## string_ref_t NS ## string_end(NS ## builder_t *B)\\\n"
     309                 :            :         "{ return flatcc_builder_end_string(B); }\\\n"
     310                 :            :         "static inline NS ## ref_t NS ## string_create(NS ## builder_t *B, const char *s, size_t len)\\\n"
     311                 :            :         "{ return flatcc_builder_create_string(B, s, len); }\\\n"
     312                 :            :         "static inline NS ## ref_t NS ## string_create_str(NS ## builder_t *B, const char *s)\\\n"
     313                 :            :         "{ return flatcc_builder_create_string_str(B, s); }\\\n"
     314                 :            :         "static inline NS ## ref_t NS ## string_create_strn(NS ## builder_t *B, const char *s, size_t len)\\\n"
     315                 :            :         "{ return flatcc_builder_create_string_strn(B, s, len); }\\\n"
     316                 :            :         "static inline NS ## string_ref_t NS ## string_clone(NS ## builder_t *B, NS ## string_t string)\\\n"
     317                 :            :         "{ return flatcc_builder_create_string(B, string, NS ## string_len(string)); }\\\n"
     318                 :            :         "static inline NS ## string_ref_t NS ## string_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n"
     319                 :            :         "{ size_t n = NS ## string_len(string); if (index >= n) index = n; n -= index; if (len > n) len = n;\\\n"
     320                 :            :         "  return flatcc_builder_create_string(B, string + index, len); }\\\n"
     321                 :            :         "__%sbuild_string_ops(NS, NS ## string)\\\n"
     322                 :            :         "__%sbuild_offset_vector(NS, NS ## string)\n"
     323                 :            :         "\n",
     324                 :            :         nsc, nsc, nsc);
     325                 :         10 :     fprintf(out->fp,
     326                 :            :         "#define __%scopy_from_pe(P, P2, N) (*(P) = N ## _cast_from_pe(*P2), (P))\n"
     327                 :            :         "#define __%sfrom_pe(P, N) (*(P) = N ## _cast_from_pe(*P), (P))\n"
     328                 :            :         "#define __%scopy_to_pe(P, P2, N) (*(P) = N ## _cast_to_pe(*P2), (P))\n"
     329                 :            :         "#define __%sto_pe(P, N) (*(P) = N ## _cast_to_pe(*P), (P))\n",
     330                 :            :         nsc, nsc, nsc, nsc);
     331                 :         10 :     fprintf(out->fp,
     332                 :            :         "#define __%sdefine_scalar_primitives(NS, N, T)\\\n"
     333                 :            :         "static inline T *N ## _from_pe(T *p) { return __ ## NS ## from_pe(p, N); }\\\n"
     334                 :            :         "static inline T *N ## _to_pe(T *p) { return __ ## NS ## to_pe(p, N); }\\\n"
     335                 :            :         "static inline T *N ## _copy(T *p, const T *p2) { *p = *p2; return p; }\\\n"
     336                 :            :         "static inline T *N ## _copy_from_pe(T *p, const T *p2)\\\n"
     337                 :            :         "{ return __ ## NS ## copy_from_pe(p, p2, N); }\\\n"
     338                 :            :         "static inline T *N ## _copy_to_pe(T *p, const T *p2) \\\n"
     339                 :            :         "{ return __ ## NS ## copy_to_pe(p, p2, N); }\\\n"
     340                 :            :         "static inline T *N ## _assign(T *p, const T v0) { *p = v0; return p; }\\\n"
     341                 :            :         "static inline T *N ## _assign_from_pe(T *p, T v0)\\\n"
     342                 :            :         "{ *p = N ## _cast_from_pe(v0); return p; }\\\n"
     343                 :            :         "static inline T *N ## _assign_to_pe(T *p, T v0)\\\n"
     344                 :            :         "{ *p = N ## _cast_to_pe(v0); return p; }\n"
     345                 :            :         "#define __%sbuild_scalar(NS, N, T)\\\n"
     346                 :            :         "__ ## NS ## define_scalar_primitives(NS, N, T)\\\n"
     347                 :            :         "__ ## NS ## build_vector(NS, N, T, sizeof(T), sizeof(T))\n",
     348                 :            :         nsc, nsc);
     349                 :            : 
     350                 :         10 :     fprintf(out->fp,
     351                 :            :         "/* Depends on generated copy_to/from_pe functions, and the type. */\n"
     352                 :            :         "#define __%sdefine_struct_primitives(NS, N)\\\n"
     353                 :            :         "static inline N ## _t *N ##_to_pe(N ## _t *p)\\\n"
     354                 :            :         "{ if (!NS ## is_native_pe()) { N ## _copy_to_pe(p, p); }; return p; }\\\n"
     355                 :            :         "static inline N ## _t *N ##_from_pe(N ## _t *p)\\\n"
     356                 :            :         "{ if (!NS ## is_native_pe()) { N ## _copy_from_pe(p, p); }; return p; }\\\n"
     357                 :            :         "static inline N ## _t *N ## _clear(N ## _t *p) { return memset(p, 0, N ## __size()); }\n"
     358                 :            :         "\n"
     359                 :            :         "/* Depends on generated copy/assign_to/from_pe functions, and the type. */\n"
     360                 :            :         "#define __%sbuild_struct(NS, N, S, A, FID, TFID)\\\n"
     361                 :            :         "__ ## NS ## define_struct_primitives(NS, N)\\\n"
     362                 :            :         "typedef NS ## ref_t N ## _ref_t;\\\n"
     363                 :            :         "static inline N ## _t *N ## _start(NS ## builder_t *B)\\\n"
     364                 :            :         "{ return flatcc_builder_start_struct(B, S, A); }\\\n"
     365                 :            :         "static inline N ## _ref_t N ## _end(NS ## builder_t *B)\\\n"
     366                 :            :         "{ if (!NS ## is_native_pe()) { N ## _to_pe(flatcc_builder_struct_edit(B)); }\\\n"
     367                 :            :         "  return flatcc_builder_end_struct(B); }\\\n"
     368                 :            :         "static inline N ## _ref_t N ## _end_pe(NS ## builder_t *B)\\\n"
     369                 :            :         "{ return flatcc_builder_end_struct(B); }\\\n"
     370                 :            :         "static inline N ## _ref_t N ## _create(NS ## builder_t *B __ ## N ## _formal_args)\\\n"
     371                 :            :         "{ N ## _t *_p = N ## _start(B); if (!_p) return 0; N ##_assign_to_pe(_p __ ## N ## _call_args);\\\n"
     372                 :            :         "  return N ## _end_pe(B); }\\\n"
     373                 :            :         "__%sbuild_vector(NS, N, N ## _t, S, A)\\\n"
     374                 :            :         "__%sbuild_struct_root(NS, N, A, FID, TFID)\n"
     375                 :            :         "\n",
     376                 :            :         nsc, nsc, nsc, nsc);
     377                 :            : 
     378                 :         10 :     fprintf(out->fp,
     379                 :            :         "#define __%sbuild_table(NS, N, K)\\\n"
     380                 :            :         "typedef NS ## ref_t N ## _ref_t;\\\n"
     381                 :            :         "static inline int N ## _start(NS ## builder_t *B)\\\n"
     382                 :            :         "{ return flatcc_builder_start_table(B, K); }\\\n"
     383                 :            :         "static inline N ## _ref_t N ## _end(NS ## builder_t *B)\\\n"
     384                 :            :         "{ assert(flatcc_builder_check_required(B, __ ## N ## _required,\\\n"
     385                 :            :         "  sizeof(__ ## N ## _required) / sizeof(__ ## N ## _required[0]) - 1));\\\n"
     386                 :            :         "  return flatcc_builder_end_table(B); }\\\n"
     387                 :            :         "__%sbuild_offset_vector(NS, N)\n"
     388                 :            :         "\n",
     389                 :            :         nsc, nsc);
     390                 :            : 
     391                 :         10 :     fprintf(out->fp,
     392                 :            :         "#define __%sbuild_table_field(ID, NS, N, TN)\\\n"
     393                 :            :         "static inline int N ## _add(NS ## builder_t *B, TN ## _ref_t ref)\\\n"
     394                 :            :         "{ TN ## _ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ?\\\n"
     395                 :            :         "  ((*_p = ref), 0) : -1; }\\\n"
     396                 :            :         "static inline int N ## _start(NS ## builder_t *B)\\\n"
     397                 :            :         "{ return TN ## _start(B); }\\\n"
     398                 :            :         "static inline int N ## _end(NS ## builder_t *B)\\\n"
     399                 :            :         "{ return N ## _add(B, TN ## _end(B)); }\\\n"
     400                 :            :         "static inline TN ## _ref_t N ## _create(NS ## builder_t *B __ ## TN ##_formal_args)\\\n"
     401                 :            :         "{ return N ## _add(B, TN ## _create(B __ ## TN ## _call_args)); }\n"
     402                 :            :         "\n",
     403                 :            :         nsc);
     404                 :            : 
     405                 :         10 :     fprintf(out->fp,
     406                 :            :         "#define __%sbuild_union_field(ID, NS, N, TN)\\\n"
     407                 :            :         "static inline int N ## _add(NS ## builder_t *B, TN ## _union_ref_t uref)\\\n"
     408                 :            :         "{ NS ## ref_t *_p; TN ## _union_type_t *_pt; if (uref.type == TN ## _NONE) return 0; if (uref._member == 0) return -1;\\\n"
     409                 :            :         "  if (!(_pt = flatcc_builder_table_add(B, ID - 1, sizeof(*_pt), sizeof(_pt))) ||\\\n"
     410                 :            :         "  !(_p = flatcc_builder_table_add_offset(B, ID))) return -1; *_pt = uref.type; *_p = uref._member; return 0; }\\\n"
     411                 :            :         "static inline int N ## _add_type(NS ## builder_t *B, TN ## _union_type_t type)\\\n"
     412                 :            :         "{ TN ## _union_type_t *_pt; if (type == TN ## _NONE) return 0; return (_pt = flatcc_builder_table_add(B, ID - 1,\\\n"
     413                 :            :         "  sizeof(*_pt), sizeof(*_pt))) ? ((*_pt = type), 0) : -1; }\\\n"
     414                 :            :         "static inline int N ## _add_member(NS ## builder_t *B, TN ## _union_ref_t uref)\\\n"
     415                 :            :         "{ NS ## ref_t *p; if (uref.type == TN ## _NONE) return 0; return (p = flatcc_builder_table_add_offset(B, ID)) ?\\\n"
     416                 :            :         "  ((*p = uref._member), 0) : -1; }\n"
     417                 :            :         "\n",
     418                 :            :         nsc);
     419                 :            : 
     420                 :         10 :     fprintf(out->fp,
     421                 :            :         "/* M is the union member name and T is its type, i.e. the qualified name. */\n"
     422                 :            :         "#define __%sbuild_union_member_field(NS, N, NU, M, T)\\\n"
     423                 :            :         "static inline int N ## _ ## M ## _add(NS ## builder_t *B, T ## _ref_t ref)\\\n"
     424                 :            :         "{ return N ## _add(B, NU ## _as_ ## M (ref)); }\\\n"
     425                 :            :         "static inline int N ## _ ## M ## _start(NS ## builder_t *B)\\\n"
     426                 :            :         "{ return T ## _start(B); }\\\n"
     427                 :            :         "static inline int N ## _ ## M ## _end(NS ## builder_t *B)\\\n"
     428                 :            :         "{ return N ## _ ## M ## _add(B, T ## _end(B)); }\n"
     429                 :            :         "\n",
     430                 :            :         nsc);
     431                 :            : 
     432                 :         10 :     fprintf(out->fp,
     433                 :            :         "/* NS: common namespace, ID: table field id (not offset), TN: name of type T,\n"
     434                 :            :         " * S: sizeof of scalar type, A: alignment of type T, default value V of type T. */\n"
     435                 :            :         "#define __%sbuild_scalar_field(ID, NS, N, TN, T, S, A, V)\\\n"
     436                 :            :         "static inline int N ## _add(NS ## builder_t *B, const T v)\\\n"
     437                 :            :         "{ T *_p; if (v == V) return 0; if (!(_p = flatcc_builder_table_add(B, ID, S, A))) return -1;\\\n"
     438                 :            :         "  TN ## _assign_to_pe(_p, v); return 0; }\\\n"
     439                 :            :         "static inline int N ## _force_add(NS ## builder_t *B, const T v)\\\n"
     440                 :            :         "{ T *_p; if (!(_p = flatcc_builder_table_add(B, ID, S, A))) return -1;\\\n"
     441                 :            :         "  TN ## _assign_to_pe(_p, v); return 0; }\\\n"
     442                 :            :         "\n",
     443                 :            :         nsc);
     444                 :            : 
     445                 :         10 :     fprintf(out->fp,
     446                 :            :         "#define __%sbuild_struct_field(ID, NS, N, TN, S, A)\\\n"
     447                 :            :         "static inline TN ## _t *N ## _start(NS ## builder_t *B)\\\n"
     448                 :            :         "{ return flatcc_builder_table_add(B, ID, S, A); }\\\n"
     449                 :            :         "static inline int N ## _end(NS ## builder_t *B)\\\n"
     450                 :            :         "{ if (!NS ## is_native_pe()) { TN ## _to_pe(flatcc_builder_table_edit(B, S)); } return 0; }\\\n"
     451                 :            :         "static inline int N ## _end_pe(NS ## builder_t *B) { return 0; }\\\n"
     452                 :            :         "static inline int N ## _create(NS ## builder_t *B __ ## TN ## _formal_args)\\\n"
     453                 :            :         "{ TN ## _t *_p = N ## _start(B); if (!_p) return 0; TN ##_assign_to_pe(_p __ ## TN ## _call_args);\\\n"
     454                 :            :         " return 0; }\\\n"
     455                 :            :         "static inline int N ## _add(NS ## builder_t *B, const TN ## _t *p)\\\n"
     456                 :            :         "{ TN ## _t *_p = N ## _start(B); if (!_p) return -1; TN ##_copy_to_pe(_p, p); return 0; }\\\n"
     457                 :            :         "static inline int N ## _clone(NS ## builder_t *B, TN ## _struct_t p)\\\n"
     458                 :            :         "{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\n"
     459                 :            :         "\n",
     460                 :            :         nsc);
     461                 :            : 
     462                 :            :     /* This goes for scalar, struct, and enum vectors. */
     463                 :         10 :     fprintf(out->fp,
     464                 :            :         "#define __%sbuild_vector_field(ID, NS, N, TN, T)\\\n"
     465                 :            :         "static inline int N ## _add(NS ## builder_t *B, TN ## _vec_ref_t ref)\\\n"
     466                 :            :         "{ TN ## _vec_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\\\n"
     467                 :            :         "static inline int N ## _start(NS ## builder_t *B)\\\n"
     468                 :            :         "{ return TN ## _vec_start(B); }\\\n"
     469                 :            :         "static inline int N ## _end_pe(NS ## builder_t *B)\\\n"
     470                 :            :         "{ return N ## _add(B, TN ## _vec_end_pe(B)); }\\\n"
     471                 :            :         "static inline int N ## _end(NS ## builder_t *B)\\\n"
     472                 :            :         "{ return N ## _add(B, TN ## _vec_end(B)); }\\\n"
     473                 :            :         "static inline int N ## _create_pe(NS ## builder_t *B, T *data, size_t len)\\\n"
     474                 :            :         "{ return N ## _add(B, TN ## _vec_create_pe(B, data, len)); }\\\n"
     475                 :            :         "static inline int N ## _create(NS ## builder_t *B, T *data, size_t len)\\\n"
     476                 :            :         "{ return N ## _add(B, TN ## _vec_create(B, data, len)); }\\\n"
     477                 :            :         "static inline int N ## _clone(NS ## builder_t *B, TN ## _vec_t vec)\\\n"
     478                 :            :         "{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\\\n"
     479                 :            :         "static inline int N ## _slice(NS ## builder_t *B, TN ## _vec_t vec, size_t index, size_t len)\\\n"
     480                 :            :         "{ return N ## _add(B, TN ## _vec_slice(B, vec, index, len)); }\\\n"
     481                 :            :         "__%sbuild_vector_ops(NS, N, N, TN, T)\n"
     482                 :            :         "\n",
     483                 :            :         nsc, nsc);
     484                 :            : 
     485                 :         10 :     fprintf(out->fp,
     486                 :            :         "#define __%sbuild_offset_vector_field(ID, NS, N, TN)\\\n"
     487                 :            :         "static inline int N ## _add(NS ## builder_t *B, TN ## _vec_ref_t ref)\\\n"
     488                 :            :         "{ TN ## _vec_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\\\n"
     489                 :            :         "static inline int N ## _start(NS ## builder_t *B)\\\n"
     490                 :            :         "{ return flatcc_builder_start_offset_vector(B); }\\\n"
     491                 :            :         "static inline int N ## _end(NS ## builder_t *B)\\\n"
     492                 :            :         "{ return N ## _add(B, flatcc_builder_end_offset_vector(B)); }\\\n"
     493                 :            :         "static inline int N ## _create(NS ## builder_t *B, const TN ## _ref_t *data, size_t len)\\\n"
     494                 :            :         "{ return N ## _add(B, flatcc_builder_create_offset_vector(B, data, len)); }\\\n"
     495                 :            :         "__%sbuild_offset_vector_ops(NS, N, N, TN)\n"
     496                 :            :         "\n",
     497                 :            :         nsc, nsc);
     498                 :            : 
     499                 :         10 :     fprintf(out->fp,
     500                 :            :         "#define __%sbuild_string_field(ID, NS, N)\\\n"
     501                 :            :         "static inline int N ## _add(NS ## builder_t *B, NS ## string_ref_t ref)\\\n"
     502                 :            :         "{ NS ## string_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\\\n"
     503                 :            :         "static inline int N ## _start(NS ## builder_t *B)\\\n"
     504                 :            :         "{ return flatcc_builder_start_string(B); }\\\n"
     505                 :            :         "static inline int N ## _end(NS ## builder_t *B)\\\n"
     506                 :            :         "{ return N ## _add(B, flatcc_builder_end_string(B)); }\\\n"
     507                 :            :         "static inline int N ## _create(NS ## builder_t *B, const char *s, size_t len)\\\n"
     508                 :            :         "{ return N ## _add(B, flatcc_builder_create_string(B, s, len)); }\\\n"
     509                 :            :         "static inline int N ## _create_str(NS ## builder_t *B, const char *s)\\\n"
     510                 :            :         "{ return N ## _add(B, flatcc_builder_create_string_str(B, s)); }\\\n"
     511                 :            :         "static inline int N ## _create_strn(NS ## builder_t *B, const char *s, size_t max_len)\\\n"
     512                 :            :         "{ return N ## _add(B, flatcc_builder_create_string_strn(B, s, max_len)); }\\\n"
     513                 :            :         "static inline int N ## _clone(NS ## builder_t *B, NS ## string_t string)\\\n"
     514                 :            :         "{ return N ## _add(B, NS ## string_clone(B, string)); }\\\n"
     515                 :            :         "static inline int N ## _slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n"
     516                 :            :         "{ return N ## _add(B, NS ## string_slice(B, string, index, len)); }\\\n"
     517                 :            :         "__%sbuild_string_ops(NS, N)\n"
     518                 :            :         "\n",
     519                 :            :         nsc, nsc);
     520                 :            : 
     521                 :         10 :     fprintf(out->fp,
     522                 :            :         "#define __%sbuild_table_vector_field(ID, NS, N, TN)\\\n"
     523                 :            :         "__%sbuild_offset_vector_field(ID, NS, N, TN)\\\n"
     524                 :            :         "__%sbuild_table_vector_ops(NS, N, TN)\n"
     525                 :            :         "\n",
     526                 :            :         nsc, nsc, nsc);
     527                 :            : 
     528                 :         10 :     fprintf(out->fp,
     529                 :            :         "#define __%sbuild_string_vector_field(ID, NS, N)\\\n"
     530                 :            :         "__%sbuild_offset_vector_field(ID, NS, N, NS ## string)\\\n"
     531                 :            :         "__%sbuild_string_vector_ops(NS, N)\n"
     532                 :            :         "\n",
     533                 :            :         nsc, nsc, nsc);
     534                 :            : 
     535                 :         10 :     fprintf(out->fp, "#define __%suint8_formal_args , uint8_t v0\n", nsc);
     536                 :         10 :     fprintf(out->fp, "#define __%suint8_call_args , v0\n", nsc);
     537                 :         10 :     fprintf(out->fp, "#define __%sint8_formal_args , int8_t v0\n", nsc);
     538                 :         10 :     fprintf(out->fp, "#define __%sint8_call_args , v0\n", nsc);
     539                 :         10 :     fprintf(out->fp, "#define __%sbool_formal_args , %sbool_t v0\n", nsc, nsc);
     540                 :         10 :     fprintf(out->fp, "#define __%sbool_call_args , v0\n", nsc);
     541                 :         10 :     fprintf(out->fp, "#define __%suint16_formal_args , uint16_t v0\n", nsc);
     542                 :         10 :     fprintf(out->fp, "#define __%suint16_call_args , v0\n", nsc);
     543                 :         10 :     fprintf(out->fp, "#define __%suint32_formal_args , uint32_t v0\n", nsc);
     544                 :         10 :     fprintf(out->fp, "#define __%suint32_call_args , v0\n", nsc);
     545                 :         10 :     fprintf(out->fp, "#define __%suint64_formal_args , uint64_t v0\n", nsc);
     546                 :         10 :     fprintf(out->fp, "#define __%suint64_call_args , v0\n", nsc);
     547                 :         10 :     fprintf(out->fp, "#define __%sint16_formal_args , int16_t v0\n", nsc);
     548                 :         10 :     fprintf(out->fp, "#define __%sint16_call_args , v0\n", nsc);
     549                 :         10 :     fprintf(out->fp, "#define __%sint32_formal_args , int32_t v0\n", nsc);
     550                 :         10 :     fprintf(out->fp, "#define __%sint32_call_args , v0\n", nsc);
     551                 :         10 :     fprintf(out->fp, "#define __%sint64_formal_args , int64_t v0\n", nsc);
     552                 :         10 :     fprintf(out->fp, "#define __%sint64_call_args , v0\n", nsc);
     553                 :         10 :     fprintf(out->fp, "#define __%sfloat_formal_args , float v0\n", nsc);
     554                 :         10 :     fprintf(out->fp, "#define __%sfloat_call_args , v0\n", nsc);
     555                 :         10 :     fprintf(out->fp, "#define __%sdouble_formal_args , double v0\n", nsc);
     556                 :         10 :     fprintf(out->fp, "#define __%sdouble_call_args , v0\n", nsc);
     557                 :         10 :     fprintf(out->fp, "\n");
     558                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %suint8, uint8_t)\n", nsc, nsc, nsc);
     559                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sint8, int8_t)\n", nsc, nsc, nsc);
     560                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sbool, %sbool_t)\n", nsc, nsc, nsc, nsc);
     561                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %suint16, uint16_t)\n", nsc, nsc, nsc);
     562                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %suint32, uint32_t)\n", nsc, nsc, nsc);
     563                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %suint64, uint64_t)\n", nsc, nsc, nsc);
     564                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sint16, int16_t)\n", nsc, nsc, nsc);
     565                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sint32, int32_t)\n", nsc, nsc, nsc);
     566                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sint64, int64_t)\n", nsc, nsc, nsc);
     567                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sfloat, float)\n", nsc, nsc, nsc);
     568                 :         10 :     fprintf(out->fp, "__%sbuild_scalar(%s, %sdouble, double)\n", nsc, nsc, nsc);
     569                 :         10 :     fprintf(out->fp, "\n");
     570                 :         10 :     fprintf(out->fp, "__%sbuild_string(%s)\n", nsc, nsc);
     571                 :         10 :     fprintf(out->fp, "\n");
     572                 :            : 
     573                 :         10 :     fprintf(out->fp, "__%sbuild_buffer(%s)\n", nsc, nsc);
     574                 :            :     gen_pragma_pop(out);
     575                 :         10 :     fprintf(out->fp, "#endif /* %s_COMMON_BUILDER_H */\n", nscup);
     576                 :         10 :     return 0;
     577                 :            : }
     578                 :            : 
     579                 :         24 : static int gen_builder_pretext(fb_output_t *out)
     580                 :            : {
     581                 :         24 :     const char *nsc = out->nsc;
     582                 :         24 :     const char *nscup = out->nscup;
     583                 :            : 
     584                 :         24 :     fprintf(out->fp,
     585                 :            :         "#ifndef %s_BUILDER_H\n"
     586                 :            :         "#define %s_BUILDER_H\n",
     587                 :         24 :         out->S->basenameup, out->S->basenameup);
     588                 :            : 
     589                 :         24 :     fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n");
     590                 :         24 :     fprintf(out->fp, "#ifndef %s_READER_H\n", out->S->basenameup);
     591                 :         24 :     fprintf(out->fp, "#include \"%s_reader.h\"\n", out->S->basename);
     592                 :         24 :     fprintf(out->fp, "#endif\n");
     593                 :         24 :     fprintf(out->fp, "#ifndef %s_COMMON_BUILDER_H\n", nscup);
     594                 :         24 :     fprintf(out->fp, "#include \"%scommon_builder.h\"\n", nsc);
     595                 :         24 :     fprintf(out->fp, "#endif\n");
     596                 :            : 
     597                 :         24 :     fb_gen_c_includes(out, "_builder.h", "_BUILDER_H");
     598                 :            : 
     599                 :            :     gen_pragma_push(out);
     600                 :            : 
     601                 :            :     /*
     602                 :            :      * Even if defined in the reader header, we must redefine it here
     603                 :            :      * because another file might sneak in and update.
     604                 :            :      */
     605         [ +  + ]:         24 :     if (out->S->file_identifier.type == vt_string) {
     606                 :          8 :         fprintf(out->fp,
     607                 :            :             "#undef %sidentifier\n"
     608                 :            :             "#define %sidentifier \"%.*s\"\n",
     609                 :            :             nsc,
     610                 :            :             nsc, out->S->file_identifier.s.len, out->S->file_identifier.s.s);
     611                 :            :     } else {
     612                 :         16 :         fprintf(out->fp,
     613                 :            :             "#ifndef %sidentifier\n"
     614                 :            :             "#define %sidentifier 0\n"
     615                 :            :             "#endif\n",
     616                 :            :             nsc, nsc);
     617                 :            :     }
     618         [ +  + ]:         24 :     if (out->S->file_extension.type == vt_string) {
     619                 :          8 :         fprintf(out->fp,
     620                 :            :             "#undef %sextension\n"
     621                 :            :             "#define %sextension \".%.*s\"\n",
     622                 :            :             nsc,
     623                 :            :             nsc, out->S->file_extension.s.len, out->S->file_extension.s.s);
     624                 :            :     } else {
     625                 :         16 :         fprintf(out->fp,
     626                 :            :             /* Configured extensions include dot, schema does not. */
     627                 :            :             "#ifndef %sextension\n"
     628                 :            :             "#define %sextension \"%s\"\n"
     629                 :            :             "#endif\n",
     630                 :         16 :             nsc, nsc, out->opts->default_bin_ext);
     631                 :            :     }
     632                 :         24 :     fprintf(out->fp, "\n");
     633                 :         24 :     return 0;
     634                 :            : }
     635                 :            : 
     636                 :        310 : static int get_total_struct_field_count(fb_compound_type_t *ct)
     637                 :            : {
     638                 :            :     fb_member_t *member;
     639                 :            :     fb_symbol_t *sym;
     640                 :            :     int count = 0;
     641         [ +  + ]:        427 :     for (sym = ct->members; sym; sym = sym->link) {
     642                 :            :         member = (fb_member_t *)sym;
     643         [ +  + ]:        272 :         if (member->metadata_flags & fb_f_deprecated) {
     644                 :          2 :             continue;
     645                 :            :         }
     646         [ +  + ]:        270 :         switch (member->type.type) {
     647                 :            :         case vt_compound_type_ref:
     648         [ +  + ]:         55 :             if (member->type.ct->symbol.kind == fb_is_struct) {
     649                 :         35 :                 count += get_total_struct_field_count(member->type.ct);
     650                 :         35 :                 continue;
     651                 :            :             }
     652                 :            :             /* enum fall through. */
     653                 :            :         default:
     654                 :        235 :             ++count;
     655                 :            :         }
     656                 :            :     }
     657                 :        155 :     return count;
     658                 :            : }
     659                 :            : 
     660                 :       2248 : static inline void gen_comma(fb_output_t *out, int index, int count, int is_macro)
     661                 :            : {
     662         [ +  + ]:       1124 :     char *cont = is_macro ? "\\\n" : "\n";
     663                 :            : 
     664         [ +  - ]:       1124 :     if (count == 0) {
     665                 :            :         return;
     666                 :            :     }
     667         [ +  + ]:       1124 :     if (index == 0) {
     668         [ +  + ]:        243 :         if (count > 4) {
     669                 :         96 :             fprintf(out->fp, ",%s  ", cont);
     670                 :            :         } else {
     671                 :        147 :             fprintf(out->fp, ", ");
     672                 :            :         }
     673                 :            :     } else {
     674 [ +  + ][ +  + ]:        881 :         if (index % 4 || count - index <= 2) {
     675                 :        768 :             fprintf(out->fp, ", ");
     676                 :            :         } else {
     677                 :        113 :             fprintf(out->fp, ",%s  ", cont);
     678                 :            :         }
     679                 :            :     }
     680                 :            : }
     681                 :            : 
     682                 :        220 : static int gen_builder_struct_args(fb_output_t *out, fb_compound_type_t *ct, int index, int len, int is_macro)
     683                 :            : {
     684                 :        220 :     const char *nsc = out->nsc;
     685                 :            :     fb_member_t *member;
     686                 :            :     fb_symbol_t *sym;
     687                 :            :     const char *tname, *tname_ns;
     688                 :            :     fb_scoped_name_t snref;
     689                 :            : 
     690                 :        220 :     fb_clear(snref);
     691                 :            : 
     692         [ +  + ]:        596 :     for (sym = ct->members; sym; sym = sym->link) {
     693                 :            :         member = (fb_member_t *)sym;
     694         [ +  + ]:        376 :         if (member->metadata_flags & fb_f_deprecated) {
     695                 :          4 :             continue;
     696                 :            :         }
     697      [ +  +  - ]:        372 :         switch (member->type.type) {
     698                 :            :         case vt_compound_type_ref:
     699         [ +  + ]:         92 :             if (member->type.ct->symbol.kind == fb_is_struct) {
     700                 :         52 :                 index = gen_builder_struct_args(out, member->type.ct, index, len, is_macro);
     701                 :         52 :                 continue;
     702                 :            :             }
     703                 :         40 :             gen_comma(out, index, len, is_macro);
     704                 :         40 :             fb_compound_name(member->type.ct, &snref);
     705                 :         40 :             fprintf(out->fp, "%s_enum_t v%i", snref.text, index++);
     706                 :            :             break;
     707                 :            :         case vt_scalar_type:
     708                 :        280 :             gen_comma(out, index, len, is_macro);
     709                 :        280 :             tname_ns = scalar_type_ns(member->type.st, nsc);
     710                 :        280 :             tname = scalar_type_name(member->type.st);
     711                 :        280 :             fprintf(out->fp, "%s%s v%i", tname_ns, tname, index++);
     712                 :            :             break;
     713                 :            :         default:
     714                 :          0 :             gen_panic(out, "internal error: unexpected struct member type");
     715                 :            :             continue;
     716                 :            :         }
     717                 :            :     }
     718                 :        220 :     return index;
     719                 :            : }
     720                 :            : 
     721                 :         72 : static int gen_builder_struct_call_list(fb_output_t *out, fb_compound_type_t *ct, int index, int arg_count, int is_macro)
     722                 :            : {
     723                 :            :     int i;
     724                 :         72 :     int len = get_total_struct_field_count(ct);
     725                 :            : 
     726         [ +  + ]:        203 :     for (i = 0; i < len; ++i) {
     727                 :        131 :         gen_comma(out, i, arg_count, is_macro);
     728                 :        131 :         fprintf(out->fp, "v%i", index++);
     729                 :            :     }
     730                 :         72 :     return index;
     731                 :            : }
     732                 :            : 
     733                 :            : enum { no_conversion, convert_from_pe, convert_to_pe };
     734                 :            : 
     735                 :            : /* Note: returned index is not correct when using from_ptr since it doesn't track arguments, but it shouldn't matter. */
     736                 :        252 : static int gen_builder_struct_field_assign(fb_output_t *out, fb_compound_type_t *ct, int index, int arg_count, int conversion, int from_ptr)
     737                 :            : {
     738                 :        252 :     const char *nsc = out->nsc;
     739                 :            :     fb_member_t *member;
     740                 :            :     fb_symbol_t *sym;
     741                 :            :     int n;
     742                 :            :     const char *s;
     743                 :            :     int deprecated_index = 0;
     744                 :            :     const char *kind, *tprefix;
     745                 :            :     fb_scoped_name_t snref;
     746                 :            : 
     747                 :        252 :     fb_clear(snref);
     748      [ +  +  + ]:        252 :     switch (conversion) {
     749                 :            :     case convert_to_pe: kind = "_to_pe"; break;
     750                 :            :     case convert_from_pe: kind = "_from_pe"; break;
     751                 :            :     default: kind = ""; break;
     752                 :            :     }
     753         [ +  + ]:        696 :     for (sym = ct->members; sym; sym = sym->link) {
     754                 :            :         member = (fb_member_t *)sym;
     755                 :            :         symbol_name(sym, &n, &s);
     756                 :            : 
     757         [ +  + ]:        444 :         if (index > 0) {
     758         [ +  + ]:        318 :             if (index % 4 == 0) {
     759                 :         48 :                 fprintf(out->fp, ";\n  ");
     760                 :            :             } else {
     761                 :        270 :                 fprintf(out->fp, "; ");
     762                 :            :             }
     763                 :            :         }
     764      [ +  +  - ]:        444 :         switch (member->type.type) {
     765                 :            :         case vt_compound_type_ref:
     766                 :        126 :             fb_compound_name(member->type.ct, &snref);
     767         [ +  + ]:        126 :             if (member->type.ct->symbol.kind == fb_is_struct) {
     768         [ +  + ]:         66 :                 if (member->metadata_flags & fb_f_deprecated) {
     769                 :          6 :                     fprintf(out->fp, "memset(p->__deprecated%i, 0, sizeof(*p->__deprecated%i))",
     770                 :            :                             deprecated_index, deprecated_index);
     771                 :          6 :                     deprecated_index++;
     772                 :          6 :                     index += get_total_struct_field_count(member->type.ct);
     773                 :          6 :                     continue;
     774                 :            :                 }
     775         [ +  + ]:         60 :                 if (from_ptr) {
     776                 :         30 :                     fprintf(out->fp, "%s_copy%s(&p->%.*s, &p2->%.*s)", snref.text, kind, n, s, n, s);
     777                 :            :                     /* `index` does not count children, but it doesn't matter here. */
     778                 :         30 :                     ++index;
     779                 :            :                 } else {
     780                 :         30 :                     fprintf(out->fp, "%s_assign%s(&p->%.*s", snref.text, kind, n, s);
     781                 :         30 :                     index = gen_builder_struct_call_list(out, member->type.ct, index, arg_count, 0);
     782                 :         30 :                     fprintf(out->fp, ")");
     783                 :            :                 }
     784                 :         60 :                 continue;
     785                 :            :             }
     786         [ -  + ]:         60 :             if (member->metadata_flags & fb_f_deprecated) {
     787                 :          0 :                 fprintf(out->fp, "p->__deprecated%i = 0", deprecated_index++);
     788                 :          0 :                 ++index;
     789                 :          0 :                 continue;
     790                 :            :             }
     791         [ +  + ]:         60 :             switch (member->size == 1 ? no_conversion : conversion) {
              [ +  +  + ]
     792                 :            :             case convert_from_pe:
     793         [ +  + ]:          2 :                 if (from_ptr) {
     794                 :          1 :                     fprintf(out->fp, "%s_copy_from_pe(&p->%.*s, &p2->%.*s)",
     795                 :            :                             snref.text, n, s, n, s);
     796                 :            :                 } else {
     797                 :          1 :                     fprintf(out->fp, "%s_assign_from_pe(&p->%.*s, v%i)",
     798                 :            :                             snref.text, n, s, index);
     799                 :            :                 }
     800                 :            :                 break;
     801                 :            :             case convert_to_pe:
     802         [ +  + ]:          2 :                 if (from_ptr) {
     803                 :          1 :                     fprintf(out->fp, "%s_copy_to_pe(&p->%.*s, &p2->%.*s)",
     804                 :            :                             snref.text, n, s, n, s);
     805                 :            :                 } else {
     806                 :          1 :                     fprintf(out->fp, "%s_assign_to_pe(&p->%.*s, v%i)",
     807                 :            :                             snref.text, n, s, index);
     808                 :            :                 }
     809                 :            :                 break;
     810                 :            :             default:
     811         [ +  + ]:         56 :                 if (from_ptr) {
     812                 :         28 :                     fprintf(out->fp, "p->%.*s = p2->%.*s", n, s, n, s);
     813                 :            :                 } else {
     814                 :         28 :                     fprintf(out->fp, "p->%.*s = v%i", n, s, index);
     815                 :            :                 }
     816                 :            :                 break;
     817                 :            :             }
     818                 :         60 :             ++index;
     819                 :         60 :             continue;
     820                 :            :         case vt_scalar_type:
     821                 :        318 :             tprefix = scalar_type_prefix(member->type.st);
     822         [ -  + ]:        318 :             if (member->metadata_flags & fb_f_deprecated) {
     823                 :          0 :                 fprintf(out->fp, "p->__deprecated%i = 0", deprecated_index++);
     824                 :          0 :                 ++index;
     825                 :          0 :                 continue;
     826                 :            :             }
     827         [ +  + ]:        318 :             switch (member->size == 1 ? no_conversion : conversion) {
              [ +  +  + ]
     828                 :            :             case convert_from_pe:
     829         [ +  + ]:         82 :                 if (from_ptr) {
     830                 :         41 :                     fprintf(out->fp, "%s%s_copy_from_pe(&p->%.*s, &p2->%.*s)",
     831                 :            :                             nsc, tprefix, n, s, n, s);
     832                 :            :                 } else {
     833                 :         41 :                     fprintf(out->fp, "%s%s_assign_from_pe(&p->%.*s, v%i)",
     834                 :            :                             nsc, tprefix, n, s, index);
     835                 :            :                 }
     836                 :            :                 break;
     837                 :            :             case convert_to_pe:
     838         [ +  + ]:         82 :                 if (from_ptr) {
     839                 :         41 :                     fprintf(out->fp, "%s%s_copy_to_pe(&p->%.*s, &p2->%.*s)",
     840                 :            :                             nsc, tprefix, n, s, n, s);
     841                 :            :                 } else {
     842                 :         41 :                     fprintf(out->fp, "%s%s_assign_to_pe(&p->%.*s, v%i)",
     843                 :            :                             nsc, tprefix, n, s, index);
     844                 :            :                 }
     845                 :            :                 break;
     846                 :            :             default:
     847         [ +  + ]:        154 :                 if (from_ptr) {
     848                 :         77 :                     fprintf(out->fp, "p->%.*s = p2->%.*s", n, s, n, s);
     849                 :            :                 } else {
     850                 :         77 :                     fprintf(out->fp, "p->%.*s = v%i", n, s, index);
     851                 :            :                 }
     852                 :            :                 break;
     853                 :            :             }
     854                 :        318 :             ++index;
     855                 :            :             break;
     856                 :            :         default:
     857                 :          0 :             gen_panic(out, "internal error: type error");
     858                 :            :             continue;
     859                 :            :         }
     860                 :            :     }
     861         [ +  + ]:        252 :     if (arg_count > 0) {
     862                 :        126 :         fprintf(out->fp, ";\n  ");
     863                 :            :     }
     864                 :        252 :     return index;
     865                 :            : }
     866                 :            : 
     867                 :         42 : static void gen_builder_struct(fb_output_t *out, fb_compound_type_t *ct)
     868                 :            : {
     869                 :         42 :     const char *nsc = out->nsc;
     870                 :            :     int arg_count;
     871                 :            :     fb_scoped_name_t snt;
     872                 :            : 
     873                 :         42 :     fb_clear(snt);
     874                 :            :     assert(ct->symbol.kind == fb_is_struct);
     875                 :            : 
     876                 :            :     fb_compound_name(ct, &snt);
     877                 :            : 
     878                 :         42 :     arg_count = get_total_struct_field_count(ct);
     879                 :         42 :     fprintf(out->fp, "#define __%s_formal_args ", snt.text);
     880                 :         42 :     gen_builder_struct_args(out, ct, 0, arg_count, 1);
     881                 :         42 :     fprintf(out->fp, "\n#define __%s_call_args ", snt.text);
     882                 :         42 :     gen_builder_struct_call_list(out, ct, 0, arg_count, 1);
     883                 :         42 :     fprintf(out->fp, "\n");
     884                 :         42 :     fprintf(out->fp,
     885                 :            :             "static inline %s_t *%s_assign(%s_t *p",
     886                 :            :             snt.text, snt.text, snt.text);
     887                 :         42 :     gen_builder_struct_args(out, ct, 0, arg_count, 0);
     888                 :         42 :     fprintf(out->fp, ")\n{ ");
     889                 :         42 :     gen_builder_struct_field_assign(out, ct, 0, arg_count, no_conversion, 0);
     890                 :         42 :     fprintf(out->fp, "return p; }\n");
     891                 :         42 :     fprintf(out->fp,
     892                 :            :             "static inline %s_t *%s_copy(%s_t *p, const %s_t *p2)\n",
     893                 :            :             snt.text, snt.text, snt.text, snt.text);
     894                 :         42 :     fprintf(out->fp, "{ ");
     895                 :         42 :     gen_builder_struct_field_assign(out, ct, 0, arg_count, no_conversion, 1);
     896                 :         42 :     fprintf(out->fp, "return p; }\n");
     897                 :         42 :     fprintf(out->fp,
     898                 :            :             "static inline %s_t *%s_assign_to_pe(%s_t *p",
     899                 :            :             snt.text, snt.text, snt.text);
     900                 :         42 :     gen_builder_struct_args(out, ct, 0, arg_count, 0);
     901                 :         42 :     fprintf(out->fp, ")\n{ ");
     902                 :         42 :     gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_to_pe, 0);
     903                 :         42 :     fprintf(out->fp, "return p; }\n");
     904                 :         42 :     fprintf(out->fp,
     905                 :            :             "static inline %s_t *%s_copy_to_pe(%s_t *p, const %s_t *p2)\n",
     906                 :            :             snt.text, snt.text, snt.text, snt.text);
     907                 :         42 :     fprintf(out->fp, "{ ");
     908                 :         42 :     gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_to_pe, 1);
     909                 :         42 :     fprintf(out->fp, "return p; }\n");
     910                 :         42 :     fprintf(out->fp,
     911                 :            :             "static inline %s_t *%s_assign_from_pe(%s_t *p",
     912                 :            :             snt.text, snt.text, snt.text);
     913                 :         42 :     gen_builder_struct_args(out, ct, 0, arg_count, 0);
     914                 :         42 :     fprintf(out->fp, ")\n{ ");
     915                 :         42 :     gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_from_pe, 0);
     916                 :         42 :     fprintf(out->fp, "return p; }\n");
     917                 :         42 :     fprintf(out->fp,
     918                 :            :             "static inline %s_t *%s_copy_from_pe(%s_t *p, const %s_t *p2)\n",
     919                 :            :             snt.text, snt.text, snt.text, snt.text);
     920                 :         42 :     fprintf(out->fp, "{ ");
     921                 :         42 :     gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_from_pe, 1);
     922                 :         42 :     fprintf(out->fp, "return p; }\n");
     923                 :         42 :     fprintf(out->fp, "__%sbuild_struct(%s, %s, %llu, %u, %s_identifier, %s_type_identifier)\n",
     924                 :         84 :             nsc, nsc, snt.text, llu(ct->size), ct->align, snt.text, snt.text);
     925                 :         42 : }
     926                 :            : 
     927                 :            : static int get_create_table_arg_count(fb_compound_type_t *ct)
     928                 :            : {
     929                 :            :     fb_member_t *member;
     930                 :            :     fb_symbol_t *sym;
     931                 :            :     int count = 0;
     932                 :            : 
     933 [ +  + ][ +  + ]:        816 :     for (sym = ct->members; sym; sym = sym->link) {
     934                 :            :         member = (fb_member_t *)sym;
     935 [ +  + ][ +  + ]:        690 :         if (member->metadata_flags & fb_f_deprecated) {
     936                 :         18 :             continue;
     937                 :            :         }
     938                 :        672 :         ++count;
     939                 :            :     }
     940                 :            :     return count;
     941                 :            : }
     942                 :            : 
     943                 :        126 : static int gen_builder_table_call_list(fb_output_t *out, fb_compound_type_t *ct, int arg_count, int is_macro)
     944                 :            : {
     945                 :            :     fb_member_t *member;
     946                 :            :     fb_symbol_t *sym;
     947                 :            :     int index = 0;
     948                 :            : 
     949         [ +  + ]:        408 :     for (sym = ct->members; sym; sym = sym->link) {
     950                 :            :         member = (fb_member_t *)sym;
     951         [ +  + ]:        345 :         if (member->metadata_flags & fb_f_deprecated) {
     952                 :          9 :             continue;
     953                 :            :         }
     954                 :        336 :         gen_comma(out, index, arg_count, is_macro);
     955                 :        336 :         fprintf(out->fp, "v%llu", llu(member->id));
     956                 :        336 :         ++index;
     957                 :            :     }
     958                 :         63 :     return index;
     959                 :            : }
     960                 :            : 
     961                 :            : 
     962                 :         63 : static int gen_required_table_fields(fb_output_t *out, fb_compound_type_t *ct)
     963                 :            : {
     964                 :         63 :     const char *nsc = out->nsc;
     965                 :            :     fb_member_t *member;
     966                 :            :     fb_symbol_t *sym;
     967                 :            :     int index;
     968                 :            :     int arg_count;
     969                 :            :     fb_scoped_name_t snt;
     970                 :            : 
     971                 :         63 :     fb_clear(snt);
     972                 :            :     arg_count = get_create_table_arg_count(ct);
     973                 :            :     index = 0;
     974                 :            :     fb_compound_name(ct, &snt);
     975                 :         63 :     fprintf(out->fp, "static const %svoffset_t __%s_required[] = {", nsc, snt.text);
     976         [ +  + ]:        408 :     for (sym = ct->members; sym; sym = sym->link) {
     977                 :            :         member = (fb_member_t *)sym;
     978         [ +  + ]:        345 :         if (member->metadata_flags & fb_f_deprecated) {
     979                 :          9 :             continue;
     980                 :            :         }
     981         [ +  + ]:        336 :         if (member->metadata_flags & fb_f_required) {
     982         [ +  + ]:         10 :             if (index > 0) {
     983                 :          1 :                 gen_comma(out, index, arg_count, 0);
     984                 :            :             } else {
     985                 :          9 :                 fprintf(out->fp, " ");
     986                 :            :             }
     987                 :         10 :             fprintf(out->fp, "%u", (unsigned)member->id);
     988                 :         10 :             index++;
     989                 :            :         }
     990                 :            :     }
     991                 :            :     /* Add extra element to avoid null arrays. */
     992         [ +  + ]:         63 :     if (index > 0) {
     993                 :          9 :         fprintf(out->fp, ", 0 };\n");
     994                 :            :     } else {
     995                 :         54 :         fprintf(out->fp, "0 };\n");
     996                 :            :     }
     997                 :         63 :     return index;
     998                 :            : }
     999                 :            : 
    1000                 :         63 : static int gen_builder_table_args(fb_output_t *out, fb_compound_type_t *ct, int arg_count, int is_macro)
    1001                 :            : {
    1002                 :         63 :     const char *nsc = out->nsc;
    1003                 :            :     fb_symbol_t *sym;
    1004                 :            :     fb_member_t *member;
    1005                 :            :     const char *tname, *tname_ns;
    1006                 :            :     int index;
    1007                 :            :     fb_scoped_name_t snref;
    1008                 :            : 
    1009                 :         63 :     fb_clear(snref);
    1010                 :            :     /* Just to help the comma. */
    1011                 :            :     index = 0;
    1012                 :            :     /* We use the id to name arguments so sorted assignment can find the arguments trivially. */
    1013         [ +  + ]:        408 :     for (sym = ct->members; sym; sym = sym->link) {
    1014                 :            :         member = (fb_member_t *)sym;
    1015         [ +  + ]:        345 :         if (member->metadata_flags & fb_f_deprecated) {
    1016                 :          9 :             continue;
    1017                 :            :         }
    1018                 :        336 :         gen_comma(out, index++, arg_count, is_macro);
    1019   [ +  +  +  +  :        336 :         switch (member->type.type) {
                +  +  - ]
    1020                 :            :         case vt_compound_type_ref:
    1021                 :        109 :             fb_compound_name(member->type.ct, &snref);
    1022   [ +  +  +  +  :        109 :             switch (member->type.ct->symbol.kind) {
                      - ]
    1023                 :            :             case fb_is_struct:
    1024                 :         27 :                 fprintf(out->fp, "%s_t *v%llu", snref.text, llu(member->id));
    1025                 :            :                 break;
    1026                 :            :             case fb_is_enum:
    1027                 :         48 :                 fprintf(out->fp, "%s_enum_t v%llu", snref.text, llu(member->id));
    1028                 :            :                 break;
    1029                 :            :             case fb_is_table:
    1030                 :         23 :                 fprintf(out->fp, "%s_ref_t v%llu", snref.text, llu(member->id));
    1031                 :            :                 break;
    1032                 :            :             case fb_is_union:
    1033                 :            :                 /* Unions jump an index because it is two fields. */
    1034                 :         11 :                 fprintf(out->fp, "%s_union_ref_t v%llu", snref.text, llu(member->id));
    1035                 :            :                 break;
    1036                 :            :             default:
    1037                 :          0 :                 gen_panic(out, "internal error: unexpected table field type");
    1038                 :            :                 continue;
    1039                 :            :             }
    1040                 :            :             break;
    1041                 :            :         case vt_vector_compound_type_ref:
    1042                 :         18 :             fb_compound_name(member->type.ct, &snref);
    1043 [ +  - ][ +  - ]:         18 :             switch (member->type.ct->symbol.kind) {
    1044                 :            :             case fb_is_struct:
    1045                 :            :             case fb_is_enum:
    1046                 :            :             case fb_is_table:
    1047                 :         18 :                 fprintf(out->fp, "%s_vec_ref_t v%llu", snref.text, llu(member->id));
    1048                 :            :                 break;
    1049                 :            :             /* There are no union vectors. */
    1050                 :            :             default:
    1051                 :          0 :                 gen_panic(out, "internal error: unexpected table table type");
    1052                 :            :                 continue;
    1053                 :            :             }
    1054                 :            :             break;
    1055                 :            :         case vt_scalar_type:
    1056                 :        147 :             tname_ns = scalar_type_ns(member->type.st, nsc);
    1057                 :        147 :             tname = scalar_type_name(member->type.st);
    1058                 :        147 :             fprintf(out->fp, "%s%s v%llu", tname_ns, tname, llu(member->id));
    1059                 :            :             break;
    1060                 :            :         case vt_vector_type:
    1061                 :         25 :             tname = scalar_type_prefix(member->type.st);
    1062                 :         25 :             fprintf(out->fp, "%s%s_vec_ref_t v%llu", nsc, tname, llu(member->id));
    1063                 :            :             break;
    1064                 :            :         case vt_string_type:
    1065                 :         27 :             fprintf(out->fp, "%sstring_ref_t v%llu", nsc, llu(member->id));
    1066                 :            :             break;
    1067                 :            :         case vt_vector_string_type:
    1068                 :         10 :             fprintf(out->fp, "%sstring_vec_ref_t v%llu", nsc, llu(member->id));
    1069                 :            :             break;
    1070                 :            :         default:
    1071                 :          0 :             gen_panic(out, "internal error: unexpected struct member type");
    1072                 :            :             continue;
    1073                 :            :         }
    1074                 :            :     }
    1075                 :         63 :     return index;
    1076                 :            : }
    1077                 :            : 
    1078                 :         63 : static int gen_builder_create_table_decl(fb_output_t *out, fb_compound_type_t *ct)
    1079                 :            : {
    1080                 :         63 :     const char *nsc = out->nsc;
    1081                 :            :     int arg_count;
    1082                 :            :     fb_scoped_name_t snt;
    1083                 :            : 
    1084                 :         63 :     fb_clear(snt);
    1085                 :            :     fb_compound_name(ct, &snt);
    1086                 :            : 
    1087                 :            :     arg_count = get_create_table_arg_count(ct);
    1088                 :         63 :     fprintf(out->fp, "#define __%s_formal_args ", snt.text);
    1089                 :         63 :     gen_builder_table_args(out, ct, arg_count, 1);
    1090                 :         63 :     fprintf(out->fp, "\n#define __%s_call_args ", snt.text);
    1091                 :         63 :     gen_builder_table_call_list(out, ct, arg_count, 1);
    1092                 :         63 :     fprintf(out->fp, "\n");
    1093                 :            : 
    1094                 :         63 :     fprintf(out->fp,
    1095                 :            :             "static inline %s_ref_t %s_create(%sbuilder_t *B __%s_formal_args);\n",
    1096                 :            :             snt.text, snt.text, nsc, snt.text);
    1097                 :         63 :     return 0;
    1098                 :            : }
    1099                 :            : 
    1100                 :         63 : static int gen_builder_create_table(fb_output_t *out, fb_compound_type_t *ct)
    1101                 :            : {
    1102                 :         63 :     const char *nsc = out->nsc;
    1103                 :            :     fb_member_t *member;
    1104                 :            :     int n;
    1105                 :            :     const char *s;
    1106                 :         63 :     int patch_union = !(ct->metadata_flags & fb_f_original_order);
    1107                 :            :     int has_union = 0;
    1108                 :            :     fb_scoped_name_t snt;
    1109                 :            : 
    1110                 :         63 :     fb_clear(snt);
    1111                 :            :     fb_compound_name(ct, &snt);
    1112                 :            : 
    1113                 :         63 :     fprintf(out->fp,
    1114                 :            :             "static inline %s_ref_t %s_create(%sbuilder_t *B __%s_formal_args)\n",
    1115                 :            :             snt.text, snt.text, nsc, snt.text);
    1116                 :            : 
    1117                 :         63 :     fprintf(out->fp, "{\n    if (%s_start(B)", snt.text);
    1118         [ +  + ]:        408 :     for (member = ct->ordered_members; member; member = member->order) {
    1119         [ +  + ]:        345 :         if (member->metadata_flags & fb_f_deprecated) {
    1120                 :          9 :             continue;
    1121                 :            :         }
    1122                 :            :         symbol_name(&member->symbol, &n, &s);
    1123 [ +  + ][ +  + ]:        336 :         if (member->type.type == vt_compound_type_ref && member->type.ct->symbol.kind == fb_is_union) {
    1124                 :            :             has_union = 1;
    1125         [ +  + ]:         11 :             if (patch_union) {
    1126                 :         10 :                 fprintf(out->fp, "\n        || %s_%.*s_add_member(B, v%llu)", snt.text, n, s, llu(member->id));
    1127                 :         10 :                 continue;
    1128                 :            :             }
    1129                 :            :         }
    1130                 :        326 :         fprintf(out->fp, "\n        || %s_%.*s_add(B, v%llu)", snt.text, n, s, llu(member->id));
    1131                 :            :     }
    1132         [ +  + ]:         63 :     if (patch_union && has_union) {
    1133         [ +  + ]:        207 :         for (member = ct->ordered_members; member; member = member->order) {
    1134         [ +  + ]:        197 :             if (member->metadata_flags & fb_f_deprecated) {
    1135                 :          8 :                 continue;
    1136                 :            :             }
    1137 [ +  + ][ +  + ]:        189 :             if (member->type.type == vt_compound_type_ref && member->type.ct->symbol.kind == fb_is_union) {
    1138                 :            :                 symbol_name(&member->symbol, &n, &s);
    1139                 :         10 :                 fprintf(out->fp, "\n        || %s_%.*s_add_type(B, v%llu.type)", snt.text, n, s, llu(member->id));
    1140                 :            :             }
    1141                 :            :         }
    1142                 :            :     }
    1143                 :         63 :     fprintf(out->fp, ") {\n        return 0;\n    }\n    return %s_end(B);\n}\n", snt.text);
    1144                 :         63 :     return 0;
    1145                 :            : }
    1146                 :            : 
    1147                 :         24 : static int gen_builder_structs(fb_output_t *out)
    1148                 :            : {
    1149                 :            :     fb_compound_type_t *ct;
    1150                 :            : 
    1151                 :            :     /* Generate structs in topologically sorted order. */
    1152         [ +  + ]:         66 :     for (ct = out->S->ordered_structs; ct; ct = ct->order) {
    1153                 :         42 :         gen_builder_struct(out, ct);
    1154                 :         42 :         fprintf(out->fp, "\n");
    1155                 :            :     }
    1156                 :         24 :     return 0;
    1157                 :            : }
    1158                 :            : 
    1159                 :         63 : static int gen_builder_table(fb_output_t *out, fb_compound_type_t *ct)
    1160                 :            : {
    1161                 :         63 :     const char *nsc = out->nsc;
    1162                 :            :     fb_scoped_name_t snt;
    1163                 :            : 
    1164                 :         63 :     fb_clear(snt);
    1165                 :            :     fb_compound_name(ct, &snt);
    1166                 :            : 
    1167                 :         63 :     fprintf(out->fp, "__%sbuild_table(%s, %s, %llu)\n",
    1168                 :         63 :             nsc, nsc, snt.text, llu(ct->count));
    1169                 :         63 :     return 0;
    1170                 :            : }
    1171                 :            : 
    1172                 :         63 : static int gen_builder_table_prolog(fb_output_t *out, fb_compound_type_t *ct)
    1173                 :            : {
    1174                 :         63 :     const char *nsc = out->nsc;
    1175                 :            :     fb_scoped_name_t snt;
    1176                 :            : 
    1177                 :         63 :     fb_clear(snt);
    1178                 :            :     fb_compound_name(ct, &snt);
    1179                 :            : 
    1180                 :         63 :     fprintf(out->fp, "__%sbuild_table_prolog(%s, %s, %s_identifier, %s_type_identifier)\n",
    1181                 :            :             nsc, nsc, snt.text, snt.text, snt.text);
    1182                 :         63 :     return 0;
    1183                 :            : }
    1184                 :            : 
    1185                 :         11 : static int gen_union_member_fields(fb_output_t *out, const char *st, int n, const char *s, fb_compound_type_t *ct)
    1186                 :            : {
    1187                 :         11 :     const char *nsc = out->nsc;
    1188                 :            :     fb_symbol_t *sym;
    1189                 :            :     fb_member_t *member;
    1190                 :            :     const char *su;
    1191                 :            :     int nu;
    1192                 :            :     fb_scoped_name_t snref;
    1193                 :            :     fb_scoped_name_t snu;
    1194                 :            : 
    1195                 :         11 :     fb_clear(snref);
    1196                 :         11 :     fb_clear(snu);
    1197                 :            :     fb_compound_name(ct, &snref);
    1198         [ +  + ]:         46 :     for (sym = ct->members; sym; sym = sym->link) {
    1199                 :            :         member = (fb_member_t *)sym;
    1200         [ +  + ]:         35 :         switch (member->type.type) {
    1201                 :            :         case vt_compound_type_ref:
    1202                 :         24 :             fb_compound_name(member->type.ct, &snu);
    1203                 :            :             symbol_name(sym, &nu, &su);
    1204                 :         24 :             fprintf(out->fp,
    1205                 :            :                     "__%sbuild_union_member_field(%s, %s_%.*s, %s, %.*s, %s)\n",
    1206                 :            :                     nsc, nsc, st, n, s, snref.text, nu, su, snu.text);
    1207                 :         24 :             break;
    1208                 :            :         default:
    1209                 :            :             break;
    1210                 :            :         }
    1211                 :            :     }
    1212                 :         11 :     return 0;
    1213                 :            : }
    1214                 :            : 
    1215                 :         63 : static int gen_builder_table_fields(fb_output_t *out, fb_compound_type_t *ct)
    1216                 :            : {
    1217                 :         63 :     const char *nsc = out->nsc;
    1218                 :            :     fb_member_t *member;
    1219                 :            :     fb_symbol_t *sym;
    1220                 :            :     const char *s, *tprefix, *tname, *tname_ns;
    1221                 :            :     int n;
    1222                 :            :     fb_scoped_name_t snt;
    1223                 :            :     fb_scoped_name_t snref;
    1224                 :            : 
    1225                 :         63 :     fb_clear(snt);
    1226                 :         63 :     fb_clear(snref);
    1227                 :            :     fb_compound_name(ct, &snt);
    1228                 :            : 
    1229         [ +  + ]:        408 :     for (sym = ct->members; sym; sym = sym->link) {
    1230                 :            :         member = (fb_member_t *)sym;
    1231                 :            :         symbol_name(&member->symbol, &n, &s);
    1232         [ +  + ]:        345 :         if (member->metadata_flags & fb_f_deprecated) {
    1233                 :          9 :             fprintf(out->fp, "/* Skipping build of deprecated field: '%s_%.*s' */\n\n", snt.text, n, s);
    1234                 :          9 :             continue;
    1235                 :            :         }
    1236   [ +  +  +  +  :        336 :         switch (member->type.type) {
                +  +  - ]
    1237                 :            :         case vt_scalar_type:
    1238                 :        147 :             tname_ns = scalar_type_ns(member->type.st, nsc);
    1239                 :        147 :             tname = scalar_type_name(member->type.st);
    1240                 :        147 :             tprefix = scalar_type_prefix(member->type.st);
    1241   [ +  +  +  +  :        147 :             switch (member->value.type) {
                      - ]
    1242                 :            :             case vt_uint:
    1243                 :         65 :                 fprintf(out->fp,
    1244                 :            :                     "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s%s, %s%s, %llu, %u, %llu)\n",
    1245                 :         65 :                     nsc, llu(member->id), nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname,
    1246                 :        130 :                     llu(member->size), member->align, llu(member->value.u));
    1247                 :         65 :                 break;
    1248                 :            :             case vt_int:
    1249                 :         75 :                 fprintf(out->fp,
    1250                 :            :                     "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s%s, %s%s, %llu, %u, %lld)\n",
    1251                 :         75 :                     nsc, llu(member->id), nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname,
    1252                 :        150 :                     llu(member->size), member->align, lld(member->value.i));
    1253                 :         75 :                 break;
    1254                 :            :             case vt_bool:
    1255                 :          2 :                 fprintf(out->fp,
    1256                 :            :                     "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s%s, %s%s, %llu, %u, %u)\n",
    1257                 :          2 :                     nsc, llu(member->id), nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname,
    1258                 :          6 :                     llu(member->size), member->align, (unsigned)member->value.b);
    1259                 :          2 :                 break;
    1260                 :            :             case vt_float:
    1261                 :          5 :                 fprintf(out->fp,
    1262                 :            :                     "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s%s, %s%s, %llu, %u, %.17g)\n",
    1263                 :          5 :                     nsc, llu(member->id), nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname,
    1264                 :         10 :                     llu(member->size), member->align, member->value.f);
    1265                 :          5 :                 break;
    1266                 :            :             default:
    1267                 :          0 :                 gen_panic(out, "internal error: unexpected scalar table default value");
    1268                 :            :                 continue;
    1269                 :            :             }
    1270                 :            :             break;
    1271                 :            :         case vt_vector_type:
    1272                 :         25 :             tname_ns = scalar_type_ns(member->type.st, nsc);
    1273                 :         25 :             tname = scalar_type_name(member->type.st);
    1274                 :         25 :             tprefix = scalar_type_prefix(member->type.st);
    1275                 :         25 :             fprintf(out->fp,
    1276                 :            :                 "__%sbuild_vector_field(%llu, %s, %s_%.*s, %s%s, %s%s)\n",
    1277                 :         25 :                 nsc, llu(member->id), nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname);
    1278                 :            :             /* [ubyte] vectors can nest buffers. */
    1279         [ +  + ]:         25 :             if (member->nest) {
    1280      [ +  +  - ]:          9 :                 switch (member->nest->symbol.kind) {
    1281                 :            :                 case fb_is_table:
    1282                 :            :                     fb_compound_name((fb_compound_type_t *)(&member->nest->symbol), &snref);
    1283                 :          8 :                     fprintf(out->fp, "__%sbuild_nested_table_root(%s, %s_%.*s, %s, %s_identifier, %s_type_identifier)\n",
    1284                 :            :                         nsc, nsc, snt.text, n, s, snref.text, snref.text, snref.text);
    1285                 :          8 :                     break;
    1286                 :            :                 case fb_is_struct:
    1287                 :            :                     fb_compound_name((fb_compound_type_t *)(&member->nest->symbol), &snref);
    1288                 :          1 :                     fprintf(out->fp, "__%sbuild_nested_struct_root(%s, %s_%.*s, %s, %u, %s_identifier, %s_type_identifier)\n",
    1289                 :            :                         nsc, nsc, snt.text, n, s, snref.text,
    1290                 :          1 :                         (unsigned)((fb_compound_type_t *)(member->nest))->align, snref.text, snref.text);
    1291                 :          1 :                     break;
    1292                 :            :                 default:
    1293                 :          0 :                     gen_panic(out, "internal error: unexpected nested type");
    1294                 :            :                     continue;
    1295                 :            :                 }
    1296                 :            :             }
    1297                 :            :             break;
    1298                 :            :         case vt_string_type:
    1299                 :         27 :             fprintf(out->fp,
    1300                 :            :                 "__%sbuild_string_field(%llu, %s, %s_%.*s)\n",
    1301                 :         27 :                 nsc, llu(member->id), nsc, snt.text, n, s);
    1302                 :         27 :             break;
    1303                 :            :         case vt_vector_string_type:
    1304                 :         10 :             fprintf(out->fp,
    1305                 :            :                 "__%sbuild_string_vector_field(%llu, %s, %s_%.*s)\n",
    1306                 :         10 :                 nsc, llu(member->id), nsc, snt.text, n, s);
    1307                 :         10 :             break;
    1308                 :            :         case vt_compound_type_ref:
    1309                 :        109 :             fb_compound_name(member->type.ct, &snref);
    1310   [ +  +  +  +  :        109 :             switch (member->type.ct->symbol.kind) {
                      - ]
    1311                 :            :             case fb_is_struct:
    1312                 :         27 :                 fprintf(out->fp,
    1313                 :            :                     "__%sbuild_struct_field(%llu, %s, %s_%.*s, %s, %llu, %u)\n",
    1314                 :         54 :                     nsc, llu(member->id), nsc, snt.text, n, s, snref.text, llu(member->size), member->align);
    1315                 :         27 :                 break;
    1316                 :            :             case fb_is_table:
    1317                 :         23 :                 fprintf(out->fp,
    1318                 :            :                     "__%sbuild_table_field(%llu, %s, %s_%.*s, %s)\n",
    1319                 :         23 :                     nsc, llu(member->id), nsc, snt.text, n, s, snref.text);
    1320                 :         23 :                 break;
    1321                 :            :             case fb_is_enum:
    1322   [ +  +  -  - ]:         48 :                 switch (member->value.type) {
    1323                 :            :                 case vt_uint:
    1324                 :          2 :                     fprintf(out->fp,
    1325                 :            :                         "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s, %s_enum_t, %llu, %u, %llu)\n",
    1326                 :          2 :                         nsc, llu(member->id), nsc, snt.text, n, s, snref.text, snref.text,
    1327                 :          4 :                         llu(member->size), member->align, llu(member->value.u));
    1328                 :          2 :                     break;
    1329                 :            :                 case vt_int:
    1330                 :         46 :                     fprintf(out->fp,
    1331                 :            :                         "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s, %s_enum_t, %llu, %u, %lli)\n",
    1332                 :         46 :                         nsc, llu(member->id), nsc, snt.text, n, s, snref.text, snref.text,
    1333                 :         92 :                         llu(member->size), member->align, lld(member->value.i));
    1334                 :         46 :                     break;
    1335                 :            :                 case vt_bool:
    1336                 :          0 :                     fprintf(out->fp,
    1337                 :            :                         "__%sbuild_scalar_field(%llu, %s, %s_%.*s, %s, %s_enum_t, %llu, %u, %u)\n",
    1338                 :          0 :                         nsc, llu(member->id), nsc, snt.text, n, s, snref.text, snref.text,
    1339                 :          0 :                         llu(member->size), member->align, (unsigned)member->value.b);
    1340                 :          0 :                     break;
    1341                 :            :                 default:
    1342                 :          0 :                     gen_panic(out, "internal error: unexpected enum type referenced by table");
    1343                 :            :                     continue;
    1344                 :            :                 }
    1345                 :            :                 break;
    1346                 :            :             case fb_is_union:
    1347                 :         11 :                 fprintf(out->fp,
    1348                 :            :                     "__%sbuild_union_field(%llu, %s, %s_%.*s, %s)\n",
    1349                 :         11 :                     nsc, llu(member->id), nsc, snt.text, n, s, snref.text);
    1350                 :         11 :                     gen_union_member_fields(out, snt.text, n, s, member->type.ct);
    1351                 :         11 :                 break;
    1352                 :            :             default:
    1353                 :          0 :                 gen_panic(out, "internal error: unexpected compound type in table during code generation");
    1354                 :            :                 break;
    1355                 :            :             }
    1356                 :            :             break;
    1357                 :            :         case vt_vector_compound_type_ref:
    1358                 :         18 :             fb_compound_name(member->type.ct, &snref);
    1359   [ +  +  +  -  :         18 :             switch (member->type.ct->symbol.kind) {
                      - ]
    1360                 :            :             case fb_is_struct:
    1361         [ -  + ]:          8 :                 if (member->type.ct->symbol.flags & fb_indexed) {
    1362                 :          0 :                     fprintf(out->fp, "/* vector has keyed elements */\n");
    1363                 :            :                 }
    1364                 :          8 :                 fprintf(out->fp,
    1365                 :            :                     "__%sbuild_vector_field(%llu, %s, %s_%.*s, %s, %s_t)\n",
    1366                 :          8 :                     nsc, llu(member->id), nsc, snt.text, n, s, snref.text, snref.text);
    1367                 :          8 :                 break;
    1368                 :            :             case fb_is_table:
    1369         [ +  + ]:          9 :                 if (member->type.ct->symbol.flags & fb_indexed) {
    1370                 :          8 :                     fprintf(out->fp, "/* vector has keyed elements */\n");
    1371                 :            :                 }
    1372                 :          9 :                 fprintf(out->fp,
    1373                 :            :                     "__%sbuild_table_vector_field(%llu, %s, %s_%.*s, %s)\n",
    1374                 :          9 :                     nsc, llu(member->id), nsc, snt.text, n, s, snref.text);
    1375                 :          9 :                 break;
    1376                 :            :             case fb_is_enum:
    1377                 :          1 :                 fprintf(out->fp,
    1378                 :            :                     "__%sbuild_vector_field(%llu, %s, %s_%.*s, %s, %s_enum_t)\n",
    1379                 :          1 :                     nsc, llu(member->id), nsc, snt.text, n, s, snref.text, snref.text);
    1380                 :          1 :                 break;
    1381                 :            :             case fb_is_union:
    1382                 :          0 :                 gen_panic(out, "internal error: unexpected vector of union present in table");
    1383                 :            :                 break;
    1384                 :            :             default:
    1385                 :          0 :                 gen_panic(out, "internal error: unexpected vector compound type in table during code generation");
    1386                 :            :                 break;
    1387                 :            :             }
    1388                 :            :             break;
    1389                 :            :         default:
    1390                 :          0 :             gen_panic(out, "internal error: unexpected table member type during code generation");
    1391                 :            :             break;
    1392                 :            :         }
    1393                 :            :     }
    1394                 :         63 :     fprintf(out->fp, "\n");
    1395                 :         63 :     return 0;
    1396                 :            : }
    1397                 :            : 
    1398                 :         24 : static int gen_builder_enums(fb_output_t *out)
    1399                 :            : {
    1400                 :         24 :     const char *nsc = out->nsc;
    1401                 :            :     fb_symbol_t *sym;
    1402                 :            :     int was_here = 0;
    1403                 :            :     fb_scoped_name_t snt;
    1404                 :            : 
    1405                 :         24 :     fb_clear(snt);
    1406                 :            : 
    1407         [ +  + ]:        166 :     for (sym = out->S->symbols; sym; sym = sym->link) {
    1408         [ +  + ]:        142 :         switch (sym->kind) {
    1409                 :            :         case fb_is_enum:
    1410                 :            :             fb_compound_name((fb_compound_type_t *)sym, &snt);
    1411                 :         27 :             fprintf(out->fp,
    1412                 :            :                 "#define __%s_formal_args , %s_enum_t v0\n"
    1413                 :            :                 "#define __%s_call_args , v0\n",
    1414                 :            :                 snt.text, snt.text,
    1415                 :            :                 snt.text);
    1416                 :         27 :             fprintf(out->fp, "__%sbuild_scalar(%s, %s, %s_enum_t)\n",
    1417                 :            :                 nsc, nsc, snt.text, snt.text);
    1418                 :            :             was_here = 1;
    1419                 :         27 :             break;
    1420                 :            :         default:
    1421                 :        115 :             continue;
    1422                 :            :         }
    1423                 :            :     }
    1424         [ +  + ]:         24 :     if (was_here) {
    1425                 :         16 :         fprintf(out->fp, "\n");
    1426                 :            :     }
    1427                 :         24 :     return 0;
    1428                 :            : }
    1429                 :            : 
    1430                 :            : /*
    1431                 :            :  * Scope resolution is a bit fuzzy in unions -
    1432                 :            :  *
    1433                 :            :  * Googles flatc compiler allows dot notation in unions but not enums.
    1434                 :            :  * C++ generates unqualified enum members (i.e. MyGame.Example.Monster
    1435                 :            :  * becomes Monster) in the generated enum but still refers to the
    1436                 :            :  * specific table type in the given namespace. This makes it possible
    1437                 :            :  * to have name conflicts, and flatc raises these like other enum
    1438                 :            :  * conficts.
    1439                 :            :  *
    1440                 :            :  * We use the same approach and this is why we both look up compound
    1441                 :            :  * name and symbol name for the same member but the code generator
    1442                 :            :  * is not concerned with how the scope is parsed or how errors are
    1443                 :            :  * flagged - it just expects members to be unique.
    1444                 :            :  */
    1445                 :          9 : static int gen_union(fb_output_t *out, fb_compound_type_t *ct)
    1446                 :            : {
    1447                 :          9 :     const char *nsc = out->nsc;
    1448                 :            :     fb_member_t *member;
    1449                 :            :     fb_symbol_t *sym;
    1450                 :            :     const char *s;
    1451                 :            :     int n;
    1452                 :            :     fb_scoped_name_t snt;
    1453                 :            :     fb_scoped_name_t snref;
    1454                 :            : 
    1455                 :          9 :     fb_clear(snt);
    1456                 :          9 :     fb_clear(snref);
    1457                 :            :     fb_compound_name(ct, &snt);
    1458                 :            : 
    1459                 :          9 :     fprintf(out->fp,
    1460                 :            :         "struct %s_union_ref {\n"
    1461                 :            :         "    %s_union_type_t type;\n"
    1462                 :            :         "    union {\n"
    1463                 :            :         "        %sref_t _member;\n",
    1464                 :            :         snt.text, snt.text, nsc);
    1465         [ +  + ]:         36 :     for (sym = ct->members; sym; sym = sym->link) {
    1466                 :            :         member = (fb_member_t *)sym;
    1467      [ +  +  - ]:         27 :         switch (member->type.type) {
    1468                 :            :         case vt_compound_type_ref:
    1469                 :         18 :             fb_compound_name((fb_compound_type_t *)member->type.ct, &snref);
    1470                 :            :             symbol_name(sym, &n, &s);
    1471                 :         18 :             fprintf(out->fp,
    1472                 :            :                 "        %s_ref_t %.*s;\n",
    1473                 :            :                 snref.text, n, s);
    1474                 :         18 :             break;
    1475                 :            :         case vt_missing:
    1476                 :          9 :             fprintf(out->fp, "        %sref_t NONE;\n", nsc);
    1477                 :          9 :             break;
    1478                 :            :         default:
    1479                 :          0 :             gen_panic(out, "internal error: unexpected union member type");
    1480                 :            :             break;
    1481                 :            :         }
    1482                 :            :     }
    1483                 :          9 :     fprintf(out->fp,
    1484                 :            :         "    };\n"
    1485                 :            :         "};\n\n");
    1486         [ +  + ]:         36 :     for (sym = ct->members; sym; sym = sym->link) {
    1487                 :            :         member = (fb_member_t *)sym;
    1488      [ +  +  - ]:         27 :         switch (member->type.type) {
    1489                 :            :         case vt_compound_type_ref:
    1490                 :         18 :             fb_compound_name((fb_compound_type_t *)member->type.ct, &snref);
    1491                 :            :             symbol_name(sym, &n, &s);
    1492                 :         18 :             fprintf(out->fp,
    1493                 :            :                 "static inline %s_union_ref_t %s_as_%.*s(%s_ref_t ref)\n"
    1494                 :            :                 "{ %s_union_ref_t uref; uref.type = %s_%.*s; uref.%.*s = ref; return uref; }\n",
    1495                 :            :                 snt.text, snt.text, n, s, snref.text,
    1496                 :            :                 snt.text, snt.text, n, s, n, s);
    1497                 :         18 :             break;
    1498                 :            :         case vt_missing:
    1499                 :          9 :             fprintf(out->fp,
    1500                 :            :                 "static inline %s_union_ref_t %s_as_NONE()\n"
    1501                 :            :                 "{ %s_union_ref_t uref; uref.type = %s_NONE; uref._member = 0; return uref; }\n",
    1502                 :            :                 snt.text, snt.text, snt.text, snt.text);
    1503                 :          9 :             break;
    1504                 :            :         default:
    1505                 :          0 :             gen_panic(out, "internal error: unexpected union member type");
    1506                 :            :             break;
    1507                 :            :         }
    1508                 :            :     }
    1509                 :          9 :     return 0;
    1510                 :            : }
    1511                 :            : 
    1512                 :         48 : static int gen_union_typedefs(fb_output_t *out)
    1513                 :            : {
    1514                 :            :     fb_symbol_t *sym;
    1515                 :            :     int was_here = 0;
    1516                 :            :     fb_scoped_name_t snt;
    1517                 :            : 
    1518                 :         24 :     fb_clear(snt);
    1519                 :            : 
    1520         [ +  + ]:        166 :     for (sym = out->S->symbols; sym; sym = sym->link) {
    1521         [ +  + ]:        142 :         switch (sym->kind) {
    1522                 :            :         case fb_is_union:
    1523                 :            :             fb_compound_name((fb_compound_type_t *)sym, &snt);
    1524                 :          9 :             fprintf(out->fp,
    1525                 :            :                     "typedef struct %s_union_ref %s_union_ref_t;\n",
    1526                 :            :                     snt.text, snt.text);
    1527                 :            :             was_here = 1;
    1528                 :            :             break;
    1529                 :            :         default:
    1530                 :        133 :             continue;
    1531                 :            :         }
    1532                 :            :     }
    1533         [ +  + ]:         24 :     if (was_here) {
    1534                 :          9 :         fprintf(out->fp, "\n");
    1535                 :            :     }
    1536                 :         24 :     return 0;
    1537                 :            : }
    1538                 :            : 
    1539                 :         24 : static int gen_unions(fb_output_t *out)
    1540                 :            : {
    1541                 :            :     fb_symbol_t *sym;
    1542                 :            :     int was_here = 0;
    1543                 :            : 
    1544         [ +  + ]:        166 :     for (sym = out->S->symbols; sym; sym = sym->link) {
    1545         [ +  + ]:        142 :         switch (sym->kind) {
    1546                 :            :         case fb_is_union:
    1547                 :          9 :             gen_union(out, (fb_compound_type_t *)sym);
    1548                 :            :             was_here = 1;
    1549                 :          9 :             break;
    1550                 :            :         default:
    1551                 :        133 :             continue;
    1552                 :            :         }
    1553                 :            :     }
    1554         [ +  + ]:         24 :     if (was_here) {
    1555                 :          9 :         fprintf(out->fp, "\n");
    1556                 :            :     }
    1557                 :         24 :     return 0;
    1558                 :            : }
    1559                 :            : 
    1560                 :         24 : static int gen_builder_tables(fb_output_t *out)
    1561                 :            : {
    1562                 :            :     fb_symbol_t *sym;
    1563                 :            :     int was_here = 0;
    1564                 :            : 
    1565                 :            :     /* Needed by table create args. */
    1566                 :         24 :     gen_union_typedefs(out);
    1567                 :            :     /*
    1568                 :            :      * Because tables are recursive, we need the type and `start/end/add`
    1569                 :            :      * operations before the fields. We also need create for push_create
    1570                 :            :      * but it needs all dependent types, so create is fw declared
    1571                 :            :      * in a subsequent step. The actual create impl. then follows
    1572                 :            :      * after the table fields.
    1573                 :            :      */
    1574         [ +  + ]:        166 :     for (sym = out->S->symbols; sym; sym = sym->link) {
    1575         [ +  + ]:        142 :         switch (sym->kind) {
    1576                 :            :         case fb_is_table:
    1577                 :            :             was_here = 1;
    1578                 :         63 :             gen_required_table_fields(out, (fb_compound_type_t *)sym);
    1579                 :         63 :             gen_builder_table(out, (fb_compound_type_t *)sym);
    1580                 :         63 :             break;
    1581                 :            :         default:
    1582                 :         79 :             continue;
    1583                 :            :         }
    1584                 :            :     }
    1585         [ +  + ]:        166 :     for (sym = out->S->symbols; sym; sym = sym->link) {
    1586         [ +  + ]:        142 :         switch (sym->kind) {
    1587                 :            :         case fb_is_table:
    1588                 :         63 :             gen_builder_create_table_decl(out, (fb_compound_type_t *)sym);
    1589                 :         63 :             break;
    1590                 :            :         default:
    1591                 :         79 :             continue;
    1592                 :            :         }
    1593                 :            :     }
    1594         [ +  + ]:         24 :     if (was_here) {
    1595                 :         10 :         fprintf(out->fp, "\n");
    1596                 :            :     }
    1597                 :            :     /* Unions require the table ref_t types to be present. */
    1598                 :         24 :     gen_unions(out);
    1599         [ +  + ]:         24 :     if (!was_here) {
    1600                 :            :         return 0;
    1601                 :            :     }
    1602         [ +  + ]:        138 :     for (sym = out->S->symbols; sym; sym = sym->link) {
    1603         [ +  + ]:        128 :         switch (sym->kind) {
    1604                 :            :         case fb_is_table:
    1605                 :         63 :             gen_builder_table_fields(out, (fb_compound_type_t *)sym);
    1606                 :         63 :             gen_builder_create_table(out, (fb_compound_type_t *)sym);
    1607                 :         63 :             gen_builder_table_prolog(out, (fb_compound_type_t *)sym);
    1608                 :         63 :             fprintf(out->fp, "\n");
    1609                 :         63 :             break;
    1610                 :            :         default:
    1611                 :         65 :             continue;
    1612                 :            :         }
    1613                 :            :     }
    1614                 :            :     return 0;
    1615                 :            : }
    1616                 :            : 
    1617                 :         24 : static int gen_builder_footer(fb_output_t *out)
    1618                 :            : {
    1619                 :            :     gen_pragma_pop(out);
    1620                 :         24 :     fprintf(out->fp,
    1621                 :            :         "#endif /* %s_BUILDER_H */\n",
    1622                 :         24 :         out->S->basenameup);
    1623                 :         24 :     return 0;
    1624                 :            : }
    1625                 :            : 
    1626                 :         24 : int fb_gen_c_builder(fb_output_t *out)
    1627                 :            : {
    1628                 :         24 :     gen_builder_pretext(out);
    1629                 :         24 :     gen_builder_enums(out);
    1630                 :         24 :     gen_builder_structs(out);
    1631                 :         24 :     gen_builder_tables(out);
    1632                 :         24 :     gen_builder_footer(out);
    1633                 :         24 :     return 0;
    1634                 :            : }

Generated by: LCOV version 1.12