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