Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | merge trunk |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | dgp-refactor |
Files: | files | file ages | folders |
SHA3-256: |
d40e2342001c3dc834b4609ce3a7017a |
User & Date: | dgp 2019-06-17 18:36:48.186 |
Context
2019-06-27
| ||
13:32 | merge trunk check-in: 34fe090bc2 user: dgp tags: dgp-refactor | |
2019-06-17
| ||
18:36 | merge trunk check-in: d40e234200 user: dgp tags: dgp-refactor | |
18:18 | merge 8.7 check-in: 806615c420 user: dgp tags: trunk | |
2019-06-13
| ||
12:13 | merge trunk check-in: 08d36921f0 user: dgp tags: dgp-refactor | |
Changes
Changes to doc/binary.n.
︙ | ︙ | |||
8 9 10 11 12 13 14 | .TH binary n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME binary \- Insert and extract fields from binary strings .SH SYNOPSIS | < < < < < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | .TH binary n 8.0 Tcl "Tcl Built-In Commands" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME binary \- Insert and extract fields from binary strings .SH SYNOPSIS \fBbinary decode \fIformat\fR ?\fI\-option value ...\fR? \fIdata\fR .br \fBbinary encode \fIformat\fR ?\fI\-option value ...\fR? \fIdata\fR .br \fBbinary format \fIformatString \fR?\fIarg arg ...\fR? .br \fBbinary scan \fIstring formatString \fR?\fIvarName varName ...\fR? .BE .SH DESCRIPTION .PP This command provides facilities for manipulating binary data. The subcommand \fBbinary format\fR creates a binary string from normal Tcl values. For example, given the values 16 and 22, on a 32-bit architecture, it might produce an 8-byte binary string consisting of two 4-byte integers, one for each of the numbers. The subcommand \fBbinary scan\fR, does the opposite: it extracts data from a binary string and returns it as ordinary Tcl string values. The \fBbinary encode\fR and \fBbinary decode\fR subcommands convert binary data to or from string encodings such as base64 (used in MIME messages for example). .PP Note that other operations on binary data, such as taking a subsequence of it, getting its length, or reinterpreting it as a string in some encoding, are done by other Tcl commands (respectively \fBstring range\fR, \fBstring length\fR and \fBencoding convertfrom\fR in the example cases). A binary string in Tcl is merely one where all the characters it contains are in the range \eu0000\-\eu00FF. .SH "BINARY ENCODE AND DECODE" .PP When encoding binary data as a readable string, the starting binary data is passed to the \fBbinary encode\fR command, together with the name of the encoding to use and any encoding-specific options desired. Data which has been encoded can be converted back to binary form using \fBbinary decode\fR. The following formats and options are supported. .TP |
︙ | ︙ | |||
124 125 126 127 128 129 130 | . Instructs the decoder to throw an error if it encounters unexpected whitespace characters. Otherwise it ignores them. .PP Note that neither the encoder nor the decoder handle the header and footer of the uuencode format. .RE | < | > > > | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | . Instructs the decoder to throw an error if it encounters unexpected whitespace characters. Otherwise it ignores them. .PP Note that neither the encoder nor the decoder handle the header and footer of the uuencode format. .RE .SH "BINARY FORMAT" .PP The \fBbinary format\fR command generates a binary string whose layout is specified by the \fIformatString\fR and whose contents come from the additional arguments. The resulting binary value is returned. .PP The \fIformatString\fR consists of a sequence of zero or more field specifiers separated by zero or more spaces. Each field specifier is a single type character followed by an optional flag character followed by an optional numeric \fIcount\fR. Most field specifiers consume one argument to obtain the value to be formatted. The type character specifies how the value is to be formatted. The \fIcount\fR typically indicates how many items of the specified type are taken from the value. If present, the \fIcount\fR is a non-negative decimal integer or .QW \fB*\fR , which normally indicates that all of the items in the value are to be used. If the number of arguments does not match the number of fields in the format string that consume arguments, then an error is generated. The flag character is ignored for \fBbinary format\fR. .PP Here is a small example to clarify the relation between the field specifiers and the arguments: .PP .CS \fBbinary format\fR d3d {1.0 2.0 3.0 4.0} 0.1 .CE .PP The first argument is a list of four numbers, but because of the count of 3 for the associated field specifier, only the first three will be used. The second argument is associated with the second field |
︙ | ︙ | |||
174 175 176 177 178 179 180 | the \fBencoding convertto\fR command should be used first to change the string into an external representation if this truncation is not desired (i.e. if the characters are not part of the ISO 8859\-1 character set.) If \fIarg\fR has fewer than \fIcount\fR bytes, then additional zero bytes are used to pad out the field. If \fIarg\fR is longer than the specified length, the extra characters will be ignored. If | > > | | | > | > > > > | > > > > | > > > > | > > > | > | > > > > > > > | | > > > > > > > > | | > | > | > > > > | | > > | > | > > > > | > | > | > > > > | > | > | | > | > > > > | > | > | > > > > | > | > | | > | > | > > | > > > > | > | > | > | > > | > | > | > | > > | > | > | > | > > > | > | > | > > > | > | > | | > | > | | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | the \fBencoding convertto\fR command should be used first to change the string into an external representation if this truncation is not desired (i.e. if the characters are not part of the ISO 8859\-1 character set.) If \fIarg\fR has fewer than \fIcount\fR bytes, then additional zero bytes are used to pad out the field. If \fIarg\fR is longer than the specified length, the extra characters will be ignored. If \fIcount\fR is .QW \fB*\fR , then all of the bytes in \fIarg\fR will be formatted. If \fIcount\fR is omitted, then one character will be formatted. For example, the command: .RS .PP .CS \fBbinary format\fR a7a*a alpha bravo charlie .CE .PP will return a binary string equivalent to: .PP .CS \fBalpha\e000\e000bravoc\fR .CE .PP the command: .PP .CS \fBbinary format\fR a* [encoding convertto utf-8 \eu20ac] .CE .PP will return a binary string equivalent to: .PP .CS \fB\e342\e202\e254\fR .CE .PP (which is the UTF-8 byte sequence for a Euro-currency character), and the command: .PP .CS \fBbinary format\fR a* [encoding convertto iso8859-15 \eu20ac] .CE .PP will return a binary string equivalent to: .PP .CS \fB\e244\fR .CE .PP (which is the ISO 8859\-15 byte sequence for a Euro-currency character). Contrast these last two with: .PP .CS \fBbinary format\fR a* \eu20ac .CE .PP which returns a binary string equivalent to: .PP .CS \fB\e254\fR .CE .PP (i.e. \fB\exac\fR) by truncating the high-bits of the character, and which is probably not what is desired. .RE .IP \fBA\fR 5 This form is the same as \fBa\fR except that spaces are used for padding instead of nulls. For example, .RS .PP .CS \fBbinary format\fR A6A*A alpha bravo charlie .CE .PP will return .PP .CS \fBalpha bravoc\fR .CE .RE .IP \fBb\fR 5 Stores a string of \fIcount\fR binary digits in low-to-high order within each byte in the output binary string. \fIArg\fR must contain a sequence of \fB1\fR and \fB0\fR characters. The resulting bytes are emitted in first to last order with the bits being formatted in low-to-high order within each byte. If \fIarg\fR has fewer than \fIcount\fR digits, then zeros will be used for the remaining bits. If \fIarg\fR has more than the specified number of digits, the extra digits will be ignored. If \fIcount\fR is .QW \fB*\fR , then all of the digits in \fIarg\fR will be formatted. If \fIcount\fR is omitted, then one digit will be formatted. If the number of bits formatted does not end at a byte boundary, the remaining bits of the last byte will be zeros. For example, .RS .PP .CS \fBbinary format\fR b5b* 11100 111000011010 .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex07\ex87\ex05\fR .CE .RE .IP \fBB\fR 5 This form is the same as \fBb\fR except that the bits are stored in high-to-low order within each byte. For example, .RS .PP .CS \fBbinary format\fR B5B* 11100 111000011010 .CE .PP will return a binary string equivalent to: .PP .CS \fB\exe0\exe1\exa0\fR .CE .RE .IP \fBH\fR 5 Stores a string of \fIcount\fR hexadecimal digits in high-to-low within each byte in the output binary string. \fIArg\fR must contain a sequence of characters in the set .QW 0123456789abcdefABCDEF . The resulting bytes are emitted in first to last order with the hex digits being formatted in high-to-low order within each byte. If \fIarg\fR has fewer than \fIcount\fR digits, then zeros will be used for the remaining digits. If \fIarg\fR has more than the specified number of digits, the extra digits will be ignored. If \fIcount\fR is .QW \fB*\fR , then all of the digits in \fIarg\fR will be formatted. If \fIcount\fR is omitted, then one digit will be formatted. If the number of digits formatted does not end at a byte boundary, the remaining bits of the last byte will be zeros. For example, .RS .PP .CS \fBbinary format\fR H3H*H2 ab DEF 987 .CE .PP will return a binary string equivalent to: .PP .CS \fB\exab\ex00\exde\exf0\ex98\fR .CE .RE .IP \fBh\fR 5 This form is the same as \fBH\fR except that the digits are stored in low-to-high order within each byte. This is seldom required. For example, .RS .PP .CS \fBbinary format\fR h3h*h2 AB def 987 .CE .PP will return a binary string equivalent to: .PP .CS \fB\exba\ex00\exed\ex0f\ex89\fR .CE .RE .IP \fBc\fR 5 Stores one or more 8-bit integer values in the output string. If no \fIcount\fR is specified, then \fIarg\fR must consist of an integer value. If \fIcount\fR is specified, \fIarg\fR must consist of a list containing at least that many integers. The low-order 8 bits of each integer are stored as a one-byte value at the cursor position. If \fIcount\fR is .QW \fB*\fR , then all of the integers in the list are formatted. If the number of elements in the list is greater than \fIcount\fR, then the extra elements are ignored. For example, .RS .PP .CS \fBbinary format\fR c3cc* {3 -3 128 1} 260 {2 5} .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex03\exfd\ex80\ex04\ex02\ex05\fR .CE .PP whereas: .PP .CS \fBbinary format\fR c {2 5} .CE .PP will generate an error. .RE .IP \fBs\fR 5 This form is the same as \fBc\fR except that it stores one or more 16-bit integers in little-endian byte order in the output string. The low-order 16-bits of each integer are stored as a two-byte value at the cursor position with the least significant byte stored first. For example, .RS .PP .CS \fBbinary format\fR s3 {3 -3 258 1} .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex03\ex00\exfd\exff\ex02\ex01\fR .CE .RE .IP \fBS\fR 5 This form is the same as \fBs\fR except that it stores one or more 16-bit integers in big-endian byte order in the output string. For example, .RS .PP .CS \fBbinary format\fR S3 {3 -3 258 1} .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex00\ex03\exff\exfd\ex01\ex02\fR .CE .RE .IP \fBt\fR 5 This form (mnemonically \fItiny\fR) is the same as \fBs\fR and \fBS\fR except that it stores the 16-bit integers in the output string in the native byte order of the machine where the Tcl script is running. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBi\fR 5 This form is the same as \fBc\fR except that it stores one or more 32-bit integers in little-endian byte order in the output string. The low-order 32-bits of each integer are stored as a four-byte value at the cursor position with the least significant byte stored first. For example, .RS .PP .CS \fBbinary format\fR i3 {3 -3 65536 1} .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex03\ex00\ex00\ex00\exfd\exff\exff\exff\ex00\ex00\ex01\ex00\fR .CE .RE .IP \fBI\fR 5 This form is the same as \fBi\fR except that it stores one or more one or more 32-bit integers in big-endian byte order in the output string. For example, .RS .PP .CS \fBbinary format\fR I3 {3 -3 65536 1} .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex00\ex00\ex00\ex03\exff\exff\exff\exfd\ex00\ex01\ex00\ex00\fR .CE .RE .IP \fBn\fR 5 This form (mnemonically \fInumber\fR or \fInormal\fR) is the same as \fBi\fR and \fBI\fR except that it stores the 32-bit integers in the output string in the native byte order of the machine where the Tcl script is running. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBw\fR 5 This form is the same as \fBc\fR except that it stores one or more 64-bit integers in little-endian byte order in the output string. The low-order 64-bits of each integer are stored as an eight-byte value at the cursor position with the least significant byte stored first. For example, .RS .PP .CS \fBbinary format\fR w 7810179016327718216 .CE .PP will return the binary string \fBHelloTcl\fR. .RE .IP \fBW\fR 5 This form is the same as \fBw\fR except that it stores one or more one or more 64-bit integers in big-endian byte order in the output string. For example, .RS .PP .CS \fBbinary format\fR Wc 4785469626960341345 110 .CE .PP will return the binary string \fBBigEndian\fR .RE .IP \fBm\fR 5 This form (mnemonically the mirror of \fBw\fR) is the same as \fBw\fR and \fBW\fR except that it stores the 64-bit integers in the output string in the native byte order of the machine where the Tcl script is running. To determine what the native byte order of the machine is, refer to |
︙ | ︙ | |||
389 390 391 392 393 394 395 | point number may vary across architectures, so the number of bytes that are generated may vary. If the value overflows the machine's native representation, then the value of FLT_MAX as defined by the system will be used instead. Because Tcl uses double-precision floating point numbers internally, there may be some loss of precision in the conversion to single-precision. For example, on a Windows system running on an Intel Pentium processor, | | > | > | > > | > | > | > | > > | > | > | > | > > > > | > > > | | > | > > > | | > | > > > > | > | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 | point number may vary across architectures, so the number of bytes that are generated may vary. If the value overflows the machine's native representation, then the value of FLT_MAX as defined by the system will be used instead. Because Tcl uses double-precision floating point numbers internally, there may be some loss of precision in the conversion to single-precision. For example, on a Windows system running on an Intel Pentium processor, .RS .PP .CS \fBbinary format\fR f2 {1.6 3.4} .CE .PP will return a binary string equivalent to: .PP .CS \fB\excd\excc\excc\ex3f\ex9a\ex99\ex59\ex40\fR .CE .RE .IP \fBr\fR 5 This form (mnemonically \fIreal\fR) is the same as \fBf\fR except that it stores the single-precision floating point numbers in little-endian order. This conversion only produces meaningful output when used on machines which use the IEEE floating point representation (very common, but not universal.) .IP \fBR\fR 5 This form is the same as \fBr\fR except that it stores the single-precision floating point numbers in big-endian order. .IP \fBd\fR 5 This form is the same as \fBf\fR except that it stores one or more one or more double-precision floating point numbers in the machine's native representation in the output string. For example, on a Windows system running on an Intel Pentium processor, .RS .PP .CS \fBbinary format\fR d1 {1.6} .CE .PP will return a binary string equivalent to: .PP .CS \fB\ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f\fR .CE .RE .IP \fBq\fR 5 This form (mnemonically the mirror of \fBd\fR) is the same as \fBd\fR except that it stores the double-precision floating point numbers in little-endian order. This conversion only produces meaningful output when used on machines which use the IEEE floating point representation (very common, but not universal.) .IP \fBQ\fR 5 This form is the same as \fBq\fR except that it stores the double-precision floating point numbers in big-endian order. .IP \fBx\fR 5 Stores \fIcount\fR null bytes in the output string. If \fIcount\fR is not specified, stores one null byte. If \fIcount\fR is .QW \fB*\fR , generates an error. This type does not consume an argument. For example, .RS .PP .CS \fBbinary format\fR a3xa3x2a3 abc def ghi .CE .PP will return a binary string equivalent to: .PP .CS \fBabc\e000def\e000\e000ghi\fR .CE .RE .IP \fBX\fR 5 Moves the cursor back \fIcount\fR bytes in the output string. If \fIcount\fR is .QW \fB*\fR or is larger than the current cursor position, then the cursor is positioned at location 0 so that the next byte stored will be the first byte in the result string. If \fIcount\fR is omitted then the cursor is moved back one byte. This type does not consume an argument. For example, .RS .PP .CS \fBbinary format\fR a3X*a3X2a3 abc def ghi .CE .PP will return \fBdghi\fR. .RE .IP \fB@\fR 5 Moves the cursor to the absolute location in the output string specified by \fIcount\fR. Position 0 refers to the first byte in the output string. If \fIcount\fR refers to a position beyond the last byte stored so far, then null bytes will be placed in the uninitialized locations and the cursor will be placed at the specified location. If \fIcount\fR is .QW \fB*\fR , then the cursor is moved to the current end of the output string. If \fIcount\fR is omitted, then an error will be generated. This type does not consume an argument. For example, .RS .PP .CS \fBbinary format\fR a5@2a1@*a3@10a1 abcde f ghi j .CE .PP will return .PP .CS \fBabfdeghi\e000\e000j\fR .CE .RE .SH "BINARY SCAN" .PP The \fBbinary scan\fR command parses fields from a binary string, returning the number of conversions performed. \fIString\fR gives the input bytes to be parsed (one byte per character, and characters not representable as a byte have their high bits chopped) |
︙ | ︙ | |||
485 486 487 488 489 490 491 | spaces. Each field specifier is a single type character followed by an optional flag character followed by an optional numeric \fIcount\fR. Most field specifiers consume one argument to obtain the variable into which the scanned values should be placed. The type character specifies how the binary data is to be interpreted. The \fIcount\fR typically indicates how many items of the specified type are taken from the data. If present, the | | > | | > | > | > | > | > | > | > | > | | > | > | > | > | > | > | > | | > | > | > | > > | | > | > | > | > | > > | > | > | < < < < < > | > | > | | > | > | < < < < < > | | > | > > | | > | > | | > | > | < | < < < > | | > | > > | | > | > | | > | > | < > | | > | > > | > > | | > | > | > | > > > | | > | > > > | | > | > | > | > | 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 | spaces. Each field specifier is a single type character followed by an optional flag character followed by an optional numeric \fIcount\fR. Most field specifiers consume one argument to obtain the variable into which the scanned values should be placed. The type character specifies how the binary data is to be interpreted. The \fIcount\fR typically indicates how many items of the specified type are taken from the data. If present, the \fIcount\fR is a non-negative decimal integer or .QW \fB*\fR , which normally indicates that all of the remaining items in the data are to be used. If there are not enough bytes left after the current cursor position to satisfy the current field specifier, then the corresponding variable is left untouched and \fBbinary scan\fR returns immediately with the number of variables that were set. If there are not enough arguments for all of the fields in the format string that consume arguments, then an error is generated. The flag character .QW u may be given to cause some types to be read as unsigned values. The flag is accepted for all field types but is ignored for non-integer fields. .PP A similar example as with \fBbinary format\fR should explain the relation between field specifiers and arguments in case of the binary scan subcommand: .PP .CS \fBbinary scan\fR $bytes s3s first second .CE .PP This command (provided the binary string in the variable \fIbytes\fR is long enough) assigns a list of three integers to the variable \fIfirst\fR and assigns a single value to the variable \fIsecond\fR. If \fIbytes\fR contains fewer than 8 bytes (i.e. four 2-byte integers), no assignment to \fIsecond\fR will be made, and if \fIbytes\fR contains fewer than 6 bytes (i.e. three 2-byte integers), no assignment to \fIfirst\fR will be made. Hence: .PP .CS puts [\fBbinary scan\fR abcdefg s3s first second] puts $first puts $second .CE .PP will print (assuming neither variable is set previously): .PP .CS 1 25185 25699 26213 can't read "second": no such variable .CE .PP It is \fIimportant\fR to note that the \fBc\fR, \fBs\fR, and \fBS\fR (and \fBi\fR and \fBI\fR on 64bit systems) will be scanned into long data size values. In doing this, values that have their high bit set (0x80 for chars, 0x8000 for shorts, 0x80000000 for ints), will be sign extended. Thus the following will occur: .PP .CS set signShort [\fBbinary format\fR s1 0x8000] \fBbinary scan\fR $signShort s1 val; \fI# val == 0xFFFF8000\fR .CE .PP If you require unsigned values you can include the .QW u flag character following the field type. For example, to read an unsigned short value: .PP .CS set signShort [\fBbinary format\fR s1 0x8000] \fBbinary scan\fR $signShort su1 val; \fI# val == 0x00008000\fR .CE .PP Each type-count pair moves an imaginary cursor through the binary data, reading bytes from the current position. The cursor is initially at position 0 at the beginning of the data. The type may be any one of the following characters: .IP \fBa\fR 5 The data is a byte string of length \fIcount\fR. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bytes in \fIstring\fR will be scanned into the variable. If \fIcount\fR is omitted, then one byte will be scanned. All bytes scanned will be interpreted as being characters in the range \eu0000-\eu00ff so the \fBencoding convertfrom\fR command will be needed if the string is not a binary string or a string encoded in ISO 8859\-1. For example, .RS .PP .CS \fBbinary scan\fR abcde\e000fghi a6a10 var1 var2 .CE .PP will return \fB1\fR with the string equivalent to \fBabcde\e000\fR stored in \fIvar1\fR and \fIvar2\fR left unmodified, and .PP .CS \fBbinary scan\fR \e342\e202\e254 a* var1 set var2 [encoding convertfrom utf-8 $var1] .CE .PP will store a Euro-currency character in \fIvar2\fR. .RE .IP \fBA\fR 5 This form is the same as \fBa\fR, except trailing blanks and nulls are stripped from the scanned value before it is stored in the variable. For example, .RS .PP .CS \fBbinary scan\fR "abc efghi \e000" A* var1 .CE .PP will return \fB1\fR with \fBabc efghi\fR stored in \fIvar1\fR. .RE .IP \fBb\fR 5 The data is turned into a string of \fIcount\fR binary digits in low-to-high order represented as a sequence of .QW 1 and .QW 0 characters. The data bytes are scanned in first to last order with the bits being taken in low-to-high order within each byte. Any extra bits in the last byte are ignored. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bits in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one bit will be scanned. For example, .RS .PP .CS \fBbinary scan\fR \ex07\ex87\ex05 b5b* var1 var2 .CE .PP will return \fB2\fR with \fB11100\fR stored in \fIvar1\fR and \fB1110000110100000\fR stored in \fIvar2\fR. .RE .IP \fBB\fR 5 This form is the same as \fBb\fR, except the bits are taken in high-to-low order within each byte. For example, .RS .PP .CS \fBbinary scan\fR \ex70\ex87\ex05 B5B* var1 var2 .CE .PP will return \fB2\fR with \fB01110\fR stored in \fIvar1\fR and \fB1000011100000101\fR stored in \fIvar2\fR. .RE .IP \fBH\fR 5 The data is turned into a string of \fIcount\fR hexadecimal digits in high-to-low order represented as a sequence of characters in the set .QW 0123456789abcdef . The data bytes are scanned in first to last order with the hex digits being taken in high-to-low order within each byte. Any extra bits in the last byte are ignored. If \fIcount\fR is .QW \fB*\fR , then all of the remaining hex digits in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one hex digit will be scanned. For example, .RS .PP .CS \fBbinary scan\fR \ex07\exC6\ex05\ex1f\ex34 H3H* var1 var2 .CE .PP will return \fB2\fR with \fB07c\fR stored in \fIvar1\fR and \fB051f34\fR stored in \fIvar2\fR. .RE .IP \fBh\fR 5 This form is the same as \fBH\fR, except the digits are taken in reverse (low-to-high) order within each byte. For example, .RS .PP .CS \fBbinary scan\fR \ex07\ex86\ex05\ex12\ex34 h3h* var1 var2 .CE .PP will return \fB2\fR with \fB706\fR stored in \fIvar1\fR and \fB502143\fR stored in \fIvar2\fR. .PP Note that most code that wishes to parse the hexadecimal digits from multiple bytes in order should use the \fBH\fR format. .RE .IP \fBc\fR 5 The data is turned into \fIcount\fR 8-bit signed integers and stored in the corresponding variable as a list, or as unsigned if \fBu\fR is placed immediately after the \fBc\fR. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 8-bit integer will be scanned. For example, .RS .PP .CS \fBbinary scan\fR \ex07\ex86\ex05 c2c* var1 var2 .CE .PP will return \fB2\fR with \fB7 -122\fR stored in \fIvar1\fR and \fB5\fR stored in \fIvar2\fR. Note that the integers returned are signed unless \fBcu\fR in place of \fBc\fR. .RE .IP \fBs\fR 5 The data is interpreted as \fIcount\fR 16-bit signed integers represented in little-endian byte order, or as unsigned if \fBu\fR is placed immediately after the \fBs\fR. The integers are stored in the corresponding variable as a list. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 16-bit integer will be scanned. For example, .RS .PP .CS \fBbinary scan\fR \ex05\ex00\ex07\ex00\exf0\exff s2s* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed unless \fBsu\fR is used in place of \fBs\fR. .RE .IP \fBS\fR 5 This form is the same as \fBs\fR except that the data is interpreted as \fIcount\fR 16-bit integers represented in big-endian byte order. For example, .RS .PP .CS \fBbinary scan\fR \ex00\ex05\ex00\ex07\exff\exf0 S2S* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBt\fR 5 The data is interpreted as \fIcount\fR 16-bit signed integers represented in the native byte order of the machine running the Tcl script, or as unsigned if \fBu\fR is placed immediately after the \fBt\fR. It is otherwise identical to \fBs\fR and \fBS\fR. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBi\fR 5 The data is interpreted as \fIcount\fR 32-bit signed integers represented in little-endian byte order, or as unsigned if \fBu\fR is placed immediately after the \fBi\fR. The integers are stored in the corresponding variable as a list. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 32-bit integer will be scanned. For example, .RS .PP .CS set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff \fBbinary scan\fR $str i2i* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. Note that the integers returned are signed unless \fBiu\fR is used in place of \fBi\fR. .RE .IP \fBI\fR 5 This form is the same as \fBI\fR except that the data is interpreted as \fIcount\fR 32-bit signed integers represented in big-endian byte order, or as unsigned if \fBu\fR is placed immediately after the \fBI\fR. For example, .RS .PP .CS set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0 \fBbinary scan\fR $str I2I* var1 var2 .CE .PP will return \fB2\fR with \fB5 7\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBn\fR 5 The data is interpreted as \fIcount\fR 32-bit signed integers represented in the native byte order of the machine running the Tcl script, or as unsigned if \fBu\fR is placed immediately after the \fBn\fR. It is otherwise identical to \fBi\fR and \fBI\fR. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBw\fR 5 The data is interpreted as \fIcount\fR 64-bit signed integers represented in little-endian byte order, or as unsigned if \fBu\fR is placed immediately after the \fBw\fR. The integers are stored in the corresponding variable as a list. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one 64-bit integer will be scanned. For example, .RS .PP .CS set str \ex05\ex00\ex00\ex00\ex07\ex00\ex00\ex00\exf0\exff\exff\exff \fBbinary scan\fR $str wi* var1 var2 .CE .PP will return \fB2\fR with \fB30064771077\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBW\fR 5 This form is the same as \fBw\fR except that the data is interpreted as \fIcount\fR 64-bit signed integers represented in big-endian byte order, or as unsigned if \fBu\fR is placed immediately after the \fBW\fR. For example, .RS .PP .CS set str \ex00\ex00\ex00\ex05\ex00\ex00\ex00\ex07\exff\exff\exff\exf0 \fBbinary scan\fR $str WI* var1 var2 .CE .PP will return \fB2\fR with \fB21474836487\fR stored in \fIvar1\fR and \fB\-16\fR stored in \fIvar2\fR. .RE .IP \fBm\fR 5 The data is interpreted as \fIcount\fR 64-bit signed integers represented in the native byte order of the machine running the Tcl script, or as unsigned if \fBu\fR is placed immediately after the \fBm\fR. It is otherwise identical to \fBw\fR and \fBW\fR. To determine what the native byte order of the machine is, refer to the \fBbyteOrder\fR element of the \fBtcl_platform\fR array. .IP \fBf\fR 5 The data is interpreted as \fIcount\fR single-precision floating point numbers in the machine's native representation. The floating point numbers are stored in the corresponding variable as a list. If \fIcount\fR is .QW \fB*\fR , then all of the remaining bytes in \fIstring\fR will be scanned. If \fIcount\fR is omitted, then one single-precision floating point number will be scanned. The size of a floating point number may vary across architectures, so the number of bytes that are scanned may vary. If the data does not represent a valid floating point number, the resulting value is undefined and compiler dependent. For example, on a Windows system running on an Intel Pentium processor, .RS .PP .CS \fBbinary scan\fR \ex3f\excc\excc\excd f var1 .CE .PP will return \fB1\fR with \fB1.6000000238418579\fR stored in \fIvar1\fR. .RE .IP \fBr\fR 5 This form is the same as \fBf\fR except that the data is interpreted as \fIcount\fR single-precision floating point number in little-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBR\fR 5 This form is the same as \fBf\fR except that the data is interpreted as \fIcount\fR single-precision floating point number in big-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBd\fR 5 This form is the same as \fBf\fR except that the data is interpreted as \fIcount\fR double-precision floating point numbers in the machine's native representation. For example, on a Windows system running on an Intel Pentium processor, .RS .PP .CS \fBbinary scan\fR \ex9a\ex99\ex99\ex99\ex99\ex99\exf9\ex3f d var1 .CE .PP will return \fB1\fR with \fB1.6000000000000001\fR stored in \fIvar1\fR. .RE .IP \fBq\fR 5 This form is the same as \fBd\fR except that the data is interpreted as \fIcount\fR double-precision floating point number in little-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBQ\fR 5 This form is the same as \fBd\fR except that the data is interpreted as \fIcount\fR double-precision floating point number in big-endian order. This conversion is not portable to the minority of systems not using IEEE floating point representations. .IP \fBx\fR 5 Moves the cursor forward \fIcount\fR bytes in \fIstring\fR. If \fIcount\fR is .QW \fB*\fR or is larger than the number of bytes after the current cursor position, then the cursor is positioned after the last byte in \fIstring\fR. If \fIcount\fR is omitted, then the cursor is moved forward one byte. Note that this type does not consume an argument. For example, .RS .PP .CS \fBbinary scan\fR \ex01\ex02\ex03\ex04 x2H* var1 .CE .PP will return \fB1\fR with \fB0304\fR stored in \fIvar1\fR. .RE .IP \fBX\fR 5 Moves the cursor back \fIcount\fR bytes in \fIstring\fR. If \fIcount\fR is .QW \fB*\fR or is larger than the current cursor position, then the cursor is positioned at location 0 so that the next byte scanned will be the first byte in \fIstring\fR. If \fIcount\fR is omitted then the cursor is moved back one byte. Note that this type does not consume an argument. For example, .RS .PP .CS \fBbinary scan\fR \ex01\ex02\ex03\ex04 c2XH* var1 var2 .CE .PP will return \fB2\fR with \fB1 2\fR stored in \fIvar1\fR and \fB020304\fR stored in \fIvar2\fR. .RE .IP \fB@\fR 5 Moves the cursor to the absolute location in the data string specified by \fIcount\fR. Note that position 0 refers to the first byte in \fIstring\fR. If \fIcount\fR refers to a position beyond the end of \fIstring\fR, then the cursor is positioned after the last byte. If \fIcount\fR is omitted, then an error will be generated. For example, .RS .PP .CS \fBbinary scan\fR \ex01\ex02\ex03\ex04 c2@1H* var1 var2 .CE .PP will return \fB2\fR with \fB1 2\fR stored in \fIvar1\fR and \fB020304\fR stored in \fIvar2\fR. .RE .SH "PORTABILITY ISSUES" .PP The \fBr\fR, \fBR\fR, \fBq\fR and \fBQ\fR conversions will only work reliably for transferring data between computers which are all using |
︙ | ︙ |
Changes to doc/expr.n.
︙ | ︙ | |||
153 154 155 156 157 158 159 | \fB<<\0\0>>\fR . Left and right shift. Valid for integers. A right shift always propagates the sign bit. .TP 20 \fB<\0\0>\0\0<=\0\0>=\fR . | > > > > > > > | > > > > | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | \fB<<\0\0>>\fR . Left and right shift. Valid for integers. A right shift always propagates the sign bit. .TP 20 \fB<\0\0>\0\0<=\0\0>=\fR . Boolean numeric-preferring comparisons: less than, greater than, less than or equal, and greater than or equal. If either argument is not numeric, the comparison is done using UNICODE string comparison, as with the string comparison operators below, which have the same precedence. .TP 20 \fBlt\0\0gt\0\0le\0\0ge\fR .VS "8.7, TIP461" Boolean string comparisons: less than, greater than, less than or equal, and greater than or equal. These always compare values using their UNICODE strings (also see \fBstring compare\fR), unlike with the numeric-preferring comparisons abov, which have the same precedence. .VE "8.7, TIP461" .TP 20 \fB==\0\0!=\fR . Boolean equal and not equal. .TP 20 \fBeq\0\0ne\fR . |
︙ | ︙ | |||
396 397 398 399 400 401 402 403 404 405 406 407 408 409 | .CE .PP A string comparison whose result is 1: .PP .CS \fBexpr\fR {"0y" > "0x12"} .CE .PP Define a procedure that computes an .QW interesting mathematical function: .PP .CS proc tcl::mathfunc::calc {x y} { | > > > > > > > > | 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 | .CE .PP A string comparison whose result is 1: .PP .CS \fBexpr\fR {"0y" > "0x12"} .CE .PP .VS "8.7, TIP461" A forced string comparison whose result is 0: .PP .CS \fBexpr\fR {"0x03" gt "2"} .CE .VE "8.7, TIP461" .PP Define a procedure that computes an .QW interesting mathematical function: .PP .CS proc tcl::mathfunc::calc {x y} { |
︙ | ︙ | |||
452 453 454 455 456 457 458 | .SH "SEE ALSO" array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n), string(n), Tcl(n), while(n) .SH KEYWORDS arithmetic, boolean, compare, expression, fuzzy comparison .SH COPYRIGHT .nf | | | | | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 | .SH "SEE ALSO" array(n), for(n), if(n), mathfunc(n), mathop(n), namespace(n), proc(n), string(n), Tcl(n), while(n) .SH KEYWORDS arithmetic, boolean, compare, expression, fuzzy comparison .SH COPYRIGHT .nf Copyright \(co 1993 The Regents of the University of California. Copyright \(co 1994-2000 Sun Microsystems Incorporated. Copyright \(co 2005 by Kevin B. Kenny <[email protected]>. All rights reserved. .fi '\" Local Variables: '\" mode: nroff '\" End: |
Added doc/fpclassify.n.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | '\" '\" Copyright (c) 2018 by Kevin B. Kenny <[email protected]>. All rights reserved '\" Copyright (c) 2019 by Donal Fellows '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" .TH fpclassify n 8.7 Tcl "Tcl Float Classifier" .so man.macros .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME fpclassify \- Floating point number classification of Tcl values .SH SYNOPSIS package require \fBTcl 8.7\fR .sp \fBfpclassify \fIvalue\fR .BE .SH DESCRIPTION The \fBfpclassify\fR command takes a floating point number, \fIvalue\fR, and returns one of the following strings that describe it: .TP \fBzero\fR . \fIvalue\fR is a floating point zero. .TP \fBsubnormal\fR . \fIvalue\fR is the result of a gradual underflow. .TP \fBnormal\fR . \fIvalue\fR is an ordinary floating-point number (not zero, subnormal, infinite, nor NaN). .TP \fBinfinite\fR . \fIvalue\fR is a floating-point infinity. .TP \fBnan\fR . \fIvalue\fR is Not-a-Number. .PP The \fBfpclassify\fR command throws an error if value is not a floating-point value and cannot be converted to one. .SH EXAMPLE .PP This shows how to check whether the result of a computation is numerically safe or not. (Note however that it does not guard against numerical errors; just against representational problems.) .PP .CS set value [command-that-computes-a-value] switch [\fBfpclassify\fR $value] { normal - zero { puts "Result is $value" } infinite { puts "Result is infinite" } subnormal { puts "Result is $value - WARNING! precision lost" } nan { puts "Computation completely failed" } } .CE .SH "SEE ALSO" expr(n), mathfunc(n) .SH KEYWORDS floating point .SH STANDARDS This command depends on the \fBfpclassify\fR() C macro conforming to .QW "ISO C99" (i.e., to ISO/IEC 9899:1999). .SH COPYRIGHT .nf Copyright \(co 2018 by Kevin B. Kenny <[email protected]>. All rights reserved .fi '\" Local Variables: '\" mode: nroff '\" End: |
Changes to doc/mathfunc.n.
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | \fB::tcl::mathfunc::floor\fR \fIarg\fR .br \fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::int\fR \fIarg\fR .br \fB::tcl::mathfunc::isqrt\fR \fIarg\fR .br \fB::tcl::mathfunc::log\fR \fIarg\fR .br \fB::tcl::mathfunc::log10\fR \fIarg\fR .br \fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...? .br | > > > > > > > > > > > > > > > > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | \fB::tcl::mathfunc::floor\fR \fIarg\fR .br \fB::tcl::mathfunc::fmod\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::hypot\fR \fIx\fR \fIy\fR .br \fB::tcl::mathfunc::int\fR \fIarg\fR .br .VS "8.7, TIP 521" \fB::tcl::mathfunc::isfinite\fR \fIarg\fR .br \fB::tcl::mathfunc::isinf\fR \fIarg\fR .br \fB::tcl::mathfunc::isnan\fR \fIarg\fR .br \fB::tcl::mathfunc::isnormal\fR \fIarg\fR .VE "8.7, TIP 521" .br \fB::tcl::mathfunc::isqrt\fR \fIarg\fR .br .VS "8.7, TIP 521" \fB::tcl::mathfunc::issubnormal\fR \fIarg\fR .br \fB::tcl::mathfunc::isunordered\fR \fIx y\fR .VE "8.7, TIP 521" .br \fB::tcl::mathfunc::log\fR \fIarg\fR .br \fB::tcl::mathfunc::log10\fR \fIarg\fR .br \fB::tcl::mathfunc::max\fR \fIarg\fR ?\fIarg\fR ...? .br |
︙ | ︙ | |||
88 89 90 91 92 93 94 | namespace \fB::tcl::mathfunc\fR; these functions are also available for code apart from \fBexpr\fR, by invoking the given commands directly. .PP Tcl supports the following mathematical functions in expressions, all of which work solely with floating-point numbers unless otherwise noted: .DS | | > > | | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | namespace \fB::tcl::mathfunc\fR; these functions are also available for code apart from \fBexpr\fR, by invoking the given commands directly. .PP Tcl supports the following mathematical functions in expressions, all of which work solely with floating-point numbers unless otherwise noted: .DS .ta 3.2c 6.4c 9.6c \fBabs\fR \fBacos\fR \fBasin\fR \fBatan\fR \fBatan2\fR \fBbool\fR \fBceil\fR \fBcos\fR \fBcosh\fR \fBdouble\fR \fBentier\fR \fBexp\fR \fBfloor\fR \fBfmod\fR \fBhypot\fR \fBint\fR \fBisfinite\fR \fBisinf\fR \fBisnan\fR \fBisnormal\fR \fBisqrt\fR \fBissubnormal\fR \fBisunordered\fR \fBlog\fR \fBlog10\fR \fBmax\fR \fBmin\fR \fBpow\fR \fBrand\fR \fBround\fR \fBsin\fR \fBsinh\fR \fBsqrt\fR \fBsrand\fR \fBtan\fR \fBtanh\fR \fBwide\fR .DE .PP In addition to these predefined functions, applications may define additional functions by using \fBproc\fR (or any other method, such as \fBinterp alias\fR or \fBTcl_CreateObjCommand\fR) to define new commands in the \fBtcl::mathfunc\fR namespace. .SS "DETAILED DEFINITIONS" |
︙ | ︙ | |||
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order bits of that integer value up to the machine word size are returned as an integer value. For reference, the number of bytes in the machine word are stored in the \fBwordSize\fR element of the \fBtcl_platform\fR array. .TP \fBisqrt \fIarg\fR . Computes the integer part of the square root of \fIarg\fR. \fIArg\fR must be a positive value, either an integer or a floating point number. Unlike \fBsqrt\fR, which is limited to the precision of a floating point number, \fIisqrt\fR will return a result of arbitrary precision. .TP \fBlog \fIarg\fR . Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a positive value. .TP \fBlog10 \fIarg\fR | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 | . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order bits of that integer value up to the machine word size are returned as an integer value. For reference, the number of bytes in the machine word are stored in the \fBwordSize\fR element of the \fBtcl_platform\fR array. .TP \fBisfinite \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is finite. That is, if it is zero, subnormal, or normal. Returns 0 if the number is infinite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisinf \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is infinite. Returns 0 if the number is finite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisnan \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is Not-a-Number. Returns 0 if the number is finite or infinite. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisnormal \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is normal. Returns 0 if the number is zero, subnormal, infinite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisqrt \fIarg\fR . Computes the integer part of the square root of \fIarg\fR. \fIArg\fR must be a positive value, either an integer or a floating point number. Unlike \fBsqrt\fR, which is limited to the precision of a floating point number, \fIisqrt\fR will return a result of arbitrary precision. .TP \fBissubnormal \fIarg\fR .VS "8.7, TIP 521" Returns 1 if the floating-point number \fIarg\fR is subnormal, i.e., the result of gradual underflow. Returns 0 if the number is zero, normal, infinite or NaN. Throws an error if \fIarg\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBisunordered \fIx y\fR .VS "8.7, TIP 521" Returns 1 if \fIx\fR and \fIy\fR cannot be compared for ordering, that is, if either one is NaN. Returns 0 if both values can be ordered, that is, if they are both chosen from among the set of zero, subnormal, normal and infinite values. Throws an error if either \fIx\fR or \fIy\fR cannot be promoted to a floating-point value. .VE "8.7, TIP 521" .TP \fBlog \fIarg\fR . Returns the natural logarithm of \fIarg\fR. \fIArg\fR must be a positive value. .TP \fBlog10 \fIarg\fR |
︙ | ︙ | |||
285 286 287 288 289 290 291 | .TP \fBwide \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order 64 bits of that integer value are returned as an integer value. .SH "SEE ALSO" | | | | | | 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 | .TP \fBwide \fIarg\fR . The argument may be any numeric value. The integer part of \fIarg\fR is determined, and then the low order 64 bits of that integer value are returned as an integer value. .SH "SEE ALSO" expr(n), fpclassify(n), mathop(n), namespace(n) .SH "COPYRIGHT" .nf Copyright \(co 1993 The Regents of the University of California. Copyright \(co 1994-2000 Sun Microsystems Incorporated. Copyright \(co 2005, 2006 by Kevin B. Kenny <[email protected]>. .fi '\" Local Variables: '\" mode: nroff '\" fill-column: 78 '\" End: |
Changes to doc/mathop.n.
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | \fB::tcl::mathop::>=\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::>\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::eq\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::ne\fR \fIarg arg\fR .br \fB::tcl::mathop::in\fR \fIarg list\fR .br \fB::tcl::mathop::ni\fR \fIarg list\fR .sp .BE .SH DESCRIPTION | > > > > > > > > > > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | \fB::tcl::mathop::>=\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::>\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::eq\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::ne\fR \fIarg arg\fR .br .VS "8.7, TIP461" \fB::tcl::mathop::lt\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::le\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::gt\fR ?\fIarg\fR ...? .br \fB::tcl::mathop::ge\fR ?\fIarg\fR ...? .VE "8.7, TIP461" .br \fB::tcl::mathop::in\fR \fIarg list\fR .br \fB::tcl::mathop::ni\fR \fIarg list\fR .sp .BE .SH DESCRIPTION |
︙ | ︙ | |||
72 73 74 75 76 77 78 | The following operator commands are supported: .DS .ta 2c 4c 6c 8c \fB~\fR \fB!\fR \fB+\fR \fB\-\fR \fB*\fR \fB/\fR \fB%\fR \fB**\fR \fB&\fR \fB|\fR \fB^\fR \fB>>\fR \fB<<\fR \fB==\fR \fBeq\fR \fB!=\fR \fBne\fR \fB<\fR \fB<=\fR \fB>\fR | | > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | The following operator commands are supported: .DS .ta 2c 4c 6c 8c \fB~\fR \fB!\fR \fB+\fR \fB\-\fR \fB*\fR \fB/\fR \fB%\fR \fB**\fR \fB&\fR \fB|\fR \fB^\fR \fB>>\fR \fB<<\fR \fB==\fR \fBeq\fR \fB!=\fR \fBne\fR \fB<\fR \fB<=\fR \fB>\fR \fB>=\fR \fBin\fR \fBni\fR \fBlt\fR \fBle\fR \fBgt\fR \fBge\fR .DE .SS "MATHEMATICAL OPERATORS" .PP The behaviors of the mathematical operator commands are as follows: .TP \fB!\fR \fIboolean\fR . |
︙ | ︙ | |||
188 189 190 191 192 193 194 | \fB<\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly more than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 | \fB<\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly more than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBlt\fR operator or the \fBstring compare\fR command should be used instead. .TP \fB<=\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be equal to or more than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBle\fR operator or the \fBstring compare\fR command should be used instead. .TP \fB>\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly less than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBgt\fR operator or the \fBstring compare\fR command should be used instead. .TP \fB>=\fR ?\fIarg\fR ...? . Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be equal to or less than the one preceding it. Comparisons are performed preferentially on the numeric values, and are otherwise performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. When the arguments are numeric but should be compared as strings, the \fBge\fR operator or the \fBstring compare\fR command should be used instead. .TP \fBlt\fR ?\fIarg\fR ...? .VS "8.7, TIP461" Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly more than the one preceding it. Comparisons are performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. .VE "8.7, TIP461" .TP \fBle\fR ?\fIarg\fR ...? .VS "8.7, TIP461" Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be equal to or strictly more than the one preceding it. Comparisons are performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. .VE "8.7, TIP461" .TP \fBgt\fR ?\fIarg\fR ...? .VS "8.7, TIP461" Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be strictly less than the one preceding it. Comparisons are performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. .VE "8.7, TIP461" .TP \fBge\fR ?\fIarg\fR ...? .VS "8.7, TIP461" Returns whether the arbitrarily-many arguments are ordered, with each argument after the first having to be equal to or strictly less than the one preceding it. Comparisons are performed using UNICODE string comparison. If fewer than two arguments are present, this operation always returns a true value. .VE "8.7, TIP461" .SS "BIT-WISE OPERATORS" .PP The behaviors of the bit-wise operator commands (all of which only operate on integral arguments) are as follows: .TP \fB~\fR \fInumber\fR . |
︙ | ︙ | |||
295 296 297 298 299 300 301 | \fI# Test for list membership\fR set gotIt [\fBin\fR 3 $list] \fI# Test to see if a value is within some defined range\fR set inRange [\fB<=\fR 1 $x 5] | | > > > > | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 | \fI# Test for list membership\fR set gotIt [\fBin\fR 3 $list] \fI# Test to see if a value is within some defined range\fR set inRange [\fB<=\fR 1 $x 5] \fI# Test to see if a list is numerically sorted\fR set sorted [\fB<=\fR {*}$list] \fI# Test to see if a list is lexically sorted\fR set alphaList {a b c d e f} set sorted [\fBle\fR {*}$alphaList] .CE .SH "SEE ALSO" expr(n), mathfunc(n), namespace(n) .SH KEYWORDS command, expression, operator '\" Local Variables: '\" mode: nroff '\" End: |
Changes to generic/tclAssembly.c.
︙ | ︙ | |||
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 | {"strcaseLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1}, {"strcaseTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1}, {"strcaseUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1}, {"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1}, {"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1}, {"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1}, {"strfind", ASSEM_1BYTE, INST_STR_FIND, 2, 1}, {"strindex", ASSEM_1BYTE, INST_STR_INDEX, 2, 1}, {"strlen", ASSEM_1BYTE, INST_STR_LEN, 1, 1}, {"strmap", ASSEM_1BYTE, INST_STR_MAP, 3, 1}, {"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1}, {"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1}, {"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1}, {"strreplace", ASSEM_1BYTE, INST_STR_REPLACE, 4, 1}, {"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1}, {"strtrim", ASSEM_1BYTE, INST_STR_TRIM, 2, 1}, | > > > > | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 | {"strcaseLower", ASSEM_1BYTE, INST_STR_LOWER, 1, 1}, {"strcaseTitle", ASSEM_1BYTE, INST_STR_TITLE, 1, 1}, {"strcaseUpper", ASSEM_1BYTE, INST_STR_UPPER, 1, 1}, {"strcmp", ASSEM_1BYTE, INST_STR_CMP, 2, 1}, {"strcat", ASSEM_CONCAT1, INST_STR_CONCAT1, INT_MIN,1}, {"streq", ASSEM_1BYTE, INST_STR_EQ, 2, 1}, {"strfind", ASSEM_1BYTE, INST_STR_FIND, 2, 1}, {"strge", ASSEM_1BYTE, INST_STR_GE, 2, 1}, {"strgt", ASSEM_1BYTE, INST_STR_GT, 2, 1}, {"strindex", ASSEM_1BYTE, INST_STR_INDEX, 2, 1}, {"strle", ASSEM_1BYTE, INST_STR_LE, 2, 1}, {"strlen", ASSEM_1BYTE, INST_STR_LEN, 1, 1}, {"strlt", ASSEM_1BYTE, INST_STR_LT, 2, 1}, {"strmap", ASSEM_1BYTE, INST_STR_MAP, 3, 1}, {"strmatch", ASSEM_BOOL, INST_STR_MATCH, 2, 1}, {"strneq", ASSEM_1BYTE, INST_STR_NEQ, 2, 1}, {"strrange", ASSEM_1BYTE, INST_STR_RANGE, 3, 1}, {"strreplace", ASSEM_1BYTE, INST_STR_REPLACE, 4, 1}, {"strrfind", ASSEM_1BYTE, INST_STR_FIND_LAST, 2, 1}, {"strtrim", ASSEM_1BYTE, INST_STR_TRIM, 2, 1}, |
︙ | ︙ | |||
526 527 528 529 530 531 532 | INST_COROUTINE_NAME, /* 149 */ INST_NS_CURRENT, /* 151 */ INST_INFO_LEVEL_NUM, /* 152 */ INST_RESOLVE_COMMAND, /* 154 */ INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */ INST_CONCAT_STK, /* 169 */ INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */ | | > | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 | INST_COROUTINE_NAME, /* 149 */ INST_NS_CURRENT, /* 151 */ INST_INFO_LEVEL_NUM, /* 152 */ INST_RESOLVE_COMMAND, /* 154 */ INST_STR_TRIM, INST_STR_TRIM_LEFT, INST_STR_TRIM_RIGHT, /* 166-168 */ INST_CONCAT_STK, /* 169 */ INST_STR_UPPER, INST_STR_LOWER, INST_STR_TITLE, /* 170-172 */ INST_NUM_TYPE, /* 180 */ INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE /* 191-194 */ }; /* * Helper macros. */ #if defined(TCL_DEBUG_ASSEMBLY) && defined(__GNUC__) && __GNUC__ > 2 |
︙ | ︙ |
Changes to generic/tclBasic.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" #include "tommath.h" #include <math.h> #include <assert.h> #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 /* * Determine whether we're using IEEE floating point */ | > > > | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | #include "tclInt.h" #include "tclOOInt.h" #include "tclCompile.h" #include "tommath.h" #include <math.h> #include <assert.h> #ifndef fpclassify /* Older MSVC */ #include <float.h> #endif /* !fpclassify */ #define INTERP_STACK_INITIAL_SIZE 2000 #define CORO_STACK_INITIAL_SIZE 200 /* * Determine whether we're using IEEE floating point */ |
︙ | ︙ | |||
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | static Tcl_ObjCmdProc ExprBinaryFunc; static Tcl_ObjCmdProc ExprBoolFunc; static Tcl_ObjCmdProc ExprCeilFunc; static Tcl_ObjCmdProc ExprDoubleFunc; static Tcl_ObjCmdProc ExprFloorFunc; static Tcl_ObjCmdProc ExprIntFunc; static Tcl_ObjCmdProc ExprIsqrtFunc; static Tcl_ObjCmdProc ExprMaxFunc; static Tcl_ObjCmdProc ExprMinFunc; static Tcl_ObjCmdProc ExprRandFunc; static Tcl_ObjCmdProc ExprRoundFunc; static Tcl_ObjCmdProc ExprSqrtFunc; static Tcl_ObjCmdProc ExprSrandFunc; static Tcl_ObjCmdProc ExprUnaryFunc; static Tcl_ObjCmdProc ExprWideFunc; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static Tcl_NRPostProc NRCommand; static void ProcessUnexpectedResult(Tcl_Interp *interp, | > > > > > > > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | static Tcl_ObjCmdProc ExprBinaryFunc; static Tcl_ObjCmdProc ExprBoolFunc; static Tcl_ObjCmdProc ExprCeilFunc; static Tcl_ObjCmdProc ExprDoubleFunc; static Tcl_ObjCmdProc ExprFloorFunc; static Tcl_ObjCmdProc ExprIntFunc; static Tcl_ObjCmdProc ExprIsqrtFunc; static Tcl_ObjCmdProc ExprIsFiniteFunc; static Tcl_ObjCmdProc ExprIsInfinityFunc; static Tcl_ObjCmdProc ExprIsNaNFunc; static Tcl_ObjCmdProc ExprIsNormalFunc; static Tcl_ObjCmdProc ExprIsSubnormalFunc; static Tcl_ObjCmdProc ExprIsUnorderedFunc; static Tcl_ObjCmdProc ExprMaxFunc; static Tcl_ObjCmdProc ExprMinFunc; static Tcl_ObjCmdProc ExprRandFunc; static Tcl_ObjCmdProc ExprRoundFunc; static Tcl_ObjCmdProc ExprSqrtFunc; static Tcl_ObjCmdProc ExprSrandFunc; static Tcl_ObjCmdProc ExprUnaryFunc; static Tcl_ObjCmdProc ExprWideFunc; static Tcl_ObjCmdProc FloatClassifyObjCmd; static void MathFuncWrongNumArgs(Tcl_Interp *interp, int expected, int actual, Tcl_Obj *const *objv); static Tcl_NRPostProc NRCoroutineCallerCallback; static Tcl_NRPostProc NRCoroutineExitCallback; static Tcl_NRPostProc NRCommand; static void ProcessUnexpectedResult(Tcl_Interp *interp, |
︙ | ︙ | |||
233 234 235 236 237 238 239 240 241 242 243 244 245 246 | {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, | > | 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | {"coroutine", NULL, NULL, TclNRCoroutineObjCmd, CMD_IS_SAFE}, {"error", Tcl_ErrorObjCmd, TclCompileErrorCmd, NULL, CMD_IS_SAFE}, {"eval", Tcl_EvalObjCmd, NULL, TclNREvalObjCmd, CMD_IS_SAFE}, {"expr", Tcl_ExprObjCmd, TclCompileExprCmd, TclNRExprObjCmd, CMD_IS_SAFE}, {"for", Tcl_ForObjCmd, TclCompileForCmd, TclNRForObjCmd, CMD_IS_SAFE}, {"foreach", Tcl_ForeachObjCmd, TclCompileForeachCmd, TclNRForeachCmd, CMD_IS_SAFE}, {"format", Tcl_FormatObjCmd, TclCompileFormatCmd, NULL, CMD_IS_SAFE}, {"fpclassify", FloatClassifyObjCmd, NULL, NULL, CMD_IS_SAFE}, {"global", Tcl_GlobalObjCmd, TclCompileGlobalCmd, NULL, CMD_IS_SAFE}, {"if", Tcl_IfObjCmd, TclCompileIfCmd, TclNRIfObjCmd, CMD_IS_SAFE}, {"incr", Tcl_IncrObjCmd, TclCompileIncrCmd, NULL, CMD_IS_SAFE}, {"join", Tcl_JoinObjCmd, NULL, NULL, CMD_IS_SAFE}, {"lappend", Tcl_LappendObjCmd, TclCompileLappendCmd, NULL, CMD_IS_SAFE}, {"lassign", Tcl_LassignObjCmd, TclCompileLassignCmd, NULL, CMD_IS_SAFE}, {"lindex", Tcl_LindexObjCmd, TclCompileLindexCmd, NULL, CMD_IS_SAFE}, |
︙ | ︙ | |||
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | { "double", ExprDoubleFunc, NULL }, { "entier", ExprIntFunc, NULL }, { "exp", ExprUnaryFunc, (ClientData) exp }, { "floor", ExprFloorFunc, NULL }, { "fmod", ExprBinaryFunc, (ClientData) fmod }, { "hypot", ExprBinaryFunc, (ClientData) hypot }, { "int", ExprIntFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, { "log", ExprUnaryFunc, (ClientData) log }, { "log10", ExprUnaryFunc, (ClientData) log10 }, { "max", ExprMaxFunc, NULL }, { "min", ExprMinFunc, NULL }, { "pow", ExprBinaryFunc, (ClientData) pow }, { "rand", ExprRandFunc, NULL }, { "round", ExprRoundFunc, NULL }, | > > > > > > | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 | { "double", ExprDoubleFunc, NULL }, { "entier", ExprIntFunc, NULL }, { "exp", ExprUnaryFunc, (ClientData) exp }, { "floor", ExprFloorFunc, NULL }, { "fmod", ExprBinaryFunc, (ClientData) fmod }, { "hypot", ExprBinaryFunc, (ClientData) hypot }, { "int", ExprIntFunc, NULL }, { "isfinite", ExprIsFiniteFunc, NULL }, { "isinf", ExprIsInfinityFunc, NULL }, { "isnan", ExprIsNaNFunc, NULL }, { "isnormal", ExprIsNormalFunc, NULL }, { "isqrt", ExprIsqrtFunc, NULL }, { "issubnormal", ExprIsSubnormalFunc, NULL, }, { "isunordered", ExprIsUnorderedFunc, NULL, }, { "log", ExprUnaryFunc, (ClientData) log }, { "log10", ExprUnaryFunc, (ClientData) log10 }, { "max", ExprMaxFunc, NULL }, { "min", ExprMinFunc, NULL }, { "pow", ExprBinaryFunc, (ClientData) pow }, { "rand", ExprRandFunc, NULL }, { "round", ExprRoundFunc, NULL }, |
︙ | ︙ | |||
480 481 482 483 484 485 486 487 488 489 490 491 492 493 | { ">", TclSortingOpCmd, TclCompileGreaterOpCmd, /* unused */ {0}, NULL}, { ">=", TclSortingOpCmd, TclCompileGeqOpCmd, /* unused */ {0}, NULL}, { "==", TclSortingOpCmd, TclCompileEqOpCmd, /* unused */ {0}, NULL}, { "eq", TclSortingOpCmd, TclCompileStreqOpCmd, /* unused */ {0}, NULL}, { NULL, NULL, NULL, {0}, NULL} }; /* *---------------------------------------------------------------------- | > > > > > > > > | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 | { ">", TclSortingOpCmd, TclCompileGreaterOpCmd, /* unused */ {0}, NULL}, { ">=", TclSortingOpCmd, TclCompileGeqOpCmd, /* unused */ {0}, NULL}, { "==", TclSortingOpCmd, TclCompileEqOpCmd, /* unused */ {0}, NULL}, { "eq", TclSortingOpCmd, TclCompileStreqOpCmd, /* unused */ {0}, NULL}, { "lt", TclSortingOpCmd, TclCompileStrLtOpCmd, /* unused */ {0}, NULL}, { "le", TclSortingOpCmd, TclCompileStrLeOpCmd, /* unused */ {0}, NULL}, { "gt", TclSortingOpCmd, TclCompileStrGtOpCmd, /* unused */ {0}, NULL}, { "ge", TclSortingOpCmd, TclCompileStrGeOpCmd, /* unused */ {0}, NULL}, { NULL, NULL, NULL, {0}, NULL} }; /* *---------------------------------------------------------------------- |
︙ | ︙ | |||
7506 7507 7508 7509 7510 7511 7512 7513 7514 7515 7516 7517 7518 7519 | * To avoid duplicating the random number generation code we simply clean * up our state and call the real random number function. That function * will always succeed. */ return ExprRandFunc(clientData, interp, 1, objv); } /* *---------------------------------------------------------------------- * * MathFuncWrongNumArgs -- * * Generate an error message when a math function presents the wrong | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581 7582 7583 7584 7585 7586 7587 7588 7589 7590 7591 7592 7593 7594 7595 7596 7597 7598 7599 7600 7601 7602 7603 7604 7605 7606 7607 7608 7609 7610 7611 7612 7613 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 7628 7629 7630 7631 7632 7633 7634 7635 7636 7637 7638 7639 7640 7641 7642 7643 7644 7645 7646 7647 7648 7649 7650 7651 7652 7653 7654 7655 7656 7657 7658 7659 7660 7661 7662 7663 7664 7665 7666 7667 7668 7669 7670 7671 7672 7673 7674 7675 7676 7677 7678 7679 7680 7681 7682 7683 7684 7685 7686 7687 7688 7689 7690 7691 7692 7693 7694 7695 7696 7697 7698 7699 7700 7701 7702 7703 7704 7705 7706 7707 7708 7709 7710 7711 7712 7713 7714 7715 7716 7717 7718 7719 7720 7721 7722 7723 7724 7725 7726 7727 7728 7729 7730 7731 7732 7733 7734 7735 7736 7737 7738 7739 7740 7741 7742 7743 7744 7745 7746 7747 7748 7749 7750 7751 7752 7753 7754 7755 7756 7757 7758 7759 7760 7761 7762 7763 7764 7765 7766 7767 7768 7769 7770 7771 7772 7773 7774 7775 7776 7777 7778 7779 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 7832 7833 7834 7835 7836 7837 7838 7839 7840 7841 7842 7843 7844 7845 7846 7847 7848 7849 7850 7851 7852 7853 | * To avoid duplicating the random number generation code we simply clean * up our state and call the real random number function. That function * will always succeed. */ return ExprRandFunc(clientData, interp, 1, objv); } /* *---------------------------------------------------------------------- * * Double Classification Functions -- * * This page contains the functions that implement all of the built-in * math functions for classifying IEEE doubles. * * These have to be a little bit careful while Tcl_GetDoubleFromObj() * rejects NaN values, which these functions *explicitly* accept. * * Results: * Each function returns TCL_OK if it succeeds and pushes an Tcl object * holding the result. If it fails it returns TCL_ERROR and leaves an * error message in the interpreter's result. * * Side effects: * None. * *---------------------------------------------------------------------- */ /* * Older MSVC is supported by Tcl, but doesn't have fpclassify(). Of course. * But it does have _fpclass() which does almost the same job. * * This makes it conform to the C99 standard API, and just delegates to the * standard macro on platforms that do it correctly. */ static inline int ClassifyDouble( double d) { #ifdef fpclassify return fpclassify(d); #else /* !fpclassify */ #define FP_ZERO 0 #define FP_NORMAL 1 #define FP_SUBNORMAL 2 #define FP_INFINITE 3 #define FP_NAN 4 switch (_fpclass(d)) { case _FPCLASS_NZ: case _FPCLASS_PZ: return FP_ZERO; case _FPCLASS_NN: case _FPCLASS_PN: return FP_NORMAL; case _FPCLASS_ND: case _FPCLASS_PD: return FP_SUBNORMAL; case _FPCLASS_NINF: case _FPCLASS_PINF: return FP_INFINITE; default: Tcl_Panic("result of _fpclass() outside documented range!"); case _FPCLASS_QNAN: case _FPCLASS_SNAN: return FP_NAN; } #endif /* fpclassify */ } static int ExprIsFiniteFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } type = ClassifyDouble(d); result = (type != FP_INFINITE && type != FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsInfinityFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_INFINITE); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsNaNFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 1; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsNormalFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_NORMAL); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsSubnormalFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 2) { MathFuncWrongNumArgs(interp, 2, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type != TCL_NUMBER_NAN) { if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } result = (ClassifyDouble(d) == FP_SUBNORMAL); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int ExprIsUnorderedFunc( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; ClientData ptr; int type, result = 0; if (objc != 3) { MathFuncWrongNumArgs(interp, 3, objc, objv); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result = 1; } else { d = *((const double *) ptr); result = (ClassifyDouble(d) == FP_NAN); } if (TclGetNumberFromObj(interp, objv[2], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { result |= 1; } else { d = *((const double *) ptr); result |= (ClassifyDouble(d) == FP_NAN); } Tcl_SetObjResult(interp, Tcl_NewBooleanObj(result)); return TCL_OK; } static int FloatClassifyObjCmd( ClientData ignored, Tcl_Interp *interp, /* The interpreter in which to execute the * function. */ int objc, /* Actual parameter count */ Tcl_Obj *const *objv) /* Actual parameter list */ { double d; Tcl_Obj *objPtr; ClientData ptr; int type; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "floatValue"); return TCL_ERROR; } if (TclGetNumberFromObj(interp, objv[1], &ptr, &type) != TCL_OK) { return TCL_ERROR; } if (type == TCL_NUMBER_NAN) { goto gotNaN; } else if (Tcl_GetDoubleFromObj(interp, objv[1], &d) != TCL_OK) { return TCL_ERROR; } switch (ClassifyDouble(d)) { case FP_INFINITE: TclNewLiteralStringObj(objPtr, "infinite"); break; case FP_NAN: gotNaN: TclNewLiteralStringObj(objPtr, "nan"); break; case FP_NORMAL: TclNewLiteralStringObj(objPtr, "normal"); break; case FP_SUBNORMAL: TclNewLiteralStringObj(objPtr, "subnormal"); break; case FP_ZERO: TclNewLiteralStringObj(objPtr, "zero"); break; default: Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unable to classify number: %f", d)); return TCL_ERROR; } Tcl_SetObjResult(interp, objPtr); return TCL_OK; } /* *---------------------------------------------------------------------- * * MathFuncWrongNumArgs -- * * Generate an error message when a math function presents the wrong |
︙ | ︙ |
Changes to generic/tclCompCmdsSZ.c.
︙ | ︙ | |||
4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 | Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_EQ, envPtr); } int TclCompileMinusOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 | Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_EQ, envPtr); } int TclCompileStrLtOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_LT, envPtr); } int TclCompileStrLeOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_LE, envPtr); } int TclCompileStrGtOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_GT, envPtr); } int TclCompileStrGeOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ CompileEnv *envPtr) { return CompileComparisonOpCmd(interp, parsePtr, INST_STR_GE, envPtr); } int TclCompileMinusOpCmd( Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, /* Points to defintion of command being * compiled. */ |
︙ | ︙ |
Changes to generic/tclCompExpr.c.
︙ | ︙ | |||
277 278 279 280 281 282 283 | * for us. In the end though, a close paren is * not really a binary operator, and some * special coding in ParseExpr() make sure we * never put an actual CLOSE_PAREN node in the * parse tree. The sub-expression between * parens becomes the single argument of the * matching OPEN_PAREN unary operator. */ | > > > > | | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | * for us. In the end though, a close paren is * not really a binary operator, and some * special coding in ParseExpr() make sure we * never put an actual CLOSE_PAREN node in the * parse tree. The sub-expression between * parens becomes the single argument of the * matching OPEN_PAREN unary operator. */ #define STR_LT (BINARY | 28) #define STR_GT (BINARY | 29) #define STR_LEQ (BINARY | 30) #define STR_GEQ (BINARY | 31) #define END (BINARY | 32) /* This lexeme represents the end of the * string being parsed. Treating it as a * binary operator follows the same logic as * the CLOSE_PAREN lexeme and END pairs with * START, in the same way that CLOSE_PAREN * pairs with OPEN_PAREN. */ |
︙ | ︙ | |||
356 357 358 359 360 361 362 363 364 | PREC_OR, /* OR */ PREC_EQUAL, /* STREQ */ PREC_EQUAL, /* STRNEQ */ PREC_EXPON, /* EXPON */ PREC_EQUAL, /* IN_LIST */ PREC_EQUAL, /* NOT_IN_LIST */ PREC_CLOSE_PAREN, /* CLOSE_PAREN */ PREC_END, /* END */ /* Expansion room for more binary operators */ | > > > > < < | 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 | PREC_OR, /* OR */ PREC_EQUAL, /* STREQ */ PREC_EQUAL, /* STRNEQ */ PREC_EXPON, /* EXPON */ PREC_EQUAL, /* IN_LIST */ PREC_EQUAL, /* NOT_IN_LIST */ PREC_CLOSE_PAREN, /* CLOSE_PAREN */ PREC_COMPARE, /* STR_LT */ PREC_COMPARE, /* STR_GT */ PREC_COMPARE, /* STR_LEQ */ PREC_COMPARE, /* STR_GEQ */ PREC_END, /* END */ /* Expansion room for more binary operators */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Unary operator lexemes */ PREC_UNARY, /* UNARY_PLUS */ PREC_UNARY, /* UNARY_MINUS */ PREC_UNARY, /* FUNCTION */ PREC_START, /* START */ PREC_OPEN_PAREN, /* OPEN_PAREN */ PREC_UNARY, /* NOT*/ |
︙ | ︙ | |||
411 412 413 414 415 416 417 418 419 | 0, /* OR */ INST_STR_EQ, /* STREQ */ INST_STR_NEQ, /* STRNEQ */ INST_EXPON, /* EXPON */ INST_LIST_IN, /* IN_LIST */ INST_LIST_NOT_IN, /* NOT_IN_LIST */ 0, /* CLOSE_PAREN */ 0, /* END */ /* Expansion room for more binary operators */ | > > > > < < | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | 0, /* OR */ INST_STR_EQ, /* STREQ */ INST_STR_NEQ, /* STRNEQ */ INST_EXPON, /* EXPON */ INST_LIST_IN, /* IN_LIST */ INST_LIST_NOT_IN, /* NOT_IN_LIST */ 0, /* CLOSE_PAREN */ INST_STR_LT, /* STR_LT */ INST_STR_GT, /* STR_GT */ INST_STR_LE, /* STR_LEQ */ INST_STR_GE, /* STR_GEQ */ 0, /* END */ /* Expansion room for more binary operators */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Unary operator lexemes */ INST_UPLUS, /* UNARY_PLUS */ INST_UMINUS, /* UNARY_MINUS */ 0, /* FUNCTION */ 0, /* START */ 0, /* OPEN_PAREN */ INST_LNOT, /* NOT*/ |
︙ | ︙ | |||
1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 | *lexemePtr = STRNEQ; return 2; case 'i': *lexemePtr = NOT_IN_LIST; return 2; } } } literal = Tcl_NewObj(); if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end, TCL_PARSE_NO_WHITESPACE) == TCL_OK) { if (end < start + numBytes && !TclIsBareword(*end)) { | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 | *lexemePtr = STRNEQ; return 2; case 'i': *lexemePtr = NOT_IN_LIST; return 2; } } break; case 'l': if ((numBytes > 1) && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { switch (start[1]) { case 't': *lexemePtr = STR_LT; return 2; case 'e': *lexemePtr = STR_LEQ; return 2; } } break; case 'g': if ((numBytes > 1) && ((numBytes == 2) || start[2] & 0x80 || !isalpha(UCHAR(start[2])))) { switch (start[1]) { case 't': *lexemePtr = STR_GT; return 2; case 'e': *lexemePtr = STR_GEQ; return 2; } } break; } literal = Tcl_NewObj(); if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end, TCL_PARSE_NO_WHITESPACE) == TCL_OK) { if (end < start + numBytes && !TclIsBareword(*end)) { |
︙ | ︙ | |||
2553 2554 2555 2556 2557 2558 2559 | } /* *---------------------------------------------------------------------- * * TclSortingOpCmd -- * Implements the commands: | | | 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 | } /* *---------------------------------------------------------------------- * * TclSortingOpCmd -- * Implements the commands: * <, <=, >, >=, ==, eq, lt, le, gt, ge * in the ::tcl::mathop namespace. These commands are defined for * arbitrary number of arguments by computing the AND of the base * operator applied to all neighbor argument pairs. * * Results: * A standard Tcl return code and result left in interp. * |
︙ | ︙ |
Changes to generic/tclCompile.c.
︙ | ︙ | |||
663 664 665 666 667 668 669 670 671 672 673 674 675 676 | /* The top word is the default, the next op4 words (min 1) are a key * path into the dictionary just below the keys on the stack, and all * those values are replaced by the value read out of that key-path * (like [dict get]) except if there is no such key, when instead the * default is pushed instead. * Stack: ... dict key1 ... keyN default => ... value */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ | > > > > > > > > > | 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 | /* The top word is the default, the next op4 words (min 1) are a key * path into the dictionary just below the keys on the stack, and all * those values are replaced by the value read out of that key-path * (like [dict get]) except if there is no such key, when instead the * default is pushed instead. * Stack: ... dict key1 ... keyN default => ... value */ {"strlt", 1, -1, 0, {OPERAND_NONE}}, /* String Less: push (stknext < stktop) */ {"strgt", 1, -1, 0, {OPERAND_NONE}}, /* String Greater: push (stknext > stktop) */ {"strle", 1, -1, 0, {OPERAND_NONE}}, /* String Less or equal: push (stknext <= stktop) */ {"strge", 1, -1, 0, {OPERAND_NONE}}, /* String Greater or equal: push (stknext >= stktop) */ {NULL, 0, 0, 0, {OPERAND_NONE}} }; /* * Prototypes for procedures defined later in this file: */ |
︙ | ︙ |
Changes to generic/tclCompile.h.
︙ | ︙ | |||
785 786 787 788 789 790 791 792 793 794 795 796 797 798 | INST_LAPPEND_LIST_ARRAY, INST_LAPPEND_LIST_ARRAY_STK, INST_LAPPEND_LIST_STK, INST_CLOCK_READ, INST_DICT_GET_DEF, /* The last opcode */ LAST_INST_OPCODE }; /* * Table describing the Tcl bytecode instructions: their name (for displaying | > > > > > > | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | INST_LAPPEND_LIST_ARRAY, INST_LAPPEND_LIST_ARRAY_STK, INST_LAPPEND_LIST_STK, INST_CLOCK_READ, INST_DICT_GET_DEF, /* TIP 461 */ INST_STR_LT, INST_STR_GT, INST_STR_LE, INST_STR_GE, /* The last opcode */ LAST_INST_OPCODE }; /* * Table describing the Tcl bytecode instructions: their name (for displaying |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 | * ----------------------------------------------------------------- * Start of string-related instructions. */ case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ stringCompare: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; { int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ) || (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ)); | > > > > | 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 | * ----------------------------------------------------------------- * Start of string-related instructions. */ case INST_STR_EQ: case INST_STR_NEQ: /* String (in)equality check */ case INST_STR_CMP: /* String compare. */ case INST_STR_LT: case INST_STR_GT: case INST_STR_LE: case INST_STR_GE: stringCompare: value2Ptr = OBJ_AT_TOS; valuePtr = OBJ_UNDER_TOS; { int checkEq = ((*pc == INST_EQ) || (*pc == INST_NEQ) || (*pc == INST_STR_EQ) || (*pc == INST_STR_NEQ)); |
︙ | ︙ | |||
4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 | match = (match == 0); break; case INST_STR_NEQ: case INST_NEQ: match = (match != 0); break; case INST_LT: match = (match < 0); break; case INST_GT: match = (match > 0); break; case INST_LE: match = (match <= 0); break; case INST_GE: match = (match >= 0); break; } } TRACE(("\"%.20s\" \"%.20s\" => %d\n", O2S(valuePtr), O2S(value2Ptr), (match < 0 ? -1 : match > 0 ? 1 : 0))); | > > > > | 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 | match = (match == 0); break; case INST_STR_NEQ: case INST_NEQ: match = (match != 0); break; case INST_LT: case INST_STR_LT: match = (match < 0); break; case INST_GT: case INST_STR_GT: match = (match > 0); break; case INST_LE: case INST_STR_LE: match = (match <= 0); break; case INST_GE: case INST_STR_GE: match = (match >= 0); break; } } TRACE(("\"%.20s\" \"%.20s\" => %d\n", O2S(valuePtr), O2S(value2Ptr), (match < 0 ? -1 : match > 0 ? 1 : 0))); |
︙ | ︙ |
Changes to generic/tclInt.h.
︙ | ︙ | |||
4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 | Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileEqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStreqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); /* | > > > > > > > > > > > > | 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 | Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileEqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStreqOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStrLtOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStrLeOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStrGtOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileStrGeOpCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); MODULE_SCOPE int TclCompileAssembleCmd(Tcl_Interp *interp, Tcl_Parse *parsePtr, Command *cmdPtr, struct CompileEnv *envPtr); /* |
︙ | ︙ |
Changes to generic/tclNamesp.c.
︙ | ︙ | |||
1563 1564 1565 1566 1567 1568 1569 | * substituted part of the command (as a list) as their * content! */ if (isNew) { Tcl_Obj *cmdObj, *cmdPrefixObj; | | | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 | * substituted part of the command (as a list) as their * content! */ if (isNew) { Tcl_Obj *cmdObj, *cmdPrefixObj; #if 1 TclNewObj(cmdObj); Tcl_AppendStringsToObj(cmdObj, nsPtr->fullName, (nsPtr->parentPtr ? "::" : ""), nsCmdName, NULL); #else cmdObj = Tcl_NewStringObj(nsCmdName, -1); #endif cmdPrefixObj = Tcl_NewListObj(1, &cmdObj); |
︙ | ︙ |
Changes to generic/tclStrToD.c.
︙ | ︙ | |||
3209 3210 3211 3212 3213 3214 3215 | /* * b = bw * 2**b2 * 5**b5 * mminus = 5**m5 */ TclInitBignumFromWideUInt(&b, bw); | | | 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 | /* * b = bw * 2**b2 * 5**b5 * mminus = 5**m5 */ TclInitBignumFromWideUInt(&b, bw); mp_init_set(&mminus, 1); MulPow5(&b, b5, &b); mp_mul_2d(&b, b2, &b); /* * Adjust if the logarithm was guessed wrong. */ |
︙ | ︙ | |||
3594 3595 3596 3597 3598 3599 3600 | /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ TclInitBignumFromWideUInt(&b, bw); mp_mul_2d(&b, b2, &b); | | | | 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 | /* * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ TclInitBignumFromWideUInt(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); /* * Handle the case where we guess the position of the decimal point wrong. */ if (mp_cmp_mag(&b, &S) == MP_LT) { mp_mul_d(&b, 10, &b); minit = 10; ilim =ilim1; --k; } /* * mminus = 2**m2minus * 5**m5 */ mp_init_set(&mminus, minit); mp_mul_2d(&mminus, m2minus, &mminus); if (m2plus > m2minus) { mp_init_copy(&mplus, &mminus); mp_mul_2d(&mplus, m2plus-m2minus, &mplus); } /* |
︙ | ︙ | |||
3803 3804 3805 3806 3807 3808 3809 | * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ mp_init_multi(&dig, NULL); TclInitBignumFromWideUInt(&b, bw); mp_mul_2d(&b, b2, &b); | | | 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 | * b = bw * 2**b2 * 5**b5 * S = 2**s2 * 5*s5 */ mp_init_multi(&dig, NULL); TclInitBignumFromWideUInt(&b, bw); mp_mul_2d(&b, b2, &b); mp_init_set(&S, 1); MulPow5(&S, s5, &S); mp_mul_2d(&S, s2, &S); /* * Handle the case where we guess the position of the decimal point wrong. */ if (mp_cmp_mag(&b, &S) == MP_LT) { |
︙ | ︙ |
Changes to tests/expr.test.
︙ | ︙ | |||
128 129 130 131 132 133 134 | global xxx set xxx "" 12days 1 1 1 set result [string length $xxx] unset xxx return $result } | | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | global xxx set xxx "" 12days 1 1 1 set result [string length $xxx] unset xxx return $result } # start of tests catch {unset a b i x} test expr-1.1 {TclCompileExprCmd: no expression} { list [catch {expr } msg] $msg } {1 {wrong # args: should be "expr arg ?arg ...?"}} |
︙ | ︙ | |||
406 407 408 409 410 411 412 413 414 415 416 417 418 419 | } -returnCodes error -match glob -result * test expr-8.34 {expr edge cases} -body { expr {1E+} } -returnCodes error -match glob -result * test expr-8.35 {expr edge cases} -body { expr {1ea} } -returnCodes error -match glob -result * test expr-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12 test expr-9.2 {CompileRelationalExpr: just shift expr} {expr 0xff>>2} 63 test expr-9.3 {CompileRelationalExpr: just shift expr} {expr -1>>2} -1 test expr-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8 test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} { expr {int(1<<63)} | > > > > > > > > > > > > > > > > > > > > | 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | } -returnCodes error -match glob -result * test expr-8.34 {expr edge cases} -body { expr {1E+} } -returnCodes error -match glob -result * test expr-8.35 {expr edge cases} -body { expr {1ea} } -returnCodes error -match glob -result * test expr-8.36 {CompileEqualtyExpr: string comparison ops} { set x 012 set y 0x0 list [expr {$x < $y}] [expr {$x lt $y}] [expr {$x lt $x}] } {0 1 0} test expr-8.37 {CompileEqualtyExpr: string comparison ops} { set x 012 set y 0x0 list [expr {$x <= $y}] [expr {$x le $y}] [expr {$x le $x}] } {0 1 1} test expr-8.38 {CompileEqualtyExpr: string comparison ops} { set x 012 set y 0x0 list [expr {$x > $y}] [expr {$x gt $y}] [expr {$x gt $x}] } {1 0 0} test expr-8.39 {CompileEqualtyExpr: string comparison ops} { set x 012 set y 0x0 list [expr {$x >= $y}] [expr {$x ge $y}] [expr {$x ge $x}] } {1 0 1} test expr-9.1 {CompileRelationalExpr: just shift expr} {expr 3<<2} 12 test expr-9.2 {CompileRelationalExpr: just shift expr} {expr 0xff>>2} 63 test expr-9.3 {CompileRelationalExpr: just shift expr} {expr -1>>2} -1 test expr-9.4 {CompileRelationalExpr: just shift expr} {expr {1<<3}} 8 test expr-9.5 {CompileRelationalExpr: shift expr producing LONG_MIN} { expr {int(1<<63)} |
︙ | ︙ | |||
7157 7158 7159 7160 7161 7162 7163 | } { set a [list one two three] list [expr {$a eq {}}] [expr {$a < {}}] [expr {$a > {}}] [ string match {*no string representation*} [ ::tcl::unsupported::representation $a]] } {0 0 1 1} | > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > | > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > | > > | > | > > | 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 7221 7222 7223 7224 7225 7226 7227 7228 7229 7230 7231 7232 7233 7234 7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 | } { set a [list one two three] list [expr {$a eq {}}] [expr {$a < {}}] [expr {$a > {}}] [ string match {*no string representation*} [ ::tcl::unsupported::representation $a]] } {0 0 1 1} foreach func {isfinite isinf isnan isnormal issubnormal} { test expr-53.1.$func {float classification: basic arg handling} -body { expr ${func}() } -returnCodes error -result "too few arguments for math function \"$func\"" test expr-53.2.$func {float classification: basic arg handling} -body { expr ${func}(1,2) } -returnCodes error -result "too many arguments for math function \"$func\"" test expr-53.3.$func {float classification: basic arg handling} -body { expr ${func}(true) } -returnCodes error -result {expected number but got "true"} test expr-53.4.$func {float classification: basic arg handling} -body { expr ${func}("gorp") } -returnCodes error -result {expected number but got "gorp"} test expr-53.5.$func {float classification: basic arg handling} -body { expr ${func}(1.0) } -match glob -result * test expr-53.6.$func {float classification: basic arg handling} -body { expr ${func}(0x123) } -match glob -result * } test expr-54.0 {float classification: isfinite} {expr {isfinite(1.0)}} 1 test expr-54.1 {float classification: isfinite} {expr {isfinite(-1.0)}} 1 test expr-54.2 {float classification: isfinite} {expr {isfinite(0.0)}} 1 test expr-54.3 {float classification: isfinite} {expr {isfinite(-0.0)}} 1 test expr-54.4 {float classification: isfinite} {expr {isfinite(1/Inf)}} 1 test expr-54.5 {float classification: isfinite} {expr {isfinite(-1/Inf)}} 1 test expr-54.6 {float classification: isfinite} {expr {isfinite(1e-314)}} 1 test expr-54.7 {float classification: isfinite} {expr {isfinite(inf)}} 0 test expr-54.8 {float classification: isfinite} {expr {isfinite(-inf)}} 0 test expr-54.9 {float classification: isfinite} {expr {isfinite(NaN)}} 0 test expr-55.0 {float classification: isinf} {expr {isinf(1.0)}} 0 test expr-55.1 {float classification: isinf} {expr {isinf(-1.0)}} 0 test expr-55.2 {float classification: isinf} {expr {isinf(0.0)}} 0 test expr-55.3 {float classification: isinf} {expr {isinf(-0.0)}} 0 test expr-55.4 {float classification: isinf} {expr {isinf(1/Inf)}} 0 test expr-55.5 {float classification: isinf} {expr {isinf(-1/Inf)}} 0 test expr-55.6 {float classification: isinf} {expr {isinf(1e-314)}} 0 test expr-55.7 {float classification: isinf} {expr {isinf(inf)}} 1 test expr-55.8 {float classification: isinf} {expr {isinf(-inf)}} 1 test expr-55.9 {float classification: isinf} {expr {isinf(NaN)}} 0 test expr-56.0 {float classification: isnan} {expr {isnan(1.0)}} 0 test expr-56.1 {float classification: isnan} {expr {isnan(-1.0)}} 0 test expr-56.2 {float classification: isnan} {expr {isnan(0.0)}} 0 test expr-56.3 {float classification: isnan} {expr {isnan(-0.0)}} 0 test expr-56.4 {float classification: isnan} {expr {isnan(1/Inf)}} 0 test expr-56.5 {float classification: isnan} {expr {isnan(-1/Inf)}} 0 test expr-56.6 {float classification: isnan} {expr {isnan(1e-314)}} 0 test expr-56.7 {float classification: isnan} {expr {isnan(inf)}} 0 test expr-56.8 {float classification: isnan} {expr {isnan(-inf)}} 0 test expr-56.9 {float classification: isnan} {expr {isnan(NaN)}} 1 test expr-57.0 {float classification: isnormal} {expr {isnormal(1.0)}} 1 test expr-57.1 {float classification: isnormal} {expr {isnormal(-1.0)}} 1 test expr-57.2 {float classification: isnormal} {expr {isnormal(0.0)}} 0 test expr-57.3 {float classification: isnormal} {expr {isnormal(-0.0)}} 0 test expr-57.4 {float classification: isnormal} {expr {isnormal(1/Inf)}} 0 test expr-57.5 {float classification: isnormal} {expr {isnormal(-1/Inf)}} 0 test expr-57.6 {float classification: isnormal} {expr {isnormal(1e-314)}} 0 test expr-57.7 {float classification: isnormal} {expr {isnormal(inf)}} 0 test expr-57.8 {float classification: isnormal} {expr {isnormal(-inf)}} 0 test expr-57.9 {float classification: isnormal} {expr {isnormal(NaN)}} 0 test expr-58.0 {float classification: issubnormal} {expr {issubnormal(1.0)}} 0 test expr-58.1 {float classification: issubnormal} {expr {issubnormal(-1.0)}} 0 test expr-58.2 {float classification: issubnormal} {expr {issubnormal(0.0)}} 0 test expr-58.3 {float classification: issubnormal} {expr {issubnormal(-0.0)}} 0 test expr-58.4 {float classification: issubnormal} {expr {issubnormal(1/Inf)}} 0 test expr-58.5 {float classification: issubnormal} {expr {issubnormal(-1/Inf)}} 0 test expr-58.6 {float classification: issubnormal} {expr {issubnormal(1e-314)}} 1 test expr-58.7 {float classification: issubnormal} {expr {issubnormal(inf)}} 0 test expr-58.8 {float classification: issubnormal} {expr {issubnormal(-inf)}} 0 test expr-58.9 {float classification: issubnormal} {expr {issubnormal(NaN)}} 0 test expr-59.0 {float classification: fpclassify} {fpclassify 1.0} normal test expr-59.1 {float classification: fpclassify} {fpclassify -1.0} normal test expr-59.2 {float classification: fpclassify} {fpclassify 0.0} zero test expr-59.3 {float classification: fpclassify} {fpclassify -0.0} zero test expr-59.4 {float classification: fpclassify} {fpclassify [expr 1/Inf]} zero test expr-59.5 {float classification: fpclassify} {fpclassify [expr -1/Inf]} zero test expr-59.6 {float classification: fpclassify} {fpclassify 1e-314} subnormal test expr-59.7 {float classification: fpclassify} {fpclassify inf} infinite test expr-59.8 {float classification: fpclassify} {fpclassify -inf} infinite test expr-59.9 {float classification: fpclassify} {fpclassify NaN} nan test expr-59.10 {float classification: fpclassify} -returnCodes error -body { fpclassify } -result {wrong # args: should be "fpclassify floatValue"} test expr-59.11 {float classification: fpclassify} -returnCodes error -body { fpclassify a b } -result {wrong # args: should be "fpclassify floatValue"} test expr-59.12 {float classification: fpclassify} -returnCodes error -body { fpclassify gorp } -result {expected number but got "gorp"} test expr-60.1 {float classification: basic arg handling} -body { expr isunordered() } -returnCodes error -result {too few arguments for math function "isunordered"} test expr-60.2 {float classification: basic arg handling} -body { expr isunordered(1) } -returnCodes error -result {too few arguments for math function "isunordered"} test expr-60.3 {float classification: basic arg handling} -body { expr {isunordered(1, 2, 3)} } -returnCodes error -result {too many arguments for math function "isunordered"} test expr-60.4 {float classification: basic arg handling} -body { expr {isunordered(true, 1.0)} } -returnCodes error -result {expected number but got "true"} test expr-60.5 {float classification: basic arg handling} -body { expr {isunordered("gorp", 1.0)} } -returnCodes error -result {expected number but got "gorp"} test expr-60.6 {float classification: basic arg handling} -body { expr {isunordered(0x123, 1.0)} } -match glob -result * test expr-60.7 {float classification: basic arg handling} -body { expr {isunordered(1.0, true)} } -returnCodes error -result {expected number but got "true"} test expr-60.8 {float classification: basic arg handling} -body { expr {isunordered(1.0, "gorp")} } -returnCodes error -result {expected number but got "gorp"} test expr-60.9 {float classification: basic arg handling} -body { expr {isunordered(1.0, 0x123)} } -match glob -result * # Big matrix of comparisons, but it's just a binary isinf() set values {1.0 -1.0 0.0 -0.0 1e-314 Inf -Inf NaN} set results {0 0 0 0 0 0 0 1} set ctr 0 foreach v1 $values r1 $results { foreach v2 $values r2 $results { test expr-61.[incr ctr] "float classification: isunordered($v1,$v2)" { expr {isunordered($v1, $v2)} } [expr {$r1 || $r2}] } } unset -nocomplain values results ctr # cleanup unset -nocomplain a unset -nocomplain min unset -nocomplain max ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: |
Changes to tests/info.test.
︙ | ︙ | |||
651 652 653 654 655 656 657 | catch {namespace delete x} } -body { namespace eval x info vars foo } -cleanup { namespace delete x } -result {} | | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 | catch {namespace delete x} } -body { namespace eval x info vars foo } -cleanup { namespace delete x } -result {} set functions {abs acos asin atan atan2 bool ceil cos cosh double entier exp floor fmod hypot int isfinite isinf isnan isnormal isqrt issubnormal isunordered log log10 max min pow rand round sin sinh sqrt srand tan tanh wide} # Check whether the extra testing functions are defined... if {!([catch {expr T1()} msg] && ($msg eq {invalid command name "tcl::mathfunc::T1"}))} { set functions "T1 T2 T3 $functions" ;# A lazy way of prepending! } test info-20.1 {info functions option} {info functions sin} sin test info-20.2 {info functions option} {lsort [info functions]} $functions test info-20.3 {info functions option} { |
︙ | ︙ |
Changes to tests/mathop.test.
︙ | ︙ | |||
91 92 93 94 95 96 97 | set res2 [lindex $results $i+1] if {$res1 ne $res2} { return "$i:($res1 != $res2)" } } return [lindex $results 0] } | | | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | set res2 [lindex $results $i+1] if {$res1 ne $res2} { return "$i:($res1 != $res2)" } } return [lindex $results 0] } # start of tests namespace eval ::testmathop { namespace path ::tcl::mathop variable op ;# stop surprises! test mathop-1.1 {compiled +} { + } 0 |
︙ | ︙ | |||
1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 | lappend res [TestOp - 0 -9223372036854775808] ;# -2**63 lappend res [TestOp / -9223372036854775808 -1] lappend res [TestOp * 2147483648 2] lappend res [TestOp * 9223372036854775808 2] set res } [list 2147483648 9223372036854775808 9223372036854775808 4294967296 18446744073709551616] if 0 { # Compare ops to expr bytecodes namespace import ::tcl::mathop::* proc _X {a b c} { set x [+ $a [- $b $c]] set y [expr {$a + ($b - $c)}] set z [< $a $b $c] } set ::tcl_traceCompile 2 _X 3 4 5 set ::tcl_traceCompile 0 } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 | lappend res [TestOp - 0 -9223372036854775808] ;# -2**63 lappend res [TestOp / -9223372036854775808 -1] lappend res [TestOp * 2147483648 2] lappend res [TestOp * 9223372036854775808 2] set res } [list 2147483648 9223372036854775808 9223372036854775808 4294967296 18446744073709551616] test mathop-27.1 {lt operator} {::tcl::mathop::lt} 1 test mathop-27.2 {lt operator} {::tcl::mathop::lt a} 1 test mathop-27.3 {lt operator} {::tcl::mathop::lt a b} 1 test mathop-27.4 {lt operator} {::tcl::mathop::lt b a} 0 test mathop-27.5 {lt operator} {::tcl::mathop::lt a a} 0 test mathop-27.6 {lt operator} {::tcl::mathop::lt a b c} 1 test mathop-27.7 {lt operator} {::tcl::mathop::lt b a c} 0 test mathop-27.8 {lt operator} {::tcl::mathop::lt a c b} 0 test mathop-27.9 {lt operator} {::tcl::mathop::lt 012 0x0} 1 test mathop-28.1 {le operator} {::tcl::mathop::le} 1 test mathop-28.2 {le operator} {::tcl::mathop::le a} 1 test mathop-28.3 {le operator} {::tcl::mathop::le a b} 1 test mathop-28.4 {le operator} {::tcl::mathop::le b a} 0 test mathop-28.5 {le operator} {::tcl::mathop::le a a} 1 test mathop-28.6 {le operator} {::tcl::mathop::le a b c} 1 test mathop-28.7 {le operator} {::tcl::mathop::le b a c} 0 test mathop-28.8 {le operator} {::tcl::mathop::le a c b} 0 test mathop-28.9 {le operator} {::tcl::mathop::le 012 0x0} 1 test mathop-29.1 {gt operator} {::tcl::mathop::gt} 1 test mathop-29.2 {gt operator} {::tcl::mathop::gt a} 1 test mathop-29.3 {gt operator} {::tcl::mathop::gt a b} 0 test mathop-29.4 {gt operator} {::tcl::mathop::gt b a} 1 test mathop-29.5 {gt operator} {::tcl::mathop::gt a a} 0 test mathop-29.6 {gt operator} {::tcl::mathop::gt c b a} 1 test mathop-29.7 {gt operator} {::tcl::mathop::gt b a c} 0 test mathop-29.8 {gt operator} {::tcl::mathop::gt a c b} 0 test mathop-29.9 {gt operator} {::tcl::mathop::gt 0x0 012} 1 test mathop-30.1 {ge operator} {::tcl::mathop::ge} 1 test mathop-30.2 {ge operator} {::tcl::mathop::ge a} 1 test mathop-30.3 {ge operator} {::tcl::mathop::ge a b} 0 test mathop-30.4 {ge operator} {::tcl::mathop::ge b a} 1 test mathop-30.5 {ge operator} {::tcl::mathop::ge a a} 1 test mathop-30.6 {ge operator} {::tcl::mathop::ge c b a} 1 test mathop-30.7 {ge operator} {::tcl::mathop::ge b a c} 0 test mathop-30.8 {ge operator} {::tcl::mathop::ge a c b} 0 test mathop-30.9 {ge operator} {::tcl::mathop::ge 0x0 012} 1 if 0 { # Compare ops to expr bytecodes namespace import ::tcl::mathop::* proc _X {a b c} { set x [+ $a [- $b $c]] set y [expr {$a + ($b - $c)}] set z [< $a $b $c] } set ::tcl_traceCompile 2 _X 3 4 5 set ::tcl_traceCompile 0 } # cleanup namespace delete ::testmathop namespace delete ::testmathop2 ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: |
Changes to tests/namespace.test.
︙ | ︙ | |||
1805 1806 1807 1808 1809 1810 1811 | proc x2 {} {format 2} proc x3 {} {format 3} namespace ensemble create } list [ns x0 z] [ns x1] [ns x2] [ns x3] } -cleanup { namespace delete ns | | | 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 | proc x2 {} {format 2} proc x3 {} {format 3} namespace ensemble create } list [ns x0 z] [ns x1] [ns x2] [ns x3] } -cleanup { namespace delete ns } -result {{1 ::ns::x0::z} 1 2 3} test namespace-42.8 { ensembles: [Bug 1670091], panic due to pointer to a deallocated List struct. } -setup { proc demo args {} variable target [list [namespace which demo] x] proc trial args {variable target; string length $target} |
︙ | ︙ | |||
2136 2137 2138 2139 2140 2141 2142 | set result {} lappend result [catch {ns a b c} msg] $msg lappend result [catch {ns a b c} msg] $msg lappend result [catch {ns b c d} msg] $msg lappend result [catch {ns c d e} msg] $msg lappend result [catch {ns Magic foo bar spong wibble} msg] $msg list $result [lsort [info commands ::ns::*]] $log [namespace delete ns] | | | 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 | set result {} lappend result [catch {ns a b c} msg] $msg lappend result [catch {ns a b c} msg] $msg lappend result [catch {ns b c d} msg] $msg lappend result [catch {ns c d e} msg] $msg lappend result [catch {ns Magic foo bar spong wibble} msg] $msg list $result [lsort [info commands ::ns::*]] $log [namespace delete ns] } {{0 2 0 2 0 2 0 2 1 {unknown or protected subcommand "Magic"}} {::ns::Magic ::ns::a ::ns::b ::ns::c} {{making a} {running ::ns::a b c} {running ::ns::a b c} {making b} {running ::ns::b c d} {making c} {running ::ns::c d e} {unknown Magic - args = foo bar spong wibble}} {}} test namespace-47.2 {ensemble: unknown handler} { namespace eval ns { namespace export {[a-z]*} proc Magic {ensemble subcmd args} { error foobar } namespace ensemble create -unknown ::ns::Magic |
︙ | ︙ | |||
3235 3236 3237 3238 3239 3240 3241 | } -cleanup { namespace delete ns } -result\ {0 0\ 1 {wrong # args: should be "ns z1 x a1"}\ 1 {wrong # args: should be "ns z2 x a1 a2"}\ 1 {wrong # args: should be "ns z2 x a1 a2"}\ | | | 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 | } -cleanup { namespace delete ns } -result\ {0 0\ 1 {wrong # args: should be "ns z1 x a1"}\ 1 {wrong # args: should be "ns z2 x a1 a2"}\ 1 {wrong # args: should be "ns z2 x a1 a2"}\ 1 {wrong # args: should be "::ns::x::z0"}\ 0 {1 v}\ 1 {wrong # args: should be "ns v x z2 a2"}\ 0 {2 v v2}} test namespace-53.11 {ensembles: nested rewrite} -setup { namespace eval ns { namespace export x namespace eval x { |
︙ | ︙ | |||
3320 3321 3322 3323 3324 3325 3326 | return [lsort $gone] } finally { namespace delete ::testing } } } {::testing::abc::def ::testing::abc::ghi} | | > > > > > > > > > > > > > | 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 | return [lsort $gone] } finally { namespace delete ::testing } } } {::testing::abc::def ::testing::abc::ghi} test namespace-56.4 {bug 16fe1b5807: names starting with ":"} knownBug { namespace eval : { namespace ensemble create namespace export * proc p1 {} { return 16fe1b5807 } } : p1 } 16fe1b5807 test namespace-56.5 {Bug 8b9854c3d8} -setup { namespace eval namespace-56.5 { proc cmd {} {string match ::* [lindex [[string cat info] level 0] 0]} namespace export * namespace ensemble create } } -body { namespace-56.5 cmd } -cleanup { namespace delete namespace-56.5 } -result 1 # cleanup catch {rename cmd1 {}} catch {unset l} catch {unset msg} catch {unset trigger} namespace delete {*}[namespace children :: test_ns_*] ::tcltest::cleanupTests return # Local Variables: # mode: tcl # End: |