Index: head/lib/libedit/edit/readline =================================================================== --- head/lib/libedit/edit/readline (revision 295368) +++ head/lib/libedit/edit/readline (revision 295369) Property changes on: head/lib/libedit/edit/readline ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,33 ## Merged /projects/multi-fibv6/head/lib/libedit/edit/readline:r230929-231848 Merged /user/ngie/bug203673/lib/libedit/edit/readline:r289470-289489 Merged /user/delphij/zfs-arc-rebase/lib/libedit/edit/readline:r281754 Merged /projects/clang-sparc64/lib/libedit/edit/readline:r262258-262612 Merged /user/ngie/more-tests/lib/libedit/edit/readline:r281427-281428,281430,281432,281450,281460,281464-281465,281485,281489-281491,281515,281519,281589,281593-281597,281619,284388,288316,288321-288327,288422,288476,288478-288481,288483,288578,288650-288651,288655-288656,288659-288661,288663,288673-288676,288680,288828,288930-288932 Merged /projects/pf/head/lib/libedit/edit/readline:r263908 Merged /projects/clang-trunk/lib/libedit/edit/readline:r283596-287505 Merged /projects/building-blocks/lib/libedit/edit/readline:r275142-275143,275198,275297,275306-275307,275309,275311,275556,275558,275600,277445,277670,277673 Merged /projects/collation/lib/libedit/edit/readline:r286424-290491 Merged /projects/release-arm64/lib/libedit/edit/readline:r281786,281788,281792 Merged /projects/clang350-import/lib/libedit/edit/readline:r274961-275126,275128-275133,275135-276476 Merged /vendor/resolver/dist/lib/libedit/edit/readline:r1540-186085 Merged /projects/elftoolchain-update-r3130/lib/libedit/edit/readline:r276164,276167,276170-276172 Merged /projects/clang370-import/lib/libedit/edit/readline:r287506-288928 Merged /projects/quota64/lib/libedit/edit/readline:r184125-207707 Merged /projects/mpsutil/lib/libedit/edit/readline:r286179-290100 Merged /projects/elftoolchain/lib/libedit/edit/readline:r260687-261245 Merged /projects/zfsd/head/lib/libedit/edit/readline:r266519,269993 Merged /projects/ipfw/lib/libedit/edit/readline:r267383-272837 Merged /vendor/NetBSD/libedit/dist/edit/readline:r295360 Merged /user/ngie/more-tests2/lib/libedit/edit/readline:r288935-289179,289223-289224,289226-289227,289230,289236,289325,289437,289440,289484-289486,290904 Merged /projects/cxl_iscsi/lib/libedit/edit/readline:r291227-291228,292618 Merged /projects/release-embedded/lib/libedit/edit/readline:r262314,262504,262510-262511,262580,262660,262662,262700,262713,262774,262786-262788,262790-262792,262798,262802,262808 Merged /projects/largeSMP/lib/libedit/edit/readline:r221273-222812,222815-223757 Merged /vendor/NetBSD/libedit/dist/readline:r295360 Merged /projects/head_mfi/lib/libedit/edit/readline:r233621 Merged /projects/release-arm-redux/lib/libedit/edit/readline:r278203,278595-278597,278610,280643-280650,280652,280655,282539-282546,282548,282553-282557,282564,282566,282570,282573,282587-282593,282596-282607,282615-282616,282624-282629,282631,282633,282635-282640,282642,282647-282648,282653-282654,282656-282657,282659,282662-282667,282682,282691 Merged /projects/clang360-import/lib/libedit/edit/readline:r277327-280030 Merged /projects/lldb-r201577/lib/libedit/edit/readline:r262185-262527 Merged /projects/clang380-import/lib/libedit/edit/readline:r293006,293013 Merged /projects/pms/lib/libedit/edit/readline:r285199-285661 Merged /user/ngie/socket-tests/lib/libedit/edit/readline:r293882-293885,294103,294117,294119-294120,294245-294247,294488,294555,294643-294644 Merged /projects/random_number_generator/lib/libedit/edit/readline:r254613-256243 Index: head/lib/libedit/editline.3 =================================================================== --- head/lib/libedit/editline.3 (revision 295368) +++ head/lib/libedit/editline.3 (revision 295369) @@ -1,932 +1,939 @@ -.\" $NetBSD: editline.3,v 1.84 2014/12/25 13:39:41 wiz Exp $ +.\" $NetBSD: editline.3,v 1.85 2015/11/03 21:36:59 christos Exp $ .\" .\" Copyright (c) 1997-2014 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. .\" .\" 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 FOUNDATION 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. .\" .\" $FreeBSD$ .\" -.Dd December 25, 2014 +.Dd November 3, 2015 .Dt EDITLINE 3 .Os .Sh NAME .Nm editline , .Nm el_init , .Nm el_init_fd , .Nm el_end , .Nm el_reset , .Nm el_gets , .Nm el_wgets , .Nm el_getc , .Nm el_wgetc , .Nm el_push , .Nm el_wpush , .Nm el_parse , .Nm el_wparse , .Nm el_set , .Nm el_wset , .Nm el_get , .Nm el_wget , .Nm el_source , .Nm el_resize , .Nm el_cursor , .Nm el_line , .Nm el_wline , .Nm el_insertstr , .Nm el_winsertstr , .Nm el_deletestr , .Nm el_wdeletestr , .Nm history_init , .Nm history_winit , .Nm history_end , .Nm history_wend , .Nm history , .Nm history_w , .Nm tok_init , .Nm tok_winit , .Nm tok_end , .Nm tok_wend , .Nm tok_reset , .Nm tok_wreset , .Nm tok_line , .Nm tok_wline , .Nm tok_str .Nm tok_wstr .Nd line editor, history and tokenization functions .Sh LIBRARY .Lb libedit .Sh SYNOPSIS .In histedit.h .Ft EditLine * .Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr" .Ft EditLine * .Fn el_init_fd "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr" "int fdin" "int fdout" "int fderr" .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 const wchar_t * .Fn el_wgets "EditLine *e" "int *count" .Ft int .Fn el_getc "EditLine *e" "char *ch" .Ft int .Fn el_wgetc "EditLine *e" "wchar_t *ch" .Ft void .Fn el_push "EditLine *e" "const char *str" .Ft void .Fn el_wpush "EditLine *e" "const wchar_t *str" .Ft int .Fn el_parse "EditLine *e" "int argc" "const char *argv[]" .Ft int .Fn el_wparse "EditLine *e" "int argc" "const wchar_t *argv[]" .Ft int .Fn el_set "EditLine *e" "int op" "..." .Ft int .Fn el_wset "EditLine *e" "int op" "..." .Ft int .Fn el_get "EditLine *e" "int op" "..." .Ft int .Fn el_wget "EditLine *e" "int op" "..." .Ft int .Fn el_source "EditLine *e" "const char *file" .Ft void .Fn el_resize "EditLine *e" .Fn int .Fn el_cursor "EditLine *e" "int count" .Ft const LineInfo * .Fn el_line "EditLine *e" .Ft const LineInfoW * .Fn el_wline "EditLine *e" .Ft int .Fn el_insertstr "EditLine *e" "const char *str" .Ft int .Fn el_winsertstr "EditLine *e" "const wchar_t *str" .Ft void .Fn el_deletestr "EditLine *e" "int count" .Ft void .Fn el_wdeletestr "EditLine *e" "int count" .Ft History * .Fn history_init .Ft HistoryW * .Fn history_winit .Ft void .Fn history_end "History *h" .Ft void .Fn history_wend "HistoryW *h" .Ft int .Fn history "History *h" "HistEvent *ev" "int op" "..." .Ft int .Fn history_w "HistoryW *h" "HistEventW *ev" "int op" "..." .Ft Tokenizer * .Fn tok_init "const char *IFS" .Ft TokenizerW * .Fn tok_winit "const wchar_t *IFS" .Ft void .Fn tok_end "Tokenizer *t" .Ft void .Fn tok_wend "TokenizerW *t" .Ft void .Fn tok_reset "Tokenizer *t" .Ft void .Fn tok_wreset "TokenizerW *t" .Ft int .Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro" .Ft int .Fn tok_wline "TokenizerW *t" "const LineInfoW *li" "int *argc" "const wchar_t **argv[]" "int *cursorc" "int *cursoro" .Ft int .Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]" .Ft int .Fn tok_wstr "TokenizerW *t" "const wchar_t *str" "int *argc" "const wchar_t **argv[]" .Sh DESCRIPTION The .Nm library provides generic line editing, history and tokenization 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 or .Fn el_init_fd and freed by .Fn el_end . .Pp The wide-character functions behave the same way as their narrow counterparts. .Pp The following functions are available: .Bl -tag -width 4n .It Fn el_init -Initialise the line editor, and return a data structure +Initialize the line editor, and return a data structure to be used by all other line editing functions, or .Dv NULL on failure. .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 , .Fa fout and .Fa ferr are the input, output, and error streams (respectively) to use. In this documentation, references to .Dq the tty are actually to this input/output stream combination. .It Fn el_init_fd Like .Fn el_init but allows specifying file descriptors for the .Xr stdio 3 corresponding streams, in case those were created with .Xr funopen 3 . .It Fn el_end Clean up and finish with .Fa e , assumed to have been created with .Fn el_init or .Fn el_init_fd . .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. If an error occurred, .Fa count is set to \-1 and .Dv errno contains the error code that caused it. The return value may not remain valid across calls to .Fn el_gets and must be copied if the data is to be retained. .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, in which case .Dv errno can be inspected for the cause. .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. .It Fn el_set Set .Nm parameters. .Fa op determines which parameter to set, and each operation has its own parameter list. Returns 0 on success, \-1 on failure. .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_PROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c" Same as .Dv EL_PROMPT , but the .Fa c argument indicates the start/stop literal prompt character. .Pp If a start/stop literal character is found in the prompt, the character itself is not printed, but characters after it are printed directly to the terminal without affecting the state of the current line. A subsequent second start/stop literal character ends this behavior. This is typically used to embed literal escape sequences that change the color/style of the terminal in the prompt. .Dv 0 unsets it. .It Dv EL_REFRESH Re-display the current line on the next terminal line. .It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" Define right side prompt printing function as .Fa f , which is to return a string that contains the prompt. .It Dv EL_RPROMPT_ESC , Fa "char *(*f)(EditLine *)" , Fa "char c" Define the right prompt printing function but with a literal escape character. .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 , Fa "const char *" , Fa "..." , Dv NULL Perform the .Ic bind builtin command. Refer to .Xr editrc 5 for more information. .It Dv EL_ECHOTC , Fa "const char *" , Fa "..." , Dv NULL Perform the .Ic echotc builtin command. Refer to .Xr editrc 5 for more information. .It Dv EL_SETTC , Fa "const char *" , Fa "..." , Dv NULL Perform the .Ic settc builtin command. Refer to .Xr editrc 5 for more information. .It Dv EL_SETTY , Fa "const char *" , Fa "..." , Dv NULL Perform the .Ic setty builtin command. Refer to .Xr editrc 5 for more information. .It Dv EL_TELLTC , Fa "const char *" , Fa "..." , Dv NULL Perform the .Ic telltc builtin command. Refer to .Xr editrc 5 for more information. .It Dv EL_ADDFN , Fa "const char *name" , Fa "const char *help" , \ Fa "unsigned char (*func)(EditLine *e, int ch)" 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_REFRESH_BEEP Refresh display, and beep. .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 , Fa "History *(*func)(History *, int op, ...)" , \ Fa "const char *ptr" Defines which history function to use, which is usually .Fn history . .Fa ptr should be the value returned by .Fn history_init . .It Dv EL_EDITMODE , Fa "int flag" If .Fa flag is non-zero, editing is enabled (the default). Note that this is only an indication, and does not affect the operation of .Nm . At this time, it is the caller's responsibility to check this (using .Fn el_get ) to determine if editing should be enabled or not. .It Dv EL_UNBUFFERED , Fa "int flag" If .Fa flag is zero, unbuffered mode is disabled (the default). In unbuffered mode, .Fn el_gets will return immediately after processing a single character. .It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)" Define the character reading function as .Fa f , which is to return the number of characters read and store them in .Fa c . This function is called internally by .Fn el_gets and .Fn el_getc . The builtin function can be set or restored with the special function name .Dq Dv EL_BUILTIN_GETCFN . .It Dv EL_CLIENTDATA , Fa "void *data" Register .Fa data to be associated with this EditLine structure. It can be retrieved with the corresponding .Fn el_get call. .It Dv EL_SETFP , Fa "int fd" , Fa "FILE *fp" Set the current .Nm editline file pointer for .Dq input .Fa fd = .Dv 0 , .Dq output .Fa fd = .Dv 1 , or .Dq error .Fa fd = .Dv 2 from .Fa fp . .El .It Fn el_get Get .Nm parameters. .Fa op determines which parameter to retrieve into .Fa result . Returns 0 if successful, \-1 otherwise. .Pp The following values for .Fa op are supported, along with actual type of .Fa result : .Bl -tag -width 4n .It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" -Return a pointer to the function that displays the prompt in +Set .Fa f . +to a pointer to the function that displays the prompt. If .Fa c is not .Dv NULL , -return the start/stop literal prompt character in it. +set it to the start/stop literal prompt character. .It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c" -Return a pointer to the function that displays the prompt in +Set .Fa f . +to a pointer to the function that displays the prompt. If .Fa c is not .Dv NULL , -return the start/stop literal prompt character in it. -.It Dv EL_EDITOR , Fa "const char **" -Return the name of the editor, which will be one of +set it to the start/stop literal prompt character. +.It Dv EL_EDITOR , Fa "const char **n" +Set the name of the editor in +.Fa n , +which will be one of .Dq emacs or .Dq vi . .It Dv EL_GETTC , Fa "const char *name" , Fa "void *value" -Return non-zero if +If .Fa name is a valid .Xr termcap 5 -capability -and set +capability set .Fa value to the current value of that capability. -.It Dv EL_SIGNAL , Fa "int *" -Return non-zero if +.It Dv EL_SIGNAL , Fa "int *s" +Set +.Fa s +to non zero if .Nm has installed private signal handlers (see .Fn el_get above). -.It Dv EL_EDITMODE , Fa "int *" -Return non-zero if editing is enabled. +.It Dv EL_EDITMODE , Fa "int *c" +Set +.Fa c +to non-zero if editing is enabled. .It Dv EL_GETCFN , Fa "int (**f)(EditLine *, char *)" Return a pointer to the function that read characters, which is equal to .Dq Dv EL_BUILTIN_GETCFN in the case of the default builtin function. .It Dv EL_CLIENTDATA , Fa "void **data" -Retrieve +Set .Fa data -previously registered with the corresponding +to the previously registered client data set by an .Fn el_set call. -.It Dv EL_UNBUFFERED , Fa "int" -Return non-zero if unbuffered mode is enabled. -.It Dv EL_PREP_TERM , Fa "int" -Sets or clears terminal editing mode. +.It Dv EL_UNBUFFERED , Fa "int *c" +Set +.Fa c +to non-zero if unbuffered mode is enabled. .It Dv EL_GETFP , Fa "int fd", Fa "FILE **fp" -Return in +Set .Fa fp -the current +to the current .Nm editline file pointer for .Dq input .Fa fd = .Dv 0 , .Dq output .Fa fd = .Dv 1 , or .Dq error .Fa fd = .Dv 2 . .El .It Fn el_source -Initialise +Initialize .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 $HOME/.editrc . Refer to .Xr editrc 5 for details on the format of .Fa file . .Fn el_source returns 0 on success and \-1 on error. .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_cursor Move the cursor to the right (if positive) or to the left (if negative) .Fa count characters. Returns the resulting offset of the cursor from the beginning of the line. .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 .Pp .Fa buffer is not NUL terminated. This function may be called after .Fn el_gets to obtain the .Fa LineInfo structure pertaining to line returned by that function, and from within user defined functions added with .Dv EL_ADDFN . .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 count 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 +Initialize the history list, and return a data structure to be used by all other history list functions, or .Dv NULL on failure. .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. .Fa ev is changed accordingly to operation. The following values for .Fa op are supported, along with the required argument list: .Bl -tag -width 4n .It Dv H_SETSIZE , Fa "int size" Set size of history to .Fa size elements. .It Dv H_GETSIZE Get number of events currently in history. .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 , 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_sfun_t set" , Fa "history_vfun_t clear" , \ Fa "history_efun_t enter" , Fa "history_efun_t add" 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_SET Set the cursor to point to the requested element. .It Dv H_ADD , Fa "const char *str" Append .Fa str to the current element of the history, or perform the .Dv H_ENTER operation with argument .Fa str if there is no current element. .It Dv H_APPEND , Fa "const char *str" Append .Fa str to the last new element of the history. .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. If .Dv H_SETUNIQUE has been called with a non-zero argument, the element will not be entered into the history if its contents match the ones of the current history element. If the element is entered .Fn history returns 1; if it is ignored as a duplicate returns 0. Finally .Fn history returns \-1 if an error occurred. .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 . .It Dv H_SAVE_FP , Fa "FILE *fp" Save the history list to the opened .Ft FILE pointer .Fa fp . .It Dv H_SETUNIQUE , Fa "int unique" Set flag that adjacent identical event strings should not be entered into the history. .It Dv H_GETUNIQUE Retrieve the current setting if adjacent identical elements should be entered into the history. .It Dv H_DEL , Fa "int e" Delete the event numbered .Fa e . This function is only provided for .Xr readline 3 compatibility. The caller is responsible for free'ing the string in the returned .Fa HistEvent . .El .Pp .Fn history returns \*[Gt]= 0 if the operation .Fa op succeeds. Otherwise, \-1 is returned and .Fa ev is updated to contain more details about the error. .El .Sh TOKENIZATION FUNCTIONS The tokenization functions use a common data structure, .Fa Tokenizer , which is created by .Fn tok_init and freed by .Fn tok_end . .Pp The following functions are available: .Bl -tag -width 4n .It Fn tok_init -Initialise the tokenizer, and return a data structure +Initialize the tokenizer, and return a data structure to be used by all other tokenizer functions. .Fa IFS contains the Input Field Separators, which defaults to .Aq space , .Aq tab , and .Aq newline if .Dv NULL . .It Fn tok_end Clean up and finish with .Fa t , assumed to have been created with .Fn tok_init . .It Fn tok_reset Reset the tokenizer state. Use after a line has been successfully tokenized by .Fn tok_line or .Fn tok_str and before a new line is to be tokenized. .It Fn tok_line Tokenize .Fa li , If successful, modify: .Fa argv to contain the words, .Fa argc to contain the number of words, .Fa cursorc (if not .Dv NULL ) to contain the index of the word containing the cursor, and .Fa cursoro (if not .Dv NULL ) to contain the offset within .Fa argv[cursorc] of the cursor. .Pp Returns 0 if successful, \-1 for an internal error, 1 for an unmatched single quote, 2 for an unmatched double quote, and 3 for a backslash quoted .Aq newline . A positive exit code indicates that another line should be read and tokenization attempted again. . .It Fn tok_str A simpler form of .Fn tok_line ; .Fa str is a NUL terminated string to tokenize. .El . .\"XXX.Sh EXAMPLES .\"XXX: provide some examples .Sh SEE ALSO .Xr sh 1 , .Xr signal 3 , .Xr termcap 3 , .Xr editrc 5 , .Xr termcap 5 .Sh HISTORY The .Nm library first appeared in .Bx 4.4 . .Dv CC_REDISPLAY appeared in .Nx 1.3 . .Dv CC_REFRESH_BEEP , .Dv EL_EDITMODE and the readline emulation appeared in .Nx 1.4 . .Dv EL_RPROMPT appeared in .Nx 1.5 . .Sh AUTHORS .An -nosplit The .Nm library was written by .An Christos Zoulas . .An Luke Mewburn wrote this manual and implemented .Dv CC_REDISPLAY , .Dv CC_REFRESH_BEEP , .Dv EL_EDITMODE , and .Dv EL_RPROMPT . .An Jaromir Dolecek implemented the readline emulation. .An Johny Mattsson implemented wide-character support. .Sh BUGS At this time, it is the responsibility of the caller to check the result of the .Dv EL_EDITMODE operation of .Fn el_get (after an .Fn el_source or .Fn el_parse ) to determine if .Nm should be used for further input. I.e., .Dv EL_EDITMODE is purely an indication of the result of the most recent .Xr editrc 5 .Ic edit command. Index: head/lib/libedit/el.c =================================================================== --- head/lib/libedit/el.c (revision 295368) +++ head/lib/libedit/el.c (revision 295369) @@ -1,634 +1,635 @@ -/* $NetBSD: el.c,v 1.73 2014/06/18 18:12:28 christos Exp $ */ +/* $NetBSD: el.c,v 1.74 2015/12/08 12:56:55 christos Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * 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. Neither the name of the University 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 REGENTS 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. */ #include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -__RCSID("$NetBSD: el.c,v 1.73 2014/06/18 18:12:28 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.74 2015/12/08 12:56:55 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); /* * el.c: EditLine interface functions */ #include #include #include #include #include #include #include #include #include "el.h" /* el_init(): * Initialize editline and set default parameters. */ public EditLine * el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) { return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout), fileno(ferr)); } public EditLine * el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr, int fdin, int fdout, int fderr) { EditLine *el = el_malloc(sizeof(*el)); if (el == NULL) return NULL; memset(el, 0, sizeof(EditLine)); el->el_infile = fin; el->el_outfile = fout; el->el_errfile = ferr; el->el_infd = fdin; el->el_outfd = fdout; el->el_errfd = fderr; el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch)); if (el->el_prog == NULL) { el_free(el); return NULL; } /* * Initialize all the modules. Order is important!!! */ el->el_flags = 0; #ifdef WIDECHAR if (setlocale(LC_CTYPE, NULL) != NULL){ if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0) el->el_flags |= CHARSET_IS_UTF8; } #endif if (terminal_init(el) == -1) { el_free(el->el_prog); el_free(el); return NULL; } (void) keymacro_init(el); (void) map_init(el); if (tty_init(el) == -1) el->el_flags |= NO_TTY; (void) ch_init(el); (void) search_init(el); (void) hist_init(el); (void) prompt_init(el); (void) sig_init(el); (void) read_init(el); return el; } /* el_end(): * Clean up. */ public void el_end(EditLine *el) { if (el == NULL) return; el_reset(el); terminal_end(el); keymacro_end(el); map_end(el); - tty_end(el); + if (!(el->el_flags & NO_TTY)) + tty_end(el); ch_end(el); search_end(el); hist_end(el); prompt_end(el); sig_end(el); el_free(el->el_prog); #ifdef WIDECHAR el_free(el->el_scratch.cbuff); el_free(el->el_scratch.wbuff); el_free(el->el_lgcyconv.cbuff); el_free(el->el_lgcyconv.wbuff); #endif el_free(el); } /* el_reset(): * Reset the tty and the parser */ public void el_reset(EditLine *el) { tty_cookedmode(el); ch_reset(el, 0); /* XXX: Do we want that? */ } /* el_set(): * set the editline parameters */ public int FUN(el,set)(EditLine *el, int op, ...) { va_list ap; int rv = 0; if (el == NULL) return -1; va_start(ap, op); switch (op) { case EL_PROMPT: case EL_RPROMPT: { el_pfunc_t p = va_arg(ap, el_pfunc_t); rv = prompt_set(el, p, 0, op, 1); break; } case EL_RESIZE: { el_zfunc_t p = va_arg(ap, el_zfunc_t); void *arg = va_arg(ap, void *); rv = ch_resizefun(el, p, arg); break; } case EL_ALIAS_TEXT: { el_afunc_t p = va_arg(ap, el_afunc_t); void *arg = va_arg(ap, void *); rv = ch_aliasfun(el, p, arg); break; } case EL_PROMPT_ESC: case EL_RPROMPT_ESC: { el_pfunc_t p = va_arg(ap, el_pfunc_t); int c = va_arg(ap, int); rv = prompt_set(el, p, c, op, 1); break; } case EL_TERMINAL: rv = terminal_set(el, va_arg(ap, char *)); break; case EL_EDITOR: rv = map_set_editor(el, va_arg(ap, Char *)); break; case EL_SIGNAL: if (va_arg(ap, int)) el->el_flags |= HANDLE_SIGNALS; else el->el_flags &= ~HANDLE_SIGNALS; break; case EL_BIND: case EL_TELLTC: case EL_SETTC: case EL_ECHOTC: case EL_SETTY: { const Char *argv[20]; int i; for (i = 1; i < (int)__arraycount(argv); i++) if ((argv[i] = va_arg(ap, Char *)) == NULL) break; switch (op) { case EL_BIND: argv[0] = STR("bind"); rv = map_bind(el, i, argv); break; case EL_TELLTC: argv[0] = STR("telltc"); rv = terminal_telltc(el, i, argv); break; case EL_SETTC: argv[0] = STR("settc"); rv = terminal_settc(el, i, argv); break; case EL_ECHOTC: argv[0] = STR("echotc"); rv = terminal_echotc(el, i, argv); break; case EL_SETTY: argv[0] = STR("setty"); rv = tty_stty(el, i, argv); break; default: rv = -1; EL_ABORT((el->el_errfile, "Bad op %d\n", op)); break; } break; } case EL_ADDFN: { Char *name = va_arg(ap, Char *); Char *help = va_arg(ap, Char *); el_func_t func = va_arg(ap, el_func_t); rv = map_addfunc(el, name, help, func); break; } case EL_HIST: { hist_fun_t func = va_arg(ap, hist_fun_t); void *ptr = va_arg(ap, void *); rv = hist_set(el, func, ptr); if (!(el->el_flags & CHARSET_IS_UTF8)) el->el_flags &= ~NARROW_HISTORY; break; } case EL_EDITMODE: if (va_arg(ap, int)) el->el_flags &= ~EDIT_DISABLED; else el->el_flags |= EDIT_DISABLED; rv = 0; break; case EL_GETCFN: { el_rfunc_t rc = va_arg(ap, el_rfunc_t); rv = el_read_setfn(el, rc); el->el_flags &= ~NARROW_READ; break; } case EL_CLIENTDATA: el->el_data = va_arg(ap, void *); break; case EL_UNBUFFERED: rv = va_arg(ap, int); if (rv && !(el->el_flags & UNBUFFERED)) { el->el_flags |= UNBUFFERED; read_prepare(el); } else if (!rv && (el->el_flags & UNBUFFERED)) { el->el_flags &= ~UNBUFFERED; read_finish(el); } rv = 0; break; case EL_PREP_TERM: rv = va_arg(ap, int); if (rv) (void) tty_rawmode(el); else (void) tty_cookedmode(el); rv = 0; break; case EL_SETFP: { FILE *fp; int what; what = va_arg(ap, int); fp = va_arg(ap, FILE *); rv = 0; switch (what) { case 0: el->el_infile = fp; el->el_infd = fileno(fp); break; case 1: el->el_outfile = fp; el->el_outfd = fileno(fp); break; case 2: el->el_errfile = fp; el->el_errfd = fileno(fp); break; default: rv = -1; break; } break; } case EL_REFRESH: re_clear_display(el); re_refresh(el); terminal__flush(el); break; default: rv = -1; break; } va_end(ap); return rv; } /* el_get(): * retrieve the editline parameters */ public int FUN(el,get)(EditLine *el, int op, ...) { va_list ap; int rv; if (el == NULL) return -1; va_start(ap, op); switch (op) { case EL_PROMPT: case EL_RPROMPT: { el_pfunc_t *p = va_arg(ap, el_pfunc_t *); rv = prompt_get(el, p, 0, op); break; } case EL_PROMPT_ESC: case EL_RPROMPT_ESC: { el_pfunc_t *p = va_arg(ap, el_pfunc_t *); Char *c = va_arg(ap, Char *); rv = prompt_get(el, p, c, op); break; } case EL_EDITOR: rv = map_get_editor(el, va_arg(ap, const Char **)); break; case EL_SIGNAL: *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS); rv = 0; break; case EL_EDITMODE: *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED); rv = 0; break; case EL_TERMINAL: terminal_get(el, va_arg(ap, const char **)); rv = 0; break; case EL_GETTC: { static char name[] = "gettc"; char *argv[20]; int i; for (i = 1; i < (int)__arraycount(argv); i++) if ((argv[i] = va_arg(ap, char *)) == NULL) break; argv[0] = name; rv = terminal_gettc(el, i, argv); break; } case EL_GETCFN: *va_arg(ap, el_rfunc_t *) = el_read_getfn(el); rv = 0; break; case EL_CLIENTDATA: *va_arg(ap, void **) = el->el_data; rv = 0; break; case EL_UNBUFFERED: *va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0; rv = 0; break; case EL_GETFP: { int what; FILE **fpp; what = va_arg(ap, int); fpp = va_arg(ap, FILE **); rv = 0; switch (what) { case 0: *fpp = el->el_infile; break; case 1: *fpp = el->el_outfile; break; case 2: *fpp = el->el_errfile; break; default: rv = -1; break; } break; } default: rv = -1; break; } va_end(ap); return rv; } /* el_line(): * Return editing info */ public const TYPE(LineInfo) * FUN(el,line)(EditLine *el) { return (const TYPE(LineInfo) *)(void *)&el->el_line; } /* el_source(): * Source a file */ public int el_source(EditLine *el, const char *fname) { FILE *fp; size_t len; char *ptr; char *path = NULL; const Char *dptr; int error = 0; fp = NULL; if (fname == NULL) { #ifdef HAVE_ISSETUGID static const char elpath[] = "/.editrc"; size_t plen = sizeof(elpath); if (issetugid()) return -1; if ((ptr = getenv("HOME")) == NULL) return -1; plen += strlen(ptr); if ((path = el_malloc(plen * sizeof(*path))) == NULL) return -1; (void)snprintf(path, plen, "%s%s", ptr, elpath); fname = path; #else /* * If issetugid() is missing, always return an error, in order * to keep from inadvertently opening up the user to a security * hole. */ return -1; #endif } if (fp == NULL) fp = fopen(fname, "r"); if (fp == NULL) { el_free(path); return -1; } while ((ptr = fgetln(fp, &len)) != NULL) { if (*ptr == '\n') continue; /* Empty line. */ dptr = ct_decode_string(ptr, &el->el_scratch); if (!dptr) continue; if (len > 0 && dptr[len - 1] == '\n') --len; /* loop until first non-space char or EOL */ while (*dptr != '\0' && Isspace(*dptr)) dptr++; if (*dptr == '#') continue; /* ignore, this is a comment line */ if ((error = parse_line(el, dptr)) == -1) break; } el_free(path); (void) fclose(fp); return error; } /* el_resize(): * Called from program when terminal is resized */ public void el_resize(EditLine *el) { int lins, cols; sigset_t oset, nset; (void) sigemptyset(&nset); (void) sigaddset(&nset, SIGWINCH); (void) sigprocmask(SIG_BLOCK, &nset, &oset); /* get the correct window size */ if (terminal_get_size(el, &lins, &cols)) terminal_change_size(el, lins, cols); (void) sigprocmask(SIG_SETMASK, &oset, NULL); } /* el_beep(): * Called from the program to beep */ public void el_beep(EditLine *el) { terminal_beep(el); } /* el_editmode() * Set the state of EDIT_DISABLED from the `edit' command. */ protected int /*ARGSUSED*/ el_editmode(EditLine *el, int argc, const Char **argv) { const Char *how; if (argv == NULL || argc != 2 || argv[1] == NULL) return -1; how = argv[1]; if (Strcmp(how, STR("on")) == 0) { el->el_flags &= ~EDIT_DISABLED; tty_rawmode(el); } else if (Strcmp(how, STR("off")) == 0) { tty_cookedmode(el); el->el_flags |= EDIT_DISABLED; } else { (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n", how); return -1; } return 0; } Index: head/lib/libedit/hist.h =================================================================== --- head/lib/libedit/hist.h (revision 295368) +++ head/lib/libedit/hist.h (revision 295369) @@ -1,89 +1,89 @@ -/* $NetBSD: hist.h,v 1.14 2014/05/11 01:05:17 christos Exp $ */ +/* $NetBSD: hist.h,v 1.15 2016/01/30 15:05:27 christos Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * 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. Neither the name of the University 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 REGENTS 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. * * @(#)hist.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * el.hist.c: History functions */ #ifndef _h_el_hist #define _h_el_hist #include "histedit.h" typedef int (*hist_fun_t)(void *, TYPE(HistEvent) *, int, ...); typedef struct el_history_t { Char *buf; /* The history buffer */ - size_t sz; /* Size of history buffer */ + size_t sz; /* Size of history buffer */ Char *last; /* The last character */ int eventno; /* Event we are looking for */ - void * ref; /* Argument for history fcns */ + void *ref; /* Argument for history fcns */ hist_fun_t fun; /* Event access */ TYPE(HistEvent) ev; /* Event cookie */ } el_history_t; #define HIST_FUN_INTERNAL(el, fn, arg) \ ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \ fn, arg)) == -1) ? NULL : (el)->el_history.ev.str) #ifdef WIDECHAR #define HIST_FUN(el, fn, arg) \ (((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \ HIST_FUN_INTERNAL(el, fn, arg)) #else #define HIST_FUN(el, fn, arg) HIST_FUN_INTERNAL(el, fn, arg) #endif #define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL) #define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL) #define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL) #define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL) #define HIST_SET(el, num) HIST_FUN(el, H_SET, num) #define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname) #define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname) #define HIST_SAVE_FP(el, fp) HIST_FUN(el, H_SAVE_FP fp) protected int hist_init(EditLine *); protected void hist_end(EditLine *); protected el_action_t hist_get(EditLine *); protected int hist_set(EditLine *, hist_fun_t, void *); protected int hist_command(EditLine *, int, const Char **); protected int hist_enlargebuf(EditLine *, size_t, size_t); #ifdef WIDECHAR protected wchar_t *hist_convert(EditLine *, int, void *); #endif #endif /* _h_el_hist */ Index: head/lib/libedit/keymacro.h =================================================================== --- head/lib/libedit/keymacro.h (revision 295368) +++ head/lib/libedit/keymacro.h (revision 295369) @@ -1,77 +1,77 @@ -/* $NetBSD: keymacro.h,v 1.2 2011/07/28 03:44:36 christos Exp $ */ +/* $NetBSD: keymacro.h,v 1.3 2016/01/29 19:59:11 christos Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * 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. Neither the name of the University 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 REGENTS 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. * * @(#)key.h 8.1 (Berkeley) 6/4/93 * $FreeBSD$ */ /* * el.keymacro.h: Key macro header */ #ifndef _h_el_keymacro #define _h_el_keymacro typedef union keymacro_value_t { el_action_t cmd; /* If it is a command the # */ Char *str; /* If it is a string... */ } keymacro_value_t; typedef struct keymacro_node_t keymacro_node_t; -typedef struct el_keymacromacro_t { +typedef struct el_keymacro_t { Char *buf; /* Key print buffer */ keymacro_node_t *map; /* Key map */ keymacro_value_t val; /* Local conversion buffer */ } el_keymacro_t; #define XK_CMD 0 #define XK_STR 1 #define XK_NOD 2 #define XK_EXE 3 protected int keymacro_init(EditLine *); protected void keymacro_end(EditLine *); protected keymacro_value_t *keymacro_map_cmd(EditLine *, int); protected keymacro_value_t *keymacro_map_str(EditLine *, Char *); protected void keymacro_reset(EditLine *); protected int keymacro_get(EditLine *, Char *, keymacro_value_t *); protected void keymacro_add(EditLine *, const Char *, keymacro_value_t *, int); protected void keymacro_clear(EditLine *, el_action_t *, const Char *); protected int keymacro_delete(EditLine *, const Char *); protected void keymacro_print(EditLine *, const Char *); protected void keymacro_kprint(EditLine *, const Char *, keymacro_value_t *, int); protected size_t keymacro__decode_str(const Char *, char *, size_t, const char *); #endif /* _h_el_keymacro */ Index: head/lib/libedit/search.c =================================================================== --- head/lib/libedit/search.c (revision 295368) +++ head/lib/libedit/search.c (revision 295369) @@ -1,643 +1,643 @@ -/* $NetBSD: search.c,v 1.30 2011/10/04 15:27:04 christos Exp $ */ +/* $NetBSD: search.c,v 1.31 2016/01/30 04:02:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * 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. Neither the name of the University 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 REGENTS 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. */ #include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: search.c,v 1.30 2011/10/04 15:27:04 christos Exp $"); +__RCSID("$NetBSD: search.c,v 1.31 2016/01/30 04:02:51 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); /* * search.c: History and character search functions */ #include #if defined(REGEX) #include #elif defined(REGEXP) #include #endif #include "el.h" /* * Adjust cursor in vi mode to include the character under it */ #define EL_CURSOR(el) \ ((el)->el_line.cursor + (((el)->el_map.type == MAP_VI) && \ ((el)->el_map.current == (el)->el_map.alt))) /* search_init(): * Initialize the search stuff */ protected int search_init(EditLine *el) { el->el_search.patbuf = el_malloc(EL_BUFSIZ * sizeof(*el->el_search.patbuf)); if (el->el_search.patbuf == NULL) return -1; el->el_search.patlen = 0; el->el_search.patdir = -1; el->el_search.chacha = '\0'; el->el_search.chadir = CHAR_FWD; el->el_search.chatflg = 0; return 0; } /* search_end(): * Initialize the search stuff */ protected void search_end(EditLine *el) { el_free(el->el_search.patbuf); el->el_search.patbuf = NULL; } #ifdef REGEXP /* regerror(): * Handle regular expression errors */ public void /*ARGSUSED*/ regerror(const char *msg) { } #endif /* el_match(): * Return if string matches pattern */ protected int el_match(const Char *str, const Char *pat) { #ifdef WIDECHAR static ct_buffer_t conv; #endif #if defined (REGEX) regex_t re; int rv; #elif defined (REGEXP) regexp *rp; int rv; #else extern char *re_comp(const char *); extern int re_exec(const char *); #endif if (Strstr(str, pat) != 0) return 1; #if defined(REGEX) if (regcomp(&re, ct_encode_string(pat, &conv), 0) == 0) { rv = regexec(&re, ct_encode_string(str, &conv), (size_t)0, NULL, 0) == 0; regfree(&re); } else { rv = 0; } return rv; #elif defined(REGEXP) if ((re = regcomp(ct_encode_string(pat, &conv))) != NULL) { rv = regexec(re, ct_encode_string(str, &conv)); el_free(re); } else { rv = 0; } return rv; #else if (re_comp(ct_encode_string(pat, &conv)) != NULL) return 0; else - return re_exec(ct_encode_string(str, &conv) == 1); + return re_exec(ct_encode_string(str, &conv)) == 1; #endif } /* c_hmatch(): * return True if the pattern matches the prefix */ protected int c_hmatch(EditLine *el, const Char *str) { #ifdef SDEBUG (void) fprintf(el->el_errfile, "match `%s' with `%s'\n", el->el_search.patbuf, str); #endif /* SDEBUG */ return el_match(str, el->el_search.patbuf); } /* c_setpat(): * Set the history seatch pattern */ protected void c_setpat(EditLine *el) { if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY && el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { el->el_search.patlen = (size_t)(EL_CURSOR(el) - el->el_line.buffer); if (el->el_search.patlen >= EL_BUFSIZ) el->el_search.patlen = EL_BUFSIZ - 1; if (el->el_search.patlen != 0) { (void) Strncpy(el->el_search.patbuf, el->el_line.buffer, el->el_search.patlen); el->el_search.patbuf[el->el_search.patlen] = '\0'; } else el->el_search.patlen = Strlen(el->el_search.patbuf); } #ifdef SDEBUG (void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno); (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", el->el_search.patbuf); (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n", EL_CURSOR(el) - el->el_line.buffer, el->el_line.lastchar - el->el_line.buffer); #endif } /* ce_inc_search(): * Emacs incremental search */ protected el_action_t ce_inc_search(EditLine *el, int dir) { static const Char STRfwd[] = {'f', 'w', 'd', '\0'}, STRbck[] = {'b', 'c', 'k', '\0'}; static Char pchar = ':';/* ':' = normal, '?' = failed */ static Char endcmd[2] = {'\0', '\0'}; Char ch, *ocursor = el->el_line.cursor, oldpchar = pchar; const Char *cp; el_action_t ret = CC_NORM; int ohisteventno = el->el_history.eventno; size_t oldpatlen = el->el_search.patlen; int newdir = dir; int done, redo; if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(*el->el_line.lastchar) + 2 + el->el_search.patlen >= el->el_line.limit) return CC_ERROR; for (;;) { if (el->el_search.patlen == 0) { /* first round */ pchar = ':'; #ifdef ANCHOR #define LEN 2 el->el_search.patbuf[el->el_search.patlen++] = '.'; el->el_search.patbuf[el->el_search.patlen++] = '*'; #else #define LEN 0 #endif } done = redo = 0; *el->el_line.lastchar++ = '\n'; for (cp = (newdir == ED_SEARCH_PREV_HISTORY) ? STRbck : STRfwd; *cp; *el->el_line.lastchar++ = *cp++) continue; *el->el_line.lastchar++ = pchar; for (cp = &el->el_search.patbuf[LEN]; cp < &el->el_search.patbuf[el->el_search.patlen]; *el->el_line.lastchar++ = *cp++) continue; *el->el_line.lastchar = '\0'; re_refresh(el); if (FUN(el,getc)(el, &ch) != 1) return ed_end_of_file(el, 0); switch (el->el_map.current[(unsigned char) ch]) { case ED_INSERT: case ED_DIGIT: if (el->el_search.patlen >= EL_BUFSIZ - LEN) terminal_beep(el); else { el->el_search.patbuf[el->el_search.patlen++] = ch; *el->el_line.lastchar++ = ch; *el->el_line.lastchar = '\0'; re_refresh(el); } break; case EM_INC_SEARCH_NEXT: newdir = ED_SEARCH_NEXT_HISTORY; redo++; break; case EM_INC_SEARCH_PREV: newdir = ED_SEARCH_PREV_HISTORY; redo++; break; case EM_DELETE_PREV_CHAR: case ED_DELETE_PREV_CHAR: if (el->el_search.patlen > LEN) done++; else terminal_beep(el); break; default: switch (ch) { case 0007: /* ^G: Abort */ ret = CC_ERROR; done++; break; case 0027: /* ^W: Append word */ /* No can do if globbing characters in pattern */ for (cp = &el->el_search.patbuf[LEN];; cp++) if (cp >= &el->el_search.patbuf[ el->el_search.patlen]) { el->el_line.cursor += el->el_search.patlen - LEN - 1; cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, 1, ce__isword); while (el->el_line.cursor < cp && *el->el_line.cursor != '\n') { if (el->el_search.patlen >= EL_BUFSIZ - LEN) { terminal_beep(el); break; } el->el_search.patbuf[el->el_search.patlen++] = *el->el_line.cursor; *el->el_line.lastchar++ = *el->el_line.cursor++; } el->el_line.cursor = ocursor; *el->el_line.lastchar = '\0'; re_refresh(el); break; } else if (isglob(*cp)) { terminal_beep(el); break; } break; default: /* Terminate and execute cmd */ endcmd[0] = ch; FUN(el,push)(el, endcmd); /* FALLTHROUGH */ case 0033: /* ESC: Terminate */ ret = CC_REFRESH; done++; break; } break; } while (el->el_line.lastchar > el->el_line.buffer && *el->el_line.lastchar != '\n') *el->el_line.lastchar-- = '\0'; *el->el_line.lastchar = '\0'; if (!done) { /* Can't search if unmatched '[' */ for (cp = &el->el_search.patbuf[el->el_search.patlen-1], ch = ']'; cp >= &el->el_search.patbuf[LEN]; cp--) if (*cp == '[' || *cp == ']') { ch = *cp; break; } if (el->el_search.patlen > LEN && ch != '[') { if (redo && newdir == dir) { if (pchar == '?') { /* wrap around */ el->el_history.eventno = newdir == ED_SEARCH_PREV_HISTORY ? 0 : 0x7fffffff; if (hist_get(el) == CC_ERROR) /* el->el_history.event * no was fixed by * first call */ (void) hist_get(el); el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? el->el_line.lastchar : el->el_line.buffer; } else el->el_line.cursor += newdir == ED_SEARCH_PREV_HISTORY ? -1 : 1; } #ifdef ANCHOR el->el_search.patbuf[el->el_search.patlen++] = '.'; el->el_search.patbuf[el->el_search.patlen++] = '*'; #endif el->el_search.patbuf[el->el_search.patlen] = '\0'; if (el->el_line.cursor < el->el_line.buffer || el->el_line.cursor > el->el_line.lastchar || (ret = ce_search_line(el, newdir)) == CC_ERROR) { /* avoid c_setpat */ el->el_state.lastcmd = (el_action_t) newdir; ret = (el_action_t) (newdir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : ed_search_next_history(el, 0)); if (ret != CC_ERROR) { el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? el->el_line.lastchar : el->el_line.buffer; (void) ce_search_line(el, newdir); } } el->el_search.patlen -= LEN; el->el_search.patbuf[el->el_search.patlen] = '\0'; if (ret == CC_ERROR) { terminal_beep(el); if (el->el_history.eventno != ohisteventno) { el->el_history.eventno = ohisteventno; if (hist_get(el) == CC_ERROR) return CC_ERROR; } el->el_line.cursor = ocursor; pchar = '?'; } else { pchar = ':'; } } ret = ce_inc_search(el, newdir); if (ret == CC_ERROR && pchar == '?' && oldpchar == ':') /* * break abort of failed search at last * non-failed */ ret = CC_NORM; } if (ret == CC_NORM || (ret == CC_ERROR && oldpatlen == 0)) { /* restore on normal return or error exit */ pchar = oldpchar; el->el_search.patlen = oldpatlen; if (el->el_history.eventno != ohisteventno) { el->el_history.eventno = ohisteventno; if (hist_get(el) == CC_ERROR) return CC_ERROR; } el->el_line.cursor = ocursor; if (ret == CC_ERROR) re_refresh(el); } if (done || ret != CC_NORM) return ret; } } /* cv_search(): * Vi search. */ protected el_action_t cv_search(EditLine *el, int dir) { Char ch; Char tmpbuf[EL_BUFSIZ]; ssize_t tmplen; #ifdef ANCHOR tmpbuf[0] = '.'; tmpbuf[1] = '*'; #endif tmplen = LEN; el->el_search.patdir = dir; tmplen = c_gets(el, &tmpbuf[LEN], dir == ED_SEARCH_PREV_HISTORY ? STR("\n/") : STR("\n?") ); if (tmplen == -1) return CC_REFRESH; tmplen += LEN; ch = tmpbuf[tmplen]; tmpbuf[tmplen] = '\0'; if (tmplen == LEN) { /* * Use the old pattern, but wild-card it. */ if (el->el_search.patlen == 0) { re_refresh(el); return CC_ERROR; } #ifdef ANCHOR if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') { (void) Strncpy(tmpbuf, el->el_search.patbuf, sizeof(tmpbuf) / sizeof(*tmpbuf) - 1); el->el_search.patbuf[0] = '.'; el->el_search.patbuf[1] = '*'; (void) Strncpy(&el->el_search.patbuf[2], tmpbuf, EL_BUFSIZ - 3); el->el_search.patlen++; el->el_search.patbuf[el->el_search.patlen++] = '.'; el->el_search.patbuf[el->el_search.patlen++] = '*'; el->el_search.patbuf[el->el_search.patlen] = '\0'; } #endif } else { #ifdef ANCHOR tmpbuf[tmplen++] = '.'; tmpbuf[tmplen++] = '*'; #endif tmpbuf[tmplen] = '\0'; (void) Strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); el->el_search.patlen = (size_t)tmplen; } el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */ el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer; if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : ed_search_next_history(el, 0)) == CC_ERROR) { re_refresh(el); return CC_ERROR; } if (ch == 0033) { re_refresh(el); return ed_newline(el, 0); } return CC_REFRESH; } /* ce_search_line(): * Look for a pattern inside a line */ protected el_action_t ce_search_line(EditLine *el, int dir) { Char *cp = el->el_line.cursor; Char *pattern = el->el_search.patbuf; Char oc, *ocp; #ifdef ANCHOR ocp = &pattern[1]; oc = *ocp; *ocp = '^'; #else ocp = pattern; oc = *ocp; #endif if (dir == ED_SEARCH_PREV_HISTORY) { for (; cp >= el->el_line.buffer; cp--) { if (el_match(cp, ocp)) { *ocp = oc; el->el_line.cursor = cp; return CC_NORM; } } *ocp = oc; return CC_ERROR; } else { for (; *cp != '\0' && cp < el->el_line.limit; cp++) { if (el_match(cp, ocp)) { *ocp = oc; el->el_line.cursor = cp; return CC_NORM; } } *ocp = oc; return CC_ERROR; } } /* cv_repeat_srch(): * Vi repeat search */ protected el_action_t cv_repeat_srch(EditLine *el, Int c) { #ifdef SDEBUG (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", c, el->el_search.patlen, ct_encode_string(el->el_search.patbuf)); #endif el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ el->el_line.lastchar = el->el_line.buffer; switch (c) { case ED_SEARCH_NEXT_HISTORY: return ed_search_next_history(el, 0); case ED_SEARCH_PREV_HISTORY: return ed_search_prev_history(el, 0); default: return CC_ERROR; } } /* cv_csearch(): * Vi character search */ protected el_action_t cv_csearch(EditLine *el, int direction, Int ch, int count, int tflag) { Char *cp; if (ch == 0) return CC_ERROR; if (ch == (Int)-1) { Char c; if (FUN(el,getc)(el, &c) != 1) return ed_end_of_file(el, 0); ch = c; } /* Save for ';' and ',' commands */ el->el_search.chacha = ch; el->el_search.chadir = direction; el->el_search.chatflg = (char)tflag; cp = el->el_line.cursor; while (count--) { if ((Int)*cp == ch) cp += direction; for (;;cp += direction) { if (cp >= el->el_line.lastchar) return CC_ERROR; if (cp < el->el_line.buffer) return CC_ERROR; if ((Int)*cp == ch) break; } } if (tflag) cp -= direction; el->el_line.cursor = cp; if (el->el_chared.c_vcmd.action != NOP) { if (direction > 0) el->el_line.cursor++; cv_delfini(el); return CC_REFRESH; } return CC_CURSOR; } Index: head/lib/libedit/tokenizer.c =================================================================== --- head/lib/libedit/tokenizer.c (revision 295368) +++ head/lib/libedit/tokenizer.c (revision 295369) @@ -1,452 +1,452 @@ -/* $NetBSD: tokenizer.c,v 1.21 2011/08/16 16:25:15 christos Exp $ */ +/* $NetBSD: tokenizer.c,v 1.22 2016/01/30 04:02:51 christos Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * 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. Neither the name of the University 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 REGENTS 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. */ #include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tokenizer.c,v 1.21 2011/08/16 16:25:15 christos Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.22 2016/01/30 04:02:51 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); /* We build this file twice, once as NARROW, once as WIDE. */ /* * tokenize.c: Bourne shell like tokenizer */ #include #include #include "histedit.h" #include "chartype.h" typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone } quote_t; #define TOK_KEEP 1 #define TOK_EAT 2 #define WINCR 20 #define AINCR 10 #define IFS STR("\t \n") #define tok_malloc(a) malloc(a) #define tok_free(a) free(a) #define tok_realloc(a, b) realloc(a, b) #define tok_strdup(a) Strdup(a) struct TYPE(tokenizer) { Char *ifs; /* In field separator */ size_t argc, amax; /* Current and maximum number of args */ Char **argv; /* Argument list */ Char *wptr, *wmax; /* Space and limit on the word buffer */ Char *wstart; /* Beginning of next word */ Char *wspace; /* Space of word buffer */ quote_t quote; /* Quoting state */ int flags; /* flags; */ }; private void FUN(tok,finish)(TYPE(Tokenizer) *); /* FUN(tok,finish)(): * Finish a word in the tokenizer. */ private void FUN(tok,finish)(TYPE(Tokenizer) *tok) { *tok->wptr = '\0'; if ((tok->flags & TOK_KEEP) || tok->wptr != tok->wstart) { tok->argv[tok->argc++] = tok->wstart; tok->argv[tok->argc] = NULL; tok->wstart = ++tok->wptr; } tok->flags &= ~TOK_KEEP; } /* FUN(tok,init)(): * Initialize the tokenizer */ public TYPE(Tokenizer) * FUN(tok,init)(const Char *ifs) { TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok)); if (tok == NULL) return NULL; tok->ifs = tok_strdup(ifs ? ifs : IFS); if (tok->ifs == NULL) { tok_free(tok); return NULL; } tok->argc = 0; tok->amax = AINCR; tok->argv = tok_malloc(sizeof(*tok->argv) * tok->amax); if (tok->argv == NULL) { tok_free(tok->ifs); tok_free(tok); return NULL; } tok->argv[0] = NULL; tok->wspace = tok_malloc(WINCR * sizeof(*tok->wspace)); if (tok->wspace == NULL) { tok_free(tok->argv); tok_free(tok->ifs); tok_free(tok); return NULL; } tok->wmax = tok->wspace + WINCR; tok->wstart = tok->wspace; tok->wptr = tok->wspace; tok->flags = 0; tok->quote = Q_none; return tok; } /* FUN(tok,reset)(): * Reset the tokenizer */ public void FUN(tok,reset)(TYPE(Tokenizer) *tok) { tok->argc = 0; tok->wstart = tok->wspace; tok->wptr = tok->wspace; tok->flags = 0; tok->quote = Q_none; } /* FUN(tok,end)(): * Clean up */ public void FUN(tok,end)(TYPE(Tokenizer) *tok) { tok_free(tok->ifs); tok_free(tok->wspace); tok_free(tok->argv); tok_free(tok); } /* FUN(tok,line)(): * Bourne shell (sh(1)) like tokenizing * Arguments: * tok current tokenizer state (setup with FUN(tok,init)()) * line line to parse * Returns: * -1 Internal error * 3 Quoted return * 2 Unmatched double quote * 1 Unmatched single quote * 0 Ok * Modifies (if return value is 0): * argc number of arguments * argv argument array * cursorc if !NULL, argv element containing cursor * cursorv if !NULL, offset in argv[cursorc] of cursor */ public int FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line, int *argc, const Char ***argv, int *cursorc, int *cursoro) { const Char *ptr; int cc, co; cc = co = -1; ptr = line->buffer; for (ptr = line->buffer; ;ptr++) { if (ptr >= line->lastchar) ptr = STR(""); if (ptr == line->cursor) { cc = (int)tok->argc; co = (int)(tok->wptr - tok->wstart); } switch (*ptr) { case '\'': tok->flags |= TOK_KEEP; tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: tok->quote = Q_single; /* Enter single quote * mode */ break; case Q_single: /* Exit single quote mode */ tok->quote = Q_none; break; case Q_one: /* Quote this ' */ tok->quote = Q_none; *tok->wptr++ = *ptr; break; case Q_double: /* Stay in double quote mode */ *tok->wptr++ = *ptr; break; case Q_doubleone: /* Quote this ' */ tok->quote = Q_double; *tok->wptr++ = *ptr; break; default: return -1; } break; case '"': tok->flags &= ~TOK_EAT; tok->flags |= TOK_KEEP; switch (tok->quote) { case Q_none: /* Enter double quote mode */ tok->quote = Q_double; break; case Q_double: /* Exit double quote mode */ tok->quote = Q_none; break; case Q_one: /* Quote this " */ tok->quote = Q_none; *tok->wptr++ = *ptr; break; case Q_single: /* Stay in single quote mode */ *tok->wptr++ = *ptr; break; case Q_doubleone: /* Quote this " */ tok->quote = Q_double; *tok->wptr++ = *ptr; break; default: return -1; } break; case '\\': tok->flags |= TOK_KEEP; tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: /* Quote next character */ tok->quote = Q_one; break; case Q_double: /* Quote next character */ tok->quote = Q_doubleone; break; case Q_one: /* Quote this, restore state */ *tok->wptr++ = *ptr; tok->quote = Q_none; break; case Q_single: /* Stay in single quote mode */ *tok->wptr++ = *ptr; break; case Q_doubleone: /* Quote this \ */ tok->quote = Q_double; *tok->wptr++ = *ptr; break; default: return -1; } break; case '\n': tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: goto tok_line_outok; case Q_single: case Q_double: *tok->wptr++ = *ptr; /* Add the return */ break; case Q_doubleone: /* Back to double, eat the '\n' */ tok->flags |= TOK_EAT; tok->quote = Q_double; break; case Q_one: /* No quote, more eat the '\n' */ tok->flags |= TOK_EAT; tok->quote = Q_none; break; default: return 0; } break; case '\0': switch (tok->quote) { case Q_none: /* Finish word and return */ if (tok->flags & TOK_EAT) { tok->flags &= ~TOK_EAT; return 3; } goto tok_line_outok; case Q_single: return 1; case Q_double: return 2; case Q_doubleone: tok->quote = Q_double; *tok->wptr++ = *ptr; break; case Q_one: tok->quote = Q_none; *tok->wptr++ = *ptr; break; default: return -1; } break; default: tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: if (Strchr(tok->ifs, *ptr) != NULL) FUN(tok,finish)(tok); else *tok->wptr++ = *ptr; break; case Q_single: case Q_double: *tok->wptr++ = *ptr; break; case Q_doubleone: *tok->wptr++ = '\\'; tok->quote = Q_double; *tok->wptr++ = *ptr; break; case Q_one: tok->quote = Q_none; *tok->wptr++ = *ptr; break; default: return -1; } break; } if (tok->wptr >= tok->wmax - 4) { size_t size = (size_t)(tok->wmax - tok->wspace + WINCR); Char *s = tok_realloc(tok->wspace, size * sizeof(*s)); if (s == NULL) return -1; if (s != tok->wspace) { size_t i; for (i = 0; i < tok->argc; i++) { tok->argv[i] = (tok->argv[i] - tok->wspace) + s; } tok->wptr = (tok->wptr - tok->wspace) + s; tok->wstart = (tok->wstart - tok->wspace) + s; tok->wspace = s; } tok->wmax = s + size; } if (tok->argc >= tok->amax - 4) { Char **p; tok->amax += AINCR; p = tok_realloc(tok->argv, tok->amax * sizeof(*p)); if (p == NULL) return -1; tok->argv = p; } } tok_line_outok: if (cc == -1 && co == -1) { cc = (int)tok->argc; co = (int)(tok->wptr - tok->wstart); } if (cursorc != NULL) *cursorc = cc; if (cursoro != NULL) *cursoro = co; FUN(tok,finish)(tok); *argv = (const Char **)tok->argv; *argc = (int)tok->argc; return 0; } /* FUN(tok,str)(): * Simpler version of tok_line, taking a NUL terminated line * and splitting into words, ignoring cursor state. */ public int FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc, const Char ***argv) { TYPE(LineInfo) li; memset(&li, 0, sizeof(li)); li.buffer = line; li.cursor = li.lastchar = Strchr(line, '\0'); - return FUN(tok,line(tok, &li, argc, argv, NULL, NULL)); + return FUN(tok,line)(tok, &li, argc, argv, NULL, NULL); } Index: head/lib/libedit/tty.c =================================================================== --- head/lib/libedit/tty.c (revision 295368) +++ head/lib/libedit/tty.c (revision 295369) @@ -1,1327 +1,1330 @@ -/* $NetBSD: tty.c,v 1.47 2015/05/14 10:44:15 christos Exp $ */ +/* $NetBSD: tty.c,v 1.49 2015/12/08 16:53:27 gson Exp $ */ /*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * 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. Neither the name of the University 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 REGENTS 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. */ #include "config.h" #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tty.c,v 1.47 2015/05/14 10:44:15 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.49 2015/12/08 16:53:27 gson Exp $"); #endif #endif /* not lint && not SCCSID */ #include __FBSDID("$FreeBSD$"); /* * tty.c: tty interface stuff */ #include #include #include /* for isatty */ #include /* for ffs */ #include /* for abort */ #include "el.h" #include "tty.h" typedef struct ttymodes_t { const char *m_name; unsigned int m_value; int m_type; } ttymodes_t; typedef struct ttymap_t { Int nch, och; /* Internal and termio rep of chars */ el_action_t bind[3]; /* emacs, vi, and vi-cmd */ } ttymap_t; private const ttyperm_t ttyperm = { { {"iflag:", ICRNL, (INLCR | IGNCR)}, {"oflag:", (OPOST | ONLCR), ONLRET}, {"cflag:", 0, 0}, {"lflag:", (ISIG | ICANON | ECHO | ECHOE | ECHOCTL | IEXTEN), (NOFLSH | ECHONL | EXTPROC | FLUSHO)}, {"chars:", 0, 0}, }, { {"iflag:", (INLCR | ICRNL), IGNCR}, {"oflag:", (OPOST | ONLCR), ONLRET}, {"cflag:", 0, 0}, {"lflag:", ISIG, (NOFLSH | ICANON | ECHO | ECHOK | ECHONL | EXTPROC | IEXTEN | FLUSHO)}, {"chars:", (C_SH(C_MIN) | C_SH(C_TIME) | C_SH(C_SWTCH) | C_SH(C_DSWTCH) | C_SH(C_SUSP) | C_SH(C_DSUSP) | C_SH(C_EOL) | C_SH(C_DISCARD) | C_SH(C_PGOFF) | C_SH(C_PAGE) | C_SH(C_STATUS)), 0} }, { {"iflag:", 0, IXON | IXOFF | INLCR | ICRNL}, {"oflag:", 0, 0}, {"cflag:", 0, 0}, {"lflag:", 0, ISIG | IEXTEN}, {"chars:", 0, 0}, } }; private const ttychar_t ttychar = { { CINTR, CQUIT, CERASE, CKILL, CEOF, CEOL, CEOL2, CSWTCH, CDSWTCH, CERASE2, CSTART, CSTOP, CWERASE, CSUSP, CDSUSP, CREPRINT, CDISCARD, CLNEXT, CSTATUS, CPAGE, CPGOFF, CKILL2, CBRK, CMIN, CTIME }, { CINTR, CQUIT, CERASE, CKILL, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, CERASE2, CSTART, CSTOP, _POSIX_VDISABLE, CSUSP, _POSIX_VDISABLE, _POSIX_VDISABLE, CDISCARD, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, _POSIX_VDISABLE, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; private const ttymap_t tty_map[] = { #ifdef VERASE {C_ERASE, VERASE, {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, #endif /* VERASE */ #ifdef VERASE2 {C_ERASE2, VERASE2, {EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, #endif /* VERASE2 */ #ifdef VKILL {C_KILL, VKILL, {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, #endif /* VKILL */ #ifdef VKILL2 {C_KILL2, VKILL2, {EM_KILL_LINE, VI_KILL_LINE_PREV, ED_UNASSIGNED}}, #endif /* VKILL2 */ #ifdef VEOF {C_EOF, VEOF, {EM_DELETE_OR_LIST, VI_LIST_OR_EOF, ED_UNASSIGNED}}, #endif /* VEOF */ #ifdef VWERASE {C_WERASE, VWERASE, {ED_DELETE_PREV_WORD, ED_DELETE_PREV_WORD, ED_PREV_WORD}}, #endif /* VWERASE */ #ifdef VREPRINT {C_REPRINT, VREPRINT, {ED_REDISPLAY, ED_INSERT, ED_REDISPLAY}}, #endif /* VREPRINT */ #ifdef VLNEXT {C_LNEXT, VLNEXT, {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, #endif /* VLNEXT */ {(Int)-1, (Int)-1, {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} }; private const ttymodes_t ttymodes[] = { #ifdef IGNBRK {"ignbrk", IGNBRK, MD_INP}, #endif /* IGNBRK */ #ifdef BRKINT {"brkint", BRKINT, MD_INP}, #endif /* BRKINT */ #ifdef IGNPAR {"ignpar", IGNPAR, MD_INP}, #endif /* IGNPAR */ #ifdef PARMRK {"parmrk", PARMRK, MD_INP}, #endif /* PARMRK */ #ifdef INPCK {"inpck", INPCK, MD_INP}, #endif /* INPCK */ #ifdef ISTRIP {"istrip", ISTRIP, MD_INP}, #endif /* ISTRIP */ #ifdef INLCR {"inlcr", INLCR, MD_INP}, #endif /* INLCR */ #ifdef IGNCR {"igncr", IGNCR, MD_INP}, #endif /* IGNCR */ #ifdef ICRNL {"icrnl", ICRNL, MD_INP}, #endif /* ICRNL */ #ifdef IUCLC {"iuclc", IUCLC, MD_INP}, #endif /* IUCLC */ #ifdef IXON {"ixon", IXON, MD_INP}, #endif /* IXON */ #ifdef IXANY {"ixany", IXANY, MD_INP}, #endif /* IXANY */ #ifdef IXOFF {"ixoff", IXOFF, MD_INP}, #endif /* IXOFF */ #ifdef IMAXBEL {"imaxbel", IMAXBEL, MD_INP}, #endif /* IMAXBEL */ #ifdef OPOST {"opost", OPOST, MD_OUT}, #endif /* OPOST */ #ifdef OLCUC {"olcuc", OLCUC, MD_OUT}, #endif /* OLCUC */ #ifdef ONLCR {"onlcr", ONLCR, MD_OUT}, #endif /* ONLCR */ #ifdef OCRNL {"ocrnl", OCRNL, MD_OUT}, #endif /* OCRNL */ #ifdef ONOCR {"onocr", ONOCR, MD_OUT}, #endif /* ONOCR */ #ifdef ONOEOT {"onoeot", ONOEOT, MD_OUT}, #endif /* ONOEOT */ #ifdef ONLRET {"onlret", ONLRET, MD_OUT}, #endif /* ONLRET */ #ifdef OFILL {"ofill", OFILL, MD_OUT}, #endif /* OFILL */ #ifdef OFDEL {"ofdel", OFDEL, MD_OUT}, #endif /* OFDEL */ #ifdef NLDLY {"nldly", NLDLY, MD_OUT}, #endif /* NLDLY */ #ifdef CRDLY {"crdly", CRDLY, MD_OUT}, #endif /* CRDLY */ #ifdef TABDLY {"tabdly", TABDLY, MD_OUT}, #endif /* TABDLY */ #ifdef XTABS {"xtabs", XTABS, MD_OUT}, #endif /* XTABS */ #ifdef BSDLY {"bsdly", BSDLY, MD_OUT}, #endif /* BSDLY */ #ifdef VTDLY {"vtdly", VTDLY, MD_OUT}, #endif /* VTDLY */ #ifdef FFDLY {"ffdly", FFDLY, MD_OUT}, #endif /* FFDLY */ #ifdef PAGEOUT {"pageout", PAGEOUT, MD_OUT}, #endif /* PAGEOUT */ #ifdef WRAP {"wrap", WRAP, MD_OUT}, #endif /* WRAP */ #ifdef CIGNORE {"cignore", CIGNORE, MD_CTL}, #endif /* CBAUD */ #ifdef CBAUD {"cbaud", CBAUD, MD_CTL}, #endif /* CBAUD */ #ifdef CSTOPB {"cstopb", CSTOPB, MD_CTL}, #endif /* CSTOPB */ #ifdef CREAD {"cread", CREAD, MD_CTL}, #endif /* CREAD */ #ifdef PARENB {"parenb", PARENB, MD_CTL}, #endif /* PARENB */ #ifdef PARODD {"parodd", PARODD, MD_CTL}, #endif /* PARODD */ #ifdef HUPCL {"hupcl", HUPCL, MD_CTL}, #endif /* HUPCL */ #ifdef CLOCAL {"clocal", CLOCAL, MD_CTL}, #endif /* CLOCAL */ #ifdef LOBLK {"loblk", LOBLK, MD_CTL}, #endif /* LOBLK */ #ifdef CIBAUD {"cibaud", CIBAUD, MD_CTL}, #endif /* CIBAUD */ #ifdef CRTSCTS #ifdef CCTS_OFLOW {"ccts_oflow", CCTS_OFLOW, MD_CTL}, #else {"crtscts", CRTSCTS, MD_CTL}, #endif /* CCTS_OFLOW */ #endif /* CRTSCTS */ #ifdef CRTS_IFLOW {"crts_iflow", CRTS_IFLOW, MD_CTL}, #endif /* CRTS_IFLOW */ #ifdef CDTRCTS {"cdtrcts", CDTRCTS, MD_CTL}, #endif /* CDTRCTS */ #ifdef MDMBUF {"mdmbuf", MDMBUF, MD_CTL}, #endif /* MDMBUF */ #ifdef RCV1EN {"rcv1en", RCV1EN, MD_CTL}, #endif /* RCV1EN */ #ifdef XMT1EN {"xmt1en", XMT1EN, MD_CTL}, #endif /* XMT1EN */ #ifdef ISIG {"isig", ISIG, MD_LIN}, #endif /* ISIG */ #ifdef ICANON {"icanon", ICANON, MD_LIN}, #endif /* ICANON */ #ifdef XCASE {"xcase", XCASE, MD_LIN}, #endif /* XCASE */ #ifdef ECHO {"echo", ECHO, MD_LIN}, #endif /* ECHO */ #ifdef ECHOE {"echoe", ECHOE, MD_LIN}, #endif /* ECHOE */ #ifdef ECHOK {"echok", ECHOK, MD_LIN}, #endif /* ECHOK */ #ifdef ECHONL {"echonl", ECHONL, MD_LIN}, #endif /* ECHONL */ #ifdef NOFLSH {"noflsh", NOFLSH, MD_LIN}, #endif /* NOFLSH */ #ifdef TOSTOP {"tostop", TOSTOP, MD_LIN}, #endif /* TOSTOP */ #ifdef ECHOCTL {"echoctl", ECHOCTL, MD_LIN}, #endif /* ECHOCTL */ #ifdef ECHOPRT {"echoprt", ECHOPRT, MD_LIN}, #endif /* ECHOPRT */ #ifdef ECHOKE {"echoke", ECHOKE, MD_LIN}, #endif /* ECHOKE */ #ifdef DEFECHO {"defecho", DEFECHO, MD_LIN}, #endif /* DEFECHO */ #ifdef FLUSHO {"flusho", FLUSHO, MD_LIN}, #endif /* FLUSHO */ #ifdef PENDIN {"pendin", PENDIN, MD_LIN}, #endif /* PENDIN */ #ifdef IEXTEN {"iexten", IEXTEN, MD_LIN}, #endif /* IEXTEN */ #ifdef NOKERNINFO {"nokerninfo", NOKERNINFO, MD_LIN}, #endif /* NOKERNINFO */ #ifdef ALTWERASE {"altwerase", ALTWERASE, MD_LIN}, #endif /* ALTWERASE */ #ifdef EXTPROC {"extproc", EXTPROC, MD_LIN}, #endif /* EXTPROC */ #if defined(VINTR) {"intr", C_SH(C_INTR), MD_CHAR}, #endif /* VINTR */ #if defined(VQUIT) {"quit", C_SH(C_QUIT), MD_CHAR}, #endif /* VQUIT */ #if defined(VERASE) {"erase", C_SH(C_ERASE), MD_CHAR}, #endif /* VERASE */ #if defined(VKILL) {"kill", C_SH(C_KILL), MD_CHAR}, #endif /* VKILL */ #if defined(VEOF) {"eof", C_SH(C_EOF), MD_CHAR}, #endif /* VEOF */ #if defined(VEOL) {"eol", C_SH(C_EOL), MD_CHAR}, #endif /* VEOL */ #if defined(VEOL2) {"eol2", C_SH(C_EOL2), MD_CHAR}, #endif /* VEOL2 */ #if defined(VSWTCH) {"swtch", C_SH(C_SWTCH), MD_CHAR}, #endif /* VSWTCH */ #if defined(VDSWTCH) {"dswtch", C_SH(C_DSWTCH), MD_CHAR}, #endif /* VDSWTCH */ #if defined(VERASE2) {"erase2", C_SH(C_ERASE2), MD_CHAR}, #endif /* VERASE2 */ #if defined(VSTART) {"start", C_SH(C_START), MD_CHAR}, #endif /* VSTART */ #if defined(VSTOP) {"stop", C_SH(C_STOP), MD_CHAR}, #endif /* VSTOP */ #if defined(VWERASE) {"werase", C_SH(C_WERASE), MD_CHAR}, #endif /* VWERASE */ #if defined(VSUSP) {"susp", C_SH(C_SUSP), MD_CHAR}, #endif /* VSUSP */ #if defined(VDSUSP) {"dsusp", C_SH(C_DSUSP), MD_CHAR}, #endif /* VDSUSP */ #if defined(VREPRINT) {"reprint", C_SH(C_REPRINT), MD_CHAR}, #endif /* VREPRINT */ #if defined(VDISCARD) {"discard", C_SH(C_DISCARD), MD_CHAR}, #endif /* VDISCARD */ #if defined(VLNEXT) {"lnext", C_SH(C_LNEXT), MD_CHAR}, #endif /* VLNEXT */ #if defined(VSTATUS) {"status", C_SH(C_STATUS), MD_CHAR}, #endif /* VSTATUS */ #if defined(VPAGE) {"page", C_SH(C_PAGE), MD_CHAR}, #endif /* VPAGE */ #if defined(VPGOFF) {"pgoff", C_SH(C_PGOFF), MD_CHAR}, #endif /* VPGOFF */ #if defined(VKILL2) {"kill2", C_SH(C_KILL2), MD_CHAR}, #endif /* VKILL2 */ #if defined(VBRK) {"brk", C_SH(C_BRK), MD_CHAR}, #endif /* VBRK */ #if defined(VMIN) {"min", C_SH(C_MIN), MD_CHAR}, #endif /* VMIN */ #if defined(VTIME) {"time", C_SH(C_TIME), MD_CHAR}, #endif /* VTIME */ {NULL, 0, -1}, }; #define tty__gettabs(td) ((((td)->c_oflag & TAB3) == TAB3) ? 0 : 1) #define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8) #define tty__cooked_mode(td) ((td)->c_lflag & ICANON) private int tty_getty(EditLine *, struct termios *); private int tty_setty(EditLine *, int, const struct termios *); private int tty__getcharindex(int); private void tty__getchar(struct termios *, unsigned char *); private void tty__setchar(struct termios *, unsigned char *); private speed_t tty__getspeed(struct termios *); private int tty_setup(EditLine *); private void tty_setup_flags(EditLine *, struct termios *, int); #define t_qu t_ts /* tty_getty(): * Wrapper for tcgetattr to handle EINTR */ private int tty_getty(EditLine *el, struct termios *t) { int rv; while ((rv = tcgetattr(el->el_infd, t)) == -1 && errno == EINTR) continue; return rv; } /* tty_setty(): * Wrapper for tcsetattr to handle EINTR */ private int tty_setty(EditLine *el, int action, const struct termios *t) { int rv; while ((rv = tcsetattr(el->el_infd, action, t)) == -1 && errno == EINTR) continue; return rv; } /* tty_setup(): * Get the tty parameters and initialize the editing state */ private int tty_setup(EditLine *el) { int rst = 1; if (el->el_flags & EDIT_DISABLED) return 0; if (!isatty(el->el_outfd)) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } if (tty_getty(el, &el->el_tty.t_or) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or; el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); tty_setup_flags(el, &el->el_tty.t_ex, EX_IO); /* * Reset the tty chars to reasonable defaults * If they are disabled, then enable them. */ if (rst) { if (tty__cooked_mode(&el->el_tty.t_ts)) { tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); /* * Don't affect CMIN and CTIME for the editor mode */ for (rst = 0; rst < C_NCC - 2; rst++) if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable && el->el_tty.t_c[ED_IO][rst] != el->el_tty.t_vdisable) el->el_tty.t_c[ED_IO][rst] = el->el_tty.t_c[TS_IO][rst]; for (rst = 0; rst < C_NCC; rst++) if (el->el_tty.t_c[TS_IO][rst] != el->el_tty.t_vdisable) el->el_tty.t_c[EX_IO][rst] = el->el_tty.t_c[TS_IO][rst]; } tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } } tty_setup_flags(el, &el->el_tty.t_ed, ED_IO); tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); tty_bind_char(el, 1); return 0; } protected int tty_init(EditLine *el) { el->el_tty.t_mode = EX_IO; el->el_tty.t_vdisable = _POSIX_VDISABLE; (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); return tty_setup(el); } /* tty_end(): * Restore the tty to its original settings */ protected void /*ARGSUSED*/ tty_end(EditLine *el) { + if (el->el_flags & EDIT_DISABLED) + return; + if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ } } /* tty__getspeed(): * Get the tty speed */ private speed_t tty__getspeed(struct termios *td) { speed_t spd; if ((spd = cfgetispeed(td)) == 0) spd = cfgetospeed(td); return spd; } /* tty__getspeed(): * Return the index of the asked char in the c_cc array */ private int tty__getcharindex(int i) { switch (i) { #ifdef VINTR case C_INTR: return VINTR; #endif /* VINTR */ #ifdef VQUIT case C_QUIT: return VQUIT; #endif /* VQUIT */ #ifdef VERASE case C_ERASE: return VERASE; #endif /* VERASE */ #ifdef VKILL case C_KILL: return VKILL; #endif /* VKILL */ #ifdef VEOF case C_EOF: return VEOF; #endif /* VEOF */ #ifdef VEOL case C_EOL: return VEOL; #endif /* VEOL */ #ifdef VEOL2 case C_EOL2: return VEOL2; #endif /* VEOL2 */ #ifdef VSWTCH case C_SWTCH: return VSWTCH; #endif /* VSWTCH */ #ifdef VDSWTCH case C_DSWTCH: return VDSWTCH; #endif /* VDSWTCH */ #ifdef VERASE2 case C_ERASE2: return VERASE2; #endif /* VERASE2 */ #ifdef VSTART case C_START: return VSTART; #endif /* VSTART */ #ifdef VSTOP case C_STOP: return VSTOP; #endif /* VSTOP */ #ifdef VWERASE case C_WERASE: return VWERASE; #endif /* VWERASE */ #ifdef VSUSP case C_SUSP: return VSUSP; #endif /* VSUSP */ #ifdef VDSUSP case C_DSUSP: return VDSUSP; #endif /* VDSUSP */ #ifdef VREPRINT case C_REPRINT: return VREPRINT; #endif /* VREPRINT */ #ifdef VDISCARD case C_DISCARD: return VDISCARD; #endif /* VDISCARD */ #ifdef VLNEXT case C_LNEXT: return VLNEXT; #endif /* VLNEXT */ #ifdef VSTATUS case C_STATUS: return VSTATUS; #endif /* VSTATUS */ #ifdef VPAGE case C_PAGE: return VPAGE; #endif /* VPAGE */ #ifdef VPGOFF case C_PGOFF: return VPGOFF; #endif /* VPGOFF */ #ifdef VKILL2 case C_KILL2: return VKILL2; #endif /* KILL2 */ #ifdef VMIN case C_MIN: return VMIN; #endif /* VMIN */ #ifdef VTIME case C_TIME: return VTIME; #endif /* VTIME */ default: return -1; } } /* tty__getchar(): * Get the tty characters */ private void tty__getchar(struct termios *td, unsigned char *s) { #ifdef VINTR s[C_INTR] = td->c_cc[VINTR]; #endif /* VINTR */ #ifdef VQUIT s[C_QUIT] = td->c_cc[VQUIT]; #endif /* VQUIT */ #ifdef VERASE s[C_ERASE] = td->c_cc[VERASE]; #endif /* VERASE */ #ifdef VKILL s[C_KILL] = td->c_cc[VKILL]; #endif /* VKILL */ #ifdef VEOF s[C_EOF] = td->c_cc[VEOF]; #endif /* VEOF */ #ifdef VEOL s[C_EOL] = td->c_cc[VEOL]; #endif /* VEOL */ #ifdef VEOL2 s[C_EOL2] = td->c_cc[VEOL2]; #endif /* VEOL2 */ #ifdef VSWTCH s[C_SWTCH] = td->c_cc[VSWTCH]; #endif /* VSWTCH */ #ifdef VDSWTCH s[C_DSWTCH] = td->c_cc[VDSWTCH]; #endif /* VDSWTCH */ #ifdef VERASE2 s[C_ERASE2] = td->c_cc[VERASE2]; #endif /* VERASE2 */ #ifdef VSTART s[C_START] = td->c_cc[VSTART]; #endif /* VSTART */ #ifdef VSTOP s[C_STOP] = td->c_cc[VSTOP]; #endif /* VSTOP */ #ifdef VWERASE s[C_WERASE] = td->c_cc[VWERASE]; #endif /* VWERASE */ #ifdef VSUSP s[C_SUSP] = td->c_cc[VSUSP]; #endif /* VSUSP */ #ifdef VDSUSP s[C_DSUSP] = td->c_cc[VDSUSP]; #endif /* VDSUSP */ #ifdef VREPRINT s[C_REPRINT] = td->c_cc[VREPRINT]; #endif /* VREPRINT */ #ifdef VDISCARD s[C_DISCARD] = td->c_cc[VDISCARD]; #endif /* VDISCARD */ #ifdef VLNEXT s[C_LNEXT] = td->c_cc[VLNEXT]; #endif /* VLNEXT */ #ifdef VSTATUS s[C_STATUS] = td->c_cc[VSTATUS]; #endif /* VSTATUS */ #ifdef VPAGE s[C_PAGE] = td->c_cc[VPAGE]; #endif /* VPAGE */ #ifdef VPGOFF s[C_PGOFF] = td->c_cc[VPGOFF]; #endif /* VPGOFF */ #ifdef VKILL2 s[C_KILL2] = td->c_cc[VKILL2]; #endif /* KILL2 */ #ifdef VMIN s[C_MIN] = td->c_cc[VMIN]; #endif /* VMIN */ #ifdef VTIME s[C_TIME] = td->c_cc[VTIME]; #endif /* VTIME */ } /* tty__getchar */ /* tty__setchar(): * Set the tty characters */ private void tty__setchar(struct termios *td, unsigned char *s) { #ifdef VINTR td->c_cc[VINTR] = s[C_INTR]; #endif /* VINTR */ #ifdef VQUIT td->c_cc[VQUIT] = s[C_QUIT]; #endif /* VQUIT */ #ifdef VERASE td->c_cc[VERASE] = s[C_ERASE]; #endif /* VERASE */ #ifdef VKILL td->c_cc[VKILL] = s[C_KILL]; #endif /* VKILL */ #ifdef VEOF td->c_cc[VEOF] = s[C_EOF]; #endif /* VEOF */ #ifdef VEOL td->c_cc[VEOL] = s[C_EOL]; #endif /* VEOL */ #ifdef VEOL2 td->c_cc[VEOL2] = s[C_EOL2]; #endif /* VEOL2 */ #ifdef VSWTCH td->c_cc[VSWTCH] = s[C_SWTCH]; #endif /* VSWTCH */ #ifdef VDSWTCH td->c_cc[VDSWTCH] = s[C_DSWTCH]; #endif /* VDSWTCH */ #ifdef VERASE2 td->c_cc[VERASE2] = s[C_ERASE2]; #endif /* VERASE2 */ #ifdef VSTART td->c_cc[VSTART] = s[C_START]; #endif /* VSTART */ #ifdef VSTOP td->c_cc[VSTOP] = s[C_STOP]; #endif /* VSTOP */ #ifdef VWERASE td->c_cc[VWERASE] = s[C_WERASE]; #endif /* VWERASE */ #ifdef VSUSP td->c_cc[VSUSP] = s[C_SUSP]; #endif /* VSUSP */ #ifdef VDSUSP td->c_cc[VDSUSP] = s[C_DSUSP]; #endif /* VDSUSP */ #ifdef VREPRINT td->c_cc[VREPRINT] = s[C_REPRINT]; #endif /* VREPRINT */ #ifdef VDISCARD td->c_cc[VDISCARD] = s[C_DISCARD]; #endif /* VDISCARD */ #ifdef VLNEXT td->c_cc[VLNEXT] = s[C_LNEXT]; #endif /* VLNEXT */ #ifdef VSTATUS td->c_cc[VSTATUS] = s[C_STATUS]; #endif /* VSTATUS */ #ifdef VPAGE td->c_cc[VPAGE] = s[C_PAGE]; #endif /* VPAGE */ #ifdef VPGOFF td->c_cc[VPGOFF] = s[C_PGOFF]; #endif /* VPGOFF */ #ifdef VKILL2 td->c_cc[VKILL2] = s[C_KILL2]; #endif /* VKILL2 */ #ifdef VMIN td->c_cc[VMIN] = s[C_MIN]; #endif /* VMIN */ #ifdef VTIME td->c_cc[VTIME] = s[C_TIME]; #endif /* VTIME */ } /* tty__setchar */ /* tty_bind_char(): * Rebind the editline functions */ protected void tty_bind_char(EditLine *el, int force) { unsigned char *t_n = el->el_tty.t_c[ED_IO]; unsigned char *t_o = el->el_tty.t_ed.c_cc; Char new[2], old[2]; const ttymap_t *tp; el_action_t *map, *alt; const el_action_t *dmap, *dalt; new[1] = old[1] = '\0'; map = el->el_map.key; alt = el->el_map.alt; if (el->el_map.type == MAP_VI) { dmap = el->el_map.vii; dalt = el->el_map.vic; } else { dmap = el->el_map.emacs; dalt = NULL; } for (tp = tty_map; tp->nch != (Int)-1; tp++) { new[0] = t_n[tp->nch]; old[0] = t_o[tp->och]; if (new[0] == old[0] && !force) continue; /* Put the old default binding back, and set the new binding */ keymacro_clear(el, map, old); map[UC(old[0])] = dmap[UC(old[0])]; keymacro_clear(el, map, new); /* MAP_VI == 1, MAP_EMACS == 0... */ map[UC(new[0])] = tp->bind[el->el_map.type]; if (dalt) { keymacro_clear(el, alt, old); alt[UC(old[0])] = dalt[UC(old[0])]; keymacro_clear(el, alt, new); alt[UC(new[0])] = tp->bind[el->el_map.type + 1]; } } } private tcflag_t * tty__get_flag(struct termios *t, int kind) { switch (kind) { case MD_INP: return &t->c_iflag; case MD_OUT: return &t->c_oflag; case MD_CTL: return &t->c_cflag; case MD_LIN: return &t->c_lflag; default: abort(); /*NOTREACHED*/ } } private tcflag_t tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind) { f &= ~el->el_tty.t_t[mode][kind].t_clrmask; f |= el->el_tty.t_t[mode][kind].t_setmask; return f; } private void tty_update_flags(EditLine *el, int kind) { tcflag_t *tt, *ed, *ex; tt = tty__get_flag(&el->el_tty.t_ts, kind); ed = tty__get_flag(&el->el_tty.t_ed, kind); ex = tty__get_flag(&el->el_tty.t_ex, kind); if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) { *ed = tty_update_flag(el, *tt, ED_IO, kind); *ex = tty_update_flag(el, *tt, EX_IO, kind); } } private void tty_update_char(EditLine *el, int mode, int c) { if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c))) && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c])) el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c]; if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c)) el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable; } /* tty_rawmode(): * Set terminal into 1 character at a time mode. */ protected int tty_rawmode(EditLine *el) { if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) return 0; if (el->el_flags & EDIT_DISABLED) return 0; if (tty_getty(el, &el->el_tty.t_ts) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } /* * We always keep up with the eight bit setting and the speed of the * tty. But we only believe changes that are made to cooked mode! */ el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); if (tty__getspeed(&el->el_tty.t_ex) != el->el_tty.t_speed || tty__getspeed(&el->el_tty.t_ed) != el->el_tty.t_speed) { (void) cfsetispeed(&el->el_tty.t_ex, el->el_tty.t_speed); (void) cfsetospeed(&el->el_tty.t_ex, el->el_tty.t_speed); (void) cfsetispeed(&el->el_tty.t_ed, el->el_tty.t_speed); (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); } if (tty__cooked_mode(&el->el_tty.t_ts)) { int i; for (i = MD_INP; i <= MD_LIN; i++) tty_update_flags(el, i); if (tty__gettabs(&el->el_tty.t_ex) == 0) el->el_tty.t_tabs = 0; else el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); /* * Check if the user made any changes. * If he did, then propagate the changes to the * edit and execute data structures. */ for (i = 0; i < C_NCC; i++) if (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]) break; if (i != C_NCC) { /* * Propagate changes only to the unprotected * chars that have been modified just now. */ for (i = 0; i < C_NCC; i++) tty_update_char(el, ED_IO, i); tty_bind_char(el, 0); tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); for (i = 0; i < C_NCC; i++) tty_update_char(el, EX_IO, i); tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); } } if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } el->el_tty.t_mode = ED_IO; return 0; } /* tty_cookedmode(): * Set the tty back to normal mode */ protected int tty_cookedmode(EditLine *el) { /* set tty in normal setup */ if (el->el_tty.t_mode == EX_IO) return 0; if (el->el_flags & EDIT_DISABLED) return 0; if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } el->el_tty.t_mode = EX_IO; return 0; } /* tty_quotemode(): * Turn on quote mode */ protected int tty_quotemode(EditLine *el) { if (el->el_tty.t_mode == QU_IO) return 0; el->el_tty.t_qu = el->el_tty.t_ed; tty_setup_flags(el, &el->el_tty.t_qu, QU_IO); if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } el->el_tty.t_mode = QU_IO; return 0; } /* tty_noquotemode(): * Turn off quote mode */ protected int tty_noquotemode(EditLine *el) { if (el->el_tty.t_mode != QU_IO) return 0; if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } el->el_tty.t_mode = ED_IO; return 0; } /* tty_stty(): * Stty builtin */ protected int /*ARGSUSED*/ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv) { const ttymodes_t *m; char x; int aflag = 0; const Char *s, *d; char name[EL_BUFSIZ]; struct termios *tios = &el->el_tty.t_ex; int z = EX_IO; if (argv == NULL) return -1; strncpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); name[sizeof(name) - 1] = '\0'; while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') switch (argv[0][1]) { case 'a': aflag++; argv++; break; case 'd': argv++; tios = &el->el_tty.t_ed; z = ED_IO; break; case 'x': argv++; tios = &el->el_tty.t_ex; z = EX_IO; break; case 'q': argv++; tios = &el->el_tty.t_ts; z = QU_IO; break; default: (void) fprintf(el->el_errfile, "%s: Unknown switch `" FCHAR "'.\n", name, (Int)argv[0][1]); return -1; } if (!argv || !*argv) { int i = -1; size_t len = 0, st = 0, cu; for (m = ttymodes; m->m_name; m++) { if (m->m_type != i) { (void) fprintf(el->el_outfile, "%s%s", i != -1 ? "\n" : "", el->el_tty.t_t[z][m->m_type].t_name); i = m->m_type; st = len = strlen(el->el_tty.t_t[z][m->m_type].t_name); } if (i != -1) { x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0'; if (el->el_tty.t_t[z][i].t_clrmask & m->m_value) x = '-'; } else { x = '\0'; } if (x != '\0' || aflag) { cu = strlen(m->m_name) + (x != '\0') + 1; if (len + cu >= (size_t)el->el_terminal.t_size.h) { (void) fprintf(el->el_outfile, "\n%*s", (int)st, ""); len = st + cu; } else len += cu; if (x != '\0') (void) fprintf(el->el_outfile, "%c%s ", x, m->m_name); else (void) fprintf(el->el_outfile, "%s ", m->m_name); } } (void) fprintf(el->el_outfile, "\n"); return 0; } while (argv && (s = *argv++)) { const Char *p; switch (*s) { case '+': case '-': x = (char)*s++; break; default: x = '\0'; break; } d = s; p = Strchr(s, '='); for (m = ttymodes; m->m_name; m++) if ((p ? strncmp(m->m_name, ct_encode_string(d, &el->el_scratch), (size_t)(p - d)) : strcmp(m->m_name, ct_encode_string(d, &el->el_scratch))) == 0 && (p == NULL || m->m_type == MD_CHAR)) break; if (!m->m_name) { (void) fprintf(el->el_errfile, "%s: Invalid argument `" FSTR "'.\n", name, d); return -1; } if (p) { int c = ffs((int)m->m_value); int v = *++p ? parse__escape(&p) : el->el_tty.t_vdisable; assert(c != 0); c--; c = tty__getcharindex(c); assert(c != -1); tios->c_cc[c] = (cc_t)v; continue; } switch (x) { case '+': el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; break; case '-': el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; el->el_tty.t_t[z][m->m_type].t_clrmask |= m->m_value; break; default: el->el_tty.t_t[z][m->m_type].t_setmask &= ~m->m_value; el->el_tty.t_t[z][m->m_type].t_clrmask &= ~m->m_value; break; } } tty_setup_flags(el, tios, z); if (el->el_tty.t_mode == z) { if (tty_setty(el, TCSADRAIN, tios) == -1) { #ifdef DEBUG_TTY (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ return -1; } } return 0; } #ifdef notyet /* tty_printchar(): * DEbugging routine to print the tty characters */ private void tty_printchar(EditLine *el, unsigned char *s) { ttyperm_t *m; int i; for (i = 0; i < C_NCC; i++) { for (m = el->el_tty.t_t; m->m_name; m++) if (m->m_type == MD_CHAR && C_SH(i) == m->m_value) break; if (m->m_name) (void) fprintf(el->el_errfile, "%s ^%c ", m->m_name, s[i] + 'A' - 1); if (i % 5 == 0) (void) fprintf(el->el_errfile, "\n"); } (void) fprintf(el->el_errfile, "\n"); } #endif /* notyet */ private void tty_setup_flags(EditLine *el, struct termios *tios, int mode) { int kind; for (kind = MD_INP; kind <= MD_LIN; kind++) { tcflag_t *f = tty__get_flag(tios, kind); *f = tty_update_flag(el, *f, mode, kind); } } Index: head/lib/libedit =================================================================== --- head/lib/libedit (revision 295368) +++ head/lib/libedit (revision 295369) Property changes on: head/lib/libedit ___________________________________________________________________ Added: svn:mergeinfo ## -0,0 +0,32 ## Merged /user/ngie/more-tests2/lib/libedit:r288935-289179,289223-289224,289226-289227,289230,289236,289325,289437,289440,289484-289486,290904 Merged /projects/release-arm-redux/lib/libedit:r278203,278595-278597,278610,280643-280650,280652,280655,282539-282546,282548,282553-282557,282564,282566,282570,282573,282587-282593,282596-282607,282615-282616,282624-282629,282631,282633,282635-282640,282642,282647-282648,282653-282654,282656-282657,282659,282662-282667,282682,282691 Merged /user/ngie/socket-tests/lib/libedit:r293882-293885,294103,294117,294119-294120,294245-294247,294488,294555,294643-294644 Merged /projects/release-embedded/lib/libedit:r262314,262504,262510-262511,262580,262660,262662,262700,262713,262774,262786-262788,262790-262792,262798,262802,262808 Merged /user/ngie/bug203673/lib/libedit:r289470-289489 Merged /user/delphij/zfs-arc-rebase/lib/libedit:r281754 Merged /projects/largeSMP/lib/libedit:r221273-222812,222815-223757 Merged /projects/head_mfi/lib/libedit:r233621 Merged /projects/clang360-import/lib/libedit:r277327-280030 Merged /projects/clang-sparc64/lib/libedit:r262258-262612 Merged /projects/lldb-r201577/lib/libedit:r262185-262527 Merged /projects/pms/lib/libedit:r285199-285661 Merged /projects/clang380-import/lib/libedit:r293006,293013 Merged /projects/random_number_generator/lib/libedit:r254613-256243 Merged /vendor/NetBSD/libedit/dist:r295360 Merged /projects/multi-fibv6/head/lib/libedit:r230929-231848 Merged /projects/collation/lib/libedit:r286424-290491 Merged /projects/release-arm64/lib/libedit:r281786,281788,281792 Merged /projects/elftoolchain-update-r3130/lib/libedit:r276164,276167,276170-276172 Merged /user/ngie/more-tests/lib/libedit:r281427-281428,281430,281432,281450,281460,281464-281465,281485,281489-281491,281515,281519,281589,281593-281597,281619,284388,288316,288321-288327,288422,288476,288478-288481,288483,288578,288650-288651,288655-288656,288659-288661,288663,288673-288676,288680,288828,288930-288932 Merged /projects/pf/head/lib/libedit:r263908 Merged /projects/clang-trunk/lib/libedit:r283596-287505 Merged /projects/building-blocks/lib/libedit:r275142-275143,275198,275297,275306-275307,275309,275311,275556,275558,275600,277445,277670,277673 Merged /projects/zfsd/head/lib/libedit:r266519,269993 Merged /projects/clang350-import/lib/libedit:r274961-275126,275128-275133,275135-276476 Merged /vendor/resolver/dist/lib/libedit:r1540-186085 Merged /projects/clang370-import/lib/libedit:r287506-288928 Merged /projects/quota64/lib/libedit:r184125-207707 Merged /projects/cxl_iscsi/lib/libedit:r291227-291228,292618 Merged /projects/mpsutil/lib/libedit:r286179-290100 Merged /projects/elftoolchain/lib/libedit:r260687-261245 Merged /projects/ipfw/lib/libedit:r267383-272837