summaryrefslogtreecommitdiff
path: root/apps/nshlib
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-01-17 13:24:44 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-01-17 13:24:44 -0600
commit3895a010a5c8d971ec04802ae569f44a06bd572b (patch)
treed81fc78a1873dd6faa5b634845ddb940c6ce2cab /apps/nshlib
parent5d3165161596265372177859b50577ae1ee54be0 (diff)
downloadnuttx-3895a010a5c8d971ec04802ae569f44a06bd572b.tar.gz
nuttx-3895a010a5c8d971ec04802ae569f44a06bd572b.tar.bz2
nuttx-3895a010a5c8d971ec04802ae569f44a06bd572b.zip
Add true and false commands; repartition some logic to better support forthcoming looping
Diffstat (limited to 'apps/nshlib')
-rw-r--r--apps/nshlib/nsh.h39
-rw-r--r--apps/nshlib/nsh_command.c38
-rw-r--r--apps/nshlib/nsh_parse.c77
-rw-r--r--apps/nshlib/nsh_script.c36
4 files changed, 133 insertions, 57 deletions
diff --git a/apps/nshlib/nsh.h b/apps/nshlib/nsh.h
index a38d04c4a..a9db6e5d2 100644
--- a/apps/nshlib/nsh.h
+++ b/apps/nshlib/nsh.h
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/nshlib/nsh.h
*
- * Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -453,23 +453,28 @@
/****************************************************************************
* Public Types
****************************************************************************/
+/* State when parsing and if-then-else sequence */
enum nsh_parser_e
{
- NSH_PARSER_NORMAL = 0,
- NSH_PARSER_IF,
- NSH_PARSER_THEN,
- NSH_PARSER_ELSE
+ NSH_PARSER_NORMAL = 0, /* Not in any special sequence */
+ NSH_PARSER_IF, /* Just parsed 'if', expect condition */
+ NSH_PARSER_THEN, /* Just parsed 'then', looking for 'else' or 'fi' */
+ NSH_PARSER_ELSE /* Just parsed 'else', look for 'fi' */
};
-struct nsh_state_s
+/* All state data for parsing one if-then-else sequence */
+
+struct nsh_ifthenelse_s
{
- uint8_t ns_ifcond : 1; /* Value of command in 'if' statement */
- uint8_t ns_disabled : 1; /* TRUE: Unconditionally disabled */
- uint8_t ns_unused : 4;
- uint8_t ns_state : 2; /* Parser state (see enum nsh_parser_e) */
+ uint8_t ie_ifcond : 1; /* Value of command in 'if' statement */
+ uint8_t ie_disabled : 1; /* TRUE: Unconditionally disabled */
+ uint8_t ie_unused : 4;
+ uint8_t ie_state : 2; /* Parser state (see enum nsh_parser_e) */
};
+/* These structure provides the overall state of the parser */
+
struct nsh_parser_s
{
#ifndef CONFIG_NSH_DISABLEBG
@@ -479,19 +484,17 @@ struct nsh_parser_s
bool np_redirect; /* true: Output from the last command was re-directed */
#endif
bool np_fail; /* true: The last command failed */
-#ifndef CONFIG_NSH_DISABLESCRIPT
- uint8_t np_ndx; /* Current index into np_st[] */
-#endif
#ifndef CONFIG_NSH_DISABLEBG
int np_nice; /* "nice" value applied to last background cmd */
#endif
- /* This is a stack of parser state information. It supports nested
- * execution of commands that span multiple lines (like if-then-else-fi)
- */
-
#ifndef CONFIG_NSH_DISABLESCRIPT
- struct nsh_state_s np_st[CONFIG_NSH_NESTDEPTH];
+ FILE *np_stream; /* Stream of current script */
+ uint8_t np_iendx; /* Current index into np_iestate[] */
+
+ /* This is a stack of if-then-else state information. */
+
+ struct nsh_ifthenelse_s np_iestate[CONFIG_NSH_NESTDEPTH];
#endif
};
diff --git a/apps/nshlib/nsh_command.c b/apps/nshlib/nsh_command.c
index faf64bbe5..8321ad876 100644
--- a/apps/nshlib/nsh_command.c
+++ b/apps/nshlib/nsh_command.c
@@ -81,9 +81,15 @@ struct cmdmap_s
static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif
+#ifndef CONFIG_NSH_DISABLESCRIPT
+static int cmd_true(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+static int cmd_false(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
+#endif
+
#ifndef CONFIG_NSH_DISABLE_EXIT
static int cmd_exit(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
#endif
+
static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
/****************************************************************************
@@ -167,10 +173,15 @@ static const struct cmdmap_s g_cmdmap[] =
#ifndef CONFIG_NSH_DISABLE_EXEC
{ "exec", cmd_exec, 2, 3, "<hex-address>" },
#endif
+
#ifndef CONFIG_NSH_DISABLE_EXIT
{ "exit", cmd_exit, 1, 1, NULL },
#endif
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ { "false", cmd_false, 1, 1, NULL },
+#endif
+
#ifndef CONFIG_NSH_DISABLE_FREE
{ "free", cmd_free, 1, 1, NULL },
#endif
@@ -356,6 +367,10 @@ static const struct cmdmap_s g_cmdmap[] =
{ "test", cmd_test, 3, CONFIG_NSH_MAXARGUMENTS, "<expression>" },
#endif
+#ifndef CONFIG_NSH_DISABLESCRIPT
+ { "true", cmd_true, 1, 1, NULL },
+#endif
+
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0 && defined(CONFIG_FS_READABLE)
# ifndef CONFIG_NSH_DISABLE_UMOUNT
{ "umount", cmd_umount, 2, 2, "<dir-path>" },
@@ -645,6 +660,29 @@ static int cmd_unrecognized(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
}
/****************************************************************************
+ * Name: cmd_true
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+static int cmd_true(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return OK;
+}
+
+#endif
+
+/****************************************************************************
+ * Name: cmd_false
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLESCRIPT
+static int cmd_false(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
+{
+ return ERROR;
+}
+#endif
+
+/****************************************************************************
* Name: cmd_exit
****************************************************************************/
diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c
index c7ef521a1..a83b9e999 100644
--- a/apps/nshlib/nsh_parse.c
+++ b/apps/nshlib/nsh_parse.c
@@ -392,10 +392,10 @@ static int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, bool result)
struct nsh_parser_s *np = &vtbl->np;
#ifndef CONFIG_NSH_DISABLESCRIPT
- if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
+ if (np->np_iestate[np->np_iendx].ie_state == NSH_PARSER_IF)
{
np->np_fail = false;
- np->np_st[np->np_ndx].ns_ifcond = result;
+ np->np_iestate[np->np_iendx].ie_ifcond = result;
return OK;
}
else
@@ -1335,10 +1335,10 @@ static FAR char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, FAR char **saveptr,
static bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
{
struct nsh_parser_s *np = &vtbl->np;
- bool ret = !np->np_st[np->np_ndx].ns_disabled;
+ bool ret = !np->np_iestate[np->np_iendx].ie_disabled;
if (ret)
{
- switch (np->np_st[np->np_ndx].ns_state)
+ switch (np->np_iestate[np->np_iendx].ie_state)
{
case NSH_PARSER_NORMAL :
case NSH_PARSER_IF:
@@ -1346,11 +1346,11 @@ static bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
break;
case NSH_PARSER_THEN:
- ret = !np->np_st[np->np_ndx].ns_ifcond;
+ ret = !np->np_iestate[np->np_iendx].ie_ifcond;
break;
case NSH_PARSER_ELSE:
- ret = np->np_st[np->np_ndx].ns_ifcond;
+ ret = np->np_iestate[np->np_iendx].ie_ifcond;
break;
}
}
@@ -1367,13 +1367,13 @@ static bool nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
FAR char **saveptr, FAR NSH_MEMLIST_TYPE *memlist)
{
- struct nsh_parser_s *np = &vtbl->np;
+ FAR struct nsh_parser_s *np = &vtbl->np;
FAR char *cmd = *ppcmd;
bool disabled;
if (cmd)
{
- /* Check if the command is preceeded by "if" */
+ /* Check if the command is preceded by "if" */
if (strcmp(cmd, "if") == 0)
{
@@ -1388,9 +1388,9 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* Verify that "if" is valid in this context */
- if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_NORMAL &&
- np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN &&
- np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE)
+ if (np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_NORMAL &&
+ np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_THEN &&
+ np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_ELSE)
{
nsh_output(vtbl, g_fmtcontext, "if");
goto errout;
@@ -1398,7 +1398,7 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* Check if we have exceeded the maximum depth of nesting */
- if (np->np_ndx >= CONFIG_NSH_NESTDEPTH-1)
+ if (np->np_iendx >= CONFIG_NSH_NESTDEPTH-1)
{
nsh_output(vtbl, g_fmtdeepnesting, "if");
goto errout;
@@ -1406,12 +1406,15 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* "Push" the old state and set the new state */
- disabled = !nsh_cmdenabled(vtbl);
- np->np_ndx++;
- np->np_st[np->np_ndx].ns_state = NSH_PARSER_IF;
- np->np_st[np->np_ndx].ns_disabled = disabled;
- np->np_st[np->np_ndx].ns_ifcond = false;
+ disabled = !nsh_cmdenabled(vtbl);
+ np->np_iendx++;
+ np->np_iestate[np->np_iendx].ie_state = NSH_PARSER_IF;
+ np->np_iestate[np->np_iendx].ie_disabled = disabled;
+ np->np_iestate[np->np_iendx].ie_ifcond = false;
}
+
+ /* Check if the command is "then" */
+
else if (strcmp(cmd, "then") == 0)
{
/* Get the cmd following the then -- there shouldn't be one */
@@ -1425,13 +1428,17 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* Verify that "then" is valid in this context */
- if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_IF)
+ if (np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_IF)
{
nsh_output(vtbl, g_fmtcontext, "then");
goto errout;
}
- np->np_st[np->np_ndx].ns_state = NSH_PARSER_THEN;
+
+ np->np_iestate[np->np_iendx].ie_state = NSH_PARSER_THEN;
}
+
+ /* Check if the command is "else" */
+
else if (strcmp(cmd, "else") == 0)
{
/* Get the cmd following the else -- there shouldn't be one */
@@ -1443,15 +1450,19 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
goto errout;
}
- /* Verify that "then" is valid in this context */
+ /* Verify that "else" is valid in this context */
- if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN)
+ if (np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_THEN)
{
nsh_output(vtbl, g_fmtcontext, "else");
goto errout;
}
- np->np_st[np->np_ndx].ns_state = NSH_PARSER_ELSE;
+
+ np->np_iestate[np->np_iendx].ie_state = NSH_PARSER_ELSE;
}
+
+ /* Check if the command is "fi" */
+
else if (strcmp(cmd, "fi") == 0)
{
/* Get the cmd following the fi -- there should be one */
@@ -1465,14 +1476,14 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* Verify that "fi" is valid in this context */
- if (np->np_st[np->np_ndx].ns_state != NSH_PARSER_THEN &&
- np->np_st[np->np_ndx].ns_state != NSH_PARSER_ELSE)
+ if (np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_THEN &&
+ np->np_iestate[np->np_iendx].ie_state != NSH_PARSER_ELSE)
{
nsh_output(vtbl, g_fmtcontext, "fi");
goto errout;
}
- if (np->np_ndx < 1) /* Shouldn't happen */
+ if (np->np_iendx < 1) /* Shouldn't happen */
{
nsh_output(vtbl, g_fmtinternalerror, "if");
goto errout;
@@ -1480,21 +1491,25 @@ static int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd,
/* "Pop" the previous state */
- np->np_ndx--;
+ np->np_iendx--;
}
- else if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
+
+ /* If we just parsed 'if', then nothing is acceptable other than 'then' */
+
+ else if (np->np_iestate[np->np_iendx].ie_state == NSH_PARSER_IF)
{
nsh_output(vtbl, g_fmtcontext, cmd);
goto errout;
}
}
+
return OK;
errout:
- np->np_ndx = 0;
- np->np_st[0].ns_state = NSH_PARSER_NORMAL;
- np->np_st[0].ns_disabled = false;
- np->np_st[0].ns_ifcond = false;
+ np->np_iendx = 0;
+ np->np_iestate[0].ie_state = NSH_PARSER_NORMAL;
+ np->np_iestate[0].ie_disabled = false;
+ np->np_iestate[0].ie_ifcond = false;
return ERROR;
}
#endif
diff --git a/apps/nshlib/nsh_script.c b/apps/nshlib/nsh_script.c
index 3aa698b31..088df6878 100644
--- a/apps/nshlib/nsh_script.c
+++ b/apps/nshlib/nsh_script.c
@@ -83,10 +83,10 @@
int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
FAR const char *path)
{
- char *fullpath;
- FILE *stream;
- char *buffer;
- char *pret;
+ FAR char *fullpath;
+ FAR FILE *savestream;
+ FAR char *buffer;
+ FAR char *pret;
int ret = ERROR;
/* The path to the script may be relative to the current working directory */
@@ -102,13 +102,24 @@ int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
buffer = nsh_linebuffer(vtbl);
if (buffer)
{
+ /* Save the parent stream in case of nested script processing */
+
+ savestream = vtbl->np.np_stream;
+
/* Open the file containing the script */
- stream = fopen(fullpath, "r");
- if (!stream)
+ vtbl->np.np_stream = fopen(fullpath, "r");
+ if (!vtbl->np.np_stream)
{
nsh_output(vtbl, g_fmtcmdfailed, cmd, "fopen", NSH_ERRNO);
+
+ /* Free the allocated path */
+
nsh_freefullpath(fullpath);
+
+ /* Restore the parent script stream */
+
+ vtbl->np.np_stream = savestream;
return ERROR;
}
@@ -121,7 +132,7 @@ int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
/* Get the next line of input from the file */
fflush(stdout);
- pret = fgets(buffer, CONFIG_NSH_LINELEN, stream);
+ pret = fgets(buffer, CONFIG_NSH_LINELEN, vtbl->np.np_stream);
if (pret)
{
/* Parse process the command. NOTE: this is recursive...
@@ -133,9 +144,18 @@ int nsh_script(FAR struct nsh_vtbl_s *vtbl, FAR const char *cmd,
}
}
while (pret && ret == OK);
- fclose(stream);
+
+ /* Close the script file */
+
+ fclose(vtbl->np.np_stream);
+
+ /* Restore the parent script stream */
+
+ vtbl->np.np_stream = savestream;
}
+ /* Free the allocated path */
+
nsh_freefullpath(fullpath);
return ret;
}