sl@0
|
1 |
# regexpTestLib.tcl --
|
sl@0
|
2 |
#
|
sl@0
|
3 |
# This file contains tcl procedures used by spencer2testregexp.tcl and
|
sl@0
|
4 |
# spencer2regexp.tcl, which are programs written to convert Henry
|
sl@0
|
5 |
# Spencer's test suite to tcl test files.
|
sl@0
|
6 |
#
|
sl@0
|
7 |
# Copyright (c) 1996 by Sun Microsystems, Inc.
|
sl@0
|
8 |
#
|
sl@0
|
9 |
# SCCS: @(#) regexpTestLib.tcl 1.4 98/01/22 14:48:34
|
sl@0
|
10 |
#
|
sl@0
|
11 |
|
sl@0
|
12 |
proc readInputFile {} {
|
sl@0
|
13 |
global inFileName
|
sl@0
|
14 |
global lineArray
|
sl@0
|
15 |
|
sl@0
|
16 |
set fileId [open $inFileName r]
|
sl@0
|
17 |
|
sl@0
|
18 |
set i 0
|
sl@0
|
19 |
while {[gets $fileId line] >= 0} {
|
sl@0
|
20 |
|
sl@0
|
21 |
set len [string length $line]
|
sl@0
|
22 |
|
sl@0
|
23 |
if {($len > 0) && ([string index $line [expr $len - 1]] == "\\")} {
|
sl@0
|
24 |
if {[info exists lineArray(c$i)] == 0} {
|
sl@0
|
25 |
set lineArray(c$i) 1
|
sl@0
|
26 |
} else {
|
sl@0
|
27 |
incr lineArray(c$i)
|
sl@0
|
28 |
}
|
sl@0
|
29 |
set line [string range $line 0 [expr $len - 2]]
|
sl@0
|
30 |
append lineArray($i) $line
|
sl@0
|
31 |
continue
|
sl@0
|
32 |
}
|
sl@0
|
33 |
if {[info exists lineArray(c$i)] == 0} {
|
sl@0
|
34 |
set lineArray(c$i) 1
|
sl@0
|
35 |
} else {
|
sl@0
|
36 |
incr lineArray(c$i)
|
sl@0
|
37 |
}
|
sl@0
|
38 |
append lineArray($i) $line
|
sl@0
|
39 |
incr i
|
sl@0
|
40 |
}
|
sl@0
|
41 |
|
sl@0
|
42 |
close $fileId
|
sl@0
|
43 |
return $i
|
sl@0
|
44 |
}
|
sl@0
|
45 |
|
sl@0
|
46 |
#
|
sl@0
|
47 |
# strings with embedded @'s are truncated
|
sl@0
|
48 |
# unpreceeded @'s are replaced by {}
|
sl@0
|
49 |
#
|
sl@0
|
50 |
proc removeAts {ls} {
|
sl@0
|
51 |
set len [llength $ls]
|
sl@0
|
52 |
set newLs {}
|
sl@0
|
53 |
foreach item $ls {
|
sl@0
|
54 |
regsub @.* $item "" newItem
|
sl@0
|
55 |
lappend newLs $newItem
|
sl@0
|
56 |
}
|
sl@0
|
57 |
return $newLs
|
sl@0
|
58 |
}
|
sl@0
|
59 |
|
sl@0
|
60 |
proc convertErrCode {code} {
|
sl@0
|
61 |
|
sl@0
|
62 |
set errMsg "couldn't compile regular expression pattern:"
|
sl@0
|
63 |
|
sl@0
|
64 |
if {[string compare $code "INVARG"] == 0} {
|
sl@0
|
65 |
return "$errMsg invalid argument to regex routine"
|
sl@0
|
66 |
} elseif {[string compare $code "BADRPT"] == 0} {
|
sl@0
|
67 |
return "$errMsg ?+* follows nothing"
|
sl@0
|
68 |
} elseif {[string compare $code "BADBR"] == 0} {
|
sl@0
|
69 |
return "$errMsg invalid repetition count(s)"
|
sl@0
|
70 |
} elseif {[string compare $code "BADOPT"] == 0} {
|
sl@0
|
71 |
return "$errMsg invalid embedded option"
|
sl@0
|
72 |
} elseif {[string compare $code "EPAREN"] == 0} {
|
sl@0
|
73 |
return "$errMsg unmatched ()"
|
sl@0
|
74 |
} elseif {[string compare $code "EBRACE"] == 0} {
|
sl@0
|
75 |
return "$errMsg unmatched {}"
|
sl@0
|
76 |
} elseif {[string compare $code "EBRACK"] == 0} {
|
sl@0
|
77 |
return "$errMsg unmatched \[\]"
|
sl@0
|
78 |
} elseif {[string compare $code "ERANGE"] == 0} {
|
sl@0
|
79 |
return "$errMsg invalid character range"
|
sl@0
|
80 |
} elseif {[string compare $code "ECTYPE"] == 0} {
|
sl@0
|
81 |
return "$errMsg invalid character class"
|
sl@0
|
82 |
} elseif {[string compare $code "ECOLLATE"] == 0} {
|
sl@0
|
83 |
return "$errMsg invalid collating element"
|
sl@0
|
84 |
} elseif {[string compare $code "EESCAPE"] == 0} {
|
sl@0
|
85 |
return "$errMsg invalid escape sequence"
|
sl@0
|
86 |
} elseif {[string compare $code "BADPAT"] == 0} {
|
sl@0
|
87 |
return "$errMsg invalid regular expression"
|
sl@0
|
88 |
} elseif {[string compare $code "ESUBREG"] == 0} {
|
sl@0
|
89 |
return "$errMsg invalid backreference number"
|
sl@0
|
90 |
} elseif {[string compare $code "IMPOSS"] == 0} {
|
sl@0
|
91 |
return "$errMsg can never match"
|
sl@0
|
92 |
}
|
sl@0
|
93 |
return "$errMsg $code"
|
sl@0
|
94 |
}
|
sl@0
|
95 |
|
sl@0
|
96 |
proc writeOutputFile {numLines fcn} {
|
sl@0
|
97 |
global outFileName
|
sl@0
|
98 |
global lineArray
|
sl@0
|
99 |
|
sl@0
|
100 |
# open output file and write file header info to it.
|
sl@0
|
101 |
|
sl@0
|
102 |
set fileId [open $outFileName w]
|
sl@0
|
103 |
|
sl@0
|
104 |
puts $fileId "# Commands covered: $fcn"
|
sl@0
|
105 |
puts $fileId "#"
|
sl@0
|
106 |
puts $fileId "# This Tcl-generated file contains tests for the $fcn tcl command."
|
sl@0
|
107 |
puts $fileId "# Sourcing this file into Tcl runs the tests and generates output for"
|
sl@0
|
108 |
puts $fileId "# errors. No output means no errors were found. Setting VERBOSE to"
|
sl@0
|
109 |
puts $fileId "# -1 will run tests that are known to fail."
|
sl@0
|
110 |
puts $fileId "#"
|
sl@0
|
111 |
puts $fileId "# Copyright (c) 1998 Sun Microsystems, Inc."
|
sl@0
|
112 |
puts $fileId "#"
|
sl@0
|
113 |
puts $fileId "# See the file \"license.terms\" for information on usage and redistribution"
|
sl@0
|
114 |
puts $fileId "# of this file, and for a DISCLAIMER OF ALL WARRANTIES."
|
sl@0
|
115 |
puts $fileId "#"
|
sl@0
|
116 |
puts $fileId "\# SCCS: \%Z\% \%M\% \%I\% \%E\% \%U\%"
|
sl@0
|
117 |
puts $fileId "\nproc print \{arg\} \{puts \$arg\}\n"
|
sl@0
|
118 |
puts $fileId "if \{\[string compare test \[info procs test\]\] == 1\} \{"
|
sl@0
|
119 |
puts $fileId " source defs ; set VERBOSE -1\n\}\n"
|
sl@0
|
120 |
puts $fileId "if \{\$VERBOSE != -1\} \{"
|
sl@0
|
121 |
puts $fileId " proc print \{arg\} \{\}\n\}\n"
|
sl@0
|
122 |
puts $fileId "#"
|
sl@0
|
123 |
puts $fileId "# The remainder of this file is Tcl tests that have been"
|
sl@0
|
124 |
puts $fileId "# converted from Henry Spencer's regexp test suite."
|
sl@0
|
125 |
puts $fileId "#\n"
|
sl@0
|
126 |
|
sl@0
|
127 |
set lineNum 0
|
sl@0
|
128 |
set srcLineNum 1
|
sl@0
|
129 |
while {$lineNum < $numLines} {
|
sl@0
|
130 |
|
sl@0
|
131 |
set currentLine $lineArray($lineNum)
|
sl@0
|
132 |
|
sl@0
|
133 |
# copy comment string to output file and continue
|
sl@0
|
134 |
|
sl@0
|
135 |
if {[string index $currentLine 0] == "#"} {
|
sl@0
|
136 |
puts $fileId $currentLine
|
sl@0
|
137 |
incr srcLineNum $lineArray(c$lineNum)
|
sl@0
|
138 |
incr lineNum
|
sl@0
|
139 |
continue
|
sl@0
|
140 |
}
|
sl@0
|
141 |
|
sl@0
|
142 |
set len [llength $currentLine]
|
sl@0
|
143 |
|
sl@0
|
144 |
# copy empty string to output file and continue
|
sl@0
|
145 |
|
sl@0
|
146 |
if {$len == 0} {
|
sl@0
|
147 |
puts $fileId "\n"
|
sl@0
|
148 |
incr srcLineNum $lineArray(c$lineNum)
|
sl@0
|
149 |
incr lineNum
|
sl@0
|
150 |
continue
|
sl@0
|
151 |
}
|
sl@0
|
152 |
if {($len < 3)} {
|
sl@0
|
153 |
puts "warning: test is too short --\n\t$currentLine"
|
sl@0
|
154 |
incr srcLineNum $lineArray(c$lineNum)
|
sl@0
|
155 |
incr lineNum
|
sl@0
|
156 |
continue
|
sl@0
|
157 |
}
|
sl@0
|
158 |
|
sl@0
|
159 |
puts $fileId [convertTestLine $currentLine $len $lineNum $srcLineNum]
|
sl@0
|
160 |
|
sl@0
|
161 |
incr srcLineNum $lineArray(c$lineNum)
|
sl@0
|
162 |
incr lineNum
|
sl@0
|
163 |
}
|
sl@0
|
164 |
|
sl@0
|
165 |
close $fileId
|
sl@0
|
166 |
}
|
sl@0
|
167 |
|
sl@0
|
168 |
proc convertTestLine {currentLine len lineNum srcLineNum} {
|
sl@0
|
169 |
|
sl@0
|
170 |
regsub -all {(?b)\\} $currentLine {\\\\} currentLine
|
sl@0
|
171 |
set re [lindex $currentLine 0]
|
sl@0
|
172 |
set flags [lindex $currentLine 1]
|
sl@0
|
173 |
set str [lindex $currentLine 2]
|
sl@0
|
174 |
|
sl@0
|
175 |
# based on flags, decide whether to skip the test
|
sl@0
|
176 |
|
sl@0
|
177 |
if {[findSkipFlag $flags]} {
|
sl@0
|
178 |
regsub -all {\[|\]|\(|\)|\{|\}|\#} $currentLine {\&} line
|
sl@0
|
179 |
set msg "\# skipping char mapping test from line $srcLineNum\n"
|
sl@0
|
180 |
append msg "print \{... skip test from line $srcLineNum: $line\}"
|
sl@0
|
181 |
return $msg
|
sl@0
|
182 |
}
|
sl@0
|
183 |
|
sl@0
|
184 |
# perform mapping if '=' flag exists
|
sl@0
|
185 |
|
sl@0
|
186 |
set noBraces 0
|
sl@0
|
187 |
if {[regexp {=|>} $flags] == 1} {
|
sl@0
|
188 |
regsub -all {_} $currentLine {\\ } currentLine
|
sl@0
|
189 |
regsub -all {A} $currentLine {\\007} currentLine
|
sl@0
|
190 |
regsub -all {B} $currentLine {\\b} currentLine
|
sl@0
|
191 |
regsub -all {E} $currentLine {\\033} currentLine
|
sl@0
|
192 |
regsub -all {F} $currentLine {\\f} currentLine
|
sl@0
|
193 |
regsub -all {N} $currentLine {\\n} currentLine
|
sl@0
|
194 |
|
sl@0
|
195 |
# if and \r substitutions are made, do not wrap re, flags,
|
sl@0
|
196 |
# str, and result in braces
|
sl@0
|
197 |
|
sl@0
|
198 |
set noBraces [regsub -all {R} $currentLine {\\\u000D} currentLine]
|
sl@0
|
199 |
regsub -all {T} $currentLine {\\t} currentLine
|
sl@0
|
200 |
regsub -all {V} $currentLine {\\v} currentLine
|
sl@0
|
201 |
if {[regexp {=} $flags] == 1} {
|
sl@0
|
202 |
set re [lindex $currentLine 0]
|
sl@0
|
203 |
}
|
sl@0
|
204 |
set str [lindex $currentLine 2]
|
sl@0
|
205 |
}
|
sl@0
|
206 |
set flags [removeFlags $flags]
|
sl@0
|
207 |
|
sl@0
|
208 |
# find the test result
|
sl@0
|
209 |
|
sl@0
|
210 |
set numVars [expr $len - 3]
|
sl@0
|
211 |
set vars {}
|
sl@0
|
212 |
set vals {}
|
sl@0
|
213 |
set result 0
|
sl@0
|
214 |
set v 0
|
sl@0
|
215 |
|
sl@0
|
216 |
if {[regsub {\*} "$flags" "" newFlags] == 1} {
|
sl@0
|
217 |
# an error is expected
|
sl@0
|
218 |
|
sl@0
|
219 |
if {[string compare $str "EMPTY"] == 0} {
|
sl@0
|
220 |
# empty regexp is not an error
|
sl@0
|
221 |
# skip this test
|
sl@0
|
222 |
|
sl@0
|
223 |
return "\# skipping the empty-re test from line $srcLineNum\n"
|
sl@0
|
224 |
}
|
sl@0
|
225 |
set flags $newFlags
|
sl@0
|
226 |
set result "\{1 \{[convertErrCode $str]\}\}"
|
sl@0
|
227 |
} elseif {$numVars > 0} {
|
sl@0
|
228 |
# at least 1 match is made
|
sl@0
|
229 |
|
sl@0
|
230 |
if {[regexp {s} $flags] == 1} {
|
sl@0
|
231 |
set result "\{0 1\}"
|
sl@0
|
232 |
} else {
|
sl@0
|
233 |
while {$v < $numVars} {
|
sl@0
|
234 |
append vars " var($v)"
|
sl@0
|
235 |
append vals " \$var($v)"
|
sl@0
|
236 |
incr v
|
sl@0
|
237 |
}
|
sl@0
|
238 |
set tmp [removeAts [lrange $currentLine 3 $len]]
|
sl@0
|
239 |
set result "\{0 \{1 $tmp\}\}"
|
sl@0
|
240 |
if {$noBraces} {
|
sl@0
|
241 |
set result "\[subst $result\]"
|
sl@0
|
242 |
}
|
sl@0
|
243 |
}
|
sl@0
|
244 |
} else {
|
sl@0
|
245 |
# no match is made
|
sl@0
|
246 |
|
sl@0
|
247 |
set result "\{0 0\}"
|
sl@0
|
248 |
}
|
sl@0
|
249 |
|
sl@0
|
250 |
# set up the test and write it to the output file
|
sl@0
|
251 |
|
sl@0
|
252 |
set cmd [prepareCmd $flags $re $str $vars $noBraces]
|
sl@0
|
253 |
if {$cmd == -1} {
|
sl@0
|
254 |
return "\# skipping test with metasyntax from line $srcLineNum\n"
|
sl@0
|
255 |
}
|
sl@0
|
256 |
|
sl@0
|
257 |
set test "test regexp-1.$srcLineNum \{converted from line $srcLineNum\} \{\n"
|
sl@0
|
258 |
append test "\tcatch {unset var}\n"
|
sl@0
|
259 |
append test "\tlist \[catch \{ \n"
|
sl@0
|
260 |
append test "\t\tset match \[$cmd\] \n"
|
sl@0
|
261 |
append test "\t\tlist \$match $vals \n"
|
sl@0
|
262 |
append test "\t\} msg\] \$msg \n"
|
sl@0
|
263 |
append test "\} $result \n"
|
sl@0
|
264 |
return $test
|
sl@0
|
265 |
}
|
sl@0
|
266 |
|