Add test and [ commands
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@864 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
0179e3a363
commit
51ca48986f
@ -440,4 +440,5 @@
|
||||
* fseek() needs to discard bytes buffered by ungetc().
|
||||
* Corrected ftell() return value.
|
||||
* Added fsetpos() and fgetpos().
|
||||
* NSH now supports 'test' and '[' commands
|
||||
|
||||
|
@ -456,7 +456,7 @@
|
||||
</table>
|
||||
|
||||
<p>
|
||||
The 2tth release of NuttX (nuttx-0.3.13) is available for download
|
||||
The 25th release of NuttX (nuttx-0.3.13) is available for download
|
||||
from the <a href="http://sourceforge.net/project/showfiles.php?group_id=189573">SourceForge</a>
|
||||
website.
|
||||
The change log associated with the release is available <a href="#currentrelease">here</a>.
|
||||
@ -1067,6 +1067,7 @@ nuttx-0.3.14 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
* fseek() needs to discard bytes buffered by ungetc().
|
||||
* Corrected ftell() return value.
|
||||
* Added fsetpos() and fgetpos().
|
||||
* NSH now supports 'test' and '[' commands
|
||||
|
||||
pascal-0.1.3 2008-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
|
||||
|
@ -37,6 +37,7 @@ examples/nsh
|
||||
|
||||
Command Depends on Configuration
|
||||
---------- --------------------------
|
||||
[ !CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
cat CONFIG_NFILE_DESCRIPTORS > 0
|
||||
cd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0
|
||||
cp CONFIG_NFILE_DESCRIPTORS > 0
|
||||
@ -54,15 +55,38 @@ examples/nsh
|
||||
mount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_FAT
|
||||
ps --
|
||||
pwd !CONFIG_DISABLE_ENVIRON && CONFIG_NFILE_DESCRIPTORS > 0
|
||||
set !CONFIG_DISABLE_ENVIRON
|
||||
sleep !CONFIG_DISABLE_SIGNALS
|
||||
sh CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
|
||||
rm !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0
|
||||
rmdir !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0
|
||||
set !CONFIG_DISABLE_ENVIRON
|
||||
sh CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
sleep !CONFIG_DISABLE_SIGNALS
|
||||
test !CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
umount !CONFIG_DISABLE_MOUNTPOINT && CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_FS_FAT
|
||||
unset !CONFIG_DISABLE_ENVIRON
|
||||
usleep !CONFIG_DISABLE_SIGNALS
|
||||
|
||||
Test syntax:
|
||||
|
||||
expression = simple-expression | !expression |
|
||||
expression -o expression | expression -a expression
|
||||
|
||||
simple-expression = unary-expression | binary-expression
|
||||
|
||||
unary-expression = string-unary | file-unary
|
||||
|
||||
string-unary = -n string | -z string
|
||||
|
||||
file-unary = -b file | -c file | -d file | -e file | -f file |
|
||||
-r file | -s file | -w file
|
||||
|
||||
binary-expression = string-binary | numeric-binary
|
||||
|
||||
string-binary = string = string | string == string | string != string
|
||||
|
||||
numeric-binary = integer -eq integer | integer -ge integer |
|
||||
integer -gt integer | integer -le integer |
|
||||
integer -lt integer | integer -ne integer
|
||||
|
||||
Other behavior of NSH can be modified with the following settings in
|
||||
the configs/<board-name>/defconfig file:
|
||||
|
||||
@ -87,6 +111,12 @@ examples/nsh
|
||||
The maximum number of nested if-then[-else]-fi sequences that
|
||||
are permissable. Default: 3
|
||||
|
||||
* CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
This can be set to 'y' to suppress support for scripting. This
|
||||
setting disables the 'sh', 'test', and '[' commands and the
|
||||
if-then[-else]-fi construct. This would only be set on systems
|
||||
where a minimal footprint is a necessity and scripting is not.
|
||||
|
||||
* CONFIG_EXAMPLES_NSH_CONSOLE
|
||||
If CONFIG_EXAMPLES_NSH_CONSOLE is set to 'y', then a serial
|
||||
console front-end is selected.
|
||||
|
@ -53,6 +53,10 @@ ifeq ($(CONFIG_EXAMPLES_NSH_TELNET),y)
|
||||
CSRCS += nsh_telnetd.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_EXAMPLES_NSH_DISABLESCRIPT),y)
|
||||
CSRCS += nsh_test.c
|
||||
endif
|
||||
|
||||
AOBJS = $(ASRCS:.S=$(OBJEXT))
|
||||
COBJS = $(CSRCS:.c=$(OBJEXT))
|
||||
|
||||
|
@ -163,7 +163,9 @@ struct nsh_parser_s
|
||||
#endif
|
||||
boolean np_redirect; /* TRUE: Output from the last command was re-directed */
|
||||
boolean np_fail; /* TRUE: The last command failed */
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
ubyte np_ndx; /* Current index into np_st[] */
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
int np_nice; /* "nice" value applied to last background cmd */
|
||||
#endif
|
||||
@ -172,7 +174,9 @@ struct nsh_parser_s
|
||||
* execution of commands that span multiple lines (like if-then-else-fi)
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
struct nsh_state_s np_st[CONFIG_EXAMPLES_NSH_NESTDEPTH];
|
||||
#endif
|
||||
};
|
||||
|
||||
struct nsh_vtbl_s
|
||||
@ -207,11 +211,11 @@ typedef int (*cmd_t)(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
|
||||
extern const char g_nshgreeting[];
|
||||
extern const char g_nshprompt[];
|
||||
extern const char g_nshsyntax[];
|
||||
extern const char g_fmtargrequired[];
|
||||
extern const char g_fmtarginvalid[];
|
||||
extern const char g_fmtargrange[];
|
||||
extern const char g_fmtcmdnotfound[];
|
||||
extern const char g_fmtcmdnotimpl[];
|
||||
extern const char g_fmtnosuch[];
|
||||
extern const char g_fmttoomanyargs[];
|
||||
extern const char g_fmtdeepnesting[];
|
||||
@ -256,13 +260,18 @@ extern int cmd_mw(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
extern int cmd_mem(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
extern int cmd_ps(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
extern int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
extern int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
#endif
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
extern int cmd_cat(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
extern int cmd_cp(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
extern int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
# if CONFIG_NFILE_STREAMS > 0
|
||||
# if CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_EXAMPLES_NSH_DISABLESCRIPT)
|
||||
extern int cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
# endif /* CONFIG_NFILE_STREAMS */
|
||||
# endif /* CONFIG_NFILE_STREAMS && !CONFIG_EXAMPLES_NSH_DISABLESCRIPT */
|
||||
# ifndef CONFIG_DISABLE_MOUNTPOINT
|
||||
extern int cmd_mkdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
extern int cmd_mkfifo(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv);
|
||||
|
@ -905,7 +905,7 @@ int cmd_rmdir(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
* Name: cmd_sh
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_EXAMPLES_NSH_DISABLESCRIPT)
|
||||
int cmd_sh(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
char *fullpath;
|
||||
|
@ -128,6 +128,9 @@ static const char g_failure[] = "1";
|
||||
|
||||
static const struct cmdmap_s g_cmdmap[] =
|
||||
{
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
{ "[", cmd_lbracket, 4, NSH_MAX_ARGUMENTS, "<expression> ]" },
|
||||
#endif
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0
|
||||
{ "cat", cmd_cat, 2, NSH_MAX_ARGUMENTS, "<path> [<path> [<path> ...]]" },
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
@ -169,19 +172,22 @@ static const struct cmdmap_s g_cmdmap[] =
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && !defined(CONFIG_DISABLE_ENVIRON)
|
||||
{ "pwd", cmd_pwd, 1, 1, NULL },
|
||||
#endif
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
{ "set", cmd_set, 3, 3, "<name> <value>" },
|
||||
#endif
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
|
||||
{ "rm", cmd_rm, 2, 2, "<file-path>" },
|
||||
{ "rmdir", cmd_rmdir, 2, 2, "<dir-path>" },
|
||||
#endif
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0
|
||||
#ifndef CONFIG_DISABLE_ENVIRON
|
||||
{ "set", cmd_set, 3, 3, "<name> <value>" },
|
||||
#endif
|
||||
#if CONFIG_NFILE_DESCRIPTORS > 0 && CONFIG_NFILE_STREAMS > 0 && !defined(CONFIG_EXAMPLES_NSH_DISABLESCRIPT)
|
||||
{ "sh", cmd_sh, 2, 2, "<script-path>" },
|
||||
#endif /* CONFIG_NFILE_DESCRIPTORS && CONFIG_NFILE_STREAMS */
|
||||
#ifndef CONFIG_DISABLE_SIGNALS
|
||||
{ "sleep", cmd_sleep, 2, 2, "<sec>" },
|
||||
#endif /* CONFIG_DISABLE_SIGNALS */
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
{ "test", cmd_test, 3, NSH_MAX_ARGUMENTS, "<expression>" },
|
||||
#endif
|
||||
#if !defined(CONFIG_DISABLE_MOUNTPOINT) && CONFIG_NFILE_DESCRIPTORS > 0
|
||||
# ifdef CONFIG_FS_FAT /* Need at least one filesytem in configuration */
|
||||
{ "umount", cmd_umount, 2, 2, "<dir-path>" },
|
||||
@ -202,11 +208,11 @@ static const struct cmdmap_s g_cmdmap[] =
|
||||
|
||||
const char g_nshgreeting[] = "NuttShell (NSH)\n";
|
||||
const char g_nshprompt[] = "nsh> ";
|
||||
const char g_nshsyntax[] = "nsh: %s: syntax error\n";
|
||||
const char g_fmtargrequired[] = "nsh: %s: missing required argument(s)\n";
|
||||
const char g_fmtarginvalid[] = "nsh: %s: argument invalid\n";
|
||||
const char g_fmtargrange[] = "nsh: %s: value out of range\n";
|
||||
const char g_fmtcmdnotfound[] = "nsh: %s: command not found\n";
|
||||
const char g_fmtcmdnotimpl[] = "nsh: %s: command not implemented\n";
|
||||
const char g_fmtnosuch[] = "nsh: %s: no such %s: %s\n";
|
||||
const char g_fmttoomanyargs[] = "nsh: %s: too many arguments\n";
|
||||
const char g_fmtdeepnesting[] = "nsh: %s: nesting too deep\n";
|
||||
@ -237,6 +243,7 @@ static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
#else
|
||||
nsh_output(vtbl, " <cmd> [> <file>|>> <file>]\n");
|
||||
#endif
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
nsh_output(vtbl, "OR\n");
|
||||
nsh_output(vtbl, " if <cmd>\n");
|
||||
nsh_output(vtbl, " then\n");
|
||||
@ -244,6 +251,7 @@ static int cmd_help(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
nsh_output(vtbl, " else\n");
|
||||
nsh_output(vtbl, " [sequence of <cmd>]\n");
|
||||
nsh_output(vtbl, " fi\n");
|
||||
#endif
|
||||
nsh_output(vtbl, "Where <cmd> is one of:\n");
|
||||
for (ptr = g_cmdmap; ptr->cmd; ptr++)
|
||||
{
|
||||
@ -569,6 +577,7 @@ char *nsh_argument(FAR struct nsh_vtbl_s *vtbl, char **saveptr)
|
||||
* Name: nsh_cmdenabled
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
static inline boolean nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
|
||||
{
|
||||
struct nsh_parser_s *np = &vtbl->np;
|
||||
@ -593,11 +602,13 @@ static inline boolean nsh_cmdenabled(FAR struct nsh_vtbl_s *vtbl)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_ifthenelse
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
static inline int nsh_ifthenelse(FAR struct nsh_vtbl_s *vtbl, FAR char **ppcmd, FAR char **saveptr)
|
||||
{
|
||||
struct nsh_parser_s *np = &vtbl->np;
|
||||
@ -730,6 +741,7 @@ errout:
|
||||
np->np_st[0].ns_ifcond = FALSE;
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_saveresult
|
||||
@ -739,6 +751,7 @@ static inline int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, boolean result)
|
||||
{
|
||||
struct nsh_parser_s *np = &vtbl->np;
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
if (np->np_st[np->np_ndx].ns_state == NSH_PARSER_IF)
|
||||
{
|
||||
np->np_fail = FALSE;
|
||||
@ -746,6 +759,7 @@ static inline int nsh_saveresult(FAR struct nsh_vtbl_s *vtbl, boolean result)
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
np->np_fail = result;
|
||||
return result ? ERROR : OK;
|
||||
@ -898,10 +912,12 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
|
||||
|
||||
/* Handler if-then-else-fi */
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
if (nsh_ifthenelse(vtbl, &cmd, &saveptr) != 0)
|
||||
{
|
||||
goto errout;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handle nice */
|
||||
|
||||
@ -916,7 +932,11 @@ int nsh_parse(FAR struct nsh_vtbl_s *vtbl, char *cmdline)
|
||||
* currently disabled.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
if (!cmd || !nsh_cmdenabled(vtbl))
|
||||
#else
|
||||
if (!cmd)
|
||||
#endif
|
||||
{
|
||||
/* An empty line is not an error and an unprocessed command cannot
|
||||
* generate an error, but neither should they change the last
|
||||
|
446
examples/nsh/nsh_test.c
Normal file
446
examples/nsh/nsh_test.c
Normal file
@ -0,0 +1,446 @@
|
||||
/****************************************************************************
|
||||
* examples/nsh/nsh_test.c
|
||||
*
|
||||
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/* Test syntax:
|
||||
*
|
||||
* expression = simple-expression | !expression |
|
||||
* expression -o expression | expression -a expression
|
||||
*
|
||||
* simple-expression = unary-expression | binary-expression
|
||||
*
|
||||
* unary-expression = string-unary | file-unary
|
||||
*
|
||||
* string-unary = -n string | -z string
|
||||
*
|
||||
* file-unary = -b file | -c file | -d file | -e file | -f file |
|
||||
* -r file | -s file | -w file
|
||||
*
|
||||
* binary-expression = string-binary | numeric-binary
|
||||
*
|
||||
* string-binary = string = string | string == string | string != string
|
||||
*
|
||||
* numeric-binary = integer -eq integer | integer -ge integer |
|
||||
* integer -gt integer | integer -le integer |
|
||||
* integer -lt integer | integer -ne integer
|
||||
*
|
||||
* Note that the smallest expression consists of two strings.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nsh.h"
|
||||
|
||||
#ifndef CONFIG_EXAMPLES_NSH_DISABLESCRIPT
|
||||
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define TEST_TRUE OK
|
||||
#define TEST_FALSE ERROR
|
||||
#define TEST_ERROR 1
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: binaryexpression
|
||||
****************************************************************************/
|
||||
|
||||
static inline int binaryexpression(FAR struct nsh_vtbl_s *vtbl, char **argv)
|
||||
{
|
||||
char *endptr;
|
||||
long integer1;
|
||||
long integer2;
|
||||
|
||||
/* STRING2 = STRING2 */
|
||||
|
||||
if (strcmp(argv[1], "=") == 0 || strcmp(argv[1], "==") == 0)
|
||||
{
|
||||
/* Return true if the strings are identical */
|
||||
|
||||
return strcmp(argv[0], argv[2]) == 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* STRING1 != STRING2 */
|
||||
|
||||
if (strcmp(argv[1], "!=") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return strcmp(argv[0], argv[2]) != 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* The remaining operators assuming that the two values are integers */
|
||||
|
||||
integer1 = strtol(argv[0], &endptr, 0);
|
||||
if (argv[0][0] == '\0' || *endptr != '\0')
|
||||
{
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
integer2 = strtol(argv[2], &endptr, 0);
|
||||
if (argv[2][0] == '\0' || *endptr != '\0')
|
||||
{
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
/* INTEGER1 -eq INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-eq") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 == integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -ge INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-ge") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 >= integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -gt INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-gt") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 > integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -le INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-le") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 <= integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -lt INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-lt") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 < integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* INTEGER1 -ne INTEGER2 */
|
||||
|
||||
if (strcmp(argv[1], "-ne") == 0)
|
||||
{
|
||||
/* Return true if the strings are different */
|
||||
|
||||
return integer1 != integer2 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: unaryexpression
|
||||
****************************************************************************/
|
||||
|
||||
static inline int unaryexpression(FAR struct nsh_vtbl_s *vtbl, char **argv)
|
||||
{
|
||||
struct stat buf;
|
||||
char *fullpath;
|
||||
int ret;
|
||||
|
||||
/* -n STRING */
|
||||
|
||||
if (strcmp(argv[0], "-n") == 0)
|
||||
{
|
||||
/* Return true if the length of the string is non-zero */
|
||||
|
||||
return strlen(argv[1]) != 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -z STRING */
|
||||
|
||||
if (strcmp(argv[0], "-z") == 0)
|
||||
{
|
||||
/* Return true if the length of the string is zero */
|
||||
|
||||
return strlen(argv[1]) == 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* All of the remaining assume that the following argument is the
|
||||
* path to a file.
|
||||
*/
|
||||
|
||||
fullpath = nsh_getfullpath(vtbl, argv[1]);
|
||||
if (!fullpath)
|
||||
{
|
||||
return TEST_FALSE;
|
||||
}
|
||||
|
||||
ret = stat(fullpath, &buf);
|
||||
nsh_freefullpath(fullpath);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
/* The file does not exist (or another error occurred) -- return FALSE */
|
||||
|
||||
return TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -b FILE */
|
||||
|
||||
if (strcmp(argv[0], "-b") == 0)
|
||||
{
|
||||
/* Return true if the path is a block device */
|
||||
|
||||
return S_ISBLK(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -c FILE */
|
||||
|
||||
if (strcmp(argv[0], "-c") == 0)
|
||||
{
|
||||
/* Return true if the path is a character device */
|
||||
|
||||
return S_ISCHR(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -d FILE */
|
||||
|
||||
if (strcmp(argv[0], "-d") == 0)
|
||||
{
|
||||
/* Return true if the path is a directory */
|
||||
|
||||
return S_ISDIR(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -e FILE */
|
||||
|
||||
if (strcmp(argv[0], "-e") == 0)
|
||||
{
|
||||
/* Return true if the file exists */
|
||||
|
||||
return TEST_TRUE;
|
||||
}
|
||||
|
||||
/* -f FILE */
|
||||
|
||||
if (strcmp(argv[0], "-f") == 0)
|
||||
{
|
||||
/* Return true if the path refers to a regular file */
|
||||
|
||||
return S_ISREG(buf.st_mode) ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -r FILE */
|
||||
|
||||
if (strcmp(argv[0], "-r") == 0)
|
||||
{
|
||||
/* Return true if the file is readable */
|
||||
|
||||
return (buf.st_mode & (S_IRUSR|S_IRGRP|S_IROTH)) != 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -s FILE */
|
||||
|
||||
if (strcmp(argv[0], "-s") == 0)
|
||||
{
|
||||
/* Return true if the size of the file is greater than zero */
|
||||
|
||||
return buf.st_size > 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* -w FILE */
|
||||
|
||||
if (strcmp(argv[0], "-w") == 0)
|
||||
{
|
||||
/* Return true if the file is write-able */
|
||||
|
||||
return (buf.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)) != 0 ? TEST_TRUE : TEST_FALSE;
|
||||
}
|
||||
|
||||
/* Unrecognized operator */
|
||||
|
||||
return TEST_ERROR;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: expression
|
||||
****************************************************************************/
|
||||
|
||||
static int expression(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
int value;
|
||||
boolean valid;
|
||||
int i = 0;
|
||||
|
||||
/* Check for unary operations on expressions */
|
||||
|
||||
if (strcmp(argv[0], "!") == 0)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
return expression(vtbl, argc-1, &argv[1]) == TEST_TRUE ? TEST_FALSE : TEST_TRUE;
|
||||
}
|
||||
|
||||
/* Check for unary operations on simple, typed arguments */
|
||||
|
||||
else if (argv[0][0] == '-')
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
i += 2;
|
||||
value = unaryexpression(vtbl, argv);
|
||||
}
|
||||
|
||||
/* Check for binary operations on simple, typed arguments */
|
||||
|
||||
else
|
||||
{
|
||||
if (argc < 3)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
i += 3;
|
||||
value = binaryexpression(vtbl, argv);
|
||||
}
|
||||
|
||||
/* Test if there any failure */
|
||||
|
||||
if (value == TEST_ERROR)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
|
||||
/* Is there anything after the simple expression? */
|
||||
|
||||
if (i < argc)
|
||||
{
|
||||
/* EXPRESSION -a EXPRESSION */
|
||||
|
||||
if (strcmp(argv[i], "-a") == 0)
|
||||
{
|
||||
if (!valid)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
else if (value != TEST_TRUE)
|
||||
{
|
||||
return TEST_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
return expression(vtbl, argc-i, &argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* EXPRESSION -o EXPRESSION */
|
||||
|
||||
else if (strcmp(argv[i], "-o") == 0)
|
||||
{
|
||||
if (!valid)
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
else if (value == TEST_TRUE)
|
||||
{
|
||||
return TEST_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
i++;
|
||||
return expression(vtbl, argc-i, &argv[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto errout_syntax;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
|
||||
errout_syntax:
|
||||
nsh_output(vtbl, g_nshsyntax, "test");
|
||||
return TEST_FALSE;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_test
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_test(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
return expression(vtbl, argc-1, &argv[1]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cmd_lbracket
|
||||
****************************************************************************/
|
||||
|
||||
int cmd_lbracket(FAR struct nsh_vtbl_s *vtbl, int argc, char **argv)
|
||||
{
|
||||
if (strcmp(argv[argc-1], "]") != 0)
|
||||
{
|
||||
nsh_output(vtbl, g_nshsyntax, argv[0]);
|
||||
return ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return expression(vtbl, argc-2, &argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_EXAMPLES_NSH_DISABLESCRIPT */
|
Loading…
Reference in New Issue
Block a user