150 lines
2.8 KiB
Go
150 lines
2.8 KiB
Go
|
// 18 april 2015
|
||
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"bufio"
|
||
|
"strings"
|
||
|
"strconv"
|
||
|
)
|
||
|
|
||
|
func toaddr(s string) uintptr {
|
||
|
n, err := strconv.Itoa(s)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return uintptr(n)
|
||
|
}
|
||
|
|
||
|
var failed = false
|
||
|
|
||
|
func report(format string, args ...interface{}) {
|
||
|
fmt.Fprintf(os.Stderr, format, args...)
|
||
|
failed = true
|
||
|
}
|
||
|
|
||
|
type Object struct {
|
||
|
Type string
|
||
|
Detail string
|
||
|
Refs int
|
||
|
CanDestroy bool
|
||
|
}
|
||
|
|
||
|
var objs = make(map[uintptr]*Object)
|
||
|
var singles = make(map[uintptr]*Object)
|
||
|
|
||
|
var newControls = map[string]string{
|
||
|
"uiNewButton()": "button",
|
||
|
"uiNewCheckbox()": "checkbox",
|
||
|
"uiNewEntry()": "entry",
|
||
|
"uiNewLabel()": "label",
|
||
|
"uiNewTab()": "tab",
|
||
|
}
|
||
|
|
||
|
func newControl(parts []string) {
|
||
|
ty := newControls[parts[0]]
|
||
|
addr := toaddr(parts[1])
|
||
|
detail := strings.Join(parts[2:], " ")
|
||
|
o := &Object{
|
||
|
Type: ty,
|
||
|
Detail: detail,
|
||
|
Refs: 1,
|
||
|
}
|
||
|
if oo := objs[addr]; oo != nil {
|
||
|
report("duplicate object %s %q, %s %q at 0x%X\n",
|
||
|
oo.Type, oo.Detail,
|
||
|
o.Type, o.Detail,
|
||
|
addr)
|
||
|
}
|
||
|
if oo := singles[addr]; oo != nil {
|
||
|
report("single %s %q and objecct %s %q coexist at 0x%X\n",
|
||
|
oo.Type, oo.Detail,
|
||
|
o.Type, o.Detail,
|
||
|
addr)
|
||
|
}
|
||
|
objs[addr] = o
|
||
|
}
|
||
|
|
||
|
func newSingle(parts []string) {
|
||
|
addrObj := toaddr(parts[1])
|
||
|
addrSingle := toaddr(parts[2])
|
||
|
o := objs[addrObj]
|
||
|
if o == nil {
|
||
|
report("single without object at 0x%X\n", addrObj)
|
||
|
}
|
||
|
o.Refs++
|
||
|
if oo := singles[addrSingle]; oo != nil {
|
||
|
report("duplicate singles %s %q, %s %q at 0x%X\n",
|
||
|
oo.Type, oo.Detail,
|
||
|
o.Type, o.Detail,
|
||
|
addrSingle)
|
||
|
}
|
||
|
singles[addrSingle] = o
|
||
|
}
|
||
|
|
||
|
func canDestroy(parts []string) {
|
||
|
addrObj := toaddr(parts[1])
|
||
|
addrSingle := toaddr(parts[2])
|
||
|
o := objs[addrObj]
|
||
|
if o == nil {
|
||
|
report("destroy object without object at 0x%X\n", addrObj)
|
||
|
}
|
||
|
if singles[addrSingle] != o {
|
||
|
report("inconsistency: single 0x%X has different object\n", addrSingle)
|
||
|
}
|
||
|
o.CanDestroy = true
|
||
|
}
|
||
|
|
||
|
func destroy(parts []string) {
|
||
|
var o *Object
|
||
|
var what string
|
||
|
|
||
|
ty := parts[1]
|
||
|
addr := toaddr(parts[2])
|
||
|
if ty == "single" {
|
||
|
o = singles[addr]
|
||
|
delete(singles, addr)
|
||
|
what = "single"
|
||
|
} else {
|
||
|
o = objs[addr]
|
||
|
delete(objs, addr)
|
||
|
what = "object"
|
||
|
}
|
||
|
if o == nil {
|
||
|
report("missing %s %p in destroy()\n", what, addr)
|
||
|
return
|
||
|
}
|
||
|
if !o.CanDestroy {
|
||
|
report("can't destroy %s %p yet\n", what, addr)
|
||
|
}
|
||
|
o.Refs--
|
||
|
if o.Refs < 0 {
|
||
|
report("not enough references to %p in destroy()\n", addr)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func main() {
|
||
|
b := bufio.NewScanner(os.Stdin)
|
||
|
for b.Scan() {
|
||
|
s := b.String()
|
||
|
parts := strings.Split(s, " ")
|
||
|
name := parts[0]
|
||
|
switch {
|
||
|
case newControls[name] != "":
|
||
|
newControl(parts)
|
||
|
case name == "newSingle":
|
||
|
newSingle(parts)
|
||
|
case name == "uiControlDestroy()":
|
||
|
canDestroy(parts)
|
||
|
case name == "OSdestroy":
|
||
|
destroy(parts)
|
||
|
default:
|
||
|
panic("unknown line " + name)
|
||
|
}
|
||
|
}
|
||
|
if err := b.Err(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|