]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libedit/read.c
Merge llvm-project release/15.x llvmorg-15.0.7-0-g8dfdcc7b7bf6
[FreeBSD/FreeBSD.git] / contrib / libedit / read.c
1 /*      $NetBSD: read.c,v 1.108 2022/10/30 19:11:31 christos Exp $      */
2
3 /*-
4  * Copyright (c) 1992, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell University.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)read.c      8.1 (Berkeley) 6/4/93";
39 #else
40 __RCSID("$NetBSD: read.c,v 1.108 2022/10/30 19:11:31 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
43
44 /*
45  * read.c: Terminal read functions
46  */
47 #include <ctype.h>
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <limits.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <unistd.h>
54
55 #include "el.h"
56 #include "fcns.h"
57 #include "read.h"
58
59 #define EL_MAXMACRO     10
60
61 struct macros {
62         wchar_t **macro;
63         int       level;
64         int       offset;
65 };
66
67 struct el_read_t {
68         struct macros    macros;
69         el_rfunc_t       read_char;     /* Function to read a character. */
70         int              read_errno;
71 };
72
73 static int      read__fixio(int, int);
74 static int      read_char(EditLine *, wchar_t *);
75 static int      read_getcmd(EditLine *, el_action_t *, wchar_t *);
76 static void     read_clearmacros(struct macros *);
77 static void     read_pop(struct macros *);
78 static const wchar_t *noedit_wgets(EditLine *, int *);
79
80 /* read_init():
81  *      Initialize the read stuff
82  */
83 libedit_private int
84 read_init(EditLine *el)
85 {
86         struct macros *ma;
87
88         if ((el->el_read = el_malloc(sizeof(*el->el_read))) == NULL)
89                 return -1;
90
91         ma = &el->el_read->macros;
92         if ((ma->macro = el_calloc(EL_MAXMACRO, sizeof(*ma->macro))) == NULL)
93                 goto out;
94         ma->level = -1;
95         ma->offset = 0;
96
97         /* builtin read_char */
98         el->el_read->read_char = read_char;
99         return 0;
100 out:
101         read_end(el);
102         return -1;
103 }
104
105 /* el_read_end():
106  *      Free the data structures used by the read stuff.
107  */
108 libedit_private void
109 read_end(EditLine *el)
110 {
111
112         read_clearmacros(&el->el_read->macros);
113         el_free(el->el_read->macros.macro);
114         el->el_read->macros.macro = NULL;
115         el_free(el->el_read);
116         el->el_read = NULL;
117 }
118
119 /* el_read_setfn():
120  *      Set the read char function to the one provided.
121  *      If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
122  */
123 libedit_private int
124 el_read_setfn(struct el_read_t *el_read, el_rfunc_t rc)
125 {
126         el_read->read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
127         return 0;
128 }
129
130
131 /* el_read_getfn():
132  *      return the current read char function, or EL_BUILTIN_GETCFN
133  *      if it is the default one
134  */
135 libedit_private el_rfunc_t
136 el_read_getfn(struct el_read_t *el_read)
137 {
138        return el_read->read_char == read_char ?
139             EL_BUILTIN_GETCFN : el_read->read_char;
140 }
141
142
143 /* read__fixio():
144  *      Try to recover from a read error
145  */
146 /* ARGSUSED */
147 static int
148 read__fixio(int fd __attribute__((__unused__)), int e)
149 {
150
151         switch (e) {
152         case -1:                /* Make sure that the code is reachable */
153
154 #ifdef EWOULDBLOCK
155         case EWOULDBLOCK:
156 #ifndef TRY_AGAIN
157 #define TRY_AGAIN
158 #endif
159 #endif /* EWOULDBLOCK */
160
161 #if defined(POSIX) && defined(EAGAIN)
162 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
163         case EAGAIN:
164 #ifndef TRY_AGAIN
165 #define TRY_AGAIN
166 #endif
167 #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
168 #endif /* POSIX && EAGAIN */
169
170                 e = 0;
171 #ifdef TRY_AGAIN
172 #if defined(F_SETFL) && defined(O_NDELAY)
173                 if ((e = fcntl(fd, F_GETFL, 0)) == -1)
174                         return -1;
175
176                 if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
177                         return -1;
178                 else
179                         e = 1;
180 #endif /* F_SETFL && O_NDELAY */
181
182 #ifdef FIONBIO
183                 {
184                         int zero = 0;
185
186                         if (ioctl(fd, FIONBIO, &zero) == -1)
187                                 return -1;
188                         else
189                                 e = 1;
190                 }
191 #endif /* FIONBIO */
192
193 #endif /* TRY_AGAIN */
194                 return e ? 0 : -1;
195
196         case EINTR:
197                 return 0;
198
199         default:
200                 return -1;
201         }
202 }
203
204
205 /* el_push():
206  *      Push a macro
207  */
208 void
209 el_wpush(EditLine *el, const wchar_t *str)
210 {
211         struct macros *ma = &el->el_read->macros;
212
213         if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
214                 ma->level++;
215                 if ((ma->macro[ma->level] = wcsdup(str)) != NULL)
216                         return;
217                 ma->level--;
218         }
219         terminal_beep(el);
220         terminal__flush(el);
221 }
222
223
224 /* read_getcmd():
225  *      Get next command from the input stream,
226  *      return 0 on success or -1 on EOF or error.
227  *      Character values > 255 are not looked up in the map, but inserted.
228  */
229 static int
230 read_getcmd(EditLine *el, el_action_t *cmdnum, wchar_t *ch)
231 {
232         static const wchar_t meta = (wchar_t)0x80;
233         el_action_t cmd;
234
235         do {
236                 if (el_wgetc(el, ch) != 1)
237                         return -1;
238
239 #ifdef  KANJI
240                 if ((*ch & meta)) {
241                         el->el_state.metanext = 0;
242                         cmd = CcViMap[' '];
243                         break;
244                 } else
245 #endif /* KANJI */
246
247                 if (el->el_state.metanext) {
248                         el->el_state.metanext = 0;
249                         *ch |= meta;
250                 }
251                 if (*ch >= N_KEYS)
252                         cmd = ED_INSERT;
253                 else
254                         cmd = el->el_map.current[(unsigned char) *ch];
255                 if (cmd == ED_SEQUENCE_LEAD_IN) {
256                         keymacro_value_t val;
257                         switch (keymacro_get(el, ch, &val)) {
258                         case XK_CMD:
259                                 cmd = val.cmd;
260                                 break;
261                         case XK_STR:
262                                 el_wpush(el, val.str);
263                                 break;
264                         case XK_NOD:
265                                 return -1;
266                         default:
267                                 EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
268                                 break;
269                         }
270                 }
271         } while (cmd == ED_SEQUENCE_LEAD_IN);
272         *cmdnum = cmd;
273         return 0;
274 }
275
276 /* read_char():
277  *      Read a character from the tty.
278  */
279 static int
280 read_char(EditLine *el, wchar_t *cp)
281 {
282         ssize_t num_read;
283         int tried = (el->el_flags & FIXIO) == 0;
284         char cbuf[MB_LEN_MAX];
285         size_t cbp = 0;
286         int save_errno = errno;
287
288  again:
289         el->el_signal->sig_no = 0;
290         while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) {
291                 int e = errno;
292                 switch (el->el_signal->sig_no) {
293                 case SIGCONT:
294                         el_wset(el, EL_REFRESH);
295                         /*FALLTHROUGH*/
296                 case SIGWINCH:
297                         sig_set(el);
298                         goto again;
299                 default:
300                         break;
301                 }
302                 if (!tried && read__fixio(el->el_infd, e) == 0) {
303                         errno = save_errno;
304                         tried = 1;
305                 } else {
306                         errno = e;
307                         *cp = L'\0';
308                         return -1;
309                 }
310         }
311
312         /* Test for EOF */
313         if (num_read == 0) {
314                 *cp = L'\0';
315                 return 0;
316         }
317
318         for (;;) {
319                 mbstate_t mbs;
320
321                 ++cbp;
322                 /* This only works because UTF8 is stateless. */
323                 memset(&mbs, 0, sizeof(mbs));
324                 switch (mbrtowc(cp, cbuf, cbp, &mbs)) {
325                 case (size_t)-1:
326                         if (cbp > 1) {
327                                 /*
328                                  * Invalid sequence, discard all bytes
329                                  * except the last one.
330                                  */
331                                 cbuf[0] = cbuf[cbp - 1];
332                                 cbp = 0;
333                                 break;
334                         } else {
335                                 /* Invalid byte, discard it. */
336                                 cbp = 0;
337                                 goto again;
338                         }
339                 case (size_t)-2:
340                         if (cbp >= MB_LEN_MAX) {
341                                 errno = EILSEQ;
342                                 *cp = L'\0';
343                                 return -1;
344                         }
345                         /* Incomplete sequence, read another byte. */
346                         goto again;
347                 default:
348                         /* Valid character, process it. */
349                         return 1;
350                 }
351         }
352 }
353
354 /* read_pop():
355  *      Pop a macro from the stack
356  */
357 static void
358 read_pop(struct macros *ma)
359 {
360         int i;
361
362         el_free(ma->macro[0]);
363         for (i = 0; i < ma->level; i++)
364                 ma->macro[i] = ma->macro[i + 1];
365         ma->level--;
366         ma->offset = 0;
367 }
368
369 static void
370 read_clearmacros(struct macros *ma)
371 {
372         while (ma->level >= 0)
373                 el_free(ma->macro[ma->level--]);
374         ma->offset = 0;
375 }
376
377 /* el_wgetc():
378  *      Read a wide character
379  */
380 int
381 el_wgetc(EditLine *el, wchar_t *cp)
382 {
383         struct macros *ma = &el->el_read->macros;
384         int num_read;
385
386         terminal__flush(el);
387         for (;;) {
388                 if (ma->level < 0)
389                         break;
390
391                 if (ma->macro[0][ma->offset] == '\0') {
392                         read_pop(ma);
393                         continue;
394                 }
395
396                 *cp = ma->macro[0][ma->offset++];
397
398                 if (ma->macro[0][ma->offset] == '\0') {
399                         /* Needed for QuoteMode On */
400                         read_pop(ma);
401                 }
402
403                 return 1;
404         }
405
406         if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
407                 return 0;
408
409         num_read = (*el->el_read->read_char)(el, cp);
410
411         /*
412          * Remember the original reason of a read failure
413          * such that el_wgets() can restore it after doing
414          * various cleanup operation that might change errno.
415          */
416         if (num_read < 0)
417                 el->el_read->read_errno = errno;
418
419         return num_read;
420 }
421
422 libedit_private void
423 read_prepare(EditLine *el)
424 {
425         if (el->el_flags & HANDLE_SIGNALS)
426                 sig_set(el);
427         if (el->el_flags & NO_TTY)
428                 return;
429         if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
430                 tty_rawmode(el);
431
432         /* This is relatively cheap, and things go terribly wrong if
433            we have the wrong size. */
434         el_resize(el);
435         re_clear_display(el);   /* reset the display stuff */
436         ch_reset(el);
437         re_refresh(el);         /* print the prompt */
438
439         if (el->el_flags & UNBUFFERED)
440                 terminal__flush(el);
441 }
442
443 libedit_private void
444 read_finish(EditLine *el)
445 {
446         if ((el->el_flags & UNBUFFERED) == 0)
447                 (void) tty_cookedmode(el);
448         if (el->el_flags & HANDLE_SIGNALS)
449                 sig_clr(el);
450 }
451
452 static const wchar_t *
453 noedit_wgets(EditLine *el, int *nread)
454 {
455         el_line_t       *lp = &el->el_line;
456         int              num;
457
458         while ((num = (*el->el_read->read_char)(el, lp->lastchar)) == 1) {
459                 if (lp->lastchar + 1 >= lp->limit &&
460                     !ch_enlargebufs(el, (size_t)2))
461                         break;
462                 lp->lastchar++;
463                 if (el->el_flags & UNBUFFERED ||
464                     lp->lastchar[-1] == '\r' ||
465                     lp->lastchar[-1] == '\n')
466                         break;
467         }
468         if (num == -1 && errno == EINTR)
469                 lp->lastchar = lp->buffer;
470         lp->cursor = lp->lastchar;
471         *lp->lastchar = '\0';
472         *nread = (int)(lp->lastchar - lp->buffer);
473         return *nread ? lp->buffer : NULL;
474 }
475
476 const wchar_t *
477 el_wgets(EditLine *el, int *nread)
478 {
479         int retval;
480         el_action_t cmdnum = 0;
481         int num;                /* how many chars we have read at NL */
482         wchar_t ch;
483         int nrb;
484
485         if (nread == NULL)
486                 nread = &nrb;
487         *nread = 0;
488         el->el_read->read_errno = 0;
489
490         if (el->el_flags & NO_TTY) {
491                 el->el_line.lastchar = el->el_line.buffer;
492                 return noedit_wgets(el, nread);
493         }
494
495 #ifdef FIONREAD
496         if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) {
497                 int chrs = 0;
498
499                 (void) ioctl(el->el_infd, FIONREAD, &chrs);
500                 if (chrs == 0) {
501                         if (tty_rawmode(el) < 0) {
502                                 errno = 0;
503                                 *nread = 0;
504                                 return NULL;
505                         }
506                 }
507         }
508 #endif /* FIONREAD */
509
510         if ((el->el_flags & UNBUFFERED) == 0)
511                 read_prepare(el);
512
513         if (el->el_flags & EDIT_DISABLED) {
514                 if ((el->el_flags & UNBUFFERED) == 0)
515                         el->el_line.lastchar = el->el_line.buffer;
516                 terminal__flush(el);
517                 return noedit_wgets(el, nread);
518         }
519
520         for (num = -1; num == -1;) {  /* while still editing this line */
521                 /* if EOF or error */
522                 if (read_getcmd(el, &cmdnum, &ch) == -1)
523                         break;
524                 if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */
525                         continue;       /* try again */
526                 /* now do the real command */
527                 /* vi redo needs these way down the levels... */
528                 el->el_state.thiscmd = cmdnum;
529                 el->el_state.thisch = ch;
530                 if (el->el_map.type == MAP_VI &&
531                     el->el_map.current == el->el_map.key &&
532                     el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
533                         if (cmdnum == VI_DELETE_PREV_CHAR &&
534                             el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
535                             && iswprint(el->el_chared.c_redo.pos[-1]))
536                                 el->el_chared.c_redo.pos--;
537                         else
538                                 *el->el_chared.c_redo.pos++ = ch;
539                 }
540                 retval = (*el->el_map.func[cmdnum]) (el, ch);
541
542                 /* save the last command here */
543                 el->el_state.lastcmd = cmdnum;
544
545                 /* use any return value */
546                 switch (retval) {
547                 case CC_CURSOR:
548                         re_refresh_cursor(el);
549                         break;
550
551                 case CC_REDISPLAY:
552                         re_clear_lines(el);
553                         re_clear_display(el);
554                         /* FALLTHROUGH */
555
556                 case CC_REFRESH:
557                         re_refresh(el);
558                         break;
559
560                 case CC_REFRESH_BEEP:
561                         re_refresh(el);
562                         terminal_beep(el);
563                         break;
564
565                 case CC_NORM:   /* normal char */
566                         break;
567
568                 case CC_ARGHACK:        /* Suggested by Rich Salz */
569                         /* <rsalz@pineapple.bbn.com> */
570                         continue;       /* keep going... */
571
572                 case CC_EOF:    /* end of file typed */
573                         if ((el->el_flags & UNBUFFERED) == 0)
574                                 num = 0;
575                         else if (num == -1) {
576                                 *el->el_line.lastchar++ = CONTROL('d');
577                                 el->el_line.cursor = el->el_line.lastchar;
578                                 num = 1;
579                         }
580                         break;
581
582                 case CC_NEWLINE:        /* normal end of line */
583                         num = (int)(el->el_line.lastchar - el->el_line.buffer);
584                         break;
585
586                 case CC_FATAL:  /* fatal error, reset to known state */
587                         /* put (real) cursor in a known place */
588                         re_clear_display(el);   /* reset the display stuff */
589                         ch_reset(el);   /* reset the input pointers */
590                         read_clearmacros(&el->el_read->macros);
591                         re_refresh(el); /* print the prompt again */
592                         break;
593
594                 case CC_ERROR:
595                 default:        /* functions we don't know about */
596                         terminal_beep(el);
597                         terminal__flush(el);
598                         break;
599                 }
600                 el->el_state.argument = 1;
601                 el->el_state.doingarg = 0;
602                 el->el_chared.c_vcmd.action = NOP;
603                 if (el->el_flags & UNBUFFERED)
604                         break;
605         }
606
607         terminal__flush(el);            /* flush any buffered output */
608         /* make sure the tty is set up correctly */
609         if ((el->el_flags & UNBUFFERED) == 0) {
610                 read_finish(el);
611                 *nread = num != -1 ? num : 0;
612         } else
613                 *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
614
615         if (*nread == 0) {
616                 if (num == -1) {
617                         *nread = -1;
618                         if (el->el_read->read_errno)
619                                 errno = el->el_read->read_errno;
620                 }
621                 return NULL;
622         } else
623                 return el->el_line.buffer;
624 }