// 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, } } } }
func (cp *compiler) redirOp(n *parse.Redir) Op { return Op{cp.redir(n), n.Begin(), n.End()} }