"Initial commit to Gerrit"
[profile/ivi/libedit.git] / src / read.c
1 /*      $NetBSD: read.c,v 1.52 2009/07/22 15:57:00 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.52 2009/07/22 15:57:00 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
43
44 /*
45  * read.c: Clean this junk up! This is horrible code.
46  *         Terminal read functions
47  */
48 #include <errno.h>
49 #include <fcntl.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include "el.h"
53
54 #define OKCMD   -1      /* must be -1! */
55
56 private int     read__fixio(int, int);
57 private int     read_preread(EditLine *);
58 private int     read_char(EditLine *, char *);
59 private int     read_getcmd(EditLine *, el_action_t *, char *);
60 private void    read_pop(c_macro_t *);
61
62 /* read_init():
63  *      Initialize the read stuff
64  */
65 protected int
66 read_init(EditLine *el)
67 {
68         /* builtin read_char */
69         el->el_read.read_char = read_char;
70         return 0;
71 }
72
73
74 /* el_read_setfn():
75  *      Set the read char function to the one provided.
76  *      If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
77  */
78 protected int
79 el_read_setfn(EditLine *el, el_rfunc_t rc)
80 {
81         el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
82         return 0;
83 }
84
85
86 /* el_read_getfn():
87  *      return the current read char function, or EL_BUILTIN_GETCFN
88  *      if it is the default one
89  */
90 protected el_rfunc_t
91 el_read_getfn(EditLine *el)
92 {
93        return (el->el_read.read_char == read_char) ?
94             EL_BUILTIN_GETCFN : el->el_read.read_char;
95 }
96
97
98 #ifndef MIN
99 #define MIN(A,B) ((A) < (B) ? (A) : (B))
100 #endif
101
102 #ifdef DEBUG_EDIT
103 private void
104 read_debug(EditLine *el)
105 {
106
107         if (el->el_line.cursor > el->el_line.lastchar)
108                 (void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
109         if (el->el_line.cursor < el->el_line.buffer)
110                 (void) fprintf(el->el_errfile, "cursor < buffer\r\n");
111         if (el->el_line.cursor > el->el_line.limit)
112                 (void) fprintf(el->el_errfile, "cursor > limit\r\n");
113         if (el->el_line.lastchar > el->el_line.limit)
114                 (void) fprintf(el->el_errfile, "lastchar > limit\r\n");
115         if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
116                 (void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
117 }
118 #endif /* DEBUG_EDIT */
119
120
121 /* read__fixio():
122  *      Try to recover from a read error
123  */
124 /* ARGSUSED */
125 private int
126 read__fixio(int fd __attribute__((__unused__)), int e)
127 {
128
129         switch (e) {
130         case -1:                /* Make sure that the code is reachable */
131
132 #ifdef EWOULDBLOCK
133         case EWOULDBLOCK:
134 #ifndef TRY_AGAIN
135 #define TRY_AGAIN
136 #endif
137 #endif /* EWOULDBLOCK */
138
139 #if defined(POSIX) && defined(EAGAIN)
140 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
141         case EAGAIN:
142 #ifndef TRY_AGAIN
143 #define TRY_AGAIN
144 #endif
145 #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
146 #endif /* POSIX && EAGAIN */
147
148                 e = 0;
149 #ifdef TRY_AGAIN
150 #if defined(F_SETFL) && defined(O_NDELAY)
151                 if ((e = fcntl(fd, F_GETFL, 0)) == -1)
152                         return (-1);
153
154                 if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
155                         return (-1);
156                 else
157                         e = 1;
158 #endif /* F_SETFL && O_NDELAY */
159
160 #ifdef FIONBIO
161                 {
162                         int zero = 0;
163
164                         if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1)
165                                 return (-1);
166                         else
167                                 e = 1;
168                 }
169 #endif /* FIONBIO */
170
171 #endif /* TRY_AGAIN */
172                 return (e ? 0 : -1);
173
174         case EINTR:
175                 return (-1);
176
177         default:
178                 return (-1);
179         }
180 }
181
182
183 /* read_preread():
184  *      Try to read the stuff in the input queue;
185  */
186 private int
187 read_preread(EditLine *el)
188 {
189         int chrs = 0;
190
191         if (el->el_tty.t_mode == ED_IO)
192                 return (0);
193
194 #ifdef FIONREAD
195         (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
196         if (chrs > 0) {
197                 char buf[EL_BUFSIZ];
198
199                 chrs = read(el->el_infd, buf,
200                     (size_t) MIN(chrs, EL_BUFSIZ - 1));
201                 if (chrs > 0) {
202                         buf[chrs] = '\0';
203                         el_push(el, buf);
204                 }
205         }
206 #endif /* FIONREAD */
207
208         return (chrs > 0);
209 }
210
211
212 /* el_push():
213  *      Push a macro
214  */
215 public void
216 el_push(EditLine *el, const char *str)
217 {
218         c_macro_t *ma = &el->el_chared.c_macro;
219
220         if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
221                 ma->level++;
222                 if ((ma->macro[ma->level] = el_strdup(str)) != NULL)
223                         return;
224                 ma->level--;
225         }
226         term_beep(el);
227         term__flush(el);
228 }
229
230
231 /* read_getcmd():
232  *      Return next command from the input stream.
233  */
234 private int
235 read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
236 {
237         el_action_t cmd;
238         int num;
239
240         el->el_errno = 0;
241         do {
242                 if ((num = el_getc(el, ch)) != 1) {     /* if EOF or error */
243                         el->el_errno = num == 0 ? 0 : errno;
244                         return (num);
245                 }
246
247 #ifdef  KANJI
248                 if ((*ch & 0200)) {
249                         el->el_state.metanext = 0;
250                         cmd = CcViMap[' '];
251                         break;
252                 } else
253 #endif /* KANJI */
254
255                 if (el->el_state.metanext) {
256                         el->el_state.metanext = 0;
257                         *ch |= 0200;
258                 }
259                 cmd = el->el_map.current[(unsigned char) *ch];
260                 if (cmd == ED_SEQUENCE_LEAD_IN) {
261                         key_value_t val;
262                         switch (key_get(el, ch, &val)) {
263                         case XK_CMD:
264                                 cmd = val.cmd;
265                                 break;
266                         case XK_STR:
267                                 el_push(el, val.str);
268                                 break;
269 #ifdef notyet
270                         case XK_EXE:
271                                 /* XXX: In the future to run a user function */
272                                 RunCommand(val.str);
273                                 break;
274 #endif
275                         default:
276                                 EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
277                                 break;
278                         }
279                 }
280                 if (el->el_map.alt == NULL)
281                         el->el_map.current = el->el_map.key;
282         } while (cmd == ED_SEQUENCE_LEAD_IN);
283         *cmdnum = cmd;
284         return (OKCMD);
285 }
286
287
288 /* read_char():
289  *      Read a character from the tty.
290  */
291 private int
292 read_char(EditLine *el, char *cp)
293 {
294         ssize_t num_read;
295         int tried = 0;
296
297  again:
298         el->el_signal->sig_no = 0;
299         while ((num_read = read(el->el_infd, cp, 1)) == -1) {
300                 if (el->el_signal->sig_no == SIGCONT) {
301                         sig_set(el);
302                         el_set(el, EL_REFRESH);
303                         goto again;
304                 }
305                 if (!tried && read__fixio(el->el_infd, errno) == 0)
306                         tried = 1;
307                 else {
308                         *cp = '\0';
309                         return (-1);
310                 }
311         }
312         return (int)num_read;
313 }
314
315 /* read_pop():
316  *      Pop a macro from the stack
317  */
318 private void
319 read_pop(c_macro_t *ma)
320 {
321         int i;
322
323         el_free(ma->macro[0]);
324         for (i = 0; i < ma->level; i++)
325                 ma->macro[i] = ma->macro[i + 1];
326         ma->level--;
327         ma->offset = 0;
328 }
329
330 /* el_getc():
331  *      Read a character
332  */
333 public int
334 el_getc(EditLine *el, char *cp)
335 {
336         int num_read;
337         c_macro_t *ma = &el->el_chared.c_macro;
338
339         term__flush(el);
340         for (;;) {
341                 if (ma->level < 0) {
342                         if (!read_preread(el))
343                                 break;
344                 }
345
346                 if (ma->level < 0)
347                         break;
348
349                 if (ma->macro[0][ma->offset] == '\0') {
350                         read_pop(ma);
351                         continue;
352                 }
353
354                 *cp = ma->macro[0][ma->offset++] & 0377;
355
356                 if (ma->macro[0][ma->offset] == '\0') {
357                         /* Needed for QuoteMode On */
358                         read_pop(ma);
359                 }
360
361                 return (1);
362         }
363
364 #ifdef DEBUG_READ
365         (void) fprintf(el->el_errfile, "Turning raw mode on\n");
366 #endif /* DEBUG_READ */
367         if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
368                 return (0);
369
370 #ifdef DEBUG_READ
371         (void) fprintf(el->el_errfile, "Reading a character\n");
372 #endif /* DEBUG_READ */
373         num_read = (*el->el_read.read_char)(el, cp);
374 #ifdef DEBUG_READ
375         (void) fprintf(el->el_errfile, "Got it %c\n", *cp);
376 #endif /* DEBUG_READ */
377         return (num_read);
378 }
379
380 protected void
381 read_prepare(EditLine *el)
382 {
383         if (el->el_flags & HANDLE_SIGNALS)
384                 sig_set(el);
385         if (el->el_flags & NO_TTY)
386                 return;
387         if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
388                 tty_rawmode(el);
389
390         /* This is relatively cheap, and things go terribly wrong if
391            we have the wrong size. */
392         el_resize(el);
393         re_clear_display(el);   /* reset the display stuff */
394         ch_reset(el, 0);
395         re_refresh(el);         /* print the prompt */
396
397         if (el->el_flags & UNBUFFERED)
398                 term__flush(el);
399 }
400
401 protected void
402 read_finish(EditLine *el)
403 {
404         if ((el->el_flags & UNBUFFERED) == 0)
405                 (void) tty_cookedmode(el);
406         if (el->el_flags & HANDLE_SIGNALS)
407                 sig_clr(el);
408 }
409
410 public const char *
411 el_gets(EditLine *el, int *nread)
412 {
413         int retval;
414         el_action_t cmdnum = 0;
415         int num;                /* how many chars we have read at NL */
416         char ch;
417         int crlf = 0;
418         int nrb;
419 #ifdef FIONREAD
420         c_macro_t *ma = &el->el_chared.c_macro;
421 #endif /* FIONREAD */
422
423         if (nread == NULL)
424                 nread = &nrb;
425         *nread = 0;
426
427         if (el->el_flags & NO_TTY) {
428                 char *cp = el->el_line.buffer;
429                 size_t idx;
430
431                 while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
432                         /* make sure there is space for next character */
433                         if (cp + 1 >= el->el_line.limit) {
434                                 idx = (cp - el->el_line.buffer);
435                                 if (!ch_enlargebufs(el, 2))
436                                         break;
437                                 cp = &el->el_line.buffer[idx];
438                         }
439                         cp++;
440                         if (el->el_flags & UNBUFFERED)
441                                 break;
442                         if (cp[-1] == '\r' || cp[-1] == '\n')
443                                 break;
444                 }
445                 if (num == -1) {
446                         if (errno == EINTR)
447                                 cp = el->el_line.buffer;
448                         el->el_errno = errno;
449                 }
450
451                 el->el_line.cursor = el->el_line.lastchar = cp;
452                 *cp = '\0';
453                 *nread = (int)(el->el_line.cursor - el->el_line.buffer);
454                 goto done;
455         }
456
457
458 #ifdef FIONREAD
459         if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
460                 long chrs = 0;
461
462                 (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
463                 if (chrs == 0) {
464                         if (tty_rawmode(el) < 0) {
465                                 errno = 0;
466                                 *nread = 0;
467                                 return (NULL);
468                         }
469                 }
470         }
471 #endif /* FIONREAD */
472
473         if ((el->el_flags & UNBUFFERED) == 0)
474                 read_prepare(el);
475
476         if (el->el_flags & EDIT_DISABLED) {
477                 char *cp;
478                 size_t idx;
479
480                 if ((el->el_flags & UNBUFFERED) == 0)
481                         cp = el->el_line.buffer;
482                 else
483                         cp = el->el_line.lastchar;
484
485                 term__flush(el);
486
487                 while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
488                         /* make sure there is space next character */
489                         if (cp + 1 >= el->el_line.limit) {
490                                 idx = (cp - el->el_line.buffer);
491                                 if (!ch_enlargebufs(el, 2))
492                                         break;
493                                 cp = &el->el_line.buffer[idx];
494                         }
495                         cp++;
496                         crlf = cp[-1] == '\r' || cp[-1] == '\n';
497                         if (el->el_flags & UNBUFFERED)
498                                 break;
499                         if (crlf)
500                                 break;
501                 }
502
503                 if (num == -1) {
504                         if (errno == EINTR)
505                                 cp = el->el_line.buffer;
506                         el->el_errno = errno;
507                 }
508
509                 el->el_line.cursor = el->el_line.lastchar = cp;
510                 *cp = '\0';
511                 goto done;
512         }
513
514         for (num = OKCMD; num == OKCMD;) {      /* while still editing this
515                                                  * line */
516 #ifdef DEBUG_EDIT
517                 read_debug(el);
518 #endif /* DEBUG_EDIT */
519                 /* if EOF or error */
520                 if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
521 #ifdef DEBUG_READ
522                         (void) fprintf(el->el_errfile,
523                             "Returning from el_gets %d\n", num);
524 #endif /* DEBUG_READ */
525                         break;
526                 }
527                 if (el->el_errno == EINTR) {
528                         el->el_line.buffer[0] = '\0';
529                         el->el_line.lastchar =
530                             el->el_line.cursor = el->el_line.buffer;
531                         break;
532                 }
533                 if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) {   /* BUG CHECK command */
534 #ifdef DEBUG_EDIT
535                         (void) fprintf(el->el_errfile,
536                             "ERROR: illegal command from key 0%o\r\n", ch);
537 #endif /* DEBUG_EDIT */
538                         continue;       /* try again */
539                 }
540                 /* now do the real command */
541 #ifdef DEBUG_READ
542                 {
543                         el_bindings_t *b;
544                         for (b = el->el_map.help; b->name; b++)
545                                 if (b->func == cmdnum)
546                                         break;
547                         if (b->name)
548                                 (void) fprintf(el->el_errfile,
549                                     "Executing %s\n", b->name);
550                         else
551                                 (void) fprintf(el->el_errfile,
552                                     "Error command = %d\n", cmdnum);
553                 }
554 #endif /* DEBUG_READ */
555                 /* vi redo needs these way down the levels... */
556                 el->el_state.thiscmd = cmdnum;
557                 el->el_state.thisch = ch;
558                 if (el->el_map.type == MAP_VI &&
559                     el->el_map.current == el->el_map.key &&
560                     el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
561                         if (cmdnum == VI_DELETE_PREV_CHAR &&
562                             el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
563                             && isprint((unsigned char)el->el_chared.c_redo.pos[-1]))
564                                 el->el_chared.c_redo.pos--;
565                         else
566                                 *el->el_chared.c_redo.pos++ = ch;
567                 }
568                 retval = (*el->el_map.func[cmdnum]) (el, ch);
569 #ifdef DEBUG_READ
570                 (void) fprintf(el->el_errfile,
571                         "Returned state %d\n", retval );
572 #endif /* DEBUG_READ */
573
574                 /* save the last command here */
575                 el->el_state.lastcmd = cmdnum;
576
577                 /* use any return value */
578                 switch (retval) {
579                 case CC_CURSOR:
580                         re_refresh_cursor(el);
581                         break;
582
583                 case CC_REDISPLAY:
584                         re_clear_lines(el);
585                         re_clear_display(el);
586                         /* FALLTHROUGH */
587
588                 case CC_REFRESH:
589                         re_refresh(el);
590                         break;
591
592                 case CC_REFRESH_BEEP:
593                         re_refresh(el);
594                         term_beep(el);
595                         break;
596
597                 case CC_NORM:   /* normal char */
598                         break;
599
600                 case CC_ARGHACK:        /* Suggested by Rich Salz */
601                         /* <rsalz@pineapple.bbn.com> */
602                         continue;       /* keep going... */
603
604                 case CC_EOF:    /* end of file typed */
605                         if ((el->el_flags & UNBUFFERED) == 0)
606                                 num = 0;
607                         else if (num == -1) {
608                                 *el->el_line.lastchar++ = CONTROL('d');
609                                 el->el_line.cursor = el->el_line.lastchar;
610                                 num = 1;
611                         }
612                         break;
613
614                 case CC_NEWLINE:        /* normal end of line */
615                         num = (int)(el->el_line.lastchar - el->el_line.buffer);
616                         break;
617
618                 case CC_FATAL:  /* fatal error, reset to known state */
619 #ifdef DEBUG_READ
620                         (void) fprintf(el->el_errfile,
621                             "*** editor fatal ERROR ***\r\n\n");
622 #endif /* DEBUG_READ */
623                         /* put (real) cursor in a known place */
624                         re_clear_display(el);   /* reset the display stuff */
625                         ch_reset(el, 1);        /* reset the input pointers */
626                         re_refresh(el); /* print the prompt again */
627                         break;
628
629                 case CC_ERROR:
630                 default:        /* functions we don't know about */
631 #ifdef DEBUG_READ
632                         (void) fprintf(el->el_errfile,
633                             "*** editor ERROR ***\r\n\n");
634 #endif /* DEBUG_READ */
635                         term_beep(el);
636                         term__flush(el);
637                         break;
638                 }
639                 el->el_state.argument = 1;
640                 el->el_state.doingarg = 0;
641                 el->el_chared.c_vcmd.action = NOP;
642                 if (el->el_flags & UNBUFFERED)
643                         break;
644         }
645
646         term__flush(el);                /* flush any buffered output */
647         /* make sure the tty is set up correctly */
648         if ((el->el_flags & UNBUFFERED) == 0) {
649                 read_finish(el);
650                 *nread = num != -1 ? num : 0;
651         } else {
652                 *nread = (int)(el->el_line.lastchar - el->el_line.buffer);
653         }
654 done:
655         if (*nread == 0) {
656                 if (num == -1) {
657                         *nread = -1;
658                         errno = el->el_errno;
659                 }
660                 return NULL;
661         } else
662                 return el->el_line.buffer;
663 }