📄 if.c
字号:
/* if.c:
* This file started off as the file for the "if" command in the monitor,
* and has since grown into the file that contains the commands that only
* make sense if they are used in scripts; hence, a prerequisite to these
* commands is that TFS is included in the build.
* It also contains the script runner portion of TFS. The name of this
* file should have been changed to tfsscript.c!
*
* if:
* Supports the monitor's ability to do conditional branching within
* scripts executed through TFS.
*
* goto:
* Tag based jumping in a script.
*
* item:
* A simple way to process a list (similar to KSH's 'for' construct).
*
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#include "config.h"
#include "genlib.h"
#include "stddefs.h"
#include "tfs.h"
#include "tfsprivate.h"
#include "ether.h"
#include "cli.h"
#if INCLUDE_TFSSCRIPT
/* Subroutine variables:
* The definition of MAXGOSUBDEPTH (15) determines the maximum number
* of subroutines that can be nested within any one script invocation.
* ReturnToTellTbl[]
* Used by script runner to keep track of the location in the file that
* the subroutine is supposed to return to.
* ReturnToDepth
* The current subroutine nesting depth of the script runner.
*/
#define MAXGOSUBDEPTH 15
static int ReturnToDepth;
static long ReturnToTellTbl[MAXGOSUBDEPTH+1];
static int CurrentScriptfdTbl[TFS_MAXOPEN+1];
/* ScriptIsRunning:
* Non-zero if a script is active, else zero.
*/
static int ScriptIsRunning;
/* ScriptGotoTag:
* Points to the string that is the most recent target of
* a goto or gosub command.
*/
static char *ScriptGotoTag;
/* ScriptExitFlag:
* If non-zero, then the script must exit.
* The 'exit' command will set this to either EXIT_SCRIPT (normal case)
* or 'EXIT_SCRIPT | REMOVE_SCRIPT' if the -r option of exit was used.
*/
int ScriptExitFlag;
/*****************************************************************************/
/* If:
* A simple test/action statement.
* Currently, the only action supported is "goto tag".
* Syntax:
* if ARG1 compar ARG2 {action} [else action]
* if -t TEST {action} [else action]
*/
char *IfHelp[] = {
"Conditional branching",
"-[t:v] [{arg1} {compar} {arg2}] {action} [else action]",
#if INCLUDE_VERBOSEHELP
" Options:",
" -t{test} see below",
" -v verbose mode (print TRUE or FALSE result)",
" Notes:",
" * Numerical/logical/string compare:",
" seq sne sin gt lt le ge eq ne and or xor",
" * Action:",
" goto tag | gosub tag | exit | return",
" * Other tests (-t args):",
" gc, ngc, iscmp {filename}",
#endif
0,
};
int
If(int argc, char *argv[])
{
int opt, arg, true, if_else, offset, verbose;
void (*iffunc)(), (*elsefunc)();
long var1, var2;
char *testtype, *arg1, *arg2, *iftag, *elsetag;
verbose = 0;
testtype = 0;
while((opt=getopt(argc,argv,"vt:")) != -1) {
switch(opt) {
case 'v':
verbose = 1;
break;
case 't':
testtype = optarg;
break;
default:
return(CMD_PARAM_ERROR);
}
}
elsetag = 0;
elsefunc = 0;
offset = true = if_else = 0;
/* First see if there is an 'else' present... */
for (arg=optind;arg<argc;arg++) {
if (!strcmp(argv[arg],"else")) {
if_else = 1;
break;
}
}
if (if_else) {
elsetag = argv[argc-1];
if (!strcmp(argv[argc-1],"exit")) {
offset = 2;
elsefunc = exitscript;
}
else if (!strcmp(argv[argc-1],"return")) {
offset = 2;
elsefunc = gosubret;
}
else if (!strcmp(argv[argc-2],"goto")) {
offset = 3;
elsefunc = gototag;
}
else if (!strcmp(argv[argc-2],"gosub")) {
offset = 3;
elsefunc = gosubtag;
}
else
return(CMD_PARAM_ERROR);
}
iftag = argv[argc-offset-1];
if (!strcmp(argv[argc-offset-1],"exit"))
iffunc = exitscript;
else if (!strcmp(argv[argc-offset-1],"return"))
iffunc = gosubret;
else if (!strcmp(argv[argc-offset-2],"goto"))
iffunc = gototag;
else if (!strcmp(argv[argc-offset-2],"gosub"))
iffunc = gosubtag;
else
return(CMD_PARAM_ERROR);
if (testtype) {
if (!strcmp(testtype,"gc")) {
if (gotachar())
true=1;
}
else if (!strcmp(testtype,"ngc")) {
if (!gotachar())
true=1;
}
else if (!strcmp(testtype,"iscmp")) {
TFILE *tfp;
tfp = tfsstat(argv[optind]);
if (tfp) {
if (TFS_ISCPRS(tfp))
true=1;
}
else
printf("'%s' not found\n",argv[optind]);
}
else
return(CMD_PARAM_ERROR);
}
else {
arg1 = argv[optind];
testtype = argv[optind+1];
arg2 = argv[optind+2];
var1 = strtoul(arg1,(char **)0,0);
var2 = strtoul(arg2,(char **)0,0);
if (!strcmp(testtype,"gt")) {
if (var1 > var2)
true = 1;
}
else if (!strcmp(testtype,"lt")) {
if (var1 < var2)
true = 1;
}
else if (!strcmp(testtype,"le")) {
if (var1 <= var2)
true = 1;
}
else if (!strcmp(testtype,"ge")) {
if (var1 >= var2)
true = 1;
}
else if (!strcmp(testtype,"eq")) {
if (var1 == var2)
true = 1;
}
else if (!strcmp(testtype,"ne")) {
if (var1 != var2)
true = 1;
}
else if (!strcmp(testtype,"and")) {
if (var1 & var2)
true = 1;
}
else if (!strcmp(testtype,"xor")) {
if (var1 ^ var2)
true = 1;
}
else if (!strcmp(testtype,"or")) {
if (var1 | var2)
true = 1;
}
else if (!strcmp(testtype,"seq")) {
if (!strcmp(arg1,arg2))
true = 1;
}
else if (!strcmp(testtype,"sin")) {
if (strstr(arg2,arg1))
true = 1;
}
else if (!strcmp(testtype,"sne")) {
if (strcmp(arg1,arg2))
true = 1;
}
else
return(CMD_PARAM_ERROR);
}
/* If the true flag is set, call the 'if' function.
* If the true flag is clear, and "else" was found on the command
* line, then call the 'else' function...
*/
if (true) {
if (verbose)
printf("TRUE\n");
iffunc(iftag);
}
else {
if (verbose)
printf("FALSE\n");
if (if_else)
elsefunc(elsetag);
}
return(CMD_SUCCESS);
}
int
InAScript(void)
{
if (ScriptIsRunning)
return(1);
else {
printf("Invalid from outside a script\n");
return(0);
}
}
void
exitscript(char *ignored)
{
if (InAScript()) {
ScriptExitFlag = EXIT_SCRIPT;
}
}
char *ExitHelp[] = {
"Exit a script",
"-[r]",
#if INCLUDE_VERBOSEHELP
"Options:",
" -r remove script after exit",
#endif
0,
};
int
Exit(int argc, char *argv[])
{
ScriptExitFlag = EXIT_SCRIPT;
if ((argc == 2) && (!strcmp(argv[1],"-r")))
ScriptExitFlag |= REMOVE_SCRIPT;
return(CMD_SUCCESS);
}
char *GotoHelp[] = {
"Branch to file tag",
"{tagname}",
0,
};
int
Goto(int argc, char *argv[])
{
if (argc != 2)
return(CMD_PARAM_ERROR);
gototag(argv[1]);
return(CMD_SUCCESS);
}
char *GosubHelp[] = {
"Call a subroutine",
"{tagname}",
0,
};
int
Gosub(int argc, char *argv[])
{
if (argc != 2)
return(CMD_PARAM_ERROR);
gosubtag(argv[1]);
return(CMD_SUCCESS);
}
char *ReturnHelp[] = {
"Return from subroutine",
"",
0,
};
int
Return(int argc, char *argv[])
{
if (argc != 1)
return(CMD_PARAM_ERROR);
gosubret(0);
return(CMD_SUCCESS);
}
/* Item:
* This is a simple replacement for the KSH "for" construct...
* It allows the user to build a list of strings and retrieve one at a time.
* Basically, the items can be thought of as a table. The value of idx
* (starting with 1) is used to index into the list of items and place
* that item in the shell variable "var".
* Syntax:
* item {idx} {var} {item1} {item2} {item3} ....
*/
char *ItemHelp[] = {
"Extract an item from a list",
"{idx} {stor_var} [item1] [item2] ...",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -