version 1.1.1.1, 2014/07/30 08:16:45
|
version 1.1.1.2, 2021/03/17 01:01:01
|
Line 1
|
Line 1
|
/* histexpand.c -- history expansion. */ |
/* histexpand.c -- history expansion. */ |
|
|
/* Copyright (C) 1989-2012 Free Software Foundation, Inc. | /* Copyright (C) 1989-2018 Free Software Foundation, Inc. |
|
|
This file contains the GNU History Library (History), a set of |
This file contains the GNU History Library (History), a set of |
routines for managing the text of previously typed lines. |
routines for managing the text of previously typed lines. |
Line 44
|
Line 44
|
|
|
#include "history.h" |
#include "history.h" |
#include "histlib.h" |
#include "histlib.h" |
|
#include "chardefs.h" |
|
|
#include "rlshell.h" |
#include "rlshell.h" |
#include "xmalloc.h" |
#include "xmalloc.h" |
|
|
#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" |
#define HISTORY_WORD_DELIMITERS " \t\n;&()|<>" |
#define HISTORY_QUOTE_CHARACTERS "\"'`" |
#define HISTORY_QUOTE_CHARACTERS "\"'`" |
|
#define HISTORY_EVENT_DELIMITERS "^$*%-" |
|
|
#define slashify_in_quotes "\\`\"$" |
#define slashify_in_quotes "\\`\"$" |
|
|
|
#define fielddelim(c) (whitespace(c) || (c) == '\n') |
|
|
typedef int _hist_search_func_t PARAMS((const char *, int)); |
typedef int _hist_search_func_t PARAMS((const char *, int)); |
|
|
static char error_pointer; |
static char error_pointer; |
Line 62 static char *subst_rhs;
|
Line 66 static char *subst_rhs;
|
static int subst_lhs_len; |
static int subst_lhs_len; |
static int subst_rhs_len; |
static int subst_rhs_len; |
|
|
|
/* Characters that delimit history event specifications and separate event |
|
specifications from word designators. Static for now */ |
|
static char *history_event_delimiter_chars = HISTORY_EVENT_DELIMITERS; |
|
|
static char *get_history_word_specifier PARAMS((char *, char *, int *)); |
static char *get_history_word_specifier PARAMS((char *, char *, int *)); |
static int history_tokenize_word PARAMS((const char *, int)); |
static int history_tokenize_word PARAMS((const char *, int)); |
static char **history_tokenize_internal PARAMS((const char *, int, int *)); |
static char **history_tokenize_internal PARAMS((const char *, int, int *)); |
Line 81 char history_expansion_char = '!';
|
Line 89 char history_expansion_char = '!';
|
char history_subst_char = '^'; |
char history_subst_char = '^'; |
|
|
/* During tokenization, if this character is seen as the first character |
/* During tokenization, if this character is seen as the first character |
of a word, then it, and all subsequent characters upto a newline are | of a word, then it, and all subsequent characters up to a newline are |
ignored. For a Bourne shell, this should be '#'. Bash special cases |
ignored. For a Bourne shell, this should be '#'. Bash special cases |
the interactive comment character to not be a comment delimiter. */ |
the interactive comment character to not be a comment delimiter. */ |
char history_comment_char = '\0'; |
char history_comment_char = '\0'; |
Line 101 char *history_word_delimiters = HISTORY_WORD_DELIMITER
|
Line 109 char *history_word_delimiters = HISTORY_WORD_DELIMITER
|
particular history expansion should be performed. */ |
particular history expansion should be performed. */ |
rl_linebuf_func_t *history_inhibit_expansion_function; |
rl_linebuf_func_t *history_inhibit_expansion_function; |
|
|
|
int history_quoting_state = 0; |
|
|
/* **************************************************************** */ |
/* **************************************************************** */ |
/* */ |
/* */ |
/* History Expansion */ |
/* History Expansion */ |
Line 112 rl_linebuf_func_t *history_inhibit_expansion_function;
|
Line 122 rl_linebuf_func_t *history_inhibit_expansion_function;
|
|
|
/* The last string searched for by a !?string? search. */ |
/* The last string searched for by a !?string? search. */ |
static char *search_string; |
static char *search_string; |
|
|
/* The last string matched by a !?string? search. */ |
/* The last string matched by a !?string? search. */ |
static char *search_match; |
static char *search_match; |
|
|
Line 127 static char *search_match;
|
Line 136 static char *search_match;
|
So you might call this function like: |
So you might call this function like: |
line = get_history_event ("!echo:p", &index, 0); */ |
line = get_history_event ("!echo:p", &index, 0); */ |
char * |
char * |
get_history_event (string, caller_index, delimiting_quote) | get_history_event (const char *string, int *caller_index, int delimiting_quote) |
const char *string; | |
int *caller_index; | |
int delimiting_quote; | |
{ |
{ |
register int i; |
register int i; |
register char c; |
register char c; |
Line 174 get_history_event (string, caller_index, delimiting_qu
|
Line 180 get_history_event (string, caller_index, delimiting_qu
|
} |
} |
|
|
/* Hack case of numeric line specification. */ |
/* Hack case of numeric line specification. */ |
if (string[i] == '-') | if (string[i] == '-' && _rl_digit_p (string[i+1])) |
{ |
{ |
sign = -1; |
sign = -1; |
i++; |
i++; |
Line 224 get_history_event (string, caller_index, delimiting_qu
|
Line 230 get_history_event (string, caller_index, delimiting_qu
|
} |
} |
|
|
#endif /* HANDLE_MULTIBYTE */ |
#endif /* HANDLE_MULTIBYTE */ |
if ((!substring_okay && (whitespace (c) || c == ':' || | if ((!substring_okay && |
(history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || | (whitespace (c) || c == ':' || |
string[i] == delimiting_quote)) || | (i > local_index && history_event_delimiter_chars && c == '-') || |
| (c != '-' && history_event_delimiter_chars && member (c, history_event_delimiter_chars)) || |
| (history_search_delimiter_chars && member (c, history_search_delimiter_chars)) || |
| string[i] == delimiting_quote)) || |
string[i] == '\n' || |
string[i] == '\n' || |
(substring_okay && string[i] == '?')) |
(substring_okay && string[i] == '?')) |
break; |
break; |
Line 310 get_history_event (string, caller_index, delimiting_qu
|
Line 319 get_history_event (string, caller_index, delimiting_qu
|
to the closing single quote. FLAGS currently used to allow backslash |
to the closing single quote. FLAGS currently used to allow backslash |
to escape a single quote (e.g., for bash $'...'). */ |
to escape a single quote (e.g., for bash $'...'). */ |
static void |
static void |
hist_string_extract_single_quoted (string, sindex, flags) | hist_string_extract_single_quoted (char *string, int *sindex, int flags) |
char *string; | |
int *sindex, flags; | |
{ |
{ |
register int i; |
register int i; |
|
|
Line 326 hist_string_extract_single_quoted (string, sindex, fla
|
Line 333 hist_string_extract_single_quoted (string, sindex, fla
|
} |
} |
|
|
static char * |
static char * |
quote_breaks (s) | quote_breaks (char *s) |
char *s; | |
{ |
{ |
register char *p, *r; |
register char *p, *r; |
char *ret; |
char *ret; |
Line 368 quote_breaks (s)
|
Line 374 quote_breaks (s)
|
} |
} |
|
|
static char * |
static char * |
hist_error(s, start, current, errtype) | hist_error(char *s, int start, int current, int errtype) |
char *s; | |
int start, current, errtype; | |
{ |
{ |
char *temp; |
char *temp; |
const char *emsg; |
const char *emsg; |
Line 407 hist_error(s, start, current, errtype)
|
Line 411 hist_error(s, start, current, errtype)
|
} |
} |
|
|
temp = (char *)xmalloc (ll + elen + 3); |
temp = (char *)xmalloc (ll + elen + 3); |
strncpy (temp, s + start, ll); | if (s[start]) |
| strncpy (temp, s + start, ll); |
| else |
| ll = 0; |
temp[ll] = ':'; |
temp[ll] = ':'; |
temp[ll + 1] = ' '; |
temp[ll + 1] = ' '; |
strcpy (temp + ll + 2, emsg); |
strcpy (temp + ll + 2, emsg); |
Line 427 hist_error(s, start, current, errtype)
|
Line 434 hist_error(s, start, current, errtype)
|
subst_rhs is allowed to be set to the empty string. */ |
subst_rhs is allowed to be set to the empty string. */ |
|
|
static char * |
static char * |
get_subst_pattern (str, iptr, delimiter, is_rhs, lenptr) | get_subst_pattern (char *str, int *iptr, int delimiter, int is_rhs, int *lenptr) |
char *str; | |
int *iptr, delimiter, is_rhs, *lenptr; | |
{ |
{ |
register int si, i, j, k; |
register int si, i, j, k; |
char *s; |
char *s; |
Line 484 get_subst_pattern (str, iptr, delimiter, is_rhs, lenpt
|
Line 489 get_subst_pattern (str, iptr, delimiter, is_rhs, lenpt
|
} |
} |
|
|
static void |
static void |
postproc_subst_rhs () | postproc_subst_rhs (void) |
{ |
{ |
char *new; |
char *new; |
int i, j, new_size; |
int i, j, new_size; |
Line 520 postproc_subst_rhs ()
|
Line 525 postproc_subst_rhs ()
|
if the `p' modifier was supplied and the caller should just print |
if the `p' modifier was supplied and the caller should just print |
the returned string. Returns the new index into string in |
the returned string. Returns the new index into string in |
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ |
*END_INDEX_PTR, and the expanded specifier in *RET_STRING. */ |
|
/* need current line for !# */ |
static int |
static int |
history_expand_internal (string, start, qc, end_index_ptr, ret_string, current_line) | history_expand_internal (char *string, int start, int qc, int *end_index_ptr, char **ret_string, char *current_line) |
char *string; | |
int start, qc, *end_index_ptr; | |
char **ret_string; | |
char *current_line; /* for !# */ | |
{ |
{ |
int i, n, starting_index; |
int i, n, starting_index; |
int substitute_globally, subst_bywords, want_quotes, print_only; |
int substitute_globally, subst_bywords, want_quotes, print_only; |
Line 627 history_expand_internal (string, start, qc, end_index_
|
Line 629 history_expand_internal (string, start, qc, end_index_
|
return an error state after adding this line to the |
return an error state after adding this line to the |
history. */ |
history. */ |
case 'p': |
case 'p': |
print_only++; | print_only = 1; |
break; |
break; |
|
|
/* :t discards all but the last part of the pathname. */ |
/* :t discards all but the last part of the pathname. */ |
Line 774 history_expand_internal (string, start, qc, end_index_
|
Line 776 history_expand_internal (string, start, qc, end_index_
|
the last time. */ |
the last time. */ |
if (subst_bywords && si > we) |
if (subst_bywords && si > we) |
{ |
{ |
for (; temp[si] && whitespace (temp[si]); si++) | for (; temp[si] && fielddelim (temp[si]); si++) |
; |
; |
ws = si; |
ws = si; |
we = history_tokenize_word (temp, si); |
we = history_tokenize_word (temp, si); |
Line 873 history_expand_internal (string, start, qc, end_index_
|
Line 875 history_expand_internal (string, start, qc, end_index_
|
1) If expansions did take place |
1) If expansions did take place |
2) If the `p' modifier was given and the caller should print the result |
2) If the `p' modifier was given and the caller should print the result |
|
|
If an error ocurred in expansion, then OUTPUT contains a descriptive | If an error occurred in expansion, then OUTPUT contains a descriptive |
error message. */ |
error message. */ |
|
|
#define ADD_STRING(s) \ |
#define ADD_STRING(s) \ |
Line 902 history_expand_internal (string, start, qc, end_index_
|
Line 904 history_expand_internal (string, start, qc, end_index_
|
while (0) |
while (0) |
|
|
int |
int |
history_expand (hstring, output) | history_expand (char *hstring, char **output) |
char *hstring; | |
char **output; | |
{ |
{ |
register int j; |
register int j; |
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag; |
int i, r, l, passc, cc, modified, eindex, only_printing, dquote, squote, flag; |
Line 970 history_expand (hstring, output)
|
Line 970 history_expand (hstring, output)
|
|
|
/* `!' followed by one of the characters in history_no_expand_chars |
/* `!' followed by one of the characters in history_no_expand_chars |
is NOT an expansion. */ |
is NOT an expansion. */ |
for (i = dquote = squote = 0; string[i]; i++) | dquote = history_quoting_state == '"'; |
| squote = history_quoting_state == '\''; |
| |
| /* If the calling application tells us we are already reading a |
| single-quoted string, consume the rest of the string right now |
| and then go on. */ |
| i = 0; |
| if (squote && history_quotes_inhibit_expansion) |
{ |
{ |
|
hist_string_extract_single_quoted (string, &i, 0); |
|
squote = 0; |
|
if (string[i]) |
|
i++; |
|
} |
|
|
|
for ( ; string[i]; i++) |
|
{ |
#if defined (HANDLE_MULTIBYTE) |
#if defined (HANDLE_MULTIBYTE) |
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) |
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) |
{ |
{ |
Line 991 history_expand (hstring, output)
|
Line 1006 history_expand (hstring, output)
|
history expansion performed on it. |
history expansion performed on it. |
Skip the rest of the line and break out of the loop. */ |
Skip the rest of the line and break out of the loop. */ |
if (history_comment_char && string[i] == history_comment_char && |
if (history_comment_char && string[i] == history_comment_char && |
|
dquote == 0 && |
(i == 0 || member (string[i - 1], history_word_delimiters))) |
(i == 0 || member (string[i - 1], history_word_delimiters))) |
{ |
{ |
while (string[i]) |
while (string[i]) |
Line 1057 history_expand (hstring, output)
|
Line 1073 history_expand (hstring, output)
|
} |
} |
|
|
/* Extract and perform the substitution. */ |
/* Extract and perform the substitution. */ |
for (passc = dquote = squote = i = j = 0; i < l; i++) | dquote = history_quoting_state == '"'; |
| squote = history_quoting_state == '\''; |
| |
| /* If the calling application tells us we are already reading a |
| single-quoted string, consume the rest of the string right now |
| and then go on. */ |
| i = j = 0; |
| if (squote && history_quotes_inhibit_expansion) |
{ |
{ |
|
int c; |
|
|
|
hist_string_extract_single_quoted (string, &i, 0); |
|
squote = 0; |
|
for (c = 0; c < i; c++) |
|
ADD_CHAR (string[c]); |
|
if (string[i]) |
|
{ |
|
ADD_CHAR (string[i]); |
|
i++; |
|
} |
|
} |
|
|
|
for (passc = 0; i < l; i++) |
|
{ |
int qc, tchar = string[i]; |
int qc, tchar = string[i]; |
|
|
if (passc) |
if (passc) |
Line 1149 history_expand (hstring, output)
|
Line 1187 history_expand (hstring, output)
|
} |
} |
|
|
case -2: /* history_comment_char */ |
case -2: /* history_comment_char */ |
if (i == 0 || member (string[i - 1], history_word_delimiters)) | if ((dquote == 0 || history_quotes_inhibit_expansion == 0) && |
| (i == 0 || member (string[i - 1], history_word_delimiters))) |
{ |
{ |
temp = (char *)xmalloc (l - i + 1); |
temp = (char *)xmalloc (l - i + 1); |
strcpy (temp, string + i); |
strcpy (temp, string + i); |
Line 1213 history_expand (hstring, output)
|
Line 1252 history_expand (hstring, output)
|
ADD_STRING (temp); |
ADD_STRING (temp); |
xfree (temp); |
xfree (temp); |
} |
} |
only_printing = r == 1; | only_printing += r == 1; |
i = eindex; |
i = eindex; |
} |
} |
break; |
break; |
Line 1241 history_expand (hstring, output)
|
Line 1280 history_expand (hstring, output)
|
CALLER_INDEX is the offset in SPEC to start looking; it is updated |
CALLER_INDEX is the offset in SPEC to start looking; it is updated |
to point to just after the last character parsed. */ |
to point to just after the last character parsed. */ |
static char * |
static char * |
get_history_word_specifier (spec, from, caller_index) | get_history_word_specifier (char *spec, char *from, int *caller_index) |
char *spec, *from; | |
int *caller_index; | |
{ |
{ |
register int i = *caller_index; |
register int i = *caller_index; |
int first, last; |
int first, last; |
Line 1324 get_history_word_specifier (spec, from, caller_index)
|
Line 1361 get_history_word_specifier (spec, from, caller_index)
|
i++; |
i++; |
last = '$'; |
last = '$'; |
} |
} |
|
else if (spec[i] == '^') |
|
{ |
|
i++; |
|
last = 1; |
|
} |
#if 0 |
#if 0 |
else if (!spec[i] || spec[i] == ':') |
else if (!spec[i] || spec[i] == ':') |
/* check against `:' because there could be a modifier separator */ |
/* check against `:' because there could be a modifier separator */ |
Line 1349 get_history_word_specifier (spec, from, caller_index)
|
Line 1391 get_history_word_specifier (spec, from, caller_index)
|
tokens, so that FIRST = -1 means the next to last token on the line). |
tokens, so that FIRST = -1 means the next to last token on the line). |
If LAST is `$' the last arg from STRING is used. */ |
If LAST is `$' the last arg from STRING is used. */ |
char * |
char * |
history_arg_extract (first, last, string) | history_arg_extract (int first, int last, const char *string) |
int first, last; | |
const char *string; | |
{ |
{ |
register int i, len; |
register int i, len; |
char *result; |
char *result; |
Line 1410 history_arg_extract (first, last, string)
|
Line 1450 history_arg_extract (first, last, string)
|
} |
} |
|
|
static int |
static int |
history_tokenize_word (string, ind) | history_tokenize_word (const char *string, int ind) |
const char *string; | |
int ind; | |
{ |
{ |
register int i; | register int i, j; |
int delimiter, nestdelim, delimopen; |
int delimiter, nestdelim, delimopen; |
|
|
i = ind; |
i = ind; |
delimiter = nestdelim = 0; |
delimiter = nestdelim = 0; |
|
|
if (member (string[i], "()\n")) | if (member (string[i], "()\n")) /* XXX - included \n, but why? been here forever */ |
{ |
{ |
i++; |
i++; |
return i; |
return i; |
} |
} |
|
|
if (member (string[i], "<>;&|$")) | if (ISDIGIT (string[i])) |
{ |
{ |
|
j = i; |
|
while (string[j] && ISDIGIT (string[j])) |
|
j++; |
|
if (string[j] == 0) |
|
return (j); |
|
if (string[j] == '<' || string[j] == '>') |
|
i = j; /* digit sequence is a file descriptor */ |
|
else |
|
{ |
|
i = j; |
|
goto get_word; /* digit sequence is part of a word */ |
|
} |
|
} |
|
|
|
if (member (string[i], "<>;&|")) |
|
{ |
int peek = string[i + 1]; |
int peek = string[i + 1]; |
|
|
if (peek == string[i] && peek != '$') | if (peek == string[i]) |
{ |
{ |
if (peek == '<' && string[i + 2] == '-') |
if (peek == '<' && string[i + 2] == '-') |
i++; |
i++; |
Line 1439 history_tokenize_word (string, ind)
|
Line 1493 history_tokenize_word (string, ind)
|
i += 2; |
i += 2; |
return i; |
return i; |
} |
} |
else if ((peek == '&' && (string[i] == '>' || string[i] == '<')) || | else if (peek == '&' && (string[i] == '>' || string[i] == '<')) |
(peek == '>' && string[i] == '&')) | |
{ |
{ |
|
j = i + 2; |
|
while (string[j] && ISDIGIT (string[j])) /* file descriptor */ |
|
j++; |
|
if (string[j] =='-') /* <&[digits]-, >&[digits]- */ |
|
j++; |
|
return j; |
|
} |
|
else if ((peek == '>' && string[i] == '&') || (peek == '|' && string[i] == '>')) |
|
{ |
i += 2; |
i += 2; |
return i; |
return i; |
} |
} |
/* XXX - separated out for later -- bash-4.2 */ | /* XXX - process substitution -- separated out for later -- bash-4.2 */ |
else if ((peek == '(' && (string[i] == '>' || string[i] == '<')) || /* ) */ | else if (peek == '(' && (string[i] == '>' || string[i] == '<')) /*)*/ |
(peek == '(' && string[i] == '$')) /*)*/ | |
{ |
{ |
i += 2; |
i += 2; |
delimopen = '('; |
delimopen = '('; |
Line 1455 history_tokenize_word (string, ind)
|
Line 1516 history_tokenize_word (string, ind)
|
nestdelim = 1; |
nestdelim = 1; |
goto get_word; |
goto get_word; |
} |
} |
#if 0 |
|
else if (peek == '\'' && string[i] == '$') |
|
{ |
|
i += 2; /* XXX */ |
|
return i; |
|
} |
|
#endif |
|
|
|
if (string[i] != '$') | i++; |
{ | return i; |
i++; | |
return i; | |
} | |
} |
} |
|
|
/* same code also used for $(...)/<(...)/>(...) above */ |
|
if (member (string[i], "!@?+*")) |
|
{ |
|
int peek = string[i + 1]; |
|
|
|
if (peek == '(') /*)*/ |
|
{ |
|
/* Shell extended globbing patterns */ |
|
i += 2; |
|
delimopen = '('; |
|
delimiter = ')'; /* XXX - not perfect */ |
|
nestdelim = 1; |
|
} |
|
} |
|
|
|
get_word: |
get_word: |
/* Get word from string + i; */ |
/* Get word from string + i; */ |
|
|
Line 1527 get_word:
|
Line 1563 get_word:
|
continue; |
continue; |
} |
} |
|
|
|
/* Command and process substitution; shell extended globbing patterns */ |
|
if (nestdelim == 0 && delimiter == 0 && member (string[i], "<>$!@?+*") && string[i+1] == '(') /*)*/ |
|
{ |
|
i += 2; |
|
delimopen = '('; |
|
delimiter = ')'; |
|
nestdelim = 1; |
|
continue; |
|
} |
|
|
if (delimiter == 0 && (member (string[i], history_word_delimiters))) |
if (delimiter == 0 && (member (string[i], history_word_delimiters))) |
break; |
break; |
|
|
Line 1538 get_word:
|
Line 1584 get_word:
|
} |
} |
|
|
static char * |
static char * |
history_substring (string, start, end) | history_substring (const char *string, int start, int end) |
const char *string; | |
int start, end; | |
{ |
{ |
register int len; |
register int len; |
register char *result; |
register char *result; |
Line 1557 history_substring (string, start, end)
|
Line 1601 history_substring (string, start, end)
|
WIND. The position in the returned array of strings is returned in |
WIND. The position in the returned array of strings is returned in |
*INDP. */ |
*INDP. */ |
static char ** |
static char ** |
history_tokenize_internal (string, wind, indp) | history_tokenize_internal (const char *string, int wind, int *indp) |
const char *string; | |
int wind, *indp; | |
{ |
{ |
char **result; |
char **result; |
register int i, start, result_index, size; |
register int i, start, result_index, size; |
Line 1574 history_tokenize_internal (string, wind, indp)
|
Line 1616 history_tokenize_internal (string, wind, indp)
|
for (i = result_index = size = 0, result = (char **)NULL; string[i]; ) |
for (i = result_index = size = 0, result = (char **)NULL; string[i]; ) |
{ |
{ |
/* Skip leading whitespace. */ |
/* Skip leading whitespace. */ |
for (; string[i] && whitespace (string[i]); i++) | for (; string[i] && fielddelim (string[i]); i++) |
; |
; |
if (string[i] == 0 || string[i] == history_comment_char) |
if (string[i] == 0 || string[i] == history_comment_char) |
return (result); |
return (result); |
Line 1612 history_tokenize_internal (string, wind, indp)
|
Line 1654 history_tokenize_internal (string, wind, indp)
|
/* Return an array of tokens, much as the shell might. The tokens are |
/* Return an array of tokens, much as the shell might. The tokens are |
parsed out of STRING. */ |
parsed out of STRING. */ |
char ** |
char ** |
history_tokenize (string) | history_tokenize (const char *string) |
const char *string; | |
{ |
{ |
return (history_tokenize_internal (string, -1, (int *)NULL)); |
return (history_tokenize_internal (string, -1, (int *)NULL)); |
} |
} |
|
|
/* Free members of WORDS from START to an empty string */ |
/* Free members of WORDS from START to an empty string */ |
static void |
static void |
freewords (words, start) | freewords (char **words, int start) |
char **words; | |
int start; | |
{ |
{ |
register int i; |
register int i; |
|
|
Line 1634 freewords (words, start)
|
Line 1673 freewords (words, start)
|
in the history line LINE. Used to save the word matched by the |
in the history line LINE. Used to save the word matched by the |
last history !?string? search. */ |
last history !?string? search. */ |
static char * |
static char * |
history_find_word (line, ind) | history_find_word (char *line, int ind) |
char *line; | |
int ind; | |
{ |
{ |
char **words, *s; |
char **words, *s; |
int i, wind; |
int i, wind; |