// Copyright (C) 2018-2019 Joel Rosdahl // // This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3 of the License, or (at your option) // any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // // You should have received a copy of the GNU General Public License along with // this program; if not, write to the Free Software Foundation, Inc., 51 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "confitems.h" #include "ccache.h" static char * format_string(const void *value) { const char *const *str = (const char *const *)value; return x_strdup(*str); } bool confitem_parse_bool(const char *str, void *result, char **errmsg) { bool *value = (bool *)result; if (str_eq(str, "true")) { *value = true; return true; } else if (str_eq(str, "false")) { *value = false; return true; } else { *errmsg = format("not a boolean value: \"%s\"", str); return false; } } char * confitem_format_bool(const void *value) { const bool *b = (const bool *)value; return x_strdup(*b ? "true" : "false"); } bool confitem_parse_env_string(const char *str, void *result, char **errmsg) { char **value = (char **)result; free(*value); *value = subst_env_in_string(str, errmsg); return *value != NULL; } char * confitem_format_env_string(const void *value) { return format_string(value); } bool confitem_parse_double(const char *str, void *result, char **errmsg) { double *value = (double *)result; errno = 0; char *endptr; double x = strtod(str, &endptr); if (errno == 0 && *str != '\0' && *endptr == '\0') { *value = x; return true; } else { *errmsg = format("invalid floating point: \"%s\"", str); return false; } } char * confitem_format_double(const void *value) { const double *x = (const double *)value; return format("%.1f", *x); } bool confitem_parse_size(const char *str, void *result, char **errmsg) { uint64_t *value = (uint64_t *)result; uint64_t size; if (parse_size_with_suffix(str, &size)) { *value = size; return true; } else { *errmsg = format("invalid size: \"%s\"", str); return false; } } char * confitem_format_size(const void *value) { const uint64_t *size = (const uint64_t *)value; return format_parsable_size_with_suffix(*size); } bool confitem_parse_sloppiness(const char *str, void *result, char **errmsg) { (void)errmsg; unsigned *value = (unsigned *)result; if (!str) { return *value; } char *p = x_strdup(str); char *q = p; char *word; char *saveptr = NULL; while ((word = strtok_r(q, ", ", &saveptr))) { if (str_eq(word, "file_stat_matches")) { *value |= SLOPPY_FILE_STAT_MATCHES; } else if (str_eq(word, "file_stat_matches_ctime")) { *value |= SLOPPY_FILE_STAT_MATCHES_CTIME; } else if (str_eq(word, "include_file_ctime")) { *value |= SLOPPY_INCLUDE_FILE_CTIME; } else if (str_eq(word, "include_file_mtime")) { *value |= SLOPPY_INCLUDE_FILE_MTIME; } else if (str_eq(word, "system_headers") || str_eq(word, "no_system_headers")) { *value |= SLOPPY_SYSTEM_HEADERS; } else if (str_eq(word, "pch_defines")) { *value |= SLOPPY_PCH_DEFINES; } else if (str_eq(word, "time_macros")) { *value |= SLOPPY_TIME_MACROS; } else if (str_eq(word, "clang_index_store")) { *value |= SLOPPY_CLANG_INDEX_STORE; } else if (str_eq(word, "locale")) { *value |= SLOPPY_LOCALE; } // else: ignore unknown value for forward compatibility q = NULL; } free(p); return true; } char * confitem_format_sloppiness(const void *value) { const unsigned *sloppiness = (const unsigned *)value; char *s = x_strdup(""); if (*sloppiness & SLOPPY_INCLUDE_FILE_MTIME) { reformat(&s, "%sinclude_file_mtime, ", s); } if (*sloppiness & SLOPPY_INCLUDE_FILE_CTIME) { reformat(&s, "%sinclude_file_ctime, ", s); } if (*sloppiness & SLOPPY_TIME_MACROS) { reformat(&s, "%stime_macros, ", s); } if (*sloppiness & SLOPPY_PCH_DEFINES) { reformat(&s, "%spch_defines, ", s); } if (*sloppiness & SLOPPY_FILE_STAT_MATCHES) { reformat(&s, "%sfile_stat_matches, ", s); } if (*sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME) { reformat(&s, "%sfile_stat_matches_ctime, ", s); } if (*sloppiness & SLOPPY_SYSTEM_HEADERS) { reformat(&s, "%ssystem_headers, ", s); } if (*sloppiness & SLOPPY_CLANG_INDEX_STORE) { reformat(&s, "%sclang_index_store, ", s); } if (*sloppiness & SLOPPY_LOCALE) { reformat(&s, "%slocale, ", s); } if (*sloppiness) { // Strip last ", ". s[strlen(s) - 2] = '\0'; } return s; } bool confitem_parse_string(const char *str, void *result, char **errmsg) { (void)errmsg; char **value = (char **)result; free(*value); *value = x_strdup(str); return true; } char * confitem_format_string(const void *value) { return format_string(value); } bool confitem_parse_umask(const char *str, void *result, char **errmsg) { unsigned *value = (unsigned *)result; if (str_eq(str, "")) { *value = UINT_MAX; return true; } errno = 0; char *endptr; *value = strtoul(str, &endptr, 8); if (errno == 0 && *str != '\0' && *endptr == '\0') { return true; } else { *errmsg = format("not an octal integer: \"%s\"", str); return false; } } char * confitem_format_umask(const void *value) { const unsigned *umask = (const unsigned *)value; if (*umask == UINT_MAX) { return x_strdup(""); } else { return format("%03o", *umask); } } bool confitem_parse_unsigned(const char *str, void *result, char **errmsg) { unsigned *value = (unsigned *)result; errno = 0; char *endptr; long x = strtol(str, &endptr, 10); if (errno == 0 && x >= 0 && *str != '\0' && *endptr == '\0') { *value = x; return true; } else { *errmsg = format("invalid unsigned integer: \"%s\"", str); return false; } } char * confitem_format_unsigned(const void *value) { const unsigned *i = (const unsigned *)value; return format("%u", *i); } bool confitem_verify_absolute_path(const void *value, char **errmsg) { const char *const *path = (const char *const *)value; assert(*path); if (str_eq(*path, "")) { // The empty string means "disable" in this case. return true; } else if (is_absolute_path(*path)) { return true; } else { *errmsg = format("not an absolute path: \"%s\"", *path); return false; } } bool confitem_verify_dir_levels(const void *value, char **errmsg) { const unsigned *levels = (const unsigned *)value; assert(levels); if (*levels >= 1 && *levels <= 8) { return true; } else { *errmsg = format("cache directory levels must be between 1 and 8"); return false; } }