assorted cleanup and fixes

R=r
DELTA=209  (109 added, 79 deleted, 21 changed)
OCL=20930
CL=20934
diff --git a/src/lib/reflect/value.go b/src/lib/reflect/value.go
index 0457080..1b6ec31 100644
--- a/src/lib/reflect/value.go
+++ b/src/lib/reflect/value.go
@@ -14,6 +14,10 @@
 
 type Addr unsafe.pointer	// TODO: where are ptrint/intptr etc?
 
+func EqualType(a, b Type) bool {
+	return a.String() == b.String()
+}
+
 export type Value interface {
 	Kind()	int;
 	Type()	Type;
@@ -490,11 +494,12 @@
 	return NewValueAddr(v.typ.(PtrType).Sub(), v.Get());
 }
 
-func (v *PtrValueStruct) SetSub(subv Value)  {
-	a := v.typ.(PtrType).Sub().String();
-	b := subv.Type().String();
-	if a != b {
-		panicln("reflect: incompatible types in PtrValue.SetSub:", a, b);
+func (v *PtrValueStruct) SetSub(subv Value) {
+	a := v.typ.(PtrType).Sub();
+	b := subv.Type();
+	if !EqualType(a, b) {
+		panicln("reflect: incompatible types in PtrValue.SetSub:",
+			a.String(), b.String());
 	}
 	*v.addr.(*Addr) = subv.Addr();
 }
@@ -806,6 +811,38 @@
 	return NewValueAddr(typ, Addr(array));
 }
 
+export func CopyArray(dst ArrayValue, src ArrayValue, n int) {
+	if n == 0 {
+		return
+	}
+	dt := dst.Type().(ArrayType).Elem();
+	st := src.Type().(ArrayType).Elem();
+	if !EqualType(dt, st) {
+		panicln("reflect: incompatible types in CopyArray:",
+			dt.String(), st.String());
+	}
+	if n < 0 || n > dst.Len() || n > src.Len() {
+		panicln("reflect: CopyArray: invalid count", n);
+	}
+	dstp := uintptr(dst.Elem(0).Addr());
+	srcp := uintptr(src.Elem(0).Addr());
+	end := uintptr(n)*uintptr(dt.Size());
+	if dst.Type().Size() % 8 == 0 {
+		for i := uintptr(0); i < end; i += 8{
+			di := Addr(dstp + i);
+			si := Addr(srcp + i);
+			*di.(*uint64) = *si.(*uint64);
+		}
+	} else {
+		for i := uintptr(0); i < end; i++ {
+			di := Addr(dstp + i);
+			si := Addr(srcp + i);
+			*di.(*byte) = *si.(*byte);
+		}
+	}
+}
+
+
 export func NewValue(e interface {}) Value {
 	value, typestring  := sys.reflect(e);
 	p, ok := typecache[typestring];