xref: /freebsd/contrib/bc/src/history.c (revision aa1a8ff2d6dbc51ef058f46f3db5a8bb77967145)
1 /*
2  * *****************************************************************************
3  *
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c) 2018-2023 Gavin D. Howard and contributors.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * * Redistributions of source code must retain the above copyright notice, this
12  *   list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright notice,
15  *   this list of conditions and the following disclaimer in the documentation
16  *   and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * *****************************************************************************
31  *
32  * Adapted from the following:
33  *
34  * linenoise.c -- guerrilla line editing library against the idea that a
35  * line editing lib needs to be 20,000 lines of C code.
36  *
37  * You can find the original source code at:
38  *   http://github.com/antirez/linenoise
39  *
40  * You can find the fork that this code is based on at:
41  *   https://github.com/rain-1/linenoise-mob
42  *
43  * ------------------------------------------------------------------------
44  *
45  * This code is also under the following license:
46  *
47  * Copyright (c) 2010-2016, Salvatore Sanfilippo <antirez at gmail dot com>
48  * Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
49  *
50  * Redistribution and use in source and binary forms, with or without
51  * modification, are permitted provided that the following conditions are
52  * met:
53  *
54  *  *  Redistributions of source code must retain the above copyright
55  *     notice, this list of conditions and the following disclaimer.
56  *
57  *  *  Redistributions in binary form must reproduce the above copyright
58  *     notice, this list of conditions and the following disclaimer in the
59  *     documentation and/or other materials provided with the distribution.
60  *
61  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
62  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
63  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
64  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
65  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
66  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
67  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
68  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
69  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
70  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
71  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
72  *
73  * ------------------------------------------------------------------------
74  *
75  * Does a number of crazy assumptions that happen to be true in 99.9999% of
76  * the 2010 UNIX computers around.
77  *
78  * References:
79  * - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
80  * - http://www.3waylabs.com/nw/WWW/products/wizcon/vt220.html
81  *
82  * Todo list:
83  * - Filter bogus Ctrl+<char> combinations.
84  * - Win32 support
85  *
86  * Bloat:
87  * - History search like Ctrl+r in readline?
88  *
89  * List of escape sequences used by this program, we do everything just
90  * with three sequences. In order to be so cheap we may have some
91  * flickering effect with some slow terminal, but the lesser sequences
92  * the more compatible.
93  *
94  * EL (Erase Line)
95  *    Sequence: ESC [ n K
96  *    Effect: if n is 0 or missing, clear from cursor to end of line
97  *    Effect: if n is 1, clear from beginning of line to cursor
98  *    Effect: if n is 2, clear entire line
99  *
100  * CUF (CUrsor Forward)
101  *    Sequence: ESC [ n C
102  *    Effect: moves cursor forward n chars
103  *
104  * CUB (CUrsor Backward)
105  *    Sequence: ESC [ n D
106  *    Effect: moves cursor backward n chars
107  *
108  * The following is used to get the terminal width if getting
109  * the width with the TIOCGWINSZ ioctl fails
110  *
111  * DSR (Device Status Report)
112  *    Sequence: ESC [ 6 n
113  *    Effect: reports the current cusor position as ESC [ n ; m R
114  *            where n is the row and m is the column
115  *
116  * When multi line mode is enabled, we also use two additional escape
117  * sequences. However multi line editing is disabled by default.
118  *
119  * CUU (CUrsor Up)
120  *    Sequence: ESC [ n A
121  *    Effect: moves cursor up of n chars.
122  *
123  * CUD (CUrsor Down)
124  *    Sequence: ESC [ n B
125  *    Effect: moves cursor down of n chars.
126  *
127  * When bc_history_clearScreen() is called, two additional escape sequences
128  * are used in order to clear the screen and position the cursor at home
129  * position.
130  *
131  * CUP (CUrsor Position)
132  *    Sequence: ESC [ H
133  *    Effect: moves the cursor to upper left corner
134  *
135  * ED (Erase Display)
136  *    Sequence: ESC [ 2 J
137  *    Effect: clear the whole screen
138  *
139  * *****************************************************************************
140  *
141  * Code for line history.
142  *
143  */
144 
145 #if BC_ENABLE_HISTORY
146 
147 #if BC_ENABLE_EDITLINE
148 
149 #include <string.h>
150 #include <errno.h>
151 #include <setjmp.h>
152 
153 #include <history.h>
154 #include <vm.h>
155 
156 sigjmp_buf bc_history_jmpbuf;
157 volatile sig_atomic_t bc_history_inlinelib;
158 
159 static char* bc_history_prompt;
160 static char bc_history_no_prompt[] = "";
161 static HistEvent bc_history_event;
162 static bool bc_history_use_prompt;
163 
164 static char*
165 bc_history_promptFunc(EditLine* el)
166 {
167 	BC_UNUSED(el);
168 	return BC_PROMPT && bc_history_use_prompt ? bc_history_prompt :
169 	                                            bc_history_no_prompt;
170 }
171 
172 void
173 bc_history_init(BcHistory* h)
174 {
175 	BcVec v;
176 	char* home;
177 
178 	home = getenv("HOME");
179 
180 	// This will hold the true path to the editrc.
181 	bc_vec_init(&v, 1, BC_DTOR_NONE);
182 
183 	// Initialize the path to the editrc. This is done manually because the
184 	// libedit I used to test was failing with a NULL argument for the path,
185 	// which was supposed to automatically do $HOME/.editrc. But it was failing,
186 	// so I set it manually.
187 	if (home == NULL)
188 	{
189 		bc_vec_string(&v, bc_history_editrc_len - 1, bc_history_editrc + 1);
190 	}
191 	else
192 	{
193 		bc_vec_string(&v, strlen(home), home);
194 		bc_vec_concat(&v, bc_history_editrc);
195 	}
196 
197 	h->hist = history_init();
198 	if (BC_ERR(h->hist == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
199 
200 	h->el = el_init(vm->name, stdin, stdout, stderr);
201 	if (BC_ERR(h->el == NULL)) bc_vm_fatalError(BC_ERR_FATAL_ALLOC_ERR);
202 
203 	// I want history and a prompt.
204 	history(h->hist, &bc_history_event, H_SETSIZE, 100);
205 	history(h->hist, &bc_history_event, H_SETUNIQUE, 1);
206 	el_set(h->el, EL_EDITOR, "emacs");
207 	el_set(h->el, EL_HIST, history, h->hist);
208 	el_set(h->el, EL_PROMPT, bc_history_promptFunc);
209 
210 	// I also want to get the user's .editrc.
211 	el_source(h->el, v.v);
212 
213 	bc_vec_free(&v);
214 
215 	h->badTerm = false;
216 	bc_history_prompt = NULL;
217 }
218 
219 void
220 bc_history_free(BcHistory* h)
221 {
222 	if (BC_PROMPT && bc_history_prompt != NULL) free(bc_history_prompt);
223 	el_end(h->el);
224 	history_end(h->hist);
225 }
226 
227 BcStatus
228 bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
229 {
230 	BcStatus s = BC_STATUS_SUCCESS;
231 	const char* line;
232 	int len;
233 
234 	BC_SIG_LOCK;
235 
236 	// If the jump happens here, then a SIGINT occurred.
237 	if (sigsetjmp(bc_history_jmpbuf, 0))
238 	{
239 		bc_vec_string(vec, 1, "\n");
240 		goto end;
241 	}
242 
243 	// This is so the signal handler can handle line libraries properly.
244 	bc_history_inlinelib = 1;
245 
246 	if (BC_PROMPT)
247 	{
248 		// Make sure to set the prompt.
249 		if (bc_history_prompt != NULL)
250 		{
251 			if (strcmp(bc_history_prompt, prompt))
252 			{
253 				free(bc_history_prompt);
254 				bc_history_prompt = bc_vm_strdup(prompt);
255 			}
256 		}
257 		else bc_history_prompt = bc_vm_strdup(prompt);
258 	}
259 
260 	bc_history_use_prompt = true;
261 
262 	line = NULL;
263 	len = -1;
264 	errno = EINTR;
265 
266 	// Get the line.
267 	while (line == NULL && len == -1 && errno == EINTR)
268 	{
269 		line = el_gets(h->el, &len);
270 		bc_history_use_prompt = false;
271 	}
272 
273 	// If there is no line...
274 	if (BC_ERR(line == NULL))
275 	{
276 		// If this is true, there was an error. Otherwise, it's just EOF.
277 		if (len == -1)
278 		{
279 			if (errno == ENOMEM) bc_err(BC_ERR_FATAL_ALLOC_ERR);
280 			bc_err(BC_ERR_FATAL_IO_ERR);
281 		}
282 		else
283 		{
284 			bc_file_printf(&vm->fout, "\n");
285 			s = BC_STATUS_EOF;
286 		}
287 	}
288 	// If there is a line...
289 	else
290 	{
291 		bc_vec_string(vec, strlen(line), line);
292 
293 		if (strcmp(line, "") && strcmp(line, "\n"))
294 		{
295 			history(h->hist, &bc_history_event, H_ENTER, line);
296 		}
297 
298 		s = BC_STATUS_SUCCESS;
299 	}
300 
301 end:
302 
303 	bc_history_inlinelib = 0;
304 
305 	BC_SIG_UNLOCK;
306 
307 	return s;
308 }
309 
310 #else // BC_ENABLE_EDITLINE
311 
312 #if BC_ENABLE_READLINE
313 
314 #include <assert.h>
315 #include <setjmp.h>
316 #include <string.h>
317 
318 #include <history.h>
319 #include <vm.h>
320 
321 sigjmp_buf bc_history_jmpbuf;
322 volatile sig_atomic_t bc_history_inlinelib;
323 
324 void
325 bc_history_init(BcHistory* h)
326 {
327 	h->line = NULL;
328 	h->badTerm = false;
329 
330 	// I want no tab completion.
331 	rl_bind_key('\t', rl_insert);
332 }
333 
334 void
335 bc_history_free(BcHistory* h)
336 {
337 	if (h->line != NULL) free(h->line);
338 }
339 
340 BcStatus
341 bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
342 {
343 	BcStatus s = BC_STATUS_SUCCESS;
344 	size_t len;
345 
346 	BC_SIG_LOCK;
347 
348 	// If the jump happens here, then a SIGINT occurred.
349 	if (sigsetjmp(bc_history_jmpbuf, 0))
350 	{
351 		bc_vec_string(vec, 1, "\n");
352 		goto end;
353 	}
354 
355 	// This is so the signal handler can handle line libraries properly.
356 	bc_history_inlinelib = 1;
357 
358 	// Get rid of the last line.
359 	if (h->line != NULL)
360 	{
361 		free(h->line);
362 		h->line = NULL;
363 	}
364 
365 	// Get the line.
366 	h->line = readline(BC_PROMPT ? prompt : "");
367 
368 	// If there was a line, add it to the history. Otherwise, just return an
369 	// empty line. Oh, and NULL actually means EOF.
370 	if (h->line != NULL && h->line[0])
371 	{
372 		add_history(h->line);
373 
374 		len = strlen(h->line);
375 
376 		bc_vec_expand(vec, len + 2);
377 
378 		bc_vec_string(vec, len, h->line);
379 		bc_vec_concat(vec, "\n");
380 	}
381 	else if (h->line == NULL)
382 	{
383 		bc_file_printf(&vm->fout, "%s\n", "^D");
384 		s = BC_STATUS_EOF;
385 	}
386 	else bc_vec_string(vec, 1, "\n");
387 
388 end:
389 
390 	bc_history_inlinelib = 0;
391 
392 	BC_SIG_UNLOCK;
393 
394 	return s;
395 }
396 
397 #else // BC_ENABLE_READLINE
398 
399 #include <assert.h>
400 #include <stdlib.h>
401 #include <errno.h>
402 #include <string.h>
403 #include <ctype.h>
404 
405 #include <signal.h>
406 #include <sys/stat.h>
407 #include <sys/types.h>
408 
409 #ifndef _WIN32
410 #include <strings.h>
411 #include <termios.h>
412 #include <unistd.h>
413 #include <sys/ioctl.h>
414 #include <sys/select.h>
415 #endif // _WIN32
416 
417 #include <status.h>
418 #include <vector.h>
419 #include <history.h>
420 #include <read.h>
421 #include <file.h>
422 #include <vm.h>
423 
424 #if BC_DEBUG_CODE
425 
426 /// A file for outputting to when debugging.
427 BcFile bc_history_debug_fp;
428 
429 /// A buffer for the above file.
430 char* bc_history_debug_buf;
431 
432 #endif // BC_DEBUG_CODE
433 
434 /**
435  * Checks if the code is a wide character.
436  * @param cp  The codepoint to check.
437  * @return    True if @a cp is a wide character, false otherwise.
438  */
439 static bool
440 bc_history_wchar(uint32_t cp)
441 {
442 	size_t i;
443 
444 	for (i = 0; i < bc_history_wchars_len; ++i)
445 	{
446 		// Ranges are listed in ascending order.  Therefore, once the
447 		// whole range is higher than the codepoint we're testing, the
448 		// codepoint won't be found in any remaining range => bail early.
449 		if (bc_history_wchars[i][0] > cp) return false;
450 
451 		// Test this range.
452 		if (bc_history_wchars[i][0] <= cp && cp <= bc_history_wchars[i][1])
453 		{
454 			return true;
455 		}
456 	}
457 
458 	return false;
459 }
460 
461 /**
462  * Checks if the code is a combining character.
463  * @param cp  The codepoint to check.
464  * @return    True if @a cp is a combining character, false otherwise.
465  */
466 static bool
467 bc_history_comboChar(uint32_t cp)
468 {
469 	size_t i;
470 
471 	for (i = 0; i < bc_history_combo_chars_len; ++i)
472 	{
473 		// Combining chars are listed in ascending order, so once we pass
474 		// the codepoint of interest, we know it's not a combining char.
475 		if (bc_history_combo_chars[i] > cp) return false;
476 		if (bc_history_combo_chars[i] == cp) return true;
477 	}
478 
479 	return false;
480 }
481 
482 /**
483  * Gets the length of previous UTF8 character.
484  * @param buf  The buffer of characters.
485  * @param pos  The index into the buffer.
486  */
487 static size_t
488 bc_history_prevCharLen(const char* buf, size_t pos)
489 {
490 	size_t end = pos;
491 	for (pos -= 1; pos < end && (buf[pos] & 0xC0) == 0x80; --pos)
492 	{
493 		continue;
494 	}
495 	return end - (pos >= end ? 0 : pos);
496 }
497 
498 /**
499  * Converts UTF-8 to a Unicode code point.
500  * @param s    The string.
501  * @param len  The length of the string.
502  * @param cp   An out parameter for the codepoint.
503  * @return     The number of bytes eaten by the codepoint.
504  */
505 static size_t
506 bc_history_codePoint(const char* s, size_t len, uint32_t* cp)
507 {
508 	if (len)
509 	{
510 		uchar byte = (uchar) s[0];
511 
512 		// This is literally the UTF-8 decoding algorithm. Look that up if you
513 		// don't understand this.
514 
515 		if ((byte & 0x80) == 0)
516 		{
517 			*cp = byte;
518 			return 1;
519 		}
520 		else if ((byte & 0xE0) == 0xC0)
521 		{
522 			if (len >= 2)
523 			{
524 				*cp = (((uint32_t) (s[0] & 0x1F)) << 6) |
525 				      ((uint32_t) (s[1] & 0x3F));
526 				return 2;
527 			}
528 		}
529 		else if ((byte & 0xF0) == 0xE0)
530 		{
531 			if (len >= 3)
532 			{
533 				*cp = (((uint32_t) (s[0] & 0x0F)) << 12) |
534 				      (((uint32_t) (s[1] & 0x3F)) << 6) |
535 				      ((uint32_t) (s[2] & 0x3F));
536 				return 3;
537 			}
538 		}
539 		else if ((byte & 0xF8) == 0xF0)
540 		{
541 			if (len >= 4)
542 			{
543 				*cp = (((uint32_t) (s[0] & 0x07)) << 18) |
544 				      (((uint32_t) (s[1] & 0x3F)) << 12) |
545 				      (((uint32_t) (s[2] & 0x3F)) << 6) |
546 				      ((uint32_t) (s[3] & 0x3F));
547 				return 4;
548 			}
549 		}
550 		else
551 		{
552 			*cp = 0xFFFD;
553 			return 1;
554 		}
555 	}
556 
557 	*cp = 0;
558 
559 	return 1;
560 }
561 
562 /**
563  * Gets the length of next grapheme.
564  * @param buf      The buffer.
565  * @param buf_len  The length of the buffer.
566  * @param pos      The index into the buffer.
567  * @param col_len  An out parameter for the length of the grapheme on screen.
568  * @return         The number of bytes in the grapheme.
569  */
570 static size_t
571 bc_history_nextLen(const char* buf, size_t buf_len, size_t pos, size_t* col_len)
572 {
573 	uint32_t cp;
574 	size_t beg = pos;
575 	size_t len = bc_history_codePoint(buf + pos, buf_len - pos, &cp);
576 
577 	if (bc_history_comboChar(cp))
578 	{
579 		BC_UNREACHABLE
580 
581 #if !BC_CLANG
582 		if (col_len != NULL) *col_len = 0;
583 
584 		return 0;
585 #endif // !BC_CLANG
586 	}
587 
588 	// Store the width of the character on screen.
589 	if (col_len != NULL) *col_len = bc_history_wchar(cp) ? 2 : 1;
590 
591 	pos += len;
592 
593 	// Find the first non-combining character.
594 	while (pos < buf_len)
595 	{
596 		len = bc_history_codePoint(buf + pos, buf_len - pos, &cp);
597 
598 		if (!bc_history_comboChar(cp)) return pos - beg;
599 
600 		pos += len;
601 	}
602 
603 	return pos - beg;
604 }
605 
606 /**
607  * Gets the length of previous grapheme.
608  * @param buf  The buffer.
609  * @param pos  The index into the buffer.
610  * @return     The number of bytes in the grapheme.
611  */
612 static size_t
613 bc_history_prevLen(const char* buf, size_t pos)
614 {
615 	size_t end = pos;
616 
617 	// Find the first non-combining character.
618 	while (pos > 0)
619 	{
620 		uint32_t cp;
621 		size_t len = bc_history_prevCharLen(buf, pos);
622 
623 		pos -= len;
624 		bc_history_codePoint(buf + pos, len, &cp);
625 
626 		// The original linenoise-mob had an extra parameter col_len, like
627 		// bc_history_nextLen(), which, if not NULL, was set in this if
628 		// statement. However, we always passed NULL, so just skip that.
629 		if (!bc_history_comboChar(cp)) return end - pos;
630 	}
631 
632 	BC_UNREACHABLE
633 
634 #if !BC_CLANG
635 	return 0;
636 #endif // BC_CLANG
637 }
638 
639 /**
640  * Reads @a n characters from stdin.
641  * @param buf  The buffer to read into. The caller is responsible for making
642  *             sure this is big enough for @a n.
643  * @param n    The number of characters to read.
644  * @return     The number of characters read or less than 0 on error.
645  */
646 static ssize_t
647 bc_history_read(char* buf, size_t n)
648 {
649 	ssize_t ret;
650 
651 	BC_SIG_ASSERT_LOCKED;
652 
653 #ifndef _WIN32
654 
655 	do
656 	{
657 		// We don't care about being interrupted.
658 		ret = read(STDIN_FILENO, buf, n);
659 	}
660 	while (ret == EINTR);
661 
662 #else // _WIN32
663 
664 	bool good;
665 	DWORD read;
666 	HANDLE hn = GetStdHandle(STD_INPUT_HANDLE);
667 
668 	good = ReadConsole(hn, buf, (DWORD) n, &read, NULL);
669 
670 	ret = (read != n || !good) ? -1 : 1;
671 
672 #endif // _WIN32
673 
674 	return ret;
675 }
676 
677 /**
678  * Reads a Unicode code point into a buffer.
679  * @param buf      The buffer to read into.
680  * @param buf_len  The length of the buffer.
681  * @param cp       An out parameter for the codepoint.
682  * @param nread    An out parameter for the number of bytes read.
683  * @return         BC_STATUS_EOF or BC_STATUS_SUCCESS.
684  */
685 static BcStatus
686 bc_history_readCode(char* buf, size_t buf_len, uint32_t* cp, size_t* nread)
687 {
688 	ssize_t n;
689 	uchar byte;
690 
691 	assert(buf_len >= 1);
692 
693 	BC_SIG_LOCK;
694 
695 	// Read a byte.
696 	n = bc_history_read(buf, 1);
697 
698 	BC_SIG_UNLOCK;
699 
700 	if (BC_ERR(n <= 0)) goto err;
701 
702 	// Get the byte.
703 	byte = ((uchar*) buf)[0];
704 
705 	// Once again, this is the UTF-8 decoding algorithm, but it has reads
706 	// instead of actual decoding.
707 	if ((byte & 0x80) != 0)
708 	{
709 		if ((byte & 0xE0) == 0xC0)
710 		{
711 			assert(buf_len >= 2);
712 
713 			BC_SIG_LOCK;
714 
715 			n = bc_history_read(buf + 1, 1);
716 
717 			BC_SIG_UNLOCK;
718 
719 			if (BC_ERR(n <= 0)) goto err;
720 		}
721 		else if ((byte & 0xF0) == 0xE0)
722 		{
723 			assert(buf_len >= 3);
724 
725 			BC_SIG_LOCK;
726 
727 			n = bc_history_read(buf + 1, 2);
728 
729 			BC_SIG_UNLOCK;
730 
731 			if (BC_ERR(n <= 0)) goto err;
732 		}
733 		else if ((byte & 0xF8) == 0xF0)
734 		{
735 			assert(buf_len >= 3);
736 
737 			BC_SIG_LOCK;
738 
739 			n = bc_history_read(buf + 1, 3);
740 
741 			BC_SIG_UNLOCK;
742 
743 			if (BC_ERR(n <= 0)) goto err;
744 		}
745 		else
746 		{
747 			n = -1;
748 			goto err;
749 		}
750 	}
751 
752 	// Convert to the codepoint.
753 	*nread = bc_history_codePoint(buf, buf_len, cp);
754 
755 	return BC_STATUS_SUCCESS;
756 
757 err:
758 	// If we get here, we either had a fatal error of EOF.
759 	if (BC_ERR(n < 0)) bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
760 	else *nread = (size_t) n;
761 	return BC_STATUS_EOF;
762 }
763 
764 /**
765  * Gets the column length from beginning of buffer to current byte position.
766  * @param buf      The buffer.
767  * @param buf_len  The length of the buffer.
768  * @param pos      The index into the buffer.
769  * @return         The number of columns between the beginning of @a buffer to
770  *                 @a pos.
771  */
772 static size_t
773 bc_history_colPos(const char* buf, size_t buf_len, size_t pos)
774 {
775 	size_t ret = 0, off = 0;
776 
777 	// While we haven't reached the offset, get the length of the next grapheme.
778 	while (off < pos && off < buf_len)
779 	{
780 		size_t col_len, len;
781 
782 		len = bc_history_nextLen(buf, buf_len, off, &col_len);
783 
784 		off += len;
785 		ret += col_len;
786 	}
787 
788 	return ret;
789 }
790 
791 /**
792  * Returns true if the terminal name is in the list of terminals we know are
793  * not able to understand basic escape sequences.
794  * @return  True if the terminal is a bad terminal.
795  */
796 static inline bool
797 bc_history_isBadTerm(void)
798 {
799 	size_t i;
800 	bool ret = false;
801 	char* term = bc_vm_getenv("TERM");
802 
803 	if (term == NULL) return false;
804 
805 	for (i = 0; !ret && bc_history_bad_terms[i]; ++i)
806 	{
807 		ret = (!strcasecmp(term, bc_history_bad_terms[i]));
808 	}
809 
810 	bc_vm_getenvFree(term);
811 
812 	return ret;
813 }
814 
815 /**
816  * Enables raw mode (1960's black magic).
817  * @param h  The history data.
818  */
819 static void
820 bc_history_enableRaw(BcHistory* h)
821 {
822 	// I don't do anything for Windows because in Windows, you set their
823 	// equivalent of raw mode and leave it, so I do it in bc_history_init().
824 
825 #ifndef _WIN32
826 	struct termios raw;
827 	int err;
828 
829 	assert(BC_TTYIN);
830 
831 	if (h->rawMode) return;
832 
833 	BC_SIG_LOCK;
834 
835 	if (BC_ERR(tcgetattr(STDIN_FILENO, &h->orig_termios) == -1))
836 	{
837 		bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
838 	}
839 
840 	BC_SIG_UNLOCK;
841 
842 	// Modify the original mode.
843 	raw = h->orig_termios;
844 
845 	// Input modes: no break, no CR to NL, no parity check, no strip char,
846 	// no start/stop output control.
847 	raw.c_iflag &= (unsigned int) (~(BRKINT | ICRNL | INPCK | ISTRIP | IXON));
848 
849 	// Control modes: set 8 bit chars.
850 	raw.c_cflag |= (CS8);
851 
852 	// Local modes - choing off, canonical off, no extended functions,
853 	// no signal chars (^Z,^C).
854 	raw.c_lflag &= (unsigned int) (~(ECHO | ICANON | IEXTEN | ISIG));
855 
856 	// Control chars - set return condition: min number of bytes and timer.
857 	// We want read to give every single byte, w/o timeout (1 byte, no timer).
858 	raw.c_cc[VMIN] = 1;
859 	raw.c_cc[VTIME] = 0;
860 
861 	BC_SIG_LOCK;
862 
863 	// Put terminal in raw mode after flushing.
864 	do
865 	{
866 		err = tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
867 	}
868 	while (BC_ERR(err < 0) && errno == EINTR);
869 
870 	BC_SIG_UNLOCK;
871 
872 	if (BC_ERR(err < 0)) bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
873 #endif // _WIN32
874 
875 	h->rawMode = true;
876 }
877 
878 /**
879  * Disables raw mode.
880  * @param h  The history data.
881  */
882 static void
883 bc_history_disableRaw(BcHistory* h)
884 {
885 	sig_atomic_t lock;
886 
887 	if (!h->rawMode) return;
888 
889 	BC_SIG_TRYLOCK(lock);
890 
891 #ifndef _WIN32
892 	if (BC_ERR(tcsetattr(STDIN_FILENO, TCSAFLUSH, &h->orig_termios) != -1))
893 	{
894 		h->rawMode = false;
895 	}
896 #endif // _WIN32
897 
898 	BC_SIG_TRYUNLOCK(lock);
899 }
900 
901 /**
902  * Uses the ESC [6n escape sequence to query the horizontal cursor position
903  * and return it. On error -1 is returned, on success the position of the
904  * cursor.
905  * @return  The horizontal cursor position.
906  */
907 static size_t
908 bc_history_cursorPos(void)
909 {
910 	char buf[BC_HIST_SEQ_SIZE];
911 	char* ptr;
912 	char* ptr2;
913 	size_t cols, rows, i;
914 
915 	BC_SIG_ASSERT_LOCKED;
916 
917 	// Report cursor location.
918 	bc_file_write(&vm->fout, bc_flush_none, "\x1b[6n", 4);
919 	bc_file_flush(&vm->fout, bc_flush_none);
920 
921 	// Read the response: ESC [ rows ; cols R.
922 	for (i = 0; i < sizeof(buf) - 1; ++i)
923 	{
924 		if (bc_history_read(buf + i, 1) != 1 || buf[i] == 'R') break;
925 	}
926 
927 	buf[i] = '\0';
928 
929 	// This is basically an error; we didn't get what we were expecting.
930 	if (BC_ERR(buf[0] != BC_ACTION_ESC || buf[1] != '[')) return SIZE_MAX;
931 
932 	// Parse the rows.
933 	ptr = buf + 2;
934 	rows = strtoul(ptr, &ptr2, 10);
935 
936 	// Here we also didn't get what we were expecting.
937 	if (BC_ERR(!rows || ptr2[0] != ';')) return SIZE_MAX;
938 
939 	// Parse the columns.
940 	ptr = ptr2 + 1;
941 	cols = strtoul(ptr, NULL, 10);
942 
943 	if (BC_ERR(!cols)) return SIZE_MAX;
944 
945 	return cols <= UINT16_MAX ? cols : 0;
946 }
947 
948 /**
949  * Tries to get the number of columns in the current terminal, or assume 80
950  * if it fails.
951  * @return  The number of columns in the terminal.
952  */
953 static size_t
954 bc_history_columns(void)
955 {
956 
957 #ifndef _WIN32
958 
959 	struct winsize ws;
960 	int ret;
961 
962 	ret = ioctl(vm->fout.fd, TIOCGWINSZ, &ws);
963 
964 	if (BC_ERR(ret == -1 || !ws.ws_col))
965 	{
966 		// Calling ioctl() failed. Try to query the terminal itself.
967 		size_t start, cols;
968 
969 		// Get the initial position so we can restore it later.
970 		start = bc_history_cursorPos();
971 		if (BC_ERR(start == SIZE_MAX)) return BC_HIST_DEF_COLS;
972 
973 		// Go to right margin and get position.
974 		bc_file_write(&vm->fout, bc_flush_none, "\x1b[999C", 6);
975 		bc_file_flush(&vm->fout, bc_flush_none);
976 		cols = bc_history_cursorPos();
977 		if (BC_ERR(cols == SIZE_MAX)) return BC_HIST_DEF_COLS;
978 
979 		// Restore position.
980 		if (cols > start)
981 		{
982 			bc_file_printf(&vm->fout, "\x1b[%zuD", cols - start);
983 			bc_file_flush(&vm->fout, bc_flush_none);
984 		}
985 
986 		return cols;
987 	}
988 
989 	return ws.ws_col;
990 
991 #else // _WIN32
992 
993 	CONSOLE_SCREEN_BUFFER_INFO csbi;
994 
995 	if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
996 	{
997 		return 80;
998 	}
999 
1000 	return ((size_t) (csbi.srWindow.Right)) - csbi.srWindow.Left + 1;
1001 
1002 #endif // _WIN32
1003 }
1004 
1005 /**
1006  * Gets the column length of prompt text. This is probably unnecessary because
1007  * the prompts that I use are ASCII, but I kept it just in case.
1008  * @param prompt  The prompt.
1009  * @param plen    The length of the prompt.
1010  * @return        The column length of the prompt.
1011  */
1012 static size_t
1013 bc_history_promptColLen(const char* prompt, size_t plen)
1014 {
1015 	char buf[BC_HIST_MAX_LINE + 1];
1016 	size_t buf_len = 0, off = 0;
1017 
1018 	// The original linenoise-mob checked for ANSI escapes here on the prompt. I
1019 	// know the prompts do not have ANSI escapes. I deleted the code.
1020 	while (off < plen)
1021 	{
1022 		buf[buf_len++] = prompt[off++];
1023 	}
1024 
1025 	return bc_history_colPos(buf, buf_len, buf_len);
1026 }
1027 
1028 /**
1029  * Rewrites the currently edited line accordingly to the buffer content,
1030  * cursor position, and number of columns of the terminal.
1031  * @param h  The history data.
1032  */
1033 static void
1034 bc_history_refresh(BcHistory* h)
1035 {
1036 	char* buf = h->buf.v;
1037 	size_t colpos, len = BC_HIST_BUF_LEN(h), pos = h->pos, extras_len = 0;
1038 
1039 	BC_SIG_ASSERT_LOCKED;
1040 
1041 	bc_file_flush(&vm->fout, bc_flush_none);
1042 
1043 	// Get to the prompt column position from the left.
1044 	while (h->pcol + bc_history_colPos(buf, len, pos) >= h->cols)
1045 	{
1046 		size_t chlen = bc_history_nextLen(buf, len, 0, NULL);
1047 
1048 		buf += chlen;
1049 		len -= chlen;
1050 		pos -= chlen;
1051 	}
1052 
1053 	// Get to the prompt column position from the right.
1054 	while (h->pcol + bc_history_colPos(buf, len, len) > h->cols)
1055 	{
1056 		len -= bc_history_prevLen(buf, len);
1057 	}
1058 
1059 	// Cursor to left edge.
1060 	bc_file_write(&vm->fout, bc_flush_none, "\r", 1);
1061 
1062 	// Take the extra stuff into account. This is where history makes sure to
1063 	// preserve stuff that was printed without a newline.
1064 	if (h->extras.len > 1)
1065 	{
1066 		extras_len = h->extras.len - 1;
1067 
1068 		bc_vec_grow(&h->buf, extras_len);
1069 
1070 		len += extras_len;
1071 		pos += extras_len;
1072 
1073 		bc_file_write(&vm->fout, bc_flush_none, h->extras.v, extras_len);
1074 	}
1075 
1076 	// Write the prompt, if desired.
1077 	if (BC_PROMPT) bc_file_write(&vm->fout, bc_flush_none, h->prompt, h->plen);
1078 
1079 	bc_file_write(&vm->fout, bc_flush_none, h->buf.v, len - extras_len);
1080 
1081 	// Erase to right.
1082 	bc_file_write(&vm->fout, bc_flush_none, "\x1b[0K", 4);
1083 
1084 	// We need to be sure to grow this.
1085 	if (pos >= h->buf.len - extras_len) bc_vec_grow(&h->buf, pos + extras_len);
1086 
1087 	// Move cursor to original position. Do NOT move the putchar of '\r' to the
1088 	// printf with colpos. That causes a bug where the cursor will go to the end
1089 	// of the line when there is no prompt.
1090 	bc_file_putchar(&vm->fout, bc_flush_none, '\r');
1091 	colpos = bc_history_colPos(h->buf.v, len - extras_len, pos) + h->pcol;
1092 
1093 	// Set the cursor position again.
1094 	if (colpos) bc_file_printf(&vm->fout, "\x1b[%zuC", colpos);
1095 
1096 	bc_file_flush(&vm->fout, bc_flush_none);
1097 }
1098 
1099 /**
1100  * Inserts the character(s) 'c' at cursor current position.
1101  * @param h     The history data.
1102  * @param cbuf  The character buffer to copy from.
1103  * @param clen  The number of characters to copy.
1104  */
1105 static void
1106 bc_history_edit_insert(BcHistory* h, const char* cbuf, size_t clen)
1107 {
1108 	BC_SIG_ASSERT_LOCKED;
1109 
1110 	bc_vec_grow(&h->buf, clen);
1111 
1112 	// If we are at the end of the line...
1113 	if (h->pos == BC_HIST_BUF_LEN(h))
1114 	{
1115 		size_t colpos = 0, len;
1116 
1117 		// Copy into the buffer.
1118 		memcpy(bc_vec_item(&h->buf, h->pos), cbuf, clen);
1119 
1120 		// Adjust the buffer.
1121 		h->pos += clen;
1122 		h->buf.len += clen - 1;
1123 		bc_vec_pushByte(&h->buf, '\0');
1124 
1125 		// Set the length and column position.
1126 		len = BC_HIST_BUF_LEN(h) + h->extras.len - 1;
1127 		colpos = bc_history_promptColLen(h->prompt, h->plen);
1128 		colpos += bc_history_colPos(h->buf.v, len, len);
1129 
1130 		// Do we have the trivial case?
1131 		if (colpos < h->cols)
1132 		{
1133 			// Avoid a full update of the line in the trivial case.
1134 			bc_file_write(&vm->fout, bc_flush_none, cbuf, clen);
1135 			bc_file_flush(&vm->fout, bc_flush_none);
1136 		}
1137 		else bc_history_refresh(h);
1138 	}
1139 	else
1140 	{
1141 		// Amount that we need to move.
1142 		size_t amt = BC_HIST_BUF_LEN(h) - h->pos;
1143 
1144 		// Move the stuff.
1145 		memmove(h->buf.v + h->pos + clen, h->buf.v + h->pos, amt);
1146 		memcpy(h->buf.v + h->pos, cbuf, clen);
1147 
1148 		// Adjust the buffer.
1149 		h->pos += clen;
1150 		h->buf.len += clen;
1151 		h->buf.v[BC_HIST_BUF_LEN(h)] = '\0';
1152 
1153 		bc_history_refresh(h);
1154 	}
1155 }
1156 
1157 /**
1158  * Moves the cursor to the left.
1159  * @param h  The history data.
1160  */
1161 static void
1162 bc_history_edit_left(BcHistory* h)
1163 {
1164 	BC_SIG_ASSERT_LOCKED;
1165 
1166 	// Stop at the left end.
1167 	if (h->pos <= 0) return;
1168 
1169 	h->pos -= bc_history_prevLen(h->buf.v, h->pos);
1170 
1171 	bc_history_refresh(h);
1172 }
1173 
1174 /**
1175  * Moves the cursor to the right.
1176  * @param h  The history data.
1177  */
1178 static void
1179 bc_history_edit_right(BcHistory* h)
1180 {
1181 	BC_SIG_ASSERT_LOCKED;
1182 
1183 	// Stop at the right end.
1184 	if (h->pos == BC_HIST_BUF_LEN(h)) return;
1185 
1186 	h->pos += bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL);
1187 
1188 	bc_history_refresh(h);
1189 }
1190 
1191 /**
1192  * Moves the cursor to the end of the current word.
1193  * @param h  The history data.
1194  */
1195 static void
1196 bc_history_edit_wordEnd(BcHistory* h)
1197 {
1198 	size_t len = BC_HIST_BUF_LEN(h);
1199 
1200 	BC_SIG_ASSERT_LOCKED;
1201 
1202 	// Don't overflow.
1203 	if (!len || h->pos >= len) return;
1204 
1205 	// Find the word, then find the end of it.
1206 	while (h->pos < len && isspace(h->buf.v[h->pos]))
1207 	{
1208 		h->pos += 1;
1209 	}
1210 	while (h->pos < len && !isspace(h->buf.v[h->pos]))
1211 	{
1212 		h->pos += 1;
1213 	}
1214 
1215 	bc_history_refresh(h);
1216 }
1217 
1218 /**
1219  * Moves the cursor to the start of the current word.
1220  * @param h  The history data.
1221  */
1222 static void
1223 bc_history_edit_wordStart(BcHistory* h)
1224 {
1225 	size_t len = BC_HIST_BUF_LEN(h);
1226 
1227 	BC_SIG_ASSERT_LOCKED;
1228 
1229 	// Stop with no data.
1230 	if (!len) return;
1231 
1232 	// Find the word, the find the beginning of the word.
1233 	while (h->pos > 0 && isspace(h->buf.v[h->pos - 1]))
1234 	{
1235 		h->pos -= 1;
1236 	}
1237 	while (h->pos > 0 && !isspace(h->buf.v[h->pos - 1]))
1238 	{
1239 		h->pos -= 1;
1240 	}
1241 
1242 	bc_history_refresh(h);
1243 }
1244 
1245 /**
1246  * Moves the cursor to the start of the line.
1247  * @param h  The history data.
1248  */
1249 static void
1250 bc_history_edit_home(BcHistory* h)
1251 {
1252 	BC_SIG_ASSERT_LOCKED;
1253 
1254 	// Stop at the beginning.
1255 	if (!h->pos) return;
1256 
1257 	h->pos = 0;
1258 
1259 	bc_history_refresh(h);
1260 }
1261 
1262 /**
1263  * Moves the cursor to the end of the line.
1264  * @param h  The history data.
1265  */
1266 static void
1267 bc_history_edit_end(BcHistory* h)
1268 {
1269 	BC_SIG_ASSERT_LOCKED;
1270 
1271 	// Stop at the end of the line.
1272 	if (h->pos == BC_HIST_BUF_LEN(h)) return;
1273 
1274 	h->pos = BC_HIST_BUF_LEN(h);
1275 
1276 	bc_history_refresh(h);
1277 }
1278 
1279 /**
1280  * Substitutes the currently edited line with the next or previous history
1281  * entry as specified by 'dir' (direction).
1282  * @param h    The history data.
1283  * @param dir  The direction to substitute; true means previous, false next.
1284  */
1285 static void
1286 bc_history_edit_next(BcHistory* h, bool dir)
1287 {
1288 	const char* dup;
1289 	const char* str;
1290 
1291 	BC_SIG_ASSERT_LOCKED;
1292 
1293 	// Stop if there is no history.
1294 	if (h->history.len <= 1) return;
1295 
1296 	// Duplicate the buffer.
1297 	if (h->buf.v[0]) dup = bc_vm_strdup(h->buf.v);
1298 	else dup = "";
1299 
1300 	// Update the current history entry before overwriting it with the next one.
1301 	bc_vec_replaceAt(&h->history, h->history.len - 1 - h->idx, &dup);
1302 
1303 	// Show the new entry.
1304 	h->idx += (dir == BC_HIST_PREV ? 1 : SIZE_MAX);
1305 
1306 	// Se the index appropriately at the ends.
1307 	if (h->idx == SIZE_MAX)
1308 	{
1309 		h->idx = 0;
1310 		return;
1311 	}
1312 	else if (h->idx >= h->history.len)
1313 	{
1314 		h->idx = h->history.len - 1;
1315 		return;
1316 	}
1317 
1318 	// Get the string.
1319 	str = *((char**) bc_vec_item(&h->history, h->history.len - 1 - h->idx));
1320 	bc_vec_string(&h->buf, strlen(str), str);
1321 
1322 	assert(h->buf.len > 0);
1323 
1324 	// Set the position at the end.
1325 	h->pos = BC_HIST_BUF_LEN(h);
1326 
1327 	bc_history_refresh(h);
1328 }
1329 
1330 /**
1331  * Deletes the character at the right of the cursor without altering the cursor
1332  * position. Basically, this is what happens with the "Delete" keyboard key.
1333  * @param h  The history data.
1334  */
1335 static void
1336 bc_history_edit_delete(BcHistory* h)
1337 {
1338 	size_t chlen, len = BC_HIST_BUF_LEN(h);
1339 
1340 	BC_SIG_ASSERT_LOCKED;
1341 
1342 	// If there is no character, skip.
1343 	if (!len || h->pos >= len) return;
1344 
1345 	// Get the length of the character.
1346 	chlen = bc_history_nextLen(h->buf.v, len, h->pos, NULL);
1347 
1348 	// Move characters after it into its place.
1349 	memmove(h->buf.v + h->pos, h->buf.v + h->pos + chlen, len - h->pos - chlen);
1350 
1351 	// Make the buffer valid again.
1352 	h->buf.len -= chlen;
1353 	h->buf.v[BC_HIST_BUF_LEN(h)] = '\0';
1354 
1355 	bc_history_refresh(h);
1356 }
1357 
1358 /**
1359  * Deletes the character to the left of the cursor and moves the cursor back one
1360  * space. Basically, this is what happens with the "Backspace" keyboard key.
1361  * @param h  The history data.
1362  */
1363 static void
1364 bc_history_edit_backspace(BcHistory* h)
1365 {
1366 	size_t chlen, len = BC_HIST_BUF_LEN(h);
1367 
1368 	BC_SIG_ASSERT_LOCKED;
1369 
1370 	// If there are no characters, skip.
1371 	if (!h->pos || !len) return;
1372 
1373 	// Get the length of the previous character.
1374 	chlen = bc_history_prevLen(h->buf.v, h->pos);
1375 
1376 	// Move everything back one.
1377 	memmove(h->buf.v + h->pos - chlen, h->buf.v + h->pos, len - h->pos);
1378 
1379 	// Make the buffer valid again.
1380 	h->pos -= chlen;
1381 	h->buf.len -= chlen;
1382 	h->buf.v[BC_HIST_BUF_LEN(h)] = '\0';
1383 
1384 	bc_history_refresh(h);
1385 }
1386 
1387 /**
1388  * Deletes the previous word, maintaining the cursor at the start of the
1389  * current word.
1390  * @param h  The history data.
1391  */
1392 static void
1393 bc_history_edit_deletePrevWord(BcHistory* h)
1394 {
1395 	size_t diff, old_pos = h->pos;
1396 
1397 	BC_SIG_ASSERT_LOCKED;
1398 
1399 	// If at the beginning of the line, skip.
1400 	if (!old_pos) return;
1401 
1402 	// Find the word, then the beginning of the word.
1403 	while (h->pos > 0 && isspace(h->buf.v[h->pos - 1]))
1404 	{
1405 		h->pos -= 1;
1406 	}
1407 	while (h->pos > 0 && !isspace(h->buf.v[h->pos - 1]))
1408 	{
1409 		h->pos -= 1;
1410 	}
1411 
1412 	// Get the difference in position.
1413 	diff = old_pos - h->pos;
1414 
1415 	// Move the data back.
1416 	memmove(h->buf.v + h->pos, h->buf.v + old_pos,
1417 	        BC_HIST_BUF_LEN(h) - old_pos + 1);
1418 
1419 	// Make the buffer valid again.
1420 	h->buf.len -= diff;
1421 
1422 	bc_history_refresh(h);
1423 }
1424 
1425 /**
1426  * Deletes the next word, maintaining the cursor at the same position.
1427  * @param h  The history data.
1428  */
1429 static void
1430 bc_history_edit_deleteNextWord(BcHistory* h)
1431 {
1432 	size_t next_end = h->pos, len = BC_HIST_BUF_LEN(h);
1433 
1434 	BC_SIG_ASSERT_LOCKED;
1435 
1436 	// If at the end of the line, skip.
1437 	if (next_end == len) return;
1438 
1439 	// Find the word, then the end of the word.
1440 	while (next_end < len && isspace(h->buf.v[next_end]))
1441 	{
1442 		next_end += 1;
1443 	}
1444 	while (next_end < len && !isspace(h->buf.v[next_end]))
1445 	{
1446 		next_end += 1;
1447 	}
1448 
1449 	// Move the stuff into position.
1450 	memmove(h->buf.v + h->pos, h->buf.v + next_end, len - next_end);
1451 
1452 	// Make the buffer valid again.
1453 	h->buf.len -= next_end - h->pos;
1454 
1455 	bc_history_refresh(h);
1456 }
1457 
1458 /**
1459  * Swaps two characters, the one under the cursor and the one to the left.
1460  * @param h  The history data.
1461  */
1462 static void
1463 bc_history_swap(BcHistory* h)
1464 {
1465 	size_t pcl, ncl;
1466 	char auxb[5];
1467 
1468 	BC_SIG_ASSERT_LOCKED;
1469 
1470 	// If there are no characters, skip.
1471 	if (!h->pos) return;
1472 
1473 	// Get the length of the previous and next characters.
1474 	pcl = bc_history_prevLen(h->buf.v, h->pos);
1475 	ncl = bc_history_nextLen(h->buf.v, BC_HIST_BUF_LEN(h), h->pos, NULL);
1476 
1477 	// To perform a swap we need:
1478 	// * Nonzero char length to the left.
1479 	// * To not be at the end of the line.
1480 	if (pcl && h->pos != BC_HIST_BUF_LEN(h) && pcl < 5 && ncl < 5)
1481 	{
1482 		// Swap.
1483 		memcpy(auxb, h->buf.v + h->pos - pcl, pcl);
1484 		memcpy(h->buf.v + h->pos - pcl, h->buf.v + h->pos, ncl);
1485 		memcpy(h->buf.v + h->pos - pcl + ncl, auxb, pcl);
1486 
1487 		// Reset the position.
1488 		h->pos += ((~pcl) + 1) + ncl;
1489 
1490 		bc_history_refresh(h);
1491 	}
1492 }
1493 
1494 /**
1495  * Raises the specified signal. This is a convenience function.
1496  * @param h    The history data.
1497  * @param sig  The signal to raise.
1498  */
1499 static void
1500 bc_history_raise(BcHistory* h, int sig)
1501 {
1502 	// We really don't want to be in raw mode when longjmp()'s are flying.
1503 	bc_history_disableRaw(h);
1504 	raise(sig);
1505 }
1506 
1507 /**
1508  * Handles escape sequences. This function will make sense if you know VT100
1509  * escape codes; otherwise, it will be confusing.
1510  * @param h  The history data.
1511  */
1512 static void
1513 bc_history_escape(BcHistory* h)
1514 {
1515 	char c, seq[3];
1516 
1517 	BC_SIG_ASSERT_LOCKED;
1518 
1519 	// Read a character into seq.
1520 	if (BC_ERR(BC_HIST_READ(seq, 1))) return;
1521 
1522 	c = seq[0];
1523 
1524 	// ESC ? sequences.
1525 	if (c != '[' && c != 'O')
1526 	{
1527 		if (c == 'f') bc_history_edit_wordEnd(h);
1528 		else if (c == 'b') bc_history_edit_wordStart(h);
1529 		else if (c == 'd') bc_history_edit_deleteNextWord(h);
1530 	}
1531 	else
1532 	{
1533 		// Read a character into seq.
1534 		if (BC_ERR(BC_HIST_READ(seq + 1, 1)))
1535 		{
1536 			bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
1537 		}
1538 
1539 		// ESC [ sequences.
1540 		if (c == '[')
1541 		{
1542 			c = seq[1];
1543 
1544 			if (c >= '0' && c <= '9')
1545 			{
1546 				// Extended escape, read additional byte.
1547 				if (BC_ERR(BC_HIST_READ(seq + 2, 1)))
1548 				{
1549 					bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
1550 				}
1551 
1552 				if (seq[2] == '~')
1553 				{
1554 					switch (c)
1555 					{
1556 						case '1':
1557 						{
1558 							bc_history_edit_home(h);
1559 							break;
1560 						}
1561 
1562 						case '3':
1563 						{
1564 							bc_history_edit_delete(h);
1565 							break;
1566 						}
1567 
1568 						case '4':
1569 						{
1570 							bc_history_edit_end(h);
1571 							break;
1572 						}
1573 
1574 						default:
1575 						{
1576 							break;
1577 						}
1578 					}
1579 				}
1580 				else if (seq[2] == ';')
1581 				{
1582 					// Read two characters into seq.
1583 					if (BC_ERR(BC_HIST_READ(seq, 2)))
1584 					{
1585 						bc_vm_fatalError(BC_ERR_FATAL_IO_ERR);
1586 					}
1587 
1588 					if (seq[0] != '5') return;
1589 					else if (seq[1] == 'C') bc_history_edit_wordEnd(h);
1590 					else if (seq[1] == 'D') bc_history_edit_wordStart(h);
1591 				}
1592 			}
1593 			else
1594 			{
1595 				switch (c)
1596 				{
1597 					// Up.
1598 					case 'A':
1599 					{
1600 						bc_history_edit_next(h, BC_HIST_PREV);
1601 						break;
1602 					}
1603 
1604 					// Down.
1605 					case 'B':
1606 					{
1607 						bc_history_edit_next(h, BC_HIST_NEXT);
1608 						break;
1609 					}
1610 
1611 					// Right.
1612 					case 'C':
1613 					{
1614 						bc_history_edit_right(h);
1615 						break;
1616 					}
1617 
1618 					// Left.
1619 					case 'D':
1620 					{
1621 						bc_history_edit_left(h);
1622 						break;
1623 					}
1624 
1625 					// Home.
1626 					case 'H':
1627 					case '1':
1628 					{
1629 						bc_history_edit_home(h);
1630 						break;
1631 					}
1632 
1633 					// End.
1634 					case 'F':
1635 					case '4':
1636 					{
1637 						bc_history_edit_end(h);
1638 						break;
1639 					}
1640 
1641 					case 'd':
1642 					{
1643 						bc_history_edit_deleteNextWord(h);
1644 						break;
1645 					}
1646 				}
1647 			}
1648 		}
1649 		// ESC O sequences.
1650 		else
1651 		{
1652 			switch (seq[1])
1653 			{
1654 				case 'A':
1655 				{
1656 					bc_history_edit_next(h, BC_HIST_PREV);
1657 					break;
1658 				}
1659 
1660 				case 'B':
1661 				{
1662 					bc_history_edit_next(h, BC_HIST_NEXT);
1663 					break;
1664 				}
1665 
1666 				case 'C':
1667 				{
1668 					bc_history_edit_right(h);
1669 					break;
1670 				}
1671 
1672 				case 'D':
1673 				{
1674 					bc_history_edit_left(h);
1675 					break;
1676 				}
1677 
1678 				case 'F':
1679 				{
1680 					bc_history_edit_end(h);
1681 					break;
1682 				}
1683 
1684 				case 'H':
1685 				{
1686 					bc_history_edit_home(h);
1687 					break;
1688 				}
1689 			}
1690 		}
1691 	}
1692 }
1693 
1694 /**
1695  * Adds a line to the history.
1696  * @param h     The history data.
1697  * @param line  The line to add.
1698  */
1699 static void
1700 bc_history_add(BcHistory* h, char* line)
1701 {
1702 	BC_SIG_ASSERT_LOCKED;
1703 
1704 	// If there is something already there...
1705 	if (h->history.len)
1706 	{
1707 		// Get the previous.
1708 		char* s = *((char**) bc_vec_item_rev(&h->history, 0));
1709 
1710 		// Check for, and discard, duplicates.
1711 		if (!strcmp(s, line))
1712 		{
1713 			free(line);
1714 			return;
1715 		}
1716 	}
1717 
1718 	bc_vec_push(&h->history, &line);
1719 }
1720 
1721 /**
1722  * Adds an empty line to the history. This is separate from bc_history_add()
1723  * because we don't want it allocating.
1724  * @param h  The history data.
1725  */
1726 static void
1727 bc_history_add_empty(BcHistory* h)
1728 {
1729 	const char* line = "";
1730 
1731 	BC_SIG_ASSERT_LOCKED;
1732 
1733 	// If there is something already there...
1734 	if (h->history.len)
1735 	{
1736 		// Get the previous.
1737 		char* s = *((char**) bc_vec_item_rev(&h->history, 0));
1738 
1739 		// Check for, and discard, duplicates.
1740 		if (!s[0]) return;
1741 	}
1742 
1743 	bc_vec_push(&h->history, &line);
1744 }
1745 
1746 /**
1747  * Resets the history state to nothing.
1748  * @param h  The history data.
1749  */
1750 static void
1751 bc_history_reset(BcHistory* h)
1752 {
1753 	BC_SIG_ASSERT_LOCKED;
1754 
1755 	h->oldcolpos = h->pos = h->idx = 0;
1756 	h->cols = bc_history_columns();
1757 
1758 	// The latest history entry is always our current buffer, that
1759 	// initially is just an empty string.
1760 	bc_history_add_empty(h);
1761 
1762 	// Buffer starts empty.
1763 	bc_vec_empty(&h->buf);
1764 }
1765 
1766 /**
1767  * Prints a control character.
1768  * @param h  The history data.
1769  * @param c  The control character to print.
1770  */
1771 static void
1772 bc_history_printCtrl(BcHistory* h, unsigned int c)
1773 {
1774 	char str[3] = { '^', 'A', '\0' };
1775 	const char newline[2] = { '\n', '\0' };
1776 
1777 	BC_SIG_ASSERT_LOCKED;
1778 
1779 	// Set the correct character.
1780 	str[1] = (char) (c + 'A' - BC_ACTION_CTRL_A);
1781 
1782 	// Concatenate the string.
1783 	bc_vec_concat(&h->buf, str);
1784 
1785 	h->pos = BC_HIST_BUF_LEN(h);
1786 	bc_history_refresh(h);
1787 
1788 	// Pop the string.
1789 	bc_vec_npop(&h->buf, sizeof(str));
1790 	bc_vec_pushByte(&h->buf, '\0');
1791 	h->pos = 0;
1792 
1793 	if (c != BC_ACTION_CTRL_C && c != BC_ACTION_CTRL_D)
1794 	{
1795 		// We sometimes want to print a newline; for the times we don't; it's
1796 		// because newlines are taken care of elsewhere.
1797 		bc_file_write(&vm->fout, bc_flush_none, newline, sizeof(newline) - 1);
1798 		bc_history_refresh(h);
1799 	}
1800 }
1801 
1802 /**
1803  * Edits a line of history. This function is the core of the line editing
1804  * capability of bc history. It expects 'fd' to be already in "raw mode" so that
1805  * every key pressed will be returned ASAP to read().
1806  * @param h       The history data.
1807  * @param prompt  The prompt.
1808  * @return        BC_STATUS_SUCCESS or BC_STATUS_EOF.
1809  */
1810 static BcStatus
1811 bc_history_edit(BcHistory* h, const char* prompt)
1812 {
1813 	BC_SIG_LOCK;
1814 
1815 	bc_history_reset(h);
1816 
1817 	// Don't write the saved output the first time. This is because it has
1818 	// already been written to output. In other words, don't uncomment the
1819 	// line below or add anything like it.
1820 	// bc_file_write(&vm->fout, bc_flush_none, h->extras.v, h->extras.len - 1);
1821 
1822 	// Write the prompt if desired.
1823 	if (BC_PROMPT)
1824 	{
1825 		h->prompt = prompt;
1826 		h->plen = strlen(prompt);
1827 		h->pcol = bc_history_promptColLen(prompt, h->plen);
1828 
1829 		bc_file_write(&vm->fout, bc_flush_none, prompt, h->plen);
1830 		bc_file_flush(&vm->fout, bc_flush_none);
1831 	}
1832 
1833 	// This is the input loop.
1834 	for (;;)
1835 	{
1836 		BcStatus s;
1837 		char cbuf[32];
1838 		unsigned int c = 0;
1839 		size_t nread = 0;
1840 
1841 		BC_SIG_UNLOCK;
1842 
1843 		// Read a code.
1844 		s = bc_history_readCode(cbuf, sizeof(cbuf), &c, &nread);
1845 		if (BC_ERR(s)) return s;
1846 
1847 		BC_SIG_LOCK;
1848 
1849 		switch (c)
1850 		{
1851 			case BC_ACTION_LINE_FEED:
1852 			case BC_ACTION_ENTER:
1853 			{
1854 				// Return the line.
1855 				bc_vec_pop(&h->history);
1856 				BC_SIG_UNLOCK;
1857 				return s;
1858 			}
1859 
1860 			case BC_ACTION_TAB:
1861 			{
1862 				// My tab handling is dumb; it just prints 8 spaces every time.
1863 				memcpy(cbuf, bc_history_tab, bc_history_tab_len + 1);
1864 				bc_history_edit_insert(h, cbuf, bc_history_tab_len);
1865 				break;
1866 			}
1867 
1868 			case BC_ACTION_CTRL_C:
1869 			{
1870 				bc_history_printCtrl(h, c);
1871 
1872 				// Quit if the user wants it.
1873 				if (!BC_SIGINT)
1874 				{
1875 					vm->status = BC_STATUS_QUIT;
1876 					BC_SIG_UNLOCK;
1877 					BC_JMP;
1878 				}
1879 
1880 				// Print the ready message.
1881 				bc_file_write(&vm->fout, bc_flush_none, vm->sigmsg, vm->siglen);
1882 				bc_file_write(&vm->fout, bc_flush_none, bc_program_ready_msg,
1883 				              bc_program_ready_msg_len);
1884 				bc_history_reset(h);
1885 				bc_history_refresh(h);
1886 
1887 				break;
1888 			}
1889 
1890 			case BC_ACTION_BACKSPACE:
1891 			case BC_ACTION_CTRL_H:
1892 			{
1893 				bc_history_edit_backspace(h);
1894 				break;
1895 			}
1896 
1897 			// Act as end-of-file or delete-forward-char.
1898 			case BC_ACTION_CTRL_D:
1899 			{
1900 				// Act as EOF if there's no chacters, otherwise emulate Emacs
1901 				// delete next character to match historical gnu bc behavior.
1902 				if (BC_HIST_BUF_LEN(h) == 0)
1903 				{
1904 					bc_history_printCtrl(h, c);
1905 					BC_SIG_UNLOCK;
1906 					return BC_STATUS_EOF;
1907 				}
1908 
1909 				bc_history_edit_delete(h);
1910 
1911 				break;
1912 			}
1913 
1914 			// Swaps current character with previous.
1915 			case BC_ACTION_CTRL_T:
1916 			{
1917 				bc_history_swap(h);
1918 				break;
1919 			}
1920 
1921 			case BC_ACTION_CTRL_B:
1922 			{
1923 				bc_history_edit_left(h);
1924 				break;
1925 			}
1926 
1927 			case BC_ACTION_CTRL_F:
1928 			{
1929 				bc_history_edit_right(h);
1930 				break;
1931 			}
1932 
1933 			case BC_ACTION_CTRL_P:
1934 			{
1935 				bc_history_edit_next(h, BC_HIST_PREV);
1936 				break;
1937 			}
1938 
1939 			case BC_ACTION_CTRL_N:
1940 			{
1941 				bc_history_edit_next(h, BC_HIST_NEXT);
1942 				break;
1943 			}
1944 
1945 			case BC_ACTION_ESC:
1946 			{
1947 				bc_history_escape(h);
1948 				break;
1949 			}
1950 
1951 			// Delete the whole line.
1952 			case BC_ACTION_CTRL_U:
1953 			{
1954 				bc_vec_string(&h->buf, 0, "");
1955 				h->pos = 0;
1956 
1957 				bc_history_refresh(h);
1958 
1959 				break;
1960 			}
1961 
1962 			// Delete from current to end of line.
1963 			case BC_ACTION_CTRL_K:
1964 			{
1965 				bc_vec_npop(&h->buf, h->buf.len - h->pos);
1966 				bc_vec_pushByte(&h->buf, '\0');
1967 				bc_history_refresh(h);
1968 				break;
1969 			}
1970 
1971 			// Go to the start of the line.
1972 			case BC_ACTION_CTRL_A:
1973 			{
1974 				bc_history_edit_home(h);
1975 				break;
1976 			}
1977 
1978 			// Go to the end of the line.
1979 			case BC_ACTION_CTRL_E:
1980 			{
1981 				bc_history_edit_end(h);
1982 				break;
1983 			}
1984 
1985 			// Clear screen.
1986 			case BC_ACTION_CTRL_L:
1987 			{
1988 				bc_file_write(&vm->fout, bc_flush_none, "\x1b[H\x1b[2J", 7);
1989 				bc_history_refresh(h);
1990 				break;
1991 			}
1992 
1993 			// Delete previous word.
1994 			case BC_ACTION_CTRL_W:
1995 			{
1996 				bc_history_edit_deletePrevWord(h);
1997 				break;
1998 			}
1999 
2000 			default:
2001 			{
2002 				// If we have a control character, print it and raise signals as
2003 				// needed.
2004 				if ((c >= BC_ACTION_CTRL_A && c <= BC_ACTION_CTRL_Z) ||
2005 				    c == BC_ACTION_CTRL_BSLASH)
2006 				{
2007 					bc_history_printCtrl(h, c);
2008 #ifndef _WIN32
2009 					if (c == BC_ACTION_CTRL_Z) bc_history_raise(h, SIGTSTP);
2010 					if (c == BC_ACTION_CTRL_S) bc_history_raise(h, SIGSTOP);
2011 					if (c == BC_ACTION_CTRL_BSLASH)
2012 					{
2013 						bc_history_raise(h, SIGQUIT);
2014 					}
2015 #else // _WIN32
2016 					vm->status = BC_STATUS_QUIT;
2017 					BC_SIG_UNLOCK;
2018 					BC_JMP;
2019 #endif // _WIN32
2020 				}
2021 				// Otherwise, just insert.
2022 				else bc_history_edit_insert(h, cbuf, nread);
2023 				break;
2024 			}
2025 		}
2026 	}
2027 
2028 	BC_SIG_UNLOCK;
2029 
2030 	return BC_STATUS_SUCCESS;
2031 }
2032 
2033 /**
2034  * Returns true if stdin has more data. This is for multi-line pasting, and it
2035  * does not work on Windows.
2036  * @param h  The history data.
2037  */
2038 static inline bool
2039 bc_history_stdinHasData(BcHistory* h)
2040 {
2041 #ifndef _WIN32
2042 	int n;
2043 	return pselect(1, &h->rdset, NULL, NULL, &h->ts, &h->sigmask) > 0 ||
2044 	       (ioctl(STDIN_FILENO, FIONREAD, &n) >= 0 && n > 0);
2045 #else // _WIN32
2046 	return false;
2047 #endif // _WIN32
2048 }
2049 
2050 BcStatus
2051 bc_history_line(BcHistory* h, BcVec* vec, const char* prompt)
2052 {
2053 	BcStatus s;
2054 	char* line;
2055 
2056 	assert(vm->fout.len == 0);
2057 
2058 	bc_history_enableRaw(h);
2059 
2060 	do
2061 	{
2062 		// Do the edit.
2063 		s = bc_history_edit(h, prompt);
2064 
2065 		// Print a newline and flush.
2066 		bc_file_write(&vm->fout, bc_flush_none, "\n", 1);
2067 		bc_file_flush(&vm->fout, bc_flush_none);
2068 
2069 		BC_SIG_LOCK;
2070 
2071 		// If we actually have data...
2072 		if (h->buf.v[0])
2073 		{
2074 			// Duplicate it.
2075 			line = bc_vm_strdup(h->buf.v);
2076 
2077 			// Store it.
2078 			bc_history_add(h, line);
2079 		}
2080 		// Add an empty string.
2081 		else bc_history_add_empty(h);
2082 
2083 		BC_SIG_UNLOCK;
2084 
2085 		// Concatenate the line to the return vector.
2086 		bc_vec_concat(vec, h->buf.v);
2087 		bc_vec_concat(vec, "\n");
2088 	}
2089 	while (!s && bc_history_stdinHasData(h));
2090 
2091 	assert(!s || s == BC_STATUS_EOF);
2092 
2093 	bc_history_disableRaw(h);
2094 
2095 	return s;
2096 }
2097 
2098 void
2099 bc_history_string_free(void* str)
2100 {
2101 	char* s = *((char**) str);
2102 	BC_SIG_ASSERT_LOCKED;
2103 	if (s[0]) free(s);
2104 }
2105 
2106 void
2107 bc_history_init(BcHistory* h)
2108 {
2109 
2110 #ifdef _WIN32
2111 	HANDLE out, in;
2112 #endif // _WIN32
2113 
2114 	BC_SIG_ASSERT_LOCKED;
2115 
2116 	h->rawMode = false;
2117 	h->badTerm = bc_history_isBadTerm();
2118 
2119 	// Just don't initialize with a bad terminal.
2120 	if (h->badTerm) return;
2121 
2122 #ifdef _WIN32
2123 
2124 	h->orig_in = 0;
2125 	h->orig_out = 0;
2126 
2127 	in = GetStdHandle(STD_INPUT_HANDLE);
2128 	out = GetStdHandle(STD_OUTPUT_HANDLE);
2129 
2130 	// Set the code pages.
2131 	SetConsoleCP(CP_UTF8);
2132 	SetConsoleOutputCP(CP_UTF8);
2133 
2134 	// Get the original modes.
2135 	if (!GetConsoleMode(in, &h->orig_in) || !GetConsoleMode(out, &h->orig_out))
2136 	{
2137 		// Just mark it as a bad terminal on error.
2138 		h->badTerm = true;
2139 		return;
2140 	}
2141 	else
2142 	{
2143 		// Set the new modes.
2144 		DWORD reqOut = h->orig_out | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
2145 		DWORD reqIn = h->orig_in | ENABLE_VIRTUAL_TERMINAL_INPUT;
2146 
2147 		// The input handle requires turning *off* some modes. That's why
2148 		// history didn't work before; I didn't read the documentation
2149 		// closely enough to see that most modes were automaticall enabled,
2150 		// and they need to be turned off.
2151 		reqOut |= DISABLE_NEWLINE_AUTO_RETURN | ENABLE_PROCESSED_OUTPUT;
2152 		reqIn &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
2153 		reqIn &= ~(ENABLE_PROCESSED_INPUT);
2154 
2155 		// Set the modes; if there was an error, assume a bad terminal and
2156 		// quit.
2157 		if (!SetConsoleMode(in, reqIn) || !SetConsoleMode(out, reqOut))
2158 		{
2159 			h->badTerm = true;
2160 			return;
2161 		}
2162 	}
2163 #endif // _WIN32
2164 
2165 	bc_vec_init(&h->buf, sizeof(char), BC_DTOR_NONE);
2166 	bc_vec_init(&h->history, sizeof(char*), BC_DTOR_HISTORY_STRING);
2167 	bc_vec_init(&h->extras, sizeof(char), BC_DTOR_NONE);
2168 
2169 #ifndef _WIN32
2170 	FD_ZERO(&h->rdset);
2171 	FD_SET(STDIN_FILENO, &h->rdset);
2172 	h->ts.tv_sec = 0;
2173 	h->ts.tv_nsec = 0;
2174 
2175 	sigemptyset(&h->sigmask);
2176 	sigaddset(&h->sigmask, SIGINT);
2177 #endif // _WIN32
2178 }
2179 
2180 void
2181 bc_history_free(BcHistory* h)
2182 {
2183 	BC_SIG_ASSERT_LOCKED;
2184 #ifndef _WIN32
2185 	bc_history_disableRaw(h);
2186 #else // _WIN32
2187 	SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), h->orig_in);
2188 	SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), h->orig_out);
2189 #endif // _WIN32
2190 #if BC_DEBUG
2191 	bc_vec_free(&h->buf);
2192 	bc_vec_free(&h->history);
2193 	bc_vec_free(&h->extras);
2194 #endif // BC_DEBUG
2195 }
2196 
2197 #if BC_DEBUG_CODE
2198 
2199 /**
2200  * Prints scan codes. This special mode is used by bc history in order to print
2201  * scan codes on screen for debugging / development purposes.
2202  * @param h  The history data.
2203  */
2204 void
2205 bc_history_printKeyCodes(BcHistory* h)
2206 {
2207 	char quit[4];
2208 
2209 	bc_vm_printf("Linenoise key codes debugging mode.\n"
2210 	             "Press keys to see scan codes. "
2211 	             "Type 'quit' at any time to exit.\n");
2212 
2213 	bc_history_enableRaw(h);
2214 	memset(quit, ' ', 4);
2215 
2216 	while (true)
2217 	{
2218 		char c;
2219 		ssize_t nread;
2220 
2221 		nread = bc_history_read(&c, 1);
2222 		if (nread <= 0) continue;
2223 
2224 		// Shift string to left.
2225 		memmove(quit, quit + 1, sizeof(quit) - 1);
2226 
2227 		// Insert current char on the right.
2228 		quit[sizeof(quit) - 1] = c;
2229 		if (!memcmp(quit, "quit", sizeof(quit))) break;
2230 
2231 		bc_vm_printf("'%c' %lu (type quit to exit)\n", isprint(c) ? c : '?',
2232 		             (unsigned long) c);
2233 
2234 		// Go left edge manually, we are in raw mode.
2235 		bc_vm_putchar('\r', bc_flush_none);
2236 		bc_file_flush(&vm->fout, bc_flush_none);
2237 	}
2238 
2239 	bc_history_disableRaw(h);
2240 }
2241 #endif // BC_DEBUG_CODE
2242 
2243 #endif // BC_ENABLE_HISTORY
2244 
2245 #endif // BC_ENABLE_READLINE
2246 
2247 #endif // BC_ENABLE_EDITLINE
2248