Tcl Source Code

Check-in [0a522a5abd]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to tclconference@googlegroups.com
or submit via the online form by Sep 9.

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

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rc0 | core-8-6-3-rc
Files: files | file ages | folders
SHA1:0a522a5abdfeddaa7b2ec10005ffa8cbf69c9fef
User & Date: dgp 2014-10-18 22:43:06
Context
2014-10-22
14:46
by request check-in: 76fb8c73a5 user: dgp tags: rc1, core-8-6-3-rc
2014-10-18
22:43
merge trunk check-in: 0a522a5abd user: dgp tags: rc0, core-8-6-3-rc
20:03
[10dc6daa37] New fix for [gets] on non-blocking channel. This time properly accounts for the effects... check-in: 58e5b26f2a user: dgp tags: trunk
2014-10-14
18:12
Bump to Tcl 8.6.3, TclOO 1.0.3, and update changes file. check-in: 481f2d5443 user: dgp tags: core-8-6-3-rc
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to changes.

8475
8476
8477
8478
8479
8480
8481
8482


8483
2014-10-03 (bug)[bc1a96] segfault in [array set] of traced array (tab,porter)

2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans)

2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter)

2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter)



--- Released 8.6.3, October 29, 2014 --- http://core.tcl.tk/tcl/ for details








>
>

8475
8476
8477
8478
8479
8480
8481
8482
8483
8484
8485
2014-10-03 (bug)[bc1a96] segfault in [array set] of traced array (tab,porter)

2014-10-08 (bug)[59a2e7] MSVC14 compile support (dower,nijtmans)

2014-10-10 (bug)[ed29c4] [fcopy] treats [blocked] as error (rowen,porter)

2014-10-10 (bug)[bf7135] regression in Tcl_Write() interface (porter)

2014-10-18 (bug)[10dc6d] fix [gets] on non-blocking channels (fassel,porter)

--- Released 8.6.3, October 29, 2014 --- http://core.tcl.tk/tcl/ for details

Changes to generic/tclIO.c.

4449
4450
4451
4452
4453
4454
4455

4456
4457
4458
4459
4460
4461
4462
....
4797
4798
4799
4800
4801
4802
4803

4804
4805
4806
4807
4808
4809
4810
....
5085
5086
5087
5088
5089
5090
5091






5092
5093
5094
5095
5096
5097
5098
....
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
    dst = objPtr->bytes + oldLength;
    dstEnd = dst;

    skip = 0;
    eof = NULL;
    inEofChar = statePtr->inEofChar;


    while (1) {
	if (dst >= dstEnd) {
	    if (FilterInputBytes(chanPtr, &gs) != 0) {
		goto restore;
	    }
	    dstEnd = dst + gs.bytesWrote;
	}
................................................................................

    /*
     * Only handle TCL_TRANSLATE_LF and TCL_TRANSLATE_CR.
     */

    eolChar = (statePtr->inputTranslation == TCL_TRANSLATE_LF) ? '\n' : '\r';


    while (1) {
	/*
	 * Subtract the number of bytes that were removed from channel
	 * buffer during last call.
	 */

	if (bufPtr != NULL) {
................................................................................
	/*
	 * All channel buffers were exhausted and the caller still hasn't seen
	 * EOL. Need to read more bytes from the channel device. Side effect
	 * is to allocate another channel buffer.
	 */

    read:






	if (GetInput(chanPtr) != 0) {
	    gsPtr->charsWrote = 0;
	    gsPtr->rawRead = 0;
	    return -1;
	}
	bufPtr = statePtr->inQueueTail;
	gsPtr->bufPtr = bufPtr;
................................................................................
		bufPtr->nextRemoved = bufPtr->nextAdded;
	    } else {
		/*
		 * There are no more cached raw bytes left. See if we can get
		 * some more, but avoid blocking on a non-blocking channel.
		 */

		if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)
			== (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) {
		    gsPtr->charsWrote = 0;
		    gsPtr->rawRead = 0;
		    return -1;
		}
		goto read;
	    }
	} else {
	    if (nextPtr == NULL) {
		nextPtr = AllocChannelBuffer(statePtr->bufSize);
		bufPtr->nextPtr = nextPtr;
		statePtr->inQueueTail = nextPtr;







>







 







>







 







>
>
>
>
>
>







 







<
<
<
<
<
<







4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
....
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
....
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
....
5183
5184
5185
5186
5187
5188
5189






5190
5191
5192
5193
5194
5195
5196
    dst = objPtr->bytes + oldLength;
    dstEnd = dst;

    skip = 0;
    eof = NULL;
    inEofChar = statePtr->inEofChar;

    ResetFlag(statePtr, CHANNEL_BLOCKED);
    while (1) {
	if (dst >= dstEnd) {
	    if (FilterInputBytes(chanPtr, &gs) != 0) {
		goto restore;
	    }
	    dstEnd = dst + gs.bytesWrote;
	}
................................................................................

    /*
     * Only handle TCL_TRANSLATE_LF and TCL_TRANSLATE_CR.
     */

    eolChar = (statePtr->inputTranslation == TCL_TRANSLATE_LF) ? '\n' : '\r';

    ResetFlag(statePtr, CHANNEL_BLOCKED);
    while (1) {
	/*
	 * Subtract the number of bytes that were removed from channel
	 * buffer during last call.
	 */

	if (bufPtr != NULL) {
................................................................................
	/*
	 * All channel buffers were exhausted and the caller still hasn't seen
	 * EOL. Need to read more bytes from the channel device. Side effect
	 * is to allocate another channel buffer.
	 */

    read:
	if (GotFlag(statePtr, CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)
		== (CHANNEL_NONBLOCKING|CHANNEL_BLOCKED)) {
	    gsPtr->charsWrote = 0;
	    gsPtr->rawRead = 0;
	    return -1;
	}
	if (GetInput(chanPtr) != 0) {
	    gsPtr->charsWrote = 0;
	    gsPtr->rawRead = 0;
	    return -1;
	}
	bufPtr = statePtr->inQueueTail;
	gsPtr->bufPtr = bufPtr;
................................................................................
		bufPtr->nextRemoved = bufPtr->nextAdded;
	    } else {
		/*
		 * There are no more cached raw bytes left. See if we can get
		 * some more, but avoid blocking on a non-blocking channel.
		 */







		goto read;
	    }
	} else {
	    if (nextPtr == NULL) {
		nextPtr = AllocChannelBuffer(statePtr->bufSize);
		bufPtr->nextPtr = nextPtr;
		statePtr->inQueueTail = nextPtr;

Changes to tests/io.test.

4321
4322
4323
4324
4325
4326
4327








































































































4328
4329
4330
4331
4332
4333
4334
    close $f
    set f [open $path(test3) r]
    fconfigure $f -translation lf
    for {set y 0} {$y < 300} {incr y} {gets $f}
    close $f
    set y
} 300









































































































# Test Tcl_Seek and Tcl_Tell.

test io-34.1 {Tcl_Seek to current position at start of file} {
    set f1 [open $path(longfile) r]
    seek $f1 0 current
    set c [tell $f1]







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
    close $f
    set f [open $path(test3) r]
    fconfigure $f -translation lf
    for {set y 0} {$y < 300} {incr y} {gets $f}
    close $f
    set y
} 300
test io-33.11 {TclGetsObjBinary, [10dc6daa37]} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) .......
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
		if {$n > 3} {set n 3}
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
    }
} -body {
    set c [chan create read [namespace which driver]]
    chan configure $c -translation binary -blocking 0
    list [gets $c] [gets $c] [gets $c] [gets $c]
} -cleanup {
    close $c
    rename driver {}
} -result {{} {} {} .......}
test io-33.12 {Tcl_GetsObj, [10dc6daa37]} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) .......
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
		if {$n > 3} {set n 3}
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
    }
} -body {
    set c [chan create read [namespace which driver]]
    chan configure $c -blocking 0
    list [gets $c] [gets $c] [gets $c] [gets $c]
} -cleanup {
    close $c
    rename driver {}
} -result {{} {} {} .......}
test io-33.13 {Tcl_GetsObj, [10dc6daa37]} -setup {
    proc driver {cmd args} {
        variable buffer
        variable index
        set chan [lindex $args 0]
        switch -- $cmd {
            initialize {
                set index($chan) 0
                set buffer($chan) [string repeat \
                        [string repeat . 64]\n[string repeat . 25] 2]
                return {initialize finalize watch read}
            }
            finalize {
                unset index($chan) buffer($chan)
                return
            }
            watch {}
            read {
                set n [lindex $args 1]
                if {$n > 65} {set n 65}
                set new [expr {$index($chan) + $n}]
                set result [string range $buffer($chan) $index($chan) $new-1]
                set index($chan) $new
                return $result
            }
        }
    }
} -body {
    set c [chan create read [namespace which driver]]
    chan configure $c -blocking 0
    list [gets $c] [gets $c] [gets $c] [gets $c] [gets $c]
} -cleanup {
    close $c
    rename driver {}
} -result [list [string repeat . 64] {} [string repeat . 89] \
	[string repeat . 25] {}]

# Test Tcl_Seek and Tcl_Tell.

test io-34.1 {Tcl_Seek to current position at start of file} {
    set f1 [open $path(longfile) r]
    seek $f1 0 current
    set c [tell $f1]

Changes to tests/socket.test.

2316
2317
2318
2319
2320
2321
2322






















2323
2324
2325
2326
2327
2328
2329
        set s [socket -async localhost [randport]]
        set x ok
        fileevent $s writable {set x fail}
        catch {read $s}
	close $s
        set x
    } -result ok























set num 0

set x {localhost {socket} 127.0.0.1 {supported_inet} ::1 {supported_inet6}}
set resultok {-result "sock*" -match glob}
set resulterr {
    -result {couldn't open socket: connection refused}







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
        set s [socket -async localhost [randport]]
        set x ok
        fileevent $s writable {set x fail}
        catch {read $s}
	close $s
        set x
    } -result ok

# v4 and v6 is required to prevent that the async connect does not terminate
# before the fconfigure command. There is always an additional ip to try.
test socket-14.16 {empty -peername while [socket -async] connecting} \
    -constraints {socket localhost_v4 localhost_v6} \
    -body {
        set client [socket -async localhost [randport]]
        fconfigure $client -peername
    } -cleanup {
        catch {close $client}
    } -result {}

# v4 and v6 is required to prevent that the async connect does not terminate
# before the fconfigure command. There is always an additional ip to try.
test socket-14.17 {empty -sockname while [socket -async] connecting} \
    -constraints {socket localhost_v4 localhost_v6} \
    -body {
        set client [socket -async localhost [randport]]
        fconfigure $client -sockname
    } -cleanup {
        catch {close $client}
    } -result {}

set num 0

set x {localhost {socket} 127.0.0.1 {supported_inet} ::1 {supported_inet6}}
set resultok {-result "sock*" -match glob}
set resulterr {
    -result {couldn't open socket: connection refused}

Changes to unix/tclUnixSock.c.

819
820
821
822
823
824
825










826



827
828
829
830
831
832
833
...
859
860
861
862
863
864
865






866
867
868
869
870

871
872
873
874
875
876
877
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
        address peername;
        socklen_t size = sizeof(peername);











	if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) {



	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }
            TcpHostPortList(interp, dsPtr, peername, size);
	    if (len) {
                return TCL_OK;
................................................................................
        socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}






	for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
	    size = sizeof(sockname);
	    if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
		found = 1;
                TcpHostPortList(interp, dsPtr, sockname, size);

	    }
	}
        if (found) {
            if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);







>
>
>
>
>
>
>
>
>
>
|
>
>
>







 







>
>
>
>
>
>
|
|
|
|
|
>







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
...
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
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
        address peername;
        socklen_t size = sizeof(peername);

	if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) {
	    /*
	     * In async connect output an empty string
	     */
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		return TCL_OK;
	    }
	} else if (getpeername(statePtr->fds.fd, &peername.sa, &size) >= 0) {
	    /*
	     * Peername fetch succeeded - output list
	     */
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }
            TcpHostPortList(interp, dsPtr, peername, size);
	    if (len) {
                return TCL_OK;
................................................................................
        socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}
	if ( (statePtr->flags & TCP_ASYNC_CONNECT) ) {
	    /*
	     * In async connect output an empty string
	     */
	     found = 1;
	} else {
	    for (fds = &statePtr->fds; fds != NULL; fds = fds->next) {
		size = sizeof(sockname);
		if (getsockname(fds->fd, &(sockname.sa), &size) >= 0) {
		    found = 1;
		    TcpHostPortList(interp, dsPtr, sockname, size);
		}
	    }
	}
        if (found) {
            if (len) {
                return TCL_OK;
            }
            Tcl_DStringEndSublist(dsPtr);

Changes to win/tclWinSock.c.

1333
1334
1335
1336
1337
1338
1339










1340



1341
1342
1343
1344
1345
1346
1347
....
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
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423

1424
1425
1426
1427
1428
1429
1430
1431

1432
1433
1434
1435
1436
1437
1438
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
	address peername;
	socklen_t size = sizeof(peername);











	if (getpeername(sock, (LPSOCKADDR) &(peername.sa), &size) == 0) {



	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }

	    getnameinfo(&(peername.sa), size, host, sizeof(host),
		    NULL, 0, NI_NUMERICHOST);
................................................................................
	socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}






	for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
	    sock = fds->fd;
	    size = sizeof(sockname);
	    if (getsockname(sock, &(sockname.sa), &size) >= 0) {
		int flags = reverseDNS;

		found = 1;
		getnameinfo(&sockname.sa, size, host, sizeof(host),
			NULL, 0, NI_NUMERICHOST);
		Tcl_DStringAppendElement(dsPtr, host);

		/*
		 * We don't want to resolve INADDR_ANY and sin6addr_any; they
		 * can sometimes cause problems (and never have a name).
		 */
		flags |= NI_NUMERICSERV;
		if (sockname.sa.sa_family == AF_INET) {
		    if (sockname.sa4.sin_addr.s_addr == INADDR_ANY) {
			flags |= NI_NUMERICHOST;
		    }
		} else if (sockname.sa.sa_family == AF_INET6) {
		    if ((IN6_ARE_ADDR_EQUAL(&sockname.sa6.sin6_addr,
				&in6addr_any)) ||
			    (IN6_IS_ADDR_V4MAPPED(&sockname.sa6.sin6_addr)
			    && sockname.sa6.sin6_addr.s6_addr[12] == 0
			    && sockname.sa6.sin6_addr.s6_addr[13] == 0
			    && sockname.sa6.sin6_addr.s6_addr[14] == 0
			    && sockname.sa6.sin6_addr.s6_addr[15] == 0)) {
			flags |= NI_NUMERICHOST;
		    }
		}
		getnameinfo(&sockname.sa, size, host, sizeof(host),
			port, sizeof(port), flags);
		Tcl_DStringAppendElement(dsPtr, host);
		Tcl_DStringAppendElement(dsPtr, port);

	    }
	}
	if (found) {
	    if (len == 0) {
		Tcl_DStringEndSublist(dsPtr);
	    } else {
		return TCL_OK;
	    }

	} else {
	    if (interp) {
		TclWinConvertError((DWORD) WSAGetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get sockname: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;







>
>
>
>
>
>
>
>
>
>
|
>
>
>







 







>
>
>
>
>
>
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>



|
<
<


>







1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
....
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447


1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
    }

    if ((len == 0) || ((len > 1) && (optionName[1] == 'p') &&
	    (strncmp(optionName, "-peername", len) == 0))) {
	address peername;
	socklen_t size = sizeof(peername);

	if ( (statePtr->flags & TCP_ASYNC_PENDING) ) {
	    /*
	     * In async connect output an empty string
	     */
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringAppendElement(dsPtr, "");
	    } else {
		return TCL_OK;
	    }
	} else if ( getpeername(sock, (LPSOCKADDR) &(peername.sa), &size) == 0) {
	    /*
	     * Peername fetch succeeded - output list
	     */
	    if (len == 0) {
		Tcl_DStringAppendElement(dsPtr, "-peername");
		Tcl_DStringStartSublist(dsPtr);
	    }

	    getnameinfo(&(peername.sa), size, host, sizeof(host),
		    NULL, 0, NI_NUMERICHOST);
................................................................................
	socklen_t size;
	int found = 0;

	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-sockname");
	    Tcl_DStringStartSublist(dsPtr);
	}
	if ( (statePtr->flags & TCP_ASYNC_PENDING ) ) {
	    /*
	     * In async connect output an empty string
	     */
	     found = 1;
	} else {
	    for (fds = statePtr->sockets; fds != NULL; fds = fds->next) {
		sock = fds->fd;
		size = sizeof(sockname);
		if (getsockname(sock, &(sockname.sa), &size) >= 0) {
		    int flags = reverseDNS;

		    found = 1;
		    getnameinfo(&sockname.sa, size, host, sizeof(host),
			    NULL, 0, NI_NUMERICHOST);
		    Tcl_DStringAppendElement(dsPtr, host);

		    /*
		     * We don't want to resolve INADDR_ANY and sin6addr_any; they
		     * can sometimes cause problems (and never have a name).
		     */
		    flags |= NI_NUMERICSERV;
		    if (sockname.sa.sa_family == AF_INET) {
			if (sockname.sa4.sin_addr.s_addr == INADDR_ANY) {
			    flags |= NI_NUMERICHOST;
			}
		    } else if (sockname.sa.sa_family == AF_INET6) {
			if ((IN6_ARE_ADDR_EQUAL(&sockname.sa6.sin6_addr,
				    &in6addr_any)) ||
				(IN6_IS_ADDR_V4MAPPED(&sockname.sa6.sin6_addr)
				&& sockname.sa6.sin6_addr.s6_addr[12] == 0
				&& sockname.sa6.sin6_addr.s6_addr[13] == 0
				&& sockname.sa6.sin6_addr.s6_addr[14] == 0
				&& sockname.sa6.sin6_addr.s6_addr[15] == 0)) {
			    flags |= NI_NUMERICHOST;
			}
		    }
		    getnameinfo(&sockname.sa, size, host, sizeof(host),
			    port, sizeof(port), flags);
		    Tcl_DStringAppendElement(dsPtr, host);
		    Tcl_DStringAppendElement(dsPtr, port);
		}
	    }
	}
	if (found) {
	    if (len) {


		return TCL_OK;
	    }
	    Tcl_DStringEndSublist(dsPtr);
	} else {
	    if (interp) {
		TclWinConvertError((DWORD) WSAGetLastError());
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"can't get sockname: %s", Tcl_PosixError(interp)));
	    }
	    return TCL_ERROR;