Skip to content

Commit

Permalink
Merge pull request #24 from yassinebenaid/dev
Browse files Browse the repository at this point in the history
Handle redirections using `<>` && respect stream mode specified by redirection notation
  • Loading branch information
yassinebenaid authored Dec 4, 2024
2 parents 2ce20d7 + 9bc5359 commit f3c07b6
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 38 deletions.
26 changes: 21 additions & 5 deletions generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (g *generator) handleRedirections(name string, redirections []ast.Redirecti
for i, redirection := range redirections {
switch redirection.Method {
case ">", ">|":
g.ins(ir.OpenOrCreateStream{
g.ins(ir.OpenWritableStream{
Name: fmt.Sprintf("%s_file_%d", name, i),
Target: g.handleExpression(redirection.Dst),
})
Expand All @@ -111,7 +111,7 @@ func (g *generator) handleRedirections(name string, redirections []ast.Redirecti
})
}
case ">>":
g.ins(ir.OpenOrCreateStreamForAppending{
g.ins(ir.OpenAppendableStream{
Name: fmt.Sprintf("%s_file_%d", name, i),
Target: g.handleExpression(redirection.Dst),
})
Expand All @@ -120,7 +120,7 @@ func (g *generator) handleRedirections(name string, redirections []ast.Redirecti
Value: ir.Literal(fmt.Sprintf("%s_file_%d", name, i)),
})
case "&>":
g.ins(ir.OpenOrCreateStream{
g.ins(ir.OpenWritableStream{
Name: fmt.Sprintf("%s_file_%d", name, i),
Target: g.handleExpression(redirection.Dst),
})
Expand All @@ -133,7 +133,7 @@ func (g *generator) handleRedirections(name string, redirections []ast.Redirecti
Value: ir.Literal(fmt.Sprintf("%s_file_%d", name, i)),
})
case "&>>":
g.ins(ir.OpenOrCreateStreamForAppending{
g.ins(ir.OpenAppendableStream{
Name: fmt.Sprintf("%s_file_%d", name, i),
Target: g.handleExpression(redirection.Dst),
})
Expand All @@ -152,8 +152,15 @@ func (g *generator) handleRedirections(name string, redirections []ast.Redirecti
Fd: g.handleExpression(redirection.Dst),
},
})
case "<&":
g.ins(ir.Set{
Name: fmt.Sprintf("%s.Stdin", name),
Value: ir.NewStreamFromFD{
Fd: g.handleExpression(redirection.Dst),
},
})
case "<":
g.ins(ir.OpenStream{
g.ins(ir.OpenReadableStream{
Name: fmt.Sprintf("%s_file_%d", name, i),
Target: g.handleExpression(redirection.Dst),
})
Expand All @@ -172,6 +179,15 @@ func (g *generator) handleRedirections(name string, redirections []ast.Redirecti
Name: fmt.Sprintf("%s.Stdin", name),
Value: ir.Literal(fmt.Sprintf("%s_file_%d", name, i)),
})
case "<>":
g.ins(ir.OpenReadWritableStream{
Name: fmt.Sprintf("%s_file_%d", name, i),
Target: g.handleExpression(redirection.Dst),
})
g.ins(ir.Set{
Name: fmt.Sprintf("%s.Stdin", name),
Value: ir.Literal(fmt.Sprintf("%s_file_%d", name, i)),
})
}
}
}
65 changes: 41 additions & 24 deletions ir/ir.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,22 @@ type RunCommanOrFail struct {
Name string
}

type OpenStream struct {
type OpenReadableStream struct {
Name string
Target Instruction
}

type OpenOrCreateStream struct {
type OpenWritableStream struct {
Name string
Target Instruction
}

type OpenOrCreateStreamForAppending struct {
type OpenReadWritableStream struct {
Name string
Target Instruction
}

type OpenAppendableStream struct {
Name string
Target Instruction
}
Expand All @@ -72,21 +77,22 @@ type DuplicateFD struct {
Old, New string
}

func (Declare) inst() {}
func (DeclareSlice) inst() {}
func (Append) inst() {}
func (ReadVar) inst() {}
func (Set) inst() {}
func (String) inst() {}
func (Literal) inst() {}
func (InitCommand) inst() {}
func (OpenStream) inst() {}
func (OpenOrCreateStreamForAppending) inst() {}
func (OpenOrCreateStream) inst() {}
func (NewStringStream) inst() {}
func (RunCommanOrFail) inst() {}
func (NewStreamFromFD) inst() {}
func (DuplicateFD) inst() {}
func (Declare) inst() {}
func (DeclareSlice) inst() {}
func (Append) inst() {}
func (ReadVar) inst() {}
func (Set) inst() {}
func (String) inst() {}
func (Literal) inst() {}
func (InitCommand) inst() {}
func (OpenReadableStream) inst() {}
func (OpenAppendableStream) inst() {}
func (OpenWritableStream) inst() {}
func (OpenReadWritableStream) inst() {}
func (NewStringStream) inst() {}
func (RunCommanOrFail) inst() {}
func (NewStreamFromFD) inst() {}
func (DuplicateFD) inst() {}

func (p Program) String() string {
var str = "package main\n\n"
Expand Down Expand Up @@ -151,9 +157,20 @@ func (rcf RunCommanOrFail) String() string {
`, rcf.Command, rcf.Name)
}

func (of OpenStream) String() string {
func (of OpenReadableStream) String() string {
return fmt.Sprintf(`
%s, err := runtime.OpenReadableStream(%s)
if err != nil {
shell.HandleError("", err)
}else{
shell.ExitCode = 0
}
`, of.Name, of.Target.String())
}

func (of OpenWritableStream) String() string {
return fmt.Sprintf(`
%s, err := runtime.OpenStream(%s)
%s, err := runtime.OpenWritableStream(%s)
if err != nil {
shell.HandleError("", err)
}else{
Expand All @@ -162,9 +179,9 @@ func (of OpenStream) String() string {
`, of.Name, of.Target.String())
}

func (of OpenOrCreateStream) String() string {
func (of OpenAppendableStream) String() string {
return fmt.Sprintf(`
%s, err := runtime.OpenOrCreateStream(%s)
%s, err := runtime.OpenAppendableStream(%s)
if err != nil {
shell.HandleError("", err)
}else{
Expand All @@ -173,9 +190,9 @@ func (of OpenOrCreateStream) String() string {
`, of.Name, of.Target.String())
}

func (of OpenOrCreateStreamForAppending) String() string {
func (of OpenReadWritableStream) String() string {
return fmt.Sprintf(`
%s, err := runtime.OpenOrCreateStreamForAppending(%s)
%s, err := runtime.OpenReadWritableStream(%s)
if err != nil {
shell.HandleError("", err)
}else{
Expand Down
6 changes: 3 additions & 3 deletions parser/redirection.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (

func (p *parser) isRedirectionToken() bool {
switch p.curr.Type {
case token.GT, token.DOUBLE_GT, token.AMPERSAND_GT, token.GT_AMPERSAND,
case token.GT, token.DOUBLE_GT, token.AMPERSAND_GT, token.GT_AMPERSAND, token.LT_GT,
token.LT, token.LT_AMPERSAND, token.TRIPLE_LT, token.GT_PIPE, token.AMPERSAND_DOUBLE_GT:
return true
case token.INT:
// redirections that use file descriptor as source
switch p.next.Type {
case token.GT, token.DOUBLE_GT, token.GT_AMPERSAND, token.LT, token.LT_AMPERSAND, token.TRIPLE_LT, token.GT_PIPE:
case token.GT, token.DOUBLE_GT, token.GT_AMPERSAND, token.LT, token.LT_AMPERSAND, token.LT_GT, token.TRIPLE_LT, token.GT_PIPE:
return true
}
}
Expand All @@ -25,7 +25,7 @@ func (p *parser) HandleRedirection(rt *[]ast.Redirection) {
switch p.curr.Type {
case token.GT, token.DOUBLE_GT, token.GT_AMPERSAND, token.GT_PIPE:
p.fromStdout(rt)
case token.LT_AMPERSAND, token.LT, token.TRIPLE_LT:
case token.LT_AMPERSAND, token.LT, token.TRIPLE_LT, token.LT_GT:
p.toStdin(rt)
case token.AMPERSAND_GT, token.AMPERSAND_DOUBLE_GT:
p.allOutputsToFile(rt)
Expand Down
19 changes: 19 additions & 0 deletions parser/redirection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,25 @@ var redirectionTests = []testCase{
},
},
}},
{`cmd<>'file.ext' arg <> file<>/foo/bar arg123<>foo 3<>bar 928 <>bar 282`, ast.Script{

ast.Command{
Name: ast.Word("cmd"),
Args: []ast.Expression{
ast.Word("arg"),
ast.Word("arg123"),
ast.Word("928"),
ast.Word("282"),
}, Redirections: []ast.Redirection{
{Src: "0", Method: "<>", Dst: ast.Word("file.ext")},
{Src: "0", Method: "<>", Dst: ast.Word("file")},
{Src: "0", Method: "<>", Dst: ast.Word("/foo/bar")},
{Src: "0", Method: "<>", Dst: ast.Word("foo")},
{Src: "3", Method: "<>", Dst: ast.Word("bar")},
{Src: "0", Method: "<>", Dst: ast.Word("bar")},
},
},
}},
// Duplicating/Closing file descriptors
{`cmd <&- 2<&- >&- 2>&- <&5- 6<&5- >&5- 6>&5-`, ast.Script{
ast.Command{
Expand Down
16 changes: 10 additions & 6 deletions runtime/stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,20 @@ type Stream interface {
Fd() uintptr
}

func OpenStream(name string) (Stream, error) {
return os.OpenFile(name, os.O_RDWR, 0644)
func OpenReadableStream(name string) (Stream, error) {
return os.OpenFile(name, os.O_RDONLY, 0)
}

func OpenOrCreateStream(name string) (Stream, error) {
return os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
func OpenWritableStream(name string) (Stream, error) {
return os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
}

func OpenOrCreateStreamForAppending(name string) (Stream, error) {
return os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
func OpenReadWritableStream(name string) (Stream, error) {
return os.OpenFile(name, os.O_RDWR|os.O_CREATE, 0644)
}

func OpenAppendableStream(name string) (Stream, error) {
return os.OpenFile(name, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
}

type stringStream struct {
Expand Down

0 comments on commit f3c07b6

Please sign in to comment.