add data type validator
[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_ip4addr(struct dt_state *s, int nargs)
318 {
319         struct in6_addr a;
320         return inet_pton(AF_INET, s->value, &a);
321 }
322
323 static bool
324 dt_type_ip6addr(struct dt_state *s, int nargs)
325 {
326         struct in6_addr a;
327         return inet_pton(AF_INET6, s->value, &a);
328 }
329
330 static bool
331 dt_type_ipaddr(struct dt_state *s, int nargs)
332 {
333         return (dt_type_ip4addr(s, 0) || dt_type_ip6addr(s, 0));
334 }
335
336 static bool
337 dt_type_netmask4(struct dt_state *s, int nargs)
338 {
339         int i;
340         struct in_addr a;
341
342         if (!inet_pton(AF_INET, s->value, &a))
343                 return false;
344
345         if (a.s_addr == 0)
346                 return true;
347
348         a.s_addr = ntohl(a.s_addr);
349
350         for (i = 0; (i < 32) && !(a.s_addr & (1 << i)); i++);
351
352         return ((uint32_t)(~((1 << i) - 1)) == a.s_addr);
353 }
354
355 static bool
356 dt_type_netmask6(struct dt_state *s, int nargs)
357 {
358         int i;
359         struct in6_addr a;
360
361         if (!inet_pton(AF_INET6, s->value, &a))
362                 return false;
363
364         for (i = 0; (i < 16) && (a.s6_addr[i] == 0xFF); i++);
365
366         if (i == 16)
367                 return true;
368
369         if ((a.s6_addr[i] != 255) && (a.s6_addr[i] != 254) &&
370                 (a.s6_addr[i] != 252) && (a.s6_addr[i] != 248) &&
371                 (a.s6_addr[i] != 240) && (a.s6_addr[i] != 224) &&
372                 (a.s6_addr[i] != 192) && (a.s6_addr[i] != 128) &&
373                 (a.s6_addr[i] != 0))
374                 return false;
375
376         for (; (i < 16) && (a.s6_addr[i] == 0); i++);
377
378         return (i == 16);
379 }
380
381 static bool
382 dt_type_cidr4(struct dt_state *s, int nargs)
383 {
384         int n;
385         struct in_addr a;
386         char *p, buf[sizeof("255.255.255.255/32\0")];
387
388         if (strlen(s->value) >= sizeof(buf))
389                 return false;
390
391         strcpy(buf, s->value);
392         p = strchr(buf, '/');
393
394         if (p)
395         {
396                 *p++ = 0;
397
398                 n = strtoul(p, &p, 10);
399
400                 if ((*p != 0) || (n > 32))
401                         return false;
402         }
403
404         return inet_pton(AF_INET, buf, &a);
405 }
406
407 static bool
408 dt_type_cidr6(struct dt_state *s, int nargs)
409 {
410         int n;
411         struct in6_addr a;
412         char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/128\0")];
413
414         if (strlen(s->value) >= sizeof(buf))
415                 return false;
416
417         strcpy(buf, s->value);
418         p = strchr(buf, '/');
419
420         if (p)
421         {
422                 *p++ = 0;
423
424                 n = strtoul(p, &p, 10);
425
426                 if ((*p != 0) || (n > 128))
427                         return false;
428         }
429
430         return inet_pton(AF_INET6, buf, &a);
431 }
432
433 static bool
434 dt_type_cidr(struct dt_state *s, int nargs)
435 {
436         return (dt_type_cidr4(s, 0) || dt_type_cidr6(s, 0));
437 }
438
439 static bool
440 dt_type_ipmask4(struct dt_state *s, int nargs)
441 {
442         bool rv;
443         struct in_addr a;
444         const char *value;
445         char *p, buf[sizeof("255.255.255.255/255.255.255.255\0")];
446
447         if (strlen(s->value) >= sizeof(buf))
448                 return false;
449
450         strcpy(buf, s->value);
451         p = strchr(buf, '/');
452
453         if (p)
454         {
455                 *p++ = 0;
456
457                 value = s->value;
458                 s->value = p;
459                 rv = dt_type_netmask4(s, 0);
460                 s->value = value;
461
462                 if (!rv)
463                         return false;
464         }
465
466         return inet_pton(AF_INET, buf, &a);
467 }
468
469 static bool
470 dt_type_ipmask6(struct dt_state *s, int nargs)
471 {
472         bool rv;
473         struct in6_addr a;
474         const char *value;
475         char *p, buf[sizeof("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255/"
476                             "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:255.255.255.255\0")];
477
478         if (strlen(s->value) >= sizeof(buf))
479                 return false;
480
481         strcpy(buf, s->value);
482         p = strchr(buf, '/');
483
484         if (p)
485         {
486                 *p++ = 0;
487
488                 value = s->value;
489                 s->value = p;
490                 rv = dt_type_netmask6(s, 0);
491                 s->value = value;
492
493                 if (!rv)
494                         return false;
495         }
496
497         return inet_pton(AF_INET6, buf, &a);
498 }
499
500 static bool
501 dt_type_ipmask(struct dt_state *s, int nargs)
502 {
503         return (dt_type_ipmask4(s, 0) || dt_type_ipmask6(s, 0));
504 }
505
506 static bool
507 dt_type_port(struct dt_state *s, int nargs)
508 {
509         int n;
510         char *e;
511
512         n = strtoul(s->value, &e, 10);
513
514         return (e > s->value && *e == 0 && n <= 65535);
515 }
516
517 static bool
518 dt_type_portrange(struct dt_state *s, int nargs)
519 {
520         int n, m;
521         char *e;
522
523         n = strtoul(s->value, &e, 10);
524
525         if (e == s->value || *e != '-')
526                 return false;
527
528         m = strtoul(e + 1, &e, 10);
529
530         return (*e == 0 && n <= 65535 && m <= 65535 && n <= m);
531 }
532
533 static bool
534 dt_type_macaddr(struct dt_state *s, int nargs)
535 {
536         return !!ether_aton(s->value);
537 }
538
539 static bool
540 dt_type_uciname(struct dt_state *s, int nargs)
541 {
542         const char *p;
543
544         for (p = s->value;
545              *p && ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
546                     (*p >= '0' && *p <= '9') || (*p == '_'));
547                  p++);
548
549         return (*p == 0);
550 }
551
552 static bool
553 dt_type_wpakey(struct dt_state *s, int nargs)
554 {
555         int len = strlen(s->value);
556         const char *p = s->value;
557
558         if (len == 64)
559         {
560                 while (isxdigit(*p))
561                         p++;
562
563                 return (*p == 0);
564         }
565
566         return (len >= 8 && len <= 63);
567 }
568
569 static bool
570 dt_type_wepkey(struct dt_state *s, int nargs)
571 {
572         int len = strlen(s->value);
573         const char *p = s->value;
574
575         if (!strncmp(p, "s:", 2))
576         {
577                 len -= 2;
578                 p += 2;
579         }
580
581         if (len == 10 || len == 26)
582         {
583                 while (isxdigit(*p))
584                         p++;
585
586                 return (*p == 0);
587         }
588
589         return (len == 5 || len == 13);
590 }
591
592 static bool
593 dt_type_hostname(struct dt_state *s, int nargs)
594 {
595         const char *p, *last;
596
597         for (p = last = s->value; *p; p++)
598         {
599                 if (*p == '.')
600                 {
601                         if ((p - last) == 0 || (p - last) > 63)
602                                 return false;
603
604                         last = p + 1;
605                         continue;
606                 }
607                 else if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') ||
608                          (*p >= '0' && *p <= '9') || (*p == '_') || (*p == '-'))
609                 {
610                         continue;
611                 }
612
613                 return false;
614         }
615
616         return ((p - last) > 0 && (p - last) <= 255);
617 }
618
619 static bool
620 dt_type_host(struct dt_state *s, int nargs)
621 {
622         return (dt_type_hostname(s, 0) || dt_type_ipaddr(s, 0));
623 }
624
625 static bool
626 dt_type_network(struct dt_state *s, int nargs)
627 {
628         return (dt_type_uciname(s, 0) || dt_type_host(s, 0));
629 }
630
631 static bool
632 dt_type_phonedigit(struct dt_state *s, int nargs)
633 {
634         const char *p;
635
636         for (p = s->value;
637              *p && ((*p >= '0' && *p <= '9') || (*p == '*') || (*p == '#') ||
638                     (*p == '!') || (*p == '.'));
639                  p++);
640
641         return (*p == 0);
642 }
643
644 static bool
645 dt_type_directory(struct dt_state *s, int nargs)
646 {
647         struct stat st;
648         return (!stat(s->value, &st) && S_ISDIR(st.st_mode));
649 }
650
651
652 static bool
653 dt_type_device(struct dt_state *s, int nargs)
654 {
655         struct stat st;
656         return (!stat(s->value, &st) &&
657                 (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)));
658 }
659
660 static bool
661 dt_type_file(struct dt_state *s, int nargs)
662 {
663         struct stat st;
664         return (!stat(s->value, &st) && S_ISREG(st.st_mode));
665 }
666
667
668 static struct dt_fun dt_types[] = {
669         { "or",                         dt_type_or                      },
670         { "and",                        dt_type_and                     },
671         { "not",                        dt_type_not                     },
672         { "neg",                        dt_type_neg                     },
673         { "list",                       dt_type_list            },
674         { "min",                        dt_type_min                     },
675         { "max",                        dt_type_max                     },
676         { "range",                      dt_type_range           },
677         { "minlength",          dt_type_minlen          },
678         { "maxlength",          dt_type_maxlen          },
679         { "rangelength",        dt_type_rangelen        },
680         { "integer",            dt_type_int                     },
681         { "uinteger",           dt_type_uint            },
682         { "float",                      dt_type_float           },
683         { "ufloat",                     dt_type_ufloat          },
684         { "bool",                       dt_type_bool            },
685         { "ip4addr",            dt_type_ip4addr         },
686         { "ip6addr",            dt_type_ip6addr         },
687         { "ipaddr",                     dt_type_ipaddr          },
688         { "cidr4",                      dt_type_cidr4           },
689         { "cidr6",                      dt_type_cidr6           },
690         { "cidr",                       dt_type_cidr            },
691         { "netmask4",           dt_type_netmask4        },
692         { "netmask6",           dt_type_netmask6        },
693         { "ipmask4",            dt_type_ipmask4         },
694         { "ipmask6",            dt_type_ipmask6         },
695         { "ipmask",                     dt_type_ipmask          },
696         { "port",                       dt_type_port            },
697         { "portrange",          dt_type_portrange       },
698         { "macaddr",            dt_type_macaddr         },
699         { "uciname",        dt_type_uciname             },
700         { "wpakey",                     dt_type_wpakey          },
701         { "wepkey",                     dt_type_wepkey          },
702         { "hostname",           dt_type_hostname        },
703         { "host",                       dt_type_host            },
704         { "network",            dt_type_network         },
705         { "phonedigit",         dt_type_phonedigit      },
706         { "directory",          dt_type_directory       },
707         { "device",                     dt_type_device          },
708         { "file",                       dt_type_file            },
709
710         { }
711 };
712
713 static struct dt_fun *
714 dt_lookup_function(const char *s, const char *e)
715 {
716         struct dt_fun *fun = dt_types;
717
718         while (fun->name)
719         {
720                 if (!strncmp(fun->name, s, e - s) && *(fun->name + (e - s)) == '\0')
721                         return fun;
722
723                 fun++;
724         }
725
726         return NULL;
727 }
728
729 static bool
730 dt_parse_atom(struct dt_state *s, const char *label, const char *end)
731 {
732         char q, *e;
733         const char *p;
734         bool esc;
735         double dval;
736         struct dt_fun *func;
737         struct dt_op *op = &s->stack[s->depth];
738
739         if ((s->depth + 1) >= (sizeof(s->stack) / sizeof(s->stack[0])))
740         {
741                 printf("Syntax error, expression too long\n");
742                 return false;
743         }
744
745         while (isspace(*label))
746                 label++;
747
748         /* test whether label is a float */
749         dval = strtod(label, &e);
750
751         if (e > label)
752         {
753                 op->next = e;
754                 op->type = OP_NUMBER;
755                 op->value.number = dval;
756                 op->nextop = ++s->depth;
757
758                 return true;
759         }
760         else if ((*label == '"') || (*label == '\''))
761         {
762                 for (p = label + 1, q = *label, esc = false; p <= end; p++)
763                 {
764                         if (esc)
765                         {
766                                 esc = false;
767                                 continue;
768                         }
769                         else if (*p == '\\')
770                         {
771                                 esc = true;
772                                 continue;
773                         }
774                         else if (*p == q)
775                         {
776                                 op->next = p + 1;
777                                 op->type = OP_STRING;
778                                 op->length = (p - label) - 2;
779                                 op->value.string = label + 1;
780                                 op->nextop = ++s->depth;
781
782                                 return true;
783                         }
784                 }
785
786                 printf("Syntax error, unterminated string\n");
787                 return false;
788         }
789         else if (*label)
790         {
791                 for (p = label;
792                      p <= end && ((*p >= 'A' && *p <= 'Z') ||
793                                   (*p >= 'a' && *p <= 'z') ||
794                                   (*p >= '0' && *p <= '9') ||
795                                   (*p == '_'));
796                      p++);
797
798                 func = dt_lookup_function(label, p);
799
800                 if (!func)
801                 {
802                         printf("Syntax error, unrecognized function\n");
803                         return false;
804                 }
805
806                 op->next = p;
807                 op->type = OP_FUNCTION;
808                 op->value.function = func;
809                 op->nextop = ++s->depth;
810
811                 return true;
812         }
813
814         printf("Syntax error, unexpected EOF\n");
815         return false;
816 }
817
818 static bool
819 dt_parse_list(struct dt_state *s, const char *code, const char *end);
820
821 static bool
822 dt_parse_expr(const char *code, const char *end, struct dt_state *s)
823 {
824         struct dt_op *tok;
825
826         if (!dt_parse_atom(s, code, end))
827                 return false;
828
829         tok = &s->stack[s->depth - 1];
830
831         while (isspace(*tok->next))
832                 tok->next++;
833
834         if (tok->type == OP_FUNCTION)
835         {
836                 if (*tok->next == '(')
837                 {
838                         end--;
839
840                         while (isspace(*end) && end > tok->next + 1)
841                                 end--;
842
843                         return dt_parse_list(s, tok->next + 1, end);
844                 }
845                 else if (tok->next == end)
846                 {
847                         return dt_parse_list(s, tok->next, tok->next);
848                 }
849
850                 printf("Syntax error, expected '(' or EOF after function label\n");
851                 return false;
852         }
853         else if (tok->next == end)
854         {
855                 return true;
856         }
857
858         printf("Syntax error, expected ',' after literal\n");
859         return false;
860 }
861
862 static bool
863 dt_parse_list(struct dt_state *s, const char *code, const char *end)
864 {
865         char c;
866         bool esc;
867         int nest;
868         const char *p, *last;
869         struct dt_op *fptr;
870
871         if (!code)
872                 return false;
873
874         fptr = &s->stack[s->depth - 1];
875
876         for (nest = 0, p = last = code, esc = false, c = *p;
877              p <= end;
878              p++, c = (p < end) ? *p : '\0')
879         {
880                 if (esc)
881                 {
882                         esc = false;
883                         continue;
884                 }
885
886                 switch (c)
887                 {
888                 case '\\':
889                         esc = true;
890                         break;
891
892                 case '(':
893                         nest++;
894                         break;
895
896                 case ')':
897                         nest--;
898                         break;
899
900                 case ',':
901                 case '\0':
902                         if (nest <= 0)
903                         {
904                                 if (p > last)
905                                 {
906                                         if (!dt_parse_expr(last, p, s))
907                                                 return false;
908
909                                         fptr->length++;
910                                 }
911
912                                 last = p + 1;
913                         }
914
915                         break;
916                 }
917         }
918
919         fptr->nextop = s->depth;
920         return true;
921 }
922
923 static bool
924 dt_step(struct dt_state *s)
925 {
926         bool rv;
927         struct dt_op *op = &s->stack[s->pos];
928
929         switch (op->type)
930         {
931         case OP_BOOL:
932                 rv = op->value.boolean;
933                 break;
934
935         case OP_NUMBER:
936                 rv = dt_test_number(op->value.number, s->value);
937                 break;
938
939         case OP_STRING:
940                 rv = dt_test_string(op->value.string, op->value.string + op->length, s->value);
941                 break;
942
943         case OP_FUNCTION:
944                 rv = dt_call(s);
945                 break;
946
947         default:
948                 rv = false;
949                 break;
950         }
951
952         s->pos = op->nextop;
953         return rv;
954 }
955
956 static bool
957 dt_call(struct dt_state *s)
958 {
959         bool rv;
960         struct dt_op *fptr = &s->stack[s->pos];
961         struct dt_fun *func = fptr->value.function;
962
963         s->pos++;
964
965         rv = func->call(s, fptr->length);
966
967         s->pos = fptr->nextop;
968
969         return rv;
970 }
971
972 bool
973 dt_parse(const char *code, const char *value)
974 {
975         struct dt_state s = {
976                 .depth = 1,
977                 .stack = {
978                         {
979                                 .type = OP_FUNCTION,
980                                 .value.function = &dt_types[0],
981                                 .next = code
982                         }
983                 }
984         };
985
986         if (!value || !*value)
987                 return false;
988
989         if (!dt_parse_list(&s, code, code + strlen(code)))
990                 return false;
991
992         s.value = value;
993
994         return dt_call(&s);
995 }