codegen_c_builder.c (104287B)
1 #include <string.h> 2 3 #include "codegen_c.h" 4 5 int fb_gen_common_c_builder_header(fb_output_t *out) 6 { 7 const char *nsc = out->nsc; 8 const char *nscup = out->nscup; 9 10 fprintf(out->fp, "#ifndef %s_COMMON_BUILDER_H\n", nscup); 11 fprintf(out->fp, "#define %s_COMMON_BUILDER_H\n", nscup); 12 fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n"); 13 fprintf(out->fp, "/* Common FlatBuffers build functionality for C. */\n\n"); 14 gen_prologue(out); 15 16 fprintf(out->fp, "#ifndef FLATBUILDER_H\n"); 17 fprintf(out->fp, "#include \"flatcc/flatcc_builder.h\"\n"); 18 fprintf(out->fp, "#endif\n"); 19 if (strcmp(nsc, "flatcc_builder_")) { 20 fprintf(out->fp, "typedef flatcc_builder_t %sbuilder_t;\n", nsc); 21 fprintf(out->fp, "typedef flatcc_builder_ref_t %sref_t;\n", nsc); 22 fprintf(out->fp, "typedef flatcc_builder_ref_t %svec_ref_t;\n", nsc); 23 fprintf(out->fp, "typedef flatcc_builder_union_ref_t %sunion_ref_t;\n", nsc); 24 fprintf(out->fp, "typedef flatcc_builder_union_vec_ref_t %sunion_vec_ref_t;\n", nsc); 25 fprintf(out->fp, "/* integer return code (ref and ptr always fail on 0) */\n" 26 "#define %sfailed(x) ((x) < 0)\n", nsc); 27 } 28 fprintf(out->fp, "typedef %sref_t %sroot_t;\n", nsc, nsc); 29 fprintf(out->fp, "#define %sroot(ref) ((%sroot_t)(ref))\n", nsc, nsc); 30 if (strcmp(nsc, "flatbuffers_")) { 31 fprintf(out->fp, "#define %sis_native_pe flatbuffers_is_native_pe\n", nsc); 32 fprintf(out->fp, "typedef flatbuffers_fid_t %sfid_t;\n", nsc); 33 } 34 fprintf(out->fp, "\n"); 35 36 fprintf(out->fp, 37 "#define __%smemoize_begin(B, src)\\\n" 38 "do { flatcc_builder_ref_t _ref; if ((_ref = flatcc_builder_refmap_find((B), (src)))) return _ref; } while (0)\n" 39 "#define __%smemoize_end(B, src, op) do { return flatcc_builder_refmap_insert((B), (src), (op)); } while (0)\n" 40 "#define __%smemoize(B, src, op) do { __%smemoize_begin(B, src); __%smemoize_end(B, src, op); } while (0)\n" 41 "\n", 42 nsc, nsc, nsc, nsc, nsc); 43 44 fprintf(out->fp, 45 "#define __%sbuild_buffer(NS)\\\n" 46 "typedef NS ## ref_t NS ## buffer_ref_t;\\\n" 47 "static inline int NS ## buffer_start(NS ## builder_t *B, const NS ##fid_t fid)\\\n" 48 "{ return flatcc_builder_start_buffer(B, fid, 0, 0); }\\\n" 49 "static inline int NS ## buffer_start_with_size(NS ## builder_t *B, const NS ##fid_t fid)\\\n" 50 "{ return flatcc_builder_start_buffer(B, fid, 0, flatcc_builder_with_size); }\\\n" 51 "static inline int NS ## buffer_start_aligned(NS ## builder_t *B, NS ##fid_t fid, uint16_t block_align)\\\n" 52 "{ return flatcc_builder_start_buffer(B, fid, block_align, 0); }\\\n" 53 "static inline int NS ## buffer_start_aligned_with_size(NS ## builder_t *B, NS ##fid_t fid, uint16_t block_align)\\\n" 54 "{ return flatcc_builder_start_buffer(B, fid, block_align, flatcc_builder_with_size); }\\\n" 55 "static inline NS ## buffer_ref_t NS ## buffer_end(NS ## builder_t *B, NS ## ref_t root)\\\n" 56 "{ return flatcc_builder_end_buffer(B, root); }\n" 57 "\n", 58 nsc); 59 60 fprintf(out->fp, 61 "#define __%sbuild_table_root(NS, N, FID, TFID)\\\n" 62 "static inline int N ## _start_as_root(NS ## builder_t *B)\\\n" 63 "{ return NS ## buffer_start(B, FID) ? -1 : N ## _start(B); }\\\n" 64 "static inline int N ## _start_as_root_with_size(NS ## builder_t *B)\\\n" 65 "{ return NS ## buffer_start_with_size(B, FID) ? -1 : N ## _start(B); }\\\n" 66 "static inline int N ## _start_as_typed_root(NS ## builder_t *B)\\\n" 67 "{ return NS ## buffer_start(B, TFID) ? -1 : N ## _start(B); }\\\n" 68 "static inline int N ## _start_as_typed_root_with_size(NS ## builder_t *B)\\\n" 69 "{ return NS ## buffer_start_with_size(B, TFID) ? -1 : N ## _start(B); }\\\n" 70 "static inline NS ## buffer_ref_t N ## _end_as_root(NS ## builder_t *B)\\\n" 71 "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n" 72 "static inline NS ## buffer_ref_t N ## _end_as_typed_root(NS ## builder_t *B)\\\n" 73 "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n" 74 /* 75 * Unlike structs, we do no use flatcc_builder_create_buffer 76 * because we would have to manage alignment, and we save very 77 * little because tables require stack allocations in any case. 78 */ 79 "static inline NS ## buffer_ref_t N ## _create_as_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 80 "{ if (NS ## buffer_start(B, FID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n" 81 "static inline NS ## buffer_ref_t N ## _create_as_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 82 "{ if (NS ## buffer_start_with_size(B, FID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n" 83 "static inline NS ## buffer_ref_t N ## _create_as_typed_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 84 "{ if (NS ## buffer_start(B, TFID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n" 85 "static inline NS ## buffer_ref_t N ## _create_as_typed_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 86 "{ if (NS ## buffer_start_with_size(B, TFID)) return 0; return NS ## buffer_end(B, N ## _create(B __ ## N ## _call_args)); }\\\n" 87 "static inline NS ## buffer_ref_t N ## _clone_as_root(NS ## builder_t *B, N ## _table_t t)\\\n" 88 "{ if (NS ## buffer_start(B, FID)) return 0; return NS ## buffer_end(B, N ## _clone(B, t)); }\\\n" 89 "static inline NS ## buffer_ref_t N ## _clone_as_root_with_size(NS ## builder_t *B, N ## _table_t t)\\\n" 90 "{ if (NS ## buffer_start_with_size(B, FID)) return 0; return NS ## buffer_end(B, N ## _clone(B, t)); }\\\n" 91 "static inline NS ## buffer_ref_t N ## _clone_as_typed_root(NS ## builder_t *B, N ## _table_t t)\\\n" 92 "{ if (NS ## buffer_start(B, TFID)) return 0;return NS ## buffer_end(B, N ## _clone(B, t)); }\\\n" 93 "static inline NS ## buffer_ref_t N ## _clone_as_typed_root_with_size(NS ## builder_t *B, N ## _table_t t)\\\n" 94 "{ if (NS ## buffer_start_with_size(B, TFID)) return 0; return NS ## buffer_end(B, N ## _clone(B, t)); }\n" 95 "\n", 96 nsc); 97 98 fprintf(out->fp, 99 "#define __%sbuild_table_prolog(NS, N, FID, TFID)\\\n" 100 "__%sbuild_table_vector_ops(NS, N ## _vec, N)\\\n" 101 "__%sbuild_table_root(NS, N, FID, TFID)\n" 102 "\n", 103 nsc, nsc, nsc); 104 105 106 fprintf(out->fp, 107 "#define __%sbuild_struct_root(NS, N, A, FID, TFID)\\\n" 108 "static inline N ## _t *N ## _start_as_root(NS ## builder_t *B)\\\n" 109 "{ return NS ## buffer_start(B, FID) ? 0 : N ## _start(B); }\\\n" 110 "static inline N ## _t *N ## _start_as_root_with_size(NS ## builder_t *B)\\\n" 111 "{ return NS ## buffer_start_with_size(B, FID) ? 0 : N ## _start(B); }\\\n" 112 "static inline N ## _t *N ## _start_as_typed_root(NS ## builder_t *B)\\\n" 113 "{ return NS ## buffer_start(B, TFID) ? 0 : N ## _start(B); }\\\n" 114 "static inline N ## _t *N ## _start_as_typed_root_with_size(NS ## builder_t *B)\\\n" 115 "{ return NS ## buffer_start_with_size(B, TFID) ? 0 : N ## _start(B); }\\\n" 116 "static inline NS ## buffer_ref_t N ## _end_as_root(NS ## builder_t *B)\\\n" 117 "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n" 118 "static inline NS ## buffer_ref_t N ## _end_as_typed_root(NS ## builder_t *B)\\\n" 119 "{ return NS ## buffer_end(B, N ## _end(B)); }\\\n" 120 "static inline NS ## buffer_ref_t N ## _end_pe_as_root(NS ## builder_t *B)\\\n" 121 "{ return NS ## buffer_end(B, N ## _end_pe(B)); }\\\n" 122 "static inline NS ## buffer_ref_t N ## _end_pe_as_typed_root(NS ## builder_t *B)\\\n" 123 "{ return NS ## buffer_end(B, N ## _end_pe(B)); }\\\n" 124 "static inline NS ## buffer_ref_t N ## _create_as_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 125 "{ return flatcc_builder_create_buffer(B, FID, 0,\\\n" 126 " N ## _create(B __ ## N ## _call_args), A, 0); }\\\n" 127 "static inline NS ## buffer_ref_t N ## _create_as_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 128 "{ return flatcc_builder_create_buffer(B, FID, 0,\\\n" 129 " N ## _create(B __ ## N ## _call_args), A, flatcc_builder_with_size); }\\\n" 130 "static inline NS ## buffer_ref_t N ## _create_as_typed_root(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 131 "{ return flatcc_builder_create_buffer(B, TFID, 0,\\\n" 132 " N ## _create(B __ ## N ## _call_args), A, 0); }\\\n" 133 "static inline NS ## buffer_ref_t N ## _create_as_typed_root_with_size(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 134 "{ return flatcc_builder_create_buffer(B, TFID, 0,\\\n" 135 " N ## _create(B __ ## N ## _call_args), A, flatcc_builder_with_size); }\\\n" 136 "static inline NS ## buffer_ref_t N ## _clone_as_root(NS ## builder_t *B, N ## _struct_t p)\\\n" 137 "{ return flatcc_builder_create_buffer(B, FID, 0, N ## _clone(B, p), A, 0); }\\\n" 138 "static inline NS ## buffer_ref_t N ## _clone_as_root_with_size(NS ## builder_t *B, N ## _struct_t p)\\\n" 139 "{ return flatcc_builder_create_buffer(B, FID, 0, N ## _clone(B, p), A, flatcc_builder_with_size); }\\\n" 140 "static inline NS ## buffer_ref_t N ## _clone_as_typed_root(NS ## builder_t *B, N ## _struct_t p)\\\n" 141 "{ return flatcc_builder_create_buffer(B, TFID, 0, N ## _clone(B, p), A, 0); }\\\n" 142 "static inline NS ## buffer_ref_t N ## _clone_as_typed_root_with_size(NS ## builder_t *B, N ## _struct_t p)\\\n" 143 "{ return flatcc_builder_create_buffer(B, TFID, 0, N ## _clone(B, p), A, flatcc_builder_with_size); }\n" 144 "\n", 145 nsc); 146 147 fprintf(out->fp, 148 "#define __%sbuild_nested_table_root(NS, N, TN, FID, TFID)\\\n" 149 "static inline int N ## _start_as_root(NS ## builder_t *B)\\\n" 150 "{ return NS ## buffer_start(B, FID) ? -1 : TN ## _start(B); }\\\n" 151 "static inline int N ## _start_as_typed_root(NS ## builder_t *B)\\\n" 152 "{ return NS ## buffer_start(B, TFID) ? -1 : TN ## _start(B); }\\\n" 153 "static inline int N ## _end_as_root(NS ## builder_t *B)\\\n" 154 "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n" 155 "static inline int N ## _end_as_typed_root(NS ## builder_t *B)\\\n" 156 "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n" 157 "static inline int N ## _nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n" 158 "{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\\\n" 159 " align ? align : 8, FLATBUFFERS_COUNT_MAX(1))); }\\\n" 160 "static inline int N ## _typed_nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n" 161 "{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\\\n" 162 " align ? align : 8, FLATBUFFERS_COUNT_MAX(1))); }\\\n" 163 "static inline int N ## _clone_as_root(NS ## builder_t *B, TN ## _table_t t)\\\n" 164 "{ return N ## _add(B, TN ## _clone_as_root(B, t)); }\\\n" 165 "static inline int N ## _clone_as_typed_root(NS ## builder_t *B, TN ## _table_t t)\\\n" 166 "{ return N ## _add(B, TN ## _clone_as_typed_root(B, t)); }\n" 167 "\n", 168 nsc); 169 170 fprintf(out->fp, 171 "#define __%sbuild_nested_struct_root(NS, N, TN, A, FID, TFID)\\\n" 172 "static inline TN ## _t *N ## _start_as_root(NS ## builder_t *B)\\\n" 173 "{ return NS ## buffer_start(B, FID) ? 0 : TN ## _start(B); }\\\n" 174 "static inline TN ## _t *N ## _start_as_typed_root(NS ## builder_t *B)\\\n" 175 "{ return NS ## buffer_start(B, FID) ? 0 : TN ## _start(B); }\\\n" 176 "static inline int N ## _end_as_root(NS ## builder_t *B)\\\n" 177 "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n" 178 "static inline int N ## _end_as_typed_root(NS ## builder_t *B)\\\n" 179 "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end(B))); }\\\n" 180 "static inline int N ## _end_pe_as_root(NS ## builder_t *B)\\\n" 181 "{ return N ## _add(B, NS ## buffer_end(B, TN ## _end_pe(B))); }\\\n" 182 "static inline int N ## _create_as_root(NS ## builder_t *B __ ## TN ## _formal_args)\\\n" 183 "{ return N ## _add(B, flatcc_builder_create_buffer(B, FID, 0,\\\n" 184 " TN ## _create(B __ ## TN ## _call_args), A, flatcc_builder_is_nested)); }\\\n" 185 "static inline int N ## _create_as_typed_root(NS ## builder_t *B __ ## TN ## _formal_args)\\\n" 186 "{ return N ## _add(B, flatcc_builder_create_buffer(B, TFID, 0,\\\n" 187 " TN ## _create(B __ ## TN ## _call_args), A, flatcc_builder_is_nested)); }\\\n" 188 "static inline int N ## _nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n" 189 "{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\\\n" 190 " align < A ? A : align, FLATBUFFERS_COUNT_MAX(1))); }\\\n" 191 "static inline int N ## _typed_nest(NS ## builder_t *B, void *data, size_t size, uint16_t align)\\\n" 192 "{ return N ## _add(B, flatcc_builder_create_vector(B, data, size, 1,\\\n" 193 " align < A ? A : align, FLATBUFFERS_COUNT_MAX(1))); }\\\n" 194 "static inline int N ## _clone_as_root(NS ## builder_t *B, TN ## _struct_t p)\\\n" 195 "{ return N ## _add(B, TN ## _clone_as_root(B, p)); }\\\n" 196 "static inline int N ## _clone_as_typed_root(NS ## builder_t *B, TN ## _struct_t p)\\\n" 197 "{ return N ## _add(B, TN ## _clone_as_typed_root(B, p)); }\n" 198 "\n", 199 nsc); 200 201 fprintf(out->fp, 202 "#define __%sbuild_vector_ops(NS, V, N, TN, T)\\\n" 203 "static inline T *V ## _extend(NS ## builder_t *B, size_t len)\\\n" 204 "{ return (T *)flatcc_builder_extend_vector(B, len); }\\\n" 205 "static inline T *V ## _append(NS ## builder_t *B, const T *data, size_t len)\\\n" 206 "{ return (T *)flatcc_builder_append_vector(B, data, len); }\\\n" 207 "static inline int V ## _truncate(NS ## builder_t *B, size_t len)\\\n" 208 "{ return flatcc_builder_truncate_vector(B, len); }\\\n" 209 "static inline T *V ## _edit(NS ## builder_t *B)\\\n" 210 "{ return (T *)flatcc_builder_vector_edit(B); }\\\n" 211 "static inline size_t V ## _reserved_len(NS ## builder_t *B)\\\n" 212 "{ return flatcc_builder_vector_count(B); }\\\n" 213 "static inline T *V ## _push(NS ## builder_t *B, const T *p)\\\n" 214 "{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? (memcpy(_p, p, TN ## __size()), _p) : 0; }\\\n" 215 "static inline T *V ## _push_copy(NS ## builder_t *B, const T *p)\\\n" 216 "{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? TN ## _copy(_p, p) : 0; }\\\n" 217 /* push_clone is the same as a for push_copy for scalar and struct vectors 218 * but copy has different semantics as a standalone operation so we can't use 219 * clone to implement push_clone - it would create a reference to a struct. */ 220 "static inline T *V ## _push_clone(NS ## builder_t *B, const T *p)\\\n" 221 "{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? TN ## _copy(_p, p) : 0; }\\\n" 222 "static inline T *V ## _push_create(NS ## builder_t *B __ ## TN ## _formal_args)\\\n" 223 "{ T *_p; return (_p = (T *)flatcc_builder_extend_vector(B, 1)) ? TN ## _assign(_p __ ## TN ## _call_args) : 0; }\n" 224 "\n", 225 nsc); 226 227 fprintf(out->fp, 228 /* NS: common namespace, N: typename, T: element type, S: elem size, A: alignment */ 229 "#define __%sbuild_vector(NS, N, T, S, A)\\\n" 230 "typedef NS ## ref_t N ## _vec_ref_t;\\\n" 231 "static inline int N ## _vec_start(NS ## builder_t *B)\\\n" 232 "{ return flatcc_builder_start_vector(B, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n" 233 "static inline N ## _vec_ref_t N ## _vec_end_pe(NS ## builder_t *B)\\\n" 234 "{ return flatcc_builder_end_vector(B); }\\\n" 235 "static inline N ## _vec_ref_t N ## _vec_end(NS ## builder_t *B)\\\n" 236 "{ if (!NS ## is_native_pe()) { size_t i, n; T *p = (T *)flatcc_builder_vector_edit(B);\\\n" 237 " for (i = 0, n = flatcc_builder_vector_count(B); i < n; ++i)\\\n" 238 " { N ## _to_pe(N ## __ptr_add(p, i)); }} return flatcc_builder_end_vector(B); }\\\n" 239 "static inline N ## _vec_ref_t N ## _vec_create_pe(NS ## builder_t *B, const T *data, size_t len)\\\n" 240 "{ return flatcc_builder_create_vector(B, data, len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n" 241 "static inline N ## _vec_ref_t N ## _vec_create(NS ## builder_t *B, const T *data, size_t len)\\\n" 242 "{ 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" 243 " p = (T *)flatcc_builder_extend_vector(B, len); if (!p) return 0;\\\n" 244 " for (i = 0; i < len; ++i) { N ## _copy_to_pe(N ## __ptr_add(p, i), N ## __const_ptr_add(data, i)); }\\\n" 245 " return flatcc_builder_end_vector(B); } else return flatcc_builder_create_vector(B, data, len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n" 246 "static inline N ## _vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_vec_t vec)\\\n" 247 "{ __%smemoize(B, vec, flatcc_builder_create_vector(B, vec, N ## _vec_len(vec), S, A, FLATBUFFERS_COUNT_MAX(S))); }\\\n" 248 "static inline N ## _vec_ref_t N ## _vec_slice(NS ## builder_t *B, N ##_vec_t vec, size_t index, size_t len)\\\n" 249 "{ size_t n = N ## _vec_len(vec); if (index >= n) index = n; n -= index; if (len > n) len = n;\\\n" 250 " return flatcc_builder_create_vector(B, N ## __const_ptr_add(vec, index), len, S, A, FLATBUFFERS_COUNT_MAX(S)); }\\\n" 251 "__%sbuild_vector_ops(NS, N ## _vec, N, N, T)\n" 252 "\n", 253 nsc, nsc, nsc); 254 255 fprintf(out->fp, 256 "#define __%sbuild_union_vector_ops(NS, V, N, TN)\\\n" 257 "static inline TN ## _union_ref_t *V ## _extend(NS ## builder_t *B, size_t len)\\\n" 258 "{ return flatcc_builder_extend_union_vector(B, len); }\\\n" 259 "static inline TN ## _union_ref_t *V ## _append(NS ## builder_t *B, const TN ## _union_ref_t *data, size_t len)\\\n" 260 "{ return flatcc_builder_append_union_vector(B, data, len); }\\\n" 261 "static inline int V ## _truncate(NS ## builder_t *B, size_t len)\\\n" 262 "{ return flatcc_builder_truncate_union_vector(B, len); }\\\n" 263 "static inline TN ## _union_ref_t *V ## _edit(NS ## builder_t *B)\\\n" 264 "{ return (TN ## _union_ref_t *) flatcc_builder_union_vector_edit(B); }\\\n" 265 "static inline size_t V ## _reserved_len(NS ## builder_t *B)\\\n" 266 "{ return flatcc_builder_union_vector_count(B); }\\\n" 267 "static inline TN ## _union_ref_t *V ## _push(NS ## builder_t *B, const TN ## _union_ref_t ref)\\\n" 268 "{ return flatcc_builder_union_vector_push(B, ref); }\\\n" 269 "static inline TN ## _union_ref_t *V ## _push_clone(NS ## builder_t *B, TN ## _union_t u)\\\n" 270 "{ return TN ## _vec_push(B, TN ## _clone(B, u)); }\n" 271 "\n", 272 nsc); 273 274 fprintf(out->fp, 275 "#define __%sbuild_union_vector(NS, N)\\\n" 276 "static inline int N ## _vec_start(NS ## builder_t *B)\\\n" 277 "{ return flatcc_builder_start_union_vector(B); }\\\n" 278 "static inline N ## _union_vec_ref_t N ## _vec_end(NS ## builder_t *B)\\\n" 279 "{ return flatcc_builder_end_union_vector(B); }\\\n" 280 "static inline N ## _union_vec_ref_t N ## _vec_create(NS ## builder_t *B, const N ## _union_ref_t *data, size_t len)\\\n" 281 "{ return flatcc_builder_create_union_vector(B, data, len); }\\\n" 282 "__%sbuild_union_vector_ops(NS, N ## _vec, N, N)\\\n" 283 "/* Preserves DAG structure separately for type and value vector, so a type vector could be shared for many value vectors. */\\\n" 284 "static inline N ## _union_vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_union_vec_t vec)\\\n" 285 "{ N ## _union_vec_ref_t _uvref, _ret = { 0, 0 }; NS ## union_ref_t _uref; size_t _i, _len;\\\n" 286 " if (vec.type == 0) return _ret;\\\n" 287 " _uvref.type = flatcc_builder_refmap_find(B, vec.type); _uvref.value = flatcc_builder_refmap_find(B, vec.value);\\\n" 288 " _len = N ## _union_vec_len(vec); if (_uvref.type == 0) {\\\n" 289 " _uvref.type = flatcc_builder_refmap_insert(B, vec.type, (flatcc_builder_create_type_vector(B, vec.type, _len))); }\\\n" 290 " if (_uvref.type == 0) return _ret; if (_uvref.value == 0) {\\\n" 291 " if (flatcc_builder_start_offset_vector(B)) return _ret;\\\n" 292 " for (_i = 0; _i < _len; ++_i) { _uref = N ## _clone(B, N ## _union_vec_at(vec, _i));\\\n" 293 " if (!_uref.value || !(flatcc_builder_offset_vector_push(B, _uref.value))) return _ret; }\\\n" 294 " _uvref.value = flatcc_builder_refmap_insert(B, vec.value, flatcc_builder_end_offset_vector(B));\\\n" 295 " if (_uvref.value == 0) return _ret; } return _uvref; }\n" 296 "\n", 297 nsc, nsc); 298 299 /* In addtion to offset_vector_ops... */ 300 fprintf(out->fp, 301 "#define __%sbuild_string_vector_ops(NS, N)\\\n" 302 "static inline int N ## _push_start(NS ## builder_t *B)\\\n" 303 "{ return NS ## string_start(B); }\\\n" 304 "static inline NS ## string_ref_t *N ## _push_end(NS ## builder_t *B)\\\n" 305 "{ return NS ## string_vec_push(B, NS ## string_end(B)); }\\\n" 306 "static inline NS ## string_ref_t *N ## _push_create(NS ## builder_t *B, const char *s, size_t len)\\\n" 307 "{ return NS ## string_vec_push(B, NS ## string_create(B, s, len)); }\\\n" 308 "static inline NS ## string_ref_t *N ## _push_create_str(NS ## builder_t *B, const char *s)\\\n" 309 "{ return NS ## string_vec_push(B, NS ## string_create_str(B, s)); }\\\n" 310 "static inline NS ## string_ref_t *N ## _push_create_strn(NS ## builder_t *B, const char *s, size_t max_len)\\\n" 311 "{ return NS ## string_vec_push(B, NS ## string_create_strn(B, s, max_len)); }\\\n" 312 "static inline NS ## string_ref_t *N ## _push_clone(NS ## builder_t *B, NS ## string_t string)\\\n" 313 "{ return NS ## string_vec_push(B, NS ## string_clone(B, string)); }\\\n" 314 "static inline NS ## string_ref_t *N ## _push_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n" 315 "{ return NS ## string_vec_push(B, NS ## string_slice(B, string, index, len)); }\n" 316 "\n", 317 nsc); 318 319 /* In addtion to offset_vector_ops... */ 320 fprintf(out->fp, 321 "#define __%sbuild_table_vector_ops(NS, N, TN)\\\n" 322 "static inline int N ## _push_start(NS ## builder_t *B)\\\n" 323 "{ return TN ## _start(B); }\\\n" 324 "static inline TN ## _ref_t *N ## _push_end(NS ## builder_t *B)\\\n" 325 "{ return N ## _push(B, TN ## _end(B)); }\\\n" 326 "static inline TN ## _ref_t *N ## _push_create(NS ## builder_t *B __ ## TN ##_formal_args)\\\n" 327 "{ return N ## _push(B, TN ## _create(B __ ## TN ## _call_args)); }\n" 328 "\n", 329 nsc); 330 331 fprintf(out->fp, 332 "#define __%sbuild_offset_vector_ops(NS, V, N, TN)\\\n" 333 "static inline TN ## _ref_t *V ## _extend(NS ## builder_t *B, size_t len)\\\n" 334 "{ return flatcc_builder_extend_offset_vector(B, len); }\\\n" 335 "static inline TN ## _ref_t *V ## _append(NS ## builder_t *B, const TN ## _ref_t *data, size_t len)\\\n" 336 "{ return flatcc_builder_append_offset_vector(B, data, len); }\\\n" 337 "static inline int V ## _truncate(NS ## builder_t *B, size_t len)\\\n" 338 "{ return flatcc_builder_truncate_offset_vector(B, len); }\\\n" 339 "static inline TN ## _ref_t *V ## _edit(NS ## builder_t *B)\\\n" 340 "{ return (TN ## _ref_t *)flatcc_builder_offset_vector_edit(B); }\\\n" 341 "static inline size_t V ## _reserved_len(NS ## builder_t *B)\\\n" 342 "{ return flatcc_builder_offset_vector_count(B); }\\\n" 343 "static inline TN ## _ref_t *V ## _push(NS ## builder_t *B, const TN ## _ref_t ref)\\\n" 344 "{ return ref ? flatcc_builder_offset_vector_push(B, ref) : 0; }\n" 345 "\n", 346 nsc); 347 348 fprintf(out->fp, 349 "#define __%sbuild_offset_vector(NS, N)\\\n" 350 "typedef NS ## ref_t N ## _vec_ref_t;\\\n" 351 "static inline int N ## _vec_start(NS ## builder_t *B)\\\n" 352 "{ return flatcc_builder_start_offset_vector(B); }\\\n" 353 "static inline N ## _vec_ref_t N ## _vec_end(NS ## builder_t *B)\\\n" 354 "{ return flatcc_builder_end_offset_vector(B); }\\\n" 355 "static inline N ## _vec_ref_t N ## _vec_create(NS ## builder_t *B, const N ## _ref_t *data, size_t len)\\\n" 356 "{ return flatcc_builder_create_offset_vector(B, data, len); }\\\n" 357 "__%sbuild_offset_vector_ops(NS, N ## _vec, N, N)\\\n" 358 "static inline N ## _vec_ref_t N ## _vec_clone(NS ## builder_t *B, N ##_vec_t vec)\\\n" 359 "{ int _ret; N ## _ref_t _e; size_t _i, _len; __%smemoize_begin(B, vec);\\\n" 360 " _len = N ## _vec_len(vec); if (flatcc_builder_start_offset_vector(B)) return 0;\\\n" 361 " for (_i = 0; _i < _len; ++_i) { if (!(_e = N ## _clone(B, N ## _vec_at(vec, _i)))) return 0;\\\n" 362 " if (!flatcc_builder_offset_vector_push(B, _e)) return 0; }\\\n" 363 " __%smemoize_end(B, vec, flatcc_builder_end_offset_vector(B)); }\\\n" 364 "\n", 365 nsc, nsc, nsc, nsc); 366 367 fprintf(out->fp, 368 "#define __%sbuild_string_ops(NS, N)\\\n" 369 "static inline char *N ## _append(NS ## builder_t *B, const char *s, size_t len)\\\n" 370 "{ return flatcc_builder_append_string(B, s, len); }\\\n" 371 "static inline char *N ## _append_str(NS ## builder_t *B, const char *s)\\\n" 372 "{ return flatcc_builder_append_string_str(B, s); }\\\n" 373 "static inline char *N ## _append_strn(NS ## builder_t *B, const char *s, size_t len)\\\n" 374 "{ return flatcc_builder_append_string_strn(B, s, len); }\\\n" 375 "static inline size_t N ## _reserved_len(NS ## builder_t *B)\\\n" 376 "{ return flatcc_builder_string_len(B); }\\\n" 377 "static inline char *N ## _extend(NS ## builder_t *B, size_t len)\\\n" 378 "{ return flatcc_builder_extend_string(B, len); }\\\n" 379 "static inline char *N ## _edit(NS ## builder_t *B)\\\n" 380 "{ return flatcc_builder_string_edit(B); }\\\n" 381 "static inline int N ## _truncate(NS ## builder_t *B, size_t len)\\\n" 382 "{ return flatcc_builder_truncate_string(B, len); }\n" 383 "\n", 384 nsc); 385 386 fprintf(out->fp, 387 "#define __%sbuild_string(NS)\\\n" 388 "typedef NS ## ref_t NS ## string_ref_t;\\\n" 389 "static inline int NS ## string_start(NS ## builder_t *B)\\\n" 390 "{ return flatcc_builder_start_string(B); }\\\n" 391 "static inline NS ## string_ref_t NS ## string_end(NS ## builder_t *B)\\\n" 392 "{ return flatcc_builder_end_string(B); }\\\n" 393 "static inline NS ## ref_t NS ## string_create(NS ## builder_t *B, const char *s, size_t len)\\\n" 394 "{ return flatcc_builder_create_string(B, s, len); }\\\n" 395 "static inline NS ## ref_t NS ## string_create_str(NS ## builder_t *B, const char *s)\\\n" 396 "{ return flatcc_builder_create_string_str(B, s); }\\\n" 397 "static inline NS ## ref_t NS ## string_create_strn(NS ## builder_t *B, const char *s, size_t len)\\\n" 398 "{ return flatcc_builder_create_string_strn(B, s, len); }\\\n" 399 "static inline NS ## string_ref_t NS ## string_clone(NS ## builder_t *B, NS ## string_t string)\\\n" 400 "{ __%smemoize(B, string, flatcc_builder_create_string(B, string, NS ## string_len(string))); }\\\n" 401 "static inline NS ## string_ref_t NS ## string_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n" 402 "{ size_t n = NS ## string_len(string); if (index >= n) index = n; n -= index; if (len > n) len = n;\\\n" 403 " return flatcc_builder_create_string(B, string + index, len); }\\\n" 404 "__%sbuild_string_ops(NS, NS ## string)\\\n" 405 "__%sbuild_offset_vector(NS, NS ## string)\n" 406 "\n", 407 nsc, nsc, nsc, nsc); 408 fprintf(out->fp, 409 "#define __%scopy_from_pe(P, P2, N) (*(P) = N ## _read_from_pe(P2), (P))\n" 410 "#define __%sfrom_pe(P, N) (*(P) = N ## _read_from_pe(P), (P))\n" 411 "#define __%scopy_to_pe(P, P2, N) (N ## _write_to_pe((P), *(P2)), (P))\n" 412 "#define __%sto_pe(P, N) (N ## _write_to_pe((P), *(P)), (P))\n", 413 nsc, nsc, nsc, nsc); 414 fprintf(out->fp, 415 "#define __%sdefine_fixed_array_primitives(NS, N, T)\\\n" 416 "static inline T *N ## _array_copy(T *p, const T *p2, size_t n)\\\n" 417 "{ memcpy(p, p2, n * sizeof(T)); return p; }\\\n" 418 "static inline T *N ## _array_copy_from_pe(T *p, const T *p2, size_t n)\\\n" 419 "{ size_t i; if (NS ## is_native_pe()) memcpy(p, p2, n * sizeof(T)); else\\\n" 420 " for (i = 0; i < n; ++i) N ## _copy_from_pe(&p[i], &p2[i]); return p; }\\\n" 421 "static inline T *N ## _array_copy_to_pe(T *p, const T *p2, size_t n)\\\n" 422 "{ size_t i; if (NS ## is_native_pe()) memcpy(p, p2, n * sizeof(T)); else\\\n" 423 " for (i = 0; i < n; ++i) N ## _copy_to_pe(&p[i], &p2[i]); return p; }\n", 424 nsc); 425 fprintf(out->fp, 426 "#define __%sdefine_scalar_primitives(NS, N, T)\\\n" 427 "static inline T *N ## _from_pe(T *p) { return __ ## NS ## from_pe(p, N); }\\\n" 428 "static inline T *N ## _to_pe(T *p) { return __ ## NS ## to_pe(p, N); }\\\n" 429 "static inline T *N ## _copy(T *p, const T *p2) { *p = *p2; return p; }\\\n" 430 "static inline T *N ## _copy_from_pe(T *p, const T *p2)\\\n" 431 "{ return __ ## NS ## copy_from_pe(p, p2, N); }\\\n" 432 "static inline T *N ## _copy_to_pe(T *p, const T *p2) \\\n" 433 "{ return __ ## NS ## copy_to_pe(p, p2, N); }\\\n" 434 "static inline T *N ## _assign(T *p, const T v0) { *p = v0; return p; }\\\n" 435 "static inline T *N ## _assign_from_pe(T *p, T v0)\\\n" 436 "{ *p = N ## _read_from_pe(&v0); return p; }\\\n" 437 "static inline T *N ## _assign_to_pe(T *p, T v0)\\\n" 438 "{ N ## _write_to_pe(p, v0); return p; }\n" 439 "#define __%sbuild_scalar(NS, N, T)\\\n" 440 "__ ## NS ## define_scalar_primitives(NS, N, T)\\\n" 441 "__ ## NS ## define_fixed_array_primitives(NS, N, T)\\\n" 442 "__ ## NS ## build_vector(NS, N, T, sizeof(T), sizeof(T))\n", 443 nsc, nsc); 444 445 fprintf(out->fp, 446 "/* Depends on generated copy_to/from_pe functions, and the type. */\n" 447 "#define __%sdefine_struct_primitives(NS, N)\\\n" 448 "static inline N ## _t *N ##_to_pe(N ## _t *p)\\\n" 449 "{ if (!NS ## is_native_pe()) { N ## _copy_to_pe(p, p); }; return p; }\\\n" 450 "static inline N ## _t *N ##_from_pe(N ## _t *p)\\\n" 451 "{ if (!NS ## is_native_pe()) { N ## _copy_from_pe(p, p); }; return p; }\\\n" 452 "static inline N ## _t *N ## _clear(N ## _t *p) { return (N ## _t *)memset(p, 0, N ## __size()); }\n" 453 "\n" 454 455 /* 456 * NOTE: structs can both be inline and independent blocks. They 457 * are independent as buffer roots, and also as union members. 458 * _clone applied to a struct type name creates a reference to 459 * an independent block, but this is ambigous. Structs also 460 * support _copy which is the inline equivalent of _clone for 461 * inline. There is also the distinction between _clone applied 462 * to a field name, clone applied to a type name, and _clone 463 * applied to a _vec_push operation. For field names and push 464 * operations, _clone is unambigiously inline and similar to 465 * _copy. So the ambigiouty is when applying _clone to a type 466 * name where _copy and _clone are different. Unions can safely 467 * implement clone on structs members via _clone because union 468 * members are indendendent blocks whereas push_clone must be 469 * implemented with _copy because structs are inline in 470 * (non-union) vectors. Structs in union-vectors are independent 471 * but these simply the unions clone operation (which is a 472 * generated function). 473 */ 474 "/* Depends on generated copy/assign_to/from_pe functions, and the type. */\n" 475 "#define __%sbuild_struct(NS, N, S, A, FID, TFID)\\\n" 476 "__ ## NS ## define_struct_primitives(NS, N)\\\n" 477 "typedef NS ## ref_t N ## _ref_t;\\\n" 478 "static inline N ## _t *N ## _start(NS ## builder_t *B)\\\n" 479 "{ return (N ## _t *)flatcc_builder_start_struct(B, S, A); }\\\n" 480 "static inline N ## _ref_t N ## _end(NS ## builder_t *B)\\\n" 481 "{ if (!NS ## is_native_pe()) { N ## _to_pe((N ## _t *)flatcc_builder_struct_edit(B)); }\\\n" 482 " return flatcc_builder_end_struct(B); }\\\n" 483 "static inline N ## _ref_t N ## _end_pe(NS ## builder_t *B)\\\n" 484 "{ return flatcc_builder_end_struct(B); }\\\n" 485 "static inline N ## _ref_t N ## _create(NS ## builder_t *B __ ## N ## _formal_args)\\\n" 486 "{ N ## _t *_p = N ## _start(B); if (!_p) return 0; N ##_assign_to_pe(_p __ ## N ## _call_args);\\\n" 487 " return N ## _end_pe(B); }\\\n" 488 "static inline N ## _ref_t N ## _clone(NS ## builder_t *B, N ## _struct_t p)\\\n" 489 "{ N ## _t *_p; __%smemoize_begin(B, p); _p = N ## _start(B); if (!_p) return 0;\\\n" 490 " N ## _copy(_p, p); __%smemoize_end(B, p, N ##_end_pe(B)); }\\\n" 491 "__%sbuild_vector(NS, N, N ## _t, S, A)\\\n" 492 "__%sbuild_struct_root(NS, N, A, FID, TFID)\\\n" 493 "\n", 494 nsc, nsc, nsc, nsc, nsc, nsc); 495 fprintf(out->fp, 496 "#define __%sstruct_clear_field(p) memset((p), 0, sizeof(*(p)))\n", 497 nsc); 498 499 fprintf(out->fp, 500 "#define __%sbuild_table(NS, N, K)\\\n" 501 "static inline int N ## _start(NS ## builder_t *B)\\\n" 502 "{ return flatcc_builder_start_table(B, K); }\\\n" 503 "static inline N ## _ref_t N ## _end(NS ## builder_t *B)\\\n" 504 "{ FLATCC_ASSERT(flatcc_builder_check_required(B, __ ## N ## _required,\\\n" 505 " sizeof(__ ## N ## _required) / sizeof(__ ## N ## _required[0]) - 1));\\\n" 506 " return flatcc_builder_end_table(B); }\\\n" 507 "__%sbuild_offset_vector(NS, N)\n" 508 "\n", 509 nsc, nsc); 510 511 fprintf(out->fp, 512 "#define __%sbuild_table_field(ID, NS, N, TN, TT)\\\n" 513 "static inline int N ## _add(NS ## builder_t *B, TN ## _ref_t ref)\\\n" 514 "{ TN ## _ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ?\\\n" 515 " ((*_p = ref), 0) : -1; }\\\n" 516 "static inline int N ## _start(NS ## builder_t *B)\\\n" 517 "{ return TN ## _start(B); }\\\n" 518 "static inline int N ## _end(NS ## builder_t *B)\\\n" 519 "{ return N ## _add(B, TN ## _end(B)); }\\\n" 520 "static inline TN ## _ref_t N ## _create(NS ## builder_t *B __ ## TN ##_formal_args)\\\n" 521 "{ return N ## _add(B, TN ## _create(B __ ## TN ## _call_args)); }\\\n" 522 "static inline int N ## _clone(NS ## builder_t *B, TN ## _table_t p)\\\n" 523 "{ return N ## _add(B, TN ## _clone(B, p)); }\\\n" 524 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 525 "{ TN ## _table_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }\n" 526 "\n", 527 nsc); 528 529 fprintf(out->fp, 530 "#define __%sbuild_union_field(ID, NS, N, TN, TT)\\\n" 531 "static inline int N ## _add(NS ## builder_t *B, TN ## _union_ref_t uref)\\\n" 532 "{ NS ## ref_t *_p; TN ## _union_type_t *_pt; if (uref.type == TN ## _NONE) return 0; if (uref.value == 0) return -1;\\\n" 533 " if (!(_pt = (TN ## _union_type_t *)flatcc_builder_table_add(B, ID - 1, sizeof(*_pt), sizeof(*_pt)))) return -1;\\\n" 534 " *_pt = uref.type; if (!(_p = flatcc_builder_table_add_offset(B, ID))) return -1; *_p = uref.value; return 0; }\\\n" 535 "static inline int N ## _add_type(NS ## builder_t *B, TN ## _union_type_t type)\\\n" 536 "{ TN ## _union_type_t *_pt; if (type == TN ## _NONE) return 0; return (_pt = (TN ## _union_type_t *)flatcc_builder_table_add(B, ID - 1,\\\n" 537 " sizeof(*_pt), sizeof(*_pt))) ? ((*_pt = type), 0) : -1; }\\\n" 538 "static inline int N ## _add_value(NS ## builder_t *B, TN ## _union_ref_t uref)\\\n" 539 "{ NS ## ref_t *p; if (uref.type == TN ## _NONE) return 0; return (p = flatcc_builder_table_add_offset(B, ID)) ?\\\n" 540 " ((*p = uref.value), 0) : -1; }\\\n" 541 "static inline int N ## _clone(NS ## builder_t *B, TN ## _union_t p)\\\n" 542 "{ return N ## _add(B, TN ## _clone(B, p)); }\\\n" 543 /* `_pick` is not supported on specific union members because the source dictates the type. */ 544 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 545 "{ TN ## _union_t _p = N ## _union(t); return _p.type ? N ## _clone(B, _p) : 0; }\n" 546 "\n", 547 nsc); 548 549 fprintf(out->fp, 550 "/* M is the union value name and T is its type, i.e. the qualified name. */\n" 551 "#define __%sbuild_union_table_value_field(NS, N, NU, M, T)\\\n" 552 "static inline int N ## _ ## M ## _add(NS ## builder_t *B, T ## _ref_t ref)\\\n" 553 "{ return N ## _add(B, NU ## _as_ ## M (ref)); }\\\n" 554 "static inline int N ## _ ## M ## _start(NS ## builder_t *B)\\\n" 555 "{ return T ## _start(B); }\\\n" 556 "static inline int N ## _ ## M ## _end(NS ## builder_t *B)\\\n" 557 "{ T ## _ref_t ref = T ## _end(B);\\\n" 558 " return ref ? N ## _ ## M ## _add(B, ref) : -1; }\\\n" 559 "static inline int N ## _ ## M ## _create(NS ## builder_t *B __ ## T ##_formal_args)\\\n" 560 "{ T ## _ref_t ref = T ## _create(B __ ## T ## _call_args);\\\n" 561 " return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\\\n" 562 "static inline int N ## _ ## M ## _clone(NS ## builder_t *B, T ## _table_t t)\\\n" 563 "{ T ## _ref_t ref = T ## _clone(B, t);\\\n" 564 " return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\n" 565 "\n", 566 nsc); 567 568 fprintf(out->fp, 569 "/* M is the union value name and T is its type, i.e. the qualified name. */\n" 570 "#define __%sbuild_union_struct_value_field(NS, N, NU, M, T)\\\n" 571 "static inline int N ## _ ## M ## _add(NS ## builder_t *B, T ## _ref_t ref)\\\n" 572 "{ return N ## _add(B, NU ## _as_ ## M (ref)); }\\\n" 573 "static inline T ## _t *N ## _ ## M ## _start(NS ## builder_t *B)\\\n" 574 "{ return T ## _start(B); }\\\n" 575 "static inline int N ## _ ## M ## _end(NS ## builder_t *B)\\\n" 576 "{ T ## _ref_t ref = T ## _end(B);\\\n" 577 " return ref ? N ## _ ## M ## _add(B, ref) : -1; }\\\n" 578 "static inline int N ## _ ## M ## _create(NS ## builder_t *B __ ## T ##_formal_args)\\\n" 579 "{ T ## _ref_t ref = T ## _create(B __ ## T ## _call_args);\\\n" 580 " return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\\\n" 581 "static inline int N ## _ ## M ## _end_pe(NS ## builder_t *B)\\\n" 582 "{ T ## _ref_t ref = T ## _end_pe(B);\\\n" 583 " return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\\\n" 584 "static inline int N ## _ ## M ## _clone(NS ## builder_t *B, T ## _struct_t p)\\\n" 585 "{ T ## _ref_t ref = T ## _clone(B, p);\\\n" 586 " return ref ? N ## _add(B, NU ## _as_ ## M(ref)) : -1; }\n", 587 nsc); 588 589 fprintf(out->fp, 590 "#define __%sbuild_union_string_value_field(NS, N, NU, M)\\\n" 591 "static inline int N ## _ ## M ## _add(NS ## builder_t *B, NS ## string_ref_t ref)\\\n" 592 "{ return N ## _add(B, NU ## _as_ ## M (ref)); }\\\n" 593 "__%sbuild_string_field_ops(NS, N ## _ ## M)\n" 594 "\n", 595 nsc, nsc); 596 597 fprintf(out->fp, 598 "/* NS: common namespace, ID: table field id (not offset), TN: name of type T, TT: name of table type\n" 599 " * S: sizeof of scalar type, A: alignment of type T, default value V of type T. */\n" 600 "#define __%sbuild_scalar_field(ID, NS, N, TN, T, S, A, V, TT)\\\n" 601 "static inline int N ## _add(NS ## builder_t *B, const T v)\\\n" 602 "{ T *_p; if (v == V) return 0; if (!(_p = (T *)flatcc_builder_table_add(B, ID, S, A))) return -1;\\\n" 603 " TN ## _assign_to_pe(_p, v); return 0; }\\\n" 604 "static inline int N ## _force_add(NS ## builder_t *B, const T v)\\\n" 605 "{ T *_p; if (!(_p = (T *)flatcc_builder_table_add(B, ID, S, A))) return -1;\\\n" 606 " TN ## _assign_to_pe(_p, v); return 0; }\\\n" 607 "/* Clone does not skip default values and expects pe endian content. */\\\n" 608 "static inline int N ## _clone(NS ## builder_t *B, const T *p)\\\n" 609 "{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\\\n" 610 "/* Transferring a missing field is a nop success with 0 as result. */\\\n" 611 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 612 "{ const T *_p = N ## _get_ptr(t); return _p ? N ## _clone(B, _p) : 0; }\n" 613 "\n", 614 nsc); 615 616 fprintf(out->fp, 617 "/* NS: common namespace, ID: table field id (not offset), TN: name of type T, TT: name of table type\n" 618 " * S: sizeof of scalar type, A: alignment of type T. */\n" 619 "#define __%sbuild_scalar_optional_field(ID, NS, N, TN, T, S, A, TT)\\\n" 620 "static inline int N ## _add(NS ## builder_t *B, const T v)\\\n" 621 "{ T *_p; if (!(_p = (T *)flatcc_builder_table_add(B, ID, S, A))) return -1;\\\n" 622 " TN ## _assign_to_pe(_p, v); return 0; }\\\n" 623 "/* Clone does not skip default values and expects pe endian content. */\\\n" 624 "static inline int N ## _clone(NS ## builder_t *B, const T *p)\\\n" 625 "{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\\\n" 626 "/* Transferring a missing field is a nop success with 0 as result. */\\\n" 627 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 628 "{ const T *_p = N ## _get_ptr(t); return _p ? N ## _clone(B, _p) : 0; }\n" 629 "\n", 630 nsc); 631 632 fprintf(out->fp, 633 "#define __%sbuild_struct_field(ID, NS, N, TN, S, A, TT)\\\n" 634 "static inline TN ## _t *N ## _start(NS ## builder_t *B)\\\n" 635 "{ return (TN ## _t *)flatcc_builder_table_add(B, ID, S, A); }\\\n" 636 "static inline int N ## _end(NS ## builder_t *B)\\\n" 637 "{ if (!NS ## is_native_pe()) { TN ## _to_pe((TN ## _t *)flatcc_builder_table_edit(B, S)); } return 0; }\\\n" 638 "static inline int N ## _end_pe(NS ## builder_t *B) { return 0; }\\\n" 639 "static inline int N ## _create(NS ## builder_t *B __ ## TN ## _formal_args)\\\n" 640 "{ TN ## _t *_p = N ## _start(B); if (!_p) return -1; TN ##_assign_to_pe(_p __ ## TN ## _call_args);\\\n" 641 " return 0; }\\\n" 642 "static inline int N ## _add(NS ## builder_t *B, const TN ## _t *p)\\\n" 643 "{ TN ## _t *_p = N ## _start(B); if (!_p) return -1; TN ##_copy_to_pe(_p, p); return 0; }\\\n" 644 "static inline int N ## _clone(NS ## builder_t *B, TN ## _struct_t p)\\\n" 645 "{ return 0 == flatcc_builder_table_add_copy(B, ID, p, S, A) ? -1 : 0; }\\\n" 646 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 647 "{ TN ## _struct_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }\n" 648 "\n", 649 nsc); 650 651 /* This goes for scalar, struct, and enum vectors. */ 652 fprintf(out->fp, 653 "#define __%sbuild_vector_field(ID, NS, N, TN, T, TT)\\\n" 654 "static inline int N ## _add(NS ## builder_t *B, TN ## _vec_ref_t ref)\\\n" 655 "{ TN ## _vec_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\\\n" 656 "static inline int N ## _start(NS ## builder_t *B)\\\n" 657 "{ return TN ## _vec_start(B); }\\\n" 658 "static inline int N ## _end_pe(NS ## builder_t *B)\\\n" 659 "{ return N ## _add(B, TN ## _vec_end_pe(B)); }\\\n" 660 "static inline int N ## _end(NS ## builder_t *B)\\\n" 661 "{ return N ## _add(B, TN ## _vec_end(B)); }\\\n" 662 "static inline int N ## _create_pe(NS ## builder_t *B, const T *data, size_t len)\\\n" 663 "{ return N ## _add(B, TN ## _vec_create_pe(B, data, len)); }\\\n" 664 "static inline int N ## _create(NS ## builder_t *B, const T *data, size_t len)\\\n" 665 "{ return N ## _add(B, TN ## _vec_create(B, data, len)); }\\\n" 666 "static inline int N ## _slice(NS ## builder_t *B, TN ## _vec_t vec, size_t index, size_t len)\\\n" 667 "{ return N ## _add(B, TN ## _vec_slice(B, vec, index, len)); }\\\n" 668 "static inline int N ## _clone(NS ## builder_t *B, TN ## _vec_t vec)\\\n" 669 "{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\\\n" 670 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 671 "{ TN ## _vec_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }\\\n" 672 "__%sbuild_vector_ops(NS, N, N, TN, T)\\\n" 673 "\n", 674 nsc, nsc); 675 676 fprintf(out->fp, 677 "#define __%sbuild_offset_vector_field(ID, NS, N, TN, TT)\\\n" 678 "static inline int N ## _add(NS ## builder_t *B, TN ## _vec_ref_t ref)\\\n" 679 "{ TN ## _vec_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\\\n" 680 "static inline int N ## _start(NS ## builder_t *B)\\\n" 681 "{ return flatcc_builder_start_offset_vector(B); }\\\n" 682 "static inline int N ## _end(NS ## builder_t *B)\\\n" 683 "{ return N ## _add(B, flatcc_builder_end_offset_vector(B)); }\\\n" 684 "static inline int N ## _create(NS ## builder_t *B, const TN ## _ref_t *data, size_t len)\\\n" 685 "{ return N ## _add(B, flatcc_builder_create_offset_vector(B, data, len)); }\\\n" 686 "__%sbuild_offset_vector_ops(NS, N, N, TN)\\\n" 687 "static inline int N ## _clone(NS ## builder_t *B, TN ## _vec_t vec)\\\n" 688 "{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\\\n" 689 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 690 "{ TN ## _vec_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }\n" 691 "\n", 692 nsc, nsc); 693 694 fprintf(out->fp, 695 "/* depends on N ## _add which differs for union member fields and ordinary fields */\\\n" 696 "#define __%sbuild_string_field_ops(NS, N)\\\n" 697 "static inline int N ## _start(NS ## builder_t *B)\\\n" 698 "{ return flatcc_builder_start_string(B); }\\\n" 699 "static inline int N ## _end(NS ## builder_t *B)\\\n" 700 "{ return N ## _add(B, flatcc_builder_end_string(B)); }\\\n" 701 "static inline int N ## _create(NS ## builder_t *B, const char *s, size_t len)\\\n" 702 "{ return N ## _add(B, flatcc_builder_create_string(B, s, len)); }\\\n" 703 "static inline int N ## _create_str(NS ## builder_t *B, const char *s)\\\n" 704 "{ return N ## _add(B, flatcc_builder_create_string_str(B, s)); }\\\n" 705 "static inline int N ## _create_strn(NS ## builder_t *B, const char *s, size_t max_len)\\\n" 706 "{ return N ## _add(B, flatcc_builder_create_string_strn(B, s, max_len)); }\\\n" 707 "static inline int N ## _clone(NS ## builder_t *B, NS ## string_t string)\\\n" 708 "{ return N ## _add(B, NS ## string_clone(B, string)); }\\\n" 709 "static inline int N ## _slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n" 710 "{ return N ## _add(B, NS ## string_slice(B, string, index, len)); }\\\n" 711 "__%sbuild_string_ops(NS, N)\n" 712 "\n", 713 nsc, nsc); 714 715 fprintf(out->fp, 716 "#define __%sbuild_string_field(ID, NS, N, TT)\\\n" 717 "static inline int N ## _add(NS ## builder_t *B, NS ## string_ref_t ref)\\\n" 718 "{ NS ## string_ref_t *_p; return (ref && (_p = flatcc_builder_table_add_offset(B, ID))) ? ((*_p = ref), 0) : -1; }\\\n" 719 "__%sbuild_string_field_ops(NS, N)\\\n" 720 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 721 "{ NS ## string_t _p = N ## _get(t); return _p ? N ## _clone(B, _p) : 0; }\n" 722 "\n", 723 nsc, nsc); 724 725 fprintf(out->fp, 726 "#define __%sbuild_table_vector_field(ID, NS, N, TN, TT)\\\n" 727 "__%sbuild_offset_vector_field(ID, NS, N, TN, TT)\\\n" 728 "__%sbuild_table_vector_ops(NS, N, TN)\n" 729 "\n", 730 nsc, nsc, nsc); 731 732 fprintf(out->fp, 733 "#define __%sbuild_union_vector_field(ID, NS, N, TN, TT)\\\n" 734 "static inline int N ## _add(NS ## builder_t *B, TN ## _union_vec_ref_t uvref)\\\n" 735 "{ NS ## vec_ref_t *_p; if (!uvref.type || !uvref.value) return uvref.type == uvref.value ? 0 : -1;\\\n" 736 " if (!(_p = flatcc_builder_table_add_offset(B, ID - 1))) return -1; *_p = uvref.type;\\\n" 737 " if (!(_p = flatcc_builder_table_add_offset(B, ID))) return -1; *_p = uvref.value; return 0; }\\\n" 738 "static inline int N ## _start(NS ## builder_t *B)\\\n" 739 "{ return flatcc_builder_start_union_vector(B); }\\\n" 740 "static inline int N ## _end(NS ## builder_t *B)\\\n" 741 "{ return N ## _add(B, flatcc_builder_end_union_vector(B)); }\\\n" 742 "static inline int N ## _create(NS ## builder_t *B, const TN ## _union_ref_t *data, size_t len)\\\n" 743 "{ return N ## _add(B, flatcc_builder_create_union_vector(B, data, len)); }\\\n" 744 "__%sbuild_union_vector_ops(NS, N, N, TN)\\\n" 745 "static inline int N ## _clone(NS ## builder_t *B, TN ## _union_vec_t vec)\\\n" 746 "{ return N ## _add(B, TN ## _vec_clone(B, vec)); }\\\n" 747 "static inline int N ## _pick(NS ## builder_t *B, TT ## _table_t t)\\\n" 748 "{ TN ## _union_vec_t _p = N ## _union(t); return _p.type ? N ## _clone(B, _p) : 0; }\n" 749 "\n", 750 nsc, nsc); 751 752 fprintf(out->fp, 753 "#define __%sbuild_union_table_vector_value_field(NS, N, NU, M, T)\\\n" 754 "static inline int N ## _ ## M ## _push_start(NS ## builder_t *B)\\\n" 755 "{ return T ## _start(B); }\\\n" 756 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_end(NS ## builder_t *B)\\\n" 757 "{ return NU ## _vec_push(B, NU ## _as_ ## M (T ## _end(B))); }\\\n" 758 "static inline NU ## _union_ref_t *N ## _ ## M ## _push(NS ## builder_t *B, T ## _ref_t ref)\\\n" 759 "{ return NU ## _vec_push(B, NU ## _as_ ## M (ref)); }\\\n" 760 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_create(NS ## builder_t *B __ ## T ##_formal_args)\\\n" 761 "{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _create(B __ ## T ## _call_args))); }\\\n" 762 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_clone(NS ## builder_t *B, T ## _table_t t)\\\n" 763 "{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _clone(B, t))); }\n" 764 "\n", 765 nsc); 766 767 fprintf(out->fp, 768 "#define __%sbuild_union_struct_vector_value_field(NS, N, NU, M, T)\\\n" 769 "static inline T ## _t *N ## _ ## M ## _push_start(NS ## builder_t *B)\\\n" 770 "{ return T ## _start(B); }\\\n" 771 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_end(NS ## builder_t *B)\\\n" 772 "{ return NU ## _vec_push(B, NU ## _as_ ## M (T ## _end(B))); }\\\n" 773 "static inline NU ## _union_ref_t *N ## _ ## M ## _push(NS ## builder_t *B, T ## _ref_t ref)\\\n" 774 "{ return NU ## _vec_push(B, NU ## _as_ ## M (ref)); }\\\n" 775 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_create(NS ## builder_t *B __ ## T ##_formal_args)\\\n" 776 "{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _create(B __ ## T ## _call_args))); }\\\n" 777 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_clone(NS ## builder_t *B, T ## _struct_t p)\\\n" 778 /* Here we create an independent struct block, so T ## _clone is appropriate as opposed to T ## _copy. */ 779 "{ return NU ## _vec_push(B, NU ## _as_ ## M(T ## _clone(B, p))); }\n" 780 "\n", 781 nsc); 782 783 fprintf(out->fp, 784 "#define __%sbuild_union_string_vector_value_field(NS, N, NU, M)\\\n" 785 "static inline NU ## _union_ref_t *N ## _ ## M ## _push(NS ## builder_t *B, NS ## string_ref_t ref)\\\n" 786 "{ return NU ## _vec_push(B, NU ## _as_ ## M (ref)); }\\\n" 787 "static inline int N ## _ ## M ## _push_start(NS ## builder_t *B)\\\n" 788 "{ return NS ## string_start(B); }\\\n" 789 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_end(NS ## builder_t *B)\\\n" 790 "{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_end(B))); }\\\n" 791 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_create(NS ## builder_t *B, const char *s, size_t len)\\\n" 792 "{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_create(B, s, len))); }\\\n" 793 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_create_str(NS ## builder_t *B, const char *s)\\\n" 794 "{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_create_str(B, s))); }\\\n" 795 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_create_strn(NS ## builder_t *B, const char *s, size_t max_len)\\\n" 796 "{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_create_strn(B, s, max_len))); }\\\n" 797 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_clone(NS ## builder_t *B, NS ## string_t string)\\\n" 798 "{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_clone(B, string))); }\\\n" 799 "static inline NU ## _union_ref_t *N ## _ ## M ## _push_slice(NS ## builder_t *B, NS ## string_t string, size_t index, size_t len)\\\n" 800 "{ return NU ## _vec_push(B, NU ## _as_ ## M(NS ## string_slice(B, string, index, len))); }\n" 801 "\n", 802 nsc); 803 804 fprintf(out->fp, 805 "#define __%sbuild_string_vector_field(ID, NS, N, TT)\\\n" 806 "__%sbuild_offset_vector_field(ID, NS, N, NS ## string, TT)\\\n" 807 "__%sbuild_string_vector_ops(NS, N)\n" 808 "\n", 809 nsc, nsc, nsc); 810 811 fprintf(out->fp, "#define __%schar_formal_args , char v0\n", nsc); 812 fprintf(out->fp, "#define __%schar_call_args , v0\n", nsc); 813 fprintf(out->fp, "#define __%suint8_formal_args , uint8_t v0\n", nsc); 814 fprintf(out->fp, "#define __%suint8_call_args , v0\n", nsc); 815 fprintf(out->fp, "#define __%sint8_formal_args , int8_t v0\n", nsc); 816 fprintf(out->fp, "#define __%sint8_call_args , v0\n", nsc); 817 fprintf(out->fp, "#define __%sbool_formal_args , %sbool_t v0\n", nsc, nsc); 818 fprintf(out->fp, "#define __%sbool_call_args , v0\n", nsc); 819 fprintf(out->fp, "#define __%suint16_formal_args , uint16_t v0\n", nsc); 820 fprintf(out->fp, "#define __%suint16_call_args , v0\n", nsc); 821 fprintf(out->fp, "#define __%suint32_formal_args , uint32_t v0\n", nsc); 822 fprintf(out->fp, "#define __%suint32_call_args , v0\n", nsc); 823 fprintf(out->fp, "#define __%suint64_formal_args , uint64_t v0\n", nsc); 824 fprintf(out->fp, "#define __%suint64_call_args , v0\n", nsc); 825 fprintf(out->fp, "#define __%sint16_formal_args , int16_t v0\n", nsc); 826 fprintf(out->fp, "#define __%sint16_call_args , v0\n", nsc); 827 fprintf(out->fp, "#define __%sint32_formal_args , int32_t v0\n", nsc); 828 fprintf(out->fp, "#define __%sint32_call_args , v0\n", nsc); 829 fprintf(out->fp, "#define __%sint64_formal_args , int64_t v0\n", nsc); 830 fprintf(out->fp, "#define __%sint64_call_args , v0\n", nsc); 831 fprintf(out->fp, "#define __%sfloat_formal_args , float v0\n", nsc); 832 fprintf(out->fp, "#define __%sfloat_call_args , v0\n", nsc); 833 fprintf(out->fp, "#define __%sdouble_formal_args , double v0\n", nsc); 834 fprintf(out->fp, "#define __%sdouble_call_args , v0\n", nsc); 835 fprintf(out->fp, "\n"); 836 fprintf(out->fp, "__%sbuild_scalar(%s, %schar, char)\n", nsc, nsc, nsc); 837 fprintf(out->fp, "__%sbuild_scalar(%s, %suint8, uint8_t)\n", nsc, nsc, nsc); 838 fprintf(out->fp, "__%sbuild_scalar(%s, %sint8, int8_t)\n", nsc, nsc, nsc); 839 fprintf(out->fp, "__%sbuild_scalar(%s, %sbool, %sbool_t)\n", nsc, nsc, nsc, nsc); 840 fprintf(out->fp, "__%sbuild_scalar(%s, %suint16, uint16_t)\n", nsc, nsc, nsc); 841 fprintf(out->fp, "__%sbuild_scalar(%s, %suint32, uint32_t)\n", nsc, nsc, nsc); 842 fprintf(out->fp, "__%sbuild_scalar(%s, %suint64, uint64_t)\n", nsc, nsc, nsc); 843 fprintf(out->fp, "__%sbuild_scalar(%s, %sint16, int16_t)\n", nsc, nsc, nsc); 844 fprintf(out->fp, "__%sbuild_scalar(%s, %sint32, int32_t)\n", nsc, nsc, nsc); 845 fprintf(out->fp, "__%sbuild_scalar(%s, %sint64, int64_t)\n", nsc, nsc, nsc); 846 fprintf(out->fp, "__%sbuild_scalar(%s, %sfloat, float)\n", nsc, nsc, nsc); 847 fprintf(out->fp, "__%sbuild_scalar(%s, %sdouble, double)\n", nsc, nsc, nsc); 848 fprintf(out->fp, "\n"); 849 fprintf(out->fp, "__%sbuild_string(%s)\n", nsc, nsc); 850 fprintf(out->fp, "\n"); 851 852 fprintf(out->fp, "__%sbuild_buffer(%s)\n", nsc, nsc); 853 gen_epilogue(out); 854 fprintf(out->fp, "#endif /* %s_COMMON_BUILDER_H */\n", nscup); 855 return 0; 856 } 857 858 static int gen_builder_pretext(fb_output_t *out) 859 { 860 const char *nsc = out->nsc; 861 const char *nscup = out->nscup; 862 863 fprintf(out->fp, 864 "#ifndef %s_BUILDER_H\n" 865 "#define %s_BUILDER_H\n", 866 out->S->basenameup, out->S->basenameup); 867 868 fprintf(out->fp, "\n/* " FLATCC_GENERATED_BY " */\n\n"); 869 fprintf(out->fp, "#ifndef %s_READER_H\n", out->S->basenameup); 870 fprintf(out->fp, "#include \"%s_reader.h\"\n", out->S->basename); 871 fprintf(out->fp, "#endif\n"); 872 fprintf(out->fp, "#ifndef %s_COMMON_BUILDER_H\n", nscup); 873 fprintf(out->fp, "#include \"%scommon_builder.h\"\n", nsc); 874 fprintf(out->fp, "#endif\n"); 875 876 fb_gen_c_includes(out, "_builder.h", "_BUILDER_H"); 877 878 gen_prologue(out); 879 880 /* 881 * Even if defined in the reader header, we must redefine it here 882 * because another file might sneak in and update. 883 */ 884 if (out->S->file_identifier.type == vt_string) { 885 fprintf(out->fp, 886 "#undef %sidentifier\n" 887 "#define %sidentifier \"%.*s\"\n", 888 nsc, 889 nsc, out->S->file_identifier.s.len, out->S->file_identifier.s.s); 890 } else { 891 fprintf(out->fp, 892 "#ifndef %sidentifier\n" 893 "#define %sidentifier 0\n" 894 "#endif\n", 895 nsc, nsc); 896 } 897 if (out->S->file_extension.type == vt_string) { 898 fprintf(out->fp, 899 "#undef %sextension\n" 900 "#define %sextension \"%.*s\"\n", 901 nsc, 902 nsc, out->S->file_extension.s.len, out->S->file_extension.s.s); 903 } else { 904 fprintf(out->fp, 905 "#ifndef %sextension\n" 906 "#define %sextension \"%s\"\n" 907 "#endif\n", 908 nsc, nsc, out->opts->default_bin_ext); 909 } 910 fprintf(out->fp, "\n"); 911 return 0; 912 } 913 914 static int get_total_struct_field_count(fb_compound_type_t *ct) 915 { 916 fb_member_t *member; 917 fb_symbol_t *sym; 918 int count = 0; 919 920 for (sym = ct->members; sym; sym = sym->link) { 921 member = (fb_member_t *)sym; 922 if (member->metadata_flags & fb_f_deprecated) { 923 continue; 924 } 925 switch (member->type.type) { 926 /* struct arrays count as 1 but struct fields are expanded */ 927 case vt_compound_type_ref: 928 if (member->type.ct->symbol.kind == fb_is_struct) { 929 count += get_total_struct_field_count(member->type.ct); 930 continue; 931 } 932 ++count; 933 break; 934 default: 935 ++count; 936 break; 937 } 938 } 939 return count; 940 } 941 942 static inline void gen_comma(fb_output_t *out, int index, int count, int is_macro) 943 { 944 char *cont = is_macro ? "\\\n" : "\n"; 945 946 if (count == 0) { 947 return; 948 } 949 if (index == 0) { 950 if (count > 4) { 951 fprintf(out->fp, ",%s ", cont); 952 } else { 953 fprintf(out->fp, ", "); 954 } 955 } else { 956 if (index % 4 || count - index <= 2) { 957 fprintf(out->fp, ", "); 958 } else { 959 fprintf(out->fp, ",%s ", cont); 960 } 961 } 962 } 963 964 static int gen_builder_struct_args(fb_output_t *out, fb_compound_type_t *ct, int index, int len, int is_macro) 965 { 966 const char *nsc = out->nsc; 967 fb_member_t *member; 968 fb_symbol_t *sym; 969 const char *tname, *tname_ns; 970 fb_scoped_name_t snref; 971 972 fb_clear(snref); 973 974 for (sym = ct->members; sym; sym = sym->link) { 975 member = (fb_member_t *)sym; 976 if (member->metadata_flags & fb_f_deprecated) { 977 continue; 978 } 979 switch (member->type.type) { 980 case vt_fixed_array_compound_type_ref: 981 gen_comma(out, index, len, is_macro); 982 fb_compound_name(member->type.ct, &snref); 983 if (member->type.ct->symbol.kind == fb_is_struct) { 984 fprintf(out->fp, "const %s_t v%i[%i]", snref.text, index++, (int)member->type.len); 985 } else { 986 fprintf(out->fp, "%s_enum_t v%i[%i]", snref.text, index++, (int)member->type.len); 987 } 988 break; 989 case vt_compound_type_ref: 990 if (member->type.ct->symbol.kind == fb_is_struct) { 991 index = gen_builder_struct_args(out, member->type.ct, index, len, is_macro); 992 continue; 993 } 994 gen_comma(out, index, len, is_macro); 995 fb_compound_name(member->type.ct, &snref); 996 fprintf(out->fp, "%s_enum_t v%i", snref.text, index++); 997 break; 998 case vt_fixed_array_type: 999 gen_comma(out, index, len, is_macro); 1000 tname_ns = scalar_type_ns(member->type.st, nsc); 1001 tname = scalar_type_name(member->type.st); 1002 fprintf(out->fp, "const %s%s v%i[%i]", tname_ns, tname, index++, (int)member->type.len); 1003 break; 1004 case vt_scalar_type: 1005 gen_comma(out, index, len, is_macro); 1006 tname_ns = scalar_type_ns(member->type.st, nsc); 1007 tname = scalar_type_name(member->type.st); 1008 fprintf(out->fp, "%s%s v%i", tname_ns, tname, index++); 1009 break; 1010 default: 1011 gen_panic(out, "internal error: unexpected struct member type"); 1012 continue; 1013 } 1014 } 1015 return index; 1016 } 1017 1018 static int gen_builder_struct_call_list(fb_output_t *out, fb_compound_type_t *ct, int index, int arg_count, int is_macro) 1019 { 1020 int i; 1021 int len = get_total_struct_field_count(ct); 1022 1023 for (i = 0; i < len; ++i) { 1024 gen_comma(out, i, arg_count, is_macro); 1025 fprintf(out->fp, "v%i", index++); 1026 } 1027 return index; 1028 } 1029 1030 enum { no_conversion, convert_from_pe, convert_to_pe }; 1031 1032 /* Note: returned index is not correct when using from_ptr since it doesn't track arguments, but it shouldn't matter. */ 1033 static int gen_builder_struct_field_assign(fb_output_t *out, fb_compound_type_t *ct, int index, int arg_count, 1034 int conversion, int from_ptr) 1035 { 1036 const char *nsc = out->nsc; 1037 fb_member_t *member; 1038 fb_symbol_t *sym; 1039 int n, len; 1040 const char *s; 1041 int deprecated_index = 0; 1042 const char *kind, *tprefix; 1043 fb_scoped_name_t snref; 1044 1045 fb_clear(snref); 1046 switch (conversion) { 1047 case convert_to_pe: kind = "_to_pe"; break; 1048 case convert_from_pe: kind = "_from_pe"; break; 1049 default: kind = ""; break; 1050 } 1051 for (sym = ct->members; sym; sym = sym->link) { 1052 member = (fb_member_t *)sym; 1053 symbol_name(sym, &n, &s); 1054 1055 if (index > 0) { 1056 if (index % 4 == 0) { 1057 fprintf(out->fp, ";\n "); 1058 } else { 1059 fprintf(out->fp, "; "); 1060 } 1061 } 1062 switch (member->type.type) { 1063 case vt_fixed_array_compound_type_ref: 1064 len = (int)member->type.len; 1065 fb_compound_name(member->type.ct, &snref); 1066 if (member->metadata_flags & fb_f_deprecated) { 1067 fprintf(out->fp, "__%sstruct_clear_field(p->__deprecated%i)", 1068 nsc, deprecated_index); 1069 ++deprecated_index; 1070 ++index; 1071 continue; 1072 } 1073 if (from_ptr) { 1074 fprintf(out->fp, "%s_array_copy%s(p->%.*s, p2->%.*s, %d)", 1075 snref.text, kind, n, s, n, s, len); 1076 } else { 1077 fprintf(out->fp, "%s_array_copy%s(p->%.*s, v%i, %d)", 1078 snref.text, kind, n, s, index, len); 1079 } 1080 ++index; 1081 continue; 1082 case vt_compound_type_ref: 1083 fb_compound_name(member->type.ct, &snref); 1084 if (member->type.ct->symbol.kind == fb_is_struct) { 1085 if (member->metadata_flags & fb_f_deprecated) { 1086 fprintf(out->fp, "__%sstruct_clear_field(p->__deprecated%i)", 1087 nsc, deprecated_index); 1088 deprecated_index++; 1089 index += get_total_struct_field_count(member->type.ct); 1090 continue; 1091 } 1092 if (from_ptr) { 1093 fprintf(out->fp, "%s_copy%s(&p->%.*s, &p2->%.*s)", snref.text, kind, n, s, n, s); 1094 /* `index` does not count children, but it doesn't matter here. */ 1095 ++index; 1096 } else { 1097 fprintf(out->fp, "%s_assign%s(&p->%.*s", snref.text, kind, n, s); 1098 index = gen_builder_struct_call_list(out, member->type.ct, index, arg_count, 0); 1099 fprintf(out->fp, ")"); 1100 } 1101 continue; 1102 } 1103 if (member->metadata_flags & fb_f_deprecated) { 1104 fprintf(out->fp, "__%sstruct_clear_field(p->__deprecated%i)", 1105 nsc, deprecated_index); 1106 ++deprecated_index; 1107 ++index; 1108 continue; 1109 } 1110 switch (member->size == 1 ? no_conversion : conversion) { 1111 case convert_from_pe: 1112 if (from_ptr) { 1113 fprintf(out->fp, "%s_copy_from_pe(&p->%.*s, &p2->%.*s)", 1114 snref.text, n, s, n, s); 1115 } else { 1116 fprintf(out->fp, "%s_assign_from_pe(&p->%.*s, v%i)", 1117 snref.text, n, s, index); 1118 } 1119 break; 1120 case convert_to_pe: 1121 if (from_ptr) { 1122 fprintf(out->fp, "%s_copy_to_pe(&p->%.*s, &p2->%.*s)", 1123 snref.text, n, s, n, s); 1124 } else { 1125 fprintf(out->fp, "%s_assign_to_pe(&p->%.*s, v%i)", 1126 snref.text, n, s, index); 1127 } 1128 break; 1129 default: 1130 if (from_ptr) { 1131 fprintf(out->fp, "p->%.*s = p2->%.*s", n, s, n, s); 1132 } else { 1133 fprintf(out->fp, "p->%.*s = v%i", n, s, index); 1134 } 1135 break; 1136 } 1137 ++index; 1138 continue; 1139 case vt_fixed_array_type: 1140 tprefix = scalar_type_prefix(member->type.st); 1141 len = (int)member->type.len; 1142 if (member->metadata_flags & fb_f_deprecated) { 1143 fprintf(out->fp, "__%sstruct_clear_field(p->__deprecated%i)", 1144 nsc, deprecated_index); 1145 ++deprecated_index; 1146 ++index; 1147 continue; 1148 } 1149 if (from_ptr) { 1150 fprintf(out->fp, "%s%s_array_copy%s(p->%.*s, p2->%.*s, %d)", 1151 nsc, tprefix, kind, n, s, n, s, len); 1152 } else { 1153 fprintf(out->fp, "%s%s_array_copy%s(p->%.*s, v%i, %d)", 1154 nsc, tprefix, kind, n, s, index, len); 1155 } 1156 ++index; 1157 break; 1158 case vt_scalar_type: 1159 tprefix = scalar_type_prefix(member->type.st); 1160 if (member->metadata_flags & fb_f_deprecated) { 1161 fprintf(out->fp, "__%sstruct_clear_field(p->__deprecated%i)", 1162 nsc, deprecated_index); 1163 ++deprecated_index; 1164 ++index; 1165 continue; 1166 } 1167 switch (member->size == 1 ? no_conversion : conversion) { 1168 case convert_from_pe: 1169 if (from_ptr) { 1170 fprintf(out->fp, "%s%s_copy_from_pe(&p->%.*s, &p2->%.*s)", 1171 nsc, tprefix, n, s, n, s); 1172 } else { 1173 fprintf(out->fp, "%s%s_assign_from_pe(&p->%.*s, v%i)", 1174 nsc, tprefix, n, s, index); 1175 } 1176 break; 1177 case convert_to_pe: 1178 if (from_ptr) { 1179 fprintf(out->fp, "%s%s_copy_to_pe(&p->%.*s, &p2->%.*s)", 1180 nsc, tprefix, n, s, n, s); 1181 } else { 1182 fprintf(out->fp, "%s%s_assign_to_pe(&p->%.*s, v%i)", 1183 nsc, tprefix, n, s, index); 1184 } 1185 break; 1186 default: 1187 if (from_ptr) { 1188 fprintf(out->fp, "p->%.*s = p2->%.*s", n, s, n, s); 1189 } else { 1190 fprintf(out->fp, "p->%.*s = v%i", n, s, index); 1191 } 1192 break; 1193 } 1194 ++index; 1195 break; 1196 default: 1197 gen_panic(out, "internal error: type error"); 1198 continue; 1199 } 1200 } 1201 if (arg_count > 0) { 1202 fprintf(out->fp, ";\n "); 1203 } 1204 return index; 1205 } 1206 1207 static void gen_builder_struct(fb_output_t *out, fb_compound_type_t *ct) 1208 { 1209 const char *nsc = out->nsc; 1210 int arg_count; 1211 fb_scoped_name_t snt; 1212 1213 fb_clear(snt); 1214 assert(ct->symbol.kind == fb_is_struct); 1215 1216 fb_compound_name(ct, &snt); 1217 1218 arg_count = get_total_struct_field_count(ct); 1219 fprintf(out->fp, "#define __%s_formal_args ", snt.text); 1220 gen_builder_struct_args(out, ct, 0, arg_count, 1); 1221 fprintf(out->fp, "\n#define __%s_call_args ", snt.text); 1222 gen_builder_struct_call_list(out, ct, 0, arg_count, 1); 1223 fprintf(out->fp, "\n"); 1224 fprintf(out->fp, 1225 "static inline %s_t *%s_assign(%s_t *p", 1226 snt.text, snt.text, snt.text); 1227 gen_builder_struct_args(out, ct, 0, arg_count, 0); 1228 fprintf(out->fp, ")\n{ "); 1229 gen_builder_struct_field_assign(out, ct, 0, arg_count, no_conversion, 0); 1230 fprintf(out->fp, "return p; }\n"); 1231 fprintf(out->fp, 1232 "static inline %s_t *%s_copy(%s_t *p, const %s_t *p2)\n", 1233 snt.text, snt.text, snt.text, snt.text); 1234 fprintf(out->fp, "{ "); 1235 gen_builder_struct_field_assign(out, ct, 0, arg_count, no_conversion, 1); 1236 fprintf(out->fp, "return p; }\n"); 1237 fprintf(out->fp, 1238 "static inline %s_t *%s_assign_to_pe(%s_t *p", 1239 snt.text, snt.text, snt.text); 1240 gen_builder_struct_args(out, ct, 0, arg_count, 0); 1241 fprintf(out->fp, ")\n{ "); 1242 gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_to_pe, 0); 1243 fprintf(out->fp, "return p; }\n"); 1244 fprintf(out->fp, 1245 "static inline %s_t *%s_copy_to_pe(%s_t *p, const %s_t *p2)\n", 1246 snt.text, snt.text, snt.text, snt.text); 1247 fprintf(out->fp, "{ "); 1248 gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_to_pe, 1); 1249 fprintf(out->fp, "return p; }\n"); 1250 fprintf(out->fp, 1251 "static inline %s_t *%s_assign_from_pe(%s_t *p", 1252 snt.text, snt.text, snt.text); 1253 gen_builder_struct_args(out, ct, 0, arg_count, 0); 1254 fprintf(out->fp, ")\n{ "); 1255 gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_from_pe, 0); 1256 fprintf(out->fp, "return p; }\n"); 1257 fprintf(out->fp, 1258 "static inline %s_t *%s_copy_from_pe(%s_t *p, const %s_t *p2)\n", 1259 snt.text, snt.text, snt.text, snt.text); 1260 fprintf(out->fp, "{ "); 1261 gen_builder_struct_field_assign(out, ct, 0, arg_count, convert_from_pe, 1); 1262 fprintf(out->fp, "return p; }\n"); 1263 fprintf(out->fp, "__%sbuild_struct(%s, %s, %"PRIu64", %u, %s_file_identifier, %s_type_identifier)\n", 1264 nsc, nsc, snt.text, (uint64_t)ct->size, ct->align, snt.text, snt.text); 1265 1266 if (ct->size > 0) { 1267 fprintf(out->fp, "__%sdefine_fixed_array_primitives(%s, %s, %s_t)\n", 1268 nsc, nsc, snt.text, snt.text); 1269 } 1270 } 1271 1272 static int get_create_table_arg_count(fb_compound_type_t *ct) 1273 { 1274 fb_member_t *member; 1275 fb_symbol_t *sym; 1276 int count = 0; 1277 1278 for (sym = ct->members; sym; sym = sym->link) { 1279 member = (fb_member_t *)sym; 1280 if (member->metadata_flags & fb_f_deprecated) { 1281 continue; 1282 } 1283 ++count; 1284 } 1285 return count; 1286 } 1287 1288 static int gen_builder_table_call_list(fb_output_t *out, fb_compound_type_t *ct, int arg_count, int is_macro) 1289 { 1290 fb_member_t *member; 1291 fb_symbol_t *sym; 1292 int index = 0; 1293 1294 for (sym = ct->members; sym; sym = sym->link) { 1295 member = (fb_member_t *)sym; 1296 if (member->metadata_flags & fb_f_deprecated) { 1297 continue; 1298 } 1299 gen_comma(out, index, arg_count, is_macro); 1300 fprintf(out->fp, "v%"PRIu64"", (uint64_t)member->id); 1301 ++index; 1302 } 1303 return index; 1304 } 1305 1306 1307 static int gen_required_table_fields(fb_output_t *out, fb_compound_type_t *ct) 1308 { 1309 const char *nsc = out->nsc; 1310 fb_member_t *member; 1311 fb_symbol_t *sym; 1312 int index; 1313 int arg_count; 1314 fb_scoped_name_t snt; 1315 1316 fb_clear(snt); 1317 arg_count = get_create_table_arg_count(ct); 1318 index = 0; 1319 fb_compound_name(ct, &snt); 1320 fprintf(out->fp, "static const %svoffset_t __%s_required[] = {", nsc, snt.text); 1321 for (sym = ct->members; sym; sym = sym->link) { 1322 member = (fb_member_t *)sym; 1323 if (member->metadata_flags & fb_f_deprecated) { 1324 continue; 1325 } 1326 if (member->metadata_flags & fb_f_required) { 1327 if (index > 0) { 1328 gen_comma(out, index, arg_count, 0); 1329 } else { 1330 fprintf(out->fp, " "); 1331 } 1332 fprintf(out->fp, "%u", (unsigned)member->id); 1333 index++; 1334 } 1335 } 1336 /* Add extra element to avoid null arrays. */ 1337 if (index > 0) { 1338 fprintf(out->fp, ", 0 };\n"); 1339 } else { 1340 fprintf(out->fp, " 0 };\n"); 1341 } 1342 return index; 1343 } 1344 1345 static int gen_builder_table_args(fb_output_t *out, fb_compound_type_t *ct, int arg_count, int is_macro) 1346 { 1347 const char *nsc = out->nsc; 1348 fb_symbol_t *sym; 1349 fb_member_t *member; 1350 const char *tname, *tname_ns; 1351 int index; 1352 fb_scoped_name_t snref; 1353 1354 fb_clear(snref); 1355 /* Just to help the comma. */ 1356 index = 0; 1357 /* We use the id to name arguments so sorted assignment can find the arguments trivially. */ 1358 for (sym = ct->members; sym; sym = sym->link) { 1359 member = (fb_member_t *)sym; 1360 if (member->metadata_flags & fb_f_deprecated) { 1361 continue; 1362 } 1363 gen_comma(out, index++, arg_count, is_macro); 1364 switch (member->type.type) { 1365 case vt_compound_type_ref: 1366 fb_compound_name(member->type.ct, &snref); 1367 switch (member->type.ct->symbol.kind) { 1368 case fb_is_struct: 1369 fprintf(out->fp, "%s_t *v%"PRIu64"", snref.text, (uint64_t)member->id); 1370 break; 1371 case fb_is_enum: 1372 fprintf(out->fp, "%s_enum_t v%"PRIu64"", snref.text, (uint64_t)member->id); 1373 break; 1374 case fb_is_table: 1375 fprintf(out->fp, "%s_ref_t v%"PRIu64"", snref.text, (uint64_t)member->id); 1376 break; 1377 case fb_is_union: 1378 /* Unions jump an index because it is two fields. */ 1379 fprintf(out->fp, "%s_union_ref_t v%"PRIu64"", snref.text, (uint64_t)member->id); 1380 break; 1381 default: 1382 gen_panic(out, "internal error: unexpected table field type"); 1383 continue; 1384 } 1385 break; 1386 case vt_vector_compound_type_ref: 1387 fb_compound_name(member->type.ct, &snref); 1388 switch (member->type.ct->symbol.kind) { 1389 case fb_is_struct: 1390 case fb_is_enum: 1391 case fb_is_table: 1392 fprintf(out->fp, "%s_vec_ref_t v%"PRIu64"", snref.text, (uint64_t)member->id); 1393 break; 1394 case fb_is_union: 1395 fprintf(out->fp, "%s_union_vec_ref_t v%"PRIu64"", snref.text, (uint64_t)member->id); 1396 break; 1397 default: 1398 gen_panic(out, "internal error: unexpected table table type"); 1399 continue; 1400 } 1401 break; 1402 case vt_scalar_type: 1403 tname_ns = scalar_type_ns(member->type.st, nsc); 1404 tname = scalar_type_name(member->type.st); 1405 fprintf(out->fp, "%s%s v%"PRIu64"", tname_ns, tname, (uint64_t)member->id); 1406 break; 1407 case vt_vector_type: 1408 tname = scalar_type_prefix(member->type.st); 1409 fprintf(out->fp, "%s%s_vec_ref_t v%"PRIu64"", nsc, tname, (uint64_t)member->id); 1410 break; 1411 case vt_string_type: 1412 fprintf(out->fp, "%sstring_ref_t v%"PRIu64"", nsc, (uint64_t)member->id); 1413 break; 1414 case vt_vector_string_type: 1415 fprintf(out->fp, "%sstring_vec_ref_t v%"PRIu64"", nsc, (uint64_t)member->id); 1416 break; 1417 default: 1418 gen_panic(out, "internal error: unexpected table member type"); 1419 continue; 1420 } 1421 } 1422 return index; 1423 } 1424 1425 static int gen_builder_create_table_decl(fb_output_t *out, fb_compound_type_t *ct) 1426 { 1427 const char *nsc = out->nsc; 1428 int arg_count; 1429 fb_scoped_name_t snt; 1430 1431 fb_clear(snt); 1432 fb_compound_name(ct, &snt); 1433 1434 arg_count = get_create_table_arg_count(ct); 1435 fprintf(out->fp, "#define __%s_formal_args ", snt.text); 1436 gen_builder_table_args(out, ct, arg_count, 1); 1437 fprintf(out->fp, "\n#define __%s_call_args ", snt.text); 1438 gen_builder_table_call_list(out, ct, arg_count, 1); 1439 fprintf(out->fp, "\n"); 1440 1441 /* `_clone` fw decl must be place before build_table macro and `_create` must be placed after. */ 1442 fprintf(out->fp, 1443 "static inline %s_ref_t %s_create(%sbuilder_t *B __%s_formal_args);\n", 1444 snt.text, snt.text, nsc, snt.text); 1445 return 0; 1446 } 1447 1448 static int gen_builder_create_table(fb_output_t *out, fb_compound_type_t *ct) 1449 { 1450 const char *nsc = out->nsc; 1451 fb_member_t *member; 1452 int n; 1453 const char *s; 1454 int patch_union = !(ct->metadata_flags & fb_f_original_order); 1455 int has_union = 0; 1456 fb_scoped_name_t snt; 1457 1458 fb_clear(snt); 1459 fb_compound_name(ct, &snt); 1460 1461 fprintf(out->fp, 1462 "static inline %s_ref_t %s_create(%sbuilder_t *B __%s_formal_args)\n", 1463 snt.text, snt.text, nsc, snt.text); 1464 1465 fprintf(out->fp, "{\n if (%s_start(B)", snt.text); 1466 for (member = ct->ordered_members; member; member = member->order) { 1467 if (member->metadata_flags & fb_f_deprecated) { 1468 continue; 1469 } 1470 symbol_name(&member->symbol, &n, &s); 1471 if (member->type.type == vt_compound_type_ref && member->type.ct->symbol.kind == fb_is_union) { 1472 has_union = 1; 1473 if (patch_union) { 1474 fprintf(out->fp, "\n || %s_%.*s_add_value(B, v%"PRIu64")", snt.text, n, s, (uint64_t)member->id); 1475 continue; 1476 } 1477 } 1478 fprintf(out->fp, "\n || %s_%.*s_add(B, v%"PRIu64")", snt.text, n, s, (uint64_t)member->id); 1479 } 1480 if (patch_union && has_union) { 1481 for (member = ct->ordered_members; member; member = member->order) { 1482 if (member->metadata_flags & fb_f_deprecated) { 1483 continue; 1484 } 1485 if (member->type.type == vt_compound_type_ref && member->type.ct->symbol.kind == fb_is_union) { 1486 symbol_name(&member->symbol, &n, &s); 1487 fprintf(out->fp, "\n || %s_%.*s_add_type(B, v%"PRIu64".type)", snt.text, n, s, (uint64_t)member->id); 1488 } 1489 } 1490 } 1491 fprintf(out->fp, ") {\n return 0;\n }\n return %s_end(B);\n}\n\n", snt.text); 1492 return 0; 1493 } 1494 1495 static int gen_builder_structs(fb_output_t *out) 1496 { 1497 fb_compound_type_t *ct; 1498 1499 /* Generate structs in topologically sorted order. */ 1500 for (ct = out->S->ordered_structs; ct; ct = ct->order) { 1501 gen_builder_struct(out, ct); 1502 fprintf(out->fp, "\n"); 1503 } 1504 return 0; 1505 } 1506 1507 static int gen_builder_table(fb_output_t *out, fb_compound_type_t *ct) 1508 { 1509 const char *nsc = out->nsc; 1510 fb_scoped_name_t snt; 1511 1512 fb_clear(snt); 1513 fb_compound_name(ct, &snt); 1514 1515 fprintf(out->fp, 1516 "typedef %sref_t %s_ref_t;\n", 1517 nsc, snt.text); 1518 fprintf(out->fp, 1519 "static %s_ref_t %s_clone(%sbuilder_t *B, %s_table_t t);\n", 1520 snt.text, snt.text, nsc, snt.text); 1521 fprintf(out->fp, "__%sbuild_table(%s, %s, %"PRIu64")\n", 1522 nsc, nsc, snt.text, (uint64_t)ct->count); 1523 return 0; 1524 } 1525 1526 static int gen_builder_table_prolog(fb_output_t *out, fb_compound_type_t *ct) 1527 { 1528 const char *nsc = out->nsc; 1529 fb_scoped_name_t snt; 1530 1531 fb_clear(snt); 1532 fb_compound_name(ct, &snt); 1533 1534 fprintf(out->fp, "__%sbuild_table_prolog(%s, %s, %s_file_identifier, %s_type_identifier)\n", 1535 nsc, nsc, snt.text, snt.text, snt.text); 1536 return 0; 1537 } 1538 1539 static int gen_union_fields(fb_output_t *out, const char *st, int n, const char *s, 1540 fb_compound_type_t *ct, int is_vector) 1541 { 1542 const char *nsc = out->nsc; 1543 fb_symbol_t *sym; 1544 fb_member_t *member; 1545 const char *su; 1546 int nu; 1547 fb_scoped_name_t snref; 1548 fb_scoped_name_t snu; 1549 const char *kind = is_vector ? "vector_value" : "value"; 1550 1551 fb_clear(snref); 1552 fb_clear(snu); 1553 fb_compound_name(ct, &snref); 1554 for (sym = ct->members; sym; sym = sym->link) { 1555 member = (fb_member_t *)sym; 1556 symbol_name(sym, &nu, &su); 1557 switch (member->type.type) { 1558 case vt_missing: 1559 break; 1560 case vt_compound_type_ref: 1561 fb_compound_name(member->type.ct, &snu); 1562 switch (member->type.ct->symbol.kind) { 1563 case fb_is_table: 1564 fprintf(out->fp, 1565 "__%sbuild_union_table_%s_field(%s, %s_%.*s, %s, %.*s, %s)\n", 1566 nsc, kind, nsc, st, n, s, snref.text, nu, su, snu.text); 1567 break; 1568 case fb_is_struct: 1569 fprintf(out->fp, 1570 "__%sbuild_union_struct_%s_field(%s, %s_%.*s, %s, %.*s, %s)\n", 1571 nsc, kind, nsc, st, n, s, snref.text, nu, su, snu.text); 1572 break; 1573 default: 1574 gen_panic(out, "internal error: unexpected union member compound type"); 1575 return -1; 1576 } 1577 break; 1578 case vt_string_type: 1579 fprintf(out->fp, 1580 "__%sbuild_union_string_%s_field(%s, %s_%.*s, %s, %.*s)\n", 1581 nsc, kind, nsc, st, n, s, snref.text, nu, su); 1582 break; 1583 default: 1584 gen_panic(out, "internal error: unexpected union member type"); 1585 return -1; 1586 } 1587 } 1588 return 0; 1589 } 1590 1591 static int gen_builder_table_fields(fb_output_t *out, fb_compound_type_t *ct) 1592 { 1593 const char *nsc = out->nsc; 1594 fb_member_t *member; 1595 fb_symbol_t *sym; 1596 const char *s, *tprefix, *tname, *tname_ns; 1597 int n; 1598 int is_optional; 1599 fb_scoped_name_t snt; 1600 fb_scoped_name_t snref; 1601 fb_literal_t literal; 1602 1603 fb_clear(snt); 1604 fb_clear(snref); 1605 fb_compound_name(ct, &snt); 1606 1607 for (sym = ct->members; sym; sym = sym->link) { 1608 member = (fb_member_t *)sym; 1609 symbol_name(&member->symbol, &n, &s); 1610 if (member->metadata_flags & fb_f_deprecated) { 1611 fprintf(out->fp, "/* Skipping build of deprecated field: '%s_%.*s' */\n\n", snt.text, n, s); 1612 continue; 1613 } 1614 is_optional = member->flags & fb_fm_optional; 1615 switch (member->type.type) { 1616 case vt_scalar_type: 1617 tname_ns = scalar_type_ns(member->type.st, nsc); 1618 tname = scalar_type_name(member->type.st); 1619 tprefix = scalar_type_prefix(member->type.st); 1620 if (is_optional) { 1621 fprintf(out->fp, 1622 "__%sbuild_scalar_optional_field(%"PRIu64", %s, %s_%.*s, %s%s, %s%s, %"PRIu64", %u, %s)\n", 1623 nsc, (uint64_t)member->id, nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname, 1624 (uint64_t)member->size, member->align, snt.text); 1625 } else { 1626 print_literal(member->type.st, &member->value, literal); 1627 fprintf(out->fp, 1628 "__%sbuild_scalar_field(%"PRIu64", %s, %s_%.*s, %s%s, %s%s, %"PRIu64", %u, %s, %s)\n", 1629 nsc, (uint64_t)member->id, nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname, 1630 (uint64_t)member->size, member->align, literal, snt.text); 1631 } 1632 break; 1633 case vt_vector_type: 1634 tname_ns = scalar_type_ns(member->type.st, nsc); 1635 tname = scalar_type_name(member->type.st); 1636 tprefix = scalar_type_prefix(member->type.st); 1637 fprintf(out->fp, 1638 "__%sbuild_vector_field(%"PRIu64", %s, %s_%.*s, %s%s, %s%s, %s)\n", 1639 nsc, (uint64_t)member->id, nsc, snt.text, n, s, nsc, tprefix, tname_ns, tname, snt.text); 1640 /* [ubyte] vectors can nest buffers. */ 1641 if (member->nest) { 1642 switch (member->nest->symbol.kind) { 1643 case fb_is_table: 1644 fb_compound_name((fb_compound_type_t *)(&member->nest->symbol), &snref); 1645 fprintf(out->fp, "__%sbuild_nested_table_root(%s, %s_%.*s, %s, %s_identifier, %s_type_identifier)\n", 1646 nsc, nsc, snt.text, n, s, snref.text, snref.text, snref.text); 1647 break; 1648 case fb_is_struct: 1649 fb_compound_name((fb_compound_type_t *)(&member->nest->symbol), &snref); 1650 fprintf(out->fp, "__%sbuild_nested_struct_root(%s, %s_%.*s, %s, %u, %s_identifier, %s_type_identifier)\n", 1651 nsc, nsc, snt.text, n, s, snref.text, 1652 (unsigned)((fb_compound_type_t *)(member->nest))->align, snref.text, snref.text); 1653 break; 1654 default: 1655 gen_panic(out, "internal error: unexpected nested type"); 1656 continue; 1657 } 1658 } 1659 break; 1660 case vt_string_type: 1661 fprintf(out->fp, 1662 "__%sbuild_string_field(%"PRIu64", %s, %s_%.*s, %s)\n", 1663 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snt.text); 1664 break; 1665 case vt_vector_string_type: 1666 fprintf(out->fp, 1667 "__%sbuild_string_vector_field(%"PRIu64", %s, %s_%.*s, %s)\n", 1668 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snt.text); 1669 break; 1670 case vt_compound_type_ref: 1671 fb_compound_name(member->type.ct, &snref); 1672 switch (member->type.ct->symbol.kind) { 1673 case fb_is_struct: 1674 fprintf(out->fp, 1675 "__%sbuild_struct_field(%"PRIu64", %s, %s_%.*s, %s, %"PRIu64", %u, %s)\n", 1676 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, (uint64_t)member->size, member->align, snt.text); 1677 break; 1678 case fb_is_table: 1679 fprintf(out->fp, 1680 "__%sbuild_table_field(%"PRIu64", %s, %s_%.*s, %s, %s)\n", 1681 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snt.text); 1682 break; 1683 case fb_is_enum: 1684 if (is_optional) { 1685 fprintf(out->fp, 1686 "__%sbuild_scalar_optional_field(%"PRIu64", %s, %s_%.*s, %s, %s_enum_t, %"PRIu64", %u, %s)\n", 1687 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snref.text, 1688 (uint64_t)member->size, member->align, snt.text); 1689 } else { 1690 print_literal(member->type.ct->type.st, &member->value, literal); 1691 fprintf(out->fp, 1692 "__%sbuild_scalar_field(%"PRIu64", %s, %s_%.*s, %s, %s_enum_t, %"PRIu64", %u, %s, %s)\n", 1693 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snref.text, 1694 (uint64_t)member->size, member->align, literal, snt.text); 1695 } 1696 break; 1697 case fb_is_union: 1698 fprintf(out->fp, 1699 "__%sbuild_union_field(%"PRIu64", %s, %s_%.*s, %s, %s)\n", 1700 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snt.text); 1701 gen_union_fields(out, snt.text, n, s, member->type.ct, 0); 1702 break; 1703 default: 1704 gen_panic(out, "internal error: unexpected compound type in table during code generation"); 1705 break; 1706 } 1707 break; 1708 case vt_vector_compound_type_ref: 1709 fb_compound_name(member->type.ct, &snref); 1710 switch (member->type.ct->symbol.kind) { 1711 case fb_is_struct: 1712 if (member->type.ct->symbol.flags & fb_indexed) { 1713 fprintf(out->fp, "/* vector has keyed elements */\n"); 1714 } 1715 fprintf(out->fp, 1716 "__%sbuild_vector_field(%"PRIu64", %s, %s_%.*s, %s, %s_t, %s)\n", 1717 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snref.text, snt.text); 1718 break; 1719 case fb_is_table: 1720 if (member->type.ct->symbol.flags & fb_indexed) { 1721 fprintf(out->fp, "/* vector has keyed elements */\n"); 1722 } 1723 fprintf(out->fp, 1724 "__%sbuild_table_vector_field(%"PRIu64", %s, %s_%.*s, %s, %s)\n", 1725 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snt.text); 1726 break; 1727 case fb_is_enum: 1728 fprintf(out->fp, 1729 "__%sbuild_vector_field(%"PRIu64", %s, %s_%.*s, %s, %s_enum_t, %s)\n", 1730 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snref.text, snt.text); 1731 break; 1732 case fb_is_union: 1733 fprintf(out->fp, 1734 "__%sbuild_union_vector_field(%"PRIu64", %s, %s_%.*s, %s, %s)\n", 1735 nsc, (uint64_t)member->id, nsc, snt.text, n, s, snref.text, snt.text); 1736 gen_union_fields(out, snt.text, n, s, member->type.ct, 1); 1737 break; 1738 default: 1739 gen_panic(out, "internal error: unexpected vector compound type in table during code generation"); 1740 break; 1741 } 1742 break; 1743 default: 1744 gen_panic(out, "internal error: unexpected table member type during code generation"); 1745 break; 1746 } 1747 } 1748 fprintf(out->fp, "\n"); 1749 return 0; 1750 } 1751 1752 /* 1753 * NOTE: 1754 * 1755 * Cloning a table might lead to a combinatorial explosion if the source 1756 * has many shared references in a DAG. In many cases this might not be 1757 * an issue, but it it is deduplication will be necessary. Deduplication 1758 * is not specific to cloning but especially relevant here. Because 1759 * deduplication carries an overhead in runtime and complexity it is not 1760 * part of the core cloning operation. Cloning of unions and vectors with 1761 * references have similar concerns. 1762 * 1763 * A deduplication operation would internally look like like this: 1764 * 1765 * dedup_clone_table(builder, dedup_map, src_ptr) 1766 * { 1767 * ref = get_cloned_ref(dedup_map, src_ptr) 1768 * if (!ref) { 1769 * ref = clone_table(builder, src_ptr); 1770 * set_cloned_ref(dedup_map, src_ptr, ref); 1771 * } 1772 * return ref; 1773 * } 1774 * 1775 * where dedup_map is a map from a pointer to a builder reference and 1776 * where the dedup_map is dedicated to a single builder and may cover 1777 * multiple source buffers as long as they have separate memory 1778 * locations - otherwise a separate dedup map must be used for each 1779 * source buffer. 1780 * 1781 * Note that the clone operation is not safe without a safe source 1782 * buffer so clone cannot be used to make a buffer with overlapping data 1783 * safe (e.g. a string and a table referencing the same memory). Even if 1784 * the source passes basic verification the result might not. To make 1785 * clone safe it would be necessariry to remember the type as well, for 1786 * example by adding a type specifier to the dedup_map. 1787 * 1788 * In the following we do not implement deduplication. 1789 */ 1790 static int gen_builder_clone_table(fb_output_t *out, fb_compound_type_t *ct) 1791 { 1792 const char *nsc = out->nsc; 1793 fb_member_t *member; 1794 const char *s; 1795 int n; 1796 fb_scoped_name_t snt; 1797 fb_scoped_name_t snref; 1798 1799 fb_clear(snt); 1800 fb_clear(snref); 1801 fb_compound_name(ct, &snt); 1802 1803 /* 1804 * We could optimize this by cloning the entire table memory block 1805 * and then update update only the references. The builder has 1806 * direct vtable operations to support this - this would not work 1807 * properly if there are deprecated fields to be stripped or if the 1808 * default value has changed - and, more complicated: it is 1809 * necessary to know what table alignment needs to be which require 1810 * inspection of all fields, or a worst case assumption. So at least 1811 * for now, we clone by picking one field at a time. 1812 */ 1813 1814 fprintf(out->fp, 1815 "static %s_ref_t %s_clone(%sbuilder_t *B, %s_table_t t)\n", 1816 snt.text, snt.text, nsc, snt.text); 1817 1818 fprintf(out->fp, 1819 "{\n" 1820 " __%smemoize_begin(B, t);\n" 1821 " if (%s_start(B)", nsc, snt.text); 1822 for (member = ct->ordered_members; member; member = member->order) { 1823 if (member->metadata_flags & fb_f_deprecated) { 1824 continue; 1825 } 1826 symbol_name(&member->symbol, &n, &s); 1827 switch (member->type.type) { 1828 case vt_scalar_type: 1829 case vt_vector_type: /* This includes nested buffers - they are just transferred as bytes. */ 1830 case vt_string_type: 1831 case vt_vector_string_type: 1832 fprintf(out->fp, "\n || %s_%.*s_pick(B, t)", snt.text, n, s); 1833 break; 1834 case vt_compound_type_ref: 1835 fb_compound_name(member->type.ct, &snref); 1836 switch (member->type.ct->symbol.kind) { 1837 case fb_is_struct: 1838 case fb_is_table: 1839 case fb_is_enum: 1840 case fb_is_union: 1841 fprintf(out->fp, "\n || %s_%.*s_pick(B, t)", snt.text, n, s); 1842 break; 1843 default: 1844 gen_panic(out, "internal error: unexpected compound type in table during code generation"); 1845 break; 1846 } 1847 break; 1848 case vt_vector_compound_type_ref: 1849 fb_compound_name(member->type.ct, &snref); 1850 switch (member->type.ct->symbol.kind) { 1851 case fb_is_struct: 1852 case fb_is_table: 1853 case fb_is_enum: 1854 case fb_is_union: 1855 fprintf(out->fp, "\n || %s_%.*s_pick(B, t)", snt.text, n, s); 1856 break; 1857 default: 1858 gen_panic(out, "internal error: unexpected vector compound type in table during code generation"); 1859 break; 1860 } 1861 break; 1862 default: 1863 gen_panic(out, "internal error: unexpected table member type during code generation"); 1864 break; 1865 } 1866 } 1867 fprintf(out->fp, ") {\n" 1868 " return 0;\n" 1869 " }\n" 1870 " __%smemoize_end(B, t, %s_end(B));\n}\n", nsc, snt.text); 1871 return 0; 1872 } 1873 1874 static int gen_builder_enums(fb_output_t *out) 1875 { 1876 const char *nsc = out->nsc; 1877 fb_symbol_t *sym; 1878 int was_here = 0; 1879 fb_scoped_name_t snt; 1880 1881 fb_clear(snt); 1882 1883 for (sym = out->S->symbols; sym; sym = sym->link) { 1884 switch (sym->kind) { 1885 case fb_is_enum: 1886 fb_compound_name((fb_compound_type_t *)sym, &snt); 1887 fprintf(out->fp, 1888 "#define __%s_formal_args , %s_enum_t v0\n" 1889 "#define __%s_call_args , v0\n", 1890 snt.text, snt.text, 1891 snt.text); 1892 fprintf(out->fp, "__%sbuild_scalar(%s, %s, %s_enum_t)\n", 1893 nsc, nsc, snt.text, snt.text); 1894 was_here = 1; 1895 break; 1896 default: 1897 continue; 1898 } 1899 } 1900 if (was_here) { 1901 fprintf(out->fp, "\n"); 1902 } 1903 return 0; 1904 } 1905 1906 /* 1907 * Scope resolution is a bit fuzzy in unions - 1908 * 1909 * Googles flatc compiler allows dot notation in unions but not enums. 1910 * C++ generates unqualified enum members (i.e. MyGame.Example.Monster 1911 * becomes Monster) in the generated enum but still refers to the 1912 * specific table type in the given namespace. This makes it possible 1913 * to have name conflicts, and flatc raises these like other enum 1914 * conficts. 1915 * 1916 * We use the same approach and this is why we both look up compound 1917 * name and symbol name for the same member but the code generator 1918 * is not concerned with how the scope is parsed or how errors are 1919 * flagged - it just expects members to be unique. 1920 */ 1921 static int gen_union(fb_output_t *out, fb_compound_type_t *ct) 1922 { 1923 const char *nsc = out->nsc; 1924 fb_member_t *member; 1925 fb_symbol_t *sym; 1926 const char *s; 1927 int n; 1928 fb_scoped_name_t snt; 1929 fb_scoped_name_t snref; 1930 1931 fb_clear(snt); 1932 fb_clear(snref); 1933 fb_compound_name(ct, &snt); 1934 1935 for (sym = ct->members; sym; sym = sym->link) { 1936 member = (fb_member_t *)sym; 1937 switch (member->type.type) { 1938 case vt_compound_type_ref: 1939 fb_compound_name((fb_compound_type_t *)member->type.ct, &snref); 1940 symbol_name(sym, &n, &s); 1941 fprintf(out->fp, 1942 "static inline %s_union_ref_t %s_as_%.*s(%s_ref_t ref)\n" 1943 "{ %s_union_ref_t uref; uref.type = %s_%.*s; uref.value = ref; return uref; }\n", 1944 snt.text, snt.text, n, s, snref.text, 1945 snt.text, snt.text, n, s); 1946 break; 1947 case vt_string_type: 1948 symbol_name(sym, &n, &s); 1949 fprintf(out->fp, 1950 "static inline %s_union_ref_t %s_as_%.*s(%sstring_ref_t ref)\n" 1951 "{ %s_union_ref_t uref; uref.type = %s_%.*s; uref.value = ref; return uref; }\n", 1952 snt.text, snt.text, n, s, nsc, 1953 snt.text, snt.text, n, s); 1954 break; 1955 case vt_missing: 1956 fprintf(out->fp, 1957 "static inline %s_union_ref_t %s_as_NONE(void)\n" 1958 "{ %s_union_ref_t uref; uref.type = %s_NONE; uref.value = 0; return uref; }\n", 1959 snt.text, snt.text, snt.text, snt.text); 1960 break; 1961 default: 1962 gen_panic(out, "internal error: unexpected union value type"); 1963 break; 1964 } 1965 } 1966 fprintf(out->fp, 1967 "__%sbuild_union_vector(%s, %s)\n\n", 1968 nsc, nsc, snt.text); 1969 return 0; 1970 } 1971 1972 static int gen_union_clone(fb_output_t *out, fb_compound_type_t *ct) 1973 { 1974 const char *nsc = out->nsc; 1975 fb_member_t *member; 1976 fb_symbol_t *sym; 1977 const char *s; 1978 int n; 1979 fb_scoped_name_t snt; 1980 fb_scoped_name_t snref; 1981 1982 fb_clear(snt); 1983 fb_clear(snref); 1984 fb_compound_name(ct, &snt); 1985 1986 fprintf(out->fp, 1987 "static %s_union_ref_t %s_clone(%sbuilder_t *B, %s_union_t u)\n{\n switch (u.type) {\n", 1988 snt.text, snt.text, nsc, snt.text); 1989 1990 for (sym = ct->members; sym; sym = sym->link) { 1991 member = (fb_member_t *)sym; 1992 switch (member->type.type) { 1993 case vt_compound_type_ref: 1994 fb_compound_name((fb_compound_type_t *)member->type.ct, &snref); 1995 symbol_name(sym, &n, &s); 1996 switch (member->type.ct->symbol.kind) { 1997 case fb_is_table: 1998 fprintf(out->fp, 1999 " case %u: return %s_as_%.*s(%s_clone(B, (%s_table_t)u.value));\n", 2000 (unsigned)member->value.u, snt.text, n, s, snref.text, snref.text); 2001 break; 2002 case fb_is_struct: 2003 fprintf(out->fp, 2004 " case %u: return %s_as_%.*s(%s_clone(B, (%s_struct_t)u.value));\n", 2005 (unsigned)member->value.u, snt.text, n, s, snref.text, snref.text); 2006 break; 2007 default: 2008 gen_panic(out, "internal error: unexpected union value type"); 2009 break; 2010 } 2011 break; 2012 case vt_string_type: 2013 symbol_name(sym, &n, &s); 2014 fprintf(out->fp, 2015 " case %u: return %s_as_%.*s(%sstring_clone(B, u.value));\n", 2016 (unsigned)member->value.u, snt.text, n, s, nsc); 2017 break; 2018 case vt_missing: 2019 break; 2020 default: 2021 gen_panic(out, "internal error: unexpected union value type"); 2022 break; 2023 } 2024 } 2025 2026 /* Unknown unions are dropped. */ 2027 fprintf(out->fp, 2028 " default: return %s_as_NONE();\n" 2029 " }\n}\n", 2030 snt.text); 2031 return 0; 2032 } 2033 2034 2035 static int gen_builder_union_decls(fb_output_t *out) 2036 { 2037 const char *nsc = out->nsc; 2038 fb_symbol_t *sym; 2039 int was_here = 0; 2040 fb_scoped_name_t snt; 2041 2042 fb_clear(snt); 2043 2044 for (sym = out->S->symbols; sym; sym = sym->link) { 2045 switch (sym->kind) { 2046 case fb_is_union: 2047 fb_compound_name((fb_compound_type_t *)sym, &snt); 2048 fprintf(out->fp, 2049 "typedef %sunion_ref_t %s_union_ref_t;\n" 2050 "typedef %sunion_vec_ref_t %s_union_vec_ref_t;\n", 2051 nsc, snt.text, nsc, snt.text); 2052 fprintf(out->fp, 2053 "static %s_union_ref_t %s_clone(%sbuilder_t *B, %s_union_t t);\n", 2054 snt.text, snt.text, nsc, snt.text); 2055 was_here = 1; 2056 break; 2057 default: 2058 continue; 2059 } 2060 } 2061 if (was_here) { 2062 fprintf(out->fp, "\n"); 2063 } 2064 return 0; 2065 } 2066 2067 static int gen_builder_unions(fb_output_t *out) 2068 { 2069 fb_symbol_t *sym; 2070 2071 for (sym = out->S->symbols; sym; sym = sym->link) { 2072 switch (sym->kind) { 2073 case fb_is_union: 2074 gen_union(out, (fb_compound_type_t *)sym); 2075 gen_union_clone(out, (fb_compound_type_t *)sym); 2076 fprintf(out->fp, "\n"); 2077 break; 2078 default: 2079 continue; 2080 } 2081 } 2082 return 0; 2083 } 2084 2085 static int gen_builder_table_decls(fb_output_t *out) 2086 { 2087 fb_symbol_t *sym; 2088 2089 /* 2090 * Because tables are recursive, we need the type and `start/end/add` 2091 * operations before the fields. We also need create for push_create 2092 * but it needs all dependent types, so create is fw declared 2093 * in a subsequent step. The actual create impl. then follows 2094 * after the table fields. 2095 */ 2096 for (sym = out->S->symbols; sym; sym = sym->link) { 2097 switch (sym->kind) { 2098 case fb_is_table: 2099 gen_required_table_fields(out, (fb_compound_type_t *)sym); 2100 gen_builder_table(out, (fb_compound_type_t *)sym); 2101 fprintf(out->fp, "\n"); 2102 break; 2103 default: 2104 continue; 2105 } 2106 } 2107 for (sym = out->S->symbols; sym; sym = sym->link) { 2108 switch (sym->kind) { 2109 case fb_is_table: 2110 gen_builder_create_table_decl(out, (fb_compound_type_t *)sym); 2111 gen_builder_table_prolog(out, (fb_compound_type_t *)sym); 2112 fprintf(out->fp, "\n"); 2113 break; 2114 default: 2115 continue; 2116 } 2117 } 2118 return 0; 2119 } 2120 2121 static int gen_builder_tables(fb_output_t *out) 2122 { 2123 fb_symbol_t *sym; 2124 for (sym = out->S->symbols; sym; sym = sym->link) { 2125 switch (sym->kind) { 2126 case fb_is_table: 2127 gen_builder_table_fields(out, (fb_compound_type_t *)sym); 2128 gen_builder_create_table(out, (fb_compound_type_t *)sym); 2129 gen_builder_clone_table(out, (fb_compound_type_t *)sym); 2130 fprintf(out->fp, "\n"); 2131 break; 2132 default: 2133 continue; 2134 } 2135 } 2136 return 0; 2137 } 2138 2139 static int gen_builder_footer(fb_output_t *out) 2140 { 2141 gen_epilogue(out); 2142 fprintf(out->fp, 2143 "#endif /* %s_BUILDER_H */\n", 2144 out->S->basenameup); 2145 return 0; 2146 } 2147 2148 int fb_gen_c_builder(fb_output_t *out) 2149 { 2150 gen_builder_pretext(out); 2151 gen_builder_enums(out); 2152 gen_builder_structs(out); 2153 gen_builder_union_decls(out); 2154 gen_builder_table_decls(out); 2155 gen_builder_unions(out); 2156 gen_builder_tables(out); 2157 gen_builder_footer(out); 2158 return 0; 2159 }