Add ability to use system libedit and update bundled libedit.

The version of libedit that is bundled with asterisk is old and has some bugs.
This patch updates the bundled version of libedit within asterisk, and also
updates asterisk to use the system libedit instead if one is available (and
pkg-config is available).  This review integrates several patches from other
users specifically kkm and tzafrir.

(closes issue #15929)
Reported by: kkm
Patches:
      015929-astcli-editrc-trunk.240324.diff uploaded by kkm (license 888)

(issue #16858)
Reported by: jw-asterisk

(closes issue #17039)
Reported by: tzafrir
Patches:
      0001-allow-using-system-copy-of-libedit.patch uploaded by tzafrir (license 46)

Review: https://reviewboard.asterisk.org/r/807/


git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@280019 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Sean Bright
2010-07-27 21:57:07 +00:00
parent 4f6728bfb8
commit 5fb5c90b89
68 changed files with 336 additions and 25531 deletions

View File

@@ -1,941 +0,0 @@
/* $NetBSD: vi.c,v 1.9 2002/03/18 16:01:01 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. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: vi.c,v 1.9 2002/03/18 16:01:01 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
/*
* vi.c: Vi mode commands.
*/
#include "el.h"
private el_action_t cv_action(EditLine *, int);
private el_action_t cv_paste(EditLine *, int);
/* cv_action():
* Handle vi actions.
*/
private el_action_t
cv_action(EditLine *el, int c)
{
char *cp, *kp;
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
kp = el->el_chared.c_undo.buf;
for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
*kp++ = *cp;
el->el_chared.c_undo.dsize++;
}
el->el_chared.c_undo.action = INSERT;
el->el_chared.c_undo.ptr = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (c & INSERT)
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
}
el->el_chared.c_vcmd.pos = el->el_line.cursor;
el->el_chared.c_vcmd.action = c;
return (CC_ARGHACK);
#ifdef notdef
/*
* I don't think that this is needed. But we keep it for now
*/
else
if (el_chared.c_vcmd.action == NOP) {
el->el_chared.c_vcmd.pos = el->el_line.cursor;
el->el_chared.c_vcmd.action = c;
return (CC_ARGHACK);
} else {
el->el_chared.c_vcmd.action = 0;
el->el_chared.c_vcmd.pos = 0;
return (CC_ERROR);
}
#endif
}
/* cv_paste():
* Paste previous deletion before or after the cursor
*/
private el_action_t
cv_paste(EditLine *el, int c)
{
char *ptr;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_PASTE
(void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
if (un->isize == 0)
return (CC_ERROR);
if (!c && el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
ptr = el->el_line.cursor;
c_insert(el, (int) un->isize);
if (el->el_line.cursor + un->isize > el->el_line.lastchar)
return (CC_ERROR);
(void) memcpy(ptr, un->buf, un->isize);
return (CC_REFRESH);
}
/* vi_paste_next():
* Vi paste previous deletion to the right of the cursor
* [p]
*/
protected el_action_t
/*ARGSUSED*/
vi_paste_next(EditLine *el, int c)
{
return (cv_paste(el, 0));
}
/* vi_paste_prev():
* Vi paste previous deletion to the left of the cursor
* [P]
*/
protected el_action_t
/*ARGSUSED*/
vi_paste_prev(EditLine *el, int c)
{
return (cv_paste(el, 1));
}
/* vi_prev_space_word():
* Vi move to the previous space delimited word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_space_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.buffer)
return (CC_ERROR);
el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
cv__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
/* vi_prev_word():
* Vi move to the previous word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.buffer)
return (CC_ERROR);
el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
ce__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
/* vi_next_space_word():
* Vi move to the next space delimited word
* [W]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_space_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
cv__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
/* vi_next_word():
* Vi move to the next word
* [w]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
ce__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
/* vi_change_case():
* Vi change case of character under the cursor and advance one character
* [~]
*/
protected el_action_t
vi_change_case(EditLine *el, int c)
{
if (el->el_line.cursor < el->el_line.lastchar) {
c = *el->el_line.cursor;
if (isupper(c))
*el->el_line.cursor++ = tolower(c);
else if (islower(c))
*el->el_line.cursor++ = toupper(c);
else
el->el_line.cursor++;
re_fastaddc(el);
return (CC_NORM);
}
return (CC_ERROR);
}
/* vi_change_meta():
* Vi change prefix command
* [c]
*/
protected el_action_t
/*ARGSUSED*/
vi_change_meta(EditLine *el, int c)
{
/*
* Delete with insert == change: first we delete and then we leave in
* insert mode.
*/
return (cv_action(el, DELETE | INSERT));
}
/* vi_insert_at_bol():
* Vi enter insert mode at the beginning of line
* [I]
*/
protected el_action_t
/*ARGSUSED*/
vi_insert_at_bol(EditLine *el, int c)
{
el->el_line.cursor = el->el_line.buffer;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
el->el_map.current = el->el_map.key;
return (CC_CURSOR);
}
/* vi_replace_char():
* Vi replace character under the cursor with the next character typed
* [r]
*/
protected el_action_t
/*ARGSUSED*/
vi_replace_char(EditLine *el, int c)
{
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE_1;
el->el_chared.c_undo.action = CHANGE;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
return (CC_NORM);
}
/* vi_replace_mode():
* Vi enter replace mode
* [R]
*/
protected el_action_t
/*ARGSUSED*/
vi_replace_mode(EditLine *el, int c)
{
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE;
el->el_chared.c_undo.action = CHANGE;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.isize = 0;
el->el_chared.c_undo.dsize = 0;
return (CC_NORM);
}
/* vi_substitute_char():
* Vi replace character under the cursor and enter insert mode
* [r]
*/
protected el_action_t
/*ARGSUSED*/
vi_substitute_char(EditLine *el, int c)
{
c_delafter(el, el->el_state.argument);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
}
/* vi_substitute_line():
* Vi substitute entire line
* [S]
*/
protected el_action_t
/*ARGSUSED*/
vi_substitute_line(EditLine *el, int c)
{
(void) em_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
}
/* vi_change_to_eol():
* Vi change to end of line
* [C]
*/
protected el_action_t
/*ARGSUSED*/
vi_change_to_eol(EditLine *el, int c)
{
(void) ed_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
}
/* vi_insert():
* Vi enter insert mode
* [i]
*/
protected el_action_t
/*ARGSUSED*/
vi_insert(EditLine *el, int c)
{
el->el_map.current = el->el_map.key;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
return (CC_NORM);
}
/* vi_add():
* Vi enter insert mode after the cursor
* [a]
*/
protected el_action_t
/*ARGSUSED*/
vi_add(EditLine *el, int c)
{
int ret;
el->el_map.current = el->el_map.key;
if (el->el_line.cursor < el->el_line.lastchar) {
el->el_line.cursor++;
if (el->el_line.cursor > el->el_line.lastchar)
el->el_line.cursor = el->el_line.lastchar;
ret = CC_CURSOR;
} else
ret = CC_NORM;
el->el_chared.c_vcmd.ins = el->el_line.cursor;
el->el_chared.c_undo.ptr = el->el_line.cursor;
el->el_chared.c_undo.action = DELETE;
return (ret);
}
/* vi_add_at_eol():
* Vi enter insert mode at end of line
* [A]
*/
protected el_action_t
/*ARGSUSED*/
vi_add_at_eol(EditLine *el, int c)
{
el->el_map.current = el->el_map.key;
el->el_line.cursor = el->el_line.lastchar;
/* Mark where insertion begins */
el->el_chared.c_vcmd.ins = el->el_line.lastchar;
el->el_chared.c_undo.ptr = el->el_line.lastchar;
el->el_chared.c_undo.action = DELETE;
return (CC_CURSOR);
}
/* vi_delete_meta():
* Vi delete prefix command
* [d]
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_meta(EditLine *el, int c)
{
return (cv_action(el, DELETE));
}
/* vi_end_word():
* Vi move to the end of the current space delimited word
* [E]
*/
protected el_action_t
/*ARGSUSED*/
vi_end_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
el->el_line.cursor = cv__endword(el->el_line.cursor,
el->el_line.lastchar, el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
/* vi_to_end_word():
* Vi move to the end of the current word
* [e]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_end_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
el->el_line.cursor = cv__endword(el->el_line.cursor,
el->el_line.lastchar, el->el_state.argument);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
/* vi_undo():
* Vi undo last change
* [u]
*/
protected el_action_t
/*ARGSUSED*/
vi_undo(EditLine *el, int c)
{
char *cp, *kp;
char temp;
int i, size;
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_UNDO
(void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
un->action, un->buf, un->isize, un->dsize);
#endif
switch (un->action) {
case DELETE:
if (un->dsize == 0)
return (CC_NORM);
(void) memcpy(un->buf, un->ptr, un->dsize);
for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
*cp = cp[un->dsize];
el->el_line.lastchar -= un->dsize;
el->el_line.cursor = un->ptr;
un->action = INSERT;
un->isize = un->dsize;
un->dsize = 0;
break;
case DELETE | INSERT:
size = un->isize - un->dsize;
if (size > 0)
i = un->dsize;
else
i = un->isize;
cp = un->ptr;
kp = un->buf;
while (i-- > 0) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
if (size > 0) {
el->el_line.cursor = cp;
c_insert(el, size);
while (size-- > 0 && cp < el->el_line.lastchar) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
} else if (size < 0) {
size = -size;
for (; cp <= el->el_line.lastchar; cp++) {
*kp++ = *cp;
*cp = cp[size];
}
el->el_line.lastchar -= size;
}
el->el_line.cursor = un->ptr;
i = un->dsize;
un->dsize = un->isize;
un->isize = i;
break;
case INSERT:
if (un->isize == 0)
return (CC_NORM);
el->el_line.cursor = un->ptr;
c_insert(el, (int) un->isize);
(void) memcpy(un->ptr, un->buf, un->isize);
un->action = DELETE;
un->dsize = un->isize;
un->isize = 0;
break;
case CHANGE:
if (un->isize == 0)
return (CC_NORM);
el->el_line.cursor = un->ptr;
size = (int) (el->el_line.cursor - el->el_line.lastchar);
if (size < un->isize)
size = un->isize;
cp = un->ptr;
kp = un->buf;
for (i = 0; i < size; i++) {
temp = *kp;
*kp++ = *cp;
*cp++ = temp;
}
un->dsize = 0;
break;
default:
return (CC_ERROR);
}
return (CC_REFRESH);
}
/* vi_command_mode():
* Vi enter command mode (use alternative key bindings)
* [<ESC>]
*/
protected el_action_t
/*ARGSUSED*/
vi_command_mode(EditLine *el, int c)
{
int size;
/* [Esc] cancels pending action */
el->el_chared.c_vcmd.ins = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_state.doingarg = 0;
size = el->el_chared.c_undo.ptr - el->el_line.cursor;
if (size < 0)
size = -size;
if (el->el_chared.c_undo.action == (INSERT | DELETE) ||
el->el_chared.c_undo.action == DELETE)
el->el_chared.c_undo.dsize = size;
else
el->el_chared.c_undo.isize = size;
el->el_state.inputmode = MODE_INSERT;
el->el_map.current = el->el_map.alt;
#ifdef VI_MOVE
if (el->el_line.cursor > el->el_line.buffer)
el->el_line.cursor--;
#endif
return (CC_CURSOR);
}
/* vi_zero():
* Vi move to the beginning of line
* [0]
*/
protected el_action_t
vi_zero(EditLine *el, int c)
{
if (el->el_state.doingarg) {
if (el->el_state.argument > 1000000)
return (CC_ERROR);
el->el_state.argument =
(el->el_state.argument * 10) + (c - '0');
return (CC_ARGHACK);
} else {
el->el_line.cursor = el->el_line.buffer;
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
return (CC_REFRESH);
}
return (CC_CURSOR);
}
}
/* vi_delete_prev_char():
* Vi move to previous character (backspace)
* [^H]
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_prev_char(EditLine *el, int c)
{
if (el->el_chared.c_vcmd.ins == 0)
return (CC_ERROR);
if (el->el_chared.c_vcmd.ins >
el->el_line.cursor - el->el_state.argument)
return (CC_ERROR);
c_delbefore(el, el->el_state.argument);
el->el_line.cursor -= el->el_state.argument;
return (CC_REFRESH);
}
/* vi_list_or_eof():
* Vi list choices for completion or indicate end of file if empty line
* [^D]
*/
protected el_action_t
/*ARGSUSED*/
vi_list_or_eof(EditLine *el, int c)
{
#ifdef notyet
if (el->el_line.cursor == el->el_line.lastchar &&
el->el_line.cursor == el->el_line.buffer) {
#endif
term_overwrite(el, STReof, 4); /* then do a EOF */
term__flush();
return (CC_EOF);
#ifdef notyet
} else {
re_goto_bottom(el);
*el->el_line.lastchar = '\0'; /* just in case */
return (CC_LIST_CHOICES);
}
#endif
}
/* vi_kill_line_prev():
* Vi cut from beginning of line to cursor
* [^U]
*/
protected el_action_t
/*ARGSUSED*/
vi_kill_line_prev(EditLine *el, int c)
{
char *kp, *cp;
cp = el->el_line.buffer;
kp = el->el_chared.c_kill.buf;
while (cp < el->el_line.cursor)
*kp++ = *cp++; /* copy it */
el->el_chared.c_kill.last = kp;
c_delbefore(el, el->el_line.cursor - el->el_line.buffer);
el->el_line.cursor = el->el_line.buffer; /* zap! */
return (CC_REFRESH);
}
/* vi_search_prev():
* Vi search history previous
* [?]
*/
protected el_action_t
/*ARGSUSED*/
vi_search_prev(EditLine *el, int c)
{
return (cv_search(el, ED_SEARCH_PREV_HISTORY));
}
/* vi_search_next():
* Vi search history next
* [/]
*/
protected el_action_t
/*ARGSUSED*/
vi_search_next(EditLine *el, int c)
{
return (cv_search(el, ED_SEARCH_NEXT_HISTORY));
}
/* vi_repeat_search_next():
* Vi repeat current search in the same search direction
* [n]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_search_next(EditLine *el, int c)
{
if (el->el_search.patlen == 0)
return (CC_ERROR);
else
return (cv_repeat_srch(el, el->el_search.patdir));
}
/* vi_repeat_search_prev():
* Vi repeat current search in the opposite search direction
* [N]
*/
/*ARGSUSED*/
protected el_action_t
vi_repeat_search_prev(EditLine *el, int c)
{
if (el->el_search.patlen == 0)
return (CC_ERROR);
else
return (cv_repeat_srch(el,
el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
}
/* vi_next_char():
* Vi move to the character specified next
* [f]
*/
protected el_action_t
/*ARGSUSED*/
vi_next_char(EditLine *el, int c)
{
char ch;
if (el_getc(el, &ch) != 1)
return (ed_end_of_file(el, 0));
el->el_search.chadir = CHAR_FWD;
el->el_search.chacha = ch;
return (cv_csearch_fwd(el, ch, el->el_state.argument, 0));
}
/* vi_prev_char():
* Vi move to the character specified previous
* [F]
*/
protected el_action_t
/*ARGSUSED*/
vi_prev_char(EditLine *el, int c)
{
char ch;
if (el_getc(el, &ch) != 1)
return (ed_end_of_file(el, 0));
el->el_search.chadir = CHAR_BACK;
el->el_search.chacha = ch;
return (cv_csearch_back(el, ch, el->el_state.argument, 0));
}
/* vi_to_next_char():
* Vi move up to the character specified next
* [t]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_next_char(EditLine *el, int c)
{
char ch;
if (el_getc(el, &ch) != 1)
return (ed_end_of_file(el, 0));
return (cv_csearch_fwd(el, ch, el->el_state.argument, 1));
}
/* vi_to_prev_char():
* Vi move up to the character specified previous
* [T]
*/
protected el_action_t
/*ARGSUSED*/
vi_to_prev_char(EditLine *el, int c)
{
char ch;
if (el_getc(el, &ch) != 1)
return (ed_end_of_file(el, 0));
return (cv_csearch_back(el, ch, el->el_state.argument, 1));
}
/* vi_repeat_next_char():
* Vi repeat current character search in the same search direction
* [;]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_next_char(EditLine *el, int c)
{
if (el->el_search.chacha == 0)
return (CC_ERROR);
return (el->el_search.chadir == CHAR_FWD
? cv_csearch_fwd(el, el->el_search.chacha,
el->el_state.argument, 0)
: cv_csearch_back(el, el->el_search.chacha,
el->el_state.argument, 0));
}
/* vi_repeat_prev_char():
* Vi repeat current character search in the opposite search direction
* [,]
*/
protected el_action_t
/*ARGSUSED*/
vi_repeat_prev_char(EditLine *el, int c)
{
if (el->el_search.chacha == 0)
return (CC_ERROR);
return el->el_search.chadir == CHAR_BACK ?
cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) :
cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0);
}