Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | merge 8.5 |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
27fd15ce57c5a1f6d10c897e54094ad2 |
User & Date: | dgp 2011-05-03 19:44:49 |
Context
2011-05-05
| ||
06:26 | no longer depend on MODULE_SCOPE being defined check-in: b439e1d71b user: jan.nijtmans tags: trunk | |
2011-05-03
| ||
19:44 | merge 8.5 check-in: 27fd15ce57 user: dgp tags: trunk | |
19:07 | Tighten Tcl_SplitList(). check-in: eeab23b73b user: dgp tags: core-8-5-branch | |
2011-05-02
| ||
21:12 | Rewrite of parts of the switch compiler to better use the powers of TclFindElement() and do less par... check-in: 30dad692de user: dgp tags: trunk | |
Changes
Changes to ChangeLog.
1 2 3 4 5 6 7 | 2011-05-02 Don Porter <[email protected]> * generic/tclCmdMZ.c: Revised TclFindElement() interface. The * generic/tclDictObj.c: final argument had been bracePtr, the address * generic/tclListObj.c: of a boolean var, where the caller can be told * generic/tclParse.c: whether or not the parsed list element was * generic/tclUtil.c: enclosed in braces. In practice, no callers | > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 2011-05-03 Don Porter <[email protected]> * generic/tclUtil.c: Tighten Tcl_SplitList(). * generic/tclListObj.c: Tighten SetListFromAny(). * generic/tclDictObj.c: Tighten SetDictFromAny(). * tests/join.test: * tests/mathop.test: 2011-05-02 Don Porter <[email protected]> * generic/tclCmdMZ.c: Revised TclFindElement() interface. The * generic/tclDictObj.c: final argument had been bracePtr, the address * generic/tclListObj.c: of a boolean var, where the caller can be told * generic/tclParse.c: whether or not the parsed list element was * generic/tclUtil.c: enclosed in braces. In practice, no callers |
︙ | ︙ |
Changes to generic/tclDictObj.c.
︙ | ︙ | |||
560 561 562 563 564 565 566 | */ static int SetDictFromAny( Tcl_Interp *interp, Tcl_Obj *objPtr) { | < | < | < < < | | > > | < < < | < < | < | | < < < | < < < < | < < | < < < | < < < < < < < | | < < > | < | < < < < < | | | | < < < | | | | | > > | < < < < < | | < | < < | | | | | < < < < | | | | < < < | < < < | | < < < < < < | | < | < < | | | > | | | | < < | | | | | | | | | | | | < > > > | 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 605 606 607 608 609 610 611 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 | */ static int SetDictFromAny( Tcl_Interp *interp, Tcl_Obj *objPtr) { Tcl_HashEntry *hPtr; int isNew, result; Dict *dict = ckalloc(sizeof(Dict)); InitChainTable(dict); /* * Since lists and dictionaries have very closely-related string * representations (i.e. the same parsing code) we can safely special-case * the conversion from lists to dictionaries. */ if (objPtr->typePtr == &tclListType) { int objc, i; Tcl_Obj **objv; /* Cannot fail, we already know the Tcl_ObjType is "list". */ TclListObjGetElements(NULL, objPtr, &objc, &objv); if (objc & 1) { goto missingValue; } for (i=0 ; i<objc ; i+=2) { /* Store key and value in the hash table we're building. */ hPtr = CreateChainEntry(dict, objv[i], &isNew); if (!isNew) { Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr); /* * Not really a well-formed dictionary as there are duplicate * keys, so better get the string rep here so that we can * convert back. */ (void) Tcl_GetString(objPtr); TclDecrRefCount(discardedValue); } Tcl_SetHashValue(hPtr, objv[i+1]); Tcl_IncrRefCount(objv[i+1]); /* Since hash now holds ref to it */ } } else { int length; const char *nextElem = TclGetStringFromObj(objPtr, &length); const char *limit = (nextElem + length); while (nextElem < limit) { Tcl_Obj *keyPtr, *valuePtr; const char *elemStart; int elemSize, literal; result = TclFindElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal); if (result != TCL_OK) { goto errorExit; } if (elemStart == limit) { break; } if (nextElem == limit) { goto missingValue; } if (literal) { TclNewStringObj(keyPtr, elemStart, elemSize); } else { /* Avoid double copy */ TclNewObj(keyPtr); keyPtr->bytes = ckalloc((unsigned) elemSize + 1); keyPtr->length = TclCopyAndCollapse(elemSize, elemStart, keyPtr->bytes); } result = TclFindElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal); if (result != TCL_OK) { TclDecrRefCount(keyPtr); goto errorExit; } if (literal) { TclNewStringObj(valuePtr, elemStart, elemSize); } else { /* Avoid double copy */ TclNewObj(valuePtr); valuePtr->bytes = ckalloc((unsigned) elemSize + 1); valuePtr->length = TclCopyAndCollapse(elemSize, elemStart, valuePtr->bytes); } /* Store key and value in the hash table we're building. */ hPtr = CreateChainEntry(dict, keyPtr, &isNew); if (!isNew) { Tcl_Obj *discardedValue = Tcl_GetHashValue(hPtr); TclDecrRefCount(keyPtr); TclDecrRefCount(discardedValue); } Tcl_SetHashValue(hPtr, valuePtr); Tcl_IncrRefCount(valuePtr); /* since hash now holds ref to it */ } } /* * Free the old internalRep before setting the new one. We do this as late * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ TclFreeIntRep(objPtr); dict->epoch = 0; dict->chain = NULL; dict->refcount = 1; objPtr->internalRep.otherValuePtr = dict; objPtr->typePtr = &tclDictType; return TCL_OK; missingValue: if (interp != NULL) { Tcl_SetResult(interp, "missing value to go with key", TCL_STATIC); Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); } result = TCL_ERROR; errorExit: if (interp != NULL) { Tcl_SetErrorCode(interp, "TCL", "VALUE", "DICTIONARY", NULL); } DeleteChainTable(dict); ckfree(dict); return result; } /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to generic/tclListObj.c.
︙ | ︙ | |||
1710 1711 1712 1713 1714 1715 1716 | */ static int SetListFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { | < < < < < < < < > | 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 | */ static int SetListFromAny( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ Tcl_Obj *objPtr) /* The object to convert. */ { List *listRepPtr; Tcl_Obj **elemPtrs; /* * Dictionaries are a special case; they have a string representation such * that *all* valid dictionaries are valid lists. Hence we can convert * more directly. Only do this when there's no existing string rep; if * there is, it is the string rep that's authoritative (because it could * describe duplicate keys). |
︙ | ︙ | |||
1755 1756 1757 1758 1759 1760 1761 | /* * Populate the list representation. */ elemPtrs = &listRepPtr->elements; Tcl_DictObjFirst(NULL, objPtr, &search, &keyPtr, &valuePtr, &done); | < | | | < < < | < < < < < < < | | < < < | | | | | | | | | | | < < | > | | | < < | | | | < < < | | | | | < < | | < < < < < < | | < | > > | > | < < < < | | | > < | 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 | /* * Populate the list representation. */ elemPtrs = &listRepPtr->elements; Tcl_DictObjFirst(NULL, objPtr, &search, &keyPtr, &valuePtr, &done); while (!done) { *elemPtrs++ = keyPtr; *elemPtrs++ = valuePtr; Tcl_IncrRefCount(keyPtr); Tcl_IncrRefCount(valuePtr); Tcl_DictObjNext(&search, &keyPtr, &valuePtr, &done); } } else { int estCount, length; const char *limit, *nextElem = TclGetStringFromObj(objPtr, &length); /* * Allocate enough space to hold a (Tcl_Obj *) for each * (possible) list element. */ estCount = TclMaxListLength(nextElem, length, &limit); estCount += (estCount == 0); /* Smallest List struct holds 1 element. */ listRepPtr = AttemptNewList(interp, estCount, NULL); if (listRepPtr == NULL) { return TCL_ERROR; } elemPtrs = &listRepPtr->elements; /* Each iteration, parse and store a list element */ while (nextElem < limit) { const char *elemStart; int elemSize, literal; if (TCL_OK != TclFindElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal)) { while (--elemPtrs >= &listRepPtr->elements) { Tcl_DecrRefCount(*elemPtrs); } ckfree((char *) listRepPtr); return TCL_ERROR; } if (elemStart == limit) { break; } /* TODO: replace panic with error on alloc failure? */ if (literal) { TclNewStringObj(*elemPtrs, elemStart, elemSize); } else { TclNewObj(*elemPtrs); (*elemPtrs)->bytes = ckalloc((unsigned) elemSize + 1); (*elemPtrs)->length = TclCopyAndCollapse(elemSize, elemStart, (*elemPtrs)->bytes); } Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */ } listRepPtr->elemCount = elemPtrs - &listRepPtr->elements; } /* * Free the old internalRep before setting the new one. We do this as late * as possible to allow the conversion code, in particular * Tcl_GetStringFromObj, to use that old internalRep. */ TclFreeIntRep(objPtr); ListSetIntRep(objPtr, listRepPtr); return TCL_OK; } /* *---------------------------------------------------------------------- |
︙ | ︙ |
Changes to generic/tclUtil.c.
︙ | ︙ | |||
175 176 177 178 179 180 181 | * that's part of the element. If this is the last argument in the list, * then *nextPtr will point just after the last character in the list * (i.e., at the character at list+listLength). If sizePtr is non-NULL, * *sizePtr is filled in with the number of characters in the element. If * the element is in braces, then *elementPtr will point to the character * after the opening brace and *sizePtr will not include either of the * braces. If there isn't an element in the list, *sizePtr will be zero, | | | 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | * that's part of the element. If this is the last argument in the list, * then *nextPtr will point just after the last character in the list * (i.e., at the character at list+listLength). If sizePtr is non-NULL, * *sizePtr is filled in with the number of characters in the element. If * the element is in braces, then *elementPtr will point to the character * after the opening brace and *sizePtr will not include either of the * braces. If there isn't an element in the list, *sizePtr will be zero, * and both *elementPtr and *nextPtr will point just after the last * character in the list. If literalPtr is non-NULL, *literalPtr is set * to a boolean value indicating whether the substring returned as * the values of **elementPtr and *sizePtr is the literal value of * a list element. If not, a call to TclCopyAndCollapse() is needed * to produce the actual value of the list element. Note: this function * does NOT collapse backslash sequences, but uses *literalPtr to tell * callers when it is required for them to do so. |
︙ | ︙ | |||
546 547 548 549 550 551 552 | argv[i] = p; if (literal) { memcpy(p, element, (size_t) elSize); p += elSize; *p = 0; p++; } else { | | < | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | argv[i] = p; if (literal) { memcpy(p, element, (size_t) elSize); p += elSize; *p = 0; p++; } else { p += 1 + TclCopyAndCollapse(elSize, element, p); } } argv[i] = NULL; *argvPtr = argv; *argcPtr = i; return TCL_OK; |
︙ | ︙ |
Changes to tests/join.test.
︙ | ︙ | |||
33 34 35 36 37 38 39 | list [catch join msg] $msg $errorCode } {1 {wrong # args: should be "join list ?joinString?"} {TCL WRONGARGS}} test join-2.2 {join errors} { list [catch {join a b c} msg] $msg $errorCode } {1 {wrong # args: should be "join list ?joinString?"} {TCL WRONGARGS}} test join-2.3 {join errors} { list [catch {join "a \{ c" 111} msg] $msg $errorCode | | | 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | list [catch join msg] $msg $errorCode } {1 {wrong # args: should be "join list ?joinString?"} {TCL WRONGARGS}} test join-2.2 {join errors} { list [catch {join a b c} msg] $msg $errorCode } {1 {wrong # args: should be "join list ?joinString?"} {TCL WRONGARGS}} test join-2.3 {join errors} { list [catch {join "a \{ c" 111} msg] $msg $errorCode } {1 {unmatched open brace in list} {TCL VALUE LIST BRACE}} test join-3.1 {joinString is binary ok} { string length [join {a b c} a\0b] } 9 test join-3.2 {join is binary ok} { string length [join "a\0b a\0b a\0b"] } 11 |
︙ | ︙ |
Changes to tests/mathop.test.
︙ | ︙ | |||
1088 1089 1090 1091 1092 1093 1094 | lappend res [TestOp $op 5.0 1] lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}" lappend res [TestOp $op 1 5.0] lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}" } foreach op {in ni} { lappend res [TestOp $op 5 "a b \{ c"] | | | 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 | lappend res [TestOp $op 5.0 1] lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}" lappend res [TestOp $op 1 5.0] lappend exp "can't use floating-point value as operand of \"$op\" ARITH DOMAIN {floating-point value}" } foreach op {in ni} { lappend res [TestOp $op 5 "a b \{ c"] lappend exp "unmatched open brace in list TCL VALUE LIST BRACE" } lappend res [TestOp % 5 0] lappend exp "divide by zero ARITH DIVZERO {divide by zero}" lappend res [TestOp % 9838923468297346238478737647637375 0] lappend exp "divide by zero ARITH DIVZERO {divide by zero}" lappend res [TestOp / 5 0] lappend exp "divide by zero ARITH DIVZERO {divide by zero}" |
︙ | ︙ |