예제 #1
0
// redir compiles a Redir into a op.
func (cp *compiler) redir(n *parse.Redir) op {
	var dstOp valuesOp
	if n.Dest != nil {
		dstOp = cp.compound(n.Dest)
	}
	p := n.Begin()
	srcOp := cp.compound(n.Source)
	sourceIsFd := n.SourceIsFd
	pSrc := n.Source.Begin()
	mode := n.Mode
	flag := makeFlag(mode)

	return func(ec *evalCtx) {
		var dst int
		if dstOp == nil {
			// use default dst fd
			switch mode {
			case parse.Read:
				dst = 0
			case parse.Write, parse.ReadWrite, parse.Append:
				dst = 1
			default:
				// XXX should report parser bug
				panic("bad RedirMode; parser bug")
			}
		} else {
			// dst must be a valid fd
			dst = ec.must(dstOp(ec), "FD", p).mustOneNonNegativeInt()
		}

		ec.growPorts(dst + 1)
		ec.ports[dst].close()

		srcMust := ec.must(srcOp(ec), "redirection source", pSrc)
		src := string(srcMust.mustOneStr())
		if sourceIsFd {
			if src == "-" {
				// close
				ec.ports[dst] = &port{}
			} else {
				fd := srcMust.zerothMustNonNegativeInt()
				ec.ports[dst] = ec.ports[fd]
				if ec.ports[dst] != nil {
					ec.ports[dst].closeF = false
					ec.ports[dst].closeCh = false
				}
			}
		} else {
			f, err := os.OpenFile(src, flag, defaultFileRedirPerm)
			if err != nil {
				ec.errorf(p, "failed to open file %q: %s", src, err)
			}
			ec.ports[dst] = &port{
				f: f, ch: make(chan Value), closeF: true, closeCh: true,
			}
		}
	}
}
예제 #2
0
파일: boilerplate.go 프로젝트: zhsj/elvish
func (cp *compiler) redirOp(n *parse.Redir) Op {
	return Op{cp.redir(n), n.Begin(), n.End()}
}