LCOV - code coverage report
Current view: top level - src/compiler - flatcc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 124 188 66.0 %
Date: 2016-11-30 13:12:14 Functions: 9 12 75.0 %
Branches: 52 134 38.8 %

           Branch data     Line data    Source code
       1                 :            : #include <assert.h>
       2                 :            : #include "config.h"
       3                 :            : #include "parser.h"
       4                 :            : #include "semantics.h"
       5                 :            : #include "fileio.h"
       6                 :            : #include "codegen.h"
       7                 :            : #include "flatcc/flatcc.h"
       8                 :            : 
       9                 :            : #define checkfree(s) if (s) { free(s); s = 0; }
      10                 :            : 
      11                 :         12 : void flatcc_init_options(flatcc_options_t *opts)
      12                 :            : {
      13                 :         12 :     memset(opts, 0, sizeof(*opts));
      14                 :            : 
      15                 :         12 :     opts->max_schema_size = FLATCC_MAX_SCHEMA_SIZE;
      16                 :         12 :     opts->max_include_depth = FLATCC_MAX_INCLUDE_DEPTH;
      17                 :         12 :     opts->max_include_count = FLATCC_MAX_INCLUDE_COUNT;
      18                 :         12 :     opts->allow_boolean_conversion = FLATCC_ALLOW_BOOLEAN_CONVERSION;
      19                 :         12 :     opts->allow_enum_key = FLATCC_ALLOW_ENUM_KEY;
      20                 :         12 :     opts->allow_enum_struct_field = FLATCC_ALLOW_ENUM_STRUCT_FIELD;
      21                 :         12 :     opts->allow_multiple_key_fields = FLATCC_ALLOW_MULTIPLE_KEY_FIELDS;
      22                 :         12 :     opts->allow_string_key = FLATCC_ALLOW_STRING_KEY;
      23                 :         12 :     opts->allow_struct_field_deprecate = FLATCC_ALLOW_STRUCT_FIELD_DEPRECATE;
      24                 :         12 :     opts->allow_struct_field_key = FLATCC_ALLOW_STRUCT_FIELD_KEY;
      25                 :         12 :     opts->allow_struct_root = FLATCC_ALLOW_STRUCT_ROOT;
      26                 :         12 :     opts->ascending_enum = FLATCC_ASCENDING_ENUM;
      27                 :         12 :     opts->hide_later_enum = FLATCC_HIDE_LATER_ENUM;
      28                 :         12 :     opts->hide_later_struct = FLATCC_HIDE_LATER_STRUCT;
      29                 :         12 :     opts->offset_size = FLATCC_OFFSET_SIZE;
      30                 :         12 :     opts->voffset_size = FLATCC_VOFFSET_SIZE;
      31                 :         12 :     opts->utype_size = FLATCC_UTYPE_SIZE;
      32                 :         12 :     opts->bool_size = FLATCC_BOOL_SIZE;
      33                 :            : 
      34                 :         12 :     opts->require_root_type = FLATCC_REQUIRE_ROOT_TYPE;
      35                 :         12 :     opts->strict_enum_init = FLATCC_STRICT_ENUM_INIT;
      36                 :            :     /*
      37                 :            :      * Index 0 is table elem count, and index 1 is table size
      38                 :            :      * so max count is reduced by 2, meaning field id's
      39                 :            :      * must be between 0 and vt_max_count - 1.
      40                 :            :      * Usually, the table is 16-bit, so FLATCC_VOFFSET_SIZE = 2.
      41                 :            :      * Strange expression to avoid shift overflow on 64 bit size.
      42                 :            :      */
      43                 :         12 :     opts->vt_max_count = ((1LL << (FLATCC_VOFFSET_SIZE * 8 - 1)) - 1) * 2;
      44                 :            : 
      45                 :         12 :     opts->default_schema_ext = FLATCC_DEFAULT_SCHEMA_EXT;
      46                 :         12 :     opts->default_bin_schema_ext = FLATCC_DEFAULT_BIN_SCHEMA_EXT;
      47                 :         12 :     opts->default_bin_ext = FLATCC_DEFAULT_BIN_EXT;
      48                 :            : 
      49                 :         12 :     opts->cgen_pad = FLATCC_CGEN_PAD;
      50                 :         12 :     opts->cgen_sort = FLATCC_CGEN_SORT;
      51                 :         12 :     opts->cgen_pragmas = FLATCC_CGEN_PRAGMAS;
      52                 :            : 
      53                 :         12 :     opts->cgen_common_reader = 0;
      54                 :         12 :     opts->cgen_common_builder = 0;
      55                 :         12 :     opts->cgen_reader = 0;
      56                 :         12 :     opts->cgen_builder = 0;
      57                 :         12 :     opts->cgen_json_parser = 0;
      58                 :         12 :     opts->cgen_spacing = FLATCC_CGEN_SPACING;
      59                 :            : 
      60                 :         12 :     opts->bgen_bfbs = FLATCC_BGEN_BFBS;
      61                 :         12 :     opts->bgen_qualify_names = FLATCC_BGEN_QUALIFY_NAMES;
      62                 :         12 :     opts->bgen_length_prefix = FLATCC_BGEN_LENGTH_PREFIX;
      63                 :         12 : }
      64                 :            : 
      65                 :         16 : flatcc_context_t flatcc_create_context(flatcc_options_t *opts, const char *name,
      66                 :            :         flatcc_error_fun error_out, void *error_ctx)
      67                 :            : {
      68                 :            :     fb_parser_t *P;
      69                 :            : 
      70         [ +  - ]:         16 :     if (!(P = malloc(sizeof(*P)))) {
      71                 :            :         return 0;
      72                 :            :     }
      73         [ -  + ]:         16 :     if (fb_init_parser(P, opts, name, error_out, error_ctx, 0)) {
      74                 :          0 :         free(P);
      75                 :          0 :         return 0;
      76                 :            :     }
      77                 :            :     return P;
      78                 :            : }
      79                 :            : 
      80                 :         50 : static flatcc_context_t __flatcc_create_child_context(flatcc_options_t *opts, const char *name,
      81                 :            :         fb_parser_t *P_parent)
      82                 :            : {
      83                 :            :     fb_parser_t *P;
      84                 :            : 
      85         [ +  - ]:         50 :     if (!(P = malloc(sizeof(*P)))) {
      86                 :            :         return 0;
      87                 :            :     }
      88         [ -  + ]:         50 :     if (fb_init_parser(P, opts, name, P_parent->error_out, P_parent->error_ctx, P_parent->schema.root_schema)) {
      89                 :          0 :         free(P);
      90                 :          0 :         return 0;
      91                 :            :     }
      92                 :            :     return P;
      93                 :            : }
      94                 :            : 
      95                 :            : /* TODO: handle include files via some sort of buffer read callback
      96                 :            :  * and possible transfer file based parser to this logic. */
      97                 :          1 : int flatcc_parse_buffer(flatcc_context_t ctx, const char *buf, size_t buflen)
      98                 :            : {
      99                 :            :     fb_parser_t *P = ctx;
     100                 :            : 
     101                 :            :     /* Currently includes cannot be handled by buffers, so they should done. */
     102                 :          1 :     P->opts.disable_includes = 1;
     103 [ -  + ][ #  # ]:          1 :     if ((size_t)buflen > P->opts.max_schema_size && P->opts.max_schema_size > 0) {
     104                 :          0 :         fb_print_error(P, "input exceeds maximum allowed size\n");
     105                 :          0 :         return -1;
     106                 :            :     }
     107                 :            :     /* Add self to set of visible schema. */
     108                 :          1 :     ptr_set_insert_item(&P->schema.visible_schema, &P->schema, ht_keep);
     109 [ +  - ][ -  + ]:          1 :     return fb_parse(P, buf, buflen, 0) || fb_build_schema(P) ? -1 : 0;
     110                 :            : }
     111                 :            : 
     112                 :         36 : static void visit_dep(void *context, void *ptr)
     113                 :            : {
     114                 :            :     fb_schema_t *parent = context;
     115                 :            :     fb_schema_t *dep = ptr;
     116                 :            : 
     117                 :         36 :     ptr_set_insert_item(&parent->visible_schema, dep, ht_keep);
     118                 :         36 : }
     119                 :            : 
     120                 :            : static void add_visible_schema(fb_schema_t *parent, fb_schema_t *dep)
     121                 :            : {
     122                 :         50 :     ptr_set_visit(&dep->visible_schema, visit_dep, parent);
     123                 :            : }
     124                 :            : 
     125                 :         50 : static int __parse_include_file(fb_parser_t *P_parent, const char *filename)
     126                 :            : {
     127                 :            :     flatcc_context_t *ctx = 0;
     128                 :            :     fb_parser_t *P = 0;
     129                 :            :     fb_root_schema_t *rs;
     130                 :         50 :     flatcc_options_t *opts = &P_parent->opts;
     131                 :            :     fb_schema_t *dep;
     132                 :            : 
     133                 :         50 :     rs = P_parent->schema.root_schema;
     134 [ -  + ][ #  # ]:         50 :     if (rs->include_depth >= opts->max_include_depth && opts->max_include_depth > 0) {
     135                 :          0 :         fb_print_error(P_parent, "include nesting level too deep\n");
     136                 :          0 :         return -1;
     137                 :            :     }
     138 [ -  + ][ #  # ]:         50 :     if (rs->include_count >= opts->max_include_count && opts->max_include_count > 0) {
     139                 :          0 :         fb_print_error(P_parent, "include count limit exceeded\n");
     140                 :          0 :         return -1;
     141                 :            :     }
     142         [ +  - ]:         50 :     if (!(ctx = __flatcc_create_child_context(opts, filename, P_parent))) {
     143                 :            :         return -1;
     144                 :            :     }
     145                 :            :     P = (fb_parser_t *)ctx;
     146                 :            :     /* Don't parse the same file twice, or any other file with same name. */
     147         [ +  + ]:         50 :     if ((dep = fb_schema_table_find_item(&rs->include_index, &P->schema))) {
     148                 :         32 :         add_visible_schema(&P_parent->schema, dep);
     149                 :         32 :         flatcc_destroy_context(ctx);
     150                 :         32 :         return 0;
     151                 :            :     }
     152                 :         18 :     P->dependencies = P_parent->dependencies;
     153                 :         18 :     P_parent->dependencies = P;
     154                 :         18 :     P->referer_path = P_parent->path;
     155                 :            :     /* Each parser has a root schema instance, but only the root parsers instance is used. */
     156                 :         18 :     rs->include_depth++;
     157                 :         18 :     rs->include_count++;
     158         [ +  - ]:         18 :     if (flatcc_parse_file(ctx, filename)) {
     159                 :            :         return -1;
     160                 :            :     }
     161                 :         18 :     add_visible_schema(&P_parent->schema, &P->schema);
     162                 :         18 :     return 0;
     163                 :            : }
     164                 :            : 
     165                 :            : /*
     166                 :            :  * The depends file format is a make rule:
     167                 :            :  *
     168                 :            :  * <outputfile> : <dep1-file> <dep2-file> ...
     169                 :            :  *
     170                 :            :  * like -MMD option for gcc/clang:
     171                 :            :  * lib.o.d generated with content:
     172                 :            :  *
     173                 :            :  * lib.o : header1.h header2.h
     174                 :            :  *
     175                 :            :  * We use a file name <basename>.depends for schema <basename>.fbs with content:
     176                 :            :  *
     177                 :            :  * <basename>_reader.h : <included-schema-1> ...
     178                 :            :  *
     179                 :            :  * The .d extension could mean the D language and we don't have sensible
     180                 :            :  * .o.d name because of multiple outputs, so .depends is better.
     181                 :            :  *
     182                 :            :  * (the above above is subject to the configuration of extensions).
     183                 :            :  *
     184                 :            :  * TODO:
     185                 :            :  * perhaps we should optionally add a dependency to the common reader
     186                 :            :  * and builder files when they are generated separately as they should in
     187                 :            :  * concurrent builds.
     188                 :            :  *
     189                 :            :  * TODO:
     190                 :            :  * 1. we should have a file for every output we produce (_builder.h * etc.)
     191                 :            :  * 2. reader might not even be in the output, e.g. verifier only.
     192                 :            :  * 3. multiple outputs doesn't work with ninja build 1.7.1, so just
     193                 :            :  *    use reader for now, and possible add an option for multiple
     194                 :            :  *    outputs later.
     195                 :            :  *
     196                 :            :  *  http://stackoverflow.com/questions/11855386/using-g-with-mmd-in-makefile-to-automatically-generate-dependencies
     197                 :            :  *  https://groups.google.com/forum/#!topic/ninja-build/j-2RfBIOd_8
     198                 :            :  *  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485
     199                 :            :  *
     200                 :            :  *  Spaces in gnu make:
     201                 :            :  *  https://www.cmcrossroads.com/article/gnu-make-meets-file-names-spaces-them
     202                 :            :  *  See comments on gnu make handling of spaces.
     203                 :            :  *  http://clang.llvm.org/doxygen/DependencyFile_8cpp_source.html
     204                 :            :  */
     205                 :          0 : static int __flatcc_gen_depends_file(fb_parser_t *P)
     206                 :            : {
     207                 :            :     FILE *fp = 0;
     208                 :            :     const char *outpath, *basename; 
     209                 :            :     const char *depfile, *deproot, *depext;
     210                 :            :     const char *targetfile, *targetsuffix, *targetroot;
     211                 :            :     char *path = 0, *deppath = 0, *tmppath = 0, *targetpath = 0; 
     212                 :            :     int ret = -1;
     213                 :            : 
     214                 :            :     /*
     215                 :            :      * The dependencies list is only correct for root files as it is a
     216                 :            :      * linear list. To deal with children, we would have to filter via
     217                 :            :      * the visible schema hash table, but we don't really need that.
     218                 :            :      */
     219                 :            :     assert(P->referer_path == 0);
     220                 :            : 
     221         [ #  # ]:          0 :     outpath = P->opts.outpath ? P->opts.outpath : "";
     222                 :          0 :     basename = P->schema.basename;
     223                 :          0 :     targetfile = P->opts.gen_deptarget;
     224                 :            : 
     225                 :            : 
     226                 :            :     /* The following is mostly considering build tools generating
     227                 :            :      * a depfile as Ninja build would use it. It is a bit strict
     228                 :            :      * on path variations and currenlty doesn't accept multiple
     229                 :            :      * build products in a build rule (Ninja 1.7.1).
     230                 :            :      *
     231                 :            :      * Make depfile relative to cwd so the user can add output if
     232                 :            :      * needed, otherwise it is not possible, or difficult, to use a path given
     233                 :            :      * by a build tool, relative the cwd. If --depfile is not given,
     234                 :            :      * then -d is given or we would not be here. In that case we add an
     235                 :            :      * extension "<basename>.fbs.d" in the outpath.
     236                 :            :      *
     237                 :            :      * A general problem is that the outpath may be a build root dir or
     238                 :            :      * a current subdir for a custom build rule while the dep file
     239                 :            :      * content needs the same path every time, not just an equivalent
     240                 :            :      * path. For dependencies, we can rely on the input schema path.
     241                 :            :      * The input search paths may because confusion but we choose the
     242                 :            :      * discovered path relative to cwd consistently for each schema file
     243                 :            :      * encountered.
     244                 :            :      *
     245                 :            :      * The target file (<target>: <include1.fbs> <include2.fbs> ...)
     246                 :            :      * is tricky because it is not unique - but we can chose <schema>_reader.h
     247                 :            :      * or <schema>.bfbs prefixed with outpath. The user should choose an
     248                 :            :      * outpath relative to cwd or an absolute path depending on what the
     249                 :            :      * build system prefers. This may not be so easy in praxis, but what
     250                 :            :      * can we do?
     251                 :            :      *
     252                 :            :      * It is important to note the default target and the default
     253                 :            :      * depfile name is not just a convenience. Sometimes it is much
     254                 :            :      * simpler to use this version over an explicit path, sometimes
     255                 :            :      * perhaps not so much.
     256                 :            :      */
     257                 :            : 
     258         [ #  # ]:          0 :     if (P->opts.gen_depfile) {
     259                 :            :         depfile = P->opts.gen_depfile;
     260                 :            :         deproot = "";
     261                 :            :         depext = "";
     262                 :            :     } else {
     263                 :            :         depfile = basename;
     264                 :            :         deproot = outpath;
     265                 :            :         depext = FLATCC_DEFAULT_DEP_EXT;
     266                 :            :     }
     267         [ #  # ]:          0 :     if (targetfile) {
     268                 :            :         targetsuffix = "";
     269                 :            :         targetroot = "";
     270                 :            :     } else {
     271                 :          0 :         targetsuffix = P->opts.bgen_bfbs 
     272                 :            :                 ? FLATCC_DEFAULT_BIN_SCHEMA_EXT 
     273         [ #  # ]:          0 :                 : FLATCC_DEFAULT_DEP_TARGET_SUFFIX;
     274                 :            :         targetfile = basename;
     275                 :            :         targetroot = outpath;
     276                 :            :     }
     277                 :            : 
     278                 :          0 :     checkmem(path = fb_create_join_path(deproot, depfile, depext, 1));
     279                 :            : 
     280                 :          0 :     checkmem(tmppath = fb_create_join_path(targetroot, targetfile, targetsuffix, 1));
     281                 :            :     /* Handle spaces in dependency file. */
     282                 :          0 :     checkmem((targetpath = fb_create_make_path(tmppath)));
     283         [ #  # ]:          0 :     checkfree(tmppath);
     284                 :            : 
     285                 :          0 :     fp = fopen(path, "wb");
     286         [ #  # ]:          0 :     if (!fp) {
     287                 :          0 :         fb_print_error(P, "could not open dependency file for output: %s\n", path);
     288                 :          0 :         goto done;
     289                 :            :     }
     290                 :          0 :     fprintf(fp, "%s:", targetpath);
     291                 :            : 
     292                 :            :     /* Don't depend on root schema. */
     293                 :          0 :     P = P->dependencies;
     294         [ #  # ]:          0 :     while (P) {
     295                 :          0 :         checkmem((deppath = fb_create_make_path(P->path)));
     296                 :          0 :         fprintf(fp, " %s", deppath);
     297                 :          0 :         P = P->dependencies;
     298         [ #  # ]:          0 :         checkfree(deppath);
     299                 :            :     }
     300                 :          0 :     fprintf(fp, "\n");
     301                 :            :     ret = 0;
     302                 :            : 
     303                 :            : done:
     304         [ #  # ]:          0 :     checkfree(path);
     305         [ #  # ]:          0 :     checkfree(tmppath);
     306         [ #  # ]:          0 :     checkfree(targetpath);
     307         [ #  # ]:          0 :     checkfree(deppath);
     308         [ #  # ]:          0 :     if (fp) {
     309                 :          0 :         fclose(fp);
     310                 :            :     }
     311                 :          0 :     return ret;
     312                 :            : }
     313                 :            : 
     314                 :         33 : int flatcc_parse_file(flatcc_context_t ctx, const char *filename)
     315                 :            : {
     316                 :            :     fb_parser_t *P = ctx;
     317                 :            :     size_t inpath_len, filename_len;
     318                 :            :     char *buf, *path, *include_file;
     319                 :            :     const char *inpath;
     320                 :            :     size_t size;
     321                 :            :     fb_name_t *inc;
     322                 :            :     int i, ret, is_root;
     323                 :            : 
     324                 :         33 :     filename_len = strlen(filename);
     325                 :            :     /* Don't parse the same file twice, or any other file with same basename. */
     326         [ +  - ]:         33 :     if (fb_schema_table_insert_item(&P->schema.root_schema->include_index, &P->schema, ht_keep)) {
     327                 :            :         return 0;
     328                 :            :     }
     329                 :            :     buf = 0;
     330                 :            :     path = 0;
     331                 :            :     include_file = 0;
     332                 :            :     ret = -1;
     333                 :         33 :     is_root = !P->referer_path;
     334                 :            : 
     335                 :            :     /*
     336                 :            :      * For root files, read file relative to working dir first. For
     337                 :            :      * included files (`referer_path` set), first try include paths
     338                 :            :      * in order, then path relative to including file.
     339                 :            :      */
     340         [ +  + ]:         33 :     if (is_root) {
     341         [ -  + ]:         15 :         if (!(buf = fb_read_file(filename, P->opts.max_schema_size, &size))) {
     342 [ #  # ][ #  # ]:          0 :             if (size + P->schema.root_schema->total_source_size > P->opts.max_schema_size && P->opts.max_schema_size > 0) {
     343                 :          0 :                 fb_print_error(P, "input exceeds maximum allowed size\n");
     344                 :            :                 ret = -1;
     345                 :          0 :                 goto done;
     346                 :            :             }
     347                 :            :         } else {
     348                 :         33 :             checkmem((path = fb_copy_path(filename)));
     349                 :            :         }
     350                 :            :     }
     351 [ +  + ][ -  + ]:         33 :     for (i = 0; !buf && i < P->opts.inpath_count; ++i) {
     352                 :          0 :         inpath = P->opts.inpaths[i];
     353                 :          0 :         inpath_len = strlen(inpath);
     354                 :          0 :         checkmem((path = fb_create_join_path_n(inpath, inpath_len, filename, filename_len, "", 1)));
     355         [ #  # ]:          0 :         if (!(buf = fb_read_file(path, P->opts.max_schema_size, &size))) {
     356                 :          0 :             free(path);
     357                 :            :             path = 0;
     358 [ #  # ][ #  # ]:          0 :             if (size > P->opts.max_schema_size && P->opts.max_schema_size > 0) {
     359                 :          0 :                 fb_print_error(P, "input exceeds maximum allowed size\n");
     360                 :            :                 ret = -1;
     361                 :          0 :                 goto done;
     362                 :            :             }
     363                 :            :         }
     364                 :            :     }
     365         [ +  + ]:         33 :     if (!buf && !is_root) {
     366                 :         18 :         inpath = P->referer_path;
     367                 :         18 :         inpath_len = fb_find_basename(inpath, strlen(inpath));
     368                 :         18 :         checkmem((path = fb_create_join_path_n(inpath, inpath_len, filename, filename_len, "", 1)));
     369         [ -  + ]:         18 :         if (!(buf = fb_read_file(path, P->opts.max_schema_size, &size))) {
     370                 :          0 :             free(path);
     371                 :            :             path = 0;
     372 [ #  # ][ #  # ]:          0 :             if (size > P->opts.max_schema_size && P->opts.max_schema_size > 0) {
     373                 :          0 :                 fb_print_error(P, "input exceeds maximum allowed size\n");
     374                 :            :                 ret = -1;
     375                 :          0 :                 goto done;
     376                 :            :             }
     377                 :            :         }
     378                 :            :     }
     379         [ -  + ]:         33 :     if (!buf) {
     380                 :          0 :         fb_print_error(P, "error reading included schema file: %s\n", filename);
     381                 :          0 :         goto done;
     382                 :            :     }
     383                 :         33 :     P->schema.root_schema->total_source_size += size;
     384                 :         33 :     P->path = path;
     385                 :            :     /* Parser owns path. */
     386                 :            :     path = 0;
     387                 :            :     /*
     388                 :            :      * Even if we do not have the recursive option set, we still
     389                 :            :      * need to parse all include files to make sense of the current
     390                 :            :      * file.
     391                 :            :      */
     392         [ +  - ]:         33 :     if (!(ret = fb_parse(P, buf, size, 1))) {
     393                 :            :         /* Parser owns buffer. */
     394                 :            :         buf = 0;
     395                 :         33 :         inc = P->schema.includes;
     396         [ +  + ]:         83 :         while (inc) {
     397                 :         50 :             checkmem((include_file = fb_copy_path_n(inc->name.s.s, inc->name.s.len)));
     398         [ +  - ]:         50 :             if (__parse_include_file(P, include_file)) {
     399                 :            :                 goto done;
     400                 :            :             }
     401                 :         50 :             free(include_file);
     402                 :            :             include_file = 0;
     403                 :         50 :             inc = inc->link;
     404                 :            :         }
     405                 :            :         /* Add self to set of visible schema. */
     406                 :         33 :         ptr_set_insert_item(&P->schema.visible_schema, &P->schema, ht_keep);
     407         [ +  - ]:         33 :         if (fb_build_schema(P)) {
     408                 :            :             goto done;
     409                 :            :         }
     410                 :            :         /*
     411                 :            :         * We choose to only generate optional .depends files for root level
     412                 :            :         * files. These will contain all nested files regardless of
     413                 :            :         * recursive file generation flags.
     414                 :            :         */
     415 [ -  + ][ #  # ]:         33 :         if (P->opts.gen_dep && is_root) {
     416         [ #  # ]:          0 :             if (__flatcc_gen_depends_file(P)) {
     417                 :            :                 goto done;
     418                 :            :             }
     419                 :            :         }
     420                 :            :     }
     421                 :            :     ret = 0;
     422                 :            : 
     423                 :            : done:
     424                 :            :     /* Parser owns buffer so don't free it here. */
     425         [ -  + ]:         33 :     checkfree(path);
     426         [ -  + ]:         33 :     checkfree(include_file);
     427                 :            :     return ret;
     428                 :            : }
     429                 :            : 
     430                 :            : #if FLATCC_REFLECTION
     431                 :          0 : int flatcc_generate_binary_schema_to_buffer(flatcc_context_t ctx, void *buf, size_t bufsiz)
     432                 :            : {
     433                 :            :     fb_parser_t *P = ctx;
     434                 :            : 
     435         [ #  # ]:          0 :     if (fb_codegen_bfbs_to_buffer(&P->opts, &P->schema, buf, &bufsiz)) {
     436                 :          0 :         return (int)bufsiz;
     437                 :            :     }
     438                 :            :     return -1;
     439                 :            : }
     440                 :            : 
     441                 :          0 : void *flatcc_generate_binary_schema(flatcc_context_t ctx, size_t *size)
     442                 :            : {
     443                 :            :     fb_parser_t *P = ctx;
     444                 :            : 
     445                 :          0 :     return fb_codegen_bfbs_alloc_buffer(&P->opts, &P->schema, size);
     446                 :            : }
     447                 :            : #endif
     448                 :            : 
     449                 :         16 : int flatcc_generate_files(flatcc_context_t ctx)
     450                 :            : {
     451                 :            :     fb_parser_t *P = ctx, *P_leaf;
     452                 :            :     fb_output_t *out, output;
     453                 :            :     int ret = 0;
     454                 :            :     out = &output;
     455                 :            : 
     456 [ +  - ][ +  - ]:         16 :     if (!P || P->failed) {
     457                 :            :         return -1;
     458                 :            :     }
     459                 :            :     P_leaf = 0;
     460         [ +  + ]:         50 :     while (P) {
     461                 :         34 :         P->inverse_dependencies = P_leaf;
     462                 :            :         P_leaf = P;
     463                 :         34 :         P = P->dependencies;
     464                 :            :     }
     465                 :            :     P = ctx;
     466                 :            : #if FLATCC_REFLECTION
     467         [ +  + ]:         16 :     if (P->opts.bgen_bfbs) {
     468         [ +  - ]:          2 :         if (fb_codegen_bfbs_to_file(&P->opts, &P->schema)) {
     469                 :            :             return -1;
     470                 :            :         }
     471                 :            :     }
     472                 :            : #endif
     473                 :            : 
     474         [ +  - ]:         16 :     if (fb_init_output_c(out, &P->opts)) {
     475                 :            :         return -1;
     476                 :            :     }
     477                 :            :     /* This does not require a parse first. */
     478 [ +  + ][ +  - ]:         16 :     if (!P->opts.gen_append && (ret = fb_codegen_common_c(out))) {
     479                 :            :         goto done;
     480                 :            :     }
     481                 :            :     /* If no file parsed - just common files if at all. */
     482         [ +  - ]:         16 :     if (!P->has_schema) {
     483                 :            :         goto done;
     484                 :            :     }
     485         [ +  + ]:         16 :     if (!P->opts.cgen_recursive) {
     486                 :          9 :         ret = fb_codegen_c(out, &P->schema);
     487                 :          9 :         goto done;
     488                 :            :     }
     489                 :            :     /* Make sure stdout and outfile output is generated in the right order. */
     490                 :            :     P = P_leaf;
     491         [ +  + ]:         24 :     while (!ret && P) {
     492 [ +  - ][ -  + ]:         17 :         ret = P->failed || fb_codegen_c(out, &P->schema);
     493                 :         17 :         P = P->inverse_dependencies;
     494                 :            :     }
     495                 :            : done:
     496                 :         16 :     fb_end_output_c(out);
     497                 :         16 :     return ret;
     498                 :            : }
     499                 :            : 
     500                 :         48 : void flatcc_destroy_context(flatcc_context_t ctx)
     501                 :            : {
     502                 :            :     fb_parser_t *P = ctx, *dep = 0;
     503                 :            : 
     504         [ +  + ]:        114 :     while (P) {
     505                 :         66 :         dep = P->dependencies;
     506                 :         66 :         fb_clear_parser(P);
     507                 :         66 :         free(P);
     508                 :            :         P = dep;
     509                 :            :     }
     510                 :         48 : }

Generated by: LCOV version 1.12