Commit ce0b9e77 authored by jan.koester's avatar jan.koester
Browse files

test

parent f3e26f8d
Loading
Loading
Loading
Loading
+1 −1
Changes for commands/shell/return.cpp: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -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
            }
+57 −0
Changes for commands/shell/use.cpp: 57 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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"

@@ -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);

}}
+12 −0
Changes for src/shell.cpp: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -1383,6 +1383,7 @@ fresh::Shell::Shell(){
    _returning=false;
    _returnCode=0;
    _functionDepth=0;
    _sourceDepth=0;
    _breaking=false;
    _breakLevels=0;
    _continuing=false;
@@ -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=&in;
    ++_sourceDepth;

    int status=0;
    std::string line;
@@ -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())
@@ -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;
+5 −0
Changes for src/shell.h: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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
@@ -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;