1 /* $NetBSD: read.c,v 1.51 2009/06/09 13:04:33 christos Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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
36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid
[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
40 __RCSID("$NetBSD: read.c,v 1.51 2009/06/09 13:04:33 christos Exp $");
42 #endif /* not lint && not SCCSID */
45 * read.c: Clean this junk up! This is horrible code.
46 * Terminal read functions
54 #define OKCMD -1 /* must be -1! */
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
*);
63 * Initialize the read stuff
66 read_init(EditLine
*el
)
68 /* builtin read_char */
69 el
->el_read
.read_char
= read_char
;
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.
79 el_read_setfn(EditLine
*el
, el_rfunc_t rc
)
81 el
->el_read
.read_char
= (rc
== EL_BUILTIN_GETCFN
) ? read_char
: rc
;
87 * return the current read char function, or EL_BUILTIN_GETCFN
88 * if it is the default one
91 el_read_getfn(EditLine
*el
)
93 return (el
->el_read
.read_char
== read_char
) ?
94 EL_BUILTIN_GETCFN
: el
->el_read
.read_char
;
99 #define MIN(A,B) ((A) < (B) ? (A) : (B))
104 read_debug(EditLine
*el
)
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");
118 #endif /* DEBUG_EDIT */
122 * Try to recover from a read error
126 read__fixio(int fd
__attribute__((__unused__
)), int e
)
130 case -1: /* Make sure that the code is reachable */
137 #endif /* EWOULDBLOCK */
139 #if defined(POSIX) && defined(EAGAIN)
140 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
145 #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
146 #endif /* POSIX && EAGAIN */
150 #if defined(F_SETFL) && defined(O_NDELAY)
151 if ((e
= fcntl(fd
, F_GETFL
, 0)) == -1)
154 if (fcntl(fd
, F_SETFL
, e
& ~O_NDELAY
) == -1)
158 #endif /* F_SETFL && O_NDELAY */
164 if (ioctl(fd
, FIONBIO
, (ioctl_t
) & zero
) == -1)
171 #endif /* TRY_AGAIN */
184 * Try to read the stuff in the input queue;
187 read_preread(EditLine
*el
)
191 if (el
->el_tty
.t_mode
== ED_IO
)
195 (void) ioctl(el
->el_infd
, FIONREAD
, (ioctl_t
) & chrs
);
199 chrs
= read(el
->el_infd
, buf
,
200 (size_t) MIN(chrs
, EL_BUFSIZ
- 1));
206 #endif /* FIONREAD */
216 el_push(EditLine
*el
, const char *str
)
218 c_macro_t
*ma
= &el
->el_chared
.c_macro
;
220 if (str
!= NULL
&& ma
->level
+ 1 < EL_MAXMACRO
) {
222 if ((ma
->macro
[ma
->level
] = el_strdup(str
)) != NULL
)
232 * Return next command from the input stream.
235 read_getcmd(EditLine
*el
, el_action_t
*cmdnum
, char *ch
)
242 if ((num
= el_getc(el
, ch
)) != 1) { /* if EOF or error */
243 el
->el_errno
= num
== 0 ? 0 : errno
;
249 el
->el_state
.metanext
= 0;
255 if (el
->el_state
.metanext
) {
256 el
->el_state
.metanext
= 0;
259 cmd
= el
->el_map
.current
[(unsigned char) *ch
];
260 if (cmd
== ED_SEQUENCE_LEAD_IN
) {
262 switch (key_get(el
, ch
, &val
)) {
267 el_push(el
, val
.str
);
271 /* XXX: In the future to run a user function */
276 EL_ABORT((el
->el_errfile
, "Bad XK_ type \n"));
280 if (el
->el_map
.alt
== NULL
)
281 el
->el_map
.current
= el
->el_map
.key
;
282 } while (cmd
== ED_SEQUENCE_LEAD_IN
);
289 * Read a character from the tty.
292 read_char(EditLine
*el
, char *cp
)
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
) {
302 el_set(el
, EL_REFRESH
);
305 if (!tried
&& read__fixio(el
->el_infd
, errno
) == 0)
312 return (int)num_read
;
316 * Pop a macro from the stack
319 read_pop(c_macro_t
*ma
)
323 el_free(ma
->macro
[0]);
324 for (i
= 0; i
< ma
->level
; i
++)
325 ma
->macro
[i
] = ma
->macro
[i
+ 1];
334 el_getc(EditLine
*el
, char *cp
)
337 c_macro_t
*ma
= &el
->el_chared
.c_macro
;
342 if (!read_preread(el
))
349 if (ma
->macro
[0][ma
->offset
] == '\0') {
354 *cp
= ma
->macro
[0][ma
->offset
++] & 0377;
356 if (ma
->macro
[0][ma
->offset
] == '\0') {
357 /* Needed for QuoteMode On */
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 */
371 (void) fprintf(el
->el_errfile
, "Reading a character\n");
372 #endif /* DEBUG_READ */
373 num_read
= (*el
->el_read
.read_char
)(el
, cp
);
375 (void) fprintf(el
->el_errfile
, "Got it %c\n", *cp
);
376 #endif /* DEBUG_READ */
381 read_prepare(EditLine
*el
)
383 if (el
->el_flags
& HANDLE_SIGNALS
)
385 if (el
->el_flags
& NO_TTY
)
387 if ((el
->el_flags
& (UNBUFFERED
|EDIT_DISABLED
)) == UNBUFFERED
)
390 /* This is relatively cheap, and things go terribly wrong if
391 we have the wrong size. */
393 re_clear_display(el
); /* reset the display stuff */
395 re_refresh(el
); /* print the prompt */
397 if (el
->el_flags
& UNBUFFERED
)
402 read_finish(EditLine
*el
)
404 if ((el
->el_flags
& UNBUFFERED
) == 0)
405 (void) tty_cookedmode(el
);
406 if (el
->el_flags
& HANDLE_SIGNALS
)
411 el_gets(EditLine
*el
, int *nread
)
414 el_action_t cmdnum
= 0;
415 int num
; /* how many chars we have read at NL */
420 c_macro_t
*ma
= &el
->el_chared
.c_macro
;
421 #endif /* FIONREAD */
427 if (el
->el_flags
& NO_TTY
) {
428 char *cp
= el
->el_line
.buffer
;
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))
437 cp
= &el
->el_line
.buffer
[idx
];
440 if (el
->el_flags
& UNBUFFERED
)
442 if (cp
[-1] == '\r' || cp
[-1] == '\n')
447 cp
= el
->el_line
.buffer
;
448 el
->el_errno
= errno
;
451 el
->el_line
.cursor
= el
->el_line
.lastchar
= cp
;
453 *nread
= (int)(el
->el_line
.cursor
- el
->el_line
.buffer
);
459 if (el
->el_tty
.t_mode
== EX_IO
&& ma
->level
< 0) {
462 (void) ioctl(el
->el_infd
, FIONREAD
, (ioctl_t
) & chrs
);
464 if (tty_rawmode(el
) < 0) {
471 #endif /* FIONREAD */
473 if ((el
->el_flags
& UNBUFFERED
) == 0)
476 if (el
->el_flags
& EDIT_DISABLED
) {
480 if ((el
->el_flags
& UNBUFFERED
) == 0)
481 cp
= el
->el_line
.buffer
;
483 cp
= el
->el_line
.lastchar
;
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))
493 cp
= &el
->el_line
.buffer
[idx
];
496 crlf
= cp
[-1] == '\r' || cp
[-1] == '\n';
497 if (el
->el_flags
& UNBUFFERED
)
505 cp
= el
->el_line
.buffer
;
506 el
->el_errno
= errno
;
509 el
->el_line
.cursor
= el
->el_line
.lastchar
= cp
;
514 for (num
= OKCMD
; num
== OKCMD
;) { /* while still editing this
518 #endif /* DEBUG_EDIT */
519 /* if EOF or error */
520 if ((num
= read_getcmd(el
, &cmdnum
, &ch
)) != OKCMD
) {
522 (void) fprintf(el
->el_errfile
,
523 "Returning from el_gets %d\n", num
);
524 #endif /* DEBUG_READ */
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
;
533 if ((unsigned int)cmdnum
>= (unsigned int)el
->el_map
.nfunc
) { /* BUG CHECK command */
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 */
540 /* now do the real command */
544 for (b
= el
->el_map
.help
; b
->name
; b
++)
545 if (b
->func
== cmdnum
)
548 (void) fprintf(el
->el_errfile
,
549 "Executing %s\n", b
->name
);
551 (void) fprintf(el
->el_errfile
,
552 "Error command = %d\n", cmdnum
);
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
--;
566 *el
->el_chared
.c_redo
.pos
++ = ch
;
568 retval
= (*el
->el_map
.func
[cmdnum
]) (el
, ch
);
570 (void) fprintf(el
->el_errfile
,
571 "Returned state %d\n", retval
);
572 #endif /* DEBUG_READ */
574 /* save the last command here */
575 el
->el_state
.lastcmd
= cmdnum
;
577 /* use any return value */
580 re_refresh_cursor(el
);
585 re_clear_display(el
);
592 case CC_REFRESH_BEEP
:
597 case CC_NORM
: /* normal char */
600 case CC_ARGHACK
: /* Suggested by Rich Salz */
601 /* <rsalz@pineapple.bbn.com> */
602 continue; /* keep going... */
604 case CC_EOF
: /* end of file typed */
605 if ((el
->el_flags
& UNBUFFERED
) == 0)
607 else if (num
== -1) {
608 *el
->el_line
.lastchar
++ = CONTROL('d');
609 el
->el_line
.cursor
= el
->el_line
.lastchar
;
614 case CC_NEWLINE
: /* normal end of line */
615 num
= (int)(el
->el_line
.lastchar
- el
->el_line
.buffer
);
618 case CC_FATAL
: /* fatal error, reset to known state */
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 */
630 default: /* functions we don't know about */
632 (void) fprintf(el
->el_errfile
,
633 "*** editor ERROR ***\r\n\n");
634 #endif /* DEBUG_READ */
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
)
646 term__flush(el
); /* flush any buffered output */
647 /* make sure the tty is set up correctly */
648 if ((el
->el_flags
& UNBUFFERED
) == 0) {
650 *nread
= num
!= -1 ? num
: 0;
652 *nread
= (int)(el
->el_line
.lastchar
- el
->el_line
.buffer
);
658 errno
= el
->el_errno
;
662 return el
->el_line
.buffer
;