Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tip-502 Excluding Merge-Ins
This is equivalent to a diff from 2f164e9d41 to bcc54d1577
2018-10-12
| ||
18:14 | TIP #502 implementation: Index value reform. check-in: bae05b9e6f user: jan.nijtmans tags: core-8-branch | |
2018-09-29
| ||
08:51 | More readability improvements to unix makefile check-in: 3a0455ee94 user: dkf tags: core-8-branch | |
2018-09-28
| ||
19:59 | \Merge 8.7 Closed-Leaf check-in: bcc54d1577 user: jan.nijtmans tags: tip-502 | |
19:58 | Merge 8.7 Closed-Leaf check-in: b4a19593fb user: jan.nijtmans tags: tip-514 | |
18:57 | Merge 8.7 check-in: d812be8851 user: jan.nijtmans tags: trunk | |
18:49 | Merge 8.6 check-in: 2f164e9d41 user: jan.nijtmans tags: core-8-branch | |
18:45 | Another patch contributed by Gustaf Neumann: shifting negative numbers is undefined behavior in the ... check-in: 165586b224 user: jan.nijtmans tags: core-8-6-branch | |
18:21 | nmake build fixes for zipfs (ongoing, zip attachments not done yet) check-in: eedd24aae1 user: jan.nijtmans tags: core-8-branch | |
2018-09-27
| ||
21:46 | Merge 8.7 check-in: bf6b97a33d user: jan.nijtmans tags: tip-502 | |
Changes to generic/tclCmdMZ.c.
︙ | ︙ | |||
254 255 256 257 258 259 260 | * regexp to avoid shimmering problems. */ objPtr = objv[1]; stringLength = Tcl_GetCharLength(objPtr); if (startIndex) { | | | 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 | * regexp to avoid shimmering problems. */ objPtr = objv[1]; stringLength = Tcl_GetCharLength(objPtr); if (startIndex) { TclGetIntForIndexM(interp, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); if (offset < 0) { offset = 0; } } regExpr = Tcl_GetRegExpFromObj(interp, objv[0], cflags); |
︙ | ︙ | |||
578 579 580 581 582 583 584 | objc -= idx; objv += idx; if (startIndex) { int stringLength = Tcl_GetCharLength(objv[1]); | | | 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | objc -= idx; objv += idx; if (startIndex) { int stringLength = Tcl_GetCharLength(objv[1]); TclGetIntForIndexM(interp, startIndex, stringLength, &offset); Tcl_DecrRefCount(startIndex); if (offset < 0) { offset = 0; } } if (all && (offset == 0) && (command == 0) |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
4757 4758 4759 4760 4761 4762 4763 | /* * Extract the desired list element. */ if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK) && (value2Ptr->typePtr != &tclListType) | | | 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 | /* * Extract the desired list element. */ if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK) && (value2Ptr->typePtr != &tclListType) && (TclGetIntForIndexM(NULL, value2Ptr, objc-1, &index) == TCL_OK)) { TclDecrRefCount(value2Ptr); tosPtr--; pcAdjustment = 1; goto lindexFastPath; } |
︙ | ︙ |
Changes to generic/tclUtil.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclParse.h" #include "tclStringTrim.h" #include <math.h> /* * The absolute pathname of the executable in which this Tcl library is * running. */ | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #include "tclInt.h" #include "tclParse.h" #include "tclStringTrim.h" #include "tommath.h" #include <math.h> /* * The absolute pathname of the executable in which this Tcl library is * running. */ |
︙ | ︙ | |||
103 104 105 106 107 108 109 | /* * Prototypes for functions defined later in this file. */ static void ClearHash(Tcl_HashTable *tablePtr); static void FreeProcessGlobalValue(ClientData clientData); static void FreeThreadHash(ClientData clientData); | | | > > | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | /* * Prototypes for functions defined later in this file. */ static void ClearHash(Tcl_HashTable *tablePtr); static void FreeProcessGlobalValue(ClientData clientData); static void FreeThreadHash(ClientData clientData); static int GetEndOffsetFromObj(Tcl_Obj *objPtr, Tcl_WideInt endValue, Tcl_WideInt *indexPtr); static Tcl_HashTable * GetThreadHash(Tcl_ThreadDataKey *keyPtr); static int GetWideForIndex(Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideInt endValue, Tcl_WideInt *widePtr); static int SetEndOffsetFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int FindElement(Tcl_Interp *interp, const char *string, int stringLength, const char *typeStr, const char *typeCode, const char **elementPtr, const char **nextPtr, int *sizePtr, int *literalPtr); |
︙ | ︙ | |||
3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 | } return numFormatted; } /* *---------------------------------------------------------------------- * * TclGetIntForIndex -- * * This function returns an integer corresponding to the list index held * in a Tcl object. The Tcl object's value is expected to be in the * format integer([+-]integer)? or the format end([+-]integer)?. * * Results: | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 | } return numFormatted; } /* *---------------------------------------------------------------------- * * GetWideForIndex -- * * This function produces a wide integer value corresponding to the * list index held in *objPtr. The parsing supports all values * recognized as any size of integer, and the syntaxes end[-+]$integer * and $integer[-+]$integer. The argument endValue is used to give * the meaning of the literal index value "end". * * Results: * When parsing of *objPtr successfully recognizes an index value, * TCL_OK is returned, and the wide integer value corresponding to * the recognized index value is written to *widePtr. When parsing * fails, TCL_ERROR is returned and error information is written to * interp, if non-NULL. * * Side effects: * The type of *objPtr may change. * *---------------------------------------------------------------------- */ static int GetWideForIndex( Tcl_Interp *interp, /* Interpreter to use for error reporting. If * NULL, then no error message is left after * errors. */ Tcl_Obj *objPtr, /* Points to the value to be parsed */ Tcl_WideInt endValue, /* The value to be stored at *widePtr if * objPtr holds "end". * NOTE: this value may be negative. */ Tcl_WideInt *widePtr) /* Location filled in with a wide integer * representing an index. */ { ClientData cd; const char *opPtr; int numType, length, t1 = 0, t2 = 0; int code = TclGetNumberFromObj(NULL, objPtr, &cd, &numType); if (code == TCL_OK) { if (numType == TCL_NUMBER_WIDE) { /* objPtr holds an integer in the signed wide range */ *widePtr = (Tcl_WideInt)(*(Tcl_WideInt *)cd); return TCL_OK; } if (numType == TCL_NUMBER_BIG) { /* objPtr holds an integer outside the signed wide range */ /* Truncate to the signed wide range. */ if (mp_isneg((mp_int *)cd)) { *widePtr = LLONG_MIN; } else { *widePtr = LLONG_MAX; } return TCL_OK; } /* Must be a double -> not a valid index */ goto parseError; } /* objPtr does not hold a number, check the end+/- format... */ if (GetEndOffsetFromObj(objPtr, endValue, widePtr) == TCL_OK) { return TCL_OK; } /* If we reach here, the string rep of objPtr exists. */ /* * The valid index syntax does not include any value that is * a list of more than one element. This is necessary so that * lists of index values can be reliably distinguished from any * single index value. */ /* * Quick scan to see if multi-value list is even possible. * This relies on TclGetString() returning a NUL-terminated string. */ if ((TclMaxListLength(TclGetString(objPtr), -1, NULL) > 1) /* If it's possible, do the full list parse. */ && (TCL_OK == Tcl_ListObjLength(NULL, objPtr, &length)) && (length > 1)) { goto parseError; } /* Passed the list screen, so parse for index arithmetic expression */ if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, NULL, -1, &opPtr, TCL_PARSE_INTEGER_ONLY)) { Tcl_WideInt w1=0, w2=0; /* value starts with valid integer... */ if ((*opPtr == '-') || (*opPtr == '+')) { /* ... value continues with [-+] ... */ /* Save first integer as wide if possible */ TclGetNumberFromObj(NULL, objPtr, &cd, &t1); if (t1 == TCL_NUMBER_WIDE) { w1 = (*(Tcl_WideInt *)cd); } if (TCL_OK == TclParseNumber(NULL, objPtr, NULL, opPtr + 1, -1, NULL, TCL_PARSE_INTEGER_ONLY)) { /* ... value concludes with second valid integer */ /* Save second integer as wide if possible */ TclGetNumberFromObj(NULL, objPtr, &cd, &t2); if (t2 == TCL_NUMBER_WIDE) { w2 = (*(Tcl_WideInt *)cd); } } } /* Clear invalid intreps left by TclParseNumber */ TclFreeIntRep(objPtr); if (t1 && t2) { /* We have both integer values */ if ((t1 == TCL_NUMBER_WIDE) && (t2 == TCL_NUMBER_WIDE)) { /* Both are wide, do wide-integer math */ if (*opPtr == '-') { if ((w2 == LLONG_MIN) && (interp != NULL)) { goto extreme; } w2 = -w2; } if ((w1 ^ w2) < 0) { /* Different signs, sum cannot overflow */ *widePtr = w1 + w2; } else if (w1 >= 0) { if (w1 < LLONG_MAX - w2) { *widePtr = w1 + w2; } else { *widePtr = LLONG_MAX; } } else { if (w1 > LLONG_MIN - w2) { *widePtr = w1 + w2; } else { *widePtr = LLONG_MIN; } } } else if (interp == NULL) { /* * We use an interp to do bignum index calculations. * If we don't get one, call all indices with bignums errors, * and rely on callers to handle it. */ return TCL_ERROR; } else { /* * At least one is big, do bignum math. Little reason to * value performance here. Re-use code. Parse has verified * objPtr is an expresion. Compute it. */ Tcl_Obj *sum; extreme: Tcl_ExprObj(interp, objPtr, &sum); TclGetNumberFromObj(NULL, sum, &cd, &numType); if (numType == TCL_NUMBER_WIDE) { /* sum holds an integer in the signed wide range */ *widePtr = (Tcl_WideInt)(*(Tcl_WideInt *)cd); } else { /* sum holds an integer outside the signed wide range */ /* Truncate to the signed wide range. */ if (mp_isneg((mp_int *)cd)) { *widePtr = LLONG_MIN; } else { *widePtr = LLONG_MAX; } } Tcl_DecrRefCount(sum); } return TCL_OK; } } /* Report a parse error. */ parseError: if (interp != NULL) { char * bytes = TclGetString(objPtr); Tcl_SetObjResult(interp, Tcl_ObjPrintf( "bad index \"%s\": must be integer?[+-]integer? or" " end?[+-]integer?", bytes)); if (!strncmp(bytes, "end-", 4)) { bytes += 4; } TclCheckBadOctal(interp, bytes); Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", NULL); } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * TclGetIntForIndex -- * * This function returns an integer corresponding to the list index held * in a Tcl object. The Tcl object's value is expected to be in the * format integer([+-]integer)? or the format end([+-]integer)?. * * Results: |
︙ | ︙ | |||
3683 3684 3685 3686 3687 3688 3689 | Tcl_Obj *objPtr, /* Points to an object containing either "end" * or an integer. */ int endValue, /* The value to be stored at "indexPtr" if * "objPtr" holds "end". */ int *indexPtr) /* Location filled in with an integer * representing an index. */ { | < < < | < < | | < | | < < | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | < < < < < < < < < < < < < < < < < < < < | 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 | Tcl_Obj *objPtr, /* Points to an object containing either "end" * or an integer. */ int endValue, /* The value to be stored at "indexPtr" if * "objPtr" holds "end". */ int *indexPtr) /* Location filled in with an integer * representing an index. */ { Tcl_WideInt wide; if (GetWideForIndex(interp, objPtr, endValue, &wide) == TCL_ERROR) { return TCL_ERROR; } if (wide < INT_MIN) { *indexPtr = INT_MIN; } else if (wide > INT_MAX) { *indexPtr = INT_MAX; } else { *indexPtr = (int) wide; } return TCL_OK; } /* *---------------------------------------------------------------------- * * GetEndOffsetFromObj -- * |
︙ | ︙ | |||
3775 3776 3777 3778 3779 3780 3781 | * *---------------------------------------------------------------------- */ static int GetEndOffsetFromObj( Tcl_Obj *objPtr, /* Pointer to the object to parse */ | | | | | | > > > > > > > > | < > > | > > > > | | > | | 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 | * *---------------------------------------------------------------------- */ static int GetEndOffsetFromObj( Tcl_Obj *objPtr, /* Pointer to the object to parse */ Tcl_WideInt endValue, /* The value to be stored at "indexPtr" if * "objPtr" holds "end". */ Tcl_WideInt *widePtr) /* Location filled in with an integer * representing an index. */ { if (SetEndOffsetFromAny(NULL, objPtr) == TCL_OK) { Tcl_WideInt offset = objPtr->internalRep.wideValue; if ((endValue ^ offset) < 0) { /* Different signs, sum cannot overflow */ *widePtr = endValue + offset; } else if (endValue >= 0) { if (endValue < LLONG_MAX - offset) { *widePtr = endValue + offset; } else { *widePtr = LLONG_MAX; } } else { if (endValue > LLONG_MIN - offset) { *widePtr = endValue + offset; } else { *widePtr = LLONG_MIN; } } return TCL_OK; } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * SetEndOffsetFromAny -- * * Look for a string of the form "end[+-]offset" and convert it to an |
︙ | ︙ | |||
3957 3958 3959 3960 3961 3962 3963 | TclIndexEncode( Tcl_Interp *interp, /* For error reporting, may be NULL */ Tcl_Obj *objPtr, /* Index value to parse */ int before, /* Value to return for index before beginning */ int after, /* Value to return for index after end */ int *indexPtr) /* Where to write the encoded answer, not NULL */ { | > | > | | > | | > > | | | | | | | | | 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 | TclIndexEncode( Tcl_Interp *interp, /* For error reporting, may be NULL */ Tcl_Obj *objPtr, /* Index value to parse */ int before, /* Value to return for index before beginning */ int after, /* Value to return for index after end */ int *indexPtr) /* Where to write the encoded answer, not NULL */ { ClientData cd; Tcl_WideInt wide; int idx, numType, code = TclGetNumberFromObj(NULL, objPtr, &cd, &numType); if ((code == TCL_OK) && (numType == TCL_NUMBER_WIDE)) { /* We parsed a value in the range LLONG_MIN...LLONG_MAX */ wide = (*(Tcl_WideInt *)cd); integerEncode: if (wide < TCL_INDEX_START) { /* All negative absolute indices are "before the beginning" */ idx = before; } else if (wide >= INT_MAX) { /* This index value is always "after the end" */ idx = after; } else { idx = (int) wide; } /* usual case, the absolute index value encodes itself */ } else if (TCL_OK == GetEndOffsetFromObj(objPtr, 0, &wide)) { /* * We parsed an end+offset index value. * wide holds the offset value in the range LLONG_MIN...LLONG_MAX. */ if (wide > 0) { /* * All end+postive or end-negative expressions * always indicate "after the end". */ idx = after; } else if (wide < INT_MIN - TCL_INDEX_END) { /* These indices always indicate "before the beginning */ idx = before; } else { /* Encoded end-positive (or end+negative) are offset */ idx = (int)wide + TCL_INDEX_END; } /* TODO: Consider flag to suppress repeated end-offset parse. */ } else if (TCL_OK == GetWideForIndex(interp, objPtr, 0, &wide)) { /* * Only reach this case when the index value is a * constant index arithmetic expression, and wide * holds the result. Treat it the same as if it were * parsed as an absolute integer value. */ goto integerEncode; } else { return TCL_ERROR; } |
︙ | ︙ |
Changes to tests/util.test.
︙ | ︙ | |||
685 686 687 688 689 690 691 | string index a 0x } -returnCodes error -match glob -result * test util-9.31.1 {TclGetIntForIndex} -body { string index a 0d } -returnCodes error -match glob -result * test util-9.32 {TclGetIntForIndex} -body { string index a 0x1FFFFFFFF+0 | | | | | 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | string index a 0x } -returnCodes error -match glob -result * test util-9.31.1 {TclGetIntForIndex} -body { string index a 0d } -returnCodes error -match glob -result * test util-9.32 {TclGetIntForIndex} -body { string index a 0x1FFFFFFFF+0 } -result {} test util-9.33 {TclGetIntForIndex} -body { string index a 100000000000+0 } -result {} test util-9.33.1 {TclGetIntForIndex} -body { string index a 0d100000000000+0 } -result {} test util-9.34 {TclGetIntForIndex} -body { string index a 1.0 } -returnCodes error -match glob -result * test util-9.35 {TclGetIntForIndex} -body { string index a 1e23 } -returnCodes error -match glob -result * test util-9.36 {TclGetIntForIndex} -body { |
︙ | ︙ | |||
724 725 726 727 728 729 730 | string index a 0+1e2 } -returnCodes error -match glob -result * test util-9.43 {TclGetIntForIndex} -body { string index a 0+1.5e1 } -returnCodes error -match glob -result * test util-9.44 {TclGetIntForIndex} -body { string index a 0+1000000000000 | | > > > > > > | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 | string index a 0+1e2 } -returnCodes error -match glob -result * test util-9.43 {TclGetIntForIndex} -body { string index a 0+1.5e1 } -returnCodes error -match glob -result * test util-9.44 {TclGetIntForIndex} -body { string index a 0+1000000000000 } -result {} test util-9.45 {TclGetIntForIndex} { string index abcd end+2305843009213693950 } {} test util-9.46 {TclGetIntForIndex} { string index abcd end+4294967294 } {} test util-10.1 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} { convertDouble 0x0000000000000000 } {0.0} test util-10.2 {Tcl_PrintDouble - rounding} {ieeeFloatingPoint} { convertDouble 0x8000000000000000 } {-0.0} |
︙ | ︙ |