WIP Add termination handler in engine
This commit is contained in:
parent
6325ef4afd
commit
a3073f6189
@ -321,7 +321,6 @@ func(bt *Batcher) MenuExit(w io.Writer) (int, error) {
|
|||||||
}
|
}
|
||||||
bt.inMenu = false
|
bt.inMenu = false
|
||||||
b := bt.menuProcessor.ToLines()
|
b := bt.menuProcessor.ToLines()
|
||||||
log.Printf("tolines %v", b)
|
|
||||||
return w.Write(b)
|
return w.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
in = strings.TrimSpace(in)
|
in = strings.TrimSpace(in)
|
||||||
err = en.Exec([]byte(in), ctx)
|
running, err = en.Exec([]byte(in), ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "execution terminated: %v\n", err)
|
fmt.Fprintf(os.Stderr, "execution terminated: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
@ -50,4 +50,5 @@ func main() {
|
|||||||
en.WriteResult(b)
|
en.WriteResult(b)
|
||||||
fmt.Println(b.String())
|
fmt.Println(b.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -59,22 +59,38 @@ func(en *Engine) Init(sym string, ctx context.Context) error {
|
|||||||
// - input is objectively invalid (too long etc)
|
// - input is objectively invalid (too long etc)
|
||||||
// - no current bytecode is available
|
// - no current bytecode is available
|
||||||
// - input processing against bytcode failed
|
// - input processing against bytcode failed
|
||||||
func (en *Engine) Exec(input []byte, ctx context.Context) error {
|
func (en *Engine) Exec(input []byte, ctx context.Context) (bool, error) {
|
||||||
err := en.st.SetInput(input)
|
err := en.st.SetInput(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
log.Printf("new execution with input '%s' (0x%x)", input, input)
|
log.Printf("new execution with input '%s' (0x%x)", input, input)
|
||||||
code, err := en.st.GetCode()
|
code, err := en.st.GetCode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return false, err
|
||||||
}
|
}
|
||||||
if len(code) == 0 {
|
if len(code) == 0 {
|
||||||
return fmt.Errorf("no code to execute")
|
return false, fmt.Errorf("no code to execute")
|
||||||
}
|
}
|
||||||
code, err = vm.Run(code, en.st, en.rs, ctx)
|
code, err = vm.Run(code, en.st, en.rs, ctx)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v, err := en.st.MatchFlag(state.FLAG_TERMINATE, false)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if v {
|
||||||
|
if len(code) > 0 {
|
||||||
|
log.Printf("terminated with code remaining: %x", code)
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
en.st.SetCode(code)
|
en.st.SetCode(code)
|
||||||
return err
|
|
||||||
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteResult writes the output of the last vm execution to the given writer.
|
// WriteResult writes the output of the last vm execution to the given writer.
|
||||||
|
@ -97,7 +97,7 @@ func TestEngineInit(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
input := []byte("1")
|
input := []byte("1")
|
||||||
err = en.Exec(input, ctx)
|
_, err = en.Exec(input, ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,26 @@ func(st *State) FlagByteSize() uint8 {
|
|||||||
return uint8(len(st.Flags))
|
return uint8(len(st.Flags))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MatchFlag matches the current state of the given flag.
|
||||||
|
//
|
||||||
|
// The flag is specified given its bit index in the bit field.
|
||||||
|
//
|
||||||
|
// If invertMatch is set, a positive result will be returned if the flag is not set.
|
||||||
|
func(st *State) MatchFlag(sig uint32, invertMatch bool) (bool, error) {
|
||||||
|
r, err := st.GetFlag(sig)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if invertMatch {
|
||||||
|
if !r {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
} else if r {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetIndex scans a byte slice in same order as in storage, and returns the index of the first set bit.
|
// GetIndex scans a byte slice in same order as in storage, and returns the index of the first set bit.
|
||||||
//
|
//
|
||||||
// If the given byte slice is too small for the bit field bitsize, the check will terminate at end-of-data without error.
|
// If the given byte slice is too small for the bit field bitsize, the check will terminate at end-of-data without error.
|
||||||
|
@ -82,7 +82,7 @@ func RunDeadCheck(b []byte, st *state.State, rs resource.Resource, ctx context.C
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
log.Printf("no code remaining, let's check if we terminate")
|
log.Printf("no code remaining, let's check if we terminate")
|
||||||
r, err := matchFlag(st, state.FLAG_TERMINATE, false)
|
r, err := st.MatchFlag(state.FLAG_TERMINATE, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ func RunCatch(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
r, err := matchFlag(st, sig, mode)
|
r, err := st.MatchFlag(sig, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
@ -132,7 +132,7 @@ func RunCroak(b []byte, st *state.State, rs resource.Resource, ctx context.Conte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
r, err := matchFlag(st, sig, mode)
|
r, err := st.MatchFlag(sig, mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return b, err
|
return b, err
|
||||||
}
|
}
|
||||||
|
17
go/vm/vm.go
17
go/vm/vm.go
@ -3,8 +3,6 @@ package vm
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"git.defalsify.org/festive/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewLine creates a new instruction line for the VM.
|
// NewLine creates a new instruction line for the VM.
|
||||||
@ -177,21 +175,6 @@ func parseSig(b []byte) (uint32, bool, []byte, error) {
|
|||||||
return sig, matchmode, b, nil
|
return sig, matchmode, b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move to state
|
|
||||||
func matchFlag(st *state.State, sig uint32, invertMatch bool) (bool, error) {
|
|
||||||
r, err := st.GetFlag(sig)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
if invertMatch {
|
|
||||||
if !r {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
} else if r {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// split bytecode into head and b using length-prefixed bitfield
|
// split bytecode into head and b using length-prefixed bitfield
|
||||||
func byteSplit(b []byte) ([]byte, []byte, error) {
|
func byteSplit(b []byte) ([]byte, []byte, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user