LCOV - code coverage report
Current view: top level - src/compiler - codegen_c.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 125 139 89.9 %
Date: 2016-11-30 13:12:14 Functions: 10 10 100.0 %
Branches: 67 92 72.8 %

           Branch data     Line data    Source code
       1                 :            : #include "codegen_c.h"
       2                 :            : #include "fileio.h"
       3                 :            : #include "pstrutil.h"
       4                 :            : #include "../../external/hash/str_set.h"
       5                 :            : 
       6                 :         97 : int fb_open_output_file(fb_output_t *out, const char *name, size_t len, const char *ext)
       7                 :            : {
       8                 :            :     char *path;
       9                 :            :     int ret;
      10         [ +  + ]:         97 :     const char *prefix = out->opts->outpath ? out->opts->outpath : "";
      11                 :         97 :     size_t prefix_len = strlen(prefix);
      12                 :            : 
      13         [ +  + ]:         97 :     if (out->fp) {
      14                 :            :         return 0;
      15                 :            :     }
      16                 :         60 :     checkmem((path = fb_create_join_path_n(prefix, prefix_len, name, len, ext, 1)));
      17                 :         60 :     out->fp = fopen(path, "wb");
      18                 :            :     ret = 0;
      19         [ -  + ]:         60 :     if (!out->fp) {
      20                 :          0 :         fprintf(stderr, "error opening file for write: %s\n", path);
      21                 :            :         ret = -1;
      22                 :            :     }
      23                 :         60 :     free(path);
      24                 :         60 :     return ret;
      25                 :            : }
      26                 :            : 
      27                 :         97 : void fb_close_output_file(fb_output_t *out)
      28                 :            : {
      29                 :            :     /* Concatenate covers either stdout or a file. */
      30 [ +  + ][ +  + ]:         97 :     if (!out->opts->gen_outfile && !out->opts->gen_stdout && out->fp) {
                 [ +  - ]
      31                 :         60 :         fclose(out->fp);
      32                 :         60 :         out->fp = 0;
      33                 :            :     }
      34                 :            :     /* Keep out->fp open for next file. */
      35                 :         97 : }
      36                 :            : 
      37                 :         16 : void fb_end_output_c(fb_output_t *out)
      38                 :            : {
      39 [ +  + ][ +  + ]:         16 :     if (out->fp != stdout && out->fp) {
      40                 :          3 :         fclose(out->fp);
      41                 :            :     }
      42                 :         16 :     out->fp = 0;
      43                 :         16 : }
      44                 :            : 
      45                 :            : /*
      46                 :            :  * If used with --stdout or concat=<file>, we assume there
      47                 :            :  * are no other language outputs at the same time.
      48                 :            :  */
      49                 :         16 : int fb_init_output_c(fb_output_t *out, fb_options_t *opts)
      50                 :            : {
      51                 :            :     const char *nsc;
      52                 :            :     char *path = 0;
      53                 :            :     size_t n;
      54         [ +  + ]:         16 :     const char *mode = opts->gen_append ? "ab" : "wb";
      55         [ +  + ]:         16 :     const char *prefix = opts->outpath ? opts->outpath : "";
      56                 :            :     int ret = -1;
      57                 :            : 
      58                 :         16 :     memset(out, 0, sizeof(*out));
      59                 :         16 :     out->opts = opts;
      60                 :         16 :     nsc = opts->nsc;
      61         [ -  + ]:         16 :     if (nsc) {
      62                 :          0 :         n = strlen(opts->nsc);
      63         [ #  # ]:          0 :         if (n > FLATCC_NAMESPACE_MAX) {
      64                 :          0 :             fprintf(stderr, "common namespace argument is limited to %i characters\n", (int)FLATCC_NAMESPACE_MAX);
      65                 :          0 :             return -1;
      66                 :            :         }
      67                 :            :     } else {
      68                 :            :         nsc = FLATCC_DEFAULT_NAMESPACE_COMMON;
      69                 :            :         n = strlen(nsc);
      70                 :            :     }
      71                 :         16 :     strncpy(out->nsc, nsc, FLATCC_NAMESPACE_MAX);
      72                 :         16 :     out->nsc[FLATCC_NAMESPACE_MAX] = '\0';
      73         [ +  - ]:         16 :     if (n) {
      74                 :         16 :         out->nsc[n] = '_';
      75                 :         16 :         out->nsc[n + 1] = '\0';
      76                 :            :     }
      77                 :         16 :     pstrcpyupper(out->nscup, out->nsc);
      78                 :         16 :     out->nscup[n] = '\0'; /* No trailing _ */
      79                 :         16 :     out->spacing = opts->cgen_spacing;
      80         [ +  + ]:         16 :     if (opts->gen_stdout) {
      81                 :          5 :         out->fp = stdout;
      82                 :          5 :         return 0;
      83                 :            :     }
      84         [ +  + ]:         11 :     if (!out->opts->gen_outfile) {
      85                 :            :         /* Normal operation to multiple header filers. */
      86                 :            :         return 0;
      87                 :            :     }
      88                 :          3 :     checkmem((path = fb_create_join_path(prefix, out->opts->gen_outfile, "", 1)));
      89                 :          3 :     out->fp = fopen(path, mode);
      90         [ -  + ]:          3 :     if (!out->fp) {
      91                 :          0 :         fprintf(stderr, "error opening file for write: %s\n", path);
      92                 :            :         ret = -1;
      93                 :          0 :         goto done;
      94                 :            :     }
      95                 :            :     ret = 0;
      96                 :            : done:
      97         [ +  - ]:          3 :     if (path) {
      98                 :          3 :         free(path);
      99                 :            :     }
     100                 :            :     return ret;
     101                 :            : }
     102                 :            : 
     103                 :        123 : static void _str_set_destructor(void *context, char *item)
     104                 :            : {
     105                 :            :     (void)context;
     106                 :            : 
     107                 :        123 :     free(item);
     108                 :        123 : }
     109                 :            : 
     110                 :            : /*
     111                 :            :  * Removal of duplicate inclusions is only for a cleaner output - it is
     112                 :            :  * not stricly necessary because the preprocessor handles include
     113                 :            :  * guards. The guards are required to deal with concatenated files
     114                 :            :  * regardless unless we generate special code for concatenation.
     115                 :            :  */
     116                 :         77 : void fb_gen_c_includes(fb_output_t *out, const char *ext, const char *extup)
     117                 :            : {
     118                 :         77 :     fb_include_t *inc = out->S->includes;
     119                 :            :     char *basename, *basenameup, *s;
     120                 :            :     str_set_t set;
     121                 :            : 
     122                 :         77 :     fb_clear(set);
     123                 :            : 
     124                 :            :     /* Don't include our own file. */
     125                 :         77 :     str_set_insert_item(&set, fb_copy_path(out->S->basenameup), ht_keep);
     126         [ +  + ]:        192 :     while (inc) {
     127                 :        115 :         checkmem((basename = fb_create_basename(
     128                 :        345 :                     inc->name.s.s, inc->name.s.len, out->opts->default_schema_ext)));
     129                 :        115 :         inc = inc->link;
     130                 :        115 :         checkmem((basenameup = fb_copy_path(basename)));
     131                 :            :         s = basenameup;
     132         [ +  + ]:       1610 :         while (*s) {
     133                 :       1495 :             *s = toupper(*s);
     134                 :       1495 :             ++s;
     135                 :            :         }
     136         [ +  + ]:        115 :         if (str_set_insert_item(&set, basenameup, ht_keep)) {
     137                 :         69 :             free(basenameup);
     138                 :         69 :             free(basename);
     139                 :         69 :             continue;
     140                 :            :         }
     141                 :            :         /* The include guard is needed when concatening output. */
     142                 :         46 :         fprintf(out->fp,
     143                 :            :             "#ifndef %s%s\n"
     144                 :            :             "#include \"%s%s\"\n"
     145                 :            :             "#endif\n",
     146                 :            :             basenameup, extup, basename, ext);
     147                 :        115 :         free(basename);
     148                 :            :         /* `basenameup` stored in str_set. */
     149                 :            :     }
     150                 :         77 :     str_set_destroy(&set, _str_set_destructor, 0);
     151                 :         77 : }
     152                 :            : 
     153                 :       1852 : int fb_copy_scope(fb_scope_t *scope, char *buf)
     154                 :            : {
     155                 :            :     size_t n, len;
     156                 :            :     fb_ref_t *name;
     157                 :            : 
     158                 :       1852 :     len = scope->prefix.len;
     159         [ +  + ]:       5207 :     for (name = scope->name; name; name = name->link) {
     160                 :       3355 :         n = name->ident->len;
     161                 :       3355 :         len += n + 1;
     162                 :            :     }
     163         [ -  + ]:       1852 :     if (len > FLATCC_NAMESPACE_MAX + 1) {
     164                 :          0 :         buf[0] = '\0';
     165                 :          0 :         return -1;
     166                 :            :     }
     167                 :            :     len = scope->prefix.len;
     168                 :       1852 :     memcpy(buf, scope->prefix.s, len);
     169         [ +  + ]:       5207 :     for (name = scope->name; name; name = name->link) {
     170                 :       3355 :         n = name->ident->len;
     171                 :       3355 :         memcpy(buf + len, name->ident->text, n);
     172                 :       3355 :         len += n + 1;
     173                 :       3355 :         buf[len - 1] = '_';
     174                 :            :     }
     175                 :       1852 :     buf[len] = '\0';
     176                 :       1852 :     return (int)len;
     177                 :            : }
     178                 :            : 
     179                 :       1785 : void fb_scoped_symbol_name(fb_scope_t *scope, fb_symbol_t *sym, fb_scoped_name_t *sn)
     180                 :            : {
     181                 :       1785 :     fb_token_t *t = sym->ident;
     182                 :            : 
     183         [ +  - ]:       1785 :     if (sn->scope != scope) {
     184         [ -  + ]:       1785 :         if (0 > (sn->scope_len = fb_copy_scope(scope, sn->text))) {
     185                 :          0 :             sn->scope_len = 0;
     186                 :          0 :             fprintf(stderr, "skipping too long namespace\n");
     187                 :            :         }
     188                 :            :     }
     189                 :       1785 :     sn->len = t->len;
     190                 :       1785 :     sn->total_len = sn->scope_len + sn->len;
     191         [ -  + ]:       1785 :     if (sn->total_len > FLATCC_NAME_BUFSIZ - 1) {
     192                 :          0 :         fprintf(stderr, "warning: truncating identifier: %.*s\n", sn->len, t->text);
     193                 :          0 :         sn->len = FLATCC_NAME_BUFSIZ - sn->scope_len - 1;
     194                 :          0 :         sn->total_len = sn->scope_len + sn->len;
     195                 :            :     }
     196                 :       1785 :     memcpy(sn->text + sn->scope_len, t->text, sn->len);
     197                 :       1785 :     sn->text[sn->total_len] = '\0';
     198                 :       1785 : }
     199                 :            : 
     200                 :         12 : int fb_codegen_common_c(fb_output_t *out)
     201                 :            : {
     202                 :            :     size_t nsc_len;
     203                 :            :     int ret;
     204                 :            : 
     205                 :         12 :     nsc_len = strlen(out->nsc) - 1;
     206                 :            :     ret = 0;
     207         [ +  + ]:         12 :     if (out->opts->cgen_common_reader) {
     208         [ +  - ]:         10 :         if (fb_open_output_file(out, out->nsc, nsc_len, "_common_reader.h")) {
     209                 :            :             return -1;
     210                 :            :         }
     211                 :         10 :         ret = fb_gen_common_c_header(out);
     212                 :         10 :         fb_close_output_file(out);
     213                 :            :     }
     214 [ +  - ][ +  + ]:         12 :     if (!ret && out->opts->cgen_common_builder) {
     215         [ +  - ]:         10 :         if (fb_open_output_file(out, out->nsc, nsc_len, "_common_builder.h")) {
     216                 :            :             return -1;
     217                 :            :         }
     218                 :         10 :         fb_gen_common_c_builder_header(out);
     219                 :         10 :         fb_close_output_file(out);
     220                 :            :     }
     221                 :            :     return ret;
     222                 :            : }
     223                 :            : 
     224                 :         26 : int fb_codegen_c(fb_output_t *out, fb_schema_t *S)
     225                 :            : {
     226                 :            :     size_t basename_len;
     227                 :            :     /* OK if no files were processed. */
     228                 :            :     int ret = 0;
     229                 :            : 
     230                 :         26 :     out->S = S;
     231                 :         26 :     out->current_scope = fb_scope_table_find(&S->root_schema->scope_index, 0, 0);
     232                 :         26 :     basename_len = strlen(out->S->basename);
     233         [ +  + ]:         26 :     if (out->opts->cgen_reader) {
     234         [ +  - ]:         24 :         if (fb_open_output_file(out, out->S->basename, basename_len, "_reader.h")) {
     235                 :            :             ret = -1;
     236                 :            :             goto done;
     237                 :            :         }
     238         [ +  - ]:         24 :         if ((ret = fb_gen_c_reader(out))) {
     239                 :            :             goto done;
     240                 :            :         }
     241                 :         24 :         fb_close_output_file(out);
     242                 :            :     }
     243         [ +  + ]:         26 :     if (out->opts->cgen_builder) {
     244         [ +  - ]:         24 :         if (fb_open_output_file(out, out->S->basename, basename_len, "_builder.h")) {
     245                 :            :             ret = -1;
     246                 :            :             goto done;
     247                 :            :         }
     248         [ +  - ]:         24 :         if ((ret = fb_gen_c_builder(out))) {
     249                 :            :                     goto done;
     250                 :            :         }
     251                 :         24 :         fb_close_output_file(out);
     252                 :            :     }
     253         [ +  + ]:         26 :     if (out->opts->cgen_verifier) {
     254         [ +  - ]:         23 :         if (fb_open_output_file(out, out->S->basename, basename_len, "_verifier.h")) {
     255                 :            :             ret = -1;
     256                 :            :             goto done;
     257                 :            :         }
     258         [ +  - ]:         23 :         if ((ret = fb_gen_c_verifier(out))) {
     259                 :            :             goto done;
     260                 :            :         }
     261                 :         23 :         fb_close_output_file(out);
     262                 :            :     }
     263         [ +  + ]:         26 :     if (out->opts->cgen_json_parser) {
     264         [ +  - ]:          3 :         if (fb_open_output_file(out, out->S->basename, basename_len, "_json_parser.h")) {
     265                 :            :             ret = -1;
     266                 :            :             goto done;
     267                 :            :         }
     268         [ +  - ]:          3 :         if ((ret = fb_gen_c_json_parser(out))) {
     269                 :            :             goto done;
     270                 :            :         }
     271                 :          3 :         fb_close_output_file(out);
     272                 :            :     }
     273         [ +  + ]:         26 :     if (out->opts->cgen_json_printer) {
     274         [ +  - ]:          3 :         if (fb_open_output_file(out, out->S->basename, basename_len, "_json_printer.h")) {
     275                 :            :             ret = -1;
     276                 :            :             goto done;
     277                 :            :         }
     278         [ +  - ]:          3 :         if ((ret = fb_gen_c_json_printer(out))) {
     279                 :            :             goto done;
     280                 :            :         }
     281                 :          3 :         fb_close_output_file(out);
     282                 :            :     }
     283                 :            : done:
     284                 :         26 :     return ret;
     285                 :            : }

Generated by: LCOV version 1.12