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