Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions include/system/readline.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
# undef CONFIG_READLINE_TABCOMPLETION
#endif

/* readline_fd_ex() options */

#define READLINE_CTRL_D_EOF (1 << 0)
#define READLINE_RETURN_ON_EINTR (1 << 1)

/* Make sure that the are valid values for all tab-completion settings */

#ifdef CONFIG_READLINE_TABCOMPLETION
Expand Down Expand Up @@ -176,6 +181,19 @@ FAR const struct extmatch_vtable_s *

ssize_t readline_fd(FAR char *buf, int buflen, int infd, int outfd);

/****************************************************************************
* Name: readline_fd_ex
*
* readline_fd_ex() extends readline_fd() with caller-selected options.
* READLINE_CTRL_D_EOF makes Ctrl-D return EOF when the line is empty.
* READLINE_RETURN_ON_EINTR makes an interrupted input read return -EINTR
* instead of being retried.
*
****************************************************************************/

ssize_t readline_fd_ex(FAR char *buf, int buflen, int infd, int outfd,
unsigned int options);

/****************************************************************************
* Name: readline_stream
*
Expand Down
116 changes: 116 additions & 0 deletions interpreters/python/python_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@

#include <nuttx/drivers/ramdisk.h>

#ifdef CONFIG_SYSTEM_READLINE
# include <system/readline.h>
#endif

#include "romfs_cpython_modules.h"

#include "Python.h"
Expand Down Expand Up @@ -80,6 +84,17 @@
#define MKMOUNT_DEVNAME(m) "/dev/ram" STR_RAMDEVNO(m)
#define MOUNT_DEVNAME MKMOUNT_DEVNAME(CONFIG_CPYTHON_ROMFS_RAMDEVNO)

#ifdef CONFIG_SYSTEM_READLINE
# if CONFIG_LINE_MAX > 2
# define PYTHON_READLINE_BUFSIZE CONFIG_LINE_MAX
# else
# define PYTHON_READLINE_BUFSIZE 2
# endif

# define PYTHON_READLINE_OPTIONS \
(READLINE_CTRL_D_EOF | READLINE_RETURN_ON_EINTR)
#endif

/****************************************************************************
* Private Types
****************************************************************************/
Expand All @@ -92,6 +107,103 @@
* Private Functions
****************************************************************************/

#ifdef CONFIG_SYSTEM_READLINE
/****************************************************************************
* Name: python_readline
*
* Description:
* Read an interactive line with the NuttX line editor. CPython calls
* this hook only for a TTY attached to the main interpreter, leaving its
* standard fgets-based reader in place for redirected input and
* subinterpreters.
*
****************************************************************************/

static char *python_readline(FILE *sys_stdin, FILE *sys_stdout,
const char *prompt)
{
#if defined(CONFIG_READLINE_TABCOMPLETION) || defined(CONFIG_READLINE_EDIT)
FAR const char *oldprompt;
#endif
FAR char *line;
FAR char *tmp;
size_t linesize;
size_t used;
ssize_t nread;

fflush(sys_stdout);

if (prompt != NULL)
{
fputs(prompt, stderr);
}

fflush(stderr);
Comment thread
xiaoxiang781216 marked this conversation as resolved.

linesize = PYTHON_READLINE_BUFSIZE;
line = PyMem_RawMalloc(linesize);

Check failure on line 144 in interpreters/python/python_wrapper.c

View workflow job for this annotation

GitHub Actions / check

Mixed case identifier found
if (line == NULL)
{
return NULL;
}

used = 0;

#if defined(CONFIG_READLINE_TABCOMPLETION) || defined(CONFIG_READLINE_EDIT)
oldprompt = readline_prompt(prompt);
#endif

for (; ; )
{
nread = readline_fd_ex(line + used, PYTHON_READLINE_BUFSIZE,
fileno(sys_stdin), fileno(sys_stdout),
PYTHON_READLINE_OPTIONS);
if (nread == -EINTR)
{
PyMem_RawFree(line);

Check failure on line 163 in interpreters/python/python_wrapper.c

View workflow job for this annotation

GitHub Actions / check

Mixed case identifier found
line = NULL;
break;
}

if (nread == EOF)
{
line[used] = '\0';
break;
}

used += nread;
if (used > 0 && line[used - 1] == '\n')
{
break;
}

if (used > SIZE_MAX - PYTHON_READLINE_BUFSIZE)
{
PyMem_RawFree(line);

Check failure on line 182 in interpreters/python/python_wrapper.c

View workflow job for this annotation

GitHub Actions / check

Mixed case identifier found
line = NULL;
break;
}

linesize = used + PYTHON_READLINE_BUFSIZE;
tmp = PyMem_RawRealloc(line, linesize);

Check failure on line 188 in interpreters/python/python_wrapper.c

View workflow job for this annotation

GitHub Actions / check

Mixed case identifier found
if (tmp == NULL)
{
PyMem_RawFree(line);

Check failure on line 191 in interpreters/python/python_wrapper.c

View workflow job for this annotation

GitHub Actions / check

Mixed case identifier found
line = NULL;
break;
}

line = tmp;
}

#if defined(CONFIG_READLINE_TABCOMPLETION) || defined(CONFIG_READLINE_EDIT)
readline_prompt(oldprompt);
#endif

return line;
}
#endif

/****************************************************************************
* Name: check_and_mount_romfs
*
Expand Down Expand Up @@ -194,6 +306,10 @@

_pyruntime_early_init();

#ifdef CONFIG_SYSTEM_READLINE
PyOS_ReadlineFunctionPointer = python_readline;

Check failure on line 310 in interpreters/python/python_wrapper.c

View workflow job for this annotation

GitHub Actions / check

Mixed case identifier found
#endif

setenv("PYTHONHOME", "/usr/local", 1);

setenv("PYTHON_BASIC_REPL", "1", 1);
Expand Down
2 changes: 1 addition & 1 deletion system/readline/readline.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,6 @@ struct rl_common_s
****************************************************************************/

ssize_t readline_common(FAR struct rl_common_s *vtbl,
FAR char *buf, int buflen);
FAR char *buf, int buflen, unsigned int options);

#endif /* __APPS_SYSTEM_READLINE_READLINE_H */
15 changes: 12 additions & 3 deletions system/readline/readline_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@
# define RL_CMDHIST_LINELEN CONFIG_READLINE_CMD_HISTORY_LINELEN
#endif

#define CTRL_D 4 /* ^D - EOF or delete at cursor */

#ifdef CONFIG_READLINE_EDIT_EMACS
/* Emacs-style control key codes */
/* Additional Emacs-style control key codes */

# define CTRL_A 1 /* ^A - Home */
# define CTRL_B 2 /* ^B - Left */
# define CTRL_D 4 /* ^D - Delete at cursor */
# define CTRL_E 5 /* ^E - End */
# define CTRL_F 6 /* ^F - Right */
# define CTRL_K 11 /* ^K - Kill to end of line */
Expand Down Expand Up @@ -849,7 +850,7 @@ FAR const struct extmatch_vtable_s *
****************************************************************************/

ssize_t readline_common(FAR struct rl_common_s *vtbl, FAR char *buf,
int buflen)
int buflen, unsigned int options)
{
int escape;
int nch;
Expand Down Expand Up @@ -1440,6 +1441,14 @@ ssize_t readline_common(FAR struct rl_common_s *vtbl, FAR char *buf,
return submit_line(buf, nch);
}

/* Some callers use the conventional empty-line Ctrl-D as EOF. */

else if (ch == CTRL_D && (options & READLINE_CTRL_D_EOF) != 0 &&
nch == 0)
{
return EOF;
}

/* Emacs-style control keys */

#ifdef CONFIG_READLINE_EDIT_EMACS
Expand Down
33 changes: 29 additions & 4 deletions system/readline/readline_fd.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,11 @@
struct readline_s
{
struct rl_common_s vtbl;
int infd;
unsigned int options;
int infd;
int errcode;
#ifdef CONFIG_READLINE_ECHO
int outfd;
int outfd;
#endif
};

Expand Down Expand Up @@ -92,7 +94,13 @@ static int readline_getc(FAR struct rl_common_s *vtbl)
*/

int errcode = errno;
if (errcode != EINTR)
if (errcode == EINTR &&
(priv->options & READLINE_RETURN_ON_EINTR) != 0)
{
priv->errcode = errcode;
return EOF;
}
else if (errcode != EINTR)
{
/* Return EOF on any errors that we cannot handle */

Expand Down Expand Up @@ -218,6 +226,16 @@ static void readline_write(FAR struct rl_common_s *vtbl,
****************************************************************************/

ssize_t readline_fd(FAR char *buf, int buflen, int infd, int outfd)
{
return readline_fd_ex(buf, buflen, infd, outfd, 0);
}

/****************************************************************************
* Name: readline_fd_ex
****************************************************************************/

ssize_t readline_fd_ex(FAR char *buf, int buflen, int infd, int outfd,
unsigned int options)
{
UNUSED(outfd);

Expand All @@ -240,6 +258,8 @@ ssize_t readline_fd(FAR char *buf, int buflen, int infd, int outfd)

vtbl.vtbl.rl_getc = readline_getc;
vtbl.infd = infd;
vtbl.options = options;
vtbl.errcode = 0;

#ifdef CONFIG_READLINE_ECHO
vtbl.vtbl.rl_putc = readline_putc;
Expand All @@ -249,12 +269,17 @@ ssize_t readline_fd(FAR char *buf, int buflen, int infd, int outfd)

/* The let the common readline logic do the work */

ret = readline_common(&vtbl.vtbl, buf, buflen);
ret = readline_common(&vtbl.vtbl, buf, buflen, options);

if (isatty(infd) && (cfg.c_lflag & ICANON))
{
tcsetattr(infd, TCSANOW, &cfg);
}

if (vtbl.errcode != 0)
{
ret = -vtbl.errcode;
}

return ret;
}
Loading