Imported Upstream version 3.5.1
[platform/upstream/ccache.git] / src / confitems.c
1 // Copyright (C) 2018 Joel Rosdahl
2 //
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)
6 // any later version.
7 //
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
11 // more details.
12 //
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
16
17 #include "confitems.h"
18 #include "ccache.h"
19
20 static char *
21 format_string(void *value)
22 {
23         char **str = (char **)value;
24         return x_strdup(*str);
25 }
26
27 bool
28 confitem_parse_bool(const char *str, void *result, char **errmsg)
29 {
30         bool *value = (bool *)result;
31
32         if (str_eq(str, "true")) {
33                 *value = true;
34                 return true;
35         } else if (str_eq(str, "false")) {
36                 *value = false;
37                 return true;
38         } else {
39                 *errmsg = format("not a boolean value: \"%s\"", str);
40                 return false;
41         }
42 }
43
44 char *
45 confitem_format_bool(void *value)
46 {
47         bool *b = (bool *)value;
48         return x_strdup(*b ? "true" : "false");
49 }
50
51 bool
52 confitem_parse_env_string(const char *str, void *result, char **errmsg)
53 {
54         char **value = (char **)result;
55         free(*value);
56         *value = subst_env_in_string(str, errmsg);
57         return *value != NULL;
58 }
59
60 char *
61 confitem_format_env_string(void *value)
62 {
63         return format_string(value);
64 }
65
66 bool
67 confitem_parse_double(const char *str, void *result, char **errmsg)
68 {
69         double *value = (double *)result;
70         errno = 0;
71         char *endptr;
72         double x = strtod(str, &endptr);
73         if (errno == 0 && *str != '\0' && *endptr == '\0') {
74                 *value = x;
75                 return true;
76         } else {
77                 *errmsg = format("invalid floating point: \"%s\"", str);
78                 return false;
79         }
80 }
81
82 char *
83 confitem_format_double(void *value)
84 {
85         double *x = (double *)value;
86         return format("%.1f", *x);
87 }
88
89 bool
90 confitem_parse_size(const char *str, void *result, char **errmsg)
91 {
92         uint64_t *value = (uint64_t *)result;
93         uint64_t size;
94         if (parse_size_with_suffix(str, &size)) {
95                 *value = size;
96                 return true;
97         } else {
98                 *errmsg = format("invalid size: \"%s\"", str);
99                 return false;
100         }
101 }
102
103 char *
104 confitem_format_size(void *value)
105 {
106         uint64_t *size = (uint64_t *)value;
107         return format_parsable_size_with_suffix(*size);
108 }
109
110 bool
111 confitem_parse_sloppiness(const char *str, void *result, char **errmsg)
112 {
113         unsigned *value = (unsigned *)result;
114         if (!str) {
115                 return *value;
116         }
117
118         char *p = x_strdup(str);
119         char *q = p;
120         char *word;
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;
139                 } else {
140                         *errmsg = format("unknown sloppiness: \"%s\"", word);
141                         free(p);
142                         return false;
143                 }
144                 q = NULL;
145         }
146         free(p);
147         return true;
148 }
149
150 char *
151 confitem_format_sloppiness(void *value)
152 {
153         unsigned *sloppiness = (unsigned *)value;
154         char *s = x_strdup("");
155         if (*sloppiness & SLOPPY_FILE_MACRO) {
156                 reformat(&s, "%sfile_macro, ", s);
157         }
158         if (*sloppiness & SLOPPY_INCLUDE_FILE_MTIME) {
159                 reformat(&s, "%sinclude_file_mtime, ", s);
160         }
161         if (*sloppiness & SLOPPY_INCLUDE_FILE_CTIME) {
162                 reformat(&s, "%sinclude_file_ctime, ", s);
163         }
164         if (*sloppiness & SLOPPY_TIME_MACROS) {
165                 reformat(&s, "%stime_macros, ", s);
166         }
167         if (*sloppiness & SLOPPY_PCH_DEFINES) {
168                 reformat(&s, "%spch_defines, ", s);
169         }
170         if (*sloppiness & SLOPPY_FILE_STAT_MATCHES) {
171                 reformat(&s, "%sfile_stat_matches, ", s);
172         }
173         if (*sloppiness & SLOPPY_FILE_STAT_MATCHES_CTIME) {
174                 reformat(&s, "%sfile_stat_matches_ctime, ", s);
175         }
176         if (*sloppiness & SLOPPY_NO_SYSTEM_HEADERS) {
177                 reformat(&s, "%sno_system_headers, ", s);
178         }
179         if (*sloppiness) {
180                 // Strip last ", ".
181                 s[strlen(s) - 2] = '\0';
182         }
183         return s;
184 }
185
186 bool
187 confitem_parse_string(const char *str, void *result, char **errmsg)
188 {
189         (void)errmsg;
190
191         char **value = (char **)result;
192         free(*value);
193         *value = x_strdup(str);
194         return true;
195 }
196
197 char *
198 confitem_format_string(void *value)
199 {
200         return format_string(value);
201 }
202
203 bool
204 confitem_parse_umask(const char *str, void *result, char **errmsg)
205 {
206         unsigned *value = (unsigned *)result;
207         if (str_eq(str, "")) {
208                 *value = UINT_MAX;
209                 return true;
210         }
211
212         errno = 0;
213         char *endptr;
214         *value = strtoul(str, &endptr, 8);
215         if (errno == 0 && *str != '\0' && *endptr == '\0') {
216                 return true;
217         } else {
218                 *errmsg = format("not an octal integer: \"%s\"", str);
219                 return false;
220         }
221 }
222
223 char *
224 confitem_format_umask(void *value)
225 {
226         unsigned *umask = (unsigned *)value;
227         if (*umask == UINT_MAX) {
228                 return x_strdup("");
229         } else {
230                 return format("%03o", *umask);
231         }
232 }
233
234 bool
235 confitem_parse_unsigned(const char *str, void *result, char **errmsg)
236 {
237         unsigned *value = (unsigned *)result;
238         errno = 0;
239         char *endptr;
240         long x = strtol(str, &endptr, 10);
241         if (errno == 0 && x >= 0 && *str != '\0' && *endptr == '\0') {
242                 *value = x;
243                 return true;
244         } else {
245                 *errmsg = format("invalid unsigned integer: \"%s\"", str);
246                 return false;
247         }
248 }
249
250 char *
251 confitem_format_unsigned(void *value)
252 {
253         unsigned *i = (unsigned *)value;
254         return format("%u", *i);
255 }
256
257 bool
258 confitem_verify_absolute_path(void *value, char **errmsg)
259 {
260         char **path = (char **)value;
261         assert(*path);
262         if (str_eq(*path, "")) {
263                 // The empty string means "disable" in this case.
264                 return true;
265         } else if (is_absolute_path(*path)) {
266                 return true;
267         } else {
268                 *errmsg = format("not an absolute path: \"%s\"", *path);
269                 return false;
270         }
271 }
272
273 bool
274 confitem_verify_dir_levels(void *value, char **errmsg)
275 {
276         unsigned *levels = (unsigned *)value;
277         assert(levels);
278         if (*levels >= 1 && *levels <= 8) {
279                 return true;
280         } else {
281                 *errmsg = format("cache directory levels must be between 1 and 8");
282                 return false;
283         }
284 }