nostrdb

an unfairly fast embedded nostr database backed by lmdb
git clone git://jb55.com/nostrdb
Log | Files | Refs | Submodules | README | LICENSE

semantics.c (72098B)


      1 #include <string.h>
      2 #include <assert.h>
      3 
      4 #include "semantics.h"
      5 #include "parser.h"
      6 #include "coerce.h"
      7 #include "stdio.h"
      8 
      9 /* -DFLATCC_PORTABLE may help if inttypes.h is missing. */
     10 #ifndef PRId64
     11 #include <inttypes.h>
     12 #endif
     13 
     14 /* Same order as enum! */
     15 static const char *fb_known_attribute_names[] = {
     16     "",
     17     "id",
     18     "deprecated",
     19     "original_order",
     20     "force_align",
     21     "bit_flags",
     22     "nested_flatbuffer",
     23     "key",
     24     "required",
     25     "hash",
     26     "base64",
     27     "base64url",
     28     "primary_key",
     29     "sorted",
     30 };
     31 
     32 static const int fb_known_attribute_types[] = {
     33     vt_invalid, /* Unknowns have arbitrary types. */
     34     vt_uint,
     35     vt_missing,
     36     vt_missing,
     37     vt_uint,
     38     vt_missing,
     39     vt_string,
     40     vt_missing,
     41     vt_missing,
     42     vt_string,
     43     vt_missing,
     44     vt_missing,
     45     vt_missing,
     46     vt_missing,
     47 };
     48 
     49 static fb_scalar_type_t map_scalar_token_type(fb_token_t *t)
     50 {
     51     switch (t->id) {
     52     case tok_kw_uint64:
     53     case tok_kw_ulong:
     54         return fb_ulong;
     55     case tok_kw_uint32:
     56     case tok_kw_uint:
     57         return fb_uint;
     58     case tok_kw_uint16:
     59     case tok_kw_ushort:
     60         return fb_ushort;
     61     case tok_kw_uint8:
     62     case tok_kw_ubyte:
     63         return fb_ubyte;
     64     case tok_kw_char:
     65         return fb_char;
     66     case tok_kw_bool:
     67         return fb_bool;
     68     case tok_kw_int64:
     69     case tok_kw_long:
     70         return fb_long;
     71     case tok_kw_int32:
     72     case tok_kw_int:
     73         return fb_int;
     74     case tok_kw_int16:
     75     case tok_kw_short:
     76         return fb_short;
     77     case tok_kw_int8:
     78     case tok_kw_byte:
     79         return fb_byte;
     80     case tok_kw_float64:
     81     case tok_kw_double:
     82         return fb_double;
     83     case tok_kw_float32:
     84     case tok_kw_float:
     85         return fb_float;
     86     default:
     87         return fb_missing_type;
     88     }
     89 }
     90 
     91 /*
     92  * The flatc compiler currently has a 256 limit.
     93  *
     94  * Some target C compilers might respect anything above
     95  * 16 and may reguire that PAD option of the C code generator.
     96  */
     97 static inline int is_valid_align(uint64_t align)
     98 {
     99     uint64_t n = 1;
    100     if (align == 0 || align > FLATCC_FORCE_ALIGN_MAX) {
    101         return 0;
    102     }
    103     while (n <= align) {
    104         if (n == align) {
    105             return 1;
    106         }
    107         n *= 2;
    108     }
    109     return 0;
    110 }
    111 
    112 static inline uint64_t fb_align(uint64_t size, uint64_t align)
    113 {
    114     assert(is_valid_align(align));
    115 
    116     return (size + align - 1) & ~(align - 1);
    117 }
    118 
    119 /*
    120  * The FNV-1a 32-bit little endian hash is a FlatBuffers standard for
    121  * transmission of type identifiers in a compact form, in particular as
    122  * alternative file identifiers. Note that if hash becomes 0, we map it
    123  * to hash("").
    124  */
    125 static inline void set_type_hash(fb_compound_type_t *ct)
    126 {
    127     fb_ref_t *name;
    128     fb_symbol_t *sym;
    129     uint32_t hash;
    130 
    131     hash = fb_hash_fnv1a_32_init();
    132     if (ct->scope) {
    133         for (name = ct->scope->name; name; name = name->link) {
    134             hash = fb_hash_fnv1a_32_append(hash, name->ident->text, (size_t)name->ident->len);
    135             hash = fb_hash_fnv1a_32_append(hash, ".", 1);
    136         }
    137     }
    138     sym = &ct->symbol;
    139     hash = fb_hash_fnv1a_32_append(hash, sym->ident->text, (size_t)sym->ident->len);
    140     if (hash == 0) {
    141         hash = fb_hash_fnv1a_32_init();
    142     }
    143     ct->type_hash = hash;
    144 }
    145 
    146 static inline fb_scope_t *fb_find_scope_by_string(fb_schema_t *S, const char *name, size_t len)
    147 {
    148     if (!S || !S->root_schema) {
    149         return 0;
    150     }
    151     if (len == 0) {
    152         /* Global scope. */
    153         name = 0;
    154     }
    155     return fb_scope_table_find(&S->root_schema->scope_index, name, len);
    156 }
    157 
    158 /* count = 0 indicates zero-terminated ref list, name = 0 indicates global scope. */
    159 static inline fb_scope_t *fb_find_scope_by_ref(fb_schema_t *S, const fb_ref_t *name, int count)
    160 {
    161     if (!S || !S->root_schema) {
    162         return 0;
    163     }
    164     return fb_scope_table_find(&S->root_schema->scope_index, name, (size_t)(-count));
    165 }
    166 
    167 static inline fb_symbol_t *define_fb_symbol(fb_symbol_table_t *si, fb_symbol_t *sym)
    168 {
    169     return fb_symbol_table_insert_item(si, sym, ht_keep);
    170 }
    171 
    172 static inline fb_symbol_t *find_fb_symbol_by_token(fb_symbol_table_t *si, fb_token_t *token)
    173 {
    174     return fb_symbol_table_find(si, token->text, (size_t)token->len);
    175 }
    176 
    177 static inline fb_name_t *define_fb_name(fb_name_table_t *ni, fb_name_t *name)
    178 {
    179     return fb_name_table_insert_item(ni, name, ht_keep);
    180 }
    181 
    182 static inline fb_name_t *find_fb_name_by_token(fb_name_table_t *ni, fb_token_t *token)
    183 {
    184     return fb_name_table_find(ni, token->text, (size_t)token->len);
    185 }
    186 
    187 /* Returns 1 if value exists, 0 otherwise, */
    188 static inline int add_to_value_set(fb_value_set_t *vs, fb_value_t *value)
    189 {
    190     return fb_value_set_insert_item(vs, value, ht_keep) != 0;
    191 }
    192 
    193 static inline int is_in_value_set(fb_value_set_t *vs, fb_value_t *value)
    194 {
    195     return 0 != fb_value_set_find_item(vs, value);
    196 }
    197 
    198 /*
    199  * An immediate parent scope does not necessarily exist and it might
    200  * appear in a later search, so we return the nearest existing parent
    201  * and do not cache the parent.
    202  */
    203 static inline fb_scope_t *find_parent_scope(fb_parser_t *P, fb_scope_t *scope)
    204 {
    205     fb_ref_t *p;
    206     int count;
    207     fb_scope_t *parent;
    208 
    209     parent = 0;
    210     count = 0;
    211     if (scope == 0) {
    212         return 0;
    213     }
    214     p = scope->name;
    215     while (p) {
    216         ++count;
    217         p = p->link;
    218     }
    219     if (count == 0) {
    220         return 0;
    221     }
    222     while (count-- > 1) {
    223         if ((parent = fb_find_scope_by_ref(&P->schema, scope->name, count))) {
    224             return parent;
    225         }
    226     }
    227     /* Root scope. */
    228     return fb_find_scope_by_ref(&P->schema, 0, 0);
    229 }
    230 
    231 static inline fb_symbol_t *lookup_string_reference(fb_parser_t *P, fb_scope_t *local, const char *s, size_t len)
    232 {
    233     fb_symbol_t *sym;
    234     fb_scope_t *scope;
    235     const char *name, *basename;
    236     size_t k;
    237 
    238     name = s;
    239     basename = s;
    240     k = len;
    241     while (k > 0) {
    242         if (s[--k] == '.') {
    243             basename = s + k + 1;
    244             --len;
    245             break;
    246         }
    247     }
    248     len -= k;
    249     if (local && k == 0) {
    250         do {
    251             if ((sym = fb_symbol_table_find(&local->symbol_index, basename, len))) {
    252                 if (get_compound_if_visible(&P->schema, sym)) {
    253                     return sym;
    254                 }
    255             }
    256             local = find_parent_scope(P, local);
    257         } while (local);
    258         return 0;
    259     }
    260     if (!(scope = fb_find_scope_by_string(&P->schema, name, k))) {
    261         return 0;
    262     }
    263     return fb_symbol_table_find(&scope->symbol_index, basename, len);
    264 }
    265 
    266 /*
    267  * First search the optional local scope, then the scope of the namespace prefix if any.
    268  * If `enumval` is non-zero, the last namepart is stored in that
    269  * pointer and the lookup stops before that part.
    270  *
    271  * If the reference is prefixed with a namespace then the scope is
    272  * looked up relative to root then the basename is searched in that
    273  * scope.
    274  *
    275  * If the refernce is not prefixed with a namespace then the name is
    276  * search in the local symbol table (which may be the root if null) and
    277  * if that fails, the nearest existing parent scope is used as the new
    278  * local scope and the process is repeated until local is root.
    279  *
    280  * This means that namespace prefixes cannot be relative to a parent
    281  * namespace or to the current scope, but simple names can be found in a
    282  * parent namespace.
    283  */
    284 static inline fb_symbol_t *lookup_reference(fb_parser_t *P, fb_scope_t *local, fb_ref_t *name, fb_ref_t **enumval)
    285 {
    286     fb_ref_t *basename, *last, *p;
    287     fb_scope_t *scope;
    288     fb_symbol_t *sym;
    289     int count;
    290 
    291     count = 0;
    292     scope = 0;
    293     p = name;
    294     last = 0;
    295     basename = 0;
    296     while (p) {
    297         basename = last;
    298         last = p;
    299         p = p->link;
    300         ++count;
    301     }
    302     if (enumval) {
    303         --count;
    304         *enumval = last;
    305     } else {
    306         basename = last;
    307     }
    308     if (!basename) {
    309         return 0;
    310     }
    311     if (local && count == 1) {
    312         do {
    313             if ((sym = find_fb_symbol_by_token(&local->symbol_index, basename->ident))) {
    314                 if (get_compound_if_visible(&P->schema, sym)) {
    315                     return sym;
    316                 }
    317             }
    318             local = find_parent_scope(P, local);
    319         } while (local);
    320         return 0;
    321     }
    322     /* Null name is valid in scope lookup, indicating global scope. */
    323     if (count == 1) {
    324         name = 0;
    325     }
    326     if (!(scope = fb_find_scope_by_ref(&P->schema, name, count - 1))) {
    327         return 0;
    328     }
    329     sym = find_fb_symbol_by_token(&scope->symbol_index, basename->ident);
    330     if (sym && get_compound_if_visible(&P->schema, sym)) {
    331         return sym;
    332     }
    333     return 0;
    334 }
    335 
    336 static inline fb_symbol_t *lookup_type_reference(fb_parser_t *P, fb_scope_t *local, fb_ref_t *name)
    337 {
    338     return lookup_reference(P, local, name, 0);
    339 }
    340 
    341 /*
    342  * `ct` is null when looking up names for scalar types and otherwise it is
    343  * the enum type being assigned. The provided reference may reference
    344  * an enum value in the `ct` type, or another enum if a scope/type is
    345  * given.
    346  */
    347 static inline int lookup_enum_name(fb_parser_t *P, fb_scope_t *local, fb_compound_type_t *ct, fb_ref_t *ref, fb_value_t *value)
    348 {
    349     fb_symbol_t *sym;
    350     fb_ref_t *enumval;
    351     fb_member_t *member;
    352 
    353     enumval = 0;
    354     assert(ref);
    355     assert(ct == 0 || ct->symbol.kind == fb_is_enum);
    356     sym = lookup_reference(P, local, ref, &enumval);
    357     if (sym && sym->kind == fb_is_enum) {
    358         ct = (fb_compound_type_t *)sym;
    359     } else if (ref->link) {
    360         /* If there was a scope / type prefix, it was not found, or it was not an enum type. */
    361         return -1;
    362     }
    363     if (!ct) {
    364         return -1;
    365     }
    366     sym = find_fb_symbol_by_token(&ct->index, enumval->ident);
    367     if (!sym) {
    368         return -1;
    369     }
    370     member = (fb_member_t *)sym;
    371     *value = member->value;
    372     return 0;
    373 }
    374 
    375 /* This is repeated for every include file, but this pose no problem. */
    376 static void install_known_attributes(fb_parser_t *P)
    377 {
    378     unsigned int i;
    379     fb_attribute_t *a;
    380 
    381     for (i = 0; i < KNOWN_ATTR_COUNT; ++i) {
    382         /* Don't put it in the parsed list, just the index. */
    383         a = new_elem(P, sizeof(*a));
    384         a->known = i;
    385         a->name.name.s.s = (char *)fb_known_attribute_names[i];
    386         a->name.name.s.len = (int)strlen(fb_known_attribute_names[i]);
    387         a->name.name.type = vt_string;
    388         a->name.link = 0;
    389         if ((a = (fb_attribute_t *)define_fb_name(&P->schema.root_schema->attribute_index, &a->name))) {
    390             /*
    391              * If the user alredy defined the attribute, keep that instead.
    392              * (Memory leak is ok here.)
    393              */
    394             a->known = i;
    395         }
    396     }
    397 }
    398 
    399 static void revert_order(fb_compound_type_t **list) {
    400     fb_compound_type_t *next, *prev = 0, *link = *list;
    401 
    402     while (link) {
    403         next = link->order;
    404         link->order = prev;
    405         prev = link;
    406         link = next;
    407     }
    408     *list = prev;
    409 }
    410 
    411 static inline unsigned short process_metadata(fb_parser_t *P, fb_metadata_t *m,
    412         uint16_t expect, fb_metadata_t *out[KNOWN_ATTR_COUNT])
    413 {
    414     uint16_t flags;
    415     unsigned int i, n = FLATCC_ATTR_MAX;
    416     int type;
    417     fb_attribute_t *a;
    418 
    419     memset(out, 0, sizeof(out[0]) * KNOWN_ATTR_COUNT);
    420     for (flags = 0; m && n; --n, m = m->link) {
    421         a = (fb_attribute_t *)find_fb_name_by_token(&P->schema.root_schema->attribute_index, m->ident);
    422         if (!a) {
    423             error_tok(P, m->ident, "unknown attribute not declared");
    424             continue;
    425         }
    426         if (!(i = a->known)) {
    427             continue;
    428         }
    429         if (!((1 << i) & expect)) {
    430             error_tok(P, m->ident, "known attribute not expected in this context");
    431             continue;
    432         }
    433         flags |= 1 << i;
    434         if (out[i]) {
    435             error_tok(P, m->ident, "known attribute listed multiple times");
    436             continue;
    437         }
    438         out[i] = m;
    439         type = fb_known_attribute_types[i];
    440         if (type == vt_missing && m->value.type != vt_missing) {
    441             error_tok(P, m->ident, "known attribute does not expect a value");
    442             continue;
    443         }
    444         if (type == vt_string && m->value.type != vt_string) {
    445             error_tok(P, m->ident, "known attribute expects a string");
    446             continue;
    447         }
    448         if (type == vt_uint && m->value.type != vt_uint) {
    449             error_tok(P, m->ident, "known attribute expects an unsigned integer");
    450             continue;
    451         }
    452         if (type == vt_int && m->value.type != vt_uint && m->value.type != vt_int) {
    453             error_tok(P, m->ident, "known attribute expects an integer");
    454             continue;
    455         }
    456         if (type == vt_bool && m->value.type != vt_bool) {
    457             error_tok(P, m->ident, "known attribute expects 'true' or 'false'");
    458             continue;
    459         }
    460     }
    461     if (m) {
    462         error_tok(P, m->ident, "too many attributes");
    463     }
    464     return flags;
    465 }
    466 
    467 /*
    468  * Recursive types are allowed, according to FlatBuffers Internals doc.,
    469  * but this cannot be possible for structs because they have no default
    470  * value or null option, and can only hold scalars and other structs, so
    471  * recursion would never terminate. Enums are simple types and cannot be
    472  * recursive either. Unions reference tables which may reference unions,
    473  * and recursion works well here. Tables allow any other table, union,
    474  * or scalar value to be optional or default, so recursion is possible.
    475  * In conclusion, Unions and Table members may reference all other
    476  * types, and self. Enums are trivially checked because the only allow
    477  * scalars, which leaves structs that can build illegal forms.
    478  *
    479  * Object instances cannot be recursive meaning the object graph is
    480  * always a tree, but this isn't really a concern for the schema
    481  * compiler, and for the builder it happens naturally as it only adds to
    482  * the buffer (though a compressor might reuse old data without
    483  * violating the tree?).
    484  *
    485  * Conclusion: check structs for circular references and allow
    486  * everything else to unfold, provided they otherwise pass type checks.
    487  *
    488  * Algorithm:
    489  *
    490  * Depth first search of the struct reference tree. We maintain flags to
    491  * find back-links. We prune sub-trees already fully analyzed by using
    492  * the closed flag. This operation is O(N) since each struct member is
    493  * visited once.
    494  *
    495  * Recursion is limited to prevent blowing the stack and to protect
    496  * against abuse.
    497  */
    498 static int analyze_struct(fb_parser_t *P, fb_compound_type_t *ct)
    499 {
    500     fb_symbol_t *sym;
    501     fb_compound_type_t *type;
    502     fb_member_t *member;
    503     int ret = 0;
    504     uint64_t size;
    505     uint16_t align;
    506     fb_token_t *t;
    507 
    508     assert(ct->symbol.kind == fb_is_struct);
    509 
    510     assert(!(ct->symbol.flags & fb_circular_open));
    511     if (ct->symbol.flags & fb_circular_closed) {
    512         return 0;
    513     }
    514     assert(!ct->order);
    515     ct->symbol.flags |= fb_circular_open;
    516     align = 1;
    517     for (sym = ct->members; sym; sym = sym->link) {
    518         type = 0;
    519         if (P->nesting_level >= FLATCC_NESTING_MAX) {
    520             error(P, "maximum allowed nesting level exceeded while processing struct hierarchy");
    521             return -1;
    522         }
    523         member = (fb_member_t *)sym;
    524         switch (member->type.type) {
    525         case vt_fixed_array_type:
    526         case vt_scalar_type:
    527             t = member->type.t;
    528             member->type.st = map_scalar_token_type(t);
    529             size = sizeof_scalar_type(member->type.st);
    530             if (size < 1) {
    531                 error_sym_tok(P, sym, "unexpected type", t);
    532                 return -1;
    533             }
    534             member->align = (uint16_t)size;
    535             member->size = size * member->type.len;
    536             break;
    537         case vt_fixed_array_compound_type_ref:
    538         case vt_compound_type_ref:
    539             /* Enums might not be valid, but then it would be detected earlier. */
    540             if (member->type.ct->symbol.kind == fb_is_enum) {
    541                 type = member->type.ct;
    542                 size = type->size;
    543                 member->align = (uint16_t)size;
    544                 member->size = member->type.len * type->size;
    545                 break;
    546             } else if (member->type.ct->symbol.kind == fb_is_struct) {
    547                 type = member->type.ct;
    548                 if (type->symbol.flags & fb_circular_open) {
    549                     error_sym_2(P, sym, "circular reference to struct at", &type->symbol);
    550                     return -1;
    551                 }
    552                 if (!(type->symbol.flags & fb_circular_closed)) {
    553                     if (P->opts.hide_later_struct) {
    554                         error_sym_2(P, sym, "dependency on later defined struct not permitted with current settings", &type->symbol);
    555                     }
    556                     ++P->nesting_level;
    557                     ret = analyze_struct(P, type);
    558                     --P->nesting_level;
    559                     if (ret) {
    560                         return ret;
    561                     }
    562                 }
    563                 member->align = type->align;
    564                 member->size = member->type.len * type->size;
    565                 break;
    566             } else {
    567                 error_sym(P, sym, "unexpected compound type for field");
    568                 return -1;
    569             }
    570             break;
    571         case vt_invalid:
    572             /* Old error. */
    573             return -1;
    574         default:
    575             error_sym(P, sym, "unexpected type");
    576             return -1;
    577         }
    578         member->offset = fb_align(ct->size, member->align);
    579         if (member->offset < ct->size || member->offset + member->size < member->offset) {
    580             error_sym(P, sym, "struct size overflow");
    581             return -1;
    582         }
    583         size = member->offset + member->size;
    584         if (size < ct->size || size > FLATCC_STRUCT_MAX_SIZE) {
    585             error_sym(P, sym, "struct field overflows maximum allowed struct size");
    586         };
    587         ct->size = size;
    588         /*
    589          * FB spec is not very clear on this - but experimentally a
    590          * force aligned member struct will force that alignment upon a
    591          * containing struct if the alignment would otherwise be
    592          * smaller. In otherwise, a struct is aligned to the alignment
    593          * of the largest member, not just the largest scalar member
    594          * (directly or indirectly).
    595          */
    596         if (align < member->align) {
    597             align = member->align;
    598         }
    599     }
    600     if (ct->align > 0) {
    601         if (align > ct->align) {
    602             error_sym(P, &ct->symbol, "'force_align' cannot be smaller than natural alignment for");
    603             ct->align = align;
    604         }
    605     } else {
    606         ct->align = align;
    607     }
    608     /* Add trailing padding if necessary. */
    609     ct->size = fb_align(ct->size, ct->align);
    610 
    611     if (ct->size == 0) {
    612         error_sym(P, &ct->symbol, "struct cannot be empty");
    613         return -1;
    614     }
    615 
    616     ct->symbol.flags |= fb_circular_closed;
    617     ct->symbol.flags &= (uint16_t)~fb_circular_open;
    618     ct->order = P->schema.ordered_structs;
    619     P->schema.ordered_structs = ct;
    620     return ret;
    621 }
    622 
    623 static int define_nested_table(fb_parser_t *P, fb_scope_t *local, fb_member_t *member, fb_metadata_t *m)
    624 {
    625     fb_symbol_t *type_sym;
    626 
    627     if (member->type.type != vt_vector_type || member->type.st != fb_ubyte) {
    628         error_tok(P, m->ident, "'nested_flatbuffer' attribute requires a [ubyte] vector type");
    629         return -1;
    630     }
    631     if (m->value.type != vt_string) {
    632         /* All known attributes get automatically type checked, so just ignore. */
    633         return -1;
    634     }
    635     type_sym = lookup_string_reference(P, local, m->value.s.s, (size_t)m->value.s.len);
    636     if (!type_sym) {
    637         error_tok_as_string(P, m->ident, "nested reference not found", m->value.s.s, (size_t)m->value.s.len);
    638         return -1;
    639     }
    640     if (type_sym->kind != fb_is_table) {
    641         if (!P->opts.allow_struct_root) {
    642             error_tok_2(P, m->ident, "nested reference does not refer to a table", type_sym->ident);
    643             return -1;
    644         }
    645         if (type_sym->kind != fb_is_struct) {
    646             error_tok_2(P, m->ident, "nested reference does not refer to a table or a struct", type_sym->ident);
    647             return -1;
    648         }
    649     }
    650     member->nest = (fb_compound_type_t *)type_sym;
    651     return 0;
    652 }
    653 
    654 static int process_struct(fb_parser_t *P, fb_compound_type_t *ct)
    655 {
    656     fb_symbol_t *sym, *old, *type_sym;
    657     fb_member_t *member;
    658     fb_metadata_t *knowns[KNOWN_ATTR_COUNT], *m;
    659     uint16_t allow_flags;
    660     int key_count = 0, primary_count = 0, key_ok = 0;
    661 
    662     if (ct->type.type) {
    663         error_sym(P, &ct->symbol, "internal error: struct cannot have a type");
    664         return -1;
    665     }
    666     ct->metadata_flags = process_metadata(P, ct->metadata, fb_f_force_align, knowns);
    667     if ((m = knowns[fb_attr_force_align])) {
    668         if (!is_valid_align(m->value.u)) {
    669             error_sym(P, &ct->symbol, "'force_align' exceeds maximum permitted alignment or is not a power of 2");
    670         } else {
    671             /* This may still fail on natural alignment size. */
    672             ct->align = (uint16_t)m->value.u;
    673         }
    674     }
    675     for (sym = ct->members; sym; sym = sym->link) {
    676         if ((old = define_fb_symbol(&ct->index, sym))) {
    677             error_sym_2(P, sym, "struct field already defined here", old);
    678             continue;
    679         }
    680         if (sym->kind != fb_is_member) {
    681             error_sym(P, sym, "internal error: field type expected");
    682             return -1;
    683         }
    684         key_ok = 1;
    685         member = (fb_member_t *)sym;
    686         allow_flags = 0;
    687         /* Notice the difference between fb_f_ and fb_attr_ (flag vs index). */
    688         if (P->opts.allow_struct_field_key) {
    689             allow_flags |= fb_f_key;
    690             if (P->opts.allow_primary_key) {
    691                 allow_flags |= fb_f_primary_key;
    692             }
    693         }
    694         if (P->opts.allow_struct_field_deprecate) {
    695             allow_flags |= fb_f_deprecated;
    696         }
    697         member->metadata_flags = process_metadata(P, member->metadata, allow_flags, knowns);
    698         switch (member->type.type) {
    699         case vt_fixed_array_type_ref:
    700             key_ok = 0;
    701             goto lbl_type_ref;
    702         case vt_type_ref:
    703 lbl_type_ref:
    704             type_sym = lookup_type_reference(P, ct->scope, member->type.ref);
    705             if (!type_sym) {
    706                 error_ref_sym(P, member->type.ref, "unknown type reference used with struct field", sym);
    707                 member->type.type = vt_invalid;
    708                 continue;
    709             }
    710             member->type.ct = (fb_compound_type_t*)type_sym;
    711             member->type.type = member->type.type == vt_fixed_array_type_ref ?
    712                 vt_fixed_array_compound_type_ref : vt_compound_type_ref;
    713             if (type_sym->kind != fb_is_struct) {
    714                 if (P->opts.allow_enum_struct_field) {
    715                     if (type_sym->kind != fb_is_enum) {
    716                         error_sym_2(P, sym, "struct fields can only be scalars, structs, and enums, or arrays of these, but has type", type_sym);
    717                         member->type.type = vt_invalid;
    718                         return -1;
    719                     }
    720                     if (!P->opts.allow_enum_key) {
    721                         key_ok = 0;
    722                         break;
    723                     }
    724                 } else {
    725                     error_sym_2(P, sym, "struct fields can only be scalars and structs, or arrays of these, but has type", type_sym);
    726                     member->type.type = vt_invalid;
    727                     return -1;
    728                 }
    729             } else {
    730                 key_ok = 0;
    731             }
    732             break;
    733         case vt_fixed_array_string_type:
    734             error_sym(P, sym, "fixed length arrays cannot have string elements");
    735             member->type.type = vt_invalid;
    736             return -1;
    737         case vt_fixed_array_type:
    738             key_ok = 0;
    739             break;
    740         case vt_scalar_type:
    741             break;
    742         default:
    743             error_sym(P, sym, "struct member member can only be of struct scalar, or fixed length scalar array type");
    744             return -1;
    745         }
    746         if (!key_ok) {
    747             if (member->metadata_flags & fb_f_key) {
    748                 member->type.type = vt_invalid;
    749                 error_sym(P, sym, "key attribute now allowed for this kind of field");
    750                 return -1;
    751             }
    752             if (member->metadata_flags & fb_f_primary_key) {
    753                 member->type.type = vt_invalid;
    754                 error_sym(P, sym, "primary_key attribute now allowed for this kind of field");
    755                 return -1;
    756             }
    757         }
    758         if (member->metadata_flags & fb_f_deprecated) {
    759             if (member->metadata_flags & fb_f_key) {
    760                 error_sym(P, sym, "key attribute not allowed for deprecated struct member");
    761                 return -1;
    762             } else if (member->metadata_flags & fb_f_primary_key) {
    763                 error_sym(P, sym, "primary_key attribute not allowed for deprecated struct member");
    764                 return -1;
    765             }
    766         }
    767         if (member->metadata_flags & fb_f_key) {
    768             if (member->metadata_flags & fb_f_primary_key) {
    769                 error_sym(P, sym, "primary_key attribute conflicts with key attribute");
    770                 member->type.type = vt_invalid;
    771                 return -1;
    772             }
    773             key_count++;
    774             if (!ct->primary_key) {
    775                 /* First key is primary key if no primary key is given explicitly. */
    776                 ct->primary_key = member;
    777             }
    778         } else if (member->metadata_flags & fb_f_primary_key) {
    779             if (primary_count++) {
    780                 error_sym(P, sym, "at most one struct member can have a primary_key attribute");
    781                 member->type.type = vt_invalid;
    782                 return -1;
    783             }
    784             key_count++;
    785             /* Allow backends to treat primary key as an ordinary key. */
    786             member->metadata_flags |= fb_f_key;
    787             ct->primary_key = member;
    788         }
    789         if (member->value.type) {
    790             error_sym(P, sym, "struct member member cannot have a default value");
    791             continue;
    792         }
    793     }
    794     if (key_count) {
    795         ct->symbol.flags |= fb_indexed;
    796     }
    797     /* Set primary key flag for backends even if chosen by default. */
    798     if (ct->primary_key) {
    799         ct->primary_key->metadata_flags |= fb_f_primary_key;
    800     }
    801     if (key_count > 1 && !P->opts.allow_multiple_key_fields) {
    802         error_sym(P, &ct->symbol, "table has multiple key fields, but at most one is permitted");
    803         return -1;
    804     }
    805     return 0;
    806 }
    807 
    808 static fb_member_t *original_order_members(fb_parser_t *P, fb_member_t *next)
    809 {
    810     fb_member_t *head = 0;
    811     fb_member_t **tail = &head;
    812 
    813     /* Not used for now, but in case we need error messages etc. */
    814     (void)P;
    815 
    816     while (next) {
    817         *tail = next;
    818         tail = &next->order;
    819         next = (fb_member_t *)(((fb_symbol_t *)next)->link);
    820     }
    821     *tail = 0;
    822     return head;
    823 }
    824 
    825 /*
    826  * Alignment of table offset fields are generally not stored, and
    827  * vectors store the element alignment for scalar types, so we
    828  * detect alignment based on type also. Unions are tricky since they
    829  * use a single byte type followed by an offset, but it is impractical
    830  * to store these separately so we sort by the type field.
    831  */
    832 static fb_member_t *align_order_members(fb_parser_t *P, fb_member_t *members)
    833 {
    834     uint16_t i, j, k;
    835     fb_member_t *heads[9] = {0};
    836     fb_member_t **tails[9] = {0};
    837     fb_member_t *next = members;
    838 
    839     while (next) {
    840         k = next->align;
    841         switch (next->type.type) {
    842         case vt_compound_type_ref:
    843             switch (next->type.ct->symbol.kind) {
    844             case fb_is_struct:
    845             case fb_is_enum:
    846                 k = next->type.ct->align;
    847                 break;
    848             case fb_is_union:
    849                 /*
    850                  * Unions align to their offsets because the type can
    851                  * always be added last in a second pass since it is 1
    852                  * byte.
    853                  */
    854                 k = (uint16_t)P->opts.offset_size;
    855                 break;
    856             default:
    857                 k = (uint16_t)P->opts.offset_size;
    858                 break;
    859             }
    860             break;
    861         case vt_vector_compound_type_ref:
    862         case vt_string_type:
    863         case vt_vector_type:
    864         case vt_vector_string_type:
    865             k = (uint16_t)P->opts.offset_size;
    866             break;
    867         case vt_invalid:
    868             /* Just to have some sane behavior. */
    869             return original_order_members(P, members);
    870         default:
    871             k = next->align;
    872             break;
    873         }
    874         assert(k > 0);
    875         i = 0;
    876         while (k >>= 1) {
    877             ++i;
    878         }
    879         /* Normally the largest alignment is 256, but otherwise we group them together. */
    880         if (i > 7) {
    881             i = 7;
    882         }
    883         if (!heads[i]) {
    884             heads[i] = next;
    885         } else {
    886             *tails[i] = next;
    887         }
    888         tails[i] = &next->order;
    889         next = (fb_member_t *)(((fb_symbol_t *)next)->link);
    890     }
    891     i = j = 8;
    892     tails[8] = &heads[8];
    893     while (j) {
    894         while (i && !heads[--i]) {
    895         }
    896         *tails[j] = heads[i];
    897         j = i;
    898     }
    899     return heads[8];
    900 }
    901 
    902 /* Temporary markers only used during assignment of field identifiers. */
    903 enum { unused_field = 0, normal_field, type_field };
    904 
    905 static int process_table(fb_parser_t *P, fb_compound_type_t *ct)
    906 {
    907     char msg_buf [100];
    908     fb_symbol_t *sym, *old, *type_sym;
    909     fb_member_t *member;
    910     fb_metadata_t *knowns[KNOWN_ATTR_COUNT], *m;
    911     int ret = 0;
    912     uint64_t count = 0;
    913     int need_id = 0, id_failed = 0;
    914     uint64_t max_id = 0;
    915     int key_ok, key_count = 0, primary_count = 0;
    916     int is_union_vector, is_vector;
    917     uint64_t i, j;
    918     int max_id_errors = 10;
    919     int allow_flags = 0;
    920 
    921     /*
    922      * This just tracks the presence of a `normal_field` or a hidden
    923      * `type_field`.  The size is litmited to 16-bit unsigned offsets.
    924      * It is only of relevance for ithe optional `id` table field
    925      * attribute.
    926      */
    927     uint8_t *field_marker = 0;
    928     fb_symbol_t **field_index = 0;
    929 
    930     assert(ct->symbol.kind == fb_is_table);
    931     assert(!ct->type.type);
    932 
    933     ct->metadata_flags = process_metadata(P, ct->metadata, fb_f_original_order, knowns);
    934     /*
    935      * `original_order` now lives as a flag, we need not consider it
    936      * further until code generation.
    937      */
    938     for (sym = ct->members; sym; sym = sym->link) {
    939         key_ok = 0;
    940         type_sym = 0;
    941         is_vector = 0;
    942         is_union_vector = 0;
    943         if ((old = define_fb_symbol(&ct->index, sym))) {
    944             error_sym_2(P, sym, "table member already defined here", old);
    945             continue;
    946         }
    947         if (sym->kind != fb_is_member) {
    948             error_sym(P, sym, "internal error: member type expected");
    949             return -1;
    950         }
    951         member = (fb_member_t *)sym;
    952         if (member->type.type == vt_invalid) {
    953             continue;
    954         }
    955         if (member->type.type == vt_scalar_type || member->type.type == vt_vector_type) {
    956             member->type.st = map_scalar_token_type(member->type.t);
    957         }
    958         allow_flags =
    959                 fb_f_id | fb_f_nested_flatbuffer | fb_f_deprecated | fb_f_key |
    960                 fb_f_required | fb_f_hash | fb_f_base64 | fb_f_base64url | fb_f_sorted;
    961 
    962         if (P->opts.allow_primary_key) {
    963             allow_flags |= fb_f_primary_key;
    964         }
    965         member->metadata_flags = process_metadata(P, member->metadata, (uint16_t)allow_flags, knowns);
    966         if ((m = knowns[fb_attr_nested_flatbuffer])) {
    967             define_nested_table(P, ct->scope, member, m);
    968         }
    969         /* Note: we allow base64 and base64url with nested attribute. */
    970         if ((member->metadata_flags & fb_f_base64) &&
    971                 (member->type.type != vt_vector_type || member->type.st != fb_ubyte)) {
    972             error_sym(P, sym, "'base64' attribute is only allowed on vectors of type ubyte");
    973         }
    974         if ((member->metadata_flags & fb_f_base64url) &&
    975                 (member->type.type != vt_vector_type || member->type.st != fb_ubyte)) {
    976             error_sym(P, sym, "'base64url' attribute is only allowed on vectors of type ubyte");
    977         }
    978         if ((member->metadata_flags & (fb_f_base64 | fb_f_base64url)) ==
    979                 (fb_f_base64 | fb_f_base64url)) {
    980             error_sym(P, sym, "'base64' and 'base64url' attributes cannot both be set");
    981         }
    982         m = knowns[fb_attr_id];
    983         if (m && count == 0) {
    984             need_id = 1;
    985             field_marker = P->tmp_field_marker;
    986             memset(field_marker, 0, (size_t)P->opts.vt_max_count);
    987         }
    988         if (!id_failed) {
    989             if (count >= P->opts.vt_max_count) {
    990                 error_sym(P, sym, "too many fields for vtable size");
    991                 id_failed = 1;
    992             } else if (!need_id) {
    993                 member->id = (unsigned short)count;
    994             }
    995             ++count;
    996         }
    997         switch (member->type.type) {
    998         case vt_scalar_type:
    999             if (member->value.type == vt_null) {
   1000                 member->value.type = vt_uint;
   1001                 member->value.u = 0;
   1002                 member->flags |= fb_fm_optional;
   1003             }
   1004             if (member->metadata_flags & fb_f_required) {
   1005                 if (member->flags & fb_fm_optional) {
   1006                     error_sym(P, sym, "'required' attribute is incompatible with optional table field (= null)");
   1007                 } else {
   1008                     error_sym(P, sym, "'required' attribute is redundant on scalar table field");
   1009                 }
   1010             }
   1011             key_ok = 1;
   1012             if (member->value.type == vt_name_ref) {
   1013                 if (lookup_enum_name(P, ct->scope, 0, member->value.ref, &member->value)) {
   1014                     error_ref_sym(P, member->value.ref, "unknown name used as initializer for scalar field", sym);
   1015                     member->type.type = vt_invalid;
   1016                     continue;
   1017                 }
   1018             }
   1019             if (!member->value.type) {
   1020                 /*
   1021                  * Simplifying by ensuring we always have a default
   1022                  * value where an initializer is possible (also goes for enum).
   1023                  */
   1024                 member->value.type = vt_uint;
   1025                 member->value.u = 0;
   1026             }
   1027             if (fb_coerce_scalar_type(P, sym, member->type.st, &member->value)) {
   1028                 member->type.type = vt_invalid;
   1029                 continue;
   1030             }
   1031             member->size = sizeof_scalar_type(member->type.st);
   1032             member->align = (uint16_t)member->size;
   1033             break;
   1034         case vt_vector_type:
   1035             is_vector = 1;
   1036             member->size = sizeof_scalar_type(member->type.st);
   1037             member->align =(uint16_t) member->size;
   1038             if (member->value.type) {
   1039                 error_sym(P, sym, "scalar vectors cannot have an initializer");
   1040                 member->type.type = vt_invalid;
   1041                 continue;
   1042             }
   1043             break;
   1044         case vt_fixed_array_type_ref:
   1045         case vt_fixed_array_string_type:
   1046         case vt_fixed_array_type:
   1047             error_sym(P, sym, "fixed length arrays can only be used with structs");
   1048             member->type.type = vt_invalid;
   1049             return -1;
   1050         case vt_string_type:
   1051             /* `size` or `align` not defined - these are implicit uoffset types. */
   1052             key_ok = P->opts.allow_string_key;
   1053             if (member->value.type) {
   1054                 error_sym(P, sym, "strings cannot have an initializer");
   1055                 member->type.type = vt_invalid;
   1056                 continue;
   1057             }
   1058             break;
   1059         case vt_vector_string_type:
   1060             is_vector = 1;
   1061             /* `size` or `align` not defined - these are implicit uoffset types. */
   1062             if (member->value.type) {
   1063                 error_sym(P, sym, "string vectors cannot have an initializer");
   1064                 member->type.type = vt_invalid;
   1065                 continue;
   1066             }
   1067             break;
   1068         case vt_type_ref:
   1069             type_sym = lookup_type_reference(P, ct->scope, member->type.ref);
   1070             if (!type_sym) {
   1071                 error_ref_sym(P, member->type.ref, "unknown type reference used with table field", sym);
   1072                 member->type.type = vt_invalid;
   1073                 /* We cannot count id's without knowing if it is a union. */
   1074                 id_failed = 1;
   1075                 continue;
   1076             }
   1077             switch (type_sym->kind) {
   1078             case fb_is_enum:
   1079                 /*
   1080                  * Note the enums without a 0 element requires an
   1081                  * initializer in the schema, but that cannot happen
   1082                  * with a null value, so in this case the value is force
   1083                  * to 0. This is only relevant when using the `_get()`
   1084                  * accessor instead of the `_option()`.
   1085                  */
   1086                 if (member->value.type == vt_null) {
   1087                     member->value.type = vt_uint;
   1088                     member->value.u = 0;
   1089                     member->flags |= fb_fm_optional;
   1090                 }
   1091                 if (member->metadata_flags & fb_f_required) {
   1092                     if (member->flags & fb_fm_optional) {
   1093                         error_sym(P, sym, "'required' attribute is incompatible with optional enum table field (= null)");
   1094                     } else {
   1095                         error_sym(P, sym, "'required' attribute is redundant on enum table field");
   1096                     }
   1097                 }
   1098                 key_ok = P->opts.allow_enum_key;
   1099                 break;
   1100             case fb_is_table:
   1101             case fb_is_struct:
   1102             case fb_is_union:
   1103                 break;
   1104             case fb_is_rpc_service:
   1105                 error_sym_2(P, sym, "rpc service is not a valid table field type", type_sym);
   1106                 member->type.type = vt_invalid;
   1107                 continue;
   1108             default:
   1109                 error_sym_2(P, sym, "internal error: unexpected field type", type_sym);
   1110                 member->type.type = vt_invalid;
   1111                 continue;
   1112             }
   1113             member->type.type = vt_compound_type_ref;
   1114             member->type.ct = (fb_compound_type_t*)type_sym;
   1115             /*
   1116              * Note: this information transfer won't always work because
   1117              * structs do not know their full size at this point so
   1118              * codegen must use the member->type.ct values.
   1119              */
   1120             member->size = member->type.ct->size;
   1121             member->align = member->type.ct->align;
   1122 
   1123             if (type_sym->kind == fb_is_union && !id_failed) {
   1124                 /* Hidden union type field. */
   1125                 if (!need_id) {
   1126                     member->id = (unsigned short)count;
   1127                 }
   1128                 ++count;
   1129             }
   1130             if (member->value.type) {
   1131                 if (type_sym->kind != fb_is_enum) {
   1132                     error_sym(P, sym, "non-scalar field cannot have an initializer");
   1133                     member->type.type = vt_invalid;
   1134                     continue;
   1135                 }
   1136                 if (member->value.type == vt_name_ref) {
   1137                     if (lookup_enum_name(P, ct->scope, member->type.ct, member->value.ref, &member->value)) {
   1138                         error_ref_sym(P, member->value.ref, "unknown name used as initializer for enum field", sym);
   1139                         member->type.type = vt_invalid;
   1140                         continue;
   1141                     }
   1142                 } else {
   1143                     if (fb_coerce_scalar_type(P, sym, ((fb_compound_type_t *)type_sym)->type.st, &member->value)) {
   1144                         member->type.type = vt_invalid;
   1145                         continue;
   1146                     }
   1147                     /* Bitflags can have complex combinations of values, and do not nativele have a 0 value. */
   1148                     if (P->opts.strict_enum_init && !(member->type.ct->metadata_flags & fb_f_bit_flags)
   1149                             && !(member->flags & fb_fm_optional)) {
   1150                         if (!is_in_value_set(&member->type.ct->value_set, &member->value)) {
   1151                             error_sym(P, sym, "initializer does not match a defined enum value");
   1152                             member->type.type = vt_invalid;
   1153                             continue;
   1154                         }
   1155                     }
   1156                 }
   1157             } else {
   1158                 /* Enum is the only type that cannot always default to 0. */
   1159                 if (type_sym->kind == fb_is_enum) {
   1160                     member->value.type = vt_uint;
   1161                     member->value.u = 0;
   1162                     if (fb_coerce_scalar_type(P, type_sym, ((fb_compound_type_t *)type_sym)->type.st, &member->value)) {
   1163                         member->type.type = vt_invalid;
   1164                         continue;
   1165                     }
   1166                     if (P->opts.strict_enum_init) {
   1167                         /* TODO: consider if this error is necessary for bit_flags - flatc 2.0.0 errors on this. */
   1168                         if (!is_in_value_set(&member->type.ct->value_set, &member->value)) {
   1169                             error_sym_2(P, sym,
   1170                                     "enum type requires an explicit initializer because it has no 0 value", type_sym);
   1171                             member->type.type = vt_invalid;
   1172                             continue;
   1173                         }
   1174                     }
   1175                 }
   1176             }
   1177             break;
   1178         case vt_vector_type_ref:
   1179             type_sym = lookup_type_reference(P, ct->scope, member->type.ref);
   1180             if (!type_sym) {
   1181                 error_ref_sym(P, member->type.ref, "unknown vector type reference used with table field", sym);
   1182                 member->type.type = vt_invalid;
   1183                 continue;
   1184             }
   1185             switch (type_sym->kind) {
   1186             case fb_is_enum:
   1187             case fb_is_table:
   1188             case fb_is_struct:
   1189             case fb_is_union:
   1190                 break;
   1191             default:
   1192                 /* Vectors of strings are handled separately but this is irrelevant to the user. */
   1193                 error_sym_tok(P, sym, "vectors can only hold scalars, structs, enums, strings, tables, and unions", member->type.t);
   1194                 member->type.type = vt_invalid;
   1195                 continue;
   1196             }
   1197             is_vector = 1;
   1198             is_union_vector = type_sym->kind == fb_is_union;
   1199             if (member->value.type) {
   1200                 error_sym(P, sym, "non-scalar field cannot have an initializer");
   1201                 member->type.type = vt_invalid;
   1202                 continue;
   1203             }
   1204             /* Size of the vector element, not of the vector itself. */
   1205             member->type.type = vt_vector_compound_type_ref;
   1206             member->type.ct = (fb_compound_type_t*)type_sym;
   1207             member->size = member->type.ct->size;
   1208             member->align = member->type.ct->align;
   1209             if (type_sym->kind == fb_is_union && !id_failed) {
   1210                 /* Hidden union type field. */
   1211                 if (!need_id) {
   1212                     member->id = (unsigned short)count;
   1213                 }
   1214                 ++count;
   1215             }
   1216             break;
   1217         default:
   1218             error_sym(P, sym, "unexpected table field type encountered");
   1219             member->type.type = vt_invalid;
   1220             continue;
   1221         }
   1222         if (!id_failed) {
   1223             if (m && !need_id && !id_failed) {
   1224                 error_tok(P, m->ident, "unexpected id attribute, must be used on all fields, or none");
   1225                 id_failed = 1;
   1226             } else if (!m && need_id && !id_failed) {
   1227                 error_sym(P, sym, "id attribute missing, must be used on all fields, or none");
   1228                 id_failed = 1;
   1229             } else if (m) {
   1230                 if (m->value.type == vt_uint) {
   1231                     if (m->value.u >= P->opts.vt_max_count) {
   1232                         error_sym(P, sym, "id too large to fit in vtable");
   1233                         id_failed = 1;
   1234                     } else {
   1235                         member->id = (unsigned short)m->value.u;
   1236                         if (member->id > max_id) {
   1237                             max_id = member->id;
   1238                         }
   1239                     }
   1240                 } else if (m->value.type == vt_int) {
   1241                     error_tok(P, m->ident, "id attribute cannot be negative");
   1242                     id_failed = 1;
   1243                 } else {
   1244                     error_tok(P, m->ident, "unexpecte id attribute type");
   1245                     id_failed = 1;
   1246                 }
   1247             }
   1248         }
   1249         if (need_id && !id_failed) {
   1250             if (field_marker[member->id] == type_field) {
   1251                 error_tok(P, m->ident, "id attribute value conflicts with a hidden type field");
   1252                 id_failed = normal_field;
   1253             } else if (field_marker[member->id]) {
   1254                 error_tok(P, m->ident, "id attribute value conflicts with another field");
   1255             } else {
   1256                 field_marker[member->id] = normal_field;
   1257             }
   1258             if (!id_failed && type_sym && type_sym->kind == fb_is_union) {
   1259                 if (member->id <= 1) {
   1260                     error_tok(P, m->ident, is_union_vector ?
   1261                             "id attribute value should be larger to accommodate hidden union vector type field" :
   1262                             "id attribute value should be larger to accommodate hidden union type field");
   1263                     id_failed = 1;
   1264                 } else if (field_marker[member->id - 1] == type_field) {
   1265                     error_tok(P, m->ident, is_union_vector ?
   1266                             "hidden union vector type field below attribute id value conflicts with another hidden type field" :
   1267                             "hidden union type field below attribute id value conflicts with another hidden type field");
   1268                     id_failed = 1;
   1269                 } else if (field_marker[member->id - 1]) {
   1270                     error_tok(P, m->ident, is_union_vector ?
   1271                             "hidden union vector type field below attribute id value conflicts with another field" :
   1272                             "hidden union type field below attribute id value conflicts with another field");
   1273                     id_failed = 1;
   1274                 } else {
   1275                     field_marker[member->id - 1] = type_field;
   1276                 }
   1277             }
   1278         }
   1279         if (member->metadata_flags & fb_f_deprecated) {
   1280             if (member->metadata_flags & fb_f_key) {
   1281                 error_sym(P, sym, "key attribute not allowed for deprecated field");
   1282                 return -1;
   1283             } else if (member->metadata_flags & fb_f_primary_key) {
   1284                 error_sym(P, sym, "primary_key attribute not allowed for deprecated field");
   1285                 return -1;
   1286             }
   1287         }
   1288         if (member->metadata_flags & fb_f_key) {
   1289             ++key_count;
   1290             if (!key_ok) {
   1291                 error_sym(P, sym, "key attribute not allowed for this kind of field");
   1292                 member->type.type = vt_invalid;
   1293             } else if (member->metadata_flags & fb_f_primary_key) {
   1294                 error_sym(P, sym, "primary_key attribute conflicts with key attribute");
   1295                 member->type.type = vt_invalid;
   1296             } else if (!ct->primary_key ||
   1297                     (primary_count == 0 && ct->primary_key->id > member->id)) {
   1298                 /*
   1299                  * Set key field with lowest id as default primary key
   1300                  * unless a key field also has a primary attribute.
   1301                  */
   1302                 ct->primary_key = member;
   1303             }
   1304         } else if (member->metadata_flags & fb_f_primary_key) {
   1305             if (member->metadata_flags & fb_f_primary_key) {
   1306                 if (primary_count++) {
   1307                     error_sym(P, sym, "at most one field can have a primary_key attribute");
   1308                     member->type.type = vt_invalid;
   1309                     continue;
   1310                 } else {
   1311                     ct->primary_key = member;
   1312                 }
   1313             }
   1314             key_count++;
   1315             /* Allow backends to treat primary key as an ordinary key. */
   1316             member->metadata_flags |= fb_f_key;
   1317         }
   1318         if (member->metadata_flags & fb_f_sorted) {
   1319             if (is_union_vector) {
   1320                 error_sym(P, sym, "sorted attribute not allowed for union vectors");
   1321                 member->type.type = vt_invalid;
   1322                 return -1;
   1323             } else if (!is_vector) {
   1324                 error_sym(P, sym, "sorted attribute only allowed for vectors");
   1325                 member->type.type = vt_invalid;
   1326                 return -1;
   1327             }
   1328             /*
   1329              * A subsequent call to validate_table_attr will verify that a
   1330              * sorted vector of tables or structs have a defined field
   1331              * key. This cannot be done before all types have been
   1332              * processed.
   1333              */
   1334         }
   1335     }
   1336     if (!id_failed) {
   1337         ct->count = count;
   1338     }
   1339     if (!id_failed && need_id) {
   1340         if (count && max_id >= count) {
   1341             for (i = 0; i < max_id; ++i) {
   1342                 if (field_marker[i] == 0) {
   1343                     if (!max_id_errors--) {
   1344                         error_sym(P, &ct->symbol, "... more id's missing");
   1345                         break;
   1346                     }
   1347                     sprintf(msg_buf,  "id range not consequtive from 0, missing id: %"PRIu64"", i);
   1348                     error_sym(P, &ct->symbol, msg_buf);
   1349                 }
   1350             }
   1351             id_failed = 1;
   1352         }
   1353     }
   1354     /* Order in which data is ordered in binary buffer. */
   1355     if (ct->metadata_flags & fb_f_original_order) {
   1356         ct->ordered_members = original_order_members(P, (fb_member_t *)ct->members);
   1357     } else {
   1358         /* Size efficient ordering. */
   1359         ct->ordered_members = align_order_members(P, (fb_member_t *)ct->members);
   1360     }
   1361     if (!id_failed && need_id && count > 0) {
   1362         field_index = P->tmp_field_index;
   1363         memset(field_index, 0, sizeof(field_index[0]) * (size_t)P->opts.vt_max_count);
   1364         /*
   1365          * Reorder by id so table constructor arguments in code
   1366          * generators always use same ordering across versions.
   1367          */
   1368         for (sym = ct->members; sym; sym = sym->link) {
   1369             member = (fb_member_t *)sym;
   1370             field_index[member->id] = sym;
   1371         }
   1372         j = 0;
   1373         if (field_index[0] == 0) {
   1374             j = 1; /* Adjust for union type. */
   1375         }
   1376         ct->members = field_index[j];
   1377         for (i = j + 1; i <= max_id; ++i) {
   1378             if (field_index[i] == 0) ++i; /* Adjust for union type. */
   1379             field_index[j]->link = field_index[i];
   1380             j = i;
   1381         }
   1382         field_index[max_id]->link = 0;
   1383     }
   1384     if (key_count) {
   1385         ct->symbol.flags |= fb_indexed;
   1386     }
   1387     /* Set primary key flag for backends even if chosen by default. */
   1388     if (ct->primary_key) {
   1389         ct->primary_key->metadata_flags |= fb_f_primary_key;
   1390     }
   1391     if (key_count > 1 && !P->opts.allow_multiple_key_fields) {
   1392         error_sym(P, &ct->symbol, "table has multiple key fields, but at most one is permitted");
   1393         ret = -1;
   1394     }
   1395     if (id_failed) {
   1396         ret = -1;
   1397     }
   1398     return ret;
   1399 }
   1400 
   1401 /*
   1402  * Post processing of process_table because some information is only
   1403  * available when all types have been processed.
   1404  */
   1405 static int validate_table_attr(fb_parser_t *P, fb_compound_type_t *ct)
   1406 {
   1407     fb_symbol_t *sym;
   1408     fb_member_t *member;
   1409 
   1410     for (sym = ct->members; sym; sym = sym->link) {
   1411         member = (fb_member_t *)sym;
   1412         if (member->metadata_flags & fb_f_deprecated) {
   1413             continue;
   1414         }
   1415 
   1416         if (member->type.type == vt_vector_compound_type_ref &&
   1417                 member->metadata_flags & fb_f_sorted) {
   1418             switch (member->type.ct->symbol.kind) {
   1419             case fb_is_table:
   1420                 if (!member->type.ct->primary_key) {
   1421                     error_sym(P, sym, "sorted table vector only valid when table has a key field");
   1422                     return -1;
   1423                 }
   1424                 break;
   1425             case fb_is_struct:
   1426                 if (!member->type.ct->primary_key) {
   1427                     error_sym(P, sym, "sorted struct vector only valid when struct has a key field");
   1428                     return -1;
   1429                 }
   1430                 break;
   1431             /* Other cases already handled in process_table. */
   1432             default:
   1433                 continue;
   1434             }
   1435         }
   1436     }
   1437     return 0;
   1438 }
   1439 
   1440 /*
   1441  * The parser already makes sure we have exactly one request type,
   1442  * one response type, and no initializer.
   1443  *
   1444  * We are a bit heavy on flagging attributes because their behavior
   1445  * isn't really specified at this point.
   1446  */
   1447 static int process_rpc_service(fb_parser_t *P, fb_compound_type_t *ct)
   1448 {
   1449     fb_symbol_t *sym, *old, *type_sym;
   1450     fb_member_t *member;
   1451 #if FLATCC_ALLOW_RPC_SERVICE_ATTRIBUTES || FLATCC_ALLOW_RPC_METHOD_ATTRIBUTES
   1452     fb_metadata_t *knowns[KNOWN_ATTR_COUNT];
   1453 #endif
   1454 
   1455     assert(ct->symbol.kind == fb_is_rpc_service);
   1456     assert(!ct->type.type);
   1457 
   1458     /*
   1459      * Deprecated is defined for fields - but it is unclear if this also
   1460      * covers rpc services. Anyway, we accept it since it may be useful,
   1461      * and does not harm.
   1462      */
   1463 #if FLATCC_ALLOW_RPC_SERVICE_ATTRIBUTES
   1464     /* But we have no known attributes to support. */
   1465     ct->metadata_flags = process_metadata(P, ct->metadata, 0, knowns);
   1466 #else
   1467     if (ct->metadata) {
   1468         error_sym(P, &ct->symbol, "rpc services cannot have attributes");
   1469         /* Non-fatal. */
   1470     }
   1471 #endif
   1472 
   1473     /*
   1474      * `original_order` now lives as a flag, we need not consider it
   1475      * further until code generation.
   1476      */
   1477     for (sym = ct->members; sym; sym = sym->link) {
   1478         type_sym = 0;
   1479         if ((old = define_fb_symbol(&ct->index, sym))) {
   1480             error_sym_2(P, sym, "rpc method already defined here", old);
   1481             continue;
   1482         }
   1483         if (sym->kind != fb_is_member) {
   1484             error_sym(P, sym, "internal error: member type expected");
   1485             return -1;
   1486         }
   1487         member = (fb_member_t *)sym;
   1488         if (member->value.type) {
   1489             error_sym(P, sym, "internal error: initializer should have been rejected by parser");
   1490         }
   1491         if (member->type.type == vt_invalid) {
   1492             continue;
   1493         }
   1494         if (member->type.type != vt_type_ref) {
   1495             error_sym(P, sym, "internal error: request type expected to be a type reference");
   1496         }
   1497         type_sym = lookup_type_reference(P, ct->scope, member->req_type.ref);
   1498         if (!type_sym) {
   1499             error_ref_sym(P, member->req_type.ref, "unknown type reference used with rpc request type", sym);
   1500             member->type.type = vt_invalid;
   1501             continue;
   1502         } else {
   1503             if (type_sym->kind != fb_is_table) {
   1504                 error_sym_2(P, sym, "rpc request type must reference a table, defined here", type_sym);
   1505                 member->type.type = vt_invalid;
   1506                 continue;
   1507             }
   1508             member->req_type.type = vt_compound_type_ref;
   1509             member->req_type.ct = (fb_compound_type_t*)type_sym;
   1510         }
   1511         type_sym = lookup_type_reference(P, ct->scope, member->type.ref);
   1512         if (!type_sym) {
   1513             error_ref_sym(P, member->type.ref, "unknown type reference used with rpc response type", sym);
   1514             member->type.type = vt_invalid;
   1515             continue;
   1516         } else {
   1517             if (type_sym->kind != fb_is_table) {
   1518                 error_sym_2(P, sym, "rpc response type must reference a table, defined here", type_sym);
   1519                 member->type.type = vt_invalid;
   1520                 continue;
   1521             }
   1522             member->type.type = vt_compound_type_ref;
   1523             member->type.ct = (fb_compound_type_t*)type_sym;
   1524             /* Symbols have no size. */
   1525             member->size = 0;
   1526         }
   1527 #if FLATCC_ALLOW_RPC_METHOD_ATTRIBUTES
   1528 #if FLATCC_ALLOW_DEPRECATED_RPC_METHOD
   1529         member->metadata_flags = process_metadata(P, member->metadata, fb_f_deprecated, knowns);
   1530 #else
   1531         member->metadata_flags = process_metadata(P, member->metadata, 0, knowns);
   1532 #endif
   1533 #else
   1534         if (member->metadata) {
   1535             error_sym(P, sym, "rpc methods cannot have attributes");
   1536             /* Non-fatal. */
   1537             continue;
   1538         }
   1539 #endif
   1540     }
   1541     return 0;
   1542 }
   1543 
   1544 static int process_enum(fb_parser_t *P, fb_compound_type_t *ct)
   1545 {
   1546     fb_symbol_t *sym, *old, *type_sym;
   1547     fb_member_t *member;
   1548     fb_metadata_t *knowns[KNOWN_ATTR_COUNT];
   1549     fb_value_t index = { { { 0 } }, 0, 0 };
   1550     fb_value_t old_index;
   1551     int first = 1;
   1552     int bit_flags = 0;
   1553     int is_union = ct->symbol.kind == fb_is_union;
   1554 
   1555     if (!is_union) {
   1556         assert(ct->symbol.kind == fb_is_enum);
   1557         if (!ct->type.type) {
   1558             ct->type.type = vt_invalid;
   1559             error_sym(P, &ct->symbol, "enum must have a type");
   1560             return -1;
   1561         }
   1562         if (ct->type.type == vt_missing) {
   1563             /*
   1564              * Enums normally require a type, but the parser may have an
   1565              * option to allow missing type, and then we provide a
   1566              * sensible default.
   1567              */
   1568             ct->type.st = fb_int;
   1569             ct->type.type = vt_scalar_type;
   1570         } else if (ct->type.type == vt_scalar_type) {
   1571             ct->type.st = map_scalar_token_type(ct->type.t);
   1572         } else {
   1573             /* Spec does not mention boolean type in enum, but we allow it. */
   1574             error_sym(P, &ct->symbol, "enum type must be a scalar integral type or bool");
   1575             return -1;
   1576         }
   1577         ct->size = sizeof_scalar_type(ct->type.st);
   1578         ct->align = (uint16_t)ct->size;
   1579     } else {
   1580         if (ct->type.type) {
   1581             error_sym(P, &ct->symbol, "unions cannot have a type, they are always enumerated as ubyte");
   1582             return -1;
   1583         }
   1584         /*
   1585          * We preprocess unions as enums to get the value assignments.
   1586          * The type field is not documented, but generated output from
   1587          * flatc suggests ubyte. We use a an injected token to represent
   1588          * the ubyte type so we do not have to hardcode elsewhere.
   1589          */
   1590         ct->type.type = vt_scalar_type;
   1591         ct->type.st = fb_ubyte;
   1592         /*
   1593          * The union field use the type field and not the offset field
   1594          * to define its size because type.type is scalar.
   1595          */
   1596         ct->size = sizeof_scalar_type(fb_ubyte);
   1597         ct->align = (uint16_t)ct->size;
   1598     }
   1599 
   1600     ct->metadata_flags = process_metadata(P, ct->metadata, fb_f_bit_flags, knowns);
   1601     if (ct->metadata_flags & fb_f_bit_flags) {
   1602         bit_flags = 1;
   1603         index.type = vt_uint;
   1604         index.u = 0;
   1605     }
   1606 
   1607     if (ct->type.st == fb_bool) {
   1608         index.b = 0;
   1609         index.type = vt_bool;
   1610     } else {
   1611         index.i = 0;
   1612         index.type = vt_int;
   1613         if (fb_coerce_scalar_type(P, (fb_symbol_t *)ct, ct->type.st, &index)) {
   1614             error(P, "internal error: unexpected conversion failure on enum 0 index");
   1615             return -1;
   1616         }
   1617     }
   1618     old_index = index;
   1619 
   1620     for (sym = ct->members; sym; sym = sym->link, first = 0) {
   1621         member = (fb_member_t *)sym;
   1622         if ((old = define_fb_symbol(&ct->index, sym))) {
   1623             if (old->ident == &P->t_none) {
   1624                 /*
   1625                  * Parser injects `NONE` as the first union member and
   1626                  * it therefore gets index 0. Additional use of NONE
   1627                  * will fail.
   1628                  */
   1629                 error_sym(P, sym, "'NONE' is a predefined value");
   1630                 member->type.type = vt_invalid;
   1631                 continue;
   1632             }
   1633             error_sym_2(P, sym, "value already defined here", old);
   1634             member->type.type = vt_invalid;
   1635             continue;
   1636         }
   1637         if (sym->kind != fb_is_member) {
   1638             error_sym(P, sym, "internal error: enum value type expected");
   1639             return -1;
   1640         }
   1641         /* Enum / union values cannot have metadata. */
   1642         assert(member->metadata == 0);
   1643         if (is_union) {
   1644             if (member->symbol.ident == &P->t_none) {
   1645                 /* Handle implicit NONE specially. */
   1646                 member->type.type = vt_missing;
   1647             } else if (member->type.type == vt_string_type) {
   1648                 member->size = 0;
   1649             } else if (member->type.type != vt_type_ref) {
   1650                 if (member->type.type != vt_invalid) {
   1651                     error_sym(P, sym, "union member type must be string or a reference to a table or a struct");
   1652                     member->type.type = vt_invalid;
   1653                 }
   1654                 continue;
   1655             } else {
   1656                 type_sym = lookup_type_reference(P, ct->scope, member->type.ref);
   1657                 if (!type_sym) {
   1658                     error_ref_sym(P, member->type.ref, "unknown type reference used with union member", sym);
   1659                     member->type.type = vt_invalid;
   1660                     continue;
   1661                 } else {
   1662                     if (type_sym->kind != fb_is_table && type_sym->kind != fb_is_struct) {
   1663                         error_sym_2(P, sym, "union member type reference must be a table or a struct, defined here", type_sym);
   1664                         member->type.type = vt_invalid;
   1665                         continue;
   1666                     }
   1667                     member->type.type = vt_compound_type_ref;
   1668                     member->type.ct = (fb_compound_type_t*)type_sym;
   1669                     /* Symbols have no size. */
   1670                     member->size = 0;
   1671                 }
   1672             }
   1673         }
   1674         if (!member->value.type && !first) {
   1675             if (index.type == vt_uint) {
   1676                 if (ct->type.st == fb_long && index.u == UINT64_MAX) {
   1677                     /* Not captured by range check. */
   1678                     error_sym(P, sym, "64-bit unsigned int overflow");
   1679                 }
   1680                 index.u = index.u + 1;
   1681             } else if (index.type == vt_int && !first) {
   1682                 if (ct->type.st == fb_long && index.i == INT64_MAX) {
   1683                     /* Not captured by range check. */
   1684                     error_sym(P, sym, "64-bit signed int overflow");
   1685                 }
   1686                 index.i = index.i + 1;
   1687             } else if (index.type == vt_bool && !first) {
   1688                 if (index.b == 1) {
   1689                     error_sym(P, sym, "boolean overflow: cannot enumerate past true");
   1690                 }
   1691                 index.b = 1;
   1692             }
   1693         }
   1694         if (bit_flags) {
   1695             if (member->value.type) {
   1696                 if (member->value.type != vt_uint) {
   1697                     error_sym(P, sym, "enum value must be unsigned int when used with 'bit_flags'");
   1698                     return -1;
   1699                 } else {
   1700                     index = member->value;
   1701                 }
   1702             }
   1703             if (index.u >= sizeof_scalar_type(ct->type.st) * 8) {
   1704                 error_sym(P, sym, "enum value out of range when used with 'bit_flags'");
   1705                 return -1;
   1706             }
   1707             member->value.u = UINT64_C(1) << index.u;
   1708             member->value.type = vt_uint;
   1709             if (fb_coerce_scalar_type(P, sym, ct->type.st, &member->value)) {
   1710                  /* E.g. enumval = 15 causes signed overflow with short. */
   1711                 error_sym(P, sym, "enum value out of range when used with 'bit_flags'");
   1712                 return -1;
   1713             }
   1714         } else {
   1715             if (member->value.type) {
   1716                 index = member->value;
   1717             }
   1718             /*
   1719              * Captures errors in user assigned values. Also captures
   1720              * overflow on auto-increment on all types except maximum
   1721              * representation size, i.e. long or ulong which we handled
   1722              * above.
   1723              */
   1724             if (fb_coerce_scalar_type(P, sym, ct->type.st, &index)) {
   1725                 return -1;
   1726             }
   1727             member->value = index;
   1728         }
   1729         if (!first && P->opts.ascending_enum) {
   1730             /* Without ascending enum we also allow duplicate values (but not names). */
   1731             if ((index.type == vt_uint && index.u <= old_index.u) ||
   1732                     (index.type == vt_int && index.i <= old_index.i)) {
   1733                 if (is_union && old_index.u == 0) {
   1734                     /*
   1735                      * The user explicitly assigned zero, or less, to the first
   1736                      * element (here second element after parser injecting
   1737                      * the NONE element).
   1738                      */
   1739                     error_sym(P, sym, "union values must be positive, 0 is reserved for implicit 'NONE'");
   1740                     member->value.type = vt_invalid;
   1741                     return -1;
   1742                 }
   1743                 error_sym(P, sym, "enum values must be in ascending order");
   1744                 member->value.type = vt_invalid;
   1745                 return -1;
   1746             }
   1747             if (index.type == vt_bool && index.b <= old_index.b) {
   1748                 error_sym(P, sym, "enum of type bool can only enumerate from false (0) to true (1)");
   1749                 member->value.type = vt_invalid;
   1750                 return -1;
   1751             }
   1752         }
   1753         old_index = index;
   1754         if (add_to_value_set(&ct->value_set, &member->value)) {
   1755             if (is_union) {
   1756                 error_sym(P, sym, "union members require unique positive values (0 being reserved for 'NONE'");
   1757                 member->value.type = vt_invalid;
   1758                 return -1;
   1759             } else {
   1760                 /*
   1761                  * With ascending enums this won't happen, but
   1762                  * otherwise flag secondary values so we can remove them
   1763                  * from inverse name mappings in code gen.
   1764                  */
   1765                 member->symbol.flags |= fb_duplicate;
   1766             }
   1767         }
   1768         if (member->metadata) {
   1769             error_sym(P, sym, "enum values cannot have attributes");
   1770             /* Non-fatal. */
   1771             continue;
   1772         }
   1773     }
   1774     return 0;
   1775 }
   1776 
   1777 static inline int process_union(fb_parser_t *P, fb_compound_type_t *ct)
   1778 {
   1779     return process_enum(P, ct);
   1780 }
   1781 
   1782 int fb_build_schema(fb_parser_t *P)
   1783 {
   1784     fb_schema_t *S = &P->schema;
   1785     fb_symbol_t *sym, *old_sym;
   1786     fb_name_t *old_name;
   1787     fb_compound_type_t *ct;
   1788     fb_attribute_t *a;
   1789 
   1790     /* Make sure self is visible at this point in time. */
   1791     assert(ptr_set_exists(&P->schema.visible_schema, &P->schema));
   1792     for (sym = S->symbols; sym; sym = sym->link) {
   1793         switch (sym->kind) {
   1794         case fb_is_table:
   1795         case fb_is_enum:
   1796         case fb_is_union:
   1797         case fb_is_struct:
   1798         case fb_is_rpc_service:
   1799             ct = (fb_compound_type_t *)sym;
   1800             set_type_hash(ct);
   1801             ct->schema = &P->schema;
   1802             if (ct->scope && (old_sym = define_fb_symbol(&ct->scope->symbol_index, sym))) {
   1803                 error_sym_2(P, sym, "symbol already defined here", old_sym);
   1804             }
   1805         }
   1806     }
   1807 
   1808     /*
   1809      * Known attributes will be pre-defined if not provided by the
   1810      * user. After that point, all attribute references must be
   1811      * defined.
   1812      */
   1813     for (a = (fb_attribute_t *)S->attributes; a; a = (fb_attribute_t *)a->name.link) {
   1814         if ((old_name = define_fb_name(&S->root_schema->attribute_index, &a->name))) {
   1815             /*
   1816              * Allow attributes to be defined multiple times, including
   1817              * known attributes.
   1818              */
   1819 #if 0
   1820             error_name(P, &a->name, "attribute already defined");
   1821 #endif
   1822         }
   1823     }
   1824     install_known_attributes(P);
   1825 
   1826     if (!P->opts.hide_later_enum) {
   1827         for (sym = S->symbols; sym; sym = sym->link) {
   1828             switch (sym->kind) {
   1829             case fb_is_enum:
   1830                 ct = (fb_compound_type_t *)sym;
   1831                 if (process_enum(P, ct)) {
   1832                     ct->type.type = vt_invalid;
   1833                     continue;
   1834                 }
   1835                 break;
   1836         default:
   1837             continue;
   1838             }
   1839         }
   1840     }
   1841 
   1842     /*
   1843      * Resolve type references both earlier and later than point of
   1844      * reference. This also supports recursion for tables and unions.
   1845      */
   1846     for (sym = S->symbols; sym; sym = sym->link) {
   1847         switch (sym->kind) {
   1848         case fb_is_struct:
   1849             ct = (fb_compound_type_t *)sym;
   1850             if (process_struct(P, ct)) {
   1851                 ct->type.type = vt_invalid;
   1852                 continue;
   1853             }
   1854             break;
   1855         case fb_is_table:
   1856             /* Handle after structs and enums. */
   1857             continue;
   1858         case fb_is_rpc_service:
   1859             /*
   1860              * Also handle rpc_service later like tables, just in case
   1861              * we allow non-table types in request/response type.
   1862              */
   1863             continue;
   1864         case fb_is_enum:
   1865             if (P->opts.hide_later_enum) {
   1866                 ct = (fb_compound_type_t *)sym;
   1867                 if (process_enum(P, ct)) {
   1868                     ct->type.type = vt_invalid;
   1869                     continue;
   1870                 }
   1871             }
   1872             break;
   1873         case fb_is_union:
   1874             ct = (fb_compound_type_t *)sym;
   1875             if (process_union(P, ct)) {
   1876                 ct->type.type = vt_invalid;
   1877                 continue;
   1878             }
   1879             break;
   1880         default:
   1881             error_sym(P, sym, "internal error: unexpected symbol at schema level");
   1882             return -1;
   1883         }
   1884     }
   1885     for (sym = P->schema.symbols; sym; sym = sym->link) {
   1886         switch (sym->kind) {
   1887         case fb_is_struct:
   1888             /*
   1889              * Structs need two stages, first process symbols, then
   1890              * analyze for size, alignment, and circular references.
   1891              */
   1892             ct = (fb_compound_type_t *)sym;
   1893             if (ct->type.type != vt_invalid && analyze_struct(P, ct)) {
   1894                 ct->type.type = vt_invalid;
   1895                 continue;
   1896             }
   1897             break;
   1898         default:
   1899             continue;
   1900         }
   1901     }
   1902     for (sym = P->schema.symbols; sym; sym = sym->link) {
   1903         switch (sym->kind) {
   1904         case fb_is_table:
   1905             ct = (fb_compound_type_t *)sym;
   1906             /* Only now is the full struct size available. */
   1907             if (ct->type.type != vt_invalid && process_table(P, ct)) {
   1908                 ct->type.type = vt_invalid;
   1909                 continue;
   1910             }
   1911             break;
   1912         case fb_is_rpc_service:
   1913             ct = (fb_compound_type_t *)sym;
   1914             /* Only now is the full struct size available. */
   1915             if (ct->type.type != vt_invalid && process_rpc_service(P, ct)) {
   1916                 ct->type.type = vt_invalid;
   1917                 continue;
   1918             }
   1919         }
   1920     }
   1921     for (sym = P->schema.symbols; sym; sym = sym->link) {
   1922         switch (sym->kind) {
   1923         case fb_is_table:
   1924             ct = (fb_compound_type_t *)sym;
   1925             /*
   1926              * Some table attributes depend on attributes on members and
   1927              * therefore can only be validated after procesing.
   1928              */
   1929             if (ct->type.type != vt_invalid && validate_table_attr(P, ct)) {
   1930                 ct->type.type = vt_invalid;
   1931                 continue;
   1932             }
   1933         }
   1934     }
   1935     revert_order(&P->schema.ordered_structs);
   1936     if (!S->root_type.name) {
   1937         if (P->opts.require_root_type) {
   1938             error(P, "root type not declared");
   1939         }
   1940     } else {
   1941         sym = S->root_type.type = lookup_type_reference(P,
   1942                 S->root_type.scope, S->root_type.name);
   1943         if (!sym) {
   1944             error_ref(P, S->root_type.name, "root type not found");
   1945         } else if (P->opts.allow_struct_root) {
   1946             if (sym->kind != fb_is_struct && sym->kind != fb_is_table) {
   1947                 error_ref(P, S->root_type.name, "root type must be a struct or a table");
   1948             } else {
   1949                 S->root_type.type = sym;
   1950             }
   1951         } else {
   1952             if (sym->kind != fb_is_table) {
   1953                 error_ref(P, S->root_type.name, "root type must be a table");
   1954             } else {
   1955                 S->root_type.type = sym;
   1956             }
   1957         }
   1958         S->root_type.name = 0;
   1959     }
   1960     P->has_schema = !P->failed;
   1961     return P->failed;
   1962 }