mirror of
https://github.com/apache/nuttx-apps.git
synced 2025-10-19 11:23:07 +08:00
apps/system/cle/cle.c: This commit modifies the cle to use the streams file interface more consistently and has removed the observed race conditions. It was previously a mix of streams and fileio. It also simplifies the VT100 cursor position handling.
This commit is contained in:

committed by
Gregory Nutt

parent
af6719d78d
commit
dbd4e67241
@@ -149,7 +149,7 @@ int nsh_session(FAR struct console_stdio_s *pstate)
|
|||||||
{
|
{
|
||||||
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
|
fprintf(pstate->cn_errstream, g_fmtcmdfailed, "nsh_session",
|
||||||
"cle", NSH_ERRNO_OF(-ret));
|
"cle", NSH_ERRNO_OF(-ret));
|
||||||
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
|
continue;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Display the prompt string */
|
/* Display the prompt string */
|
||||||
|
166
system/cle/cle.c
166
system/cle/cle.c
@@ -172,8 +172,8 @@ struct cle_s
|
|||||||
uint16_t coloffs; /* Left cursor offset */
|
uint16_t coloffs; /* Left cursor offset */
|
||||||
uint16_t linelen; /* Size of the line buffer */
|
uint16_t linelen; /* Size of the line buffer */
|
||||||
uint16_t nchars; /* Size of data in the line buffer */
|
uint16_t nchars; /* Size of data in the line buffer */
|
||||||
int infd; /* Input file descriptor */
|
FAR FILE *ins; /* Input file stream */
|
||||||
int outfd; /* Output file descriptor */
|
FAR FILE *outs; /* Output file stream */
|
||||||
FAR char *line; /* Line buffer */
|
FAR char *line; /* Line buffer */
|
||||||
FAR const char *prompt; /* Prompt, in case we have to re-print it */
|
FAR const char *prompt; /* Prompt, in case we have to re-print it */
|
||||||
};
|
};
|
||||||
@@ -297,9 +297,9 @@ static void cle_write(FAR struct cle_s *priv, FAR const char *buffer,
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Take the next gulp */
|
/* Put the next gulp */
|
||||||
|
|
||||||
nwritten = write(priv->outfd, buffer, buflen);
|
nwritten = fwrite(buffer, sizeof(char), buflen, priv->outs);
|
||||||
|
|
||||||
/* Handle write errors. write() should neve return 0. */
|
/* Handle write errors. write() should neve return 0. */
|
||||||
|
|
||||||
@@ -327,6 +327,8 @@ static void cle_write(FAR struct cle_s *priv, FAR const char *buffer,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (nremaining > 0);
|
while (nremaining > 0);
|
||||||
|
|
||||||
|
fflush(priv->outs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -363,7 +365,7 @@ static int cle_getch(FAR struct cle_s *priv)
|
|||||||
{
|
{
|
||||||
/* Read one character from the incoming stream */
|
/* Read one character from the incoming stream */
|
||||||
|
|
||||||
nread = read(priv->infd, &buffer, 1);
|
nread = fread (&buffer, sizeof(char), 1, priv->ins);
|
||||||
|
|
||||||
/* Check for error or end-of-file. */
|
/* Check for error or end-of-file. */
|
||||||
|
|
||||||
@@ -520,118 +522,70 @@ static int cle_getcursor(FAR struct cle_s *priv, FAR uint16_t *prow,
|
|||||||
|
|
||||||
cle_write(priv, g_getcursor, sizeof(g_getcursor));
|
cle_write(priv, g_getcursor, sizeof(g_getcursor));
|
||||||
|
|
||||||
/* We expect to get ESC[v;hR where v is the row and h is the column */
|
/* We expect to get back ESC[v;hR where v is the row and h is the column.
|
||||||
|
* once the sequence has started we don't expect any characters
|
||||||
|
* interspersed.
|
||||||
|
*/
|
||||||
|
|
||||||
nbad = 0;
|
for (nbad = 0; nbad < 10; nbad++)
|
||||||
for (; ; )
|
|
||||||
{
|
{
|
||||||
/* Get the next character from the input */
|
/* Look for initial ESC */
|
||||||
|
|
||||||
ch = cle_getch(priv);
|
ch = cle_getch(priv);
|
||||||
if (ch == ASCII_ESC)
|
if (ch != ASCII_ESC)
|
||||||
{
|
{
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
else if (ch < 0)
|
|
||||||
{
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
else if (++nbad > 3)
|
|
||||||
{
|
|
||||||
/* We are probably talking to a non-VT100 terminal! */
|
|
||||||
|
|
||||||
return -EINVAL;
|
/* Have ESC, now we expect '[' */
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Have ESC, now we expect '[' */
|
|
||||||
|
|
||||||
nbad = 0;
|
|
||||||
for (; ; )
|
|
||||||
{
|
|
||||||
/* Get the next character from the input */
|
|
||||||
|
|
||||||
ch = cle_getch(priv);
|
ch = cle_getch(priv);
|
||||||
if (ch == '[')
|
if (ch != '[')
|
||||||
{
|
{
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
else if (ch < 0)
|
|
||||||
|
/* ...now we expect to see a numeric value terminated with ';' */
|
||||||
|
|
||||||
|
row = 0;
|
||||||
|
|
||||||
|
while (isdigit(ch = cle_getch(priv)))
|
||||||
{
|
{
|
||||||
return -EIO;
|
row = row * 10 + (ch - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ch != ';')
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ...now we expect to see another numeric value terminated with 'R' */
|
||||||
|
|
||||||
|
column = 0;
|
||||||
|
while (isdigit(ch = cle_getch(priv)))
|
||||||
|
{
|
||||||
|
column = 10 * column + (ch - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ...we are done */
|
||||||
|
|
||||||
|
cleinfo("row=%ld column=%ld\n", row, column);
|
||||||
|
|
||||||
|
/* Make sure that the values are within range */
|
||||||
|
|
||||||
|
if (row <= UINT16_MAX && column <= UINT16_MAX)
|
||||||
|
{
|
||||||
|
*prow = row;
|
||||||
|
*pcolumn = column;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We are probably talking to a non-VT100 terminal! */
|
return -ERANGE;
|
||||||
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Have ESC'['. Now we expect to see a numeric value terminated with ';' */
|
return -EINVAL;
|
||||||
|
|
||||||
row = 0;
|
|
||||||
for (; ; )
|
|
||||||
{
|
|
||||||
/* Get the next character from the input */
|
|
||||||
|
|
||||||
ch = cle_getch(priv);
|
|
||||||
if (isdigit(ch))
|
|
||||||
{
|
|
||||||
row = 10*row + (ch - '0');
|
|
||||||
}
|
|
||||||
else if (ch == ';')
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ch < 0)
|
|
||||||
{
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Have ESC'['v';'. Now we expect to see another numeric value terminated with 'R' */
|
|
||||||
|
|
||||||
column = 0;
|
|
||||||
for (; ; )
|
|
||||||
{
|
|
||||||
/* Get the next character from the input */
|
|
||||||
|
|
||||||
ch = cle_getch(priv);
|
|
||||||
if (isdigit(ch))
|
|
||||||
{
|
|
||||||
column = 10*column + (ch - '0');
|
|
||||||
}
|
|
||||||
else if (ch == 'R')
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (ch < 0)
|
|
||||||
{
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cleinfo("row=%ld column=%ld\n", row, column);
|
|
||||||
|
|
||||||
/* Make sure that the values are within range */
|
|
||||||
|
|
||||||
if (row <= UINT16_MAX && column <= UINT16_MAX)
|
|
||||||
{
|
|
||||||
*prow = row;
|
|
||||||
*pcolumn = column;
|
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -ERANGE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -891,8 +845,8 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
case '3': /* ESC[3~ = DEL */
|
case '3': /* ESC[3~ = DEL */
|
||||||
{
|
{
|
||||||
state = ch;
|
state = ch;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
case 'A':
|
case 'A':
|
||||||
{
|
{
|
||||||
@@ -943,6 +897,7 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
{
|
{
|
||||||
ch = KEY_ENDLINE;
|
ch = KEY_ENDLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
break; /* Break the 'for' loop */
|
break; /* Break the 'for' loop */
|
||||||
}
|
}
|
||||||
else if (state == '3')
|
else if (state == '3')
|
||||||
@@ -951,6 +906,7 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
{
|
{
|
||||||
ch = KEY_DEL;
|
ch = KEY_DEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
break; /* Break the 'for' loop */
|
break; /* Break the 'for' loop */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -996,6 +952,7 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
{
|
{
|
||||||
g_cmd_history_steps_from_head = -(g_cmd_history_len - 1);
|
g_cmd_history_steps_from_head = -(g_cmd_history_len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case KEY_DN:
|
case KEY_DN:
|
||||||
@@ -1008,6 +965,7 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
{
|
{
|
||||||
g_cmd_history_steps_from_head = 1;
|
g_cmd_history_steps_from_head = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1043,6 +1001,7 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
|
|
||||||
priv->curpos = priv->nchars;
|
priv->curpos = priv->nchars;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1226,10 +1185,8 @@ int cle(FAR char *line, const char *prompt, uint16_t linelen,
|
|||||||
priv.linelen = linelen;
|
priv.linelen = linelen;
|
||||||
priv.line = line;
|
priv.line = line;
|
||||||
|
|
||||||
/* REVISIT: Non-standard, non-portable */
|
priv.ins = instream;
|
||||||
|
priv.outs = outstream;
|
||||||
priv.infd = instream->fs_fd;
|
|
||||||
priv.outfd = outstream->fs_fd;
|
|
||||||
|
|
||||||
/* Store the prompt in case we need to re-print it */
|
/* Store the prompt in case we need to re-print it */
|
||||||
|
|
||||||
@@ -1239,6 +1196,7 @@ int cle(FAR char *line, const char *prompt, uint16_t linelen,
|
|||||||
/* Get the current cursor position */
|
/* Get the current cursor position */
|
||||||
|
|
||||||
ret = cle_getcursor(&priv, &priv.row, &column);
|
ret = cle_getcursor(&priv, &priv.row, &column);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
|
Reference in New Issue
Block a user