iPXE
Macros | Functions
readline.c File Reference

Minimal readline. More...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <ipxe/console.h>
#include <ipxe/keys.h>
#include <ipxe/editstring.h>
#include <readline/readline.h>

Go to the source code of this file.

Macros

#define READLINE_MAX   256
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static void sync_console (struct edit_string *string)
 Synchronise console with edited string. More...
 
static struct readline_history_entryhistory_entry (struct readline_history *history, unsigned int depth)
 Locate history entry. More...
 
static const char * history_fetch (struct readline_history *history, unsigned int depth)
 Read string from history buffer. More...
 
static void history_store (struct readline_history *history, unsigned int depth, const char *string)
 Write temporary string copy to history buffer. More...
 
static const char * history_move (struct readline_history *history, int offset, const char *old_string)
 Move to new history depth. More...
 
static void history_append (struct readline_history *history, const char *string)
 Append new history entry. More...
 
static void history_cleanup (struct readline_history *history)
 Clean up history after editing. More...
 
void history_free (struct readline_history *history)
 Free history buffer. More...
 
int readline_history (const char *prompt, const char *prefill, struct readline_history *history, char **line)
 Read line from console (with history) More...
 
char * readline (const char *prompt)
 Read line from console. More...
 

Detailed Description

Minimal readline.

Definition in file readline.c.

Macro Definition Documentation

◆ READLINE_MAX

#define READLINE_MAX   256

Definition at line 41 of file readline.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ sync_console()

static void sync_console ( struct edit_string string)
static

Synchronise console with edited string.

Parameters
stringEditable string

Definition at line 48 of file readline.c.

48  {
49  unsigned int mod_start = string->mod_start;
50  unsigned int mod_end = string->mod_end;
51  unsigned int cursor = string->last_cursor;
52  size_t len = strlen ( string->buf );
53 
54  /* Expand region back to old cursor position if applicable */
55  if ( mod_start > string->last_cursor )
56  mod_start = string->last_cursor;
57 
58  /* Expand region forward to new cursor position if applicable */
59  if ( mod_end < string->cursor )
60  mod_end = string->cursor;
61 
62  /* Backspace to start of region */
63  while ( cursor > mod_start ) {
64  putchar ( '\b' );
65  cursor--;
66  }
67 
68  /* Print modified region */
69  while ( cursor < mod_end ) {
70  putchar ( ( cursor >= len ) ? ' ' : string->buf[cursor] );
71  cursor++;
72  }
73 
74  /* Backspace to new cursor position */
75  while ( cursor > string->cursor ) {
76  putchar ( '\b' );
77  cursor--;
78  }
79 }
uint32_t mod_start
Definition: multiboot.h:12
uint32_t mod_end
Definition: multiboot.h:13
uint32_t string
Definition: multiboot.h:14
void putchar(int character)
Write a single character to each console device.
Definition: console.c:27
size_t strlen(const char *src)
Get length of string.
Definition: string.c:228
uint32_t len
Length.
Definition: ena.h:14

References len, mod_end, mod_start, putchar(), string, and strlen().

Referenced by readline_history().

◆ history_entry()

static struct readline_history_entry* history_entry ( struct readline_history history,
unsigned int  depth 
)
static

Locate history entry.

Parameters
historyHistory buffer
depthDepth within history buffer
Return values
entryHistory entry

Definition at line 89 of file readline.c.

89  {
90  unsigned int offset;
91 
92  offset = ( ( history->next - depth ) %
93  ( sizeof ( history->entries ) /
94  sizeof ( history->entries[0] ) ) );
95  return &history->entries[offset];
96 }
struct readline_history_entry entries[READLINE_HISTORY_MAX_DEPTH+1]
History entries.
Definition: readline.h:38
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
unsigned int next
Position of next entry within buffer.
Definition: readline.h:44

References readline_history::entries, readline_history::next, and offset.

Referenced by history_append(), history_cleanup(), history_fetch(), and history_store().

◆ history_fetch()

static const char* history_fetch ( struct readline_history history,
unsigned int  depth 
)
static

Read string from history buffer.

Parameters
historyHistory buffer
depthDepth within history buffer
Return values
stringString

Definition at line 105 of file readline.c.

106  {
108 
109  /* Return the temporary copy if it exists, otherwise return
110  * the persistent copy.
111  */
112  entry = history_entry ( history, depth );
113  return ( entry->temp ? entry->temp : entry->string );
114 }
static struct readline_history_entry * history_entry(struct readline_history *history, unsigned int depth)
Locate history entry.
Definition: readline.c:89
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
A readline history entry.
Definition: readline.h:13

References entry, and history_entry().

Referenced by history_move().

◆ history_store()

static void history_store ( struct readline_history history,
unsigned int  depth,
const char *  string 
)
static

Write temporary string copy to history buffer.

Parameters
historyHistory buffer
depthDepth within history buffer
stringString

Definition at line 123 of file readline.c.

124  {
126  char *temp;
127 
128  /* Create temporary copy of string */
129  temp = strdup ( string );
130  if ( ! temp ) {
131  /* Just discard the string; there's nothing we can do */
132  DBGC ( history, "READLINE %p could not store string\n",
133  history );
134  return;
135  }
136 
137  /* Store temporary copy */
138  entry = history_entry ( history, depth );
139  free ( entry->temp );
140  entry->temp = temp;
141 }
static struct readline_history_entry * history_entry(struct readline_history *history, unsigned int depth)
Locate history entry.
Definition: readline.c:89
#define DBGC(...)
Definition: compiler.h:505
char * temp
Temporary copy of string.
Definition: readline.h:21
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
char * strdup(const char *src)
Duplicate string.
Definition: string.c:365
A readline history entry.
Definition: readline.h:13

References DBGC, entry, free, history_entry(), strdup(), and readline_history_entry::temp.

Referenced by history_move().

◆ history_move()

static const char* history_move ( struct readline_history history,
int  offset,
const char *  old_string 
)
static

Move to new history depth.

Parameters
historyHistory buffer
offsetOffset by which to change depth
old_stringString (possibly modified) at current depth
Return values
new_stringString at new depth, or NULL for no movement

Definition at line 151 of file readline.c.

152  {
153  unsigned int new_depth = ( history->depth + offset );
154  const char * new_string = history_fetch ( history, new_depth );
155 
156  /* Depth checks */
157  if ( new_depth > READLINE_HISTORY_MAX_DEPTH )
158  return NULL;
159  if ( ! new_string )
160  return NULL;
161 
162  /* Store temporary copy of old string at current depth */
163  history_store ( history, history->depth, old_string );
164 
165  /* Update depth */
166  history->depth = new_depth;
167 
168  /* Return new string */
169  return new_string;
170 }
unsigned int depth
Current depth within history buffer.
Definition: readline.h:49
static void history_store(struct readline_history *history, unsigned int depth, const char *string)
Write temporary string copy to history buffer.
Definition: readline.c:123
#define READLINE_HISTORY_MAX_DEPTH
Maximum depth of a readline history buffer.
Definition: readline.h:28
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
static const char * history_fetch(struct readline_history *history, unsigned int depth)
Read string from history buffer.
Definition: readline.c:105
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References readline_history::depth, history_fetch(), history_store(), NULL, offset, and READLINE_HISTORY_MAX_DEPTH.

Referenced by readline_history().

◆ history_append()

static void history_append ( struct readline_history history,
const char *  string 
)
static

Append new history entry.

Parameters
historyHistory buffer
stringString

Definition at line 178 of file readline.c.

179  {
181 
182  /* Store new entry */
183  entry = history_entry ( history, 0 );
184  assert ( entry->string == NULL );
185  entry->string = strdup ( string );
186  if ( ! entry->string ) {
187  /* Just discard the string; there's nothing we can do */
188  DBGC ( history, "READLINE %p could not append string\n",
189  history );
190  return;
191  }
192 
193  /* Increment history position */
194  history->next++;
195 
196  /* Prepare empty "next" slot */
197  entry = history_entry ( history, 0 );
198  free ( entry->string );
199  entry->string = NULL;
200 }
static struct readline_history_entry * history_entry(struct readline_history *history, unsigned int depth)
Locate history entry.
Definition: readline.c:89
#define DBGC(...)
Definition: compiler.h:505
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
unsigned int next
Position of next entry within buffer.
Definition: readline.h:44
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
char * strdup(const char *src)
Duplicate string.
Definition: string.c:365
A readline history entry.
Definition: readline.h:13
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References assert(), DBGC, entry, free, history_entry(), readline_history::next, NULL, and strdup().

Referenced by readline_history().

◆ history_cleanup()

static void history_cleanup ( struct readline_history history)
static

Clean up history after editing.

Parameters
historyHistory buffer

Definition at line 207 of file readline.c.

207  {
209  unsigned int i;
210 
211  /* Discard any temporary strings */
212  for ( i = 0 ; i < ( sizeof ( history->entries ) /
213  sizeof ( history->entries[0] ) ) ; i++ ) {
214  entry = &history->entries[i];
215  free ( entry->temp );
216  entry->temp = NULL;
217  }
218 
219  /* Reset depth */
220  history->depth = 0;
221 
222  /* Sanity check */
223  entry = history_entry ( history, 0 );
224  assert ( entry->string == NULL );
225 }
unsigned int depth
Current depth within history buffer.
Definition: readline.h:49
static struct readline_history_entry * history_entry(struct readline_history *history, unsigned int depth)
Locate history entry.
Definition: readline.c:89
struct readline_history_entry entries[READLINE_HISTORY_MAX_DEPTH+1]
History entries.
Definition: readline.h:38
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
A readline history entry.
Definition: readline.h:13
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References assert(), readline_history::depth, readline_history::entries, entry, free, history_entry(), and NULL.

Referenced by readline_history().

◆ history_free()

void history_free ( struct readline_history history)

Free history buffer.

Parameters
historyHistory buffer

Definition at line 232 of file readline.c.

232  {
234  unsigned int i;
235 
236  /* Discard any temporary strings */
237  for ( i = 0 ; i < ( sizeof ( history->entries ) /
238  sizeof ( history->entries[0] ) ) ; i++ ) {
239  entry = &history->entries[i];
240  assert ( entry->temp == NULL );
241  free ( entry->string );
242  }
243 }
struct readline_history_entry entries[READLINE_HISTORY_MAX_DEPTH+1]
History entries.
Definition: readline.h:38
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
A readline history entry.
Definition: readline.h:13
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References assert(), readline_history::entries, entry, free, and NULL.

Referenced by shell().

◆ readline_history()

int readline_history ( const char *  prompt,
const char *  prefill,
struct readline_history history,
char **  line 
)

Read line from console (with history)

Parameters
promptPrompt string
prefillPrefill string, or NULL for no prefill
historyHistory buffer, or NULL for no history
Return values
lineLine read from console (excluding terminating newline)
rcReturn status code

The returned line is allocated with malloc(); the caller must eventually call free() to release the storage.

Definition at line 257 of file readline.c.

258  {
259  char buf[READLINE_MAX];
260  struct edit_string string;
261  int key;
262  int move_by;
263  const char *new_string;
264  int rc;
265 
266  /* Avoid returning uninitialised data on error */
267  *line = NULL;
268 
269  /* Display prompt, if applicable */
270  if ( prompt )
271  printf ( "%s", prompt );
272 
273  /* Ensure cursor is visible */
274  printf ( "\033[?25h" );
275 
276  /* Initialise editable string */
277  memset ( &string, 0, sizeof ( string ) );
278  init_editstring ( &string, buf, sizeof ( buf ) );
279  buf[0] = '\0';
280 
281  /* Prefill string, if applicable */
282  if ( prefill ) {
283  replace_string ( &string, prefill );
284  sync_console ( &string );
285  }
286 
287  while ( 1 ) {
288  /* Handle keypress */
289  key = edit_string ( &string, getkey ( 0 ) );
290  sync_console ( &string );
291  move_by = 0;
292  switch ( key ) {
293  case CR:
294  case LF:
295  *line = strdup ( buf );
296  rc = ( ( *line ) ? 0 : -ENOMEM );
297  goto done;
298  case CTRL_C:
299  rc = -ECANCELED;
300  goto done;
301  case KEY_UP:
302  move_by = 1;
303  break;
304  case KEY_DOWN:
305  move_by = -1;
306  break;
307  default:
308  /* Do nothing */
309  break;
310  }
311 
312  /* Handle history movement, if applicable */
313  if ( move_by && history ) {
314  new_string = history_move ( history, move_by, buf );
315  if ( new_string ) {
316  replace_string ( &string, new_string );
317  sync_console ( &string );
318  }
319  }
320  }
321 
322  done:
323  putchar ( '\n' );
324  if ( history ) {
325  if ( *line && (*line)[0] )
326  history_append ( history, *line );
327  history_cleanup ( history );
328  }
329  assert ( ( rc == 0 ) ^ ( *line == NULL ) );
330  return rc;
331 }
int getkey(unsigned long timeout)
Get single keypress.
Definition: getkey.c:71
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int printf(const char *fmt,...)
Write a formatted string to the console.
Definition: vsprintf.c:464
static const char * history_move(struct readline_history *history, int offset, const char *old_string)
Move to new history depth.
Definition: readline.c:151
void replace_string(struct edit_string *string, const char *replacement)
Replace editable string.
Definition: editstring.c:173
static void history_cleanup(struct readline_history *history)
Clean up history after editing.
Definition: readline.c:207
int edit_string(struct edit_string *string, int key)
Edit editable string.
Definition: editstring.c:195
uint32_t string
Definition: multiboot.h:14
void putchar(int character)
Write a single character to each console device.
Definition: console.c:27
#define ECANCELED
Operation canceled.
Definition: errno.h:343
#define KEY_DOWN
Down arrow.
Definition: keys.h:66
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define KEY_UP
Up arrow.
Definition: keys.h:65
static void sync_console(struct edit_string *string)
Synchronise console with edited string.
Definition: readline.c:48
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static void init_editstring(struct edit_string *string, char *buf, size_t len)
Initialise editable string.
Definition: editstring.h:38
#define CTRL_C
Definition: keys.h:20
char * strdup(const char *src)
Duplicate string.
Definition: string.c:365
int prompt(const char *text, unsigned long timeout, int key)
Prompt for keypress.
Definition: prompt.c:48
#define LF
Definition: keys.h:47
static void history_append(struct readline_history *history, const char *string)
Append new history entry.
Definition: readline.c:178
An editable string.
Definition: editstring.h:13
#define CR
Definition: keys.h:48
#define READLINE_MAX
Definition: readline.c:41
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct bofm_section_header done
Definition: bofm_test.c:46
union @376 key
Sense key.
Definition: scsi.h:18
void * memset(void *dest, int character, size_t len) __nonnull
char * buf
Buffer for string.
Definition: editstring.h:15

References assert(), edit_string::buf, CR, CTRL_C, done, ECANCELED, edit_string(), ENOMEM, getkey(), history_append(), history_cleanup(), history_move(), init_editstring(), key, KEY_DOWN, KEY_UP, LF, memset(), NULL, printf(), prompt(), putchar(), rc, READLINE_MAX, replace_string(), strdup(), string, and sync_console().

Referenced by readline(), and shell().

◆ readline()

char* readline ( const char *  prompt)

Read line from console.

Parameters
promptPrompt string
Return values
lineLine read from console (excluding terminating newline)

The returned line is allocated with malloc(); the caller must eventually call free() to release the storage.

Definition at line 342 of file readline.c.

342  {
343  char *line;
344 
345  readline_history ( prompt, NULL, NULL, &line );
346  return line;
347 }
int readline_history(const char *prompt, const char *prefill, struct readline_history *history, char **line)
Read line from console (with history)
Definition: readline.c:257
int prompt(const char *text, unsigned long timeout, int key)
Prompt for keypress.
Definition: prompt.c:48
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References NULL, prompt(), and readline_history().