-
Notifications
You must be signed in to change notification settings - Fork 0
/
cli.go
184 lines (142 loc) · 3.68 KB
/
cli.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package main
import (
"bytes"
"flag"
"fmt"
"io"
"os"
"os/exec"
)
type CLIArgs struct {
ProgName string
InFile string
NoGui bool
Return bool // Print AC before exiting
// HALT on startup
HALT bool
// Exit on HALT
EXIT bool
// Clock Speed
F_CPU int64
// File[path] to use as virtual paper tape
// TapeFile string
// iTapeFile string
// oTapeFile string
// Lock memory viewer to page
Page int
}
func printUsage() {
fmt.Println("Usage:", os.Args[0], "[options] <in_file>")
fmt.Printf("\nOptions:\n")
flag.PrintDefaults()
}
func parseArgs() CLIArgs {
args := CLIArgs{}
// Set program name and usage print function
args.ProgName = os.Args[0]
flag.Usage = printUsage
// Add flags
flag.Int64Var(&args.F_CPU, "F_CPU", 8000000, "simulated clock `speed`")
flag.IntVar(&args.Page, "lock", -1, "Lock memory viewer to `page`")
flag.BoolVar(&args.HALT, "halt", false, "HALT the machine before first instruction cycle")
flag.BoolVar(&args.EXIT, "exit", false, "Exit the simulator on HALT")
flag.BoolVar(&args.NoGui, "no-gui", false, "Do not display curses ui")
flag.BoolVar(&args.Return, "print-return", false, "Print return code (AC) upon exiting")
// flag.StringVar(&args.TapeFile, "tape", "mk-12.tape", "Specify `path` to file for virtual tape reader/punch")
// flag.StringVar(&args.iTapeFile, "itape", "", "Specify `path` to file for virtual tape reader")
// flag.StringVar(&args.oTapeFile, "otape", "", "Specify `path` to file for virtual tape punch")
help := flag.Bool("help", false, "Print this message and exit")
// Parse
flag.Parse()
if *help {
flag.Usage()
os.Exit(0)
}
// if args.iTapeFile == "" {
// args.iTapeFile = args.TapeFile
// }
// if args.oTapeFile == "" {
// args.oTapeFile = args.TapeFile
// }
// Get remaining positional argument (infile)
if len(flag.Args()) == 1 {
args.InFile = flag.Arg(0)
} else {
flag.Usage()
os.Exit(1)
}
return args
}
type CLIFrontPanel struct {
}
func (fp *CLIFrontPanel) PowerOn(mk MK12) {
}
func (fp *CLIFrontPanel) PowerOff() {
}
func (fp *CLIFrontPanel) Update(mk MK12) {
}
func (fp *CLIFrontPanel) ReadSwitches() uint16 {
return 0
}
type StdinKeyboard struct {
Stdin *os.File
lastKey []byte
originalSttyState bytes.Buffer
}
func (sk *StdinKeyboard) getSttyState(state *bytes.Buffer) (err error) {
cmd := exec.Command("stty", "-g")
cmd.Stdin = sk.Stdin
cmd.Stdout = state
return cmd.Run()
}
func (sk *StdinKeyboard) saveSttyState() (err error) {
cmd := exec.Command("stty", "-g")
cmd.Stdin = sk.Stdin
cmd.Stdout = &sk.originalSttyState
return cmd.Run()
}
func (sk *StdinKeyboard) setSttyState(state *bytes.Buffer) (err error) {
cmd := exec.Command("stty", state.String())
cmd.Stdin = sk.Stdin
cmd.Stdout = nil
return cmd.Run()
}
func NewStdinKeyboard() (sk StdinKeyboard) {
sk = StdinKeyboard{
Stdin: os.Stdin,
lastKey: make([]byte, 1),
}
sk.saveSttyState()
defer sk.ResetSttyState()
// disable input buffering
err := sk.setSttyState(bytes.NewBufferString("cbreak"))
// err := exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run()
if err != nil {
panic(err)
}
// do not display entered characters on the screen
err = sk.setSttyState(bytes.NewBufferString("-echo"))
// err = exec.Command("stty", "-F", "/dev/tty", "-echo").Run()
if err != nil {
panic(err)
}
return sk
}
func (sk StdinKeyboard) Buffered() (buffered int) {
buffered, err := sk.Stdin.Read(sk.lastKey)
if err != nil {
if err == io.EOF {
// sk.Stdin.Seek(0, 0)
return 0
}
panic(err)
}
return
}
func (sk StdinKeyboard) ReadByte() (char byte, err error) {
char = sk.lastKey[0]
return
}
func (sk *StdinKeyboard) ResetSttyState() {
sk.setSttyState(&sk.originalSttyState)
}