Tcl Source Code

Check-in [c6361c69eb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge to feature branch
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-388-impl
Files: files | file ages | folders
SHA1: c6361c69eb9554ee9470737d1e3ae493d8a056b3
User & Date: jan.nijtmans 2011-08-23 07:24:27
Context
2011-08-24
07:47
Merge to feature branch check-in: 66fc824c99 user: jan.nijtmans tags: tip-388-impl
2011-08-23
07:24
Merge to feature branch check-in: c6361c69eb user: jan.nijtmans tags: tip-388-impl
07:22
gcc 4.6 (64-bit) warnings check-in: 9d43ce6fe2 user: jan.nijtmans tags: trunk
2011-08-22
10:18
Merge to feature branch check-in: 094a3c09ef user: jan.nijtmans tags: tip-388-impl
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.





1
2
3
4
5
6
7




2011-08-19  Don Porter  <[email protected]>

	* generic/tclIORTrans.c: [Bugs 3393279, 3393280] ReflectClose(.) is
	missing Tcl_EventuallyFree() calls at some of its exits.

	* generic/tclIO.c: [Bugs 3394654, 3393276] Revise FlushChannel() to
	account for the possibility that the ChanWrite() call might recycle
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
2011-08-23  Jan Nijtmans  <[email protected]>

	* generic/tclStringObj.c: [FRQ 3396731] inline string reverse

2011-08-19  Don Porter  <[email protected]>

	* generic/tclIORTrans.c: [Bugs 3393279, 3393280] ReflectClose(.) is
	missing Tcl_EventuallyFree() calls at some of its exits.

	* generic/tclIO.c: [Bugs 3394654, 3393276] Revise FlushChannel() to
	account for the possibility that the ChanWrite() call might recycle

Changes to generic/tclStringObj.c.

2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663

2664
2665
2666
2667
2668
2669
2670



2671
2672
2673
2674


2675
2676

2677
2678


2679
2680

2681
2682
2683
2684
2685
2686

2687





2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704



2705

2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716

2717
2718
2719
2720
2721
2722
2723

2724
2725
2726
2727
2728



2729


2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742

2743

2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringObjReverse(
    Tcl_Obj *objPtr)
{
    String *stringPtr;
    char *src = NULL, *dest = NULL;
    Tcl_UniChar *usrc = NULL, *udest = NULL;
    Tcl_Obj *resultPtr = NULL;


    SetStringFromAny(NULL, objPtr);
    stringPtr = GET_STRING(objPtr);

    if (stringPtr->hasUnicode == 0) {
	if (stringPtr->numChars == -1) {
	    TclNumUtfChars(stringPtr->numChars, objPtr->bytes, objPtr->length);



	}
	if (stringPtr->numChars <= 1) {
	    return objPtr;
	}


	if (stringPtr->numChars == objPtr->length) {
	    /*

	     * All one-byte chars. Reverse in objPtr->bytes.
	     */



	    if (Tcl_IsShared(objPtr)) {

		resultPtr = Tcl_NewObj();
		Tcl_SetObjLength(resultPtr, objPtr->length);
		dest = TclGetString(resultPtr);
		src = objPtr->bytes + objPtr->length - 1;
		while (src >= objPtr->bytes) {
		    *dest++ = *src--;

		}





		return resultPtr;
	    }

	    /*
	     * Unshared. Reverse objPtr->bytes in place.
	     */

	    dest = objPtr->bytes;
	    src = dest + objPtr->length - 1;
	    while (dest < src) {
		char tmp = *src;

		*src-- = *dest;
		*dest++ = tmp;
	    }
	    return objPtr;
	}



	FillUnicodeRep(objPtr);

	stringPtr = GET_STRING(objPtr);
    }
    if (stringPtr->numChars <= 1) {
	return objPtr;
    }

    /*
     * Reverse the Unicode rep.
     */

    if (Tcl_IsShared(objPtr)) {

	Tcl_UniChar ch = 0;

	/*
	 * Create a non-empty, pure unicode value, so we can coax
	 * Tcl_SetObjLength into growing the unicode rep buffer.
	 */


	resultPtr = Tcl_NewUnicodeObj(&ch, 1);
	Tcl_SetObjLength(resultPtr, stringPtr->numChars);
	udest = Tcl_GetUnicode(resultPtr);
	usrc = stringPtr->unicode + stringPtr->numChars - 1;
	while (usrc >= stringPtr->unicode) {



	    *udest++ = *usrc--;


	}
	return resultPtr;
    }

    /*
     * Unshared. Reverse objPtr->bytes in place.
     */

    udest = stringPtr->unicode;
    usrc = udest + stringPtr->numChars - 1;
    while (udest < usrc) {
	Tcl_UniChar tmp = *usrc;


	*usrc-- = *udest;

	*udest++ = tmp;
    }

    TclInvalidateStringRep(objPtr);
    stringPtr->allocated = 0;
    return objPtr;
}

/*
 *---------------------------------------------------------------------------
 *
 * FillUnicodeRep --
 *







<
|
<
|
>

|
|
|
|
|
|
>
>
>
|
|
|
|
>
>
|
<
>
|
<
>
>
|
<
>
|
<
|
|
<
|
>
|
>
>
>
>
>
|

|
<
<
<
|
|
|
|
|
|
|
|
<
|
|
>
>
>
|
>
|
<
|
<
<
|
<
|
<
|
<
>
|
|
<
|
<
<
|
>
|
|
|
|
|
>
>
>
|
>
>
|
<
|
|
<
<
<

|
<
|
<

>
|
>
|
|
<
<
<
|







2653
2654
2655
2656
2657
2658
2659

2660

2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679

2680
2681

2682
2683
2684

2685
2686

2687
2688

2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699



2700
2701
2702
2703
2704
2705
2706
2707

2708
2709
2710
2711
2712
2713
2714
2715

2716


2717

2718

2719

2720
2721
2722

2723


2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737

2738
2739



2740
2741

2742

2743
2744
2745
2746
2747
2748



2749
2750
2751
2752
2753
2754
2755
2756
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclStringObjReverse(
    Tcl_Obj *objPtr)
{

    char *src, *dest;

    Tcl_Obj *resultPtr = objPtr;
    char c;

    src = TclGetString(objPtr);
    if (Tcl_IsShared(objPtr)) {
	resultPtr = Tcl_NewObj();
	Tcl_SetObjLength(resultPtr, objPtr->length);
	dest = TclGetString(resultPtr);
	memcpy(dest, src, objPtr->length);
    } else {
	TclFreeIntRep(objPtr);
	dest = src;
    }

    src = dest + objPtr->length;

    /* Pass 1: reverse individual bytes of UTF-8 representation. */
    while (dest < src) {
	Tcl_UniChar ch = 0;

	switch (Tcl_UtfToUniChar(dest, &ch)) {
	case 1: {

		++dest;
		break;
	    }

	case 2: {
		c = dest[0];

		dest[0] = dest[1];
		dest[1] = c;

		dest += 2;
		break;
	    }
	case 3: {
		c = dest[0];
		dest[0] = dest[2];
		dest[2] = c;
		dest += 3;
		break;
	    }
#if TCL_UTF_MAX > 4



	case 5: {
		c = dest[0];
		dest[0] = dest[4];
		dest[4] = c;
		c = dest[1];
		dest[1] = dest[3];
		dest[3] = c;
		dest += 5;

		break;
	    }
#endif
#if TCL_UTF_MAX > 5
	case 6: {
		c = dest[0];
		dest[0] = dest[5];
		dest[5] = c;

		c = dest[1];


		dest[1] = dest[4];

		dest[4] = c;

		c = dest[0];

		dest[2] = dest[3];
		dest[3] = c;
		dest += 6;

		break;


	    }
#endif
	default: {
#if TCL_UTF_MAX > 3
		c = dest[0];
		dest[0] = dest[3];
		dest[3] = c;
		c = dest[1];
		dest[1] = dest[2];
		dest[2] = c;
		dest += 4;
#endif
		break;
	    }

	}
    }




	/* Pass 2: Reverse byte string. */

	dest = TclGetString(resultPtr);


	while (dest < --src) {
		c = *src;
		*src = *dest;
		*dest++ = c;
	}



    return resultPtr;
}

/*
 *---------------------------------------------------------------------------
 *
 * FillUnicodeRep --
 *

Changes to generic/tclTest.c.

795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
	asyncPtr = ckalloc(sizeof(TestAsyncHandler));
	asyncPtr->command = ckalloc(strlen(argv[2]) + 1);
	strcpy(asyncPtr->command, argv[2]);
        Tcl_MutexLock(&asyncTestMutex);
	asyncPtr->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
                                            (ClientData) asyncPtr->id);
	asyncPtr->nextPtr = firstHandler;
	firstHandler = asyncPtr;
        Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id));
    } else if (strcmp(argv[1], "delete") == 0) {
	if (argc == 2) {
            Tcl_MutexLock(&asyncTestMutex);







|







795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
	asyncPtr = ckalloc(sizeof(TestAsyncHandler));
	asyncPtr->command = ckalloc(strlen(argv[2]) + 1);
	strcpy(asyncPtr->command, argv[2]);
        Tcl_MutexLock(&asyncTestMutex);
	asyncPtr->id = nextId;
	nextId++;
	asyncPtr->handler = Tcl_AsyncCreate(AsyncHandlerProc,
                                            INT2PTR(asyncPtr->id));
	asyncPtr->nextPtr = firstHandler;
	firstHandler = asyncPtr;
        Tcl_MutexUnlock(&asyncTestMutex);
	Tcl_SetObjResult(interp, Tcl_NewIntObj(asyncPtr->id));
    } else if (strcmp(argv[1], "delete") == 0) {
	if (argc == 2) {
            Tcl_MutexLock(&asyncTestMutex);
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
	    return TCL_ERROR;
	}
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_ThreadId threadID;
		if (Tcl_CreateThread(&threadID, AsyncThreadProc,
			(ClientData) id, TCL_THREAD_STACK_DEFAULT,
			TCL_THREAD_NOFLAGS) != TCL_OK) {
		    Tcl_SetResult(interp, "can't create thread", TCL_STATIC);
		    return TCL_ERROR;
		}
		break;
	    }
	}







|







866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
	    return TCL_ERROR;
	}
	for (asyncPtr = firstHandler; asyncPtr != NULL;
		asyncPtr = asyncPtr->nextPtr) {
	    if (asyncPtr->id == id) {
		Tcl_ThreadId threadID;
		if (Tcl_CreateThread(&threadID, AsyncThreadProc,
			INT2PTR(id), TCL_THREAD_STACK_DEFAULT,
			TCL_THREAD_NOFLAGS) != TCL_OK) {
		    Tcl_SetResult(interp, "can't create thread", TCL_STATIC);
		    return TCL_ERROR;
		}
		break;
	    }
	}
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
    ClientData clientData,	/* If of TestAsyncHandler structure. 
                                 * in global list. */
    Tcl_Interp *interp,		/* Interpreter in which command was
				 * executed, or NULL. */
    int code)			/* Current return code from command. */
{
    TestAsyncHandler *asyncPtr;
    int id = (int) clientData;
    const char *listArgv[4], *cmd;
    char string[TCL_INTEGER_SPACE];

    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
         asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) break;







|







897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
    ClientData clientData,	/* If of TestAsyncHandler structure. 
                                 * in global list. */
    Tcl_Interp *interp,		/* Interpreter in which command was
				 * executed, or NULL. */
    int code)			/* Current return code from command. */
{
    TestAsyncHandler *asyncPtr;
    int id = PTR2INT(clientData);
    const char *listArgv[4], *cmd;
    char string[TCL_INTEGER_SPACE];

    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
         asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) break;
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
#ifdef TCL_THREADS
static Tcl_ThreadCreateType
AsyncThreadProc(
    ClientData clientData)	/* Parameter is the id of a
				 * TestAsyncHandler, defined above. */
{
    TestAsyncHandler *asyncPtr;
    int id = (int) clientData;

    Tcl_Sleep(1);
    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
         asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) {
            Tcl_AsyncMark(asyncPtr->handler);







|







954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
#ifdef TCL_THREADS
static Tcl_ThreadCreateType
AsyncThreadProc(
    ClientData clientData)	/* Parameter is the id of a
				 * TestAsyncHandler, defined above. */
{
    TestAsyncHandler *asyncPtr;
    int id = PTR2INT(clientData);

    Tcl_Sleep(1);
    Tcl_MutexLock(&asyncTestMutex);
    for (asyncPtr = firstHandler; asyncPtr != NULL;
         asyncPtr = asyncPtr->nextPtr) {
        if (asyncPtr->id == id) {
            Tcl_AsyncMark(asyncPtr->handler);