Loading commands/shell/return.cpp +1 −1 Changes for commands/shell/return.cpp: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ namespace fresh { namespace cmd { // call has nothing to return FROM, so it's an error (not a // silent no-op, and not treated as "exit" either) -- the shell // keeps running normally afterward. if(!shell.inFunction()){ if(!shell.inFunction() && !shell.inSourcedFile()){ std::cerr << "fresh: return: can only \x60return' from a function or sourced script" << std::endl; return 2; // matches bash's own exit status for this error } Loading commands/shell/use.cpp +57 −0 Changes for commands/shell/use.cpp: 57 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -30,9 +30,17 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Optional arguments temporarily become the sourced file's $1.. values. // Shell-only builtin: a standalone applet would necessarily lose all resulting // state when its process exits. // // "." and "source" are the POSIX/bash names for the same thing; they also // search PATH for a FILE without a '/' (POSIX), falling back to the current // directory like bash does. #include <iostream> #include <vector> #include <cstdlib> #include <sys/stat.h> #include <unistd.h> #include "shell.h" Loading @@ -57,4 +65,53 @@ namespace fresh { namespace cmd { FRESH_REGISTER_COMMAND(UseCommand); class DotCommand : public ShellCommand { public: explicit DotCommand(const char *name=".") :ShellCommand(name),_name(name){} int runCommand(int argc,const char **argv){ if(argc<2){ std::cerr << _name << ": filename argument required" << std::endl; return 2; } std::string file=argv[1]; if(file.find('/')==std::string::npos){ const char *path=getenv("PATH"); std::string dirs=path ? path : ""; size_t pos=0; for(;;){ size_t end=dirs.find(':',pos); std::string dir=dirs.substr(pos,end==std::string::npos ? std::string::npos : end-pos); std::string cand=(dir.empty() ? std::string(".") : dir)+"/"+file; struct stat st; if(stat(cand.c_str(),&st)==0 && S_ISREG(st.st_mode) && access(cand.c_str(),R_OK)==0){ file=cand; break; } if(end==std::string::npos) break; pos=end+1; } } std::vector<std::string> args; for(int i=2;i<argc;++i) args.push_back(argv[i]); return Shell::instance().useFile(file,args); } private: const char *_name; }; class SourceCommand : public DotCommand { public: SourceCommand():DotCommand("source"){} }; FRESH_REGISTER_COMMAND(DotCommand); FRESH_REGISTER_COMMAND(SourceCommand); }} src/shell.cpp +12 −0 Changes for src/shell.cpp: 12 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1383,6 +1383,7 @@ fresh::Shell::Shell(){ _returning=false; _returnCode=0; _functionDepth=0; _sourceDepth=0; _breaking=false; _breakLevels=0; _continuing=false; Loading @@ -1406,6 +1407,7 @@ int fresh::Shell::useFile(const std::string &path,const std::vector<std::string> if(!args.empty()) Environment::instance().setPositionalArgs(args); _heredocSource=∈ ++_sourceDepth; int status=0; std::string line; Loading Loading @@ -1433,6 +1435,12 @@ int fresh::Shell::useFile(const std::string &path,const std::vector<std::string> } status=parse(line); } --_sourceDepth; // "return" ends the sourced file, not the caller if(_returning){ _returning=false; status=_returnCode; } _heredocSource=savedSource; if(!args.empty()) Loading Loading @@ -1461,6 +1469,10 @@ bool fresh::Shell::inFunction() const{ return _functionDepth>0; } bool fresh::Shell::inSourcedFile() const{ return _sourceDepth>0; } void fresh::Shell::requestBreak(int levels){ _breaking=true; _breakLevels=(levels<1) ? 1 : levels; Loading src/shell.h +5 −0 Changes for src/shell.h: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -456,6 +456,9 @@ namespace fresh { // function call at all, since there is no enclosing callFunction() // for it to unwind back to. bool inFunction() const; // True while a file read by "." / "source" / "use" is running: // "return" there ends that file (POSIX). bool inSourcedFile() const; // True if `name` was defined via a "name() compound-command" (or // "function name [()] compound-command") statement already parsed Loading Loading @@ -663,6 +666,8 @@ namespace fresh { // recursive-C++-call) stack -- >0 exactly while inFunction() should // report true. int _functionDepth; // Depth of nested useFile() calls, see inSourcedFile(). int _sourceDepth; // See requestBreak()/requestContinue() and loopDepth() above. bool _breaking; int _breakLevels; Loading Loading
commands/shell/return.cpp +1 −1 Changes for commands/shell/return.cpp: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ namespace fresh { namespace cmd { // call has nothing to return FROM, so it's an error (not a // silent no-op, and not treated as "exit" either) -- the shell // keeps running normally afterward. if(!shell.inFunction()){ if(!shell.inFunction() && !shell.inSourcedFile()){ std::cerr << "fresh: return: can only \x60return' from a function or sourced script" << std::endl; return 2; // matches bash's own exit status for this error } Loading
commands/shell/use.cpp +57 −0 Changes for commands/shell/use.cpp: 57 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -30,9 +30,17 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Optional arguments temporarily become the sourced file's $1.. values. // Shell-only builtin: a standalone applet would necessarily lose all resulting // state when its process exits. // // "." and "source" are the POSIX/bash names for the same thing; they also // search PATH for a FILE without a '/' (POSIX), falling back to the current // directory like bash does. #include <iostream> #include <vector> #include <cstdlib> #include <sys/stat.h> #include <unistd.h> #include "shell.h" Loading @@ -57,4 +65,53 @@ namespace fresh { namespace cmd { FRESH_REGISTER_COMMAND(UseCommand); class DotCommand : public ShellCommand { public: explicit DotCommand(const char *name=".") :ShellCommand(name),_name(name){} int runCommand(int argc,const char **argv){ if(argc<2){ std::cerr << _name << ": filename argument required" << std::endl; return 2; } std::string file=argv[1]; if(file.find('/')==std::string::npos){ const char *path=getenv("PATH"); std::string dirs=path ? path : ""; size_t pos=0; for(;;){ size_t end=dirs.find(':',pos); std::string dir=dirs.substr(pos,end==std::string::npos ? std::string::npos : end-pos); std::string cand=(dir.empty() ? std::string(".") : dir)+"/"+file; struct stat st; if(stat(cand.c_str(),&st)==0 && S_ISREG(st.st_mode) && access(cand.c_str(),R_OK)==0){ file=cand; break; } if(end==std::string::npos) break; pos=end+1; } } std::vector<std::string> args; for(int i=2;i<argc;++i) args.push_back(argv[i]); return Shell::instance().useFile(file,args); } private: const char *_name; }; class SourceCommand : public DotCommand { public: SourceCommand():DotCommand("source"){} }; FRESH_REGISTER_COMMAND(DotCommand); FRESH_REGISTER_COMMAND(SourceCommand); }}
src/shell.cpp +12 −0 Changes for src/shell.cpp: 12 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1383,6 +1383,7 @@ fresh::Shell::Shell(){ _returning=false; _returnCode=0; _functionDepth=0; _sourceDepth=0; _breaking=false; _breakLevels=0; _continuing=false; Loading @@ -1406,6 +1407,7 @@ int fresh::Shell::useFile(const std::string &path,const std::vector<std::string> if(!args.empty()) Environment::instance().setPositionalArgs(args); _heredocSource=∈ ++_sourceDepth; int status=0; std::string line; Loading Loading @@ -1433,6 +1435,12 @@ int fresh::Shell::useFile(const std::string &path,const std::vector<std::string> } status=parse(line); } --_sourceDepth; // "return" ends the sourced file, not the caller if(_returning){ _returning=false; status=_returnCode; } _heredocSource=savedSource; if(!args.empty()) Loading Loading @@ -1461,6 +1469,10 @@ bool fresh::Shell::inFunction() const{ return _functionDepth>0; } bool fresh::Shell::inSourcedFile() const{ return _sourceDepth>0; } void fresh::Shell::requestBreak(int levels){ _breaking=true; _breakLevels=(levels<1) ? 1 : levels; Loading
src/shell.h +5 −0 Changes for src/shell.h: 5 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -456,6 +456,9 @@ namespace fresh { // function call at all, since there is no enclosing callFunction() // for it to unwind back to. bool inFunction() const; // True while a file read by "." / "source" / "use" is running: // "return" there ends that file (POSIX). bool inSourcedFile() const; // True if `name` was defined via a "name() compound-command" (or // "function name [()] compound-command") statement already parsed Loading Loading @@ -663,6 +666,8 @@ namespace fresh { // recursive-C++-call) stack -- >0 exactly while inFunction() should // report true. int _functionDepth; // Depth of nested useFile() calls, see inSourcedFile(). int _sourceDepth; // See requestBreak()/requestContinue() and loopDepth() above. bool _breaking; int _breakLevels; Loading