16
16
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17
17
│ PERFORMANCE OF THIS SOFTWARE. │
18
18
╚─────────────────────────────────────────────────────────────────────────────*/
19
- #include "libc/assert.h"
20
- #include "libc/atomic.h"
21
19
#include "libc/calls/createfileflags.internal.h"
22
20
#include "libc/calls/internal.h"
23
21
#include "libc/calls/sig.internal.h"
29
27
#include "libc/cosmo.h"
30
28
#include "libc/errno.h"
31
29
#include "libc/fmt/itoa.h"
32
- #include "libc/intrin/atomic.h"
33
30
#include "libc/intrin/describeflags.internal.h"
34
31
#include "libc/intrin/dll.h"
35
32
#include "libc/intrin/nomultics.internal.h"
36
33
#include "libc/intrin/strace.internal.h"
37
- #include "libc/intrin/weaken.h"
38
34
#include "libc/macros.internal.h"
39
- #include "libc/mem/mem.h"
40
35
#include "libc/nt/console.h"
41
36
#include "libc/nt/createfile.h"
42
37
#include "libc/nt/enum/accessmask.h"
51
46
#include "libc/nt/synchronization.h"
52
47
#include "libc/str/str.h"
53
48
#include "libc/str/utf16.h"
49
+ #include "libc/sysv/consts/limits.h"
54
50
#include "libc/sysv/consts/o.h"
55
51
#include "libc/sysv/consts/sicode.h"
56
52
#include "libc/sysv/consts/sig.h"
@@ -134,7 +130,7 @@ struct Keystrokes {
134
130
bool end_of_file ;
135
131
bool ohno_decckm ;
136
132
uint16_t utf16hs ;
137
- atomic_int_fast16_t used ;
133
+ int16_t freekeys ;
138
134
int64_t cin , cot ;
139
135
struct Dll * list ;
140
136
struct Dll * line ;
@@ -150,12 +146,42 @@ textwindows void __keystroke_wipe(void) {
150
146
bzero (& __keystroke , sizeof (__keystroke ));
151
147
}
152
148
149
+ static textwindows void FreeKeystrokeImpl (struct Dll * key ) {
150
+ dll_make_first (& __keystroke .free , key );
151
+ ++ __keystroke .freekeys ;
152
+ }
153
+
154
+ static textwindows struct Keystroke * NewKeystroke (void ) {
155
+ struct Dll * e = dll_first (__keystroke .free );
156
+ struct Keystroke * k = KEYSTROKE_CONTAINER (e );
157
+ dll_remove (& __keystroke .free , & k -> elem );
158
+ -- __keystroke .freekeys ;
159
+ k -> buflen = 0 ;
160
+ return k ;
161
+ }
162
+
163
+ static textwindows void FreeKeystroke (struct Dll * * list , struct Dll * key ) {
164
+ dll_remove (list , key );
165
+ FreeKeystrokeImpl (key );
166
+ }
167
+
168
+ static textwindows void FreeKeystrokes (struct Dll * * list ) {
169
+ struct Dll * key ;
170
+ while ((key = dll_first (* list ))) {
171
+ FreeKeystroke (list , key );
172
+ }
173
+ }
174
+
153
175
static textwindows void OpenConsole (void ) {
154
176
__keystroke .vkt = kVirtualKey ;
155
177
__keystroke .cin = CreateFile (u"CONIN$" , kNtGenericRead | kNtGenericWrite ,
156
178
kNtFileShareRead , 0 , kNtOpenExisting , 0 , 0 );
157
179
__keystroke .cot = CreateFile (u"CONOUT$" , kNtGenericRead | kNtGenericWrite ,
158
180
kNtFileShareWrite , 0 , kNtOpenExisting , 0 , 0 );
181
+ for (int i = 0 ; i < ARRAYLEN (__keystroke .pool ); ++ i ) {
182
+ dll_init (& __keystroke .pool [i ].elem );
183
+ FreeKeystrokeImpl (& __keystroke .pool [i ].elem );
184
+ }
159
185
}
160
186
161
187
static textwindows int AddSignal (int sig ) {
@@ -413,34 +439,6 @@ static textwindows int ConvertConsoleInputToAnsi(const struct NtInputRecord *r,
413
439
}
414
440
}
415
441
416
- static textwindows struct Keystroke * NewKeystroke (void ) {
417
- struct Dll * e ;
418
- struct Keystroke * k = 0 ;
419
- int i , n = ARRAYLEN (__keystroke .pool );
420
- if (atomic_load_explicit (& __keystroke .used , memory_order_acquire ) < n &&
421
- (i = atomic_fetch_add (& __keystroke .used , 1 )) < n ) {
422
- k = __keystroke .pool + i ;
423
- } else {
424
- if ((e = dll_first (__keystroke .free ))) {
425
- k = KEYSTROKE_CONTAINER (e );
426
- dll_remove (& __keystroke .free , & k -> elem );
427
- }
428
- if (!k ) {
429
- if (_weaken (malloc )) {
430
- k = _weaken (malloc )(sizeof (struct Keystroke ));
431
- } else {
432
- enomem ();
433
- return 0 ;
434
- }
435
- }
436
- }
437
- if (k ) {
438
- bzero (k , sizeof (* k ));
439
- dll_init (& k -> elem );
440
- }
441
- return k ;
442
- }
443
-
444
442
static textwindows void WriteTty (const char * p , size_t n ) {
445
443
WriteFile (__keystroke .cot , p , n , 0 , 0 );
446
444
}
@@ -479,8 +477,7 @@ static textwindows bool EraseKeystroke(void) {
479
477
struct Dll * e ;
480
478
if ((e = dll_last (__keystroke .line ))) {
481
479
struct Keystroke * k = KEYSTROKE_CONTAINER (e );
482
- dll_remove (& __keystroke .line , e );
483
- dll_make_first (& __keystroke .free , e );
480
+ FreeKeystroke (& __keystroke .line , e );
484
481
for (int i = k -> buflen ; i -- ;) {
485
482
if ((k -> buf [i ] & 0300 ) == 0200 ) continue ; // utf-8 cont
486
483
EraseCharacter ();
@@ -521,11 +518,7 @@ static textwindows void IngestConsoleInputRecord(struct NtInputRecord *r) {
521
518
}
522
519
523
520
// allocate object to hold keystroke
524
- struct Keystroke * k ;
525
- if (!(k = NewKeystroke ())) {
526
- STRACE ("out of keystroke memory" );
527
- return ;
528
- }
521
+ struct Keystroke * k = NewKeystroke ();
529
522
memcpy (k -> buf , buf , sizeof (k -> buf ));
530
523
k -> buflen = len ;
531
524
@@ -541,11 +534,11 @@ static textwindows void IngestConsoleInputRecord(struct NtInputRecord *r) {
541
534
} else {
542
535
dll_make_last (& __keystroke .line , & k -> elem );
543
536
544
- // handle enter in canonical mode
545
- if (len == 1 && buf [0 ] &&
546
- ((buf [0 ] & 255 ) == '\n' || //
547
- (buf [0 ] & 255 ) == __ttyconf .veol || //
548
- (buf [0 ] & 255 ) == __ttyconf .veol2 )) {
537
+ // flush canonical mode line if oom or enter
538
+ if (! __keystroke . freekeys || ( len == 1 && buf [0 ] &&
539
+ ((buf [0 ] & 255 ) == '\n' || //
540
+ (buf [0 ] & 255 ) == __ttyconf .veol || //
541
+ (buf [0 ] & 255 ) == __ttyconf .veol2 ) )) {
549
542
dll_make_last (& __keystroke .list , __keystroke .line );
550
543
__keystroke .line = 0 ;
551
544
}
@@ -556,12 +549,13 @@ static textwindows void IngestConsoleInput(void) {
556
549
uint32_t i , n ;
557
550
struct NtInputRecord records [16 ];
558
551
for (;;) {
552
+ if (!__keystroke .freekeys ) return ;
559
553
if (__keystroke .end_of_file ) return ;
560
554
if (!GetNumberOfConsoleInputEvents (__keystroke .cin , & n )) {
561
555
goto UnexpectedEof ;
562
556
}
563
557
if (!n ) return ;
564
- n = MIN (ARRAYLEN (records ), n );
558
+ n = MIN (__keystroke . freekeys , MIN ( ARRAYLEN (records ), n ) );
565
559
if (!ReadConsoleInput (__keystroke .cin , records , n , & n )) {
566
560
goto UnexpectedEof ;
567
561
}
@@ -576,19 +570,15 @@ static textwindows void IngestConsoleInput(void) {
576
570
577
571
// Discards all unread stdin bytes.
578
572
textwindows int FlushConsoleInputBytes (void ) {
579
- int rc ;
580
573
BLOCK_SIGNALS ;
581
574
InitConsole ();
582
575
LockKeystrokes ();
583
576
FlushConsoleInputBuffer (__keystroke .cin );
584
- dll_make_first (& __keystroke .free , __keystroke .list );
585
- __keystroke .list = 0 ;
586
- dll_make_first (& __keystroke .free , __keystroke .line );
587
- __keystroke .line = 0 ;
588
- rc = 0 ;
577
+ FreeKeystrokes (& __keystroke .list );
578
+ FreeKeystrokes (& __keystroke .line );
589
579
UnlockKeystrokes ();
590
580
ALLOW_SIGNALS ;
591
- return rc ;
581
+ return 0 ;
592
582
}
593
583
594
584
// Returns number of stdin bytes that may be read without blocking.
@@ -700,11 +690,10 @@ static textwindows bool DigestConsoleInput(char *data, size_t size, int *rc) {
700
690
}
701
691
if (remain ) {
702
692
memmove (k -> buf , k -> buf + got , remain );
693
+ k -> buflen = remain ;
703
694
} else {
704
- dll_remove (& __keystroke .list , e );
705
- dll_make_first (& __keystroke .free , e );
695
+ FreeKeystroke (& __keystroke .list , e );
706
696
}
707
- k -> buflen = remain ;
708
697
if ((__ttyconf .magic & kTtyUncanon ) && toto >= __ttyconf .vmin ) {
709
698
break ;
710
699
}
0 commit comments