1 // Copyright (C) 2018 Joel Rosdahl
3 // This program is free software; you can redistribute it and/or modify it
4 // under the terms of the GNU General Public License as published by the Free
5 // Software Foundation; either version 3 of the License, or (at your option)
8 // This program is distributed in the hope that it will be useful, but WITHOUT
9 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 // You should have received a copy of the GNU General Public License along with
14 // this program; if not, write to the Free Software Foundation, Inc., 51
15 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 #include "confitems.h"
21 format_string(void *value)
23 char **str = (char **)value;
24 return x_strdup(*str);
28 confitem_parse_bool(const char *str, void *result, char **errmsg)
30 bool *value = (bool *)result;
32 if (str_eq(str, "true")) {
35 } else if (str_eq(str, "false")) {
39 *errmsg = format("not a boolean value: \"%s\"", str);
45 confitem_format_bool(void *value)
47 bool *b = (bool *)value;
48 return x_strdup(*b ? "true" : "false");
52 confitem_parse_env_string(const char *str, void *result, char **errmsg)
54 char **value = (char **)result;
56 *value = subst_env_in_string(str, errmsg);
57 return *value != NULL;
61 confitem_format_env_string(void *value)
63 return format_string(value);
67 confitem_parse_double(const char *str, void *result, char **errmsg)
69 double *value = (double *)result;
72 double x = strtod(str, &endptr);
73 if (errno == 0 && *str != '\0' && *endptr == '\0') {
77 *errmsg = format("invalid floating point: \"%s\"", str);
83 confitem_format_double(void *value)
85 double *x = (double *)value;
86 return format("%.1f", *x);
90 confitem_parse_size(const char *str, void *result, char **errmsg)
92 uint64_t *value = (uint64_t *)result;
94 if (parse_size_with_suffix(str, &size)) {
98 *errmsg = format("invalid size: \"%s\"", str);
104 confitem_format_size(void *value)
106 uint64_t *size = (uint64_t *)value;
107 return format_parsable_size_with_suffix(*size);
111 confitem_parse_sloppiness(const char *str, void *result, char **errmsg)
113 unsigned *value = (unsigned *)result;
118 char *p = x_strdup(str);
121 char *saveptr = NULL;
122 while ((word = strtok_r(q, ", ", &saveptr))) {
123 if (str_eq(word, "file_macro")) {
124 *value |= SLOPPY_FILE_MACRO;
125 } else if (str_eq(word, "file_stat_matches")) {
126 *value |= SLOPPY_FILE_STAT_MATCHES;
127 } else if (str_eq(word, "file_stat_matches_ctime")) {
128 *value |= SLOPPY_FILE_STAT_MATCHES_CTIME;
129 } else if (str_eq(word, "include_file_ctime")) {
130 *value |= SLOPPY_INCLUDE_FILE_CTIME;
131 } else if (str_eq(word, "include_file_mtime")) {
132 *value |= SLOPPY_INCLUDE_FILE_MTIME;
133 } else if (str_eq(word, "no_system_headers")) {
134 *value |= SLOPPY_NO_SYSTEM_HEADERS;
135 } else if (str_eq(word, "pch_defines")) {
136 *value |= SLOPPY_PCH_DEFINES;
137 } else if (str_eq(word, "time_macros")) {
138 *value |= SLOPPY_TIME_MACROS;
140 *errmsg = format("unknown sloppiness: \"%s\"", word);
151 confitem_format_sloppiness(void *value)
153 unsigned *sloppiness = (unsigned *)value;
154 char *s = x_strdup("");
155 if (*sloppiness & SLOPPY_FILE_MACRO) {
156 reformat(&s, "%sfile_macro, ", s);
158 if (*sloppiness & SLOPPY_INCLUDE_FILE_MTIME) {
159 reformat(&s, "%sinclude_file_mtime, ", s);
161 if (*sloppiness & SLOPPY_INCLUDE_FILE_CTIME) {
162 reformat(&s, "%sinclude_file_ctime, ", s);
164 if (*sloppiness & SLOPPY_TIME_MACROS) {
165 reformat(&s, "%stime_macros, ", s);
167 if (*sloppiness & SLOPPY_PCH_DEFINES) {
168 reformat(&s, "%spch_defines, ", s);
170 if (*sloppiness & SLOPPY_FILE_STAT_MATCHES) {
171 reformat(&s, "%sfile_stat_matches, ", s);
173 if (*sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME) {
174 reformat(&s, "%sfile_stat_matches_ctime, ", s);
176 if (*sloppiness & SLOPPY_NO_SYSTEM_HEADERS) {
177 reformat(&s, "%sno_system_headers, ", s);
181 s[strlen(s) - 2] = '\0';
187 confitem_parse_string(const char *str, void *result, char **errmsg)
191 char **value = (char **)result;
193 *value = x_strdup(str);
198 confitem_format_string(void *value)
200 return format_string(value);
204 confitem_parse_umask(const char *str, void *result, char **errmsg)
206 unsigned *value = (unsigned *)result;
207 if (str_eq(str, "")) {
214 *value = strtoul(str, &endptr, 8);
215 if (errno == 0 && *str != '\0' && *endptr == '\0') {
218 *errmsg = format("not an octal integer: \"%s\"", str);
224 confitem_format_umask(void *value)
226 unsigned *umask = (unsigned *)value;
227 if (*umask == UINT_MAX) {
230 return format("%03o", *umask);
235 confitem_parse_unsigned(const char *str, void *result, char **errmsg)
237 unsigned *value = (unsigned *)result;
240 long x = strtol(str, &endptr, 10);
241 if (errno == 0 && x >= 0 && *str != '\0' && *endptr == '\0') {
245 *errmsg = format("invalid unsigned integer: \"%s\"", str);
251 confitem_format_unsigned(void *value)
253 unsigned *i = (unsigned *)value;
254 return format("%u", *i);
258 confitem_verify_absolute_path(void *value, char **errmsg)
260 char **path = (char **)value;
262 if (str_eq(*path, "")) {
263 // The empty string means "disable" in this case.
265 } else if (is_absolute_path(*path)) {
268 *errmsg = format("not an absolute path: \"%s\"", *path);
274 confitem_verify_dir_levels(void *value, char **errmsg)
276 unsigned *levels = (unsigned *)value;
278 if (*levels >= 1 && *levels <= 8) {
281 *errmsg = format("cache directory levels must be between 1 and 8");