GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* $OpenBSD: options.c,v 1.36 2017/08/09 13:44:36 nicm Exp $ */ |
||
2 |
|||
3 |
/* |
||
4 |
* Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com> |
||
5 |
* |
||
6 |
* Permission to use, copy, modify, and distribute this software for any |
||
7 |
* purpose with or without fee is hereby granted, provided that the above |
||
8 |
* copyright notice and this permission notice appear in all copies. |
||
9 |
* |
||
10 |
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||
11 |
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||
12 |
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||
13 |
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||
14 |
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER |
||
15 |
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING |
||
16 |
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||
17 |
*/ |
||
18 |
|||
19 |
#include <sys/types.h> |
||
20 |
|||
21 |
#include <ctype.h> |
||
22 |
#include <stdarg.h> |
||
23 |
#include <stdlib.h> |
||
24 |
#include <string.h> |
||
25 |
|||
26 |
#include "tmux.h" |
||
27 |
|||
28 |
/* |
||
29 |
* Option handling; each option has a name, type and value and is stored in |
||
30 |
* a red-black tree. |
||
31 |
*/ |
||
32 |
|||
33 |
struct options_entry { |
||
34 |
struct options *owner; |
||
35 |
|||
36 |
const char *name; |
||
37 |
const struct options_table_entry *tableentry; |
||
38 |
|||
39 |
union { |
||
40 |
char *string; |
||
41 |
long long number; |
||
42 |
struct grid_cell style; |
||
43 |
struct { |
||
44 |
const char **array; |
||
45 |
u_int arraysize; |
||
46 |
}; |
||
47 |
}; |
||
48 |
|||
49 |
RB_ENTRY(options_entry) entry; |
||
50 |
}; |
||
51 |
|||
52 |
struct options { |
||
53 |
RB_HEAD(options_tree, options_entry) tree; |
||
54 |
struct options *parent; |
||
55 |
}; |
||
56 |
|||
57 |
static struct options_entry *options_add(struct options *, const char *); |
||
58 |
|||
59 |
#define OPTIONS_ARRAY_LIMIT 1000 |
||
60 |
|||
61 |
#define OPTIONS_IS_STRING(o) \ |
||
62 |
((o)->tableentry == NULL || \ |
||
63 |
(o)->tableentry->type == OPTIONS_TABLE_STRING) |
||
64 |
#define OPTIONS_IS_NUMBER(o) \ |
||
65 |
((o)->tableentry != NULL && \ |
||
66 |
((o)->tableentry->type == OPTIONS_TABLE_NUMBER || \ |
||
67 |
(o)->tableentry->type == OPTIONS_TABLE_KEY || \ |
||
68 |
(o)->tableentry->type == OPTIONS_TABLE_COLOUR || \ |
||
69 |
(o)->tableentry->type == OPTIONS_TABLE_ATTRIBUTES || \ |
||
70 |
(o)->tableentry->type == OPTIONS_TABLE_FLAG || \ |
||
71 |
(o)->tableentry->type == OPTIONS_TABLE_CHOICE)) |
||
72 |
#define OPTIONS_IS_STYLE(o) \ |
||
73 |
((o)->tableentry != NULL && \ |
||
74 |
(o)->tableentry->type == OPTIONS_TABLE_STYLE) |
||
75 |
#define OPTIONS_IS_ARRAY(o) \ |
||
76 |
((o)->tableentry != NULL && \ |
||
77 |
(o)->tableentry->type == OPTIONS_TABLE_ARRAY) |
||
78 |
|||
79 |
static int options_cmp(struct options_entry *, struct options_entry *); |
||
80 |
✓✓✓✗ ✓✓✗✓ ✓✓✓✗ ✗✓✗✗ ✓✓✓✓ ✓✓✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓✓✓ ✓✗✓✓ ✓✓✓✗ ✓✓✓✓ ✓✓✓✓ ✗✓✗✗ ✓✗✗✓ ✓✗✗✓ ✓✗✓✓ ✓✓✓✓ ✗✓✓✗ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✓✓✓✗ ✓✓✓✓ ✓✓✓✓ ✓✓✓✗ ✗✓✗✗ ✗✗✗✗ ✓✗✓✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✓ |
72470 |
RB_GENERATE_STATIC(options_tree, options_entry, entry, options_cmp); |
81 |
|||
82 |
static int |
||
83 |
options_cmp(struct options_entry *lhs, struct options_entry *rhs) |
||
84 |
{ |
||
85 |
16340 |
return (strcmp(lhs->name, rhs->name)); |
|
86 |
} |
||
87 |
|||
88 |
static const struct options_table_entry * |
||
89 |
options_parent_table_entry(struct options *oo, const char *s) |
||
90 |
{ |
||
91 |
struct options_entry *o; |
||
92 |
|||
93 |
if (oo->parent == NULL) |
||
94 |
fatalx("no parent options for %s", s); |
||
95 |
o = options_get_only(oo->parent, s); |
||
96 |
if (o == NULL) |
||
97 |
fatalx("%s not in parent options", s); |
||
98 |
return (o->tableentry); |
||
99 |
} |
||
100 |
|||
101 |
struct options * |
||
102 |
options_create(struct options *parent) |
||
103 |
{ |
||
104 |
struct options *oo; |
||
105 |
|||
106 |
30 |
oo = xcalloc(1, sizeof *oo); |
|
107 |
15 |
RB_INIT(&oo->tree); |
|
108 |
15 |
oo->parent = parent; |
|
109 |
15 |
return (oo); |
|
110 |
} |
||
111 |
|||
112 |
void |
||
113 |
options_free(struct options *oo) |
||
114 |
{ |
||
115 |
struct options_entry *o, *tmp; |
||
116 |
|||
117 |
✓✓ | 1965 |
RB_FOREACH_SAFE(o, options_tree, &oo->tree, tmp) |
118 |
640 |
options_remove(o); |
|
119 |
15 |
free(oo); |
|
120 |
15 |
} |
|
121 |
|||
122 |
struct options_entry * |
||
123 |
options_first(struct options *oo) |
||
124 |
{ |
||
125 |
return (RB_MIN(options_tree, &oo->tree)); |
||
126 |
} |
||
127 |
|||
128 |
struct options_entry * |
||
129 |
options_next(struct options_entry *o) |
||
130 |
{ |
||
131 |
return (RB_NEXT(options_tree, &oo->tree, o)); |
||
132 |
} |
||
133 |
|||
134 |
struct options_entry * |
||
135 |
options_get_only(struct options *oo, const char *name) |
||
136 |
{ |
||
137 |
1290 |
struct options_entry o; |
|
138 |
|||
139 |
645 |
o.name = name; |
|
140 |
1290 |
return (RB_FIND(options_tree, &oo->tree, &o)); |
|
141 |
645 |
} |
|
142 |
|||
143 |
struct options_entry * |
||
144 |
options_get(struct options *oo, const char *name) |
||
145 |
{ |
||
146 |
struct options_entry *o; |
||
147 |
|||
148 |
o = options_get_only(oo, name); |
||
149 |
while (o == NULL) { |
||
150 |
oo = oo->parent; |
||
151 |
if (oo == NULL) |
||
152 |
break; |
||
153 |
o = options_get_only(oo, name); |
||
154 |
} |
||
155 |
return (o); |
||
156 |
} |
||
157 |
|||
158 |
struct options_entry * |
||
159 |
options_empty(struct options *oo, const struct options_table_entry *oe) |
||
160 |
{ |
||
161 |
struct options_entry *o; |
||
162 |
|||
163 |
1280 |
o = options_add(oo, oe->name); |
|
164 |
640 |
o->tableentry = oe; |
|
165 |
|||
166 |
640 |
return (o); |
|
167 |
} |
||
168 |
|||
169 |
struct options_entry * |
||
170 |
options_default(struct options *oo, const struct options_table_entry *oe) |
||
171 |
{ |
||
172 |
struct options_entry *o; |
||
173 |
|||
174 |
1280 |
o = options_empty(oo, oe); |
|
175 |
✓✓ | 640 |
if (oe->type == OPTIONS_TABLE_ARRAY) |
176 |
20 |
options_array_assign(o, oe->default_str); |
|
177 |
✓✓ | 620 |
else if (oe->type == OPTIONS_TABLE_STRING) |
178 |
75 |
o->string = xstrdup(oe->default_str); |
|
179 |
✓✓ | 545 |
else if (oe->type == OPTIONS_TABLE_STYLE) { |
180 |
75 |
memcpy(&o->style, &grid_default_cell, sizeof o->style); |
|
181 |
75 |
style_parse(&grid_default_cell, &o->style, oe->default_str); |
|
182 |
75 |
} else |
|
183 |
470 |
o->number = oe->default_num; |
|
184 |
640 |
return (o); |
|
185 |
} |
||
186 |
|||
187 |
static struct options_entry * |
||
188 |
options_add(struct options *oo, const char *name) |
||
189 |
{ |
||
190 |
struct options_entry *o; |
||
191 |
|||
192 |
1280 |
o = options_get_only(oo, name); |
|
193 |
✗✓ | 640 |
if (o != NULL) |
194 |
options_remove(o); |
||
195 |
|||
196 |
640 |
o = xcalloc(1, sizeof *o); |
|
197 |
640 |
o->owner = oo; |
|
198 |
640 |
o->name = xstrdup(name); |
|
199 |
|||
200 |
640 |
RB_INSERT(options_tree, &oo->tree, o); |
|
201 |
640 |
return (o); |
|
202 |
} |
||
203 |
|||
204 |
void |
||
205 |
options_remove(struct options_entry *o) |
||
206 |
{ |
||
207 |
1280 |
struct options *oo = o->owner; |
|
208 |
u_int i; |
||
209 |
|||
210 |
✓✗✓✓ |
1280 |
if (OPTIONS_IS_STRING(o)) |
211 |
75 |
free((void *)o->string); |
|
212 |
✓✗✓✓ |
1130 |
else if (OPTIONS_IS_ARRAY(o)) { |
213 |
✓✓ | 190 |
for (i = 0; i < o->arraysize; i++) |
214 |
75 |
free((void *)o->array[i]); |
|
215 |
20 |
free(o->array); |
|
216 |
20 |
} |
|
217 |
|||
218 |
640 |
RB_REMOVE(options_tree, &oo->tree, o); |
|
219 |
640 |
free(o); |
|
220 |
640 |
} |
|
221 |
|||
222 |
const char * |
||
223 |
options_name(struct options_entry *o) |
||
224 |
{ |
||
225 |
return (o->name); |
||
226 |
} |
||
227 |
|||
228 |
const struct options_table_entry * |
||
229 |
options_table_entry(struct options_entry *o) |
||
230 |
{ |
||
231 |
return (o->tableentry); |
||
232 |
} |
||
233 |
|||
234 |
void |
||
235 |
options_array_clear(struct options_entry *o) |
||
236 |
{ |
||
237 |
if (OPTIONS_IS_ARRAY(o)) |
||
238 |
o->arraysize = 0; |
||
239 |
} |
||
240 |
|||
241 |
const char * |
||
242 |
options_array_get(struct options_entry *o, u_int idx) |
||
243 |
{ |
||
244 |
if (!OPTIONS_IS_ARRAY(o)) |
||
245 |
return (NULL); |
||
246 |
if (idx >= o->arraysize) |
||
247 |
return (NULL); |
||
248 |
return (o->array[idx]); |
||
249 |
} |
||
250 |
|||
251 |
int |
||
252 |
options_array_set(struct options_entry *o, u_int idx, const char *value, |
||
253 |
int append) |
||
254 |
{ |
||
255 |
150 |
char *new; |
|
256 |
u_int i; |
||
257 |
|||
258 |
✓✗✗✓ |
150 |
if (!OPTIONS_IS_ARRAY(o)) |
259 |
return (-1); |
||
260 |
|||
261 |
✗✓ | 75 |
if (idx >= OPTIONS_ARRAY_LIMIT) |
262 |
return (-1); |
||
263 |
✓✗ | 75 |
if (idx >= o->arraysize) { |
264 |
75 |
o->array = xreallocarray(o->array, idx + 1, sizeof *o->array); |
|
265 |
✓✓ | 300 |
for (i = o->arraysize; i < idx + 1; i++) |
266 |
75 |
o->array[i] = NULL; |
|
267 |
75 |
o->arraysize = idx + 1; |
|
268 |
75 |
} |
|
269 |
|||
270 |
75 |
new = NULL; |
|
271 |
✓✗ | 75 |
if (value != NULL) { |
272 |
✗✓ | 75 |
if (o->array[idx] != NULL && append) |
273 |
xasprintf(&new, "%s%s", o->array[idx], value); |
||
274 |
else |
||
275 |
75 |
new = xstrdup(value); |
|
276 |
} |
||
277 |
|||
278 |
75 |
free((void *)o->array[idx]); |
|
279 |
75 |
o->array[idx] = new; |
|
280 |
75 |
return (0); |
|
281 |
75 |
} |
|
282 |
|||
283 |
int |
||
284 |
options_array_size(struct options_entry *o, u_int *size) |
||
285 |
{ |
||
286 |
if (!OPTIONS_IS_ARRAY(o)) |
||
287 |
return (-1); |
||
288 |
if (size != NULL) |
||
289 |
*size = o->arraysize; |
||
290 |
return (0); |
||
291 |
} |
||
292 |
|||
293 |
void |
||
294 |
options_array_assign(struct options_entry *o, const char *s) |
||
295 |
{ |
||
296 |
const char *separator; |
||
297 |
40 |
char *copy, *next, *string; |
|
298 |
u_int i; |
||
299 |
|||
300 |
20 |
separator = o->tableentry->separator; |
|
301 |
20 |
if (separator == NULL) |
|
302 |
separator = " ,"; |
||
303 |
|||
304 |
20 |
copy = string = xstrdup(s); |
|
305 |
✓✓ | 195 |
while ((next = strsep(&string, separator)) != NULL) { |
306 |
✓✓ | 80 |
if (*next == '\0') |
307 |
continue; |
||
308 |
✓✗ | 520 |
for (i = 0; i < OPTIONS_ARRAY_LIMIT; i++) { |
309 |
✓✓✓✗ |
445 |
if (i >= o->arraysize || o->array[i] == NULL) |
310 |
break; |
||
311 |
} |
||
312 |
✓✗ | 75 |
if (i == OPTIONS_ARRAY_LIMIT) |
313 |
break; |
||
314 |
75 |
options_array_set(o, i, next, 0); |
|
315 |
} |
||
316 |
20 |
free(copy); |
|
317 |
20 |
} |
|
318 |
|||
319 |
int |
||
320 |
options_isstring(struct options_entry *o) |
||
321 |
{ |
||
322 |
if (o->tableentry == NULL) |
||
323 |
return (1); |
||
324 |
return (OPTIONS_IS_STRING(o) || OPTIONS_IS_ARRAY(o)); |
||
325 |
} |
||
326 |
|||
327 |
const char * |
||
328 |
options_tostring(struct options_entry *o, int idx, int numeric) |
||
329 |
{ |
||
330 |
static char s[1024]; |
||
331 |
const char *tmp; |
||
332 |
|||
333 |
if (OPTIONS_IS_ARRAY(o)) { |
||
334 |
if (idx == -1) |
||
335 |
return (NULL); |
||
336 |
if ((u_int)idx >= o->arraysize || o->array[idx] == NULL) |
||
337 |
return (""); |
||
338 |
return (o->array[idx]); |
||
339 |
} |
||
340 |
if (OPTIONS_IS_STYLE(o)) |
||
341 |
return (style_tostring(&o->style)); |
||
342 |
if (OPTIONS_IS_NUMBER(o)) { |
||
343 |
tmp = NULL; |
||
344 |
switch (o->tableentry->type) { |
||
345 |
case OPTIONS_TABLE_NUMBER: |
||
346 |
xsnprintf(s, sizeof s, "%lld", o->number); |
||
347 |
break; |
||
348 |
case OPTIONS_TABLE_KEY: |
||
349 |
tmp = key_string_lookup_key(o->number); |
||
350 |
break; |
||
351 |
case OPTIONS_TABLE_COLOUR: |
||
352 |
tmp = colour_tostring(o->number); |
||
353 |
break; |
||
354 |
case OPTIONS_TABLE_ATTRIBUTES: |
||
355 |
tmp = attributes_tostring(o->number); |
||
356 |
break; |
||
357 |
case OPTIONS_TABLE_FLAG: |
||
358 |
if (numeric) |
||
359 |
xsnprintf(s, sizeof s, "%lld", o->number); |
||
360 |
else |
||
361 |
tmp = (o->number ? "on" : "off"); |
||
362 |
break; |
||
363 |
case OPTIONS_TABLE_CHOICE: |
||
364 |
tmp = o->tableentry->choices[o->number]; |
||
365 |
break; |
||
366 |
case OPTIONS_TABLE_STRING: |
||
367 |
case OPTIONS_TABLE_STYLE: |
||
368 |
case OPTIONS_TABLE_ARRAY: |
||
369 |
break; |
||
370 |
} |
||
371 |
if (tmp != NULL) |
||
372 |
xsnprintf(s, sizeof s, "%s", tmp); |
||
373 |
return (s); |
||
374 |
} |
||
375 |
if (OPTIONS_IS_STRING(o)) |
||
376 |
return (o->string); |
||
377 |
return (NULL); |
||
378 |
} |
||
379 |
|||
380 |
char * |
||
381 |
options_parse(const char *name, int *idx) |
||
382 |
{ |
||
383 |
char *copy, *cp, *end; |
||
384 |
|||
385 |
if (*name == '\0') |
||
386 |
return (NULL); |
||
387 |
copy = xstrdup(name); |
||
388 |
if ((cp = strchr(copy, '[')) == NULL) { |
||
389 |
*idx = -1; |
||
390 |
return (copy); |
||
391 |
} |
||
392 |
end = strchr(cp + 1, ']'); |
||
393 |
if (end == NULL || end[1] != '\0' || !isdigit((u_char)end[-1])) { |
||
394 |
free(copy); |
||
395 |
return (NULL); |
||
396 |
} |
||
397 |
if (sscanf(cp, "[%d]", idx) != 1 || *idx < 0) { |
||
398 |
free(copy); |
||
399 |
return (NULL); |
||
400 |
} |
||
401 |
*cp = '\0'; |
||
402 |
return (copy); |
||
403 |
} |
||
404 |
|||
405 |
struct options_entry * |
||
406 |
options_parse_get(struct options *oo, const char *s, int *idx, int only) |
||
407 |
{ |
||
408 |
struct options_entry *o; |
||
409 |
char *name; |
||
410 |
|||
411 |
name = options_parse(s, idx); |
||
412 |
if (name == NULL) |
||
413 |
return (NULL); |
||
414 |
if (only) |
||
415 |
o = options_get_only(oo, name); |
||
416 |
else |
||
417 |
o = options_get(oo, name); |
||
418 |
free(name); |
||
419 |
return (o); |
||
420 |
} |
||
421 |
|||
422 |
char * |
||
423 |
options_match(const char *s, int *idx, int* ambiguous) |
||
424 |
{ |
||
425 |
const struct options_table_entry *oe, *found; |
||
426 |
char *name; |
||
427 |
size_t namelen; |
||
428 |
|||
429 |
name = options_parse(s, idx); |
||
430 |
if (name == NULL) |
||
431 |
return (NULL); |
||
432 |
namelen = strlen(name); |
||
433 |
|||
434 |
if (*name == '@') { |
||
435 |
*ambiguous = 0; |
||
436 |
return (name); |
||
437 |
} |
||
438 |
|||
439 |
found = NULL; |
||
440 |
for (oe = options_table; oe->name != NULL; oe++) { |
||
441 |
if (strcmp(oe->name, name) == 0) { |
||
442 |
found = oe; |
||
443 |
break; |
||
444 |
} |
||
445 |
if (strncmp(oe->name, name, namelen) == 0) { |
||
446 |
if (found != NULL) { |
||
447 |
*ambiguous = 1; |
||
448 |
free(name); |
||
449 |
return (NULL); |
||
450 |
} |
||
451 |
found = oe; |
||
452 |
} |
||
453 |
} |
||
454 |
free(name); |
||
455 |
if (found == NULL) { |
||
456 |
*ambiguous = 0; |
||
457 |
return (NULL); |
||
458 |
} |
||
459 |
return (xstrdup(found->name)); |
||
460 |
} |
||
461 |
|||
462 |
struct options_entry * |
||
463 |
options_match_get(struct options *oo, const char *s, int *idx, int only, |
||
464 |
int* ambiguous) |
||
465 |
{ |
||
466 |
char *name; |
||
467 |
struct options_entry *o; |
||
468 |
|||
469 |
name = options_match(s, idx, ambiguous); |
||
470 |
if (name == NULL) |
||
471 |
return (NULL); |
||
472 |
*ambiguous = 0; |
||
473 |
if (only) |
||
474 |
o = options_get_only(oo, name); |
||
475 |
else |
||
476 |
o = options_get(oo, name); |
||
477 |
free(name); |
||
478 |
return (o); |
||
479 |
} |
||
480 |
|||
481 |
const char * |
||
482 |
options_get_string(struct options *oo, const char *name) |
||
483 |
{ |
||
484 |
struct options_entry *o; |
||
485 |
|||
486 |
o = options_get(oo, name); |
||
487 |
if (o == NULL) |
||
488 |
fatalx("missing option %s", name); |
||
489 |
if (!OPTIONS_IS_STRING(o)) |
||
490 |
fatalx("option %s is not a string", name); |
||
491 |
return (o->string); |
||
492 |
} |
||
493 |
|||
494 |
long long |
||
495 |
options_get_number(struct options *oo, const char *name) |
||
496 |
{ |
||
497 |
struct options_entry *o; |
||
498 |
|||
499 |
o = options_get(oo, name); |
||
500 |
if (o == NULL) |
||
501 |
fatalx("missing option %s", name); |
||
502 |
if (!OPTIONS_IS_NUMBER(o)) |
||
503 |
fatalx("option %s is not a number", name); |
||
504 |
return (o->number); |
||
505 |
} |
||
506 |
|||
507 |
const struct grid_cell * |
||
508 |
options_get_style(struct options *oo, const char *name) |
||
509 |
{ |
||
510 |
struct options_entry *o; |
||
511 |
|||
512 |
o = options_get(oo, name); |
||
513 |
if (o == NULL) |
||
514 |
fatalx("missing option %s", name); |
||
515 |
if (!OPTIONS_IS_STYLE(o)) |
||
516 |
fatalx("option %s is not a style", name); |
||
517 |
return (&o->style); |
||
518 |
} |
||
519 |
|||
520 |
struct options_entry * |
||
521 |
options_set_string(struct options *oo, const char *name, int append, |
||
522 |
const char *fmt, ...) |
||
523 |
{ |
||
524 |
struct options_entry *o; |
||
525 |
10 |
va_list ap; |
|
526 |
5 |
char *s, *value; |
|
527 |
|||
528 |
5 |
va_start(ap, fmt); |
|
529 |
5 |
xvasprintf(&s, fmt, ap); |
|
530 |
5 |
va_end(ap); |
|
531 |
|||
532 |
5 |
o = options_get_only(oo, name); |
|
533 |
✗✓✗✗ ✗✗ |
5 |
if (o != NULL && append && OPTIONS_IS_STRING(o)) { |
534 |
xasprintf(&value, "%s%s", o->string, s); |
||
535 |
free(s); |
||
536 |
} else |
||
537 |
5 |
value = s; |
|
538 |
✗✓✗✗ |
5 |
if (o == NULL && *name == '@') |
539 |
o = options_add(oo, name); |
||
540 |
✗✓ | 5 |
else if (o == NULL) { |
541 |
o = options_default(oo, options_parent_table_entry(oo, name)); |
||
542 |
if (o == NULL) |
||
543 |
return (NULL); |
||
544 |
} |
||
545 |
|||
546 |
✓✗✗✓ |
10 |
if (!OPTIONS_IS_STRING(o)) |
547 |
fatalx("option %s is not a string", name); |
||
548 |
5 |
free(o->string); |
|
549 |
5 |
o->string = value; |
|
550 |
5 |
return (o); |
|
551 |
5 |
} |
|
552 |
|||
553 |
struct options_entry * |
||
554 |
options_set_number(struct options *oo, const char *name, long long value) |
||
555 |
{ |
||
556 |
struct options_entry *o; |
||
557 |
|||
558 |
if (*name == '@') |
||
559 |
fatalx("user option %s must be a string", name); |
||
560 |
|||
561 |
o = options_get_only(oo, name); |
||
562 |
if (o == NULL) { |
||
563 |
o = options_default(oo, options_parent_table_entry(oo, name)); |
||
564 |
if (o == NULL) |
||
565 |
return (NULL); |
||
566 |
} |
||
567 |
|||
568 |
if (!OPTIONS_IS_NUMBER(o)) |
||
569 |
fatalx("option %s is not a number", name); |
||
570 |
o->number = value; |
||
571 |
return (o); |
||
572 |
} |
||
573 |
|||
574 |
struct options_entry * |
||
575 |
options_set_style(struct options *oo, const char *name, int append, |
||
576 |
const char *value) |
||
577 |
{ |
||
578 |
struct options_entry *o; |
||
579 |
struct grid_cell gc; |
||
580 |
|||
581 |
if (*name == '@') |
||
582 |
fatalx("user option %s must be a string", name); |
||
583 |
|||
584 |
o = options_get_only(oo, name); |
||
585 |
if (o != NULL && append && OPTIONS_IS_STYLE(o)) |
||
586 |
memcpy(&gc, &o->style, sizeof gc); |
||
587 |
else |
||
588 |
memcpy(&gc, &grid_default_cell, sizeof gc); |
||
589 |
if (style_parse(&grid_default_cell, &gc, value) == -1) |
||
590 |
return (NULL); |
||
591 |
if (o == NULL) { |
||
592 |
o = options_default(oo, options_parent_table_entry(oo, name)); |
||
593 |
if (o == NULL) |
||
594 |
return (NULL); |
||
595 |
} |
||
596 |
|||
597 |
if (!OPTIONS_IS_STYLE(o)) |
||
598 |
fatalx("option %s is not a style", name); |
||
599 |
memcpy(&o->style, &gc, sizeof o->style); |
||
600 |
return (o); |
||
601 |
} |
||
602 |
|||
603 |
enum options_table_scope |
||
604 |
options_scope_from_flags(struct args *args, int window, |
||
605 |
struct cmd_find_state *fs, struct options **oo, char **cause) |
||
606 |
{ |
||
607 |
struct session *s = fs->s; |
||
608 |
struct winlink *wl = fs->wl; |
||
609 |
const char *target= args_get(args, 't'); |
||
610 |
|||
611 |
if (args_has(args, 's')) { |
||
612 |
*oo = global_options; |
||
613 |
return (OPTIONS_TABLE_SERVER); |
||
614 |
} |
||
615 |
|||
616 |
if (window || args_has(args, 'w')) { |
||
617 |
if (args_has(args, 'g')) { |
||
618 |
*oo = global_w_options; |
||
619 |
return (OPTIONS_TABLE_WINDOW); |
||
620 |
} |
||
621 |
if (wl == NULL) { |
||
622 |
if (target != NULL) |
||
623 |
xasprintf(cause, "no such window: %s", target); |
||
624 |
else |
||
625 |
xasprintf(cause, "no current window"); |
||
626 |
return (OPTIONS_TABLE_NONE); |
||
627 |
} |
||
628 |
*oo = wl->window->options; |
||
629 |
return (OPTIONS_TABLE_WINDOW); |
||
630 |
} else { |
||
631 |
if (args_has(args, 'g')) { |
||
632 |
*oo = global_s_options; |
||
633 |
return (OPTIONS_TABLE_SESSION); |
||
634 |
} |
||
635 |
if (s == NULL) { |
||
636 |
if (target != NULL) |
||
637 |
xasprintf(cause, "no such session: %s", target); |
||
638 |
else |
||
639 |
xasprintf(cause, "no current session"); |
||
640 |
return (OPTIONS_TABLE_NONE); |
||
641 |
} |
||
642 |
*oo = s->options; |
||
643 |
return (OPTIONS_TABLE_SESSION); |
||
644 |
} |
||
645 |
} |
||
646 |
|||
647 |
void |
||
648 |
options_style_update_new(struct options *oo, struct options_entry *o) |
||
649 |
{ |
||
650 |
const char *newname = o->tableentry->style; |
||
651 |
struct options_entry *new; |
||
652 |
|||
653 |
if (newname == NULL) |
||
654 |
return; |
||
655 |
new = options_get_only(oo, newname); |
||
656 |
if (new == NULL) |
||
657 |
new = options_set_style(oo, newname, 0, "default"); |
||
658 |
|||
659 |
if (strstr(o->name, "-bg") != NULL) |
||
660 |
new->style.bg = o->number; |
||
661 |
else if (strstr(o->name, "-fg") != NULL) |
||
662 |
new->style.fg = o->number; |
||
663 |
else if (strstr(o->name, "-attr") != NULL) |
||
664 |
new->style.attr = o->number; |
||
665 |
} |
||
666 |
|||
667 |
void |
||
668 |
options_style_update_old(struct options *oo, struct options_entry *o) |
||
669 |
{ |
||
670 |
char newname[128]; |
||
671 |
int size; |
||
672 |
|||
673 |
size = strrchr(o->name, '-') - o->name; |
||
674 |
|||
675 |
xsnprintf(newname, sizeof newname, "%.*s-bg", size, o->name); |
||
676 |
if (options_get(oo, newname) != NULL) |
||
677 |
options_set_number(oo, newname, o->style.bg); |
||
678 |
|||
679 |
xsnprintf(newname, sizeof newname, "%.*s-fg", size, o->name); |
||
680 |
if (options_get(oo, newname) != NULL) |
||
681 |
options_set_number(oo, newname, o->style.fg); |
||
682 |
|||
683 |
xsnprintf(newname, sizeof newname, "%.*s-attr", size, o->name); |
||
684 |
if (options_get(oo, newname) != NULL) |
||
685 |
options_set_number(oo, newname, o->style.attr); |
||
686 |
} |
Generated by: GCOVR (Version 3.3) |