implement matching
clean up interface equality hack

still needs more tests; checking in for gccgo testing

R=rsc
DELTA=304  (261 added, 14 deleted, 29 changed)
OCL=17128
CL=17135
diff --git a/usr/r/regexp/main.go b/usr/r/regexp/main.go
index d723d87..25ec07a 100644
--- a/usr/r/regexp/main.go
+++ b/usr/r/regexp/main.go
@@ -9,14 +9,131 @@
 	"regexp";
 )
 
-func main() {
-	str := "a*b*c*";
-	if sys.argc() > 1 {
-		str = sys.argv(1);
-	}
-	re, err := regexp.Compile(str);
-	if err != nil {
-		print("error: ", err.String(), "\n");
+var good_re = []string{
+	``
+,	`.`
+,	`^.$`
+,	`a`
+,	`a*`
+,	`a+`
+,	`a?`
+,	`a|b`
+,	`a*|b*`
+,	`(a*|b)(c*|d)`
+,	`[a-z]`
+,	`[a-abc-c\-\]\[]`
+,	`[a-z]+`
+,	`[]`
+,	`[abc]`
+,	`[^1234]`
+}
+
+// TODO: nice to do this with a map but we don't have an iterator
+type StringError struct {
+	re	string;
+	err	*os.Error;
+}
+var bad_re = []StringError{
+	StringError{ `*`,	 	regexp.ErrBareClosure },	
+	StringError{ `(abc`,	regexp.ErrUnmatchedLpar },	
+	StringError{ `abc)`,	regexp.ErrUnmatchedRpar },	
+	StringError{ `x[a-z`,	regexp.ErrUnmatchedLbkt },	
+	StringError{ `abc]`,	regexp.ErrUnmatchedRbkt },	
+	StringError{ `[z-a]`,	regexp.ErrBadRange },	
+	StringError{ `abc\`,	regexp.ErrExtraneousBackslash },	
+	StringError{ `a**`,	regexp.ErrBadClosure },	
+	StringError{ `a*+`,	regexp.ErrBadClosure },	
+	StringError{ `a??`,	regexp.ErrBadClosure },	
+	StringError{ `*`,	 	regexp.ErrBareClosure },	
+	StringError{ `\x`,	regexp.ErrBadBackslash }
+}
+
+type Vec [20]int;
+
+type Tester struct {
+	re	string;
+	text	string;
+	match	Vec;
+}
+
+var matches = []Tester {
+	Tester{ ``,	"",	Vec{0,0, -1,-1} },
+	Tester{ `a`,	"a",	Vec{0,1, -1,-1} },
+	Tester{ `b`,	"abc",	Vec{1,2, -1,-1} },
+	Tester{ `.`,	"a",	Vec{0,1, -1,-1} },
+	Tester{ `.*`,	"abcdef",	Vec{0,6, -1,-1} },
+	Tester{ `^abcd$`,	"abcd",	Vec{0,4, -1,-1} },
+	Tester{ `^bcd'`,	"abcdef",	Vec{-1,-1} },
+	Tester{ `^abcd$`,	"abcde",	Vec{-1,-1} },
+	Tester{ `a+`,	"baaab",	Vec{1, 4, -1,-1} },
+	Tester{ `a*`,	"baaab",	Vec{0, 0, -1,-1} }
+}
+
+func Compile(expr string, error *os.Error) regexp.Regexp {
+	re, err := regexp.Compile(expr);
+	if err != error {
+		print("compiling `", expr, "`; unexpected error: ", err.String(), "\n");
 		sys.exit(1);
 	}
+	return re
+}
+
+func MarkedLen(m *[] int) int {
+	if m == nil {
+		return 0
+	}
+	var i int;
+	for i = 0; i < len(m) && m[i] >= 0; i = i+2 {
+	}
+	return i
+}
+
+func PrintVec(m *[] int) {
+	l := MarkedLen(m);
+	for i := 0; i < l && m[i] >= 0; i = i+2 {
+		print(m[i], ",", m[i+1], " ")
+	}
+}
+
+func Equal(m1, m2 *[]int) bool {
+	l := MarkedLen(m1);
+	if l != MarkedLen(m2) {
+		return false
+	}
+	for i := 0; i < l; i++ {
+		if m1[i] != m2[i] {
+			return false
+		}
+	}
+	return true
+}
+
+func Match(expr string, str string, match *[]int) {
+	re := Compile(expr, nil);
+	m := re.Execute(str);
+	if !Equal(m, match) {
+		print("failure on `", expr, "` matching `", str, "`:\n");
+		PrintVec(m);
+		print("\nshould be:\n");
+		PrintVec(match);
+		print("\n");
+		sys.exit(1);
+	}
+}
+
+func main() {
+	if sys.argc() > 1 {
+		Compile(sys.argv(1), nil);
+		sys.exit(0);
+	}
+	for i := 0; i < len(good_re); i++ {
+		Compile(good_re[i], nil);
+	}
+	for i := 0; i < len(bad_re); i++ {
+		Compile(bad_re[i].re, bad_re[i].err)
+	}
+	for i := 0; i < len(matches); i++ {
+		t := &matches[i];
+		Match(t.re, t.text, &t.match)
+	}
 }