diff options
Diffstat (limited to 'main/common/if.c')
-rw-r--r-- | main/common/if.c | 1188 |
1 files changed, 601 insertions, 587 deletions
diff --git a/main/common/if.c b/main/common/if.c index 8e8c01b..d094a85 100644 --- a/main/common/if.c +++ b/main/common/if.c @@ -1,7 +1,7 @@ /************************************************************************** * * Copyright (c) 2013 Alcatel-Lucent - * + * * Alcatel Lucent licenses this file to You under the Apache License, * Version 2.0 (the "License"); you may not use this file except in * compliance with the License. A copy of the License is contained the @@ -26,7 +26,7 @@ * 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. @@ -60,723 +60,736 @@ * 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]; +#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; +static int ScriptIsRunning; /* ScriptGotoTag: * Points to the string that is the most recent target of * a goto or gosub command. */ -static char *ScriptGotoTag; +static char *ScriptGotoTag; /* ScriptExitFlag: - * If non-zero, then the script must exit. + * If non-zero, then the script must exit. * The 'exit' command sets this flag based on options provided to exit. */ -int ScriptExitFlag; +int ScriptExitFlag; /* ExecuteAfterNext: * If the ScriptExitFlag has the EXECUTE_AFTER_EXIT flag set, then the content - * of this array is assumed to be the file that is to be executed + * of this array is assumed to be the file that is to be executed * automatically after the exit of the current script. */ -char ExecuteAfterExit[TFSNAMESIZE+1]; +char ExecuteAfterExit[TFSNAMESIZE+1]; /*****************************************************************************/ /* 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] + * 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]", + "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 sec 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}", + " Options:", + " -t{test} see below", + " -v verbose mode (print TRUE or FALSE result)", + " Notes:", + " * Numerical/logical/string compare:", + " seq sec 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, + 0, }; int If(int argc, char *argv[]) { - int opt, arg, true, if_else, offset, verbose; - void (*iffunc)(char *), (*elsefunc)(char *); - 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 - 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,"sec")) { - if (!strcasecmp(arg1,arg2)) - 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 opt, arg, true, if_else, offset, verbose; + void (*iffunc)(char *), (*elsefunc)(char *); + 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 { + 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,"sec")) { + if(!strcasecmp(arg1,arg2)) { + 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); - } + if(ScriptIsRunning) { + return(1); + } else { + printf("Invalid from outside a script\n"); + return(0); + } } void exitscript(char *ignored) { - if (InAScript()) { - ScriptExitFlag = EXIT_SCRIPT; - } + if(InAScript()) { + ScriptExitFlag = EXIT_SCRIPT; + } } char *ExitHelp[] = { - "Exit currently running script", - "-[ae:r]", + "Exit currently running script", + "-[ae:r]", #if INCLUDE_VERBOSEHELP - "Options:", - " -a exit all scripts (if nested)", - " -e {exe} automatically execute 'exe' after exit", - " -r remove script after exit", + "Options:", + " -a exit all scripts (if nested)", + " -e {exe} automatically execute 'exe' after exit", + " -r remove script after exit", #endif - 0, + 0, }; int Exit(int argc, char *argv[]) { - int opt; - ScriptExitFlag = EXIT_SCRIPT; - - while((opt=getopt(argc,argv,"ae:r")) != -1) { - switch(opt) { - case 'a': - ScriptExitFlag |= EXIT_ALL_SCRIPTS; - break; - case 'e': - if (strlen(optarg) >= sizeof(ExecuteAfterExit)) - return(CMD_PARAM_ERROR); - ScriptExitFlag |= EXECUTE_AFTER_EXIT; - strcpy(ExecuteAfterExit,optarg); - break; - case 'r': - ScriptExitFlag |= REMOVE_SCRIPT; - break; - } - } - return(CMD_SUCCESS); + int opt; + ScriptExitFlag = EXIT_SCRIPT; + + while((opt=getopt(argc,argv,"ae:r")) != -1) { + switch(opt) { + case 'a': + ScriptExitFlag |= EXIT_ALL_SCRIPTS; + break; + case 'e': + if(strlen(optarg) >= sizeof(ExecuteAfterExit)) { + return(CMD_PARAM_ERROR); + } + ScriptExitFlag |= EXECUTE_AFTER_EXIT; + strcpy(ExecuteAfterExit,optarg); + break; + case 'r': + ScriptExitFlag |= REMOVE_SCRIPT; + break; + } + } + return(CMD_SUCCESS); } char *GotoHelp[] = { - "Branch to file tag", - "{tagname}", - 0, + "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); + if(argc != 2) { + return(CMD_PARAM_ERROR); + } + gototag(argv[1]); + return(CMD_SUCCESS); } char *GosubHelp[] = { - "Call a subroutine", - "{tagname}", - 0, + "Call a subroutine", + "{tagname}", + 0, }; int Gosub(int argc, char *argv[]) { - if (argc != 2) - return(CMD_PARAM_ERROR); - gosubtag(argv[1]); - return(CMD_SUCCESS); + if(argc != 2) { + return(CMD_PARAM_ERROR); + } + gosubtag(argv[1]); + return(CMD_SUCCESS); } char *ReturnHelp[] = { - "Return from subroutine", - "", - 0, + "Return from subroutine", + "", + 0, }; int Return(int argc, char *argv[]) { - if (argc != 1) - return(CMD_PARAM_ERROR); - gosubret(0); - return(CMD_SUCCESS); + 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} .... + * 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] ...", + "Extract an item from a list", + "{idx} {stor_var} [item1] [item2] ...", #if INCLUDE_VERBOSEHELP - "Note: idx=1 retrieves item1", + "Note: idx=1 retrieves item1", #endif - 0, + 0, }; int Item(int argc, char *argv[]) { - int idx; - char *varname; + int idx; + char *varname; - if (argc < 3) - return(CMD_PARAM_ERROR); + if(argc < 3) { + return(CMD_PARAM_ERROR); + } - idx = atoi(argv[1]); - varname = argv[2]; + idx = atoi(argv[1]); + varname = argv[2]; - if ((idx < 1) || (idx > (argc-3))) { - setenv(varname,0); - return(CMD_SUCCESS); - } + if((idx < 1) || (idx > (argc-3))) { + setenv(varname,0); + return(CMD_SUCCESS); + } - idx += 2; - setenv(varname,argv[idx]); - return(CMD_SUCCESS); + idx += 2; + setenv(varname,argv[idx]); + return(CMD_SUCCESS); } /* Read(): - * Simple interactive shell variable entry. - * Syntax: - * read [options] [var1] [var2] [...] - * Options: - * -twww timeout after 'www' milliseconds (approximate) of - * waiting for input. + * Simple interactive shell variable entry. + * Syntax: + * read [options] [var1] [var2] [...] + * Options: + * -twww timeout after 'www' milliseconds (approximate) of + * waiting for input. * */ char *ReadHelp[] = { - "Interactive shellvar entry", + "Interactive shellvar entry", #if INCLUDE_VERBOSEHELP - "-[fnp:t:T:] [var1] [var2] ... ", - " -f flush console input", - " -n no echo during read", - " -p *** prefill string", - " -t ### msec timeout per char", - " -T ### msec timeout cumulative", - "Notes:", - " This command waits for console input terminated by ENTER.", - " Input tokens are whitespace delimited.", - "Examples:", - " * read name # wait forever", - " If user responds with ENTER, shell var 'name' is cleared;", - " else it is loaded with the first input token.", - " * read -t2000 name # timeout after 2 seconds", - " If timeout, shell var 'name' is untouched; else if timeout", - " doesn't occur, but user only types ENTER 'var' is cleared;", - " else 'var' will contain token.", + "-[fnp:t:T:] [var1] [var2] ... ", + " -f flush console input", + " -n no echo during read", + " -p *** prefill string", + " -t ### msec timeout per char", + " -T ### msec timeout cumulative", + "Notes:", + " This command waits for console input terminated by ENTER.", + " Input tokens are whitespace delimited.", + "Examples:", + " * read name # wait forever", + " If user responds with ENTER, shell var 'name' is cleared;", + " else it is loaded with the first input token.", + " * read -t2000 name # timeout after 2 seconds", + " If timeout, shell var 'name' is untouched; else if timeout", + " doesn't occur, but user only types ENTER 'var' is cleared;", + " else 'var' will contain token.", #endif - 0, + 0, }; int Read(int argc,char *argv[]) { - int i, reached_eol, opt, waitfor, noecho; - char *prefill, buf[64], *space, *bp; - - prefill = 0; - waitfor = noecho = 0; - while((opt=getopt(argc,argv,"fnp:t:T:")) != -1) { - switch(opt) { - case 'f': - flush_console_in(); - return(CMD_SUCCESS); - case 'n': - noecho = 1; - break; - case 'p': - prefill = optarg; - break; - case 't': - waitfor = strtol(optarg,(char **)0,0); - break; - case 'T': - waitfor = strtol(optarg,(char **)0,0); - waitfor = -waitfor; - break; - default: - return(CMD_PARAM_ERROR); - } - } + int i, reached_eol, opt, waitfor, noecho; + char *prefill, buf[64], *space, *bp; + + prefill = 0; + waitfor = noecho = 0; + while((opt=getopt(argc,argv,"fnp:t:T:")) != -1) { + switch(opt) { + case 'f': + flush_console_in(); + return(CMD_SUCCESS); + case 'n': + noecho = 1; + break; + case 'p': + prefill = optarg; + break; + case 't': + waitfor = strtol(optarg,(char **)0,0); + break; + case 'T': + waitfor = strtol(optarg,(char **)0,0); + waitfor = -waitfor; + break; + default: + return(CMD_PARAM_ERROR); + } + } #if INCLUDE_MONCMD - /* Since this command blocks waiting for user input on the console, - * check to see if we are running under the context of MONCMD, and, - * if yes, return CMD_FAILURE to avoid a lockup... - */ - if (IPMonCmdActive) { - printf("Invalid under moncmd context.\n"); - return(CMD_FAILURE); - } + /* Since this command blocks waiting for user input on the console, + * check to see if we are running under the context of MONCMD, and, + * if yes, return CMD_FAILURE to avoid a lockup... + */ + if(IPMonCmdActive) { + printf("Invalid under moncmd context.\n"); + return(CMD_FAILURE); + } #endif - /* If -t, then restart the timeout for each character. - * If -T, then the timeout accumulates over all characters. - * If a timeout does occur, then do nothing to the shell variables - * that may be specified as arguments. This allows the script - * writer to distinguish between a timeout, and an empty line... - * Timeout has no affect, empty line will NULL out the variable. - */ - if (getfullline(buf,sizeof(buf)-1,0,waitfor,prefill,noecho?0:1) == -1) - return(CMD_SUCCESS); - - /* If there were no args after the option, then there is no need to - * consider populating a shell variable, so just return here. - */ - if (argc == optind) { - return(CMD_SUCCESS); - } - - bp = buf; - reached_eol = 0; - for(i=optind;i<argc;i++) { - space=strpbrk(bp," \t"); - if (space) { - *space = 0; - setenv(argv[i],bp); - bp = space+1; - } - else { - if ((reached_eol) || (*bp == 0)) { - setenv(argv[i],0); - } - else { - setenv(argv[i],bp); - reached_eol = 1; - } - } - } - return(CMD_SUCCESS); + /* If -t, then restart the timeout for each character. + * If -T, then the timeout accumulates over all characters. + * If a timeout does occur, then do nothing to the shell variables + * that may be specified as arguments. This allows the script + * writer to distinguish between a timeout, and an empty line... + * Timeout has no affect, empty line will NULL out the variable. + */ + if(getfullline(buf,sizeof(buf)-1,0,waitfor,prefill,noecho?0:1) == -1) { + return(CMD_SUCCESS); + } + + /* If there were no args after the option, then there is no need to + * consider populating a shell variable, so just return here. + */ + if(argc == optind) { + return(CMD_SUCCESS); + } + + bp = buf; + reached_eol = 0; + for(i=optind; i<argc; i++) { + space=strpbrk(bp," \t"); + if(space) { + *space = 0; + setenv(argv[i],bp); + bp = space+1; + } else { + if((reached_eol) || (*bp == 0)) { + setenv(argv[i],0); + } else { + setenv(argv[i],bp); + reached_eol = 1; + } + } + } + return(CMD_SUCCESS); } int currentScriptfd(void) { - return(CurrentScriptfdTbl[ScriptIsRunning]); + return(CurrentScriptfdTbl[ScriptIsRunning]); } /* gototag(): - * Used with tfsscript to allow a command to adjust the pointer into the - * script that is currently being executed. It simply populates the - * "ScriptGotoTag" pointer with the tag that should be branched to next. + * Used with tfsscript to allow a command to adjust the pointer into the + * script that is currently being executed. It simply populates the + * "ScriptGotoTag" pointer with the tag that should be branched to next. */ void gototag(char *tag) { - if (InAScript()) { - if (ScriptGotoTag) - free(ScriptGotoTag); - ScriptGotoTag = malloc(strlen(tag)+8); - sprintf(ScriptGotoTag,"# %s",tag); - } + if(InAScript()) { + if(ScriptGotoTag) { + free(ScriptGotoTag); + } + ScriptGotoTag = malloc(strlen(tag)+8); + sprintf(ScriptGotoTag,"# %s",tag); + } } /* gosubtag(): - * Similar in basic use to gototag(), except that we keep a copy of the - * current position in the active script file so that it can be returned - * to later. + * Similar in basic use to gototag(), except that we keep a copy of the + * current position in the active script file so that it can be returned + * to later. */ void gosubtag(char *tag) { - if (InAScript()) { - if (ReturnToDepth >= MAXGOSUBDEPTH) { - printf("Max return-to depth reached\n"); - return; - } - ReturnToTellTbl[ReturnToDepth++] = tfstell(currentScriptfd()); - gototag(tag); - } + if(InAScript()) { + if(ReturnToDepth >= MAXGOSUBDEPTH) { + printf("Max return-to depth reached\n"); + return; + } + ReturnToTellTbl[ReturnToDepth++] = tfstell(currentScriptfd()); + gototag(tag); + } } void gosubret(char *ignored) { - int offset, err; - - if (InAScript()) { - err = 0; - - if (ReturnToDepth <= 0) { - printf("Nothing to return to\n"); - err = 1; - } - else { - ReturnToDepth--; - offset = tfsseek(currentScriptfd(), - ReturnToTellTbl[ReturnToDepth],TFS_BEGIN); - if (offset <= 0) { - err = 1; - printf("return error: %s\n",tfserrmsg(offset)); - } - } - if (err) - printf("Possible gosub/return imbalance.\n"); - } + int offset, err; + + if(InAScript()) { + err = 0; + + if(ReturnToDepth <= 0) { + printf("Nothing to return to\n"); + err = 1; + } else { + ReturnToDepth--; + offset = tfsseek(currentScriptfd(), + ReturnToTellTbl[ReturnToDepth],TFS_BEGIN); + if(offset <= 0) { + err = 1; + printf("return error: %s\n",tfserrmsg(offset)); + } + } + if(err) { + printf("Possible gosub/return imbalance.\n"); + } + } } /* tfsscript(): - * Treat the file as a list of commands that should be executed - * as monitor commands. Step through each line and execute it. - * The tfsDocommand() function pointer is used so that the application - * can assign a different command interpreter to the script capbilities - * of the monitor. To really take advantage of this, the command interpreter - * that is reassigned, should allow monitor commands to run if the command - * does not exist in the application's command list. - * - * Scripts can call other scripts that call other scripts (etc...) and - * that works fine because tfsscript() will just use more stack space but - * it eventually returns through the same function call tree. A script can - * also call a COFF, ELF or AOUT file and expect it to return as long as - * the executable returns through the same point into which it was started - * (the entrypoint). If the executable uses mon_appexit() to terminate, - * then the calling script will not regain control. + * Treat the file as a list of commands that should be executed + * as monitor commands. Step through each line and execute it. + * The tfsDocommand() function pointer is used so that the application + * can assign a different command interpreter to the script capbilities + * of the monitor. To really take advantage of this, the command interpreter + * that is reassigned, should allow monitor commands to run if the command + * does not exist in the application's command list. + * + * Scripts can call other scripts that call other scripts (etc...) and + * that works fine because tfsscript() will just use more stack space but + * it eventually returns through the same function call tree. A script can + * also call a COFF, ELF or AOUT file and expect it to return as long as + * the executable returns through the same point into which it was started + * (the entrypoint). If the executable uses mon_appexit() to terminate, + * then the calling script will not regain control. */ int tfsscript(TFILE *fp,int verbose) { - char lcpy[CMDLINESIZE], *sv; - int tfd, lnsize, lno, verbosity, ignoreerror, cmdstat; - - tfd = tfsopen(fp->name,TFS_RDONLY,0); - if (tfd < 0) - return(tfd); - - lno = 0; - - /* If ScriptIsRunning is zero, then we know that this is the top-level - * script, so we can initialize state here... - */ - if (ScriptIsRunning == 0) - ReturnToDepth = 0; - - CurrentScriptfdTbl[++ScriptIsRunning] = tfd; - - while(1) { - lno++; - lnsize = tfsgetline(tfd,lcpy,CMDLINESIZE); - if (lnsize == 0) /* end of file? */ - break; - if (lnsize < 0) { - printf("tfsscript(): %s\n",tfserrmsg(lnsize)); - break; - } - if ((lcpy[0] == '\r') || (lcpy[0] == '\n')) /* empty line? */ - continue; - - lcpy[lnsize-1] = 0; /* Remove the newline */ - - /* Just in case the goto tag was set outside a script, */ - /* clear it now. */ - if (ScriptGotoTag) { - free(ScriptGotoTag); - ScriptGotoTag = (char *)0; - } - - ScriptExitFlag = 0; - - /* Execute the command line. - * If the shell variable "SCRIPTVERBOSE" is set, then enable - * verbosity for this command; else use what was passed in - * the parameter list of the function. Note that the variable - * is tested for each command so that verbosity can be enabled - * or disabled within a script. - * If the command returns a status that indicates that there was - * some parameter error, then exit the script. - */ - sv = getenv("SCRIPTVERBOSE"); - if (sv) - verbosity = atoi(sv); - else - verbosity = verbose; - - if ((lcpy[0] == '-') || (getenv("SCRIPT_IGNORE_ERROR"))) - ignoreerror = 1; - else - ignoreerror = 0; - - if (verbosity) - printf("[%02d]: %s\n",lno,lcpy); - - cmdstat = tfsDocommand(lcpy[0] == '-' ? lcpy+1 : lcpy, 0); - - if (cmdstat != CMD_SUCCESS) { - setenv("CMDSTAT","FAIL"); - if (ignoreerror == 0) { - printf("Terminating script '%s' at line %d\n", - TFS_NAME(fp),lno); - ScriptExitFlag = EXIT_SCRIPT; - break; - } - } - else { - setenv("CMDSTAT","PASS"); - } - - /* Check for exit flag. If set, then in addition to terminating the - * script, clear the return depth here so that the "missing return" - * warning is not printed. This is done because there is likely - * to be a subroutine with an exit in it and this should not - * cause a warning. - */ - if (ScriptExitFlag) { - ReturnToDepth = 0; - break; - } - - /* If ScriptGotoTag is set, then attempt to reposition the line - * pointer to the line that contains the tag. - */ - if (ScriptGotoTag) { - int tlen; - - tlen = strlen(ScriptGotoTag); - lno = 0; - tfsseek(tfd,0,TFS_BEGIN); - while(1) { - lnsize = tfsgetline(tfd,lcpy,CMDLINESIZE); - if (lnsize == 0) { - printf("Tag '%s' not found\n",ScriptGotoTag+2); - free(ScriptGotoTag); - ScriptGotoTag = (char *)0; - tfsclose(tfd,0); - return(TFS_OKAY); - } - lno++; - if (!strncmp(lcpy,ScriptGotoTag,tlen) && - (isspace(lcpy[tlen]) || (lcpy[tlen] == ':'))) { - free(ScriptGotoTag); - ScriptGotoTag = (char *)0; - break; - } - } - } - /* After each line, poll ethernet interface. */ - pollethernet(); - } - tfsclose(tfd,0); - if (ScriptExitFlag & REMOVE_SCRIPT) - tfsunlink(fp->name); - if (ScriptIsRunning > 0) { - ScriptIsRunning--; - if ((ScriptIsRunning == 0) && (ReturnToDepth != 0)) { - printf("Error: script is done, but return-to-depth != 0\n"); - printf("(possible gosub/return imbalance)\n"); - } - } - else { - printf("Script run-depth error\n"); - } - - /* If the EXECUTE_AFTER_EXIT flag is set (by exit -e), then automatically - * start up the file specified in ExecuteAfterExit[]... - */ - if (ScriptExitFlag & EXECUTE_AFTER_EXIT) { - char *argv[2]; - - argv[0] = ExecuteAfterExit; - argv[1] = 0; - ScriptExitFlag = 0; - tfsrun(argv,0); - } - - /* Upon completion of a script, clear the ScriptExitFlag variable so - * that it is not accidentally applied to another script that may have - * called this script. - */ - if ((ScriptExitFlag & EXIT_ALL_SCRIPTS) != EXIT_ALL_SCRIPTS) - ScriptExitFlag = 0; - return(TFS_OKAY); + char lcpy[CMDLINESIZE], *sv; + int tfd, lnsize, lno, verbosity, ignoreerror, cmdstat; + + tfd = tfsopen(fp->name,TFS_RDONLY,0); + if(tfd < 0) { + return(tfd); + } + + lno = 0; + + /* If ScriptIsRunning is zero, then we know that this is the top-level + * script, so we can initialize state here... + */ + if(ScriptIsRunning == 0) { + ReturnToDepth = 0; + } + + CurrentScriptfdTbl[++ScriptIsRunning] = tfd; + + while(1) { + lno++; + lnsize = tfsgetline(tfd,lcpy,CMDLINESIZE); + if(lnsize == 0) { /* end of file? */ + break; + } + if(lnsize < 0) { + printf("tfsscript(): %s\n",tfserrmsg(lnsize)); + break; + } + if((lcpy[0] == '\r') || (lcpy[0] == '\n')) { /* empty line? */ + continue; + } + + lcpy[lnsize-1] = 0; /* Remove the newline */ + + /* Just in case the goto tag was set outside a script, */ + /* clear it now. */ + if(ScriptGotoTag) { + free(ScriptGotoTag); + ScriptGotoTag = (char *)0; + } + + ScriptExitFlag = 0; + + /* Execute the command line. + * If the shell variable "SCRIPTVERBOSE" is set, then enable + * verbosity for this command; else use what was passed in + * the parameter list of the function. Note that the variable + * is tested for each command so that verbosity can be enabled + * or disabled within a script. + * If the command returns a status that indicates that there was + * some parameter error, then exit the script. + */ + sv = getenv("SCRIPTVERBOSE"); + if(sv) { + verbosity = atoi(sv); + } else { + verbosity = verbose; + } + + if((lcpy[0] == '-') || (getenv("SCRIPT_IGNORE_ERROR"))) { + ignoreerror = 1; + } else { + ignoreerror = 0; + } + + if(verbosity) { + printf("[%02d]: %s\n",lno,lcpy); + } + + cmdstat = tfsDocommand(lcpy[0] == '-' ? lcpy+1 : lcpy, 0); + + if(cmdstat != CMD_SUCCESS) { + setenv("CMDSTAT","FAIL"); + if(ignoreerror == 0) { + printf("Terminating script '%s' at line %d\n", + TFS_NAME(fp),lno); + ScriptExitFlag = EXIT_SCRIPT; + break; + } + } else { + setenv("CMDSTAT","PASS"); + } + + /* Check for exit flag. If set, then in addition to terminating the + * script, clear the return depth here so that the "missing return" + * warning is not printed. This is done because there is likely + * to be a subroutine with an exit in it and this should not + * cause a warning. + */ + if(ScriptExitFlag) { + ReturnToDepth = 0; + break; + } + + /* If ScriptGotoTag is set, then attempt to reposition the line + * pointer to the line that contains the tag. + */ + if(ScriptGotoTag) { + int tlen; + + tlen = strlen(ScriptGotoTag); + lno = 0; + tfsseek(tfd,0,TFS_BEGIN); + while(1) { + lnsize = tfsgetline(tfd,lcpy,CMDLINESIZE); + if(lnsize == 0) { + printf("Tag '%s' not found\n",ScriptGotoTag+2); + free(ScriptGotoTag); + ScriptGotoTag = (char *)0; + tfsclose(tfd,0); + return(TFS_OKAY); + } + lno++; + if(!strncmp(lcpy,ScriptGotoTag,tlen) && + (isspace(lcpy[tlen]) || (lcpy[tlen] == ':'))) { + free(ScriptGotoTag); + ScriptGotoTag = (char *)0; + break; + } + } + } + /* After each line, poll ethernet interface. */ + pollethernet(); + } + tfsclose(tfd,0); + if(ScriptExitFlag & REMOVE_SCRIPT) { + tfsunlink(fp->name); + } + if(ScriptIsRunning > 0) { + ScriptIsRunning--; + if((ScriptIsRunning == 0) && (ReturnToDepth != 0)) { + printf("Error: script is done, but return-to-depth != 0\n"); + printf("(possible gosub/return imbalance)\n"); + } + } else { + printf("Script run-depth error\n"); + } + + /* If the EXECUTE_AFTER_EXIT flag is set (by exit -e), then automatically + * start up the file specified in ExecuteAfterExit[]... + */ + if(ScriptExitFlag & EXECUTE_AFTER_EXIT) { + char *argv[2]; + + argv[0] = ExecuteAfterExit; + argv[1] = 0; + ScriptExitFlag = 0; + tfsrun(argv,0); + } + + /* Upon completion of a script, clear the ScriptExitFlag variable so + * that it is not accidentally applied to another script that may have + * called this script. + */ + if((ScriptExitFlag & EXIT_ALL_SCRIPTS) != EXIT_ALL_SCRIPTS) { + ScriptExitFlag = 0; + } + return(TFS_OKAY); } /* tfsscriptname(): @@ -785,28 +798,29 @@ tfsscript(TFILE *fp,int verbose) char * tfsscriptname(void) { - struct tfsdat *slot; - - if (ScriptIsRunning) { - slot = &tfsSlots[CurrentScriptfdTbl[ScriptIsRunning]]; - if (slot->offset != (ulong)-1) - return(slot->hdr.name); - } - return(""); + struct tfsdat *slot; + + if(ScriptIsRunning) { + slot = &tfsSlots[CurrentScriptfdTbl[ScriptIsRunning]]; + if(slot->offset != (ulong)-1) { + return(slot->hdr.name); + } + } + return(""); } -#else /* INCLUDE_TFSSCRIPT */ +#else /* INCLUDE_TFSSCRIPT */ int tfsscript(TFILE *fp,int verbose) { - return(TFSERR_NOTAVAILABLE); + return(TFSERR_NOTAVAILABLE); } char * tfsscriptname(void) { - return(0); + return(0); } #endif |