History log of /src/lib/libedit/keymacro.c |
Revision | | Date | Author | Comments |
1.25 |
| 03-Jan-2025 |
rillig | libedit: remove redundant break statements after EL_ABORT
|
1.24 |
| 23-Jul-2019 |
christos | branches: 1.24.12; PR/54399: S�ren Tempel: Uninitialized memory access in libedit history. Initialize the buffer using calloc. While here change all malloc(a * sizeof(b)) to calloc(a, sizeof(b)). XXX: should fix realloc similarly.
|
1.23 |
| 24-May-2016 |
christos | branches: 1.23.16; From Ingo Schwarze:
Reduce obfuscation of errno handling. There is only one purpose non-local errno handling is needed for: Inside el_wgets(), several functions call down indirectly to el_wgetc(), many of them via the dispatch table. When el_wgetc() fails, it does properly report failure, but then various cleanup is done which may clobber errno. But when returning due to failure, el_wgets() wants to have errno set to the reason of the original read failure, not to the reason of some subsequent failure of some cleanup operation. So el_wgetc() needs to save errno, and if it's non-zero, el_wgets() needs to restore it on failure.
This core logic is currently obscured by the fact that el_errno is set and inspected at some additional places where it isn't needed. Besides, since el_wgetc() and and el_wgets() are both in read.c, el_errno does not need to be in struct editline, it can and should be local to read.c in struct el_read_t.
Let's look at what can be simplified.
1. keymacro_get() abuses el_errno instead of having a proper error return code. Adding that error return code is easy because node_trav() already detects the condition and an adequate code is already defined. Returning it, testing for it in read_getcmd(), and returning with error from there removes the need to inspect el_errno from el_wgets() after calling read_getcmd(). Note that resetting lastchar and cursor and clearing buffer[0] is irrelevant. The code returns from el_wgets() right afterwards. Outside el_wgets(), these variables are no longer relevant. When el_wgets() is called the next time, it will call ch_reset() anyway, resetting the two pointers. And as long as lastchar points to the beginning of the buffer, the contents of the buffer won't be used for anything.
2. read_getcmd() doesn't need to set el_errno again after el_wgetc() failure since el_wgetc() already did so. While here, remove the silly "if EOF or error" comments from the el_wgetc() return value tests. It's a public interface documented in a manual, so people working on the implementation can obviously be expected to know how it works. It's a case of
count++; /* Increment count. */
3. In the two code paths of el_wgets() that lead up to "goto noedit", there is no need to save the errno because nothing that might change it happens before returning.
For clarity, since el_wgets() is the function restoring the errno, also move initializing it to the same function.
Finally, note that restoring errno when the saved value is zero is wrong. No library code is ever allowed to clear a previously set value of errno. Only application programs are allowed to do that, and even they usually don't need to do so, except when using certain ill-designed interfaces like strtol(3).
I tested that the behaviour remains sane in the following cases, all during execution of el_wgets(3) and with a signal handler for USR1 installed without SA_RESTART.
* Enter some text and maybe move around a bit. Then send a USR1 signal. The signal gets processed, then read_char() resumes reading. Send another USR1 signal. Now el_wgets() sets errno=EINTR and returns -1.
* Press Ctrl-V to activate ed-quoted-insert. Then send a USR1 signal. The signal gets processed, then read_char() resumes reading. Send another USR1 signal. ed_quoted_insert() returns ed_end_of_file(), i.e. CC_EOF, and el_wgets() returns 0.
* Press a key starting a keyboard macro. Then send a USR1 signal. The signal gets processed, then read_char() resumes reading. Send another USR1 signal. Now el_wgets() sets errno=EINTR and returns -1.
* Press : to enter builtin command mode. Start typing a command. Then send a USR1 signal. The signal gets processed, then read_char() resumes reading. Send another USR1 signal. Now c_gets() returns -1, ed_command() beeps and returns CC_REFRESH, and el_wgets() resumes operation as it should.
I also tested with "el_set(el, EL_EDITMODE, 0)", and it returns the right value and sets errno correctly.
|
1.22 |
| 09-May-2016 |
christos | s/protected/libedit_private/g
|
1.21 |
| 18-Apr-2016 |
christos | From Ingo Schwarze: * Replace fcns.c by a shorter and simpler func.h and include it only in the one file needing it, map.c. * Combine help.h and help.c into a simplified help.h and include it only in the one file needing it, map.c. * Check the very simple, static files editline.c, historyn.c, and tokenizern.c into CVS rather than needlessly generating them. * So we no longer autogenerate any C files. :-) * Shorten and simplify makelist by deleting the options -n, -e, -bc, and -m; the latter was unused and useless in the first place. * Move the declaration of el_func_t from fcns.h to the header actually needing it, map.h. Since that header is already included by el.h for unrelated reasons, that makes el_func_t just as globally available as before. * No longer include the simplified fcns.h into el.h, include it directly into the *.c files needing it.
|
1.20 |
| 12-Apr-2016 |
christos | From Ingo Schwarze:
* Delete the stubs of the XK_EXE mechanism that was never implemented. From a security, stability, and simplicity perspective, i would consider implementing it a truly terrible idea, so let's better get rid of it.
* Do not use the local variable "num" in el_wgets() alternately for two completely different purposes. Only use it for the number of characters read, as stated in the comment (or -1 as long as that number is still unknown), not for the (more or less boolean) return value of read_getcmd(). Actually, there is no need at all to save the latter return value after testing it once.
* The function read_getcmd() has very unusual return values: It returns -1 for success and 0 for EOF/error. Switch that around to 0 for success and -1 for EOF/error to be less confusing, and get rid of the OKCMD preprocessor macro.
* Get rid of one #ifdef section in el_wgets() by using el->el_chared.c_macro directly at the only place where it is used.
* Delete the unused MIN() macro.
|
1.19 |
| 11-Apr-2016 |
christos | Get rid of private/public; keep protected (Ingo Schwarze)
|
1.18 |
| 11-Apr-2016 |
christos | Char -> wchar_t from Ingo Schwarze.
|
1.17 |
| 11-Apr-2016 |
christos | more macro WIDECHAR undoing from Ingo Schwarze.
|
1.16 |
| 09-Apr-2016 |
christos | More WIDECHAR elimination (Ingo Schwarze)
|
1.15 |
| 23-Mar-2016 |
christos | Start removing the WIDECHAR ifdefs; building without it has stopped working anyway. (Ingo Schwarze)
|
1.14 |
| 24-Feb-2016 |
christos | Get split el_getc and el_wgetc completely and call el_wgetc internally. Change some character constants to they wide versions. (Ingo Schwarze)
|
1.13 |
| 17-Feb-2016 |
christos | whitespace and header sorting changes (Ingo Schwarze). No functional changes.
|
1.12 |
| 16-Feb-2016 |
christos | From Ingo Scharze: Let "el.h" include everything needed for struct editline, and don't include that stuff multiple times. That also improves consistency, also avoids circular inclusions, and also makes it easier to follow what is going on, even though not quite as nice. But it seems like the best we can do...
|
1.11 |
| 16-Feb-2016 |
christos | cleanup chartype.h includes (Ingo Schwarze)
|
1.10 |
| 16-Feb-2016 |
christos | cleanup inclusion of histedit.h (Ingo Schwarze)
|
1.9 |
| 14-Feb-2016 |
christos | From Ingo Schwarze:
As we have seen before, "histedit.h" can never get rid of including the <wchar.h> header because using the data types defined there is deeply ingrained in the public interfaces of libedit.
Now POSIX unconditionally requires that <wchar.h> defines the type wint_t. Consequently, it can be used unconditionally, no matter whether WIDECHAR is active or not. Consequently, the #define Int is pointless.
Note that removing it is not gratuitious churn. Auditing for integer signedness problems is already hard when only fundamental types like "int" and "unsigned" are involved. It gets very hard when types come into the picture that have platform-dependent signedness, like "char" and "wint_t". Adding yet another layer on top, changing both the signedness and the width in a platform- dependent way, makes auditing yet harder, which IMHO is really dangerous. Note that while removing the #define, i already found one bug caused by this excessive complication - in the function re_putc() in refresh.c. If WIDECHAR was defined, it printed an Int = wint_t value with %c. Fortunately, that bug only affects debugging, not production. The fix is contained in the patch.
With WIDECHAR, this doesn't change anything. For the case without WIDECHAR, i checked that none of the places wants to store values that might not fit in wint_t.
This only changes internal interfaces; public ones remain unchanged.
|
1.8 |
| 11-Feb-2016 |
christos | - Add some more Char casts - reduce ifdefs by providing empty defs for nls functions (Ingo Schwarze)
|
1.7 |
| 16-Aug-2011 |
christos | re-enable -Wconversion
|
1.6 |
| 29-Jul-2011 |
christos | pass -Wconversion
|
1.5 |
| 29-Jul-2011 |
christos | KNF return (\1); -> return \1;
|
1.4 |
| 28-Jul-2011 |
christos | kill ptr_t and ioctl_t, add * sizeof(*foo) to all allocations.
|
1.3 |
| 28-Jul-2011 |
christos | whitespace
|
1.2 |
| 28-Jul-2011 |
christos | whitespace
|
1.1 |
| 28-Jul-2011 |
christos | Rename key to keymacro to avoid conflicts with term.h. The renaming of term to terminal was again to avoid conflicts with term.h. term.h is a moving namespace violation.
|
1.23.16.1 |
| 13-Apr-2020 |
martin | Mostly merge changes from HEAD upto 20200411
|
1.24.12.1 |
| 02-Aug-2025 |
perseant | Sync with HEAD
|