0628407285023e8b4c9dfa55e1b2d6303b410db0
[project/ubox.git] / validate / validate.c
1 /*
2 * Copyright (C) 2013 Jo-Philipp Wich <jow@openwrt.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <stdbool.h>
18 #include <ctype.h>
19
20 #include <arpa/inet.h>
21 #include <netinet/ether.h>
22 #include <sys/stat.h>
23
24 #include <sys/types.h>
25 #include <regex.h>
26
27 #include <uci.h>
28
29 #include "libvalidate.h"
30
31 enum dt_optype {
32 OP_UNKNOWN,
33 OP_NUMBER,
34 OP_STRING,
35 OP_FUNCTION
36 };
37
38 struct dt_fun;
39
40 struct dt_op {
41 enum dt_optype type;
42 const char *next;
43 int length;
44 int nextop;
45 union {
46 bool boolean;
47 double number;
48 const char *string;
49 struct dt_fun *function;
50 } value;
51 };
52
53 struct dt_state {
54 int pos;
55 int depth;
56 struct uci_context *ctx;
57 const char *value;
58 enum dt_type valtype;
59 struct dt_op stack[32];
60 };
61
62 struct dt_fun {
63 const char *name;
64 enum dt_type valtype;
65 bool (*call)(struct dt_state *s, int nargs);
66 };
67
68 static bool
69 dt_test_number(double number, const char *value)
70 {
71 char *e;
72 double n;
73
74 n = strtod(value, &e);
75
76 return (e > value && *e == 0 && n == number);
77 }
78
79 static bool
80 dt_test_string(const char *s, const char *end, const char *value)
81 {
82 bool esc = false;
83
84 while (*value)
85 {
86 if (s > end)
87 return false;
88
89 if (!esc && *s == '\\')
90 {
91 s++;
92
93 if (s >= end)
94 break;
95
96 esc = true;
97 continue;
98 }
99
100 if (*s != *value)
101 return false;
102
103 esc = false;
104 value++;
105 s++;
106 }
107
108 return (*s == *value || (s >= end && *value == 0));
109 }
110
111 static bool
112 dt_step(struct dt_state *s);
113
114 static bool
115 dt_call(struct dt_state *s);
116
117 #define dt_getint(n, v) \
118 ((n < nargs && s->stack[s->pos + n].type == OP_NUMBER) \
119 ? (v = s->stack[s->pos + n].value.number, 1) : 0)
120
121 static bool
122 dt_type_or(struct dt_state *s, int nargs)
123 {
124 while (nargs--)
125 if (dt_step(s))
126 return true;
127
128 return false;
129 }
130
131 static bool
132 dt_type_and(struct dt_state *s, int nargs)
133 {
134 while (nargs--)
135 if (!dt_step(s))
136 return false;
137
138 return true;
139 }
140
141 static bool
142 dt_type_not(struct dt_state *s, int nargs)
143 {
144 if (!nargs)
145 return false;
146
147 return !dt_step(s);
148 }
149
150 static bool
151 dt_type_neg(struct dt_state *s, int nargs)
152 {
153 bool rv;
154 const char *value = s->value;
155
156 if (!nargs)
157 return false;
158
159 if (*s->value == '!')
160 while (isspace(*++s->value));
161
162 rv = dt_step(s);
163 s->value = value;
164
165 return rv;
166 }
167
168 static bool
169 dt_type_list(struct dt_state *s, int nargs)
170 {
171 bool rv = true;
172 int pos = s->pos;
173 char *p, *str = strdup(s->value);
174 const char *value = s->value;
175
176 if (!str || !nargs) {
177 free(str);
178 return false;
179 }
180
181 for (p = strtok(str, " \t"); p; p = strtok(NULL, " \t"))
182 {
183 s->value = p;
184
185 if (!dt_step(s))
186 {
187 rv = false;
188 break;
189 }
190
191 s->pos = pos;
192 }
193
194 s->value = value;
195 free(str);
196
197 return rv;
198 }
199
200 static bool
201 dt_type_min(struct dt_state *s, int nargs)
202 {
203 int n, min;
204 char *e;
205
206 if (dt_getint(0, min))
207 {
208 n = strtol(s->value, &e, 0);
209 return (e > s->value && *e == 0 && n >= min);
210 }
211
212 return false;
213 }
214
215 static bool
216 dt_type_max(struct dt_state *s, int nargs)
217 {
218 int n, max;
219 char *e;
220
221 if (dt_getint(0, max))
222 {
223 n = strtol(s->value, &e, 0);
224 return (e > s->value && *e == 0 && n <= max);
225 }
226
227 return false;
228 }
229
230 static bool
231 dt_type_range(struct dt_state *s, int nargs)
232 {
233 int n, min, max;
234 char *e;
235
236 if (dt_getint(0, min) && dt_getint(1, max))
237 {
238 n = strtol(s->value, &e, 0);
239 return (e > s->value && *e == 0 && n >= min && n <= max);
240 }
241
242 return false;
243 }
244
245 static bool
246 dt_type_minlen(struct dt_state *s, int nargs)
247 {
248 int min;
249
250 if (dt_getint(0, min))
251 return (strlen(s->value) >= min);
252
253 return false;
254 }
255
256 static bool
257 dt_type_maxlen(struct dt_state *s, int nargs)
258 {
259 int max;
260
261 if (dt_getint(0, max))
262 return (strlen(s->value) <= max);
263
264 return false;
265 }
266
267 static bool
268 dt_type_rangelen(struct dt_state *s, int nargs)
269 {
270 int min, max;
271 int len = strlen(s->value);
272
273 if (dt_getint(0, min) && dt_getint(1, max))
274 return (len >= min && len <= max);
275
276 return false;
277 }
278
279 static bool
280 dt_type_int(struct dt_state *s, int nargs)
281 {
282 char *e;
283 int base = 0;
284
285 if (!isxdigit(*s->value) && *s->value != '-')
286 return false;
287
288 dt_getint(0, base);
289 strtol(s->value, &e, base);
290
291 return (e > s->value && *e == 0);
292 }
293
294 static bool
295 dt_type_uint(struct dt_state *s, int nargs)
296 {
297 char *e;
298 int base = 0;
299
300 if (!isxdigit(*s->value))
301 return false;
302
303 dt_getint(0, base);
304 strtoul(s->value, &e, base);
305
306 return (e > s->value && *e == 0);
307 }
308
309 static bool
310 dt_type_float(struct dt_state *s, int nargs)
311 {
312 char *e;
313
314 strtod(s->value, &e);
315
316 return (e > s->value && *e == 0);
317 }
318
319 static bool
320 dt_type_ufloat(struct dt_state *s, int nargs)
321 {
322 int n;
323 char *e;
324
325 n = strtod(s->value, &e);
326
327 return (e > s->value && *e == 0 && n >= 0.0);
328 }
329
330 static bool
331 dt_type_bool(struct dt_state *s, int nargs)
332 {
333 int i;
334 const char *values[] = {
335 "0", "off", "false", "no", "disabled",
336 "1", "on", "true", "yes", "enabled"
337 };
338
339 for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
340 if (!strcasecmp(values[i], s->value))
341 return true;
342
343 return false;
344 }
345
346 static bool
347 dt_type_string(struct dt_state *s, int nargs)
348 {
349 int min, max;
350 int len = strlen(s->value);
351
352 if (dt_getint(0, min) && (len < min))
353 return false;
354
355 if (dt_getint(1, max) && (len > max))
356 return false;
357
358 return true;
359 }
360
361 static bool
362 dt_type_hexstring(struct dt_state *s, int nargs)
363 {
364 int min, max;
365 int len = strlen(s->value);
366 const char *p;
367
368 if (len % 2)
369 return false;
370
371 if (dt_getint(0, min) && (len < min))
372 return false;
373
374 if (dt_getint(1, max) && (len > max))
375 return false;
376
377 for (p = s->value; *p; p++)
378 if (!isxdigit(*p))
379 return false;
380
381 return true;
382 }
383
384 static bool
385 dt_type_ip4addr(struct dt_state *s, int nargs)
386 {
387 struct in6_addr a;
388 return inet_pton(AF_INET, s->value, &a);
389 }
390
391 static bool
392 dt_type_ip6addr(struct dt_state *s, int nargs)
393 {
394 struct in6_addr a;
395 return inet_pton(AF_INET6, s->value, &a);
396 }
397
398 static bool
399 dt_type_ipaddr(struct dt_state *s, int nargs)
400 {
401 return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
402 }
403
404 static bool
405 dt_type_netmask4(struct dt_state *s, int nargs)
406 {
407 int i;
408 struct in_addr a;
409
410 if (!inet_pton(AF_INET, s->value, &a))
411 return false;
412
413 if (a.s_addr == 0)
414 return true;
415
416 a.s_addr = ntohl(a.s_addr);
417
418 for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
419
420 return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
421 }
422
423 static bool
424 dt_type_netmask6(struct dt_state *s, int nargs)
425 {
426 int i;
427 struct in6_addr a;
428
429 if (!inet_pton(AF_INET6, s->value, &a))
430 return false;
431
432 for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
433
434 if (i == 16)
435 return true;
436
437 if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
438 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
439 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
440 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
441 (a.s6_addr[i] != 0))
442 return false;
443
444 for (; (i < 16) && (a.s6_addr[i] == 0); i++);
445
446 return (i == 16);
447 }
448
449 static bool
450 dt_type_cidr4(struct dt_state *s, int nargs)
451 {
452 int n;
453 struct in_addr a;
454 char *p, buf[sizeof("255.255.255.255/32\0")];
455
456 if (strlen(s->value) >= sizeof(buf))
457 return false;
458
459 strcpy(buf, s->value);
460 p = strchr(buf, '/');
461
462 if (p)
463 {
464 *p++ = 0;
465
466 n = strtoul(p, &p, 10);
467
468 if ((*p != 0) || (n > 32))
469 return false;
470 }
471
472 return inet_pton(AF_INET, buf, &a);
473 }
474
475 static bool
476 dt_type_cidr6(struct dt_state *s, int nargs)
477 {
478 int n;
479 struct in6_addr a;
480 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
481
482 if (strlen(s->value) >= sizeof(buf))
483 return false;
484
485 strcpy(buf, s->value);
486 p = strchr(buf, '/');
487
488 if (p)
489 {
490 *p++ = 0;
491
492 n = strtoul(p, &p, 10);
493
494 if ((*p != 0) || (n > 128))
495 return false;
496 }
497
498 return inet_pton(AF_INET6, buf, &a);
499 }
500
501 static bool
502 dt_type_cidr(struct dt_state *s, int nargs)
503 {
504 return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
505 }
506
507 static bool
508 dt_type_ipmask4(struct dt_state *s, int nargs)
509 {
510 bool rv;
511 struct in_addr a;
512 const char *value;
513 char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
514
515 if (strlen(s->value) >= sizeof(buf))
516 return false;
517
518 strcpy(buf, s->value);
519 p = strchr(buf, '/');
520
521 if (p)
522 {
523 *p++ = 0;
524
525 value = s->value;
526 s->value = p;
527 rv = dt_type_netmask4(s, 0);
528 s->value = value;
529
530 if (!rv)
531 return false;
532 }
533
534 return inet_pton(AF_INET, buf, &a);
535 }
536
537 static bool
538 dt_type_ipmask6(struct dt_state *s, int nargs)
539 {
540 bool rv;
541 struct in6_addr a;
542 const char *value;
543 char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
544 "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
545
546 if (strlen(s->value) >= sizeof(buf))
547 return false;
548
549 strcpy(buf, s->value);
550 p = strchr(buf, '/');
551
552 if (p)
553 {
554 *p++ = 0;
555
556 value = s->value;
557 s->value = p;
558 rv = dt_type_netmask6(s, 0);
559 s->value = value;
560
561 if (!rv)
562 return false;
563 }
564
565 return inet_pton(AF_INET6, buf, &a);
566 }
567
568 static bool
569 dt_type_ipmask(struct dt_state *s, int nargs)
570 {
571 return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
572 }
573
574 static bool
575 dt_type_port(struct dt_state *s, int nargs)
576 {
577 int n;
578 char *e;
579
580 n = strtoul(s->value, &e, 10);
581
582 return (e > s->value && *e == 0 && n <= 65535);
583 }
584
585 static bool
586 dt_type_portrange(struct dt_state *s, int nargs)
587 {
588 int n, m;
589 char *e;
590
591 n = strtoul(s->value, &e, 10);
592
593 if (e == s->value || *e != '-')
594 return false;
595
596 m = strtoul(e + 1, &e, 10);
597
598 return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
599 }
600
601 static bool
602 dt_type_macaddr(struct dt_state *s, int nargs)
603 {
604 return !!ether_aton(s->value);
605 }
606
607 static bool
608 dt_type_uciname(struct dt_state *s, int nargs)
609 {
610 const char *p;
611
612 for (p = s->value;
613 *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
614 (*p >= '0' && *p <= '9') || (*p == '_'));
615 p++);
616
617 return (*p == 0);
618 }
619
620 static bool
621 dt_type_wpakey(struct dt_state *s, int nargs)
622 {
623 int len = strlen(s->value);
624 const char *p = s->value;
625
626 if (len == 64)
627 {
628 while (isxdigit(*p))
629 p++;
630
631 return (*p == 0);
632 }
633
634 return (len >= 8 && len <= 63);
635 }
636
637 static bool
638 dt_type_wepkey(struct dt_state *s, int nargs)
639 {
640 int len = strlen(s->value);
641 const char *p = s->value;
642
643 if (!strncmp(p, "s:", 2))
644 {
645 len -= 2;
646 p += 2;
647 }
648
649 if (len == 10 || len == 26)
650 {
651 while (isxdigit(*p))
652 p++;
653
654 return (*p == 0);
655 }
656
657 return (len == 5 || len == 13);
658 }
659
660 static bool
661 dt_type_hostname(struct dt_state *s, int nargs)
662 {
663 const char *p, *last;
664
665 for (p = last = s->value; *p; p++)
666 {
667 if (*p == '.')
668 {
669 if ((p - last) == 0 || (p - last) > 63)
670 return false;
671
672 last = p + 1;
673 continue;
674 }
675 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
676 (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
677 {
678 continue;
679 }
680
681 return false;
682 }
683
684 return ((p - last) > 0 && (p - last) <= 255);
685 }
686
687 static bool
688 dt_type_host(struct dt_state *s, int nargs)
689 {
690 return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
691 }
692
693 static bool
694 dt_type_network(struct dt_state *s, int nargs)
695 {
696 return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
697 }
698
699 static bool
700 dt_type_phonedigit(struct dt_state *s, int nargs)
701 {
702 const char *p;
703
704 for (p = s->value;
705 *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
706 (*p == '!') || (*p == '.'));
707 p++);
708
709 return (*p == 0);
710 }
711
712 static bool
713 dt_type_directory(struct dt_state *s, int nargs)
714 {
715 struct stat st;
716 return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
717 }
718
719
720 static bool
721 dt_type_device(struct dt_state *s, int nargs)
722 {
723 struct stat st;
724 return (!stat(s->value, &st) &&
725 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
726 }
727
728 static bool
729 dt_type_file(struct dt_state *s, int nargs)
730 {
731 struct stat st;
732 return (!stat(s->value, &st) && S_ISREG(st.st_mode));
733 }
734
735 static bool
736 dt_type_regex(struct dt_state *s, int nargs)
737 {
738 bool rv;
739 int relen;
740 regex_t pattern;
741 char *re = NULL;
742
743 if (nargs < 1 || s->stack[s->pos].type != OP_STRING)
744 return false;
745
746 relen = s->stack[s->pos].length;
747 re = alloca(relen + 3);
748
749 if (!re)
750 return false;
751
752 memset(re, 0, relen + 3);
753 memcpy(re + 1, s->stack[s->pos].value.string, relen);
754
755 re[0] = '^';
756 re[relen + 1] = '$';
757
758 if (regcomp(&pattern, re, REG_EXTENDED | REG_NOSUB))
759 return false;
760
761 rv = !regexec(&pattern, s->value, 0, NULL, 0);
762
763 regfree(&pattern);
764
765 return rv;
766 }
767
768 static void *
769 dt_uci_lookup(struct dt_state *s, const char *pkg,
770 const char *sct, const char *opt, enum uci_type type)
771 {
772 struct uci_ptr ptr = {
773 .package = pkg,
774 .section = sct,
775 .option = opt
776 };
777
778 if (!s->ctx || uci_lookup_ptr(s->ctx, &ptr, NULL, false) ||
779 !(ptr.flags & UCI_LOOKUP_COMPLETE))
780 return NULL;
781
782 if (ptr.last->type != type)
783 return NULL;
784
785 switch (type)
786 {
787 case UCI_TYPE_PACKAGE:
788 return uci_to_package(ptr.last);
789
790 case UCI_TYPE_SECTION:
791 return uci_to_section(ptr.last);
792
793 case UCI_TYPE_OPTION:
794 return uci_to_option(ptr.last);
795
796 default:
797 return NULL;
798 }
799 }
800
801 static bool
802 dt_uci_cmp(struct dt_state *s,
803 const char *pkg, const char *sct, const char *opt)
804 {
805 struct uci_element *e;
806 struct uci_option *o = dt_uci_lookup(s, pkg, sct, opt, UCI_TYPE_OPTION);
807
808 if (!o)
809 return false;
810
811 switch (o->type)
812 {
813 case UCI_TYPE_STRING:
814 if (!strcmp(s->value, o->v.string))
815 return true;
816 break;
817
818 case UCI_TYPE_LIST:
819 uci_foreach_element(&o->v.list, e)
820 if (!strcmp(s->value, e->name))
821 return true;
822 break;
823 }
824
825 return false;
826 }
827
828 static bool
829 dt_type_uci(struct dt_state *s, int nargs)
830 {
831 int i, len;
832 struct uci_element *e;
833 struct uci_package *p;
834 char *cso[3] = { };
835
836 if (!s->ctx)
837 return false;
838
839 for (i = 0; i < nargs && i < 3; i++)
840 {
841 if (s->stack[s->pos + i].type != OP_STRING)
842 continue;
843
844 len = s->stack[s->pos + i].length;
845 cso[i] = alloca(len + 1);
846
847 if (!cso[i])
848 continue;
849
850 memset(cso[i], 0, len + 1);
851 memcpy(cso[i], s->stack[s->pos + i].value.string, len);
852 }
853
854 if (!cso[0] || !cso[1] || (*cso[1] != '@' && !cso[2]))
855 return false;
856
857 if (*cso[1] != '@')
858 return dt_uci_cmp(s, cso[0], cso[1], cso[2]);
859
860 p = dt_uci_lookup(s, cso[0], NULL, NULL, UCI_TYPE_PACKAGE);
861
862 if (!p)
863 return false;
864
865 uci_foreach_element(&p->sections, e)
866 {
867 if (strcmp(uci_to_section(e)->type, cso[1] + 1))
868 continue;
869
870 if (!cso[2])
871 {
872 if (!strcmp(s->value, e->name))
873 return true;
874 }
875 else
876 {
877 if (dt_uci_cmp(s, cso[0], e->name, cso[2]))
878 return true;
879 }
880 }
881
882 return false;
883 }
884
885
886 static struct dt_fun dt_types[] = {
887 { "or", DT_INVALID, dt_type_or },
888 { "and", DT_INVALID, dt_type_and },
889 { "not", DT_INVALID, dt_type_not },
890 { "neg", DT_INVALID, dt_type_neg },
891 { "list", DT_INVALID, dt_type_list },
892 { "min", DT_NUMBER, dt_type_min },
893 { "max", DT_NUMBER, dt_type_max },
894 { "range", DT_NUMBER, dt_type_range },
895 { "minlength", DT_STRING, dt_type_minlen },
896 { "maxlength", DT_STRING, dt_type_maxlen },
897 { "rangelength", DT_STRING, dt_type_rangelen },
898 { "integer", DT_NUMBER, dt_type_int },
899 { "uinteger", DT_NUMBER, dt_type_uint },
900 { "float", DT_NUMBER, dt_type_float },
901 { "ufloat", DT_NUMBER, dt_type_ufloat },
902 { "bool", DT_BOOL, dt_type_bool },
903 { "string", DT_STRING, dt_type_string },
904 { "hexstring", DT_STRING, dt_type_hexstring },
905 { "ip4addr", DT_STRING, dt_type_ip4addr },
906 { "ip6addr", DT_STRING, dt_type_ip6addr },
907 { "ipaddr", DT_STRING, dt_type_ipaddr },
908 { "cidr4", DT_STRING, dt_type_cidr4 },
909 { "cidr6", DT_STRING, dt_type_cidr6 },
910 { "cidr", DT_STRING, dt_type_cidr },
911 { "netmask4", DT_STRING, dt_type_netmask4 },
912 { "netmask6", DT_STRING, dt_type_netmask6 },
913 { "ipmask4", DT_STRING, dt_type_ipmask4 },
914 { "ipmask6", DT_STRING, dt_type_ipmask6 },
915 { "ipmask", DT_STRING, dt_type_ipmask },
916 { "port", DT_NUMBER, dt_type_port },
917 { "portrange", DT_STRING, dt_type_portrange },
918 { "macaddr", DT_STRING, dt_type_macaddr },
919 { "uciname", DT_STRING, dt_type_uciname },
920 { "wpakey", DT_STRING, dt_type_wpakey },
921 { "wepkey", DT_STRING, dt_type_wepkey },
922 { "hostname", DT_STRING, dt_type_hostname },
923 { "host", DT_STRING, dt_type_host },
924 { "network", DT_STRING, dt_type_network },
925 { "phonedigit", DT_STRING, dt_type_phonedigit },
926 { "directory", DT_STRING, dt_type_directory },
927 { "device", DT_STRING, dt_type_device },
928 { "file", DT_STRING, dt_type_file },
929 { "regex", DT_STRING, dt_type_regex },
930 { "uci", DT_STRING, dt_type_uci },
931
932 { }
933 };
934
935 static struct dt_fun *
936 dt_lookup_function(const char *s, const char *e)
937 {
938 struct dt_fun *fun = dt_types;
939
940 while (fun->name)
941 {
942 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
943 return fun;
944
945 fun++;
946 }
947
948 return NULL;
949 }
950
951 static bool
952 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
953 {
954 char q, *e;
955 const char *p;
956 bool esc;
957 double dval;
958 struct dt_fun *func;
959 struct dt_op *op = &s->stack[s->depth];
960
961 if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
962 {
963 printf("Syntax error, expression too long\n");
964 return false;
965 }
966
967 while (isspace(*label))
968 label++;
969
970 /* test whether label is a float */
971 dval = strtod(label, &e);
972
973 if (e > label)
974 {
975 op->next = e;
976 op->type = OP_NUMBER;
977 op->value.number = dval;
978 op->nextop = ++s->depth;
979
980 return true;
981 }
982 else if ((*label == '"') || (*label == '\''))
983 {
984 for (p = label + 1, q = *label, esc = false; p <= end; p++)
985 {
986 if (esc)
987 {
988 esc = false;
989 continue;
990 }
991 else if (*p == '\\')
992 {
993 esc = true;
994 continue;
995 }
996 else if (*p == q)
997 {
998 op->next = p + 1;
999 op->type = OP_STRING;
1000 op->length = (p - label) - 1;
1001 op->value.string = label + 1;
1002 op->nextop = ++s->depth;
1003
1004 return true;
1005 }
1006 }
1007
1008 printf("Syntax error, unterminated string\n");
1009 return false;
1010 }
1011 else if (*label)
1012 {
1013 for (p = label;
1014 p <= end && ((*p >= 'A' && *p <= 'Z') ||
1015 (*p >= 'a' && *p <= 'z') ||
1016 (*p >= '0' && *p <= '9') ||
1017 (*p == '_'));
1018 p++);
1019
1020 func = dt_lookup_function(label, p);
1021
1022 if (!func)
1023 {
1024 printf("Syntax error, unrecognized function\n");
1025 return false;
1026 }
1027
1028 op->next = p;
1029 op->type = OP_FUNCTION;
1030 op->value.function = func;
1031 op->nextop = ++s->depth;
1032
1033 return true;
1034 }
1035
1036 printf("Syntax error, unexpected EOF\n");
1037 return false;
1038 }
1039
1040 static bool
1041 dt_parse_list(struct dt_state *s, const char *code, const char *end);
1042
1043 static bool
1044 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
1045 {
1046 struct dt_op *tok;
1047
1048 if (!dt_parse_atom(s, code, end))
1049 return false;
1050
1051 tok = &s->stack[s->depth - 1];
1052
1053 while (isspace(*tok->next))
1054 tok->next++;
1055
1056 if (tok->type == OP_FUNCTION)
1057 {
1058 if (*tok->next == '(')
1059 {
1060 end--;
1061
1062 while (isspace(*end) && end > tok->next + 1)
1063 end--;
1064
1065 return dt_parse_list(s, tok->next + 1, end);
1066 }
1067 else if (tok->next == end)
1068 {
1069 return dt_parse_list(s, tok->next, tok->next);
1070 }
1071
1072 printf("Syntax error, expected '(' or EOF after function label\n");
1073 return false;
1074 }
1075 else if (tok->next == end)
1076 {
1077 return true;
1078 }
1079
1080 printf("Syntax error, expected ',' after literal\n");
1081 return false;
1082 }
1083
1084 static bool
1085 dt_parse_list(struct dt_state *s, const char *code, const char *end)
1086 {
1087 char c;
1088 bool esc;
1089 int nest;
1090 const char *p, *last;
1091 struct dt_op *fptr;
1092
1093 if (!code)
1094 return false;
1095
1096 fptr = &s->stack[s->depth - 1];
1097
1098 for (nest = 0, p = last = code, esc = false, c = *p;
1099 p <= end;
1100 p++, c = (p < end) ? *p : '\0')
1101 {
1102 if (esc)
1103 {
1104 esc = false;
1105 continue;
1106 }
1107
1108 switch (c)
1109 {
1110 case '\\':
1111 esc = true;
1112 break;
1113
1114 case '(':
1115 nest++;
1116 break;
1117
1118 case ')':
1119 nest--;
1120 break;
1121
1122 case ',':
1123 case '\0':
1124 if (nest <= 0)
1125 {
1126 if (p > last)
1127 {
1128 if (!dt_parse_expr(last, p, s))
1129 return false;
1130
1131 fptr->length++;
1132 }
1133
1134 last = p + 1;
1135 }
1136
1137 break;
1138 }
1139 }
1140
1141 fptr->nextop = s->depth;
1142 return true;
1143 }
1144
1145 static bool
1146 dt_step(struct dt_state *s)
1147 {
1148 bool rv;
1149 struct dt_op *op = &s->stack[s->pos];
1150
1151 switch (op->type)
1152 {
1153 case OP_NUMBER:
1154 rv = dt_test_number(op->value.number, s->value);
1155 if (rv)
1156 s->valtype = DT_NUMBER;
1157 break;
1158
1159 case OP_STRING:
1160 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
1161 if (rv)
1162 s->valtype = DT_STRING;
1163 break;
1164
1165 case OP_FUNCTION:
1166 rv = dt_call(s);
1167 break;
1168
1169 default:
1170 rv = false;
1171 break;
1172 }
1173
1174 s->pos = op->nextop;
1175 return rv;
1176 }
1177
1178 static bool
1179 dt_call(struct dt_state *s)
1180 {
1181 bool rv;
1182 struct dt_op *fptr = &s->stack[s->pos];
1183 struct dt_fun *func = fptr->value.function;
1184
1185 s->pos++;
1186
1187 rv = func->call(s, fptr->length);
1188
1189 if (rv && func->valtype)
1190 s->valtype = func->valtype;
1191
1192 s->pos = fptr->nextop;
1193
1194 return rv;
1195 }
1196
1197 enum dt_type
1198 dt_parse(const char *code, const char *value)
1199 {
1200 enum dt_type rv = DT_INVALID;
1201
1202 struct dt_state s = {
1203 .depth = 1,
1204 .stack = {
1205 {
1206 .type = OP_FUNCTION,
1207 .value.function = &dt_types[0],
1208 .next = code
1209 }
1210 }
1211 };
1212
1213 if (!value || !*value)
1214 return false;
1215
1216 if (!dt_parse_list(&s, code, code + strlen(code)))
1217 return false;
1218
1219 s.ctx = uci_alloc_context();
1220 s.value = value;
1221
1222 if (dt_call(&s))
1223 rv = s.valtype;
1224
1225 if (s.ctx)
1226 uci_free_context(s.ctx);
1227
1228 return rv;
1229 }