readline: reimplement history functions
This reimplements the history functions in readline. - Use regular lists instead of homegrown list implementation - Allocate history strings dynamically instead of copying strings to fixed buffers without checking the size - saves us an initcall - slightly smaller - no longer add duplicates to the history - when moving past the last history entry print an empty line Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
ccdf13af24
commit
ada160a34a
128
lib/readline.c
128
lib/readline.c
|
@ -14,8 +14,6 @@
|
|||
printf ("%.*s", n, str); \
|
||||
} while (0)
|
||||
|
||||
#define MAX_CMDBUF_SIZE 256
|
||||
|
||||
#define CTL_BACKSPACE ('\b')
|
||||
#define DEL 255
|
||||
#define DEL7 127
|
||||
|
@ -25,90 +23,82 @@
|
|||
#define getcmd_getch() getc()
|
||||
#define getcmd_cbeep() getcmd_putch('\a')
|
||||
|
||||
#define HIST_MAX 20
|
||||
#define HIST_SIZE MAX_CMDBUF_SIZE
|
||||
struct history {
|
||||
char *line;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
static int hist_max = 0;
|
||||
static int hist_add_idx = 0;
|
||||
static int hist_cur = -1;
|
||||
static unsigned hist_num = 0;
|
||||
static LIST_HEAD(history_list);
|
||||
|
||||
static char* hist_list[HIST_MAX];
|
||||
static char hist_lines[HIST_MAX][HIST_SIZE];
|
||||
|
||||
#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
|
||||
|
||||
static int hist_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
hist_max = 0;
|
||||
hist_add_idx = 0;
|
||||
hist_cur = -1;
|
||||
hist_num = 0;
|
||||
|
||||
for (i = 0; i < HIST_MAX; i++) {
|
||||
hist_list[i] = hist_lines[i];
|
||||
hist_list[i][0] = '\0';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
postcore_initcall(hist_init);
|
||||
static struct list_head *history_current;
|
||||
static int history_num_entries;
|
||||
|
||||
static void cread_add_to_hist(char *line)
|
||||
{
|
||||
strcpy(hist_list[hist_add_idx], line);
|
||||
struct history *history;
|
||||
char *newline;
|
||||
|
||||
if (++hist_add_idx >= HIST_MAX)
|
||||
hist_add_idx = 0;
|
||||
if (!list_empty(&history_list)) {
|
||||
history = list_last_entry(&history_list, struct history, list);
|
||||
|
||||
if (hist_add_idx > hist_max)
|
||||
hist_max = hist_add_idx;
|
||||
if (!strcmp(line, history->line))
|
||||
return;
|
||||
}
|
||||
|
||||
hist_num++;
|
||||
newline = strdup(line);
|
||||
if (!newline)
|
||||
return;
|
||||
|
||||
if (history_num_entries < 32) {
|
||||
history = xzalloc(sizeof(*history));
|
||||
history_num_entries++;
|
||||
} else {
|
||||
history = list_first_entry(&history_list, struct history, list);
|
||||
free(history->line);
|
||||
list_del(&history->list);
|
||||
}
|
||||
|
||||
history->line = newline;
|
||||
|
||||
list_add_tail(&history->list, &history_list);
|
||||
}
|
||||
|
||||
static char* hist_prev(void)
|
||||
static const char *hist_prev(void)
|
||||
{
|
||||
char *ret;
|
||||
int old_cur;
|
||||
struct history *history;
|
||||
|
||||
if (hist_cur < 0)
|
||||
return NULL;
|
||||
if (history_current->prev == &history_list) {
|
||||
history = list_entry(history_current, struct history, list);
|
||||
getcmd_cbeep();
|
||||
return history->line;
|
||||
}
|
||||
|
||||
old_cur = hist_cur;
|
||||
if (--hist_cur < 0)
|
||||
hist_cur = hist_max;
|
||||
history = list_entry(history_current->prev, struct history, list);
|
||||
|
||||
if (hist_cur == hist_add_idx) {
|
||||
hist_cur = old_cur;
|
||||
ret = NULL;
|
||||
} else
|
||||
ret = hist_list[hist_cur];
|
||||
history_current = &history->list;
|
||||
|
||||
return (ret);
|
||||
return history->line;
|
||||
}
|
||||
|
||||
static char* hist_next(void)
|
||||
static const char *hist_next(void)
|
||||
{
|
||||
char *ret;
|
||||
struct history *history;
|
||||
|
||||
if (hist_cur < 0)
|
||||
return NULL;
|
||||
if (history_current->next == &history_list) {
|
||||
history_current = &history_list;
|
||||
return "";
|
||||
}
|
||||
|
||||
if (hist_cur == hist_add_idx)
|
||||
return NULL;
|
||||
if (history_current == &history_list) {
|
||||
getcmd_cbeep();
|
||||
return "";
|
||||
}
|
||||
|
||||
if (++hist_cur > hist_max)
|
||||
hist_cur = 0;
|
||||
history = list_entry(history_current->next, struct history, list);
|
||||
|
||||
if (hist_cur == hist_add_idx) {
|
||||
ret = "";
|
||||
} else
|
||||
ret = hist_list[hist_cur];
|
||||
history_current = &history->list;
|
||||
|
||||
return (ret);
|
||||
return history->line;
|
||||
}
|
||||
|
||||
#define BEGINNING_OF_LINE() { \
|
||||
|
@ -198,6 +188,8 @@ int readline(const char *prompt, char *buf, int len)
|
|||
|
||||
complete_reset();
|
||||
#endif
|
||||
history_current = &history_list;
|
||||
|
||||
puts (prompt);
|
||||
|
||||
while (1) {
|
||||
|
@ -302,18 +294,13 @@ int readline(const char *prompt, char *buf, int len)
|
|||
case BB_KEY_UP:
|
||||
case BB_KEY_DOWN:
|
||||
{
|
||||
char * hline;
|
||||
const char *hline;
|
||||
|
||||
if (ichar == BB_KEY_UP)
|
||||
hline = hist_prev();
|
||||
else
|
||||
hline = hist_next();
|
||||
|
||||
if (!hline) {
|
||||
getcmd_cbeep();
|
||||
continue;
|
||||
}
|
||||
|
||||
/* nuke the current line */
|
||||
/* first, go home */
|
||||
BEGINNING_OF_LINE();
|
||||
|
@ -346,9 +333,8 @@ int readline(const char *prompt, char *buf, int len)
|
|||
len = eol_num;
|
||||
buf[eol_num] = '\0'; /* lose the newline */
|
||||
|
||||
if (buf[0] && buf[0] != CREAD_HIST_CHAR)
|
||||
if (buf[0])
|
||||
cread_add_to_hist(buf);
|
||||
hist_cur = hist_add_idx;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue