diff options
author | msmith <msmith@FreeBSD.org> | 1997-06-25 08:14:24 +0000 |
---|---|---|
committer | msmith <msmith@FreeBSD.org> | 1997-06-25 08:14:24 +0000 |
commit | f4312c45dc5fb1b4831e63087e8563fa0fa4601f (patch) | |
tree | bfe4a6c5e19e7694273d28cb1b36a820a5ebad0d /lib | |
parent | d2cf9d630277a4d4f8601691fb1ac28b727e417e (diff) | |
download | FreeBSD-src-f4312c45dc5fb1b4831e63087e8563fa0fa4601f.zip FreeBSD-src-f4312c45dc5fb1b4831e63087e8563fa0fa4601f.tar.gz |
Update libedit with changes from NetBSD. Includes history load/save,
some buffer overflow guards and some stylistic cleanups.
Also adds manpages.
Obtained from: NetBSD
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libedit/Makefile | 25 | ||||
-rw-r--r-- | lib/libedit/common.c | 4 | ||||
-rw-r--r-- | lib/libedit/editline.3 | 532 | ||||
-rw-r--r-- | lib/libedit/editrc.5 | 292 | ||||
-rw-r--r-- | lib/libedit/el.c | 8 | ||||
-rw-r--r-- | lib/libedit/hist.h | 2 | ||||
-rw-r--r-- | lib/libedit/history.c | 165 | ||||
-rw-r--r-- | lib/libedit/map.c | 2 | ||||
-rw-r--r-- | lib/libedit/parse.c | 18 | ||||
-rw-r--r-- | lib/libedit/read.c | 13 | ||||
-rw-r--r-- | lib/libedit/refresh.c | 3 | ||||
-rw-r--r-- | lib/libedit/search.c | 59 | ||||
-rw-r--r-- | lib/libedit/sig.c | 4 | ||||
-rw-r--r-- | lib/libedit/sys.h | 7 | ||||
-rw-r--r-- | lib/libedit/term.c | 18 | ||||
-rw-r--r-- | lib/libedit/tty.c | 2 | ||||
-rw-r--r-- | lib/libedit/tty.h | 11 |
17 files changed, 1053 insertions, 112 deletions
diff --git a/lib/libedit/Makefile b/lib/libedit/Makefile index 5284c21..cbe5e1f 100644 --- a/lib/libedit/Makefile +++ b/lib/libedit/Makefile @@ -2,19 +2,31 @@ LIB= edit -OSRCS= chared.c common.c el.c emacs.c hist.c key.c map.c parse.c \ - prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c \ - help.c fcns.c help.h +OSRCS= chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \ + parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c LDADD+= -ltermcap DPADD+= ${LIBTERMCAP} +MAN3= editline.3 editrc.5 + +MLINKS= editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \ + editline.3 el_gets.3 editline.3 el_getc.3 editline.3 el_push.3 \ + editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_source.3 \ + editline.3 el_resize.3 editline.3 el_line.3 \ + editline.3 el_insertstr.3 editline.3 el_deletestr.3 \ + editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3 + + # For speed and debugging #SRCS= ${OSRCS} tokenizer.c history.c # For protection SRCS= editline.c tokenizer.c history.c -CLEANFILES+=common.h emacs.h fcns.h help.h vi.h help.c fcns.c editline.c +SRCS+= common.h emacs.h fcns.h help.h vi.h +HEADERS=histedit.h + +CLEANFILES+=common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h CFLAGS+=-I. -I${.CURDIR} CFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH CFLAGS+=#-DDEBUG_PASTE @@ -48,8 +60,11 @@ editline.c: ${OSRCS} .depend: vi.h emacs.h common.h fcns.h help.h help.c - test: test.o libedit.a ${DPADD} ${LIBTERMCAP} ${CC} ${CFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} +beforeinstall: + ${INSTALL} -C -o ${BINOWN} -g ${BINGRP} -m 444 \ + ${.CURDIR}/histedit.h ${DESTDIR}/usr/include + .include <bsd.lib.mk> diff --git a/lib/libedit/common.c b/lib/libedit/common.c index a321c52..6908819 100644 --- a/lib/libedit/common.c +++ b/lib/libedit/common.c @@ -651,9 +651,7 @@ ed_redisplay(el, c) EditLine *el; int c; { - re_clear_lines(el); - re_clear_display(el); - return CC_REFRESH; + return CC_REDISPLAY; } diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3 new file mode 100644 index 0000000..b2858f6 --- /dev/null +++ b/lib/libedit/editline.3 @@ -0,0 +1,532 @@ +.\" $NetBSD: editline.3,v 1.4 1997/01/14 04:17:23 lukem Exp $ +.\" +.\" Copyright (c) 1997 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This file was contributed to The NetBSD Foundation by Luke Mewburn. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd January 11, 1997 +.Os BSD 4.4 +.Dt EDITLINE 3 +.Sh NAME +.Nm editline , +.Nm el_init , +.Nm el_end , +.Nm el_reset , +.Nm el_gets , +.Nm el_getc , +.Nm el_push , +.Nm el_parse , +.Nm el_set , +.Nm el_source , +.Nm el_resize , +.Nm el_line , +.Nm el_insertstr , +.Nm el_deletestr , +.Nm history_init , +.Nm history_end , +.Nm history +.Nd line editor and history functions +.Sh SYNOPSIS +.Fd #include <histedit.h> +.Ft EditLine * +.Fn el_init "const char *prog" "FILE *fin" "FILE *fout" +.Ft void +.Fn el_end "EditLine *e" +.Ft void +.Fn el_reset "EditLine *e" +.Ft const char * +.Fn el_gets "EditLine *e" "int *count" +.Ft int +.Fn el_getc "EditLine *e" "char *ch" +.Ft void +.Fn el_push "EditLine *e" "const char *str" +.Ft int +.Fn el_parse "EditLine *e" "int argc" "char *argv[]" +.Ft int +.Fn el_set "EditLine *e" "int op" "..." +.Ft int +.Fn el_source "EditLine *e" "const char *file" +.Ft void +.Fn el_resize "EditLine *e" +.Ft const LineInfo * +.Fn el_line "EditLine *e" +.Ft int +.Fn el_insertstr "EditLine *e" "char *str" +.Ft void +.Fn el_deletestr "EditLine *e" "int count" +.Ft History * +.Fn history_init +.Ft void +.Fn history_end "History *h" +.Ft HistEvent * +.Fn history "History h" "int op" "..." +.Sh DESCRIPTION +The +.Nm +library provides generic line editing and history functions, +similar to those found in +.Xr sh 1 . +.Pp +These functions are available in the +.Nm libedit +library (which needs the +.Nm libtermcap +library). +Programs should be linked with +.Fl ledit ltermcap . +.Sh LINE EDITING FUNCTIONS +The line editing functions use a common data structure, +.Fa EditLine , +which is created by +.Fn el_init +and freed by +.Fn el_end . +.Pp +The following functions are available: +.Bl -tag -width 4n +.It Fn el_init +Initialise the line editor, and return a data structure +to be used by all other line editing functions. +.Fa prog +is the name of the invoking program, used when reading the +.Xr editrc 5 +file to determine which settings to use. +.Fa fin +and +.Fa fout +are the input and output streams (respectively) to use. +In this documentation, references to +.Dq the tty +are actually to this input/output stream combination. +.It Fn el_end +Clean up and finish with +.Fa e , +assumed to have been created with +.Fn el_init . +.It Fn el_reset +Reset the tty and the parser. +This should be called after an error which may have upset the tty's +state. +.It Fn el_gets +Read a line from the tty. +.Fa count +is modified to contain the number of characters read. +Returns the line read if successful, or +.Dv NULL +if no characters were read or if an error occurred. +.It Fn el_getc +Read a character from the tty. +.Fa ch +is modified to contain the character read. +Returns the number of characters read if successful, -1 otherwise. +.It Fn el_push +Pushes +.Fa str +back onto the input stream. +This is used by the macro expansion mechanism. +Refer to the description of +.Ic bind +.Fl s +in +.Xr editrc 5 +for more information. +.It Fn el_parse +Parses the +.Fa argv +array (which is +.Fa argc +elements in size) +to execute builtin +.Nm +commands. +If the command is prefixed with +.Dq prog: +then +.Fn el_parse +will only execute the command if +.Dq prog +matches the +.Fa prog +argument supplied to +.Fn el_init . +The return value is +-1 if the command is unknown, +0 if there was no error or +.Dq prog +didn't match, or +1 if the command returned an error. +Refer to +.Xr editrc 5 +for more information. +.Pp +.Em NOTE: +.Va argv[0] +may be modified by +.Fn el_parse . +The colon between +.Dq prog +and the command, +.Ar command , +will be replaced with a NUL +.Po +.Dq \e0 +.Pc . +.It Fn el_set +Set +.Nm +parameters. +.Fa op +determines which parameter to set, and each operation has its +own parameter list. +.Pp +The following values for +.Fa op +are supported, along with the required argument list: +.Bl -tag -width 4n +.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" +Define prompt printing function as +.Fa f , +which is to return a string that contains the prompt. +.It Dv EL_TERMINAL , Fa "const char *type" +Define terminal type of the tty to be +.Fa type , +or to +.Ev TERM +if +.Fa type +is +.Dv NULL . +.It Dv EL_EDITOR , Fa "const char *mode" +Set editing mode to +.Fa mode , +which must be one of +.Dq emacs +or +.Dq vi . +.It Dv EL_SIGNAL , Fa "int flag" +If +.Fa flag +is non-zero, +.Nm +will install its own signal handler for the following signals when +reading command input: +.Dv SIGCONT , +.Dv SIGHUP , +.Dv SIGINT , +.Dv SIGQUIT , +.Dv SIGSTOP , +.Dv SIGTERM , +.Dv SIGTSTP , +and +.Dv SIGWINCH . +Otherwise, the current signal handlers will be used. +.It Dv EL_BIND , Xo +.Fa "const char *" , +.Fa "..." , +.Dv NULL +.Xc +Perform the +.Ic bind +builtin command. +Refer to +.Xr editrc 5 +for more information. +.It Dv EL_ECHOTC , Xo +.Fa "const char *" , +.Fa "..." , +.Dv NULL +.Xc +Perform the +.Ic echotc +builtin command. +Refer to +.Xr editrc 5 +for more information. +.It Dv EL_SETTC , Xo +.Fa "const char *" , +.Fa "..." , +.Dv NULL +.Xc +Perform the +.Ic settc +builtin command. +Refer to +.Xr editrc 5 +for more information. +.It Dv EL_SETTY , Xo +.Fa "const char *" , +.Fa "..." , +.Dv NULL +.Xc +Perform the +.Ic setty +builtin command. +Refer to +.Xr editrc 5 +for more information. +.It Dv EL_TELLTC , Xo +.Fa "const char *" , +.Fa "..." , +.Dv NULL +.Xc +Perform the +.Ic telltc +builtin command. +Refer to +.Xr editrc 5 +for more information. +.It Dv EL_ADDFN , Xo +.Fa "const char *name" , +.Fa "const char *help" , +.Fa "unsigned char (*func)(EditLine *e, int ch) +.Xc +Add a user defined function, +.Fn func , +referred to as +.Fa name +which is invoked when a key which is bound to +.Fa name +is entered. +.Fa help +is a description of +.Fa name . +At invocation time, +.Fa ch +is the key which caused the invocation. +The return value of +.Fn func +should be one of: +.Bl -tag -width "CC_REDISPLAY" +.It Dv CC_NORM +Add a normal character. +.It Dv CC_NEWLINE +End of line was entered. +.It Dv CC_EOF +EOF was entered. +.It Dv CC_ARGHACK +Expecting further command input as arguments, do nothing visually. +.It Dv CC_REFRESH +Refresh display. +.It Dv CC_CURSOR +Cursor moved, so update and perform +.Dv CC_REFRESH. +.It Dv CC_REDISPLAY +Redisplay entire input line. +This is useful if a key binding outputs extra information. +.It Dv CC_ERROR +An error occurred. +Beep, and flush tty. +.It Dv CC_FATAL +Fatal error, reset tty to known state. +.El +.It Dv EL_HIST , Xo +.Fa "History *(*func)(History *, int op, ...)" , +.Fa "const char *ptr" +.Xc +Defines which history function to use, which is usually +.Fn history . +.Fa ptr +should be the value returned by +.Fn history_init . +.El +.It Fn el_source +Initialise +.Nm +by reading the contents of +.Fa file . +.Fn el_parse +is called for each line in +.Fa file . +If +.Fa file +is +.Dv NULL , +try +.Pa $PWD/.editrc +then +.Pa $HOME/.editrc . +Refer to +.Xr editrc 5 +for details on the format of +.Fa file . +.It Fn el_resize +Must be called if the terminal size changes. +If +.Dv EL_SIGNAL +has been set with +.Fn el_set , +then this is done automatically. +Otherwise, it's the responsibility of the application to call +.Fn el_resize +on the appropriate occasions. +.It Fn el_line +Return the editing information for the current line in a +.Fa LineInfo +structure, which is defined as follows: +.Bd -literal +typedef struct lineinfo { + const char *buffer; /* address of buffer */ + const char *cursor; /* address of cursor */ + const char *lastchar; /* address of last character */ +} LineInfo; +.Ed +.It Fn el_insertstr +Insert +.Fa str +into the line at the cursor. +Returns -1 if +.Fa str +is empty or won't fit, and 0 otherwise. +.It Fn el_deletestr +Delete +.Fa num +characters before the cursor. +.El +.Sh HISTORY LIST FUNCTIONS +The history functions use a common data structure, +.Fa History , +which is created by +.Fn history_init +and freed by +.Fn history_end . +.Pp +The following functions are available: +.Bl -tag -width 4n +.It Fn history_init +Initialise the history list, and return a data structure +to be used by all other history list functions. +.It Fn history_end +Clean up and finish with +.Fa h , +assumed to have been created with +.Fn history_init . +.It Fn history +Perform operation +.Fa op +on the history list, with optional arguments as needed by the +operation. +The following values for +.Fa op +are supported, along with the required argument list: +.Bl -tag -width 4n +.It Dv H_EVENT , Fa "int size" +Set size of history to +.Fa size +elements. +.It Dv H_END +Cleans up and finishes with +.Fa h , +assumed to be created with +.Fn history_init . +.It Dv H_CLEAR +Clear the history. +.It Dv H_FUNC , Xo +.Fa "void *ptr" , +.Fa "history_gfun_t first" , +.Fa "history_gfun_t next" , +.Fa "history_gfun_t last" , +.Fa "history_gfun_t prev" , +.Fa "history_gfun_t curr" , +.Fa "history_vfun_t clear" , +.Fa "history_efun_t enter" , +.Fa "history_efun_t add" +.Xc +Define functions to perform various history operations. +.Fa ptr +is the argument given to a function when it's invoked. +.It Dv H_FIRST +Return the first element in the history. +.It Dv H_LAST +Return the last element in the history. +.It Dv H_PREV +Return the previous element in the history. +.It Dv H_NEXT +Return the next element in the history. +.It Dv H_CURR +Return the current element in the history. +.It Dv H_ADD , Fa "const char *str" +Append +.Fa str +to the current element of the history, or create an element with +.Dv H_ENTER +if there isn't one. +.It Dv H_ENTER , Fa "const char *str" +Add +.Fa str +as a new element to the history, and, if necessary, +removing the oldest entry to keep the list to the created size. +.It Dv H_PREV_STR , Fa "const char *str" +Return the closest previous event that starts with +.Fa str . +.It Dv H_NEXT_STR , Fa "const char *str" +Return the closest next event that starts with +.Fa str . +.It Dv H_PREV_EVENT , Fa "int e" +Return the previous event numbered +.Fa e . +.It Dv H_NEXT_EVENT , Fa "int e" +Return the next event numbered +.Fa e . +.It Dv H_LOAD , Fa "const char *file" +Load the history list stored in +.Fa file . +.It Dv H_SAVE , Fa "const char *file" +Save the history list to +.Fa file . +.El +.El +.\"XXX.Sh EXAMPLES +.\"XXX: provide some examples +.Sh SEE ALSO +.Xr editrc 5 , +.Xr sh 1 , +.Xr signal 3 , +.Xr termcap 3 +.Sh HISTORY +The +.Nm +library first appeared in +.Bx 4.4 . +.Sh AUTHORS +The +.Nm +library was written by Christos Zoulas, +and this manual was written by Luke Mewburn. +.Sh BUGS +This documentation is probably incomplete. +.Pp +.Fn el_parse +should not modify the supplied +.Va argv[0] . +.Pp +The tokenization functions are not publically defined in +.Fd <histedit.h> diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5 new file mode 100644 index 0000000..e9b2992 --- /dev/null +++ b/lib/libedit/editrc.5 @@ -0,0 +1,292 @@ +.\" $NetBSD: editrc.5,v 1.4 1997/04/24 20:20:31 christos Exp $ +.\" +.\" Copyright (c) 1997 The NetBSD Foundation, Inc. +.\" All rights reserved. +.\" +.\" This file was contributed to The NetBSD Foundation by Luke Mewburn. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the NetBSD +.\" Foundation, Inc. and its contributors. +.\" 4. Neither the name of The NetBSD Foundation nor the names of its +.\" contributors may be used to endorse or promote products derived +.\" from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.Dd January 11, 1997 +.Os BSD 4.4 +.Dt EDITRC 5 +.Sh NAME +.Nm editrc +.Nd configuration file for editline library +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +The +.Nm +file defines various settings to be used by the +.Xr editline 3 +library. +.Pp +The format of each line is either: +.Dl prog:command [arg [...]] +or +.Dl command [arg [...]] +.Pp +.Ar command +is one of the +.Xr editline 3 +builtin commands. +Refer to +.Sx BUILTIN COMMANDS +for more information. +.Pp +.Ar prog +is the program name string that a program defines when it calls +.Xr el_init 3 +to setup +.Xr editline 3 , +which is usually +.Va argv[0] . +.Ar command +will be executed for any program which matches +.Ar prog . +.Pp +.Ar prog +may also be a +.Xr regex 3 +style +regular expression, in which case +.Ar command +will be executed for any program that matches the regular expression. +.Sh BUILTIN COMMANDS +The +.Nm editline +library has some builtin commands, which affect the way +that the line editing and history functions operate. +These are based on similar named builtins present in the +.Xr tcsh 1 +shell. +.Pp +The following builtin commands are available: +.Bl -tag -width 4n +.It Ic bind Xo +.Op Fl a +.Op Fl e +.Op Fl k +.Op Fl l +.Op Fl r +.Op Fl s +.Op Fl v +.Op Ar key Op Ar command +.Xc +Without options, list all bound keys, and the editor command to which +each is bound. +If +.Ar key +is supplied, show the bindings for +.Ar key . +If +.Ar key command +is supplied, bind +.Ar command +to +.Ar key . +Options include: +.Bl -tag -width 4n +.It Fl e +Bind all keys to the standard GNU Emacs-like bindings. +.It Fl v +Bind all keys to the standard +.Xr vi 1 -like +bindings. +.It Fl a +List or change key bindings in the +.Xr vi 1 +mode alternate (command mode) key map. +.It Fl k +.Ar key +is interpreted as a symbolic arrow key name, which may be one of +.Sq up , +.Sq down , +.Sq left +or +.Sq right . +.It Fl l +List all editor commands and a short description of each. +.It Fl r +Remove a key's binding. +.It Fl s +.Ar command +is taken as a literal string and treated as terminal input when +.Ar key +is typed. +Bound keys in +.Ar command +are themselves reinterpreted, and this continues for ten levels of +interpretation. +.El +.Pp +.Ar key +and +.Ar command +can contain control characters of the form +.Sm off +.Sq No ^ Ar character +.Sm on +.Po +e.g. +.Sq ^A +.Pc , +and the following backslashed escape sequences: +.Pp +.Bl -tag -compact -offset indent -width 4n +.It Ic \ea +Bell +.It Ic \eb +Backspace +.It Ic \ee +Escape +.It Ic \ef +Formfeed +.It Ic \en +Newline +.It Ic \er +Carriage return +.It Ic \et +Horizontal tab +.It Ic \ev +Vertical tab +.Sm off +.It Sy \e Ar nnn +.Sm on +The ASCII character corresponding to the octal number +.Ar nnn . +.El +.Pp +.Sq \e +nullifies the special meaning of the following character, +if it has any, notably +.Sq \e +and +.Sq ^ . +.It Ic echotc Xo +.Op Fl sv +.Ar arg +.Ar ... +.Xc +Exercise terminal capabilities given in +.Ar arg Ar ... . +If +.Ar arg +is +.Sq baud , +.Sq cols , +.Sq lines , +.Sq rows , +.Sq meta or +.Sq tabs , +the value of that capability is printed, with +.Dq yes +or +.Dq no +indicating that the terminal does or does not have that capability. +.Pp +.Fl s +returns an emptry string for non-existant capabilities, rather than +causing an error. +.Fl v +causes messages to be verbose. +.It Ic history +List the history. +.It Ic telltc +List the values of all the terminal capabilities (see +.Xr termcap 5 ). +.It Ic settc Ar cap Ar val +Set the terminal capability +.Ar cap +to +.Ar val , +as defined in +.Xr termcap 5 . +No sanity checking is done. +.It Ic setty Xo +.Op Fl a +.Op Fl d +.Op Fl q +.Op Fl x +.Op Ar +mode +.Op Ar -mode +.Op Ar mode +.Xc +Control which tty modes that +.Nm +won't allow the user to change. +.Fl d , +.Fl q +or +.Fl x +tells +.Ic setty +to act on the +.Sq edit , +.Sq quote +or +.Sq execute +set of tty modes respectively; defaulting to +.Fl x . +.Pp +Without other arguments, +.Ic setty +lists the modes in the chosen set which are fixed on +.Po +.Sq +mode +.Pc +or off +.Po +.Sq -mode +.Pc . +.Fl a +lists all tty modes in the chosen set regardless of the setting. +With +.Ar +mode , +.Ar -mode +or +.Ar mode , +fixes +.Ar mode +on or off or removes control of +.Ar mode +in the chosen set. +.El +.Sh SEE ALSO +.Xr editline 3 , +.Xr regex 3 , +.Xr termcap 5 +.Sh AUTHORS +The +.Nm editline +library was written by Christos Zoulas, +and this manual was written by Luke Mewburn, +with some sections inspired by +.Xr tcsh 1 . diff --git a/lib/libedit/el.c b/lib/libedit/el.c index 305a51d..f163ec8 100644 --- a/lib/libedit/el.c +++ b/lib/libedit/el.c @@ -301,12 +301,16 @@ el_source(el, fname) if ((fp = fopen(fname, "r")) == NULL) return -1; - while ((ptr = fgetln(fp, &len)) != NULL) - ptr[len - 1] = '\0'; + while ((ptr = fgetln(fp, &len)) != NULL) { + if (ptr[len - 1] == '\n') + --len; + ptr[len] = '\0'; + if (parse_line(el, ptr) == -1) { (void) fclose(fp); return -1; } + } (void) fclose(fp); return 0; diff --git a/lib/libedit/hist.h b/lib/libedit/hist.h index 90c0569..3f0fb9e 100644 --- a/lib/libedit/hist.h +++ b/lib/libedit/hist.h @@ -65,6 +65,8 @@ typedef struct el_history_t { #define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL) #define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL) #define HIST_EVENT(el, num) HIST_FUN(el, H_EVENT, num) +#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname) +#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname) protected int hist_init __P((EditLine *)); protected void hist_end __P((EditLine *)); diff --git a/lib/libedit/history.c b/lib/libedit/history.c index d60a7a9..ac9c3a9 100644 --- a/lib/libedit/history.c +++ b/lib/libedit/history.c @@ -51,10 +51,13 @@ static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #include <varargs.h> #endif +static const char hist_cookie[] = "_HiStOrY_V1_\n"; + #include "histedit.h" typedef const HistEvent * (*history_gfun_t) __P((ptr_t)); typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *)); +typedef void (*history_vfun_t) __P((ptr_t)); struct history { ptr_t h_ref; /* Argument for history fcns */ @@ -63,6 +66,7 @@ struct history { history_gfun_t h_last; /* Get the last element */ history_gfun_t h_prev; /* Get the previous element */ history_gfun_t h_curr; /* Get the current element */ + history_vfun_t h_clear; /* Clear the history list */ history_efun_t h_enter; /* Add an element */ history_efun_t h_add; /* Append to an element */ }; @@ -72,6 +76,7 @@ struct history { #define HPREV(h) (*(h)->h_prev)((h)->h_ref) #define HLAST(h) (*(h)->h_last)((h)->h_ref) #define HCURR(h) (*(h)->h_curr)((h)->h_ref) +#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref) #define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str) #define HADD(h, str) (*(h)->h_add)((h)->h_ref, str) @@ -80,13 +85,9 @@ struct history { private int history_set_num __P((History *, int)); -private int history_set_fun __P((History *, history_gfun_t, - history_gfun_t, - history_gfun_t, - history_gfun_t, - history_gfun_t, - history_efun_t, - history_efun_t, ptr_t)); +private int history_set_fun __P((History *, History *)); +private int history_load __P((History *, const char *)); +private int history_save __P((History *, const char *)); private const HistEvent *history_prev_event __P((History *, int)); private const HistEvent *history_next_event __P((History *, int)); private const HistEvent *history_next_string __P((History *, const char *)); @@ -120,7 +121,7 @@ private const HistEvent *history_def_curr __P((ptr_t)); private const HistEvent *history_def_enter __P((ptr_t, const char *)); private const HistEvent *history_def_add __P((ptr_t, const char *)); private void history_def_init __P((ptr_t *, int)); -private void history_def_end __P((ptr_t)); +private void history_def_clear __P((ptr_t)); private const HistEvent *history_def_insert __P((history_t *, const char *)); private void history_def_delete __P((history_t *, hentry_t *)); @@ -231,8 +232,8 @@ history_def_add(p, str) return (history_def_enter(p, str)); len = strlen(h->cursor->ev.str) + strlen(str) + 1; s = (char *) h_malloc(len); - (void) strcpy(s, h->cursor->ev.str); - (void) strcat(s, str); + (void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */ + (void)strcat(s, str); /* XXX strcat is safe */ h_free((ptr_t) h->cursor->ev.str); h->cursor->ev.str = s; return &h->cursor->ev; @@ -324,17 +325,19 @@ history_def_init(p, n) } -/* history_def_end(): +/* history_def_clear(): * Default history cleanup function */ private void -history_def_end(p) +history_def_clear(p) ptr_t p; { history_t *h = (history_t *) p; while (h->list.prev != &h->list) history_def_delete(h, h->list.prev); + h->eventno = 0; + h->cur = 0; } /************************************************************************/ @@ -354,6 +357,7 @@ history_init() h->h_last = history_def_last; h->h_prev = history_def_prev; h->h_curr = history_def_curr; + h->h_clear = history_def_clear; h->h_enter = history_def_enter; h->h_add = history_def_add; @@ -369,7 +373,7 @@ history_end(h) History *h; { if (h->h_next == history_def_next) - history_def_end(h->h_ref); + history_def_clear(h->h_ref); } @@ -393,16 +397,13 @@ history_set_num(h, num) * Set history functions */ private int -history_set_fun(h, first, next, last, prev, curr, enter, add, ptr) - History *h; - history_gfun_t first, next, last, prev, curr; - history_efun_t enter, add; - ptr_t ptr; +history_set_fun(h, nh) + History *h, *nh; { - if (first == NULL || next == NULL || - last == NULL || prev == NULL || curr == NULL || - enter == NULL || add == NULL || - ptr == NULL ) { + if (nh->h_first == NULL || nh->h_next == NULL || + nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL || + nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || + nh->h_ref == NULL) { if (h->h_next != history_def_next) { history_def_init(&h->h_ref, 0); h->h_first = history_def_first; @@ -410,6 +411,7 @@ history_set_fun(h, first, next, last, prev, curr, enter, add, ptr) h->h_last = history_def_last; h->h_prev = history_def_prev; h->h_curr = history_def_curr; + h->h_clear = history_def_clear; h->h_enter = history_def_enter; h->h_add = history_def_add; } @@ -417,16 +419,78 @@ history_set_fun(h, first, next, last, prev, curr, enter, add, ptr) } if (h->h_next == history_def_next) - history_def_end(h->h_ref); - - h->h_next = next; - h->h_first = first; - h->h_enter = enter; - h->h_add = add; + history_def_clear(h->h_ref); + + h->h_first = nh->h_first; + h->h_next = nh->h_next; + h->h_last = nh->h_last; + h->h_prev = nh->h_prev; + h->h_curr = nh->h_curr; + h->h_clear = nh->h_clear; + h->h_enter = nh->h_enter; + h->h_add = nh->h_add; return 0; } +/* history_load(): + * History load function + */ +private int +history_load(h, fname) + History *h; + const char *fname; +{ + FILE *fp; + char *line; + size_t sz; + int i = -1; + + if ((fp = fopen(fname, "r")) == NULL) + return i; + + if ((line = fgetln(fp, &sz)) == NULL) + goto done; + + if (strncmp(line, hist_cookie, sz) != 0) + goto done; + + for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { + char c = line[sz]; + line[sz] = '\0'; + HENTER(h, line); + line[sz] = c; + } + +done: + (void) fclose(fp); + return i; +} + + +/* history_save(): + * History save function + */ +private int +history_save(h, fname) + History *h; + const char *fname; +{ + FILE *fp; + const HistEvent *ev; + int i = 0; + + if ((fp = fopen(fname, "w")) == NULL) + return -1; + + (void) fputs(hist_cookie, fp); + for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++) + (void) fprintf(fp, "%s", ev->str); + (void) fclose(fp); + return i; +} + + /* history_prev_event(): * Find the previous event, with number given */ @@ -509,7 +573,7 @@ history(va_alist) va_list va; const HistEvent *ev = NULL; const char *str; - static const HistEvent sev = { 0, "" }; + static HistEvent sev = { 0, "" }; #if __STDC__ va_start(va, fun); @@ -552,6 +616,20 @@ history(va_alist) ev = HCURR(h); break; + case H_CLEAR: + HCLEAR(h); + break; + + case H_LOAD: + sev.num = history_load(h, va_arg(va, const char *)); + ev = &sev; + break; + + case H_SAVE: + sev.num = history_save(h, va_arg(va, const char *)); + ev = &sev; + break; + case H_PREV_EVENT: ev = history_prev_event(h, va_arg(va, int)); break; @@ -569,24 +647,29 @@ history(va_alist) break; case H_EVENT: - if (history_set_num(h, va_arg(va, int)) == 0) + if (history_set_num(h, va_arg(va, int)) == 0) { + sev.num = -1; ev = &sev; + } break; case H_FUNC: { - history_gfun_t first = va_arg(va, history_gfun_t); - history_gfun_t next = va_arg(va, history_gfun_t); - history_gfun_t last = va_arg(va, history_gfun_t); - history_gfun_t prev = va_arg(va, history_gfun_t); - history_gfun_t curr = va_arg(va, history_gfun_t); - history_efun_t enter = va_arg(va, history_efun_t); - history_efun_t add = va_arg(va, history_efun_t); - ptr_t ptr = va_arg(va, ptr_t); - - if (history_set_fun(h, first, next, last, prev, - curr, enter, add, ptr) == 0) + History hf; + hf.h_ref = va_arg(va, ptr_t); + hf.h_first = va_arg(va, history_gfun_t); + hf.h_next = va_arg(va, history_gfun_t); + hf.h_last = va_arg(va, history_gfun_t); + hf.h_prev = va_arg(va, history_gfun_t); + hf.h_curr = va_arg(va, history_gfun_t); + hf.h_clear = va_arg(va, history_vfun_t); + hf.h_enter = va_arg(va, history_efun_t); + hf.h_add = va_arg(va, history_efun_t); + + if (history_set_fun(h, &hf) == 0) { + sev.num = -1; ev = &sev; + } } break; diff --git a/lib/libedit/map.c b/lib/libedit/map.c index 5f91c75..3b282cc 100644 --- a/lib/libedit/map.c +++ b/lib/libedit/map.c @@ -1061,8 +1061,8 @@ map_init_emacs(el) map_init_nls(el); buf[0] = CONTROL('X'); - buf[2] = 0; buf[1] = CONTROL('X'); + buf[2] = 0; key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); tty_bind_char(el, 1); diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c index 5f648a1..751cc19 100644 --- a/lib/libedit/parse.c +++ b/lib/libedit/parse.c @@ -47,6 +47,9 @@ static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; * echotc * settc * gettc + * history + * settc + * setty */ #include "sys.h" #include "el.h" @@ -98,14 +101,11 @@ el_parse(el, argc, argv) int i; if (argc < 1) - return 0; - - for (ptr = argv[0]; *ptr && *ptr != ':'; ptr++) - continue; - - if (*ptr == ':') { - *ptr = '\0'; - if (el_match(el->el_prog, ptr)) + return -1; + ptr = strchr(argv[0], ':'); + if (ptr != NULL) { + *ptr++ = '\0'; + if (! el_match(el->el_prog, argv[0])) return 0; } else @@ -193,7 +193,7 @@ parse__escape(ptr) break; } } - else if (*p == '^' && isalpha((unsigned char) *p)) { + else if (*p == '^' && isalpha((unsigned char) p[1])) { p++; c = (*p == '?') ? '\177' : (*p & 0237); } diff --git a/lib/libedit/read.c b/lib/libedit/read.c index 05049e8..6475a25 100644 --- a/lib/libedit/read.c +++ b/lib/libedit/read.c @@ -86,13 +86,17 @@ read__fixio(fd, e) #ifdef EWOULDBLOCK case EWOULDBLOCK: -# define TRY_AGAIN +# ifndef TRY_AGAIN +# define TRY_AGAIN +# endif #endif /* EWOULDBLOCK */ #if defined(POSIX) && defined(EAGAIN) # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EAGAIN: -# define TRY_AGAIN +# ifndef TRY_AGAIN +# define TRY_AGAIN +# endif # endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ #endif /* POSIX && EAGAIN */ @@ -379,6 +383,11 @@ el_gets(el, nread) re_refresh_cursor(el); break; + case CC_REDISPLAY: + re_clear_lines(el); + re_clear_display(el); + /* FALLTHROUGH */ + case CC_REFRESH: el->el_state.argument = 1; el->el_state.doingarg = 0; diff --git a/lib/libedit/refresh.c b/lib/libedit/refresh.c index 6fc8a56..46dbe8b 100644 --- a/lib/libedit/refresh.c +++ b/lib/libedit/refresh.c @@ -43,6 +43,7 @@ static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; */ #include "sys.h" #include <stdio.h> +#include <ctype.h> #include <unistd.h> #include <string.h> @@ -865,7 +866,7 @@ re_refresh_cursor(el) EditLine *el; { char *cp; - int c; + int c; int h, v, th; /* first we must find where the cursor is... */ diff --git a/lib/libedit/search.c b/lib/libedit/search.c index bf6099d..508835e 100644 --- a/lib/libedit/search.c +++ b/lib/libedit/search.c @@ -43,14 +43,11 @@ static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; */ #include "sys.h" #include <stdlib.h> -#ifdef REGEXEC -#include <sys/types.h> +#if defined(REGEX) #include <regex.h> -#else -#ifdef REGEXP +#elif defined(REGEXP) #include <regexp.h> #endif -#endif #include "el.h" /* @@ -107,39 +104,41 @@ el_match(str, pat) const char *str; const char *pat; { -#ifdef REGEXEC +#if defined (REGEX) regex_t re; -#else -#ifndef REGEXP + int rv; +#elif defined (REGEXP) + regexp *rp; + int rv; +#else extern char *re_comp __P((const char *)); extern int re_exec __P((const char *)); -#else - regexp *re; - int rv; -#endif #endif if (strstr(str, pat) != NULL) return 1; -#ifdef REGEXEC - if (regcomp(&re, pat, REG_EXTENDED | REG_NOSUB) != 0) - return 0; - return (regexec(&re, str, 0, NULL, 0) == 0); -#else -#ifndef REGEXP - if (re_comp(pat) != NULL) - return 0; - else - return re_exec(str) == 1; -#else + +#if defined(REGEX) + if (regcomp(&re, pat, 0) == 0) { + rv = regexec(&re, str, 0, NULL, 0) == 0; + regfree(&re); + } else { + rv = 0; + } + return rv; +#elif defined(REGEXP) if ((re = regcomp(pat)) != NULL) { rv = regexec(re, str); free((ptr_t) re); - } - else + } else { rv = 0; + } return rv; -#endif +#else + if (re_comp(pat) != NULL) + return 0; + else + return re_exec(str) == 1; #endif } @@ -462,10 +461,11 @@ cv_search(el, dir) } #ifdef ANCHOR if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') { - (void) strcpy(tmpbuf, el->el_search.patbuf); + (void)strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) - 1); el->el_search.patbuf[0] = '.'; el->el_search.patbuf[1] = '*'; - (void) strcpy(&el->el_search.patbuf[2], tmpbuf); + (void)strncpy(&el->el_search.patbuf[2], tmpbuf, + sizeof(el->el_search.patbuf) - 3); el->el_search.patlen++; el->el_search.patbuf[el->el_search.patlen++] = '.'; el->el_search.patbuf[el->el_search.patlen++] = '*'; @@ -479,7 +479,8 @@ cv_search(el, dir) tmpbuf[tmplen++] = '*'; #endif tmpbuf[tmplen] = '\0'; - (void) strcpy(el->el_search.patbuf, tmpbuf); + (void)strncpy(el->el_search.patbuf, tmpbuf, + sizeof(el->el_search.patbuf) - 1); el->el_search.patlen = tmplen; } el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ diff --git a/lib/libedit/sig.c b/lib/libedit/sig.c index a16f5f1..d0a780a 100644 --- a/lib/libedit/sig.c +++ b/lib/libedit/sig.c @@ -121,7 +121,7 @@ sig_init(el) el->el_signal = (sig_t *) el_malloc(SIGSIZE); for (i = 0; sighdl[i] != -1; i++) - el->el_signal[i] = BADSIG; + el->el_signal[i] = SIG_ERR; (void) sigprocmask(SIG_SETMASK, &oset, NULL); @@ -185,7 +185,7 @@ sig_clr(el) (void) sigprocmask(SIG_BLOCK, &nset, &oset); for (i = 0; sighdl[i] != -1; i++) - if (el->el_signal[i] != BADSIG) + if (el->el_signal[i] != SIG_ERR) (void) signal(sighdl[i], el->el_signal[i]); sel = NULL; /* we are going to die if the handler is called */ diff --git a/lib/libedit/sys.h b/lib/libedit/sys.h index eccf30d..9e5fd0f 100644 --- a/lib/libedit/sys.h +++ b/lib/libedit/sys.h @@ -76,11 +76,12 @@ typedef char* ioctl_t; #endif #include <stdio.h> -#define REGEXEC -#undef REGEXP +#define REGEX /* Use POSIX.2 regular expression functions */ +#undef REGEXP /* Use UNIX V8 regular expression functions */ #ifdef SUNOS -# undef REGEXEC +# undef REGEX +# undef REGEXP # include <malloc.h> typedef void (*sig_t)__P((int)); # ifdef __GNUC__ diff --git a/lib/libedit/term.c b/lib/libedit/term.c index 6563f63..8de3027 100644 --- a/lib/libedit/term.c +++ b/lib/libedit/term.c @@ -294,7 +294,7 @@ term_alloc(el, t, cap) * New string is shorter; no need to allocate space */ if (clen <= tlen) { - (void) strcpy(*str, cap); + (void)strcpy(*str, cap); /* XXX strcpy is safe */ return; } @@ -302,7 +302,8 @@ term_alloc(el, t, cap) * New string is longer; see if we have enough space to append */ if (el->el_term.t_loc + 3 < TC_BUFSIZE) { - (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); + /* XXX strcpy is safe */ + (void)strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); el->el_term.t_loc += clen + 1; /* one for \0 */ return; } @@ -326,7 +327,8 @@ term_alloc(el, t, cap) (void) fprintf(el->el_errfile, "Out of termcap string space.\n"); return; } - (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); + /* XXX strcpy is safe */ + (void)strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); el->el_term.t_loc += clen + 1; /* one for \0 */ return; } /* end term_alloc */ @@ -766,14 +768,10 @@ term_set(el, term) if (i <= 0) { if (i == -1) -#ifdef __FreeBSD__ - (void) fprintf(el->el_errfile, "Cannot open /usr/share/misc/termcap.\n"); -#else - (void) fprintf(el->el_errfile, "Cannot open /etc/termcap.\n"); -#endif + (void) fprintf(el->el_errfile, "Cannot read termcap database;\n"); else if (i == 0) (void) fprintf(el->el_errfile, - "No entry for terminal type \"%s\"\n", term); + "No entry for terminal type \"%s\";\n", term); (void) fprintf(el->el_errfile, "using dumb terminal settings.\n"); Val(T_co) = 80; /* do a dumb terminal */ Val(T_pt) = Val(T_km) = Val(T_li) = 0; @@ -809,7 +807,7 @@ term_set(el, term) term_change_size(el, lins, cols); (void) sigprocmask(SIG_SETMASK, &oset, NULL); term_bind_arrow(el); - return 0; + return i <= 0 ? -1 : 0; } /* end term_set */ diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c index 6fdf5ea..961e340 100644 --- a/lib/libedit/tty.c +++ b/lib/libedit/tty.c @@ -47,7 +47,7 @@ static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; typedef struct ttymodes_t { char *m_name; - int m_value; + u_int m_value; int m_type; } ttymodes_t; diff --git a/lib/libedit/tty.h b/lib/libedit/tty.h index 14ba109..294c36a 100644 --- a/lib/libedit/tty.h +++ b/lib/libedit/tty.h @@ -145,7 +145,12 @@ # endif /* IEXTEN != 0 */ #endif /* convex || __convex__ */ - +/* + * So that we don't lose job control. + */ +#ifdef __SVR4 +# undef CSWTCH +#endif #ifndef _POSIX_VDISABLE # define _POSIX_VDISABLE ((unsigned char) -1) @@ -446,8 +451,8 @@ typedef struct { char *t_name; - int t_setmask; - int t_clrmask; + u_int t_setmask; + u_int t_clrmask; } ttyperm_t[NN_IO][M_NN]; typedef unsigned char ttychar_t[NN_IO][C_NCC]; |