Diff
Not logged in

Differences From Artifact [2c4d9c020a]:

To Artifact [71d450c3d9]:


407
408
409
410
411
412
413
414
415

416
417
418
419
420
421

422
423
424
425
426
427
428
407
408
409
410
411
412
413


414
415
416
417
418


419
420
421
422
423
424
425
426







-
-
+




-
-
+







    if (ringPtr->capacity - ringPtr->start > ringPtr->length) {
	/* There is room at the back */
	RingSizeT endSpaceStart = ringPtr->start + ringPtr->length;
	RingSizeT endSpace      = ringPtr->capacity - endSpaceStart;
	if (endSpace >= srcLen) {
	    /* Everything fits at the back */
	    memmove(endSpaceStart + ringPtr->bufPtr, srcPtr, srcLen);
	}
	else {
	} else {
	    /* srcLen > endSpace */
	    memmove(endSpaceStart + ringPtr->bufPtr, srcPtr, endSpace);
	    memmove(ringPtr->bufPtr, endSpace + srcPtr, srcLen - endSpace);
	}
    }
    else {
    } else {
	/* No room at the back. Existing data wrap to front. */
	RingSizeT wrapLen =
	    ringPtr->start + ringPtr->length - ringPtr->capacity;
	memmove(wrapLen + ringPtr->bufPtr, srcPtr, srcLen);
    }

    ringPtr->length += srcLen;
464
465
466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
481
482

483
484
485
486
487
488
489
462
463
464
465
466
467
468


469
470
471
472
473
474
475
476
477


478
479
480
481
482
483
484
485







-
-
+








-
-
+







	}
	dstCapacity = ringPtr->length;
    }

    if (ringPtr->start <= (ringPtr->capacity - ringPtr->length)) {
	/* No content wrap around. So leadLen is entire content */
	leadLen = ringPtr->length;
    }
    else {
    } else {
	/* Content wraps around so lead segment stretches to end of buffer */
	leadLen = ringPtr->capacity - ringPtr->start;
    }
    if (leadLen >= dstCapacity) {
	if (dstPtr) {
	    memmove(dstPtr, ringPtr->start + ringPtr->bufPtr, dstCapacity);
	}
	ringPtr->start += dstCapacity;
    }
    else {
    } else {
	RingSizeT wrapLen = dstCapacity - leadLen;
	if (dstPtr) {
	    memmove(dstPtr,
		    ringPtr->start + ringPtr->bufPtr,
		    leadLen);
	    memmove(
		leadLen + dstPtr, ringPtr->bufPtr, wrapLen);
562
563
564
565
566
567
568
569
570

571
572
573
574
575
576
577
558
559
560
561
562
563
564


565
566
567
568
569
570
571
572







-
-
+







    if (result) {
	if ((nRead == 0 || nRead == (DWORD)-1)
	    && GetLastError() == ERROR_OPERATION_ABORTED) {
	    nRead = 0;
	}
	*nCharsReadPtr = nRead;
	return 0;
    }
    else
    } else
	return GetLastError();
}

/*
 *------------------------------------------------------------------------
 *
 * WriteConsoleChars --
604
605
606
607
608
609
610
611
612

613
614
615
616
617
618
619
599
600
601
602
603
604
605


606
607
608
609
610
611
612
613







-
-
+







    result = WriteConsoleW(hConsole, lpBuffer, nChars, &nCharsWritten, NULL);
    if (result) {
	if (nCharsWritten == (DWORD) -1) {
	    nCharsWritten = 0;
	}
	*nCharsWrittenPtr = nCharsWritten;
	return 0;
    }
    else {
    } else {
	return GetLastError();
    }
}

/*
 *----------------------------------------------------------------------
 *
789
790
791
792
793
794
795
796
797

798
799
800
801
802
803
804
783
784
785
786
787
788
789


790
791
792
793
794
795
796
797







-
-
+







	    AcquireSRWLockShared(&handleInfoPtr->lock);
	    /* Remember at most one of READABLE, WRITABLE set */
	    if (chanInfoPtr->watchMask & TCL_READABLE) {
		if (RingBufferLength(&handleInfoPtr->buffer) > 0
		    || handleInfoPtr->lastError != ERROR_SUCCESS) {
		    block = 0; /* Input data available */
		}
	    }
	    else if (chanInfoPtr->watchMask & TCL_WRITABLE) {
	    } else if (chanInfoPtr->watchMask & TCL_WRITABLE) {
		if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		    /* TCL_WRITABLE */
		    block = 0; /* Output space available */
		}
	    }
	    ReleaseSRWLockShared(&handleInfoPtr->lock);
	}
872
873
874
875
876
877
878
879
880

881
882
883
884
885
886
887
865
866
867
868
869
870
871


872
873
874
875
876
877
878
879







-
-
+







	    AcquireSRWLockShared(&handleInfoPtr->lock);
	    /* Rememebr channel is read or write, never both */
	    if (chanInfoPtr->watchMask & TCL_READABLE) {
		if (RingBufferLength(&handleInfoPtr->buffer) > 0
		    || handleInfoPtr->lastError != ERROR_SUCCESS) {
		    needEvent = 1; /* Input data available or error/EOF */
		}
	    }
	    else if (chanInfoPtr->watchMask & TCL_WRITABLE) {
	    } else if (chanInfoPtr->watchMask & TCL_WRITABLE) {
		if (RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		    needEvent = 1; /* Output space available */
		}
	    }
	    ReleaseSRWLockShared(&handleInfoPtr->lock);
	}

979
980
981
982
983
984
985
986
987

988
989
990
991
992
993
994
971
972
973
974
975
976
977


978
979
980
981
982
983
984
985







-
-
+







     * still close the handle. That's historical behavior on all platforms.
     */
    if (!TclInThreadExit()
	|| ((GetStdHandle(STD_INPUT_HANDLE) != chanInfoPtr->handle)
	    && (GetStdHandle(STD_OUTPUT_HANDLE) != chanInfoPtr->handle)
	    && (GetStdHandle(STD_ERROR_HANDLE) != chanInfoPtr->handle))) {
	closeHandle = 1;
    }
    else {
    } else {
	closeHandle = 0;
    }

    AcquireSRWLockExclusive(&gConsoleLock);

    /* Remove channel from watchers' list */
    for (nextPtrPtr = &gWatchingChannelList; *nextPtrPtr != NULL;
1049
1050
1051
1052
1053
1054
1055
1056
1057

1058
1059
1060
1061
1062
1063
1064
1040
1041
1042
1043
1044
1045
1046


1047
1048
1049
1050
1051
1052
1053
1054







-
-
+







     * Note, we can check and manipulate numRefs without a lock because
     * we have removed it from the watch queue so the console thread cannot
     * get at it.
     */
    if (chanInfoPtr->numRefs > 1) {
	/* There may be references already on the event queue */
	chanInfoPtr->numRefs -= 1;
    }
    else {
    } else {
	ckfree(chanInfoPtr);
    }

    return errorCode;
}

/*
1127
1128
1129
1130
1131
1132
1133
1134
1135

1136
1137
1138
1139
1140
1141
1142
1117
1118
1119
1120
1121
1122
1123


1124
1125
1126
1127
1128
1129
1130
1131







-
-
+







	 *  - If EOF, indicate as much. It is up to the application to close
	 *    the channel.
	 *  - Otherwise, if non-blocking return EAGAIN or wait for more data.
	 */
	if (handleInfoPtr->lastError != 0) {
	    if (handleInfoPtr->lastError == ERROR_INVALID_HANDLE) {
		numRead = 0; /* Treat as EOF */
	    }
	    else {
	    } else {
		Tcl_WinConvertError(handleInfoPtr->lastError);
		handleInfoPtr->lastError = 0;
		*errorCode = Tcl_GetErrno();
		numRead = -1;
	    }
	    break;
	}
1172
1173
1174
1175
1176
1177
1178
1179
1180

1181
1182
1183
1184

1185
1186
1187
1188
1189
1190
1191
1161
1162
1163
1164
1165
1166
1167


1168
1169
1170


1171
1172
1173
1174
1175
1176
1177
1178







-
-
+


-
-
+







					 bufSize / sizeof(WCHAR),
					 &numChars);
	    /* NOTE lock released so DON'T break. Return instead */
	    if (lastError != ERROR_SUCCESS) {
		Tcl_WinConvertError(lastError);
		*errorCode = Tcl_GetErrno();
		return -1;
	    }
	    else if (numChars > 0) {
	    } else if (numChars > 0) {
		/* Successfully read something. */
		return numChars * sizeof(WCHAR);
	    }
	    else {
	    } else {
		/*
		 * Ctrl-C/Ctrl-Brk interrupt. Loop around to retry.
		 * We have to reacquire the lock. No worried about handleInfoPtr
		 * having gone away since the channel holds a reference.
		 */
		AcquireSRWLockExclusive(&handleInfoPtr->lock);
		continue;
1322
1323
1324
1325
1326
1327
1328
1329
1330

1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344

1345
1346
1347
1348
1349
1350
1351
1309
1310
1311
1312
1313
1314
1315


1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328


1329
1330
1331
1332
1333
1334
1335
1336







-
-
+












-
-
+







					   0)) {
		/* Report the error */
		Tcl_WinConvertError(GetLastError());
		*errorCode = Tcl_GetErrno();
		numWritten = -1;
		break;
	    }
	}
	else {
	} else {
	    /* Direct output */
	    DWORD winStatus;
	    HANDLE consoleHandle = handleInfoPtr->console;
	    /* Unlock before blocking in WriteConsole */
	    ReleaseSRWLockExclusive(&handleInfoPtr->lock);
	    /* UNLOCKED so return, DON'T break out of loop as it will unlock again! */
	    winStatus = WriteConsoleChars(consoleHandle,
					  (WCHAR *)buf,
					  toWrite / sizeof(WCHAR),
					  &numWritten);
	    if (winStatus == ERROR_SUCCESS) {
		return numWritten * sizeof(WCHAR);
	    }
	    else {
	    } else {
		Tcl_WinConvertError(winStatus);
		*errorCode = Tcl_GetErrno();
		return -1;
	    }
	}

	/* Lock is reacquired. Continue loop */
1416
1417
1418
1419
1420
1421
1422
1423
1424

1425
1426
1427
1428
1429
1430
1431

1432
1433
1434
1435
1436
1437
1438
1401
1402
1403
1404
1405
1406
1407


1408
1409
1410
1411
1412
1413


1414
1415
1416
1417
1418
1419
1420
1421







-
-
+





-
-
+







	ConsoleHandleInfo *handleInfoPtr;
	handleInfoPtr = FindConsoleInfo(chanInfoPtr);
	if (handleInfoPtr == NULL) {
	    /* Console was closed. EOF->read event only (not write) */
	    if (chanInfoPtr->watchMask & TCL_READABLE) {
		mask = TCL_READABLE;
	    }
	}
	else {
	} else {
	    AcquireSRWLockShared(&handleInfoPtr->lock);
	    /* Remember at most one of READABLE, WRITABLE set */
	    if ((chanInfoPtr->watchMask & TCL_READABLE)
		&& RingBufferLength(&handleInfoPtr->buffer)) {
		mask = TCL_READABLE;
	    }
	    else if ((chanInfoPtr->watchMask & TCL_WRITABLE)
	    } else if ((chanInfoPtr->watchMask & TCL_WRITABLE)
		     && RingBufferHasFreeSpace(&handleInfoPtr->buffer)) {
		/* Generate write event space available */
		mask = TCL_WRITABLE;
	    }
	    ReleaseSRWLockShared(&handleInfoPtr->lock);
	}
    }
1450
1451
1452
1453
1454
1455
1456
1457
1458

1459
1460
1461
1462
1463

1464

1465
1466
1467
1468
1469
1470
1471
1433
1434
1435
1436
1437
1438
1439


1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
1452
1453
1454







-
-
+




-
+

+








    /* No need to lock - see comments earlier */

    /* Remove the reference to the channel from event record */
    if (chanInfoPtr->numRefs > 1) {
	chanInfoPtr->numRefs -= 1;
	freeChannel = 0;
    }
    else {
    } else {
	assert(chanInfoPtr->channel == NULL);
	freeChannel = 1;
    }

    if (freeChannel)
    if (freeChannel) {
	ckfree(chanInfoPtr);
    }

    return 1;
}

/*
 *----------------------------------------------------------------------
 *
1560
1561
1562
1563
1564
1565
1566
1567
1568

1569
1570
1571
1572
1573
1574
1575
1543
1544
1545
1546
1547
1548
1549


1550
1551
1552
1553
1554
1555
1556
1557







-
-
+







    TCL_UNUSED(int) /*direction*/,
    ClientData *handlePtr)	/* Where to store the handle. */
{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;

    if (chanInfoPtr->handle == INVALID_HANDLE_VALUE) {
	return TCL_ERROR;
    }
    else {
    } else {
	*handlePtr = chanInfoPtr->handle;
	return TCL_OK;
    }
}

/*
 *------------------------------------------------------------------------
1680
1681
1682
1683
1684
1685
1686
1687
1688

1689
1690
1691
1692
1693
1694
1695
1662
1663
1664
1665
1666
1667
1668


1669
1670
1671
1672
1673
1674
1675
1676







-
-
+







				       1);
		inputOffset += nStored;
		if (inputOffset == inputLen) {
		    /* Temp buffer now empty */
		    inputOffset = 0;
		    inputLen = 0;
		}
	    }
	    else {
	    } else {
		/*
		 * On error, nothing but inform caller and wait
		 * We do not want to exit until there are no client interps.
		 */
	    }

	    /*
1739
1740
1741
1742
1743
1744
1745
1746
1747

1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758

1759
1760
1761
1762
1763
1764
1765
1720
1721
1722
1723
1724
1725
1726


1727
1728
1729
1730
1731
1732
1733
1734
1735
1736


1737
1738
1739
1740
1741
1742
1743
1744







-
-
+









-
-
+







	    error = ReadConsoleChars(handleInfoPtr->console,
				     (WCHAR *)inputChars,
				     sizeof(inputChars) / sizeof(WCHAR),
				     &inputLen);
	    AcquireSRWLockExclusive(&handleInfoPtr->lock);
	    if (error == 0) {
		inputLen *= sizeof(WCHAR);
	    }
	    else {
	    } else {
		/*
		 * We only store the last error. It is up to channel
		 * handlers whether to close or not in case of errors.
		 */
		handleInfoPtr->lastError = error;
		if (handleInfoPtr->lastError == ERROR_INVALID_HANDLE) {
		    handleInfoPtr->console = INVALID_HANDLE_VALUE;
		}
	    }
	}
	else {
	} else {
	    /*
	     * Either no one was asking for data, or no data was available.
	     * In the former case, wait until someone wakes us asking for
	     * data. In the latter case, there is no alternative but to
	     * poll since ReadConsole does not support async operation.
	     * So sleep for a short while and loop back to retry.
	     */
2136
2137
2138
2139
2140
2141
2142
2143
2144

2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161

2162
2163
2164
2165
2166
2167
2168
2115
2116
2117
2118
2119
2120
2121


2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137


2138
2139
2140
2141
2142
2143
2144
2145







-
-
+















-
-
+







	chanInfoPtr->flags |= CONSOLE_READ_OPS;
	GetConsoleMode(handle, &chanInfoPtr->initMode);

#ifdef OBSOLETE
	/* Why was priority being set on console input? Code smell */
	SetThreadPriority(infoPtr->reader.thread, THREAD_PRIORITY_HIGHEST);
#endif
    }
    else {
    } else {
	/* Already checked permissions is WRITABLE if not READABLE */
	/* TODO - enable ansi escape processing? */
    }

    /*
     * Global lock but that's ok. See comments top of file. Allocations
     * will happen only a few times in the life of a process and that too
     * generally at start up where only one thread is active.
     */
    AcquireSRWLockExclusive(&gConsoleLock); /*Allocate needs exclusive lock */

    handleInfoPtr = FindConsoleInfo(chanInfoPtr);
    if (handleInfoPtr == NULL) {
	/* Not found. Allocate one */
	handleInfoPtr = AllocateConsoleHandleInfo(handle, permissions);
    }
    else {
    } else {
	/* Found. Its direction (read/write) better be the same */
	if (handleInfoPtr->permissions != permissions) {
	    handleInfoPtr = NULL;
	}
    }

    if (handleInfoPtr == NULL) {
2230
2231
2232
2233
2234
2235
2236
2237
2238

2239
2240
2241
2242
2243
2244
2245
2207
2208
2209
2210
2211
2212
2213


2214
2215
2216
2217
2218
2219
2220
2221







-
-
+







{
    ConsoleChannelInfo *chanInfoPtr = (ConsoleChannelInfo *)instanceData;

    /* No need for any locks as no other thread will be writing to it */
    if (action == TCL_CHANNEL_THREAD_INSERT) {
	ConsoleInit(); /* Needed to set up event source handlers for this thread */
	chanInfoPtr->threadId = Tcl_GetCurrentThread();
    }
    else {
    } else {
	chanInfoPtr->threadId = NULL;
    }
}

/*
 *----------------------------------------------------------------------
 *
2394
2395
2396
2397
2398
2399
2400
2401
2402

2403
2404
2405
2406
2407
2408
2409
2370
2371
2372
2373
2374
2375
2376


2377
2378
2379
2380
2381
2382
2383
2384







-
-
+







		} else {
		    Tcl_DStringAppendElement(dsPtr, "password");
		}
	    } else {
		Tcl_DStringAppendElement(dsPtr, "raw");
	    }
	}
    }
    else {
    } else {
	/*
	 * Output channel. Get option -winsize
	 * Option is readonly and returned by [fconfigure chan -winsize] but not
	 * returned by [fconfigure chan] without explicit option name.
	 */
	if (len == 0) {
	    Tcl_DStringAppendElement(dsPtr, "-winsize");