a146eda8e664cf04e2e1b6f515e3dfa770967d33
[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 "libvalidate.h"
25
26 enum dt_optype {
27         OP_UNKNOWN,
28         OP_NUMBER,
29         OP_STRING,
30         OP_FUNCTION
31 };
32
33 struct dt_fun;
34
35 struct dt_op {
36         enum dt_optype type;
37         const char *next;
38         int length;
39         int nextop;
40         union {
41                 bool boolean;
42                 double number;
43                 const char *string;
44                 struct dt_fun *function;
45         } value;
46 };
47
48 struct dt_state {
49         int pos;
50         int depth;
51         const char *value;
52         enum dt_type valtype;
53         struct dt_op stack[32];
54 };
55
56 struct dt_fun {
57         const char *name;
58         enum dt_type valtype;
59         bool (*call)(struct dt_state *s, int nargs);
60 };
61
62 static bool
63 dt_test_number(double number, const char *value)
64 {
65         char *e;
66         double n;
67
68         n = strtod(value, &e);
69
70         return (e > value && *e == 0 && n == number);
71 }
72
73 static bool
74 dt_test_string(const char *s, const char *end, const char *value)
75 {
76         bool esc = false;
77
78         while (*value)
79         {
80                 if (s > end)
81                         return false;
82
83                 if (!esc && *s == '\\')
84                 {
85                         s++;
86
87                         if (s >= end)
88                                 break;
89
90                         esc = true;
91                         continue;
92                 }
93
94                 if (*s != *value)
95                         return false;
96
97                 esc = false;
98                 value++;
99                 s++;
100         }
101
102         return (*s == *value || (s > end && *value == 0));
103 }
104
105 static bool
106 dt_step(struct dt_state *s);
107
108 static bool
109 dt_call(struct dt_state *s);
110
111 static bool
112 dt_type_or(struct dt_state *s, int nargs)
113 {
114         while (nargs--)
115                 if (dt_step(s))
116                         return true;
117
118         return false;
119 }
120
121 static bool
122 dt_type_and(struct dt_state *s, int nargs)
123 {
124         while (nargs--)
125                 if (!dt_step(s))
126                         return false;
127
128         return true;
129 }
130
131 static bool
132 dt_type_not(struct dt_state *s, int nargs)
133 {
134         if (!nargs)
135                 return false;
136
137         return !dt_step(s);
138 }
139
140 static bool
141 dt_type_neg(struct dt_state *s, int nargs)
142 {
143         bool rv;
144         const char *value = s->value;
145
146         if (!nargs)
147                 return false;
148
149         if (*s->value == '!')
150                 while (isspace(*++s->value));
151
152         rv = dt_step(s);
153         s->value = value;
154
155         return rv;
156 }
157
158 static bool
159 dt_type_list(struct dt_state *s, int nargs)
160 {
161         bool rv = true;
162         int pos = s->pos;
163         char *p, *str = strdup(s->value);
164         const char *value = s->value;
165
166         if (!str || !nargs)
167                 return false;
168
169         for (p = strtok(str, " \t"); p; p = strtok(NULL, " \t"))
170         {
171                 s->value = p;
172
173                 if (!dt_step(s))
174                 {
175                         rv = false;
176                         break;
177                 }
178
179                 s->pos = pos;
180         }
181
182         s->value = value;
183         free(str);
184
185         return rv;
186 }
187
188 static bool
189 dt_type_min(struct dt_state *s, int nargs)
190 {
191         int n;
192         char *e;
193
194         if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
195         {
196                 n = strtol(s->value, &e, 0);
197
198                 return (e > s->value && *e == 0 &&
199                         n >= s->stack[s->pos].value.number);
200         }
201
202         return false;
203 }
204
205 static bool
206 dt_type_max(struct dt_state *s, int nargs)
207 {
208         int n;
209         char *e;
210
211         if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
212         {
213                 n = strtol(s->value, &e, 0);
214
215                 return (e > s->value && *e == 0 &&
216                         n <= s->stack[s->pos].value.number);
217         }
218
219         return false;
220 }
221
222 static bool
223 dt_type_range(struct dt_state *s, int nargs)
224 {
225         int n;
226         char *e;
227
228         if (nargs >= 2 &&
229             s->stack[s->pos].type == OP_NUMBER &&
230             s->stack[s->pos + 1].type == OP_NUMBER)
231         {
232                 n = strtol(s->value, &e, 0);
233
234                 return (e > s->value && *e == 0 &&
235                         n >= s->stack[s->pos].value.number &&
236                         n <= s->stack[s->pos + 1].value.number);
237         }
238
239         return false;
240 }
241
242 static bool
243 dt_type_minlen(struct dt_state *s, int nargs)
244 {
245         if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
246                 return (strlen(s->value) >= s->stack[s->pos].value.number);
247
248         return false;
249 }
250
251 static bool
252 dt_type_maxlen(struct dt_state *s, int nargs)
253 {
254         if (nargs >= 1 && s->stack[s->pos].type == OP_NUMBER)
255                 return (strlen(s->value) <= s->stack[s->pos].value.number);
256
257         return false;
258 }
259
260 static bool
261 dt_type_rangelen(struct dt_state *s, int nargs)
262 {
263         if (nargs >= 2 &&
264             s->stack[s->pos].type == OP_NUMBER &&
265             s->stack[s->pos + 1].type == OP_NUMBER)
266                 return (strlen(s->value) >= s->stack[s->pos].value.number &&
267                                 strlen(s->value) <= s->stack[s->pos + 1].value.number);
268
269         return false;
270 }
271
272 static bool
273 dt_type_int(struct dt_state *s, int nargs)
274 {
275         char *e;
276
277         strtol(s->value, &e, 0);
278
279         return (e > s->value && *e == 0);
280 }
281
282 static bool
283 dt_type_uint(struct dt_state *s, int nargs)
284 {
285         int n;
286         char *e;
287
288         n = strtol(s->value, &e, 0);
289
290         return (e > s->value && *e == 0 && n >= 0);
291 }
292
293 static bool
294 dt_type_float(struct dt_state *s, int nargs)
295 {
296         char *e;
297
298         strtod(s->value, &e);
299
300         return (e > s->value && *e == 0);
301 }
302
303 static bool
304 dt_type_ufloat(struct dt_state *s, int nargs)
305 {
306         int n;
307         char *e;
308
309         n = strtod(s->value, &e);
310
311         return (e > s->value && *e == 0 && n >= 0.0);
312 }
313
314 static bool
315 dt_type_bool(struct dt_state *s, int nargs)
316 {
317         int i;
318         const char *values[] = {
319                 "0", "off", "false", "no",
320                 "1", "on", "true", "yes"
321         };
322
323         for (i = 0; i < sizeof(values) / sizeof(values[0]); i++)
324                 if (!strcasecmp(values[i], s->value))
325                         return true;
326
327         return false;
328 }
329
330 static bool
331 dt_type_string(struct dt_state *s, int nargs)
332 {
333         return true;
334 }
335
336 static bool
337 dt_type_ip4addr(struct dt_state *s, int nargs)
338 {
339         struct in6_addr a;
340         return inet_pton(AF_INET, s->value, &a);
341 }
342
343 static bool
344 dt_type_ip6addr(struct dt_state *s, int nargs)
345 {
346         struct in6_addr a;
347         return inet_pton(AF_INET6, s->value, &a);
348 }
349
350 static bool
351 dt_type_ipaddr(struct dt_state *s, int nargs)
352 {
353         return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
354 }
355
356 static bool
357 dt_type_netmask4(struct dt_state *s, int nargs)
358 {
359         int i;
360         struct in_addr a;
361
362         if (!inet_pton(AF_INET, s->value, &a))
363                 return false;
364
365         if (a.s_addr == 0)
366                 return true;
367
368         a.s_addr = ntohl(a.s_addr);
369
370         for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
371
372         return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
373 }
374
375 static bool
376 dt_type_netmask6(struct dt_state *s, int nargs)
377 {
378         int i;
379         struct in6_addr a;
380
381         if (!inet_pton(AF_INET6, s->value, &a))
382                 return false;
383
384         for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
385
386         if (i == 16)
387                 return true;
388
389         if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
390                 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
391                 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
392                 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
393                 (a.s6_addr[i] != 0))
394                 return false;
395
396         for (; (i < 16) && (a.s6_addr[i] == 0); i++);
397
398         return (i == 16);
399 }
400
401 static bool
402 dt_type_cidr4(struct dt_state *s, int nargs)
403 {
404         int n;
405         struct in_addr a;
406         char *p, buf[sizeof("255.255.255.255/32\0")];
407
408         if (strlen(s->value) >= sizeof(buf))
409                 return false;
410
411         strcpy(buf, s->value);
412         p = strchr(buf, '/');
413
414         if (p)
415         {
416                 *p++ = 0;
417
418                 n = strtoul(p, &p, 10);
419
420                 if ((*p != 0) || (n > 32))
421                         return false;
422         }
423
424         return inet_pton(AF_INET, buf, &a);
425 }
426
427 static bool
428 dt_type_cidr6(struct dt_state *s, int nargs)
429 {
430         int n;
431         struct in6_addr a;
432         char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
433
434         if (strlen(s->value) >= sizeof(buf))
435                 return false;
436
437         strcpy(buf, s->value);
438         p = strchr(buf, '/');
439
440         if (p)
441         {
442                 *p++ = 0;
443
444                 n = strtoul(p, &p, 10);
445
446                 if ((*p != 0) || (n > 128))
447                         return false;
448         }
449
450         return inet_pton(AF_INET6, buf, &a);
451 }
452
453 static bool
454 dt_type_cidr(struct dt_state *s, int nargs)
455 {
456         return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
457 }
458
459 static bool
460 dt_type_ipmask4(struct dt_state *s, int nargs)
461 {
462         bool rv;
463         struct in_addr a;
464         const char *value;
465         char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
466
467         if (strlen(s->value) >= sizeof(buf))
468                 return false;
469
470         strcpy(buf, s->value);
471         p = strchr(buf, '/');
472
473         if (p)
474         {
475                 *p++ = 0;
476
477                 value = s->value;
478                 s->value = p;
479                 rv = dt_type_netmask4(s, 0);
480                 s->value = value;
481
482                 if (!rv)
483                         return false;
484         }
485
486         return inet_pton(AF_INET, buf, &a);
487 }
488
489 static bool
490 dt_type_ipmask6(struct dt_state *s, int nargs)
491 {
492         bool rv;
493         struct in6_addr a;
494         const char *value;
495         char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
496                             "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
497
498         if (strlen(s->value) >= sizeof(buf))
499                 return false;
500
501         strcpy(buf, s->value);
502         p = strchr(buf, '/');
503
504         if (p)
505         {
506                 *p++ = 0;
507
508                 value = s->value;
509                 s->value = p;
510                 rv = dt_type_netmask6(s, 0);
511                 s->value = value;
512
513                 if (!rv)
514                         return false;
515         }
516
517         return inet_pton(AF_INET6, buf, &a);
518 }
519
520 static bool
521 dt_type_ipmask(struct dt_state *s, int nargs)
522 {
523         return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
524 }
525
526 static bool
527 dt_type_port(struct dt_state *s, int nargs)
528 {
529         int n;
530         char *e;
531
532         n = strtoul(s->value, &e, 10);
533
534         return (e > s->value && *e == 0 && n <= 65535);
535 }
536
537 static bool
538 dt_type_portrange(struct dt_state *s, int nargs)
539 {
540         int n, m;
541         char *e;
542
543         n = strtoul(s->value, &e, 10);
544
545         if (e == s->value || *e != '-')
546                 return false;
547
548         m = strtoul(e + 1, &e, 10);
549
550         return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
551 }
552
553 static bool
554 dt_type_macaddr(struct dt_state *s, int nargs)
555 {
556         return !!ether_aton(s->value);
557 }
558
559 static bool
560 dt_type_uciname(struct dt_state *s, int nargs)
561 {
562         const char *p;
563
564         for (p = s->value;
565              *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
566                     (*p >= '0' && *p <= '9') || (*p == '_'));
567                  p++);
568
569         return (*p == 0);
570 }
571
572 static bool
573 dt_type_wpakey(struct dt_state *s, int nargs)
574 {
575         int len = strlen(s->value);
576         const char *p = s->value;
577
578         if (len == 64)
579         {
580                 while (isxdigit(*p))
581                         p++;
582
583                 return (*p == 0);
584         }
585
586         return (len >= 8 && len <= 63);
587 }
588
589 static bool
590 dt_type_wepkey(struct dt_state *s, int nargs)
591 {
592         int len = strlen(s->value);
593         const char *p = s->value;
594
595         if (!strncmp(p, "s:", 2))
596         {
597                 len -= 2;
598                 p += 2;
599         }
600
601         if (len == 10 || len == 26)
602         {
603                 while (isxdigit(*p))
604                         p++;
605
606                 return (*p == 0);
607         }
608
609         return (len == 5 || len == 13);
610 }
611
612 static bool
613 dt_type_hostname(struct dt_state *s, int nargs)
614 {
615         const char *p, *last;
616
617         for (p = last = s->value; *p; p++)
618         {
619                 if (*p == '.')
620                 {
621                         if ((p - last) == 0 || (p - last) > 63)
622                                 return false;
623
624                         last = p + 1;
625                         continue;
626                 }
627                 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
628                          (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
629                 {
630                         continue;
631                 }
632
633                 return false;
634         }
635
636         return ((p - last) > 0 && (p - last) <= 255);
637 }
638
639 static bool
640 dt_type_host(struct dt_state *s, int nargs)
641 {
642         return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
643 }
644
645 static bool
646 dt_type_network(struct dt_state *s, int nargs)
647 {
648         return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
649 }
650
651 static bool
652 dt_type_phonedigit(struct dt_state *s, int nargs)
653 {
654         const char *p;
655
656         for (p = s->value;
657              *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
658                     (*p == '!') || (*p == '.'));
659                  p++);
660
661         return (*p == 0);
662 }
663
664 static bool
665 dt_type_directory(struct dt_state *s, int nargs)
666 {
667         struct stat st;
668         return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
669 }
670
671
672 static bool
673 dt_type_device(struct dt_state *s, int nargs)
674 {
675         struct stat st;
676         return (!stat(s->value, &st) &&
677                 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
678 }
679
680 static bool
681 dt_type_file(struct dt_state *s, int nargs)
682 {
683         struct stat st;
684         return (!stat(s->value, &st) && S_ISREG(st.st_mode));
685 }
686
687
688 static struct dt_fun dt_types[] = {
689         { "or",                         DT_INVALID,             dt_type_or                      },
690         { "and",                        DT_INVALID,             dt_type_and                     },
691         { "not",                        DT_INVALID,             dt_type_not                     },
692         { "neg",                        DT_INVALID,             dt_type_neg                     },
693         { "list",                       DT_INVALID,             dt_type_list            },
694         { "min",                        DT_NUMBER,              dt_type_min                     },
695         { "max",                        DT_NUMBER,              dt_type_max                     },
696         { "range",                      DT_NUMBER,              dt_type_range           },
697         { "minlength",          DT_STRING,              dt_type_minlen          },
698         { "maxlength",          DT_STRING,              dt_type_maxlen          },
699         { "rangelength",        DT_STRING,              dt_type_rangelen        },
700         { "integer",            DT_NUMBER,              dt_type_int                     },
701         { "uinteger",           DT_NUMBER,              dt_type_uint            },
702         { "float",                      DT_NUMBER,              dt_type_float           },
703         { "ufloat",                     DT_NUMBER,              dt_type_ufloat          },
704         { "bool",                       DT_BOOL,                dt_type_bool            },
705         { "string",                     DT_STRING,              dt_type_string          },
706         { "ip4addr",            DT_STRING,              dt_type_ip4addr         },
707         { "ip6addr",            DT_STRING,              dt_type_ip6addr         },
708         { "ipaddr",                     DT_STRING,              dt_type_ipaddr          },
709         { "cidr4",                      DT_STRING,              dt_type_cidr4           },
710         { "cidr6",                      DT_STRING,              dt_type_cidr6           },
711         { "cidr",                       DT_STRING,              dt_type_cidr            },
712         { "netmask4",           DT_STRING,              dt_type_netmask4        },
713         { "netmask6",           DT_STRING,              dt_type_netmask6        },
714         { "ipmask4",            DT_STRING,              dt_type_ipmask4         },
715         { "ipmask6",            DT_STRING,              dt_type_ipmask6         },
716         { "ipmask",                     DT_STRING,              dt_type_ipmask          },
717         { "port",                       DT_NUMBER,              dt_type_port            },
718         { "portrange",          DT_STRING,              dt_type_portrange       },
719         { "macaddr",            DT_STRING,              dt_type_macaddr         },
720         { "uciname",            DT_STRING,              dt_type_uciname         },
721         { "wpakey",                     DT_STRING,              dt_type_wpakey          },
722         { "wepkey",                     DT_STRING,              dt_type_wepkey          },
723         { "hostname",           DT_STRING,              dt_type_hostname        },
724         { "host",                       DT_STRING,              dt_type_host            },
725         { "network",            DT_STRING,              dt_type_network         },
726         { "phonedigit",         DT_STRING,              dt_type_phonedigit      },
727         { "directory",          DT_STRING,              dt_type_directory       },
728         { "device",                     DT_STRING,              dt_type_device          },
729         { "file",                       DT_STRING,              dt_type_file            },
730
731         { }
732 };
733
734 static struct dt_fun *
735 dt_lookup_function(const char *s, const char *e)
736 {
737         struct dt_fun *fun = dt_types;
738
739         while (fun->name)
740         {
741                 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
742                         return fun;
743
744                 fun++;
745         }
746
747         return NULL;
748 }
749
750 static bool
751 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
752 {
753         char q, *e;
754         const char *p;
755         bool esc;
756         double dval;
757         struct dt_fun *func;
758         struct dt_op *op = &s->stack[s->depth];
759
760         if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
761         {
762                 printf("Syntax error, expression too long\n");
763                 return false;
764         }
765
766         while (isspace(*label))
767                 label++;
768
769         /* test whether label is a float */
770         dval = strtod(label, &e);
771
772         if (e > label)
773         {
774                 op->next = e;
775                 op->type = OP_NUMBER;
776                 op->value.number = dval;
777                 op->nextop = ++s->depth;
778
779                 return true;
780         }
781         else if ((*label == '"') || (*label == '\''))
782         {
783                 for (p = label + 1, q = *label, esc = false; p <= end; p++)
784                 {
785                         if (esc)
786                         {
787                                 esc = false;
788                                 continue;
789                         }
790                         else if (*p == '\\')
791                         {
792                                 esc = true;
793                                 continue;
794                         }
795                         else if (*p == q)
796                         {
797                                 op->next = p + 1;
798                                 op->type = OP_STRING;
799                                 op->length = (p - label) - 2;
800                                 op->value.string = label + 1;
801                                 op->nextop = ++s->depth;
802
803                                 return true;
804                         }
805                 }
806
807                 printf("Syntax error, unterminated string\n");
808                 return false;
809         }
810         else if (*label)
811         {
812                 for (p = label;
813                      p <= end && ((*p >= 'A' && *p <= 'Z') ||
814                                   (*p >= 'a' && *p <= 'z') ||
815                                   (*p >= '0' && *p <= '9') ||
816                                   (*p == '_'));
817                      p++);
818
819                 func = dt_lookup_function(label, p);
820
821                 if (!func)
822                 {
823                         printf("Syntax error, unrecognized function\n");
824                         return false;
825                 }
826
827                 op->next = p;
828                 op->type = OP_FUNCTION;
829                 op->value.function = func;
830                 op->nextop = ++s->depth;
831
832                 return true;
833         }
834
835         printf("Syntax error, unexpected EOF\n");
836         return false;
837 }
838
839 static bool
840 dt_parse_list(struct dt_state *s, const char *code, const char *end);
841
842 static bool
843 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
844 {
845         struct dt_op *tok;
846
847         if (!dt_parse_atom(s, code, end))
848                 return false;
849
850         tok = &s->stack[s->depth - 1];
851
852         while (isspace(*tok->next))
853                 tok->next++;
854
855         if (tok->type == OP_FUNCTION)
856         {
857                 if (*tok->next == '(')
858                 {
859                         end--;
860
861                         while (isspace(*end) && end > tok->next + 1)
862                                 end--;
863
864                         return dt_parse_list(s, tok->next + 1, end);
865                 }
866                 else if (tok->next == end)
867                 {
868                         return dt_parse_list(s, tok->next, tok->next);
869                 }
870
871                 printf("Syntax error, expected '(' or EOF after function label\n");
872                 return false;
873         }
874         else if (tok->next == end)
875         {
876                 return true;
877         }
878
879         printf("Syntax error, expected ',' after literal\n");
880         return false;
881 }
882
883 static bool
884 dt_parse_list(struct dt_state *s, const char *code, const char *end)
885 {
886         char c;
887         bool esc;
888         int nest;
889         const char *p, *last;
890         struct dt_op *fptr;
891
892         if (!code)
893                 return false;
894
895         fptr = &s->stack[s->depth - 1];
896
897         for (nest = 0, p = last = code, esc = false, c = *p;
898              p <= end;
899              p++, c = (p < end) ? *p : '\0')
900         {
901                 if (esc)
902                 {
903                         esc = false;
904                         continue;
905                 }
906
907                 switch (c)
908                 {
909                 case '\\':
910                         esc = true;
911                         break;
912
913                 case '(':
914                         nest++;
915                         break;
916
917                 case ')':
918                         nest--;
919                         break;
920
921                 case ',':
922                 case '\0':
923                         if (nest <= 0)
924                         {
925                                 if (p > last)
926                                 {
927                                         if (!dt_parse_expr(last, p, s))
928                                                 return false;
929
930                                         fptr->length++;
931                                 }
932
933                                 last = p + 1;
934                         }
935
936                         break;
937                 }
938         }
939
940         fptr->nextop = s->depth;
941         return true;
942 }
943
944 static bool
945 dt_step(struct dt_state *s)
946 {
947         bool rv;
948         struct dt_op *op = &s->stack[s->pos];
949
950         switch (op->type)
951         {
952         case OP_NUMBER:
953                 rv = dt_test_number(op->value.number, s->value);
954                 break;
955
956         case OP_STRING:
957                 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
958                 break;
959
960         case OP_FUNCTION:
961                 rv = dt_call(s);
962                 break;
963
964         default:
965                 rv = false;
966                 break;
967         }
968
969         s->pos = op->nextop;
970         return rv;
971 }
972
973 static bool
974 dt_call(struct dt_state *s)
975 {
976         bool rv;
977         struct dt_op *fptr = &s->stack[s->pos];
978         struct dt_fun *func = fptr->value.function;
979
980         s->pos++;
981
982         rv = func->call(s, fptr->length);
983
984         if (rv && func->valtype)
985                 s->valtype = func->valtype;
986
987         s->pos = fptr->nextop;
988
989         return rv;
990 }
991
992 enum dt_type
993 dt_parse(const char *code, const char *value)
994 {
995         struct dt_state s = {
996                 .depth = 1,
997                 .stack = {
998                         {
999                                 .type = OP_FUNCTION,
1000                                 .value.function = &dt_types[0],
1001                                 .next = code
1002                         }
1003                 }
1004         };
1005
1006         if (!value || !*value)
1007                 return false;
1008
1009         if (!dt_parse_list(&s, code, code + strlen(code)))
1010                 return false;
1011
1012         s.value = value;
1013
1014         if (dt_call(&s))
1015                 return s.valtype;
1016
1017         return DT_INVALID;
1018 }