From: Sascha Hauer <s.hauer@pengutronix.de>
To: barebox@lists.infradead.org
Subject: [PATCH] readline: reimplement history functions
Date: Tue, 29 Jul 2014 13:51:07 +0200 [thread overview]
Message-ID: <1406634667-9491-1-git-send-email-s.hauer@pengutronix.de> (raw)
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>
---
lib/readline.c | 122 +++++++++++++++++++++++++--------------------------------
1 file changed, 54 insertions(+), 68 deletions(-)
diff --git a/lib/readline.c b/lib/readline.c
index 240a131..b70bca8 100644
--- a/lib/readline.c
+++ b/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
-
-static int hist_max = 0;
-static int hist_add_idx = 0;
-static int hist_cur = -1;
-static unsigned hist_num = 0;
+struct history {
+ char *line;
+ struct list_head list;
+};
-static char* hist_list[HIST_MAX];
-static char hist_lines[HIST_MAX][HIST_SIZE];
+static LIST_HEAD(history_list);
-#define add_idx_minus_one() ((hist_add_idx == 0) ? hist_max : hist_add_idx-1)
+static struct list_head *history_current;
+static int history_num_entries;
-static int hist_init(void)
+static void cread_add_to_hist(char *line)
{
- int i;
+ struct history *history;
+ char *newline;
- hist_max = 0;
- hist_add_idx = 0;
- hist_cur = -1;
- hist_num = 0;
+ if (!list_empty(&history_list)) {
+ history = list_last_entry(&history_list, struct history, list);
- for (i = 0; i < HIST_MAX; i++) {
- hist_list[i] = hist_lines[i];
- hist_list[i][0] = '\0';
+ if (!strcmp(line, history->line))
+ return;
}
- return 0;
-}
-
-postcore_initcall(hist_init);
-static void cread_add_to_hist(char *line)
-{
- strcpy(hist_list[hist_add_idx], line);
+ newline = strdup(line);
+ if (!newline)
+ return;
- if (++hist_add_idx >= HIST_MAX)
- hist_add_idx = 0;
+ 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);
+ }
- if (hist_add_idx > hist_max)
- hist_max = hist_add_idx;
+ history->line = newline;
- hist_num++;
+ 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;
}
--
2.0.1
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
reply other threads:[~2014-07-29 11:51 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1406634667-9491-1-git-send-email-s.hauer@pengutronix.de \
--to=s.hauer@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox