summaryrefslogtreecommitdiffstats
path: root/contrib/netbsd-tests/lib/libc/regex
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/netbsd-tests/lib/libc/regex')
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/README33
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/anchor.in33
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/README8
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/basic.dat216
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/categorization.dat62
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/forcedassoc.dat30
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/leftassoc.dat16
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/nullsubexpr.dat73
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/repetition.dat140
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/att/rightassoc.dat16
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/backref.in21
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/basic.in5
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/bracket.in55
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/c_comments.in17
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/complex.in23
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/error.in30
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/meta.in21
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/nospec.in7
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/paren.in19
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/regress.in9
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/repet_bounded.in45
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/repet_multi.in21
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/repet_ordinary.in10
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/startend.in9
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/subexp.in57
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/subtle.in21
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/word_bound.in13
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/data/zero.in7
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/debug.c278
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/main.c523
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/split.c344
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/t_exhaust.c224
-rwxr-xr-xcontrib/netbsd-tests/lib/libc/regex/t_regex.sh73
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/t_regex_att.c639
-rw-r--r--contrib/netbsd-tests/lib/libc/regex/test_regex.h44
35 files changed, 3142 insertions, 0 deletions
diff --git a/contrib/netbsd-tests/lib/libc/regex/README b/contrib/netbsd-tests/lib/libc/regex/README
new file mode 100644
index 0000000..6d9a28c
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/README
@@ -0,0 +1,33 @@
+regular expression test set
+Lines are at least three fields, separated by one or more tabs. "" stands
+for an empty field. First field is an RE. Second field is flags. If
+C flag given, regcomp() is expected to fail, and the third field is the
+error name (minus the leading REG_).
+
+Otherwise it is expected to succeed, and the third field is the string to
+try matching it against. If there is no fourth field, the match is
+expected to fail. If there is a fourth field, it is the substring that
+the RE is expected to match. If there is a fifth field, it is a comma-
+separated list of what the subexpressions should match, with - indicating
+no match for that one. In both the fourth and fifth fields, a (sub)field
+starting with @ indicates that the (sub)expression is expected to match
+a null string followed by the stuff after the @; this provides a way to
+test where null strings match. The character `N' in REs and strings
+is newline, `S' is space, `T' is tab, `Z' is NUL.
+
+The full list of flags:
+ - placeholder, does nothing
+ b RE is a BRE, not an ERE
+ & try it as both an ERE and a BRE
+ C regcomp() error expected, third field is error name
+ i REG_ICASE
+ m ("mundane") REG_NOSPEC
+ s REG_NOSUB (not really testable)
+ n REG_NEWLINE
+ ^ REG_NOTBOL
+ $ REG_NOTEOL
+ # REG_STARTEND (see below)
+ p REG_PEND
+
+For REG_STARTEND, the start/end offsets are those of the substring
+enclosed in ().
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/anchor.in b/contrib/netbsd-tests/lib/libc/regex/data/anchor.in
new file mode 100644
index 0000000..d145408
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/anchor.in
@@ -0,0 +1,33 @@
+# anchoring and REG_NEWLINE
+^abc$ & abc abc
+a^b - a^b
+a^b b a^b a^b
+a$b - a$b
+a$b b a$b a$b
+^ & abc @abc
+$ & abc @
+^$ & "" @
+$^ - "" @
+\($\)\(^\) b "" @
+# stop retching, those are legitimate (although disgusting)
+^^ - "" @
+$$ - "" @
+b$ & abNc
+b$ &n abNc b
+^b$ & aNbNc
+^b$ &n aNbNc b
+^$ &n aNNb @Nb
+^$ n abc
+^$ n abcN @
+$^ n aNNb @Nb
+\($\)\(^\) bn aNNb @Nb
+^^ n^ aNNb @Nb
+$$ n aNNb @NN
+^a ^ a
+a$ $ a
+^a ^n aNb
+^b ^n aNb b
+a$ $n bNa
+b$ $n bNa b
+a*(^b$)c* - b b
+a*\(^b$\)c* b b b
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/README b/contrib/netbsd-tests/lib/libc/regex/data/att/README
new file mode 100644
index 0000000..e2ee6f6
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/README
@@ -0,0 +1,8 @@
+AT&T test data from: http://www2.research.att.com/~gsf/testregex/
+
+Quoting from the page:
+ testregex.c 2004-05-31 is the latest source for the AT&T Research
+ regression test harness for the X/Open regex pattern match interface.
+ See testregex(1) for option and test input details. The source and
+ test data posted here are license free.
+
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/basic.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/basic.dat
new file mode 100644
index 0000000..4399ca1
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/basic.dat
@@ -0,0 +1,216 @@
+NOTE all standard compliant implementations should pass these : 2002-05-31
+
+BE abracadabra$ abracadabracadabra (7,18)
+BE a...b abababbb (2,7)
+BE XXXXXX ..XXXXXX (2,8)
+E \) () (1,2)
+BE a] a]a (0,2)
+B } } (0,1)
+E \} } (0,1)
+BE \] ] (0,1)
+B ] ] (0,1)
+E ] ] (0,1)
+B { { (0,1)
+B } } (0,1)
+BE ^a ax (0,1)
+BE \^a a^a (1,3)
+BE a\^ a^ (0,2)
+BE a$ aa (1,2)
+BE a\$ a$ (0,2)
+BE ^$ NULL (0,0)
+E $^ NULL (0,0)
+E a($) aa (1,2)(2,2)
+E a*(^a) aa (0,1)(0,1)
+E (..)*(...)* a (0,0)
+E (..)*(...)* abcd (0,4)(2,4)
+E (ab|a)(bc|c) abc (0,3)(0,2)(2,3)
+E (ab)c|abc abc (0,3)(0,2)
+E a{0}b ab (1,2)
+E (a*)(b?)(b+)b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7)
+E (a*)(b{0,1})(b{1,})b{3} aaabbbbbbb (0,10)(0,3)(3,4)(4,7)
+E a{9876543210} NULL BADBR
+E ((a|a)|a) a (0,1)(0,1)(0,1)
+E (a*)(a|aa) aaaa (0,4)(0,3)(3,4)
+E a*(a.|aa) aaaa (0,4)(2,4)
+E a(b)|c(d)|a(e)f aef (0,3)(?,?)(?,?)(1,2)
+E (a|b)?.* b (0,1)(0,1)
+E (a|b)c|a(b|c) ac (0,2)(0,1)
+E (a|b)c|a(b|c) ab (0,2)(?,?)(1,2)
+E (a|b)*c|(a|ab)*c abc (0,3)(1,2)
+E (a|b)*c|(a|ab)*c xc (1,2)
+E (.a|.b).*|.*(.a|.b) xa (0,2)(0,2)
+E a?(ab|ba)ab abab (0,4)(0,2)
+E a?(ac{0}b|ba)ab abab (0,4)(0,2)
+E ab|abab abbabab (0,2)
+E aba|bab|bba baaabbbaba (5,8)
+E aba|bab baaabbbaba (6,9)
+E (aa|aaa)*|(a|aaaaa) aa (0,2)(0,2)
+E (a.|.a.)*|(a|.a...) aa (0,2)(0,2)
+E ab|a xabc (1,3)
+E ab|a xxabc (2,4)
+Ei (Ab|cD)* aBcD (0,4)(2,4)
+BE [^-] --a (2,3)
+BE [a-]* --a (0,3)
+BE [a-m-]* --amoma-- (0,4)
+E :::1:::0:|:::1:1:0: :::0:::1:::1:::0: (8,17)
+E :::1:::0:|:::1:1:1: :::0:::1:::1:::0: (8,17)
+{E [[:upper:]] A (0,1) [[<element>]] not supported
+E [[:lower:]]+ `az{ (1,3)
+E [[:upper:]]+ @AZ[ (1,3)
+BE [[-]] [[-]] (2,4)
+BE [[.NIL.]] NULL ECOLLATE
+BE [[=aleph=]] NULL ECOLLATE
+}
+BE$ \n \n (0,1)
+BEn$ \n \n (0,1)
+BE$ [^a] \n (0,1)
+BE$ \na \na (0,2)
+E (a)(b)(c) abc (0,3)(0,1)(1,2)(2,3)
+BE xxx xxx (0,3)
+E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 6, (0,6)
+E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) 2/7 (0,3)
+E1 (^|[ (,;])((([Ff]eb[^ ]* *|0*2/|\* */?)0*[6-7]))([^0-9]|$) feb 1,Feb 6 (5,11)
+E3 ((((((((((((((((((((((((((((((x)))))))))))))))))))))))))))))) x (0,1)(0,1)(0,1)
+E3 ((((((((((((((((((((((((((((((x))))))))))))))))))))))))))))))* xx (0,2)(1,2)(1,2)
+E a?(ab|ba)* ababababababababababababababababababababababababababababababababababababababababa (0,81)(79,81)
+E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabbbbaa (18,25)
+E abaa|abbaa|abbbaa|abbbbaa ababbabbbabbbabbbbabaa (18,22)
+E aaac|aabc|abac|abbc|baac|babc|bbac|bbbc baaabbbabac (7,11)
+BE$ .* \x01\xff (0,2)
+E aaaa|bbbb|cccc|ddddd|eeeeee|fffffff|gggg|hhhh|iiiii|jjjjj|kkkkk|llll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa (53,57)
+L aaaa\nbbbb\ncccc\nddddd\neeeeee\nfffffff\ngggg\nhhhh\niiiii\njjjjj\nkkkkk\nllll XaaaXbbbXcccXdddXeeeXfffXgggXhhhXiiiXjjjXkkkXlllXcbaXaaaa NOMATCH
+E a*a*a*a*a*b aaaaaaaaab (0,10)
+BE ^ NULL (0,0)
+BE $ NULL (0,0)
+BE ^$ NULL (0,0)
+BE ^a$ a (0,1)
+BE abc abc (0,3)
+BE abc xabcy (1,4)
+BE abc ababc (2,5)
+BE ab*c abc (0,3)
+BE ab*bc abc (0,3)
+BE ab*bc abbc (0,4)
+BE ab*bc abbbbc (0,6)
+E ab+bc abbc (0,4)
+E ab+bc abbbbc (0,6)
+E ab?bc abbc (0,4)
+E ab?bc abc (0,3)
+E ab?c abc (0,3)
+BE ^abc$ abc (0,3)
+BE ^abc abcc (0,3)
+BE abc$ aabc (1,4)
+BE ^ abc (0,0)
+BE $ abc (3,3)
+BE a.c abc (0,3)
+BE a.c axc (0,3)
+BE a.*c axyzc (0,5)
+BE a[bc]d abd (0,3)
+BE a[b-d]e ace (0,3)
+BE a[b-d] aac (1,3)
+BE a[-b] a- (0,2)
+BE a[b-] a- (0,2)
+BE a] a] (0,2)
+BE a[]]b a]b (0,3)
+BE a[^bc]d aed (0,3)
+BE a[^-b]c adc (0,3)
+BE a[^]b]c adc (0,3)
+E ab|cd abc (0,2)
+E ab|cd abcd (0,2)
+E a\(b a(b (0,3)
+E a\(*b ab (0,2)
+E a\(*b a((b (0,4)
+E ((a)) abc (0,1)(0,1)(0,1)
+E (a)b(c) abc (0,3)(0,1)(2,3)
+E a+b+c aabbabc (4,7)
+E a* aaa (0,3)
+E (a*)* - (0,0)(0,0)
+E (a*)+ - (0,0)(0,0)
+E (a*|b)* - (0,0)(0,0)
+E (a+|b)* ab (0,2)(1,2)
+E (a+|b)+ ab (0,2)(1,2)
+E (a+|b)? ab (0,1)(0,1)
+BE [^ab]* cde (0,3)
+E (^)* - (0,0)(0,0)
+BE a* NULL (0,0)
+E ([abc])*d abbbcd (0,6)(4,5)
+E ([abc])*bcd abcd (0,4)(0,1)
+E a|b|c|d|e e (0,1)
+E (a|b|c|d|e)f ef (0,2)(0,1)
+E ((a*|b))* - (0,0)(0,0)(0,0)
+BE abcd*efg abcdefg (0,7)
+BE ab* xabyabbbz (1,3)
+BE ab* xayabbbz (1,2)
+E (ab|cd)e abcde (2,5)(2,4)
+BE [abhgefdc]ij hij (0,3)
+E (a|b)c*d abcd (1,4)(1,2)
+E (ab|ab*)bc abc (0,3)(0,1)
+E a([bc]*)c* abc (0,3)(1,3)
+E a([bc]*)(c*d) abcd (0,4)(1,3)(3,4)
+E a([bc]+)(c*d) abcd (0,4)(1,3)(3,4)
+E a([bc]*)(c+d) abcd (0,4)(1,2)(2,4)
+E a[bcd]*dcdcde adcdcde (0,7)
+E (ab|a)b*c abc (0,3)(0,2)
+E ((a)(b)c)(d) abcd (0,4)(0,3)(0,1)(1,2)(3,4)
+BE [A-Za-z_][A-Za-z0-9_]* alpha (0,5)
+E ^a(bc+|b[eh])g|.h$ abh (1,3)
+E (bc+d$|ef*g.|h?i(j|k)) effgz (0,5)(0,5)
+E (bc+d$|ef*g.|h?i(j|k)) ij (0,2)(0,2)(1,2)
+E (bc+d$|ef*g.|h?i(j|k)) reffgz (1,6)(1,6)
+E (((((((((a))))))))) a (0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)(0,1)
+BE multiple words multiple words yeah (0,14)
+E (.*)c(.*) abcde (0,5)(0,2)(3,5)
+BE abcd abcd (0,4)
+E a(bc)d abcd (0,4)(1,3)
+E a[-]?c ac (0,3)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qaddafi (0,15)(?,?)(10,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mo'ammar Gadhafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Kaddafi (0,15)(?,?)(10,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Qadhafi (0,15)(?,?)(10,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gadafi (0,14)(?,?)(10,11)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadafi (0,15)(?,?)(11,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moamar Gaddafi (0,14)(?,?)(9,11)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Mu'ammar Qadhdhafi (0,18)(?,?)(13,15)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Khaddafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafy (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghadafi (0,15)(?,?)(11,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Ghaddafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muamar Kaddafi (0,14)(?,?)(9,11)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Quathafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Muammar Gheddafi (0,16)(?,?)(11,13)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Khadafy (0,15)(?,?)(11,12)
+E M[ou]'?am+[ae]r .*([AEae]l[- ])?[GKQ]h?[aeu]+([dtz][dhz]?)+af[iy] Moammar Qudhafi (0,15)(?,?)(10,12)
+E a+(b|c)*d+ aabcdd (0,6)(3,4)
+E ^.+$ vivi (0,4)
+E ^(.+)$ vivi (0,4)(0,4)
+E ^([^!.]+).att.com!(.+)$ gryphon.att.com!eby (0,19)(0,7)(16,19)
+E ^([^!]+!)?([^!]+)$ bas (0,3)(?,?)(0,3)
+E ^([^!]+!)?([^!]+)$ bar!bas (0,7)(0,4)(4,7)
+E ^([^!]+!)?([^!]+)$ foo!bas (0,7)(0,4)(4,7)
+E ^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(4,8)(8,11)
+E ((foo)|(bar))!bas bar!bas (0,7)(0,3)(?,?)(0,3)
+E ((foo)|(bar))!bas foo!bar!bas (4,11)(4,7)(?,?)(4,7)
+E ((foo)|(bar))!bas foo!bas (0,7)(0,3)(0,3)
+E ((foo)|bar)!bas bar!bas (0,7)(0,3)
+E ((foo)|bar)!bas foo!bar!bas (4,11)(4,7)
+E ((foo)|bar)!bas foo!bas (0,7)(0,3)(0,3)
+E (foo|(bar))!bas bar!bas (0,7)(0,3)(0,3)
+E (foo|(bar))!bas foo!bar!bas (4,11)(4,7)(4,7)
+E (foo|(bar))!bas foo!bas (0,7)(0,3)
+E (foo|bar)!bas bar!bas (0,7)(0,3)
+E (foo|bar)!bas foo!bar!bas (4,11)(4,7)
+E (foo|bar)!bas foo!bas (0,7)(0,3)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bas (0,3)(?,?)(0,3)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ bar!bas (0,7)(0,4)(4,7)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bar!bas (0,11)(?,?)(?,?)(4,8)(8,11)
+E ^([^!]+!)?([^!]+)$|^.+!([^!]+!)([^!]+)$ foo!bas (0,7)(0,4)(4,7)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bas (0,3)(0,3)(?,?)(0,3)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ bar!bas (0,7)(0,7)(0,4)(4,7)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bar!bas (0,11)(0,11)(?,?)(?,?)(4,8)(8,11)
+E ^(([^!]+!)?([^!]+)|.+!([^!]+!)([^!]+))$ foo!bas (0,7)(0,7)(0,4)(4,7)
+E .*(/XXX).* /XXX (0,4)(0,4)
+E .*(\\XXX).* \XXX (0,4)(0,4)
+E \\XXX \XXX (0,4)
+E .*(/000).* /000 (0,4)(0,4)
+E .*(\\000).* \000 (0,4)(0,4)
+E \\000 \000 (0,4)
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/categorization.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/categorization.dat
new file mode 100644
index 0000000..d348512
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/categorization.dat
@@ -0,0 +1,62 @@
+NOTE regex implementation categorization 2004-05-31
+
+?E aa* xaxaax (1,2) POSITION=leftmost
+; POSITION=bug
+
+?E (a*)(ab)*(b*) abc (0,2)(0,1)(?,?)(1,2) ASSOCIATIVITY=right
+|E (a*)(ab)*(b*) abc (0,2)(0,0)(0,2)(2,2) ASSOCIATIVITY=left
+; ASSOCIATIVITY=bug
+
+?E ((a*)(ab)*)((b*)(a*)) aba (0,3)(0,2)(0,0)(0,2)(2,3)(2,2)(2,3) SUBEXPRESSION=precedence
+|E ((a*)(ab)*)((b*)(a*)) aba (0,3)(0,1)(0,1)(?,?)(1,3)(1,2)(2,3) SUBEXPRESSION=grouping
+; SUBEXPRESSION=bug
+
+?E (...?.?)* xxxxxx (0,6)(4,6) REPEAT_LONGEST=first
+|E (...?.?)* xxxxxx (0,6)(2,6) REPEAT_LONGEST=last
+|E (...?.?)* xxxxxx OK REPEAT_LONGEST=unknown
+; REPEAT_LONGEST=bug
+
+?E (a|ab)(bc|c) abcabc (0,3)(0,2)(2,3) EXPECTED
+|E (a|ab)(bc|c) abcabc (0,3)(0,1)(1,3) BUG=alternation-order
+; BUG=alternation-order-UNKNOWN
+
+?E (aba|a*b)(aba|a*b) ababa (0,5)(0,2)(2,5) EXPECTED
+|E (aba|a*b)(aba|a*b) ababa (0,4)(0,3)(3,4) BUG=first-match
+; BUG=unknown-match
+
+?B a\(b\)*\1 a NOMATCH EXPECTED
+|B a\(b\)*\1 a (0,1) BUG=nomatch-match
+|B a\(b\)*\1 abab (0,2)(1,2) # BUG=repeat-any
+; BUG=nomatch-match-UNKNOWN
+
+?E (a*){2} xxxxx (0,0)(0,0) EXPECTED
+|E (a*){2} xxxxx (5,5)(5,5) BUG=range-null
+; BUG=range-null-UNKNOWN
+
+?B a\(b\)*\1 abab NOMATCH EXPECTED
+|B a\(b\)*\1 abab (0,1) # BUG=nomatch-match
+|B a\(b\)*\1 abab (0,2)(1,2) BUG=repeat-any
+; BUG=repeat-any-UNKNOWN
+
+?E (a*)* a (0,1)(0,1) EXPECTED
+|E (a*)* ax (0,1)(0,1) BUG=repeat-null-unknown
+|E (a*)* a (0,1)(1,1) BUG=repeat-null
+; BUG=repeat-null-UNKNOWN
+
+?E (aba|a*b)* ababa (0,5)(2,5) EXPECTED
+|E (aba|a*b)* ababa (0,5)(3,4) BUG=repeat-short
+|E (aba|a*b)* ababa (0,4)(3,4) # LENGTH=first
+; BUG=repeat-short-UNKNOWN
+
+?E (a(b)?)+ aba (0,3)(2,3) EXPECTED
+|E (a(b)?)+ aba (0,3)(2,3)(1,2) BUG=repeat-artifact
+; BUG=repeat-artifact-UNKNOWN
+
+?B \(a\(b\)*\)*\2 abab NOMATCH EXPECTED
+|B \(a\(b\)*\)*\2 abab (0,4)(2,3)(1,2) BUG=repeat-artifact-nomatch
+; BUG=repeat-artifact-nomatch-UNKNOWN
+
+?E (a?)((ab)?)(b?)a?(ab)?b? abab (0,4)(0,1)(1,1)(?,?)(1,2)(2,4) BUG=subexpression-first
+|E .*(.*) ab (0,2)(2,2) EXPECTED
+|E .*(.*) ab (0,2)(0,2) BUG=subexpression-first
+; BUG=subexpression-first-UNKNOWN
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/forcedassoc.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/forcedassoc.dat
new file mode 100644
index 0000000..39f3111
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/forcedassoc.dat
@@ -0,0 +1,30 @@
+NOTE left-assoc:pass-all right-assoc:pass-all : 2002-04-29
+
+E (a|ab)(c|bcd) abcd (0,4)(0,1)(1,4)
+E (a|ab)(bcd|c) abcd (0,4)(0,1)(1,4)
+E (ab|a)(c|bcd) abcd (0,4)(0,1)(1,4)
+E (ab|a)(bcd|c) abcd (0,4)(0,1)(1,4)
+E ((a|ab)(c|bcd))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4)
+E ((a|ab)(bcd|c))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4)
+E ((ab|a)(c|bcd))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4)
+E ((ab|a)(bcd|c))(d*) abcd (0,4)(0,4)(0,1)(1,4)(4,4)
+E (a|ab)((c|bcd)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4)
+E (a|ab)((bcd|c)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4)
+E (ab|a)((c|bcd)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4)
+E (ab|a)((bcd|c)(d*)) abcd (0,4)(0,2)(2,4)(2,3)(3,4)
+E (a*)(b|abc) abc (0,3)(0,0)(0,3)
+E (a*)(abc|b) abc (0,3)(0,0)(0,3)
+E ((a*)(b|abc))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3)
+E ((a*)(abc|b))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3)
+E (a*)((b|abc)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3)
+E (a*)((abc|b)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3)
+E (a*)(b|abc) abc (0,3)(0,0)(0,3)
+E (a*)(abc|b) abc (0,3)(0,0)(0,3)
+E ((a*)(b|abc))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3)
+E ((a*)(abc|b))(c*) abc (0,3)(0,3)(0,0)(0,3)(3,3)
+E (a*)((b|abc)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3)
+E (a*)((abc|b)(c*)) abc (0,3)(0,1)(1,3)(1,2)(2,3)
+E (a|ab) ab (0,2)(0,2)
+E (ab|a) ab (0,2)(0,2)
+E (a|ab)(b*) ab (0,2)(0,2)(2,2)
+E (ab|a)(b*) ab (0,2)(0,2)(2,2)
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/leftassoc.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/leftassoc.dat
new file mode 100644
index 0000000..9c068c6
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/leftassoc.dat
@@ -0,0 +1,16 @@
+NOTE left-assoc:pass-all right-assoc:pass-none : 2002-04-29
+
+E (a|ab)(c|bcd)(d*) abcd (0,4)(0,1)(1,4)(4,4)
+E (a|ab)(bcd|c)(d*) abcd (0,4)(0,1)(1,4)(4,4)
+E (ab|a)(c|bcd)(d*) abcd (0,4)(0,1)(1,4)(4,4)
+E (ab|a)(bcd|c)(d*) abcd (0,4)(0,1)(1,4)(4,4)
+
+E (a*)(b|abc)(c*) abc (0,3)(0,0)(0,3)(3,3)
+E (a*)(abc|b)(c*) abc (0,3)(0,0)(0,3)(3,3)
+E (a*)(b|abc)(c*) abc (0,3)(0,0)(0,3)(3,3)
+E (a*)(abc|b)(c*) abc (0,3)(0,0)(0,3)(3,3)
+
+E (a|ab)(c|bcd)(d|.*) abcd (0,4)(0,1)(1,4)(4,4)
+E (a|ab)(bcd|c)(d|.*) abcd (0,4)(0,1)(1,4)(4,4)
+E (ab|a)(c|bcd)(d|.*) abcd (0,4)(0,1)(1,4)(4,4)
+E (ab|a)(bcd|c)(d|.*) abcd (0,4)(0,1)(1,4)(4,4)
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/nullsubexpr.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/nullsubexpr.dat
new file mode 100644
index 0000000..c73d8f0
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/nullsubexpr.dat
@@ -0,0 +1,73 @@
+NOTE null subexpression matches : 2002-06-06
+
+E (a*)* a (0,1)(0,1)
+E SAME x (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E (a*)+ a (0,1)(0,1)
+E SAME x (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E (a+)* a (0,1)(0,1)
+E SAME x (0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E (a+)+ a (0,1)(0,1)
+E SAME x NOMATCH
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+
+E ([a]*)* a (0,1)(0,1)
+E SAME x (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E ([a]*)+ a (0,1)(0,1)
+E SAME x (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaax (0,6)(0,6)
+E ([^b]*)* a (0,1)(0,1)
+E SAME b (0,0)(0,0)
+E SAME aaaaaa (0,6)(0,6)
+E SAME aaaaaab (0,6)(0,6)
+E ([ab]*)* a (0,1)(0,1)
+E SAME aaaaaa (0,6)(0,6)
+E SAME ababab (0,6)(0,6)
+E SAME bababa (0,6)(0,6)
+E SAME b (0,1)(0,1)
+E SAME bbbbbb (0,6)(0,6)
+E SAME aaaabcde (0,5)(0,5)
+E ([^a]*)* b (0,1)(0,1)
+E SAME bbbbbb (0,6)(0,6)
+E SAME aaaaaa (0,0)(0,0)
+E ([^ab]*)* ccccxx (0,6)(0,6)
+E SAME ababab (0,0)(0,0)
+
+E ((z)+|a)* zabcde (0,2)(1,2)
+
+{E a+? aaaaaa (0,1) no *? +? mimimal match ops
+E (a) aaa (0,1)(0,1)
+E (a*?) aaa (0,0)(0,0)
+E (a)*? aaa (0,0)
+E (a*?)*? aaa (0,0)
+}
+
+B \(a*\)*\(x\) x (0,1)(0,0)(0,1)
+B \(a*\)*\(x\) ax (0,2)(0,1)(1,2)
+B \(a*\)*\(x\) axa (0,2)(0,1)(1,2)
+B \(a*\)*\(x\)\(\1\) x (0,1)(0,0)(0,1)(1,1)
+B \(a*\)*\(x\)\(\1\) ax (0,2)(1,1)(1,2)(2,2)
+B \(a*\)*\(x\)\(\1\) axa (0,3)(0,1)(1,2)(2,3)
+B \(a*\)*\(x\)\(\1\)\(x\) axax (0,4)(0,1)(1,2)(2,3)(3,4)
+B \(a*\)*\(x\)\(\1\)\(x\) axxa (0,3)(1,1)(1,2)(2,2)(2,3)
+
+E (a*)*(x) x (0,1)(0,0)(0,1)
+E (a*)*(x) ax (0,2)(0,1)(1,2)
+E (a*)*(x) axa (0,2)(0,1)(1,2)
+
+E (a*)+(x) x (0,1)(0,0)(0,1)
+E (a*)+(x) ax (0,2)(0,1)(1,2)
+E (a*)+(x) axa (0,2)(0,1)(1,2)
+
+E (a*){2}(x) x (0,1)(0,0)(0,1)
+E (a*){2}(x) ax (0,2)(1,1)(1,2)
+E (a*){2}(x) axa (0,2)(1,1)(1,2)
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/repetition.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/repetition.dat
new file mode 100644
index 0000000..c24749c
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/repetition.dat
@@ -0,0 +1,140 @@
+NOTE implicit vs. explicit repetitions : 2009-02-02
+
+# Glenn Fowler <gsf@research.att.com>
+# conforming matches (column 4) must match one of the following BREs
+# NOMATCH
+# (0,.)\((\(.\),\(.\))(?,?)(\2,\3)\)*
+# (0,.)\((\(.\),\(.\))(\2,\3)(?,?)\)*
+# i.e., each 3-tuple has two identical elements and one (?,?)
+
+E ((..)|(.)) NULL NOMATCH
+E ((..)|(.))((..)|(.)) NULL NOMATCH
+E ((..)|(.))((..)|(.))((..)|(.)) NULL NOMATCH
+
+E ((..)|(.)){1} NULL NOMATCH
+E ((..)|(.)){2} NULL NOMATCH
+E ((..)|(.)){3} NULL NOMATCH
+
+E ((..)|(.))* NULL (0,0)
+
+E ((..)|(.)) a (0,1)(0,1)(?,?)(0,1)
+E ((..)|(.))((..)|(.)) a NOMATCH
+E ((..)|(.))((..)|(.))((..)|(.)) a NOMATCH
+
+E ((..)|(.)){1} a (0,1)(0,1)(?,?)(0,1)
+E ((..)|(.)){2} a NOMATCH
+E ((..)|(.)){3} a NOMATCH
+
+E ((..)|(.))* a (0,1)(0,1)(?,?)(0,1)
+
+E ((..)|(.)) aa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aa (0,2)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)
+E ((..)|(.))((..)|(.))((..)|(.)) aa NOMATCH
+
+E ((..)|(.)){1} aa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aa (0,2)(1,2)(?,?)(1,2)
+E ((..)|(.)){3} aa NOMATCH
+
+E ((..)|(.))* aa (0,2)(0,2)(0,2)(?,?)
+
+E ((..)|(.)) aaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaa (0,3)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)
+E ((..)|(.))((..)|(.))((..)|(.)) aaa (0,3)(0,1)(?,?)(0,1)(1,2)(?,?)(1,2)(2,3)(?,?)(2,3)
+
+E ((..)|(.)){1} aaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaa (0,3)(2,3)(?,?)(2,3)
+E ((..)|(.)){3} aaa (0,3)(2,3)(?,?)(2,3)
+
+E ((..)|(.))* aaa (0,3)(2,3)(?,?)(2,3)
+
+E ((..)|(.)) aaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E ((..)|(.))((..)|(.))((..)|(.)) aaaa (0,4)(0,2)(0,2)(?,?)(2,3)(?,?)(2,3)(3,4)(?,?)(3,4)
+
+E ((..)|(.)){1} aaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaaa (0,4)(2,4)(2,4)(?,?)
+E ((..)|(.)){3} aaaa (0,4)(3,4)(?,?)(3,4)
+
+E ((..)|(.))* aaaa (0,4)(2,4)(2,4)(?,?)
+
+E ((..)|(.)) aaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E ((..)|(.))((..)|(.))((..)|(.)) aaaaa (0,5)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,5)(?,?)(4,5)
+
+E ((..)|(.)){1} aaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaaaa (0,4)(2,4)(2,4)(?,?)
+E ((..)|(.)){3} aaaaa (0,5)(4,5)(?,?)(4,5)
+
+E ((..)|(.))* aaaaa (0,5)(4,5)(?,?)(4,5)
+
+E ((..)|(.)) aaaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.))((..)|(.)) aaaaaa (0,4)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)
+E ((..)|(.))((..)|(.))((..)|(.)) aaaaaa (0,6)(0,2)(0,2)(?,?)(2,4)(2,4)(?,?)(4,6)(4,6)(?,?)
+
+E ((..)|(.)){1} aaaaaa (0,2)(0,2)(0,2)(?,?)
+E ((..)|(.)){2} aaaaaa (0,4)(2,4)(2,4)(?,?)
+E ((..)|(.)){3} aaaaaa (0,6)(4,6)(4,6)(?,?)
+
+E ((..)|(.))* aaaaaa (0,6)(4,6)(4,6)(?,?)
+
+NOTE additional repetition tests graciously provided by Chris Kuklewicz www.haskell.org 2009-02-02
+
+# These test a bug in OS X / FreeBSD / NetBSD, and libtree.
+# Linux/GLIBC gets the {8,} and {8,8} wrong.
+
+:HA#100:E X(.?){0,}Y X1234567Y (0,9)(7,8)
+:HA#101:E X(.?){1,}Y X1234567Y (0,9)(7,8)
+:HA#102:E X(.?){2,}Y X1234567Y (0,9)(7,8)
+:HA#103:E X(.?){3,}Y X1234567Y (0,9)(7,8)
+:HA#104:E X(.?){4,}Y X1234567Y (0,9)(7,8)
+:HA#105:E X(.?){5,}Y X1234567Y (0,9)(7,8)
+:HA#106:E X(.?){6,}Y X1234567Y (0,9)(7,8)
+:HA#107:E X(.?){7,}Y X1234567Y (0,9)(7,8)
+:HA#108:E X(.?){8,}Y X1234567Y (0,9)(8,8)
+:HA#110:E X(.?){0,8}Y X1234567Y (0,9)(7,8)
+:HA#111:E X(.?){1,8}Y X1234567Y (0,9)(7,8)
+:HA#112:E X(.?){2,8}Y X1234567Y (0,9)(7,8)
+:HA#113:E X(.?){3,8}Y X1234567Y (0,9)(7,8)
+:HA#114:E X(.?){4,8}Y X1234567Y (0,9)(7,8)
+:HA#115:E X(.?){5,8}Y X1234567Y (0,9)(7,8)
+:HA#116:E X(.?){6,8}Y X1234567Y (0,9)(7,8)
+:HA#117:E X(.?){7,8}Y X1234567Y (0,9)(7,8)
+:HA#118:E X(.?){8,8}Y X1234567Y (0,9)(8,8)
+
+# These test a fixed bug in my regex-tdfa that did not keep the expanded
+# form properly grouped, so right association did the wrong thing with
+# these ambiguous patterns (crafted just to test my code when I became
+# suspicious of my implementation). The first subexpression should use
+# "ab" then "a" then "bcd".
+
+# OS X / FreeBSD / NetBSD badly fail many of these, with impossible
+# results like (0,6)(4,5)(6,6).
+
+:HA#260:E (a|ab|c|bcd){0,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#261:E (a|ab|c|bcd){1,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#262:E (a|ab|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#263:E (a|ab|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#264:E (a|ab|c|bcd){4,}(d*) ababcd NOMATCH
+:HA#265:E (a|ab|c|bcd){0,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#266:E (a|ab|c|bcd){1,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#267:E (a|ab|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#268:E (a|ab|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#269:E (a|ab|c|bcd){4,10}(d*) ababcd NOMATCH
+:HA#270:E (a|ab|c|bcd)*(d*) ababcd (0,6)(3,6)(6,6)
+:HA#271:E (a|ab|c|bcd)+(d*) ababcd (0,6)(3,6)(6,6)
+
+# The above worked on Linux/GLIBC but the following often fail.
+# They also trip up OS X / FreeBSD / NetBSD:
+
+:HA#280:E (ab|a|c|bcd){0,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#281:E (ab|a|c|bcd){1,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#282:E (ab|a|c|bcd){2,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#283:E (ab|a|c|bcd){3,}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#284:E (ab|a|c|bcd){4,}(d*) ababcd NOMATCH
+:HA#285:E (ab|a|c|bcd){0,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#286:E (ab|a|c|bcd){1,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#287:E (ab|a|c|bcd){2,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#288:E (ab|a|c|bcd){3,10}(d*) ababcd (0,6)(3,6)(6,6)
+:HA#289:E (ab|a|c|bcd){4,10}(d*) ababcd NOMATCH
+:HA#290:E (ab|a|c|bcd)*(d*) ababcd (0,6)(3,6)(6,6)
+:HA#291:E (ab|a|c|bcd)+(d*) ababcd (0,6)(3,6)(6,6)
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/att/rightassoc.dat b/contrib/netbsd-tests/lib/libc/regex/data/att/rightassoc.dat
new file mode 100644
index 0000000..ed7f28e
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/att/rightassoc.dat
@@ -0,0 +1,16 @@
+NOTE left-assoc:pass-none right-assoc:pass-all : 2002-04-29
+
+E (a|ab)(c|bcd)(d*) abcd (0,4)(0,2)(2,3)(3,4)
+E (a|ab)(bcd|c)(d*) abcd (0,4)(0,2)(2,3)(3,4)
+E (ab|a)(c|bcd)(d*) abcd (0,4)(0,2)(2,3)(3,4)
+E (ab|a)(bcd|c)(d*) abcd (0,4)(0,2)(2,3)(3,4)
+
+E (a*)(b|abc)(c*) abc (0,3)(0,1)(1,2)(2,3)
+E (a*)(abc|b)(c*) abc (0,3)(0,1)(1,2)(2,3)
+E (a*)(b|abc)(c*) abc (0,3)(0,1)(1,2)(2,3)
+E (a*)(abc|b)(c*) abc (0,3)(0,1)(1,2)(2,3)
+
+E (a|ab)(c|bcd)(d|.*) abcd (0,4)(0,2)(2,3)(3,4)
+E (a|ab)(bcd|c)(d|.*) abcd (0,4)(0,2)(2,3)(3,4)
+E (ab|a)(c|bcd)(d|.*) abcd (0,4)(0,2)(2,3)(3,4)
+E (ab|a)(bcd|c)(d|.*) abcd (0,4)(0,2)(2,3)(3,4)
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/backref.in b/contrib/netbsd-tests/lib/libc/regex/data/backref.in
new file mode 100644
index 0000000..cc59b06
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/backref.in
@@ -0,0 +1,21 @@
+# back references, ugh
+a\(b\)\2c bC ESUBREG
+a\(b\1\)c bC ESUBREG
+a\(b*\)c\1d b abbcbbd abbcbbd bb
+a\(b*\)c\1d b abbcbd
+a\(b*\)c\1d b abbcbbbd
+^\(.\)\1 b abc
+a\([bc]\)\1d b abcdabbd abbd b
+a\(\([bc]\)\2\)*d b abbccd abbccd
+a\(\([bc]\)\2\)*d b abbcbd
+# actually, this next one probably ought to fail, but the spec is unclear
+a\(\(b\)*\2\)*d b abbbd abbbd
+# here is a case that no NFA implementation does right
+\(ab*\)[ab]*\1 b ababaaa ababaaa a
+# check out normal matching in the presence of back refs
+\(a\)\1bcd b aabcd aabcd
+\(a\)\1bc*d b aabcd aabcd
+\(a\)\1bc*d b aabd aabd
+\(a\)\1bc*d b aabcccd aabcccd
+\(a\)\1bc*[ce]d b aabcccd aabcccd
+^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/basic.in b/contrib/netbsd-tests/lib/libc/regex/data/basic.in
new file mode 100644
index 0000000..d1e3aa9
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/basic.in
@@ -0,0 +1,5 @@
+# basics
+a & a a
+abc & abc abc
+abc|de - abc abc
+a|b|c - abc a
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/bracket.in b/contrib/netbsd-tests/lib/libc/regex/data/bracket.in
new file mode 100644
index 0000000..53a0b20
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/bracket.in
@@ -0,0 +1,55 @@
+# brackets, and numerous perversions thereof
+a[b]c & abc abc
+a[ab]c & abc abc
+a[^ab]c & adc adc
+a[]b]c & a]c a]c
+a[[b]c & a[c a[c
+a[-b]c & a-c a-c
+a[^]b]c & adc adc
+a[^-b]c & adc adc
+a[b-]c & a-c a-c
+a[b &C EBRACK
+a[] &C EBRACK
+a[1-3]c & a2c a2c
+a[3-1]c &C ERANGE
+a[1-3-5]c &C ERANGE
+a[[.-.]--]c & a-c a-c
+a[1- &C ERANGE
+a[[. &C EBRACK
+a[[.x &C EBRACK
+a[[.x. &C EBRACK
+a[[.x.] &C EBRACK
+a[[.x.]] & ax ax
+a[[.x,.]] &C ECOLLATE
+a[[.one.]]b & a1b a1b
+a[[.notdef.]]b &C ECOLLATE
+a[[.].]]b & a]b a]b
+a[[:alpha:]]c & abc abc
+a[[:notdef:]]c &C ECTYPE
+a[[: &C EBRACK
+a[[:alpha &C EBRACK
+a[[:alpha:] &C EBRACK
+a[[:alpha,:] &C ECTYPE
+a[[:]:]]b &C ECTYPE
+a[[:-:]]b &C ECTYPE
+a[[:alph:]] &C ECTYPE
+a[[:alphabet:]] &C ECTYPE
+[[:alnum:]]+ - -%@a0X- a0X
+[[:alpha:]]+ - -%@aX0- aX
+[[:blank:]]+ - aSSTb SST
+[[:cntrl:]]+ - aNTb NT
+[[:digit:]]+ - a019b 019
+[[:graph:]]+ - Sa%bS a%b
+[[:lower:]]+ - AabC ab
+[[:print:]]+ - NaSbN aSb
+[[:punct:]]+ - S%-&T %-&
+[[:space:]]+ - aSNTb SNT
+[[:upper:]]+ - aBCd BC
+[[:xdigit:]]+ - p0f3Cq 0f3C
+a[[=b=]]c & abc abc
+a[[= &C EBRACK
+a[[=b &C EBRACK
+a[[=b= &C EBRACK
+a[[=b=] &C EBRACK
+a[[=b,=]] &C ECOLLATE
+a[[=one=]]b & a1b a1b
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/c_comments.in b/contrib/netbsd-tests/lib/libc/regex/data/c_comments.in
new file mode 100644
index 0000000..ea3faf9
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/c_comments.in
@@ -0,0 +1,17 @@
+# Let's have some fun -- try to match a C comment.
+# first the obvious, which looks okay at first glance...
+/\*.*\*/ - /*x*/ /*x*/
+# but...
+/\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/
+# okay, we must not match */ inside; try to do that...
+/\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/
+/\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/
+# but...
+/\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/
+# and a still fancier version, which does it right (I think)...
+/\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/
+/\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/
+/\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/
+/\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/
+/\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/
+/\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/complex.in b/contrib/netbsd-tests/lib/libc/regex/data/complex.in
new file mode 100644
index 0000000..e114058
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/complex.in
@@ -0,0 +1,23 @@
+# complexities
+a(((b)))c - abc abc
+a(b|(c))d - abd abd
+a(b*|c)d - abbd abbd
+# just gotta have one DFA-buster, of course
+a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
+# and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
+# and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights
+# fish for anomalies as the number of states passes 32
+12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789
+123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890
+1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901
+12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012
+123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123
+# and one really big one, beyond any plausible word width
+1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890
+# fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm
+[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo
+[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq
+[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/error.in b/contrib/netbsd-tests/lib/libc/regex/data/error.in
new file mode 100644
index 0000000..61e0ea4
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/error.in
@@ -0,0 +1,30 @@
+# certain syntax errors and non-errors
+| C EMPTY
+| b | |
+* C BADRPT
+* b * *
++ C BADRPT
+? C BADRPT
+"" &C EMPTY
+() - abc @abc
+\(\) b abc @abc
+a||b C EMPTY
+|ab C EMPTY
+ab| C EMPTY
+(|a)b C EMPTY
+(a|)b C EMPTY
+(*a) C BADRPT
+(+a) C BADRPT
+(?a) C BADRPT
+({1}a) C BADRPT
+\(\{1\}a\) bC BADRPT
+(a|*b) C BADRPT
+(a|+b) C BADRPT
+(a|?b) C BADRPT
+(a|{1}b) C BADRPT
+^* C BADRPT
+^* b * *
+^+ C BADRPT
+^? C BADRPT
+^{1} C BADRPT
+^\{1\} bC BADRPT
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/meta.in b/contrib/netbsd-tests/lib/libc/regex/data/meta.in
new file mode 100644
index 0000000..4533d35
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/meta.in
@@ -0,0 +1,21 @@
+# metacharacters, backslashes
+a.c & abc abc
+a[bc]d & abd abd
+a\*c & a*c a*c
+a\\b & a\b a\b
+a\\\*b & a\*b a\*b
+a\bc & abc abc
+a\ &C EESCAPE
+a\\bc & a\bc a\bc
+\{ bC BADRPT
+a\[b & a[b a[b
+a[b &C EBRACK
+# trailing $ is a peculiar special case for the BRE code
+a$ & a a
+a$ & a$
+a\$ & a
+a\$ & a$ a$
+a\\$ & a
+a\\$ & a$
+a\\$ & a\$
+a\\$ & a\ a\
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/nospec.in b/contrib/netbsd-tests/lib/libc/regex/data/nospec.in
new file mode 100644
index 0000000..baf8d04
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/nospec.in
@@ -0,0 +1,7 @@
+# plain strings, with the NOSPEC flag
+abc m abc abc
+abc m xabcy abc
+abc m xyz
+a*b m aba*b a*b
+a*b m ab
+"" mC EMPTY
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/paren.in b/contrib/netbsd-tests/lib/libc/regex/data/paren.in
new file mode 100644
index 0000000..9d206ce
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/paren.in
@@ -0,0 +1,19 @@
+# parentheses and perversions thereof
+a(b)c - abc abc
+a\(b\)c b abc abc
+a( C EPAREN
+a( b a( a(
+a\( - a( a(
+a\( bC EPAREN
+a\(b bC EPAREN
+a(b C EPAREN
+a(b b a(b a(b
+# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
+a) - a) a)
+) - ) )
+# end gagging (in a just world, those *should* give EPAREN)
+a) b a) a)
+a\) bC EPAREN
+\) bC EPAREN
+a()b - ab ab
+a\(\)b b ab ab
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/regress.in b/contrib/netbsd-tests/lib/libc/regex/data/regress.in
new file mode 100644
index 0000000..afd832a
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/regress.in
@@ -0,0 +1,9 @@
+# past problems, and suspected problems
+(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1
+abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop
+abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv
+(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11
+CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11
+Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz
+a?b - ab ab
+-\{0,1\}[0-9]*$ b -5 -5
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/repet_bounded.in b/contrib/netbsd-tests/lib/libc/regex/data/repet_bounded.in
new file mode 100644
index 0000000..ee6ff4c
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/repet_bounded.in
@@ -0,0 +1,45 @@
+# the dreaded bounded repetitions
+{ & { {
+{abc & {abc {abc
+{1 C BADRPT
+{1} C BADRPT
+a{b & a{b a{b
+a{1}b - ab ab
+a\{1\}b b ab ab
+a{1,}b - ab ab
+a\{1,\}b b ab ab
+a{1,2}b - aab aab
+a\{1,2\}b b aab aab
+a{1 C EBRACE
+a\{1 bC EBRACE
+a{1a C EBRACE
+a\{1a bC EBRACE
+a{1a} C BADBR
+a\{1a\} bC BADBR
+a{,2} - a{,2} a{,2}
+a\{,2\} bC BADBR
+a{,} - a{,} a{,}
+a\{,\} bC BADBR
+a{1,x} C BADBR
+a\{1,x\} bC BADBR
+a{1,x C EBRACE
+a\{1,x bC EBRACE
+a{300} C BADBR
+a\{300\} bC BADBR
+a{1,0} C BADBR
+a\{1,0\} bC BADBR
+ab{0,0}c - abcac ac
+ab\{0,0\}c b abcac ac
+ab{0,1}c - abcac abc
+ab\{0,1\}c b abcac abc
+ab{0,3}c - abbcac abbc
+ab\{0,3\}c b abbcac abbc
+ab{1,1}c - acabc abc
+ab\{1,1\}c b acabc abc
+ab{1,3}c - acabc abc
+ab\{1,3\}c b acabc abc
+ab{2,2}c - abcabbc abbc
+ab\{2,2\}c b abcabbc abbc
+ab{2,4}c - abcabbc abbc
+ab\{2,4\}c b abcabbc abbc
+((a{1,10}){1,10}){1,10} - a a a,a
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/repet_multi.in b/contrib/netbsd-tests/lib/libc/regex/data/repet_multi.in
new file mode 100644
index 0000000..da97bad
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/repet_multi.in
@@ -0,0 +1,21 @@
+# multiple repetitions
+a** &C BADRPT
+a++ C BADRPT
+a?? C BADRPT
+a*+ C BADRPT
+a*? C BADRPT
+a+* C BADRPT
+a+? C BADRPT
+a?* C BADRPT
+a?+ C BADRPT
+a{1}{1} C BADRPT
+a*{1} C BADRPT
+a+{1} C BADRPT
+a?{1} C BADRPT
+a{1}* C BADRPT
+a{1}+ C BADRPT
+a{1}? C BADRPT
+a*{b} - a{b} a{b}
+a\{1\}\{1\} bC BADRPT
+a*\{1\} bC BADRPT
+a\{1\}* bC BADRPT
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/repet_ordinary.in b/contrib/netbsd-tests/lib/libc/regex/data/repet_ordinary.in
new file mode 100644
index 0000000..08bc286
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/repet_ordinary.in
@@ -0,0 +1,10 @@
+# ordinary repetitions
+ab*c & abc abc
+ab+c - abc abc
+ab?c - abc abc
+a\(*\)b b a*b a*b
+a\(**\)b b ab ab
+a\(***\)b bC BADRPT
+*a b *a *a
+**a b a a
+***a bC BADRPT
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/startend.in b/contrib/netbsd-tests/lib/libc/regex/data/startend.in
new file mode 100644
index 0000000..c396e58
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/startend.in
@@ -0,0 +1,9 @@
+# check out the STARTEND option
+[abc] &# a(b)c b
+[abc] &# a(d)c
+[abc] &# a(bc)d b
+[abc] &# a(dc)d c
+. &# a()c
+b.*c &# b(bc)c bc
+b.* &# b(bc)c bc
+.*c &# b(bc)c bc
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/subexp.in b/contrib/netbsd-tests/lib/libc/regex/data/subexp.in
new file mode 100644
index 0000000..c7bcc06
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/subexp.in
@@ -0,0 +1,57 @@
+# subexpressions
+a(b)(c)d - abcd abcd b,c
+a(((b)))c - abc abc b,b,b
+a(b|(c))d - abd abd b,-
+a(b*|c|e)d - abbd abbd bb
+a(b*|c|e)d - acd acd c
+a(b*|c|e)d - ad ad @d
+a(b?)c - abc abc b
+a(b?)c - ac ac @c
+a(b+)c - abc abc b
+a(b+)c - abbbc abbbc bbb
+a(b*)c - ac ac @c
+(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de
+# the regression tester only asks for 9 subexpressions
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k
+a([bc]?)c - abc abc b
+a([bc]?)c - ac ac @c
+a([bc]+)c - abc abc b
+a([bc]+)c - abcc abcc bc
+a([bc]+)bc - abcbc abcbc bc
+a(bb+|b)b - abb abb b
+a(bbb+|bb+|b)b - abb abb b
+a(bbb+|bb+|b)b - abbb abbb bb
+a(bbb+|bb+|b)bb - abbb abbb b
+(.*).* - abcdef abcdef abcdef
+(a*)* - bc @b @b
+
+# do we get the right subexpression when it is used more than once?
+a(b|c)*d - ad ad -
+a(b|c)*d - abcd abcd c
+a(b|c)+d - abd abd b
+a(b|c)+d - abcd abcd c
+a(b|c?)+d - ad ad @d
+a(b|c?)+d - abcd abcd @d
+a(b|c){0,0}d - ad ad -
+a(b|c){0,1}d - ad ad -
+a(b|c){0,1}d - abd abd b
+a(b|c){0,2}d - ad ad -
+a(b|c){0,2}d - abcd abcd c
+a(b|c){0,}d - ad ad -
+a(b|c){0,}d - abcd abcd c
+a(b|c){1,1}d - abd abd b
+a(b|c){1,1}d - acd acd c
+a(b|c){1,2}d - abd abd b
+a(b|c){1,2}d - abcd abcd c
+a(b|c){1,}d - abd abd b
+a(b|c){1,}d - abcd abcd c
+a(b|c){2,2}d - acbd acbd b
+a(b|c){2,2}d - abcd abcd c
+a(b|c){2,4}d - abcd abcd c
+a(b|c){2,4}d - abcbd abcbd b
+a(b|c){2,4}d - abcbcd abcbcd c
+a(b|c){2,}d - abcd abcd c
+a(b|c){2,}d - abcbd abcbd b
+a(b+|((c)*))+d - abd abd @d,@d,-
+a(b+|((c)*))+d - abcd abcd @d,@d,-
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/subtle.in b/contrib/netbsd-tests/lib/libc/regex/data/subtle.in
new file mode 100644
index 0000000..92d68bb
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/subtle.in
@@ -0,0 +1,21 @@
+# subtleties of matching
+abc & xabcy abc
+a\(b\)?c\1d b acd
+aBc i Abc Abc
+a[Bc]*d i abBCcd abBCcd
+0[[:upper:]]1 &i 0a1 0a1
+0[[:lower:]]1 &i 0A1 0A1
+a[^b]c &i abc
+a[^b]c &i aBc
+a[^b]c &i adc adc
+[a]b[c] - abc abc
+[a]b[a] - aba aba
+[abc]b[abc] - abc abc
+[abc]b[abd] - abd abd
+a(b?c)+d - accd accd
+(wee|week)(knights|night) - weeknights weeknights
+(we|wee|week|frob)(knights|night|day) - weeknights weeknights
+a[bc]d - xyzaaabcaababdacd abd
+a[ab]c - aaabc abc
+abc s abc abc
+a* & b @b
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/word_bound.in b/contrib/netbsd-tests/lib/libc/regex/data/word_bound.in
new file mode 100644
index 0000000..e09a329
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/word_bound.in
@@ -0,0 +1,13 @@
+# word boundaries (ick)
+[[:<:]]a & a a
+[[:<:]]a & ba
+[[:<:]]a & -a a
+a[[:>:]] & a a
+a[[:>:]] & ab
+a[[:>:]] & a- a
+[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc
+[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc
+[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc
+[[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc
+[[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_
+[[:<:]]a_b[[:>:]] & x_a_b
diff --git a/contrib/netbsd-tests/lib/libc/regex/data/zero.in b/contrib/netbsd-tests/lib/libc/regex/data/zero.in
new file mode 100644
index 0000000..2786944
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/data/zero.in
@@ -0,0 +1,7 @@
+# cases involving NULs
+aZb & a a
+aZb &p a
+aZb &p# (aZb) aZb
+aZ*b &p# (ab) ab
+a.b &# (aZb) aZb
+a.* &# (aZb)c aZb
diff --git a/contrib/netbsd-tests/lib/libc/regex/debug.c b/contrib/netbsd-tests/lib/libc/regex/debug.c
new file mode 100644
index 0000000..f1d2b15
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/debug.c
@@ -0,0 +1,278 @@
+/* $NetBSD: debug.c,v 1.2 2011/10/10 04:32:41 christos Exp $ */
+
+/*-
+ * Copyright (c) 1993 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <limits.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#ifdef __FreeBSD__
+#include <wchar.h>
+#include <wctype.h>
+#endif
+
+/* Don't sort these! */
+#include "utils.h"
+#include "regex2.h"
+
+#include "test_regex.h"
+
+static void s_print(struct re_guts *, FILE *);
+static char *regchar(int);
+
+/*
+ * regprint - print a regexp for debugging
+ */
+void
+regprint(regex_t *r, FILE *d)
+{
+#ifdef __NetBSD__
+ struct re_guts *g = r->re_g;
+ int c;
+ int last;
+ int nincat[NC];
+
+ fprintf(d, "%ld states, %zu categories", (long)g->nstates,
+ g->ncategories);
+ fprintf(d, ", first %ld last %ld", (long)g->firststate,
+ (long)g->laststate);
+ if (g->iflags&USEBOL)
+ fprintf(d, ", USEBOL");
+ if (g->iflags&USEEOL)
+ fprintf(d, ", USEEOL");
+ if (g->iflags&BAD)
+ fprintf(d, ", BAD");
+ if (g->nsub > 0)
+ fprintf(d, ", nsub=%ld", (long)g->nsub);
+ if (g->must != NULL)
+ fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
+ g->must);
+ if (g->backrefs)
+ fprintf(d, ", backrefs");
+ if (g->nplus > 0)
+ fprintf(d, ", nplus %ld", (long)g->nplus);
+ fprintf(d, "\n");
+ s_print(g, d);
+ for (size_t i = 0; i < g->ncategories; i++) {
+ nincat[i] = 0;
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (g->categories[c] == i)
+ nincat[i]++;
+ }
+ fprintf(d, "cc0#%d", nincat[0]);
+ for (size_t i = 1; i < g->ncategories; i++)
+ if (nincat[i] == 1) {
+ for (c = CHAR_MIN; c <= CHAR_MAX; c++)
+ if (g->categories[c] == i)
+ break;
+ fprintf(d, ", %zu=%s", i, regchar(c));
+ }
+ fprintf(d, "\n");
+ for (size_t i = 1; i < g->ncategories; i++)
+ if (nincat[i] != 1) {
+ fprintf(d, "cc%zu\t", i);
+ last = -1;
+ for (c = CHAR_MIN; c <= CHAR_MAX+1; c++) /* +1 does flush */
+ if (c <= CHAR_MAX && g->categories[c] == i) {
+ if (last < 0) {
+ fprintf(d, "%s", regchar(c));
+ last = c;
+ }
+ } else {
+ if (last >= 0) {
+ if (last != c-1)
+ fprintf(d, "-%s",
+ regchar(c-1));
+ last = -1;
+ }
+ }
+ fprintf(d, "\n");
+ }
+#endif
+}
+
+/*
+ * s_print - print the strip for debugging
+ */
+static void
+s_print(struct re_guts *g, FILE *d)
+{
+ sop *s;
+ cset *cs;
+ int done = 0;
+ sop opnd;
+ int col = 0;
+ ssize_t last;
+ sopno offset = 2;
+# define GAP() { if (offset % 5 == 0) { \
+ if (col > 40) { \
+ fprintf(d, "\n\t"); \
+ col = 0; \
+ } else { \
+ fprintf(d, " "); \
+ col++; \
+ } \
+ } else \
+ col++; \
+ offset++; \
+ }
+
+ if (OP(g->strip[0]) != OEND)
+ fprintf(d, "missing initial OEND!\n");
+ for (s = &g->strip[1]; !done; s++) {
+ opnd = OPND(*s);
+ switch (OP(*s)) {
+ case OEND:
+ fprintf(d, "\n");
+ done = 1;
+ break;
+ case OCHAR:
+ if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
+ fprintf(d, "\\%c", (char)opnd);
+ else
+ fprintf(d, "%s", regchar((char)opnd));
+ break;
+ case OBOL:
+ fprintf(d, "^");
+ break;
+ case OEOL:
+ fprintf(d, "$");
+ break;
+ case OBOW:
+ fprintf(d, "\\{");
+ break;
+ case OEOW:
+ fprintf(d, "\\}");
+ break;
+ case OANY:
+ fprintf(d, ".");
+ break;
+ case OANYOF:
+ fprintf(d, "[(%ld)", (long)opnd);
+#ifdef __NetBSD__
+ cs = &g->sets[opnd];
+ last = -1;
+ for (size_t i = 0; i < g->csetsize+1; i++) /* +1 flushes */
+ if (CHIN(cs, i) && i < g->csetsize) {
+ if (last < 0) {
+ fprintf(d, "%s", regchar(i));
+ last = i;
+ }
+ } else {
+ if (last >= 0) {
+ if (last != (ssize_t)i - 1)
+ fprintf(d, "-%s",
+ regchar(i - 1));
+ last = -1;
+ }
+ }
+#endif
+ fprintf(d, "]");
+ break;
+ case OBACK_:
+ fprintf(d, "(\\<%ld>", (long)opnd);
+ break;
+ case O_BACK:
+ fprintf(d, "<%ld>\\)", (long)opnd);
+ break;
+ case OPLUS_:
+ fprintf(d, "(+");
+ if (OP(*(s+opnd)) != O_PLUS)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_PLUS:
+ if (OP(*(s-opnd)) != OPLUS_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "+)");
+ break;
+ case OQUEST_:
+ fprintf(d, "(?");
+ if (OP(*(s+opnd)) != O_QUEST)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_QUEST:
+ if (OP(*(s-opnd)) != OQUEST_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "?)");
+ break;
+ case OLPAREN:
+ fprintf(d, "((<%ld>", (long)opnd);
+ break;
+ case ORPAREN:
+ fprintf(d, "<%ld>))", (long)opnd);
+ break;
+ case OCH_:
+ fprintf(d, "<");
+ if (OP(*(s+opnd)) != OOR2)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case OOR1:
+ if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "|");
+ break;
+ case OOR2:
+ fprintf(d, "|");
+ if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_CH:
+ if (OP(*(s-opnd)) != OOR1)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, ">");
+ break;
+ default:
+#ifdef __FreeBSD__
+ fprintf(d, "!%ld(%ld)!", OP(*s), opnd);
+#else
+ fprintf(d, "!%d(%d)!", OP(*s), opnd);
+#endif
+ break;
+ }
+ if (!done)
+ GAP();
+ }
+}
+
+/*
+ * regchar - make a character printable
+ */
+static char * /* -> representation */
+regchar(int ch)
+{
+ static char buf[10];
+
+ if (isprint(ch) || ch == ' ')
+ sprintf(buf, "%c", ch);
+ else
+ sprintf(buf, "\\%o", ch);
+ return(buf);
+}
diff --git a/contrib/netbsd-tests/lib/libc/regex/main.c b/contrib/netbsd-tests/lib/libc/regex/main.c
new file mode 100644
index 0000000..eac4e2d
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/main.c
@@ -0,0 +1,523 @@
+/* $NetBSD: main.c,v 1.2 2011/09/16 16:13:18 plunky Exp $ */
+
+/*-
+ * Copyright (c) 1993 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <assert.h>
+#include <regex.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+
+#include "test_regex.h"
+
+char *progname;
+int debug = 0;
+int line = 0;
+int status = 0;
+
+int copts = REG_EXTENDED;
+int eopts = 0;
+regoff_t startoff = 0;
+regoff_t endoff = 0;
+
+static char empty = '\0';
+
+static char *eprint(int);
+static int efind(char *);
+
+/*
+ * main - do the simple case, hand off to regress() for regression
+ */
+int
+main(int argc, char *argv[])
+{
+ regex_t re;
+# define NS 10
+ regmatch_t subs[NS];
+ char erbuf[100];
+ int err;
+ size_t len;
+ int c;
+ int errflg = 0;
+ int i;
+ extern int optind;
+ extern char *optarg;
+
+ progname = argv[0];
+
+ while ((c = getopt(argc, argv, "c:e:S:E:x")) != -1)
+ switch (c) {
+ case 'c': /* compile options */
+ copts = options('c', optarg);
+ break;
+ case 'e': /* execute options */
+ eopts = options('e', optarg);
+ break;
+ case 'S': /* start offset */
+ startoff = (regoff_t)atoi(optarg);
+ break;
+ case 'E': /* end offset */
+ endoff = (regoff_t)atoi(optarg);
+ break;
+ case 'x': /* Debugging. */
+ debug++;
+ break;
+ case '?':
+ default:
+ errflg++;
+ break;
+ }
+ if (errflg) {
+ fprintf(stderr, "usage: %s ", progname);
+ fprintf(stderr, "[-c copt][-C][-d] [re]\n");
+ exit(2);
+ }
+
+ if (optind >= argc) {
+ regress(stdin);
+ exit(status);
+ }
+
+ err = regcomp(&re, argv[optind++], copts);
+ if (err) {
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %zd/%zd `%s'\n",
+ eprint(err), len, (size_t)sizeof(erbuf), erbuf);
+ exit(status);
+ }
+ regprint(&re, stdout);
+
+ if (optind >= argc) {
+ regfree(&re);
+ exit(status);
+ }
+
+ if (eopts&REG_STARTEND) {
+ subs[0].rm_so = startoff;
+ subs[0].rm_eo = strlen(argv[optind]) - endoff;
+ }
+ err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
+ if (err) {
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %zd/%zd `%s'\n",
+ eprint(err), len, (size_t)sizeof(erbuf), erbuf);
+ exit(status);
+ }
+ if (!(copts&REG_NOSUB)) {
+ len = (int)(subs[0].rm_eo - subs[0].rm_so);
+ if (subs[0].rm_so != -1) {
+ if (len != 0)
+ printf("match `%.*s'\n", (int)len,
+ argv[optind] + subs[0].rm_so);
+ else
+ printf("match `'@%.1s\n",
+ argv[optind] + subs[0].rm_so);
+ }
+ for (i = 1; i < NS; i++)
+ if (subs[i].rm_so != -1)
+ printf("(%d) `%.*s'\n", i,
+ (int)(subs[i].rm_eo - subs[i].rm_so),
+ argv[optind] + subs[i].rm_so);
+ }
+ exit(status);
+}
+
+/*
+ * regress - main loop of regression test
+ */
+void
+regress(FILE *in)
+{
+ char inbuf[1000];
+# define MAXF 10
+ char *f[MAXF];
+ int nf;
+ int i;
+ char erbuf[100];
+ size_t ne;
+ const char *badpat = "invalid regular expression";
+# define SHORT 10
+ const char *bpname = "REG_BADPAT";
+ regex_t re;
+
+ while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
+ line++;
+ if (inbuf[0] == '#' || inbuf[0] == '\n')
+ continue; /* NOTE CONTINUE */
+ inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
+ if (debug)
+ fprintf(stdout, "%d:\n", line);
+ nf = split(inbuf, f, MAXF, "\t\t");
+ if (nf < 3) {
+ fprintf(stderr, "bad input, line %d\n", line);
+ exit(1);
+ }
+ for (i = 0; i < nf; i++)
+ if (strcmp(f[i], "\"\"") == 0)
+ f[i] = &empty;
+ if (nf <= 3)
+ f[3] = NULL;
+ if (nf <= 4)
+ f[4] = NULL;
+ try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
+ if (opt('&', f[1])) /* try with either type of RE */
+ try(f[0], f[1], f[2], f[3], f[4],
+ options('c', f[1]) &~ REG_EXTENDED);
+ }
+
+ ne = regerror(REG_BADPAT, NULL, erbuf, sizeof(erbuf));
+ if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
+ fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
+ erbuf, badpat);
+ status = 1;
+ }
+ ne = regerror(REG_BADPAT, NULL, erbuf, (size_t)SHORT);
+ if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
+ ne != strlen(badpat)+1) {
+ fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
+ erbuf, SHORT-1, badpat);
+ status = 1;
+ }
+ ne = regerror(REG_ITOA|REG_BADPAT, NULL, erbuf, sizeof(erbuf));
+ if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
+ fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
+ erbuf, bpname);
+ status = 1;
+ }
+ re.re_endp = bpname;
+ ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
+ if (atoi(erbuf) != (int)REG_BADPAT) {
+ fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
+ erbuf, (long)REG_BADPAT);
+ status = 1;
+ } else if (ne != strlen(erbuf)+1) {
+ fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
+ erbuf, (long)REG_BADPAT);
+ status = 1;
+ }
+}
+
+/*
+ - try - try it, and report on problems
+ == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
+ */
+void
+try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts)
+{
+ regex_t re;
+# define NSUBS 10
+ regmatch_t subs[NSUBS];
+# define NSHOULD 15
+ char *should[NSHOULD];
+ int nshould;
+ char erbuf[100];
+ int err;
+ int len;
+ const char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
+ int i;
+ char *grump;
+ char f0copy[1000];
+ char f2copy[1000];
+
+ strcpy(f0copy, f0);
+ re.re_endp = (opts&REG_PEND) ? f0copy + strlen(f0copy) : NULL;
+ fixstr(f0copy);
+ err = regcomp(&re, f0copy, opts);
+ if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
+ /* unexpected error or wrong error */
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
+ line, type, eprint(err), len,
+ (int)sizeof(erbuf), erbuf);
+ status = 1;
+ } else if (err == 0 && opt('C', f1)) {
+ /* unexpected success */
+ fprintf(stderr, "%d: %s should have given REG_%s\n",
+ line, type, f2);
+ status = 1;
+ err = 1; /* so we won't try regexec */
+ }
+
+ if (err != 0) {
+ regfree(&re);
+ return;
+ }
+
+ strcpy(f2copy, f2);
+ fixstr(f2copy);
+
+ if (options('e', f1)&REG_STARTEND) {
+ if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
+ fprintf(stderr, "%d: bad STARTEND syntax\n", line);
+ subs[0].rm_so = strchr(f2, '(') - f2 + 1;
+ subs[0].rm_eo = strchr(f2, ')') - f2;
+ }
+ err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
+
+ if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
+ /* unexpected error or wrong error */
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
+ line, type, eprint(err), len,
+ (int)sizeof(erbuf), erbuf);
+ status = 1;
+ } else if (err != 0) {
+ /* nothing more to check */
+ } else if (f3 == NULL) {
+ /* unexpected success */
+ fprintf(stderr, "%d: %s exec should have failed\n",
+ line, type);
+ status = 1;
+ err = 1; /* just on principle */
+ } else if (opts&REG_NOSUB) {
+ /* nothing more to check */
+ } else if ((grump = check(f2, subs[0], f3)) != NULL) {
+ fprintf(stderr, "%d: %s %s\n", line, type, grump);
+ status = 1;
+ err = 1;
+ }
+
+ if (err != 0 || f4 == NULL) {
+ regfree(&re);
+ return;
+ }
+
+ for (i = 1; i < NSHOULD; i++)
+ should[i] = NULL;
+ nshould = split(f4, &should[1], NSHOULD-1, ",");
+ if (nshould == 0) {
+ nshould = 1;
+ should[1] = &empty;
+ }
+ for (i = 1; i < NSUBS; i++) {
+ grump = check(f2, subs[i], should[i]);
+ if (grump != NULL) {
+ fprintf(stderr, "%d: %s $%d %s\n", line,
+ type, i, grump);
+ status = 1;
+ err = 1;
+ }
+ }
+
+ regfree(&re);
+}
+
+/*
+ - options - pick options out of a regression-test string
+ == int options(int type, char *s);
+ */
+int
+options(int type, char *s)
+{
+ char *p;
+ int o = (type == 'c') ? copts : eopts;
+ const char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
+
+ for (p = s; *p != '\0'; p++)
+ if (strchr(legal, *p) != NULL)
+ switch (*p) {
+ case 'b':
+ o &= ~REG_EXTENDED;
+ break;
+ case 'i':
+ o |= REG_ICASE;
+ break;
+ case 's':
+ o |= REG_NOSUB;
+ break;
+ case 'n':
+ o |= REG_NEWLINE;
+ break;
+ case 'm':
+ o &= ~REG_EXTENDED;
+ o |= REG_NOSPEC;
+ break;
+ case 'p':
+ o |= REG_PEND;
+ break;
+ case '^':
+ o |= REG_NOTBOL;
+ break;
+ case '$':
+ o |= REG_NOTEOL;
+ break;
+ case '#':
+ o |= REG_STARTEND;
+ break;
+ case 't': /* trace */
+ o |= REG_TRACE;
+ break;
+ case 'l': /* force long representation */
+ o |= REG_LARGE;
+ break;
+ case 'r': /* force backref use */
+ o |= REG_BACKR;
+ break;
+ }
+ return(o);
+}
+
+/*
+ - opt - is a particular option in a regression string?
+ == int opt(int c, char *s);
+ */
+int /* predicate */
+opt(int c, char *s)
+{
+ return(strchr(s, c) != NULL);
+}
+
+/*
+ - fixstr - transform magic characters in strings
+ == void fixstr(char *p);
+ */
+void
+fixstr(char *p)
+{
+ if (p == NULL)
+ return;
+
+ for (; *p != '\0'; p++)
+ if (*p == 'N')
+ *p = '\n';
+ else if (*p == 'T')
+ *p = '\t';
+ else if (*p == 'S')
+ *p = ' ';
+ else if (*p == 'Z')
+ *p = '\0';
+}
+
+/*
+ * check - check a substring match
+ */
+char * /* NULL or complaint */
+check(char *str, regmatch_t sub, char *should)
+{
+ int len;
+ int shlen;
+ char *p;
+ static char grump[500];
+ char *at = NULL;
+
+ if (should != NULL && strcmp(should, "-") == 0)
+ should = NULL;
+ if (should != NULL && should[0] == '@') {
+ at = should + 1;
+ should = &empty;
+ }
+
+ /* check rm_so and rm_eo for consistency */
+ if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
+ (sub.rm_so != -1 && sub.rm_eo == -1) ||
+ (sub.rm_so != -1 && sub.rm_so < 0) ||
+ (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
+ sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
+ (long)sub.rm_eo);
+ return(grump);
+ }
+
+ /* check for no match */
+ if (sub.rm_so == -1) {
+ if (should == NULL)
+ return(NULL);
+ else {
+ sprintf(grump, "did not match");
+ return(grump);
+ }
+ }
+
+ /* check for in range */
+ if (sub.rm_eo > (ssize_t)strlen(str)) {
+ sprintf(grump, "start %ld end %ld, past end of string",
+ (long)sub.rm_so, (long)sub.rm_eo);
+ return(grump);
+ }
+
+ len = (int)(sub.rm_eo - sub.rm_so);
+ p = str + sub.rm_so;
+
+ /* check for not supposed to match */
+ if (should == NULL) {
+ sprintf(grump, "matched `%.*s'", len, p);
+ return(grump);
+ }
+
+ /* check for wrong match */
+ shlen = (int)strlen(should);
+ if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
+ sprintf(grump, "matched `%.*s' instead", len, p);
+ return(grump);
+ }
+ if (shlen > 0)
+ return(NULL);
+
+ /* check null match in right place */
+ if (at == NULL)
+ return(NULL);
+ shlen = strlen(at);
+ if (shlen == 0)
+ shlen = 1; /* force check for end-of-string */
+ if (strncmp(p, at, shlen) != 0) {
+ sprintf(grump, "matched null at `%.20s'", p);
+ return(grump);
+ }
+ return(NULL);
+}
+
+/*
+ * eprint - convert error number to name
+ */
+static char *
+eprint(int err)
+{
+ static char epbuf[100];
+ size_t len;
+
+ len = regerror(REG_ITOA|err, NULL, epbuf, sizeof(epbuf));
+ assert(len <= sizeof(epbuf));
+ return(epbuf);
+}
+
+/*
+ * efind - convert error name to number
+ */
+static int
+efind(char *name)
+{
+ static char efbuf[100];
+ regex_t re;
+
+ sprintf(efbuf, "REG_%s", name);
+ assert(strlen(efbuf) < sizeof(efbuf));
+ re.re_endp = efbuf;
+ (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
+ return(atoi(efbuf));
+}
diff --git a/contrib/netbsd-tests/lib/libc/regex/split.c b/contrib/netbsd-tests/lib/libc/regex/split.c
new file mode 100644
index 0000000..2a26b50
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/split.c
@@ -0,0 +1,344 @@
+/* $NetBSD: split.c,v 1.1 2011/01/08 18:10:31 pgoyette Exp $ */
+
+/*-
+ * Copyright (c) 1993 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "test_regex.h"
+
+/*
+ * split - divide a string into fields, like awk split()
+ *
+ * returns number of fields, including overflow
+ *
+ * fields[] list is not NULL-terminated
+ * nfields number of entries available in fields[]
+ * sep "" white, "c" single char, "ab" [ab]+
+ */
+int
+split(char *string, char *fields[], int nfields, const char *sep)
+{
+ char *p = string;
+ char c; /* latest character */
+ char sepc = *sep;
+ char sepc2;
+ int fn;
+ char **fp = fields;
+ const char *sepp;
+ int trimtrail;
+
+ /* white space */
+ if (sepc == '\0') {
+ while ((c = *p++) == ' ' || c == '\t')
+ continue;
+ p--;
+ trimtrail = 1;
+ sep = " \t"; /* note, code below knows this is 2 long */
+ sepc = ' ';
+ } else
+ trimtrail = 0;
+ sepc2 = sep[1]; /* now we can safely pick this up */
+
+ /* catch empties */
+ if (*p == '\0')
+ return(0);
+
+ /* single separator */
+ if (sepc2 == '\0') {
+ fn = nfields;
+ for (;;) {
+ *fp++ = p;
+ fn--;
+ if (fn == 0)
+ break;
+ while ((c = *p++) != sepc)
+ if (c == '\0')
+ return(nfields - fn);
+ *(p-1) = '\0';
+ }
+ /* we have overflowed the fields vector -- just count them */
+ fn = nfields;
+ for (;;) {
+ while ((c = *p++) != sepc)
+ if (c == '\0')
+ return(fn);
+ fn++;
+ }
+ /* not reached */
+ }
+
+ /* two separators */
+ if (sep[2] == '\0') {
+ fn = nfields;
+ for (;;) {
+ *fp++ = p;
+ fn--;
+ while ((c = *p++) != sepc && c != sepc2)
+ if (c == '\0') {
+ if (trimtrail && **(fp-1) == '\0')
+ fn++;
+ return(nfields - fn);
+ }
+ if (fn == 0)
+ break;
+ *(p-1) = '\0';
+ while ((c = *p++) == sepc || c == sepc2)
+ continue;
+ p--;
+ }
+ /* we have overflowed the fields vector -- just count them */
+ fn = nfields;
+ while (c != '\0') {
+ while ((c = *p++) == sepc || c == sepc2)
+ continue;
+ p--;
+ fn++;
+ while ((c = *p++) != '\0' && c != sepc && c != sepc2)
+ continue;
+ }
+ /* might have to trim trailing white space */
+ if (trimtrail) {
+ p--;
+ while ((c = *--p) == sepc || c == sepc2)
+ continue;
+ p++;
+ if (*p != '\0') {
+ if (fn == nfields+1)
+ *p = '\0';
+ fn--;
+ }
+ }
+ return(fn);
+ }
+
+ /* n separators */
+ fn = 0;
+ for (;;) {
+ if (fn < nfields)
+ *fp++ = p;
+ fn++;
+ for (;;) {
+ c = *p++;
+ if (c == '\0')
+ return(fn);
+ sepp = sep;
+ while ((sepc = *sepp++) != '\0' && sepc != c)
+ continue;
+ if (sepc != '\0') /* it was a separator */
+ break;
+ }
+ if (fn < nfields)
+ *(p-1) = '\0';
+ for (;;) {
+ c = *p++;
+ sepp = sep;
+ while ((sepc = *sepp++) != '\0' && sepc != c)
+ continue;
+ if (sepc == '\0') /* it wasn't a separator */
+ break;
+ }
+ p--;
+ }
+
+ /* not reached */
+}
+
+#ifdef TEST_SPLIT
+
+
+/*
+ * test program
+ * pgm runs regression
+ * pgm sep splits stdin lines by sep
+ * pgm str sep splits str by sep
+ * pgm str sep n splits str by sep n times
+ */
+int
+main(int argc, char *argv[])
+{
+ char buf[512];
+ int n;
+# define MNF 10
+ char *fields[MNF];
+
+ if (argc > 4)
+ for (n = atoi(argv[3]); n > 0; n--) {
+ (void) strcpy(buf, argv[1]);
+ }
+ else if (argc > 3)
+ for (n = atoi(argv[3]); n > 0; n--) {
+ (void) strcpy(buf, argv[1]);
+ (void) split(buf, fields, MNF, argv[2]);
+ }
+ else if (argc > 2)
+ dosplit(argv[1], argv[2]);
+ else if (argc > 1)
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ buf[strlen(buf)-1] = '\0'; /* stomp newline */
+ dosplit(buf, argv[1]);
+ }
+ else
+ regress();
+
+ exit(0);
+}
+
+void
+dosplit(char *string, char *seps)
+{
+# define NF 5
+ char *fields[NF];
+ int nf;
+
+ nf = split(string, fields, NF, seps);
+ print(nf, NF, fields);
+}
+
+void
+print(int nf, int nfp, char *fields)
+{
+ int fn;
+ int bound;
+
+ bound = (nf > nfp) ? nfp : nf;
+ printf("%d:\t", nf);
+ for (fn = 0; fn < bound; fn++)
+ printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n");
+}
+
+#define RNF 5 /* some table entries know this */
+struct {
+ char *str;
+ char *seps;
+ int nf;
+ char *fi[RNF];
+} tests[] = {
+ "", " ", 0, { "" },
+ " ", " ", 2, { "", "" },
+ "x", " ", 1, { "x" },
+ "xy", " ", 1, { "xy" },
+ "x y", " ", 2, { "x", "y" },
+ "abc def g ", " ", 5, { "abc", "def", "", "g", "" },
+ " a bcd", " ", 4, { "", "", "a", "bcd" },
+ "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " ", 6, { "", "a", "b", "c", "d " },
+
+ "", " _", 0, { "" },
+ " ", " _", 2, { "", "" },
+ "x", " _", 1, { "x" },
+ "x y", " _", 2, { "x", "y" },
+ "ab _ cd", " _", 2, { "ab", "cd" },
+ " a_b c ", " _", 5, { "", "a", "b", "c", "" },
+ "a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " _", 6, { "", "a", "b", "c", "d " },
+
+ "", " _~", 0, { "" },
+ " ", " _~", 2, { "", "" },
+ "x", " _~", 1, { "x" },
+ "x y", " _~", 2, { "x", "y" },
+ "ab _~ cd", " _~", 2, { "ab", "cd" },
+ " a_b c~", " _~", 5, { "", "a", "b", "c", "" },
+ "a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" },
+ "~a b c d ", " _~", 6, { "", "a", "b", "c", "d " },
+
+ "", " _~-", 0, { "" },
+ " ", " _~-", 2, { "", "" },
+ "x", " _~-", 1, { "x" },
+ "x y", " _~-", 2, { "x", "y" },
+ "ab _~- cd", " _~-", 2, { "ab", "cd" },
+ " a_b c~", " _~-", 5, { "", "a", "b", "c", "" },
+ "a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" },
+ "~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " },
+
+ "", " ", 0, { "" },
+ " ", " ", 2, { "", "" },
+ "x", " ", 1, { "x" },
+ "xy", " ", 1, { "xy" },
+ "x y", " ", 2, { "x", "y" },
+ "abc def g ", " ", 4, { "abc", "def", "g", "" },
+ " a bcd", " ", 3, { "", "a", "bcd" },
+ "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " ", 6, { "", "a", "b", "c", "d " },
+
+ "", "", 0, { "" },
+ " ", "", 0, { "" },
+ "x", "", 1, { "x" },
+ "xy", "", 1, { "xy" },
+ "x y", "", 2, { "x", "y" },
+ "abc def g ", "", 3, { "abc", "def", "g" },
+ "\t a bcd", "", 2, { "a", "bcd" },
+ " a \tb\t c ", "", 3, { "a", "b", "c" },
+ "a b c d e ", "", 5, { "a", "b", "c", "d", "e" },
+ "a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " },
+
+ NULL, NULL, 0, { NULL },
+};
+
+void
+regress(void)
+{
+ char buf[512];
+ int n;
+ char *fields[RNF+1];
+ int nf;
+ int i;
+ int printit;
+ char *f;
+
+ for (n = 0; tests[n].str != NULL; n++) {
+ (void) strcpy(buf, tests[n].str);
+ fields[RNF] = NULL;
+ nf = split(buf, fields, RNF, tests[n].seps);
+ printit = 0;
+ if (nf != tests[n].nf) {
+ printf("split `%s' by `%s' gave %d fields, not %d\n",
+ tests[n].str, tests[n].seps, nf, tests[n].nf);
+ printit = 1;
+ } else if (fields[RNF] != NULL) {
+ printf("split() went beyond array end\n");
+ printit = 1;
+ } else {
+ for (i = 0; i < nf && i < RNF; i++) {
+ f = fields[i];
+ if (f == NULL)
+ f = "(NULL)";
+ if (strcmp(f, tests[n].fi[i]) != 0) {
+ printf("split `%s' by `%s', field %d is `%s', not `%s'\n",
+ tests[n].str, tests[n].seps,
+ i, fields[i], tests[n].fi[i]);
+ printit = 1;
+ }
+ }
+ }
+ if (printit)
+ print(nf, RNF, fields);
+ }
+}
+#endif
diff --git a/contrib/netbsd-tests/lib/libc/regex/t_exhaust.c b/contrib/netbsd-tests/lib/libc/regex/t_exhaust.c
new file mode 100644
index 0000000..0670e51
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/t_exhaust.c
@@ -0,0 +1,224 @@
+/* $NetBSD: t_exhaust.c,v 1.7 2011/11/16 18:37:31 christos Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_exhaust.c,v 1.7 2011/11/16 18:37:31 christos Exp $");
+
+#include <stdio.h>
+#include <regex.h>
+#include <string.h>
+#include <stdlib.h>
+#include <err.h>
+#include <atf-c.h>
+#ifdef __FreeBSD__
+#include <sys/resource.h>
+#endif
+
+#ifndef REGEX_MAXSIZE
+#define REGEX_MAXSIZE 9999
+#endif
+
+static char *
+mkstr(const char *str, size_t len)
+{
+ size_t slen = strlen(str);
+ char *p = malloc(slen * len + 1);
+ ATF_REQUIRE(p != NULL);
+ for (size_t i = 0; i < len; i++)
+ strcpy(&p[i * slen], str);
+ return p;
+}
+
+static char *
+concat(const char *d, const char *s)
+{
+ size_t dlen = strlen(d);
+ size_t slen = strlen(s);
+ char *p = malloc(dlen + slen + 1);
+
+ ATF_REQUIRE(p != NULL);
+ strcpy(p, d);
+ strcpy(p + dlen, s);
+ return p;
+}
+
+static char *
+p0(size_t len)
+{
+ char *d, *s1, *s2;
+ s1 = mkstr("\\(", len);
+ s2 = concat(s1, ")");
+ free(s1);
+ d = concat("(", s2);
+ free(s2);
+ return d;
+}
+
+static char *
+p1(size_t len)
+{
+ char *d, *s1, *s2, *s3;
+ s1 = mkstr("\\(", 60);
+ s2 = mkstr("(.*)", len);
+ s3 = concat(s1, s2);
+ free(s2);
+ free(s1);
+ s1 = concat(s3, ")");
+ free(s3);
+ d = concat("(", s1);
+ free(s1);
+ return d;
+}
+
+static char *
+ps(const char *m, const char *s, size_t len)
+{
+ char *d, *s1, *s2, *s3;
+ s1 = mkstr(m, len);
+ s2 = mkstr(s, len);
+ s3 = concat(s1, s2);
+ free(s2);
+ free(s1);
+ d = concat("(.?)", s3);
+ free(s3);
+ return d;
+}
+
+static char *
+p2(size_t len)
+{
+ return ps("((.*){0,255}", ")", len);
+}
+
+static char *
+p3(size_t len)
+{
+ return ps("(.\\{0,}", ")", len);
+}
+
+static char *
+p4(size_t len)
+{
+ return ps("((.*){1,255}", ")", len);
+}
+
+static char *
+p5(size_t len)
+{
+ return ps("(", "){1,100}", len);
+}
+
+static char *
+p6(size_t len)
+{
+ char *d, *s1, *s2;
+ s1 = mkstr("(?:(.*)|", len);
+ s2 = concat(s1, "(.*)");
+ free(s1);
+ s1 = mkstr(")", len);
+ d = concat(s2, s1);
+ free(s1);
+ free(s2);
+ return d;
+}
+
+static const struct {
+ char *(*pattern)(size_t);
+ int type;
+} tests[] = {
+ { p0, REG_EXTENDED },
+ { p1, REG_EXTENDED },
+ { p2, REG_EXTENDED },
+ { p3, REG_EXTENDED },
+ { p4, REG_EXTENDED },
+ { p5, REG_EXTENDED },
+ { p6, REG_BASIC },
+};
+
+ATF_TC(regcomp_too_big);
+
+ATF_TC_HEAD(regcomp_too_big, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr", "Check that large patterns don't"
+ " crash, but return a proper error code");
+ // libtre needs it.
+ atf_tc_set_md_var(tc, "timeout", "600");
+#ifdef __FreeBSD__
+ atf_tc_set_md_var(tc, "require.memory", "64M");
+#else
+ atf_tc_set_md_var(tc, "require.memory", "120M");
+#endif
+}
+
+ATF_TC_BODY(regcomp_too_big, tc)
+{
+ regex_t re;
+#ifdef __FreeBSD__
+ struct rlimit limit;
+#endif
+ int e;
+
+#ifdef __FreeBSD__
+ limit.rlim_cur = limit.rlim_max = 64 * 1024 * 1024;
+ ATF_REQUIRE(setrlimit(RLIMIT_VMEM, &limit) != -1);
+#endif
+ for (size_t i = 0; i < __arraycount(tests); i++) {
+ char *d = (*tests[i].pattern)(REGEX_MAXSIZE);
+ e = regcomp(&re, d, tests[i].type);
+ if (e) {
+ char ebuf[1024];
+ (void)regerror(e, &re, ebuf, sizeof(ebuf));
+ ATF_REQUIRE_MSG(e == REG_ESPACE,
+ "regcomp returned %d (%s) for pattern %zu [%s]", e, ebuf,
+ i, d);
+ free(d);
+ continue;
+ }
+ free(d);
+ (void)regexec(&re, "aaaaaaaaaaa", 0, NULL, 0);
+ regfree(&re);
+ }
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, regcomp_too_big);
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/regex/t_regex.sh b/contrib/netbsd-tests/lib/libc/regex/t_regex.sh
new file mode 100755
index 0000000..bef3ac9
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/t_regex.sh
@@ -0,0 +1,73 @@
+# $NetBSD: t_regex.sh,v 1.1 2012/08/24 20:24:40 jmmv Exp $
+#
+# Copyright (c) 2008 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+check()
+{
+ local dataname="${1}"; shift
+
+ prog="$(atf_get_srcdir)/h_regex"
+ data="$(atf_get_srcdir)/data/${dataname}.in"
+
+ atf_check -x "${prog} <${data}"
+ atf_check -x "${prog} -el <${data}"
+ atf_check -x "${prog} -er <${data}"
+}
+
+create_tc()
+{
+ local name="${1}"; shift
+ local descr="${1}"; shift
+
+ atf_test_case "${name}"
+ eval "${name}_head() { atf_set 'descr' '${descr}'; }"
+ eval "${name}_body() { check '${name}'; }"
+
+ atf_add_test_case "${name}"
+}
+
+atf_init_test_cases()
+{
+ create_tc basic "Checks basic functionality"
+ create_tc paren "Checks parentheses"
+ create_tc anchor "Checks anchors and REG_NEWLINE"
+ create_tc error "Checks syntax errors and non-errors"
+ create_tc meta "Checks metacharacters and backslashes"
+ create_tc backref "Checks back references"
+ create_tc repet_ordinary "Checks ordinary repetitions"
+ create_tc repet_bounded "Checks bounded repetitions"
+ create_tc repet_multi "Checks multiple repetitions"
+ create_tc bracket "Checks brackets"
+ create_tc complex "Checks various complex examples"
+ create_tc subtle "Checks various subtle examples"
+ create_tc c_comments "Checks matching C comments"
+ create_tc subexp "Checks subexpressions"
+ create_tc startend "Checks STARTEND option"
+ create_tc nospec "Checks NOSPEC option"
+ create_tc zero "Checks NULs"
+ create_tc word_bound "Checks word boundaries"
+ create_tc regress "Checks various past problems and suspected problems"
+}
diff --git a/contrib/netbsd-tests/lib/libc/regex/t_regex_att.c b/contrib/netbsd-tests/lib/libc/regex/t_regex_att.c
new file mode 100644
index 0000000..0ca44b4
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/t_regex_att.c
@@ -0,0 +1,639 @@
+/* $NetBSD: t_regex_att.c,v 1.1 2012/08/24 20:24:40 jmmv Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_regex_att.c,v 1.1 2012/08/24 20:24:40 jmmv Exp $");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <regex.h>
+#include <string.h>
+#include <stdlib.h>
+#include <vis.h>
+#include <ctype.h>
+#include <atf-c.h>
+#ifdef __FreeBSD__
+#include <libutil.h>
+#endif
+
+static const char sep[] = "\r\n\t";
+static const char delim[3] = "\\\\\0";
+
+
+static void
+fail(const char *pattern, const char *input, size_t lineno) {
+ fprintf(stderr,
+ "skipping failed test at line %zu (pattern=%s, input=%s)\n",
+ lineno, pattern, input);
+}
+
+static int
+bug(const char *pattern, const char *input, size_t lineno) {
+ static const struct {
+ const char *p;
+ const char *i;
+ } b[] = {
+#if defined(REGEX_SPENCER)
+ /*
+ * The default libc implementation by Henry Spencer
+ */
+ { "a[-]?c", "ac" }, // basic.dat
+ { "(a*)*", "a" }, // categorization.dat
+ { "(aba|a*b)*", "ababa" }, // categorization.dat
+ { "\\(a\\(b\\)*\\)*\\2", "abab" }, // categorization.dat
+ { "(a*)*", "aaaaaa" }, // nullsubexpression.dat
+ { "(a*)*", "aaaaaax" }, // nullsubexpression.dat
+ { "(a*)+", "a" }, // nullsubexpression.dat
+ { "(a*)+", "aaaaaa" }, // nullsubexpression.dat
+ { "(a*)+", "aaaaaax" }, // nullsubexpression.dat
+ { "([a]*)*", "a" }, // nullsubexpression.dat
+ { "([a]*)*", "aaaaaa" }, // nullsubexpression.dat
+ { "([a]*)*", "aaaaaax" }, // nullsubexpression.dat
+ { "([a]*)+", "a" }, // nullsubexpression.dat
+ { "([a]*)+", "aaaaaa" }, // nullsubexpression.dat
+ { "([a]*)+", "aaaaaax" }, // nullsubexpression.dat
+ { "([^b]*)*", "a" }, // nullsubexpression.dat
+ { "([^b]*)*", "aaaaaa" }, // nullsubexpression.dat
+ { "([^b]*)*", "aaaaaab" }, // nullsubexpression.dat
+ { "([ab]*)*", "a" }, // nullsubexpression.dat
+ { "([ab]*)*", "aaaaaa" }, // nullsubexpression.dat
+ { "([ab]*)*", "ababab" }, // nullsubexpression.dat
+ { "([ab]*)*", "bababa" }, // nullsubexpression.dat
+ { "([ab]*)*", "b" }, // nullsubexpression.dat
+ { "([ab]*)*", "bbbbbb" }, // nullsubexpression.dat
+ { "([ab]*)*", "aaaabcde" }, // nullsubexpression.dat
+ { "([^a]*)*", "b" }, // nullsubexpression.dat
+ { "([^a]*)*", "bbbbbb" }, // nullsubexpression.dat
+ { "([^ab]*)*", "ccccxx" }, // nullsubexpression.dat
+ { "\\(a*\\)*\\(x\\)", "ax" }, // nullsubexpression.dat
+ { "\\(a*\\)*\\(x\\)", "axa" }, // nullsubexpression.dat
+ { "\\(a*\\)*\\(x\\)\\(\\1\\)", "x" }, // nullsubexpression.dat
+/* crash! */ { "\\(a*\\)*\\(x\\)\\(\\1\\)", "ax" }, // nullsubexpression.dat
+/* crash! */ { "\\(a*\\)*\\(x\\)\\(\\1\\)\\(x\\)", "axxa" }, // ""
+ { "(a*)*(x)", "ax" }, // nullsubexpression.dat
+ { "(a*)*(x)", "axa" }, // nullsubexpression.dat
+ { "(a*)+(x)", "ax" }, // nullsubexpression.dat
+ { "(a*)+(x)", "axa" }, // nullsubexpression.dat
+ { "((a|ab)(c|bcd))(d*)", "abcd" }, // forcedassoc.dat
+ { "((a|ab)(bcd|c))(d*)", "abcd" }, // forcedassoc.dat
+ { "((ab|a)(c|bcd))(d*)", "abcd" }, // forcedassoc.dat
+ { "((ab|a)(bcd|c))(d*)", "abcd" }, // forcedassoc.dat
+ { "((a*)(b|abc))(c*)", "abc" }, // forcedassoc.dat
+ { "((a*)(abc|b))(c*)", "abc" }, // forcedassoc.dat
+ { "((..)|(.)){2}", "aaa" }, // repetition.dat
+ { "((..)|(.)){3}", "aaa" }, // repetition.dat
+ { "((..)|(.)){3}", "aaaa" }, // repetition.dat
+ { "((..)|(.)){3}", "aaaaa" }, // repetition.dat
+ { "X(.?){0,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){1,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){2,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){3,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){4,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){5,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){6,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){7,}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){0,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){1,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){2,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){3,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){4,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){5,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){6,8}Y", "X1234567Y" }, // repetition.dat
+ { "X(.?){7,8}Y", "X1234567Y" }, // repetition.dat
+ { "(a|ab|c|bcd){0,}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd){1,}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd){2,}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd){3,}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd){1,10}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd){2,10}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd){3,10}(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd)*(d*)", "ababcd" }, // repetition.dat
+ { "(a|ab|c|bcd)+(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){0,}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){1,}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){2,}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){3,}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){1,10}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){2,10}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd){3,10}(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd)*(d*)", "ababcd" }, // repetition.dat
+ { "(ab|a|c|bcd)+(d*)", "ababcd" }, // repetition.dat
+#elif defined(REGEX_TRE)
+ { "a[-]?c", "ac" }, // basic.dat
+ { "a\\(b\\)*\\1", "a" }, // categorization.dat
+ { "a\\(b\\)*\\1", "abab" }, // categorization.dat
+ { "\\(a\\(b\\)*\\)*\\2", "abab" }, // categorization.dat
+ { "\\(a*\\)*\\(x\\)\\(\\1\\)", "ax" }, // categorization.dat
+ { "\\(a*\\)*\\(x\\)\\(\\1\\)\\(x\\)", "axxa" }, // ""
+ { "((..)|(.))*", "aa" }, // repetition.dat
+ { "((..)|(.))*", "aaa" }, // repetition.dat
+ { "((..)|(.))*", "aaaaa" }, // repetition.dat
+ { "X(.?){7,}Y", "X1234567Y" }, // repetition.dat
+#else
+ { "", "" }
+#endif
+ };
+
+ for (size_t i = 0; i < __arraycount(b); i++) {
+ if (strcmp(pattern, b[i].p) == 0 &&
+ strcmp(input, b[i].i) == 0) {
+ fail(pattern, input, lineno);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifdef REGEX_SPENCER
+#define HAVE_BRACES 1
+#define HAVE_MINIMAL 0
+#endif
+#ifndef HAVE_BRACES
+#define HAVE_BRACES 1
+#endif
+#ifndef HAVE_MINIMAL
+#define HAVE_MINIMAL 1
+#endif
+
+static int
+optional(const char *s)
+{
+ static const struct{
+ const char *n;
+ int v;
+ } nv[]= {
+ { "[[<element>]] not supported", HAVE_BRACES },
+ { "no *? +? mimimal match ops", HAVE_MINIMAL },
+ };
+
+ for (size_t i = 0; i < __arraycount(nv); i++)
+ if (strcmp(nv[i].n, s) == 0) {
+ if (nv[i].v)
+ return 0;
+ fprintf(stderr, "skipping unsupported [%s] tests\n", s);
+ return 1;
+ }
+
+ ATF_REQUIRE_MSG(0, "Unknown feature: %s", s);
+ return 0;
+}
+
+static int
+unsupported(const char *s)
+{
+ static const char *we[] = {
+#if defined(REGEX_SPENCER)
+ "ASSOCIATIVITY=left", // have right associativity
+ "SUBEXPRESSION=precedence", // have grouping subexpression
+ "REPEAT_LONGEST=last", // have first repeat longest
+ "BUG=alternation-order", // don't have it
+ "BUG=first-match", // don't have it
+ "BUG=nomatch-match", // don't have it
+ "BUG=repeat-any", // don't have it
+ "BUG=range-null", // don't have it
+ "BUG=repeat-null-unknown", // don't have it
+ "BUG=repeat-null", // don't have it
+ "BUG=repeat-artifact", // don't have it
+ "BUG=subexpression-first", // don't have it
+#elif defined(REGEX_TRE)
+ "ASSOCIATIVITY=right", // have left associativity
+ "SUBEXPRESSION=grouping", // have precedence subexpression
+ "REPEAT_LONGEST=first", // have last repeat longest
+ "LENGTH=first", // have last length
+ "BUG=alternation-order", // don't have it
+ "BUG=first-match", // don't have it
+ "BUG=range-null", // don't have it
+ "BUG=repeat-null", // don't have it
+ "BUG=repeat-artifact", // don't have it
+ "BUG=subexpression-first", // don't have it
+ "BUG=repeat-short", // don't have it
+#endif
+ };
+
+ if (s == NULL)
+ return 0;
+
+ while (*s == '#' || isspace((unsigned char)*s))
+ s++;
+
+ for (size_t i = 0; i < __arraycount(we); i++)
+ if (strcmp(we[i], s) == 0)
+ return 1;
+ return 0;
+}
+
+static void
+geterror(const char *s, int *comp, int *exec)
+{
+ static const struct {
+ const char *n;
+ int v;
+ int ce;
+ } nv[] = {
+#define COMP 1
+#define EXEC 2
+ { "OK", 0, COMP|EXEC },
+#define _DO(a, b) { # a, REG_ ## a, b },
+ _DO(NOMATCH, EXEC)
+ _DO(BADPAT, COMP)
+ _DO(ECOLLATE, COMP)
+ _DO(ECTYPE, COMP)
+ _DO(EESCAPE, COMP)
+ _DO(ESUBREG, COMP)
+ _DO(EBRACK, COMP)
+ _DO(EPAREN, COMP)
+ _DO(EBRACE, COMP)
+ _DO(BADBR, COMP)
+ _DO(ERANGE, COMP)
+ _DO(ESPACE, EXEC)
+ _DO(BADRPT, COMP)
+ _DO(EMPTY, COMP)
+ _DO(ASSERT, COMP)
+ _DO(INVARG, COMP)
+ _DO(ENOSYS, COMP)
+#undef _DO
+ };
+ *comp = 0;
+ *exec = 0;
+ for (size_t i = 0; i < __arraycount(nv); i++)
+ if (strcmp(s, nv[i].n) == 0) {
+ if (nv[i].ce & COMP)
+ *comp = nv[i].v;
+ if (nv[i].ce & EXEC)
+ *exec = nv[i].v;
+ return;
+ }
+ ATF_REQUIRE_MSG(0, "Unknown error %s", s);
+ return;
+}
+
+static int
+getflags(char *s)
+{
+ int flags = 0;
+
+ for (;; s++)
+ switch (*s) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ *s = '\0';
+ break;
+ case '\0':
+ return flags;
+ case 'B':
+ case 'E':
+ case 'F':
+ case 'L':
+ break;
+ case 'i':
+ flags |= REG_ICASE;
+ *s = '\0';
+ break;
+ case '$':
+ *s = '\0';
+ break;
+ case 'n':
+ *s = '\0';
+ break;
+ default:
+ ATF_REQUIRE_MSG(0, "Unknown char %c", *s);
+ break;
+ }
+}
+
+static size_t
+getmatches(const char *s)
+{
+ size_t i;
+ char *q;
+ for (i = 0; (q = strchr(s, '(')) != NULL; i++, s = q + 1)
+ continue;
+ ATF_REQUIRE_MSG(i != 0, "No parentheses found");
+ return i;
+}
+
+static void
+checkcomment(const char *s, size_t lineno)
+{
+ if (s && strstr(s, "BUG") != NULL)
+ fprintf(stderr, "Expected %s at line %zu\n", s, lineno);
+}
+
+static void
+checkmatches(const char *matches, size_t nm, const regmatch_t *pm,
+ size_t lineno)
+{
+ if (nm == 0)
+ return;
+
+ char *res;
+ size_t len = strlen(matches) + 1, off = 0;
+
+ ATF_REQUIRE((res = strdup(matches)) != NULL);
+ for (size_t i = 0; i < nm; i++) {
+ int l;
+ if (pm[i].rm_so == -1 && pm[i].rm_eo == -1)
+ l = snprintf(res + off, len - off, "(?,?)");
+ else
+ l = snprintf(res + off, len - off, "(%lld,%lld)",
+ (long long)pm[i].rm_so, (long long)pm[i].rm_eo);
+ ATF_REQUIRE_MSG((size_t) l < len - off, "String too long %s"
+ " cur=%d, max=%zu", res, l, len - off);
+ off += l;
+ }
+#ifdef __FreeBSD__
+ ATF_CHECK_STREQ_MSG(res, matches, " at line %zu", lineno);
+#else
+ ATF_REQUIRE_STREQ_MSG(res, matches, " at line %zu", lineno);
+#endif
+ free(res);
+}
+
+static void
+att_test(const struct atf_tc *tc, const char *data_name)
+{
+ regex_t re;
+ char *line, *lastpattern = NULL, data_path[MAXPATHLEN];
+ size_t len, lineno = 0;
+ int skipping = 0;
+ FILE *input_file;
+
+ snprintf(data_path, sizeof(data_path), "%s/data/%s.dat",
+ atf_tc_get_config_var(tc, "srcdir"), data_name);
+
+ input_file = fopen(data_path, "r");
+ if (input_file == NULL)
+ atf_tc_fail("Failed to open input file %s", data_path);
+
+ for (; (line = fparseln(input_file, &len, &lineno, delim, 0))
+ != NULL; free(line)) {
+ char *name, *pattern, *input, *matches, *comment;
+ regmatch_t *pm;
+ size_t nm;
+#ifdef DEBUG
+ fprintf(stderr, "[%s]\n", line);
+#endif
+ if ((name = strtok(line, sep)) == NULL)
+ continue;
+
+ /*
+ * We check these early so that we skip the lines quickly
+ * in order to do more strict testing on the other arguments
+ * The same characters are also tested in the switch below
+ */
+ if (*name == '}') {
+ skipping = 0;
+ continue;
+ }
+ if (skipping)
+ continue;
+ if (*name == ';' || *name == '#' || strcmp(name, "NOTE") == 0)
+ continue;
+ if (*name == ':') {
+ /* Skip ":HA#???:" prefix */
+ while (*++name && *name != ':')
+ continue;
+ if (*name)
+ name++;
+ }
+
+ ATF_REQUIRE_MSG((pattern = strtok(NULL, sep)) != NULL,
+ "Missing pattern at line %zu", lineno);
+ ATF_REQUIRE_MSG((input = strtok(NULL, sep)) != NULL,
+ "Missing input at line %zu", lineno);
+
+ if (strchr(name, '$')) {
+ ATF_REQUIRE(strunvis(pattern, pattern) != -1);
+ ATF_REQUIRE(strunvis(input, input) != -1);
+ }
+
+
+ if (strcmp(input, "NULL") == 0)
+ *input = '\0';
+
+ if (strcmp(pattern, "SAME") == 0) {
+ ATF_REQUIRE(lastpattern != NULL);
+ pattern = lastpattern;
+ } else {
+ free(lastpattern);
+ ATF_REQUIRE((lastpattern = strdup(pattern)) != NULL);
+ }
+
+ ATF_REQUIRE_MSG((matches = strtok(NULL, sep)) != NULL,
+ "Missing matches at line %zu", lineno);
+
+ comment = strtok(NULL, sep);
+ switch (*name) {
+ case '{': /* Begin optional implementation */
+ if (optional(comment)) {
+ skipping++;
+ continue;
+ }
+ name++; /* We have it, so ignore */
+ break;
+ case '}': /* End optional implementation */
+ skipping = 0;
+ continue;
+ case '?': /* Optional */
+ case '|': /* Alternative */
+ if (unsupported(comment))
+ continue;
+ name++; /* We have it, so ignore */
+ break;
+ case '#': /* Comment */
+ case ';': /* Skip */
+ continue;
+ default:
+ break;
+ }
+
+ /* XXX: Our bug */
+ if (bug(pattern, input, lineno))
+ continue;
+
+ int comp, exec;
+ if (*matches != '(') {
+ geterror(matches, &comp, &exec);
+ pm = NULL;
+ nm = 0;
+ } else {
+ comp = exec = 0;
+ nm = getmatches(matches);
+ ATF_REQUIRE((pm = calloc(nm, sizeof(*pm))) != NULL);
+ }
+
+
+
+ int iflags = getflags(name);
+ for (; *name; name++) {
+ int flags;
+ switch (*name) {
+ case 'B':
+ flags = REG_BASIC;
+ break;
+ case 'E':
+ flags = REG_EXTENDED;
+ break;
+ case 'L':
+ flags = REG_NOSPEC;
+ break;
+ default:
+ ATF_REQUIRE_MSG(0, "Bad name %c", *name);
+ continue;
+ }
+ int c = regcomp(&re, pattern, flags | iflags);
+ ATF_REQUIRE_MSG(c == comp,
+ "regcomp returned %d for pattern %s at line %zu",
+ c, pattern, lineno);
+ if (c)
+ continue;
+ int e = regexec(&re, input, nm, pm, 0);
+ ATF_REQUIRE_MSG(e == exec, "Expected error %d,"
+ " got %d at line %zu", exec, e, lineno);
+ checkmatches(matches, nm, pm, lineno);
+ checkcomment(comment, lineno);
+ regfree(&re);
+ }
+ free(pm);
+ }
+
+ fclose(input_file);
+}
+
+ATF_TC(basic);
+ATF_TC_HEAD(basic, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests basic functionality");
+}
+ATF_TC_BODY(basic, tc)
+{
+ att_test(tc, "basic");
+}
+
+ATF_TC(categorization);
+ATF_TC_HEAD(categorization, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests implementation categorization");
+}
+ATF_TC_BODY(categorization, tc)
+{
+ att_test(tc, "categorization");
+}
+
+ATF_TC(nullsubexpr);
+ATF_TC_HEAD(nullsubexpr, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests (...)*");
+}
+ATF_TC_BODY(nullsubexpr, tc)
+{
+ att_test(tc, "nullsubexpr");
+}
+
+ATF_TC(leftassoc);
+ATF_TC_HEAD(leftassoc, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests left-associative "
+ "implementations");
+}
+ATF_TC_BODY(leftassoc, tc)
+{
+#if SKIP_LEFTASSOC
+ /* jmmv: I converted the original shell-based tests to C and they
+ * disabled this test in a very unconventional way without giving
+ * any explation. Mark as broken here, but I don't know why. */
+ atf_tc_expect_fail("Reason for breakage unknown");
+#endif
+#ifdef __FreeBSD__
+ atf_tc_expect_fail("The expected and matched groups are mismatched on FreeBSD");
+#endif
+ att_test(tc, "leftassoc");
+}
+
+ATF_TC(rightassoc);
+ATF_TC_HEAD(rightassoc, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests right-associative "
+ "implementations");
+}
+ATF_TC_BODY(rightassoc, tc)
+{
+#if SKIP_RIGHTASSOC
+ /* jmmv: I converted the original shell-based tests to C and they
+ * disabled this test in a very unconventional way without giving
+ * any explation. Mark as broken here, but I don't know why. */
+ atf_tc_expect_fail("Reason for breakage unknown");
+#endif
+ att_test(tc, "rightassoc");
+}
+
+ATF_TC(forcedassoc);
+ATF_TC_HEAD(forcedassoc, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests subexpression grouping to "
+ "force association");
+}
+ATF_TC_BODY(forcedassoc, tc)
+{
+ att_test(tc, "forcedassoc");
+}
+
+ATF_TC(repetition);
+ATF_TC_HEAD(repetition, tc)
+{
+ atf_tc_set_md_var(tc, "descr", "Tests implicit vs. explicit "
+ "repetition");
+}
+ATF_TC_BODY(repetition, tc)
+{
+ att_test(tc, "repetition");
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ATF_TP_ADD_TC(tp, basic);
+ ATF_TP_ADD_TC(tp, categorization);
+ ATF_TP_ADD_TC(tp, nullsubexpr);
+ ATF_TP_ADD_TC(tp, leftassoc);
+ ATF_TP_ADD_TC(tp, rightassoc);
+ ATF_TP_ADD_TC(tp, forcedassoc);
+ ATF_TP_ADD_TC(tp, repetition);
+ return atf_no_error();
+}
diff --git a/contrib/netbsd-tests/lib/libc/regex/test_regex.h b/contrib/netbsd-tests/lib/libc/regex/test_regex.h
new file mode 100644
index 0000000..1d9f59d
--- /dev/null
+++ b/contrib/netbsd-tests/lib/libc/regex/test_regex.h
@@ -0,0 +1,44 @@
+/* $NetBSD: test_regex.h,v 1.1 2011/01/08 18:10:31 pgoyette Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* from main.c */
+void regress(FILE *);
+void try(char *, char *, char *, char *, char *, int);
+int options(int, char *);
+int opt(int, char *);
+void fixstr(char *);
+char *check(char *, regmatch_t, char *);
+
+/* from split.c */
+int split(char *string, char *fields[], int nfields, const char *sep);
+
+/* from debug.c */
+void regprint(regex_t *r, FILE *d);
OpenPOWER on IntegriCloud