libui/lifetimes.go

150 lines
2.8 KiB
Go
Raw Normal View History

// 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)
}
}