LCOV - code coverage report
Current view: top level - ccache - conf.c (source / functions) Hit Total Coverage
Test: ccache.lcov.info Lines: 324 345 93.9 %
Date: 2015-06-29 Functions: 20 20 100.0 %
Branches: 126 146 86.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2011-2014 Joel Rosdahl
       3                 :            :  *
       4                 :            :  * This program is free software; you can redistribute it and/or modify it
       5                 :            :  * under the terms of the GNU General Public License as published by the Free
       6                 :            :  * Software Foundation; either version 3 of the License, or (at your option)
       7                 :            :  * any later version.
       8                 :            :  *
       9                 :            :  * This program is distributed in the hope that it will be useful, but WITHOUT
      10                 :            :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      11                 :            :  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
      12                 :            :  * more details.
      13                 :            :  *
      14                 :            :  * You should have received a copy of the GNU General Public License along with
      15                 :            :  * this program; if not, write to the Free Software Foundation, Inc., 51
      16                 :            :  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      17                 :            :  */
      18                 :            : 
      19                 :            : #include "conf.h"
      20                 :            : #include "ccache.h"
      21                 :            : 
      22                 :            : typedef bool (*conf_item_parser)(const char *str, void *result, char **errmsg);
      23                 :            : typedef bool (*conf_item_verifier)(void *value, char **errmsg);
      24                 :            : 
      25                 :            : struct conf_item {
      26                 :            :         const char *name;
      27                 :            :         size_t number;
      28                 :            :         conf_item_parser parser;
      29                 :            :         size_t offset;
      30                 :            :         conf_item_verifier verifier;
      31                 :            : };
      32                 :            : 
      33                 :            : struct env_to_conf_item {
      34                 :            :         const char *env_name;
      35                 :            :         const char *conf_name;
      36                 :            : };
      37                 :            : 
      38                 :            : static bool
      39                 :         13 : parse_bool(const char *str, void *result, char **errmsg)
      40                 :            : {
      41                 :         13 :         bool *value = (bool *)result;
      42                 :            : 
      43         [ +  + ]:         13 :         if (str_eq(str, "true")) {
      44                 :          9 :                 *value = true;
      45                 :          9 :                 return true;
      46         [ +  + ]:          4 :         } else if (str_eq(str, "false")) {
      47                 :          2 :                 *value = false;
      48                 :          2 :                 return true;
      49                 :            :         } else {
      50                 :          2 :                 *errmsg = format("not a boolean value: \"%s\"", str);
      51                 :         13 :                 return false;
      52                 :            :         }
      53                 :            : }
      54                 :            : 
      55                 :            : static bool
      56                 :         25 : parse_env_string(const char *str, void *result, char **errmsg)
      57                 :            : {
      58                 :         25 :         char **value = (char **)result;
      59                 :         25 :         free(*value);
      60                 :         25 :         *value = subst_env_in_string(str, errmsg);
      61                 :         25 :         return *value;
      62                 :            : }
      63                 :            : 
      64                 :            : static bool
      65                 :          2 : parse_size(const char *str, void *result, char **errmsg)
      66                 :            : {
      67                 :          2 :         uint64_t *value = (uint64_t *)result;
      68                 :            :         uint64_t size;
      69                 :          2 :         *errmsg = NULL;
      70         [ +  + ]:          2 :         if (parse_size_with_suffix(str, &size)) {
      71                 :          1 :                 *value = size;
      72                 :          1 :                 return true;
      73                 :            :         } else {
      74                 :          1 :                 *errmsg = format("invalid size: \"%s\"", str);
      75                 :          2 :                 return false;
      76                 :            :         }
      77                 :            : }
      78                 :            : 
      79                 :            : static bool
      80                 :          9 : parse_sloppiness(const char *str, void *result, char **errmsg)
      81                 :            : {
      82                 :          9 :         unsigned *value = (unsigned *)result;
      83                 :          9 :         char *word, *p, *q, *saveptr = NULL;
      84                 :            : 
      85         [ -  + ]:          9 :         if (!str) {
      86                 :          0 :                 return *value;
      87                 :            :         }
      88                 :          9 :         p = x_strdup(str);
      89                 :          9 :         q = p;
      90         [ +  + ]:         23 :         while ((word = strtok_r(q, ", ", &saveptr))) {
      91         [ +  + ]:         15 :                 if (str_eq(word, "file_macro")) {
      92                 :          2 :                         *value |= SLOPPY_FILE_MACRO;
      93         [ +  + ]:         13 :                 } else if (str_eq(word, "file_stat_matches")) {
      94                 :          1 :                         *value |= SLOPPY_FILE_STAT_MATCHES;
      95         [ +  + ]:         12 :                 } else if (str_eq(word, "include_file_ctime")) {
      96                 :          8 :                         *value |= SLOPPY_INCLUDE_FILE_CTIME;
      97         [ +  + ]:          4 :                 } else if (str_eq(word, "include_file_mtime")) {
      98                 :          1 :                         *value |= SLOPPY_INCLUDE_FILE_MTIME;
      99         [ +  + ]:          3 :                 } else if (str_eq(word, "pch_defines")) {
     100                 :          1 :                         *value |= SLOPPY_PCH_DEFINES;
     101         [ +  + ]:          2 :                 } else if (str_eq(word, "time_macros")) {
     102                 :          1 :                         *value |= SLOPPY_TIME_MACROS;
     103                 :            :                 } else {
     104                 :          1 :                         *errmsg = format("unknown sloppiness: \"%s\"", word);
     105                 :          1 :                         free(p);
     106                 :          1 :                         return false;
     107                 :            :                 }
     108                 :         14 :                 q = NULL;
     109                 :            :         }
     110                 :          8 :         free(p);
     111                 :          9 :         return true;
     112                 :            : }
     113                 :            : 
     114                 :            : static bool
     115                 :          3 : parse_string(const char *str, void *result, char **errmsg)
     116                 :            : {
     117                 :          3 :         char **value = (char **)result;
     118                 :            :         (void)errmsg;
     119                 :          3 :         free(*value);
     120                 :          3 :         *value = x_strdup(str);
     121                 :          3 :         return true;
     122                 :            : }
     123                 :            : 
     124                 :            : static bool
     125                 :          2 : parse_umask(const char *str, void *result, char **errmsg)
     126                 :            : {
     127                 :          2 :         unsigned *value = (unsigned *)result;
     128                 :            :         char *endptr;
     129         [ +  + ]:          2 :         if (str_eq(str, "")) {
     130                 :          1 :                 *value = UINT_MAX;
     131                 :          1 :                 return true;
     132                 :            :         }
     133                 :          1 :         errno = 0;
     134                 :          1 :         *value = strtoul(str, &endptr, 8);
     135 [ +  - ][ +  - ]:          1 :         if (errno == 0 && *str != '\0' && *endptr == '\0') {
                 [ +  - ]
     136                 :          1 :                 return true;
     137                 :            :         } else {
     138                 :          0 :                 *errmsg = format("not an octal integer: \"%s\"", str);
     139                 :          2 :                 return false;
     140                 :            :         }
     141                 :            : }
     142                 :            : 
     143                 :            : static bool
     144                 :          8 : parse_unsigned(const char *str, void *result, char **errmsg)
     145                 :            : {
     146                 :          8 :         unsigned *value = (unsigned *)result;
     147                 :            :         long x;
     148                 :            :         char *endptr;
     149                 :          8 :         errno = 0;
     150                 :          8 :         x = strtol(str, &endptr, 10);
     151 [ +  - ][ +  + ]:          8 :         if (errno == 0 && x >= 0 && *str != '\0' && *endptr == '\0') {
         [ +  + ][ +  + ]
     152                 :          5 :                 *value = x;
     153                 :          5 :                 return true;
     154                 :            :         } else {
     155                 :          3 :                 *errmsg = format("invalid unsigned integer: \"%s\"", str);
     156                 :          8 :                 return false;
     157                 :            :         }
     158                 :            : }
     159                 :            : 
     160                 :            : static const char*
     161                 :         22 : bool_to_string(bool value)
     162                 :            : {
     163         [ +  + ]:         22 :         return value ? "true" : "false";
     164                 :            : }
     165                 :            : 
     166                 :            : static bool
     167                 :          3 : verify_absolute_path(void *value, char **errmsg)
     168                 :            : {
     169                 :          3 :         char **path = (char **)value;
     170         [ -  + ]:          3 :         assert(*path);
     171         [ +  + ]:          3 :         if (str_eq(*path, "")) {
     172                 :            :                 /* The empty string means "disable" in this case. */
     173                 :          1 :                 return true;
     174         [ +  + ]:          2 :         } else if (is_absolute_path(*path)) {
     175                 :          1 :                 return true;
     176                 :            :         } else {
     177                 :          1 :                 *errmsg = format("not an absolute path: \"%s\"", *path);
     178                 :          3 :                 return false;
     179                 :            :         }
     180                 :            : }
     181                 :            : 
     182                 :            : static bool
     183                 :          3 : verify_dir_levels(void *value, char **errmsg)
     184                 :            : {
     185                 :          3 :         unsigned *levels = (unsigned *)value;
     186         [ -  + ]:          3 :         assert(levels);
     187 [ +  + ][ +  + ]:          3 :         if (*levels >= 1 && *levels <= 8) {
     188                 :          1 :                 return true;
     189                 :            :         } else {
     190                 :          2 :                 *errmsg = format("cache directory levels must be between 1 and 8");
     191                 :          3 :                 return false;
     192                 :            :         }
     193                 :            : }
     194                 :            : 
     195                 :            : #define ITEM(name, type) \
     196                 :            :         parse_##type, offsetof(struct conf, name), NULL
     197                 :            : #define ITEM_V(name, type, verification) \
     198                 :            :         parse_##type, offsetof(struct conf, name), verify_##verification
     199                 :            : 
     200                 :            : #include "confitems_lookup.c"
     201                 :            : #include "envtoconfitems_lookup.c"
     202                 :            : 
     203                 :            : static const struct conf_item *
     204                 :        130 : find_conf(const char *name)
     205                 :            : {
     206                 :        130 :         return confitems_get(name, strlen(name));
     207                 :            : }
     208                 :            : 
     209                 :            : static const struct env_to_conf_item *
     210                 :         41 : find_env_to_conf(const char *name)
     211                 :            : {
     212                 :         41 :         return envtoconfitems_get(name, strlen(name));
     213                 :            : }
     214                 :            : 
     215                 :            : static bool
     216                 :         74 : handle_conf_setting(struct conf *conf, const char *key, const char *value,
     217                 :            :                     char **errmsg, bool from_env_variable, bool negate_boolean,
     218                 :            :                     const char *origin)
     219                 :            : {
     220                 :            :         const struct conf_item *item;
     221                 :            : 
     222                 :         74 :         item = find_conf(key);
     223         [ +  + ]:         74 :         if (!item) {
     224                 :          1 :                 *errmsg = format("unknown configuration option \"%s\"", key);
     225                 :          1 :                 return false;
     226                 :            :         }
     227                 :            : 
     228 [ +  + ][ +  + ]:         73 :         if (from_env_variable && item->parser == parse_bool) {
     229                 :            :                 /*
     230                 :            :                  * Special rule for boolean settings from the environment: any value means
     231                 :            :                  * true.
     232                 :            :                  */
     233                 :         11 :                 bool *value = (bool *)((char *)conf + item->offset);
     234                 :         11 :                 *value = !negate_boolean;
     235                 :         11 :                 goto out;
     236                 :            :         }
     237                 :            : 
     238         [ +  + ]:         62 :         if (!item->parser(value, (char *)conf + item->offset, errmsg)) {
     239                 :          8 :                 return false;
     240                 :            :         }
     241 [ +  + ][ +  + ]:         54 :         if (item->verifier && !item->verifier((char *)conf + item->offset, errmsg)) {
     242                 :          3 :                 return false;
     243                 :            :         }
     244                 :            : 
     245                 :            : out:
     246                 :         62 :         conf->item_origins[item->number] = origin;
     247                 :         74 :         return true;
     248                 :            : }
     249                 :            : 
     250                 :            : static bool
     251                 :         50 : parse_line(const char *line, char **key, char **value, char **errmsg)
     252                 :            : {
     253                 :            :         const char *p, *q;
     254                 :            : 
     255                 :            : #define SKIP_WS(x) while (isspace(*x)) { ++x; }
     256                 :            : 
     257                 :         50 :         *key = NULL;
     258                 :         50 :         *value = NULL;
     259                 :            : 
     260                 :         50 :         p = line;
     261         [ +  + ]:         57 :         SKIP_WS(p);
     262 [ +  + ][ +  + ]:         50 :         if (*p == '\0' || *p == '#') {
     263                 :          4 :                 return true;
     264                 :            :         }
     265                 :         46 :         q = p;
     266 [ +  + ][ +  + ]:        470 :         while (isalpha(*q) || *q == '_') {
     267                 :        424 :                 ++q;
     268                 :            :         }
     269                 :         46 :         *key = x_strndup(p, q - p);
     270                 :         46 :         p = q;
     271         [ +  + ]:         87 :         SKIP_WS(p);
     272         [ +  + ]:         46 :         if (*p != '=') {
     273                 :          1 :                 *errmsg = x_strdup("missing equal sign");
     274                 :          1 :                 free(*key);
     275                 :          1 :                 *key = NULL;
     276                 :          1 :                 return false;
     277                 :            :         }
     278                 :         45 :         ++p;
     279                 :            : 
     280                 :            :         /* Skip leading whitespace. */
     281         [ +  + ]:         90 :         SKIP_WS(p);
     282                 :         45 :         q = p;
     283         [ +  + ]:        404 :         while (*q) {
     284                 :        359 :                 ++q;
     285                 :            :         }
     286                 :            :         /* Skip trailing whitespace. */
     287         [ +  + ]:         80 :         while (isspace(q[-1])) {
     288                 :         35 :                 --q;
     289                 :            :         }
     290                 :         45 :         *value = x_strndup(p, q - p);
     291                 :            : 
     292                 :         50 :         return true;
     293                 :            : 
     294                 :            : #undef SKIP_WS
     295                 :            : }
     296                 :            : 
     297                 :            : /* Create a conf struct with default values. */
     298                 :            : struct conf *
     299                 :        108 : conf_create(void)
     300                 :            : {
     301                 :            :         size_t i;
     302                 :        108 :         struct conf *conf = x_malloc(sizeof(*conf));
     303                 :        108 :         conf->base_dir = x_strdup("");
     304                 :        108 :         conf->cache_dir = format("%s/.ccache", get_home_directory());
     305                 :        108 :         conf->cache_dir_levels = 2;
     306                 :        108 :         conf->compiler = x_strdup("");
     307                 :        108 :         conf->compiler_check = x_strdup("mtime");
     308                 :        108 :         conf->compression = false;
     309                 :        108 :         conf->compression_level = 6;
     310                 :        108 :         conf->cpp_extension = x_strdup("");
     311                 :        108 :         conf->direct_mode = true;
     312                 :        108 :         conf->disable = false;
     313                 :        108 :         conf->extra_files_to_hash = x_strdup("");
     314                 :        108 :         conf->hard_link = false;
     315                 :        108 :         conf->hash_dir = false;
     316                 :        108 :         conf->log_file = x_strdup("");
     317                 :        108 :         conf->max_files = 0;
     318                 :        108 :         conf->max_size = (uint64_t)5 * 1000 * 1000 * 1000;
     319                 :        108 :         conf->path = x_strdup("");
     320                 :        108 :         conf->prefix_command = x_strdup("");
     321                 :        108 :         conf->read_only = false;
     322                 :        108 :         conf->read_only_direct = false;
     323                 :        108 :         conf->recache = false;
     324                 :        108 :         conf->run_second_cpp = false;
     325                 :        108 :         conf->sloppiness = 0;
     326                 :        108 :         conf->stats = true;
     327                 :        108 :         conf->temporary_dir = x_strdup("");
     328                 :        108 :         conf->umask = UINT_MAX; /* default: don't set umask */
     329                 :        108 :         conf->unify = false;
     330                 :        108 :         conf->item_origins = x_malloc(CONFITEMS_TOTAL_KEYWORDS * sizeof(char *));
     331         [ +  + ]:       3024 :         for (i = 0; i < CONFITEMS_TOTAL_KEYWORDS; ++i) {
     332                 :       2916 :                 conf->item_origins[i] = "default";
     333                 :            :         }
     334                 :        108 :         return conf;
     335                 :            : }
     336                 :            : 
     337                 :            : void
     338                 :        108 : conf_free(struct conf *conf)
     339                 :            : {
     340         [ +  + ]:        108 :         if (!conf) {
     341                 :          8 :                 return;
     342                 :            :         }
     343                 :        100 :         free(conf->base_dir);
     344                 :        100 :         free(conf->cache_dir);
     345                 :        100 :         free(conf->compiler);
     346                 :        100 :         free(conf->compiler_check);
     347                 :        100 :         free(conf->cpp_extension);
     348                 :        100 :         free(conf->extra_files_to_hash);
     349                 :        100 :         free(conf->log_file);
     350                 :        100 :         free(conf->path);
     351                 :        100 :         free(conf->prefix_command);
     352                 :        100 :         free(conf->temporary_dir);
     353                 :        100 :         free(conf->item_origins);
     354                 :        108 :         free(conf);
     355                 :            : }
     356                 :            : 
     357                 :            : /* Note: The path pointer is stored in conf, so path must outlive conf. */
     358                 :            : bool
     359                 :         23 : conf_read(struct conf *conf, const char *path, char **errmsg)
     360                 :            : {
     361                 :            :         FILE *f;
     362                 :            :         char buf[10000];
     363                 :         23 :         bool result = true;
     364                 :            :         unsigned line_number;
     365                 :            : 
     366         [ -  + ]:         23 :         assert(errmsg);
     367                 :         23 :         *errmsg = NULL;
     368                 :            : 
     369                 :         23 :         f = fopen(path, "r");
     370         [ -  + ]:         23 :         if (!f) {
     371                 :          0 :                 *errmsg = format("%s: %s", path, strerror(errno));
     372                 :          0 :                 return false;
     373                 :            :         }
     374                 :            : 
     375                 :         23 :         line_number = 0;
     376         [ +  + ]:         57 :         while (fgets(buf, sizeof(buf), f)) {
     377                 :            :                 char *errmsg2, *key, *value;
     378                 :            :                 bool ok;
     379                 :         47 :                 ++line_number;
     380                 :         47 :                 ok = parse_line(buf, &key, &value, &errmsg2);
     381 [ +  + ][ +  + ]:         47 :                 if (ok && key) { /* key == NULL if comment or blank line */
     382                 :         42 :                         ok = handle_conf_setting(conf, key, value, &errmsg2, false, false, path);
     383                 :            :                 }
     384                 :         47 :                 free(key);
     385                 :         47 :                 free(value);
     386         [ +  + ]:         47 :                 if (!ok) {
     387                 :         13 :                         *errmsg = format("%s:%u: %s", path, line_number, errmsg2);
     388                 :         13 :                         free(errmsg2);
     389                 :         13 :                         result = false;
     390                 :         13 :                         goto out;
     391                 :            :                 }
     392                 :            :         }
     393         [ -  + ]:         10 :         if (ferror(f)) {
     394                 :          0 :                 *errmsg = x_strdup(strerror(errno));
     395                 :          0 :                 result = false;
     396                 :            :         }
     397                 :            : 
     398                 :            : out:
     399                 :         23 :         fclose(f);
     400                 :         23 :         return result;
     401                 :            : }
     402                 :            : 
     403                 :            : bool
     404                 :          9 : conf_update_from_environment(struct conf *conf, char **errmsg)
     405                 :            : {
     406                 :            :         char **p;
     407                 :            :         char *q;
     408                 :            :         char *key;
     409                 :            :         char *errmsg2;
     410                 :            :         const struct env_to_conf_item *env_to_conf_item;
     411                 :            :         bool negate;
     412                 :            :         size_t key_start;
     413                 :            : 
     414         [ +  + ]:        282 :         for (p = environ; *p; ++p) {
     415         [ +  + ]:        273 :                 if (!str_startswith(*p, "CCACHE_")) {
     416                 :        232 :                         continue;
     417                 :            :                 }
     418                 :         41 :                 q = strchr(*p, '=');
     419         [ -  + ]:         41 :                 if (!q) {
     420                 :          0 :                         continue;
     421                 :            :                 }
     422                 :            : 
     423         [ +  + ]:         41 :                 if (str_startswith(*p + 7, "NO")) {
     424                 :          8 :                         negate = true;
     425                 :          8 :                         key_start = 9;
     426                 :            :                 } else {
     427                 :         33 :                         negate = false;
     428                 :         33 :                         key_start = 7;
     429                 :            :                 }
     430                 :         41 :                 key = x_strndup(*p + key_start, q - *p - key_start);
     431                 :            : 
     432                 :         41 :                 ++q; /* Now points to the value. */
     433                 :            : 
     434                 :         41 :                 env_to_conf_item = find_env_to_conf(key);
     435         [ +  + ]:         41 :                 if (!env_to_conf_item) {
     436                 :          9 :                         free(key);
     437                 :          9 :                         continue;
     438                 :            :                 }
     439                 :            : 
     440         [ -  + ]:         32 :                 if (!handle_conf_setting(
     441                 :            :                             conf, env_to_conf_item->conf_name, q, &errmsg2, true, negate,
     442                 :            :                             "environment")) {
     443                 :          0 :                         *errmsg = format("%s: %s", key, errmsg2);
     444                 :          0 :                         free(errmsg2);
     445                 :          0 :                         free(key);
     446                 :          0 :                         return false;
     447                 :            :                 }
     448                 :            : 
     449                 :         32 :                 free(key);
     450                 :            :         }
     451                 :            : 
     452                 :          9 :         return true;
     453                 :            : }
     454                 :            : 
     455                 :            : bool
     456                 :          2 : conf_set_value_in_file(const char *path, const char *key, const char *value,
     457                 :            :                        char **errmsg)
     458                 :            : {
     459                 :            :         FILE *infile, *outfile;
     460                 :            :         char *outpath;
     461                 :            :         char buf[10000];
     462                 :            :         bool found;
     463                 :            :         const struct conf_item *item;
     464                 :            : 
     465                 :          2 :         item = find_conf(key);
     466         [ -  + ]:          2 :         if (!item) {
     467                 :          0 :                 *errmsg = format("unknown configuration option \"%s\"", key);
     468                 :          0 :                 return false;
     469                 :            :         }
     470                 :            : 
     471                 :          2 :         infile = fopen(path, "r");
     472         [ -  + ]:          2 :         if (!infile) {
     473                 :          0 :                 *errmsg = format("%s: %s", path, strerror(errno));
     474                 :          0 :                 return false;
     475                 :            :         }
     476                 :            : 
     477                 :          2 :         outpath = format("%s.tmp", path);
     478                 :          2 :         outfile = create_tmp_file(&outpath, "w");
     479         [ -  + ]:          2 :         if (!outfile) {
     480                 :          0 :                 *errmsg = format("%s: %s", outpath, strerror(errno));
     481                 :          0 :                 free(outpath);
     482                 :          0 :                 fclose(infile);
     483                 :          0 :                 return false;
     484                 :            :         }
     485                 :            : 
     486                 :          2 :         found = false;
     487         [ +  + ]:          5 :         while (fgets(buf, sizeof(buf), infile)) {
     488                 :            :                 char *errmsg2, *key2, *value2;
     489                 :            :                 bool ok;
     490                 :          3 :                 ok = parse_line(buf, &key2, &value2, &errmsg2);
     491 [ +  - ][ +  - ]:          4 :                 if (ok && key2 && str_eq(key2, key)) {
                 [ +  + ]
     492                 :          1 :                         found = true;
     493                 :          1 :                         fprintf(outfile, "%s = %s\n", key, value);
     494                 :            :                 } else {
     495                 :          2 :                         fputs(buf, outfile);
     496                 :            :                 }
     497                 :          3 :                 free(key2);
     498                 :          3 :                 free(value2);
     499                 :            :         }
     500                 :            : 
     501         [ +  + ]:          2 :         if (!found) {
     502                 :          1 :                 fprintf(outfile, "%s = %s\n", key, value);
     503                 :            :         }
     504                 :            : 
     505                 :          2 :         fclose(infile);
     506                 :          2 :         fclose(outfile);
     507         [ -  + ]:          2 :         if (x_rename(outpath, path) != 0) {
     508                 :          0 :                 *errmsg = format("rename %s to %s: %s", outpath, path, strerror(errno));
     509                 :          0 :                 return false;
     510                 :            :         }
     511                 :          2 :         free(outpath);
     512                 :            : 
     513                 :          2 :         return true;
     514                 :            : }
     515                 :            : 
     516                 :            : bool
     517                 :          2 : conf_print_items(struct conf *conf,
     518                 :            :                  void (*printer)(const char *descr, const char *origin,
     519                 :            :                                  void *context),
     520                 :            :                  void *context)
     521                 :            : {
     522                 :          2 :         char *s = x_strdup("");
     523                 :            :         char *s2;
     524                 :            : 
     525                 :          2 :         reformat(&s, "base_dir = %s", conf->base_dir);
     526                 :          2 :         printer(s, conf->item_origins[find_conf("base_dir")->number], context);
     527                 :            : 
     528                 :          2 :         reformat(&s, "cache_dir = %s", conf->cache_dir);
     529                 :          2 :         printer(s, conf->item_origins[find_conf("cache_dir")->number], context);
     530                 :            : 
     531                 :          2 :         reformat(&s, "cache_dir_levels = %u", conf->cache_dir_levels);
     532                 :          2 :         printer(s, conf->item_origins[find_conf("cache_dir_levels")->number],
     533                 :            :                 context);
     534                 :            : 
     535                 :          2 :         reformat(&s, "compiler = %s", conf->compiler);
     536                 :          2 :         printer(s, conf->item_origins[find_conf("compiler")->number], context);
     537                 :            : 
     538                 :          2 :         reformat(&s, "compiler_check = %s", conf->compiler_check);
     539                 :          2 :         printer(s, conf->item_origins[find_conf("compiler_check")->number], context);
     540                 :            : 
     541                 :          2 :         reformat(&s, "compression = %s", bool_to_string(conf->compression));
     542                 :          2 :         printer(s, conf->item_origins[find_conf("compression")->number], context);
     543                 :            : 
     544                 :          2 :         reformat(&s, "compression_level = %u", conf->compression_level);
     545                 :          2 :         printer(s, conf->item_origins[find_conf("compression_level")->number],
     546                 :            :                 context);
     547                 :            : 
     548                 :          2 :         reformat(&s, "cpp_extension = %s", conf->cpp_extension);
     549                 :          2 :         printer(s, conf->item_origins[find_conf("cpp_extension")->number], context);
     550                 :            : 
     551                 :          2 :         reformat(&s, "direct_mode = %s", bool_to_string(conf->direct_mode));
     552                 :          2 :         printer(s, conf->item_origins[find_conf("direct_mode")->number], context);
     553                 :            : 
     554                 :          2 :         reformat(&s, "disable = %s", bool_to_string(conf->disable));
     555                 :          2 :         printer(s, conf->item_origins[find_conf("disable")->number], context);
     556                 :            : 
     557                 :          2 :         reformat(&s, "extra_files_to_hash = %s", conf->extra_files_to_hash);
     558                 :          2 :         printer(s, conf->item_origins[find_conf("extra_files_to_hash")->number],
     559                 :            :                 context);
     560                 :            : 
     561                 :          2 :         reformat(&s, "hard_link = %s", bool_to_string(conf->hard_link));
     562                 :          2 :         printer(s, conf->item_origins[find_conf("hard_link")->number], context);
     563                 :            : 
     564                 :          2 :         reformat(&s, "hash_dir = %s", bool_to_string(conf->hash_dir));
     565                 :          2 :         printer(s, conf->item_origins[find_conf("hash_dir")->number], context);
     566                 :            : 
     567                 :          2 :         reformat(&s, "log_file = %s", conf->log_file);
     568                 :          2 :         printer(s, conf->item_origins[find_conf("log_file")->number], context);
     569                 :            : 
     570                 :          2 :         reformat(&s, "max_files = %u", conf->max_files);
     571                 :          2 :         printer(s, conf->item_origins[find_conf("max_files")->number], context);
     572                 :            : 
     573                 :          2 :         s2 = format_parsable_size_with_suffix(conf->max_size);
     574                 :          2 :         reformat(&s, "max_size = %s", s2);
     575                 :          2 :         printer(s, conf->item_origins[find_conf("max_size")->number], context);
     576                 :          2 :         free(s2);
     577                 :            : 
     578                 :          2 :         reformat(&s, "path = %s", conf->path);
     579                 :          2 :         printer(s, conf->item_origins[find_conf("path")->number], context);
     580                 :            : 
     581                 :          2 :         reformat(&s, "prefix_command = %s", conf->prefix_command);
     582                 :          2 :         printer(s, conf->item_origins[find_conf("prefix_command")->number], context);
     583                 :            : 
     584                 :          2 :         reformat(&s, "read_only = %s", bool_to_string(conf->read_only));
     585                 :          2 :         printer(s, conf->item_origins[find_conf("read_only")->number], context);
     586                 :            : 
     587                 :          2 :         reformat(&s, "read_only_direct = %s", bool_to_string(conf->read_only_direct));
     588                 :          2 :         printer(s, conf->item_origins[find_conf("read_only_direct")->number],
     589                 :            :                 context);
     590                 :            : 
     591                 :          2 :         reformat(&s, "recache = %s", bool_to_string(conf->recache));
     592                 :          2 :         printer(s, conf->item_origins[find_conf("recache")->number], context);
     593                 :            : 
     594                 :          2 :         reformat(&s, "run_second_cpp = %s", bool_to_string(conf->run_second_cpp));
     595                 :          2 :         printer(s, conf->item_origins[find_conf("run_second_cpp")->number], context);
     596                 :            : 
     597                 :          2 :         reformat(&s, "sloppiness = ");
     598         [ +  + ]:          2 :         if (conf->sloppiness & SLOPPY_FILE_MACRO) {
     599                 :          1 :                 reformat(&s, "%sfile_macro, ", s);
     600                 :            :         }
     601         [ +  + ]:          2 :         if (conf->sloppiness & SLOPPY_INCLUDE_FILE_MTIME) {
     602                 :          1 :                 reformat(&s, "%sinclude_file_mtime, ", s);
     603                 :            :         }
     604         [ +  - ]:          2 :         if (conf->sloppiness & SLOPPY_INCLUDE_FILE_CTIME) {
     605                 :          2 :                 reformat(&s, "%sinclude_file_ctime, ", s);
     606                 :            :         }
     607         [ +  + ]:          2 :         if (conf->sloppiness & SLOPPY_TIME_MACROS) {
     608                 :          1 :                 reformat(&s, "%stime_macros, ", s);
     609                 :            :         }
     610         [ +  + ]:          2 :         if (conf->sloppiness & SLOPPY_FILE_STAT_MATCHES) {
     611                 :          1 :                 reformat(&s, "%sfile_stat_matches, ", s);
     612                 :            :         }
     613         [ +  - ]:          2 :         if (conf->sloppiness) {
     614                 :            :                 /* Strip last ", ". */
     615                 :          2 :                 s[strlen(s) - 2] = '\0';
     616                 :            :         }
     617                 :          2 :         printer(s, conf->item_origins[find_conf("sloppiness")->number], context);
     618                 :            : 
     619                 :          2 :         reformat(&s, "stats = %s", bool_to_string(conf->stats));
     620                 :          2 :         printer(s, conf->item_origins[find_conf("stats")->number], context);
     621                 :            : 
     622                 :          2 :         reformat(&s, "temporary_dir = %s", conf->temporary_dir);
     623                 :          2 :         printer(s, conf->item_origins[find_conf("temporary_dir")->number], context);
     624                 :            : 
     625         [ +  + ]:          2 :         if (conf->umask == UINT_MAX) {
     626                 :          1 :                 reformat(&s, "umask = ");
     627                 :            :         } else {
     628                 :          1 :                 reformat(&s, "umask = %03o", conf->umask);
     629                 :            :         }
     630                 :          2 :         printer(s, conf->item_origins[find_conf("umask")->number], context);
     631                 :            : 
     632                 :          2 :         reformat(&s, "unify = %s", bool_to_string(conf->unify));
     633                 :          2 :         printer(s, conf->item_origins[find_conf("unify")->number], context);
     634                 :            : 
     635                 :          2 :         free(s);
     636                 :          2 :         return true;
     637                 :            : }

Generated by: LCOV version 1.9