commit 01301ae35765d89b988a3ac5d9c520e93b045e37
parent dfaf29bf00e52b69b8ed9e164822d55d4c91fbb0
Author: lash <dev@holbrook.no>
Date: Mon, 26 Aug 2024 18:34:56 +0100
Handle both CROAK and CATCH in preprocessor
Diffstat:
M | dev/asm/main.go | | | 134 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
1 file changed, 109 insertions(+), 25 deletions(-)
diff --git a/dev/asm/main.go b/dev/asm/main.go
@@ -1,7 +1,10 @@
package main
import (
+ "encoding/csv"
+ "flag"
"fmt"
+ "io"
"io/ioutil"
"log"
"os"
@@ -32,7 +35,75 @@ type asmAsm struct {
Instructions []*instruction `@@*`
}
-func preProcess(b []byte) ([]byte, error) {
+type preProcessor struct {
+ flags map[string]string
+}
+
+func newPreProcessor() *preProcessor {
+ return &preProcessor{
+ flags: make(map[string]string),
+ }
+}
+
+func(pp *preProcessor) load(fp string) (int, error) {
+ var i int
+ f, err := os.Open(fp)
+ if err != nil {
+ return 0, err
+ }
+ defer f.Close()
+ r := csv.NewReader(f)
+ for i = 0; true; i++ {
+ r, err := r.Read()
+ if err != nil {
+ if err == io.EOF {
+ break
+ }
+ return 0, err
+ }
+ if r[0] == "flag" {
+ if len(r) < 3 {
+ return 0, fmt.Errorf("Not enough fields for flag setting in line %d", i)
+ }
+ _, err = strconv.Atoi(r[2])
+ if err != nil {
+ return 0, fmt.Errorf("Flag translation value must be numeric")
+ }
+ pp.flags[r[1]] = r[2]
+ log.Printf("added flag translation %s -> %s", r[1], r[2])
+ }
+ }
+
+ return i, nil
+}
+
+
+func(pp *preProcessor) processFlag(s []string, one *string, two *string) ([]string, error) {
+ _, err := strconv.Atoi(*one)
+ if err != nil {
+ r, ok := pp.flags[*one]
+ if !ok {
+ return nil, fmt.Errorf("No flag translation found for '%s'", *one)
+ }
+ log.Printf("translated flag %s to %s", *one, r)
+ s = append(s, r)
+ } else {
+ s = append(s, *one)
+ }
+ return append(s, *two), nil
+}
+
+func(pp *preProcessor) pass(s []string, a arg) []string {
+ for _, r := range []*string{a.One, a.Two, a.Three} {
+ if r == nil {
+ break
+ }
+ s = append(s, *r)
+ }
+ return s
+}
+
+func(pp *preProcessor) run(b []byte) ([]byte, error) {
asmLexer := lexer.MustSimple([]lexer.SimpleRule{
{"Comment", `(?:#)[^\n]*`},
{"Ident", `^[A-Z]+`},
@@ -53,22 +124,24 @@ func preProcess(b []byte) ([]byte, error) {
b = []byte{}
for _, v := range ast.Instructions {
- s := []string{v.OpCode, *v.OpArg.One}
- if v.OpCode == "CATCH" {
- _, err := strconv.Atoi(*v.OpArg.Two)
- if err != nil {
- s = append(s, "42")
- } else {
- s = append(s, *v.OpArg.Two)
- }
- s = append(s, *v.OpArg.Three)
- } else {
- for _, r := range []*string{v.OpArg.Two, v.OpArg.Three} {
- if r == nil {
- break
+ s := []string{v.OpCode}
+ if v.OpArg.One == nil {
+ continue
+ }
+ switch v.OpCode {
+ case "CATCH":
+ s = append(s, *v.OpArg.One)
+ s, err = pp.processFlag(s, v.OpArg.Two, v.OpArg.Three)
+ if err != nil {
+ return nil, err
}
- s = append(s, *r)
- }
+ case "CROAK":
+ s, err = pp.processFlag(s, v.OpArg.One, v.OpArg.Two)
+ if err != nil {
+ return nil, err
+ }
+ default:
+ s = pp.pass(s, v.OpArg)
}
b = append(b, []byte(strings.Join(s, " "))...)
b = append(b, 0x0a)
@@ -78,27 +151,38 @@ func preProcess(b []byte) ([]byte, error) {
}
func main() {
- if (len(os.Args) < 2) {
+ var ppfp string
+ flag.StringVar(&ppfp, "f", "", "preprocessor data to load")
+ flag.Parse()
+ if (len(flag.Args()) < 1) {
os.Exit(1)
}
- fp := os.Args[1]
+ fp := flag.Arg(0)
v, err := ioutil.ReadFile(fp)
if err != nil {
- fmt.Fprintf(os.Stderr, "read error: %v", err)
+ fmt.Fprintf(os.Stderr, "read error: %v\n", err)
os.Exit(1)
}
- log.Printf("start preprocessor")
- v, err = preProcess(v)
- if err != nil {
- fmt.Fprintf(os.Stderr, "preprocess error: %v", err)
- os.Exit(1)
+ if len(ppfp) > 0 {
+ pp := newPreProcessor()
+ _, err := pp.load(ppfp)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "preprocessor load error: %v\n", err)
+ os.Exit(1)
+ }
+
+ v, err = pp.run(v)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "preprocess error: %v\n", err)
+ os.Exit(1)
+ }
}
log.Printf("preprocessor done")
n, err := asm.Parse(string(v), os.Stdout)
if err != nil {
- fmt.Fprintf(os.Stderr, "parse error: %v", err)
+ fmt.Fprintf(os.Stderr, "parse error: %v\n", err)
os.Exit(1)
}
log.Printf("parsed total %v bytes", n)