1# Commands covered:  scan
2#
3# This file contains a collection of tests for one or more of the Tcl built-in
4# commands.  Sourcing this file into Tcl runs the tests and generates output
5# for errors.  No output means no errors were found.
6#
7# Copyright © 1991-1994 The Regents of the University of California.
8# Copyright © 1994-1997 Sun Microsystems, Inc.
9# Copyright © 1998-1999 Scriptics Corporation.
10#
11# See the file "license.terms" for information on usage and redistribution
12# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13
14if {"::tcltest" ni [namespace children]} {
15    package require tcltest 2.5
16    namespace import -force ::tcltest::*
17}
18
19# procedure that returns the range of integers
20
21proc int_range {} {
22    set MAX_INT [expr {[format %u -2]/2}]
23    set MIN_INT [expr { ~ $MAX_INT }]
24    return [list $MIN_INT $MAX_INT]
25}
26
27# Big test for correct ordering of data in [expr]
28
29proc testIEEE {} {
30    variable ieeeValues
31    binary scan [binary format dd -1.0 1.0] c* c
32    switch -exact -- $c {
33	{0 0 0 0 0 0 -16 -65 0 0 0 0 0 0 -16 63} {
34	    # little endian
35	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xFF d \
36		ieeeValues(-Infinity)
37	    binary scan \x00\x00\x00\x00\x00\x00\xF0\xBF d \
38		ieeeValues(-Normal)
39	    binary scan \x00\x00\x00\x00\x00\x00\x08\x80 d \
40		ieeeValues(-Subnormal)
41	    binary scan \x00\x00\x00\x00\x00\x00\x00\x80 d \
42		ieeeValues(-0)
43	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
44		ieeeValues(+0)
45	    binary scan \x00\x00\x00\x00\x00\x00\x08\x00 d \
46		ieeeValues(+Subnormal)
47	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x3F d \
48		ieeeValues(+Normal)
49	    binary scan \x00\x00\x00\x00\x00\x00\xF0\x7F d \
50		ieeeValues(+Infinity)
51	    binary scan \x00\x00\x00\x00\x00\x00\xF8\x7F d \
52		ieeeValues(NaN)
53	    set ieeeValues(littleEndian) 1
54	    return 1
55	}
56	{-65 -16 0 0 0 0 0 0 63 -16 0 0 0 0 0 0} {
57	    binary scan \xFF\xF0\x00\x00\x00\x00\x00\x00 d \
58		ieeeValues(-Infinity)
59	    binary scan \xBF\xF0\x00\x00\x00\x00\x00\x00 d \
60		ieeeValues(-Normal)
61	    binary scan \x80\x08\x00\x00\x00\x00\x00\x00 d \
62		ieeeValues(-Subnormal)
63	    binary scan \x80\x00\x00\x00\x00\x00\x00\x00 d \
64		ieeeValues(-0)
65	    binary scan \x00\x00\x00\x00\x00\x00\x00\x00 d \
66		ieeeValues(+0)
67	    binary scan \x00\x08\x00\x00\x00\x00\x00\x00 d \
68		ieeeValues(+Subnormal)
69	    binary scan \x3F\xF0\x00\x00\x00\x00\x00\x00 d \
70		ieeeValues(+Normal)
71	    binary scan \x7F\xF0\x00\x00\x00\x00\x00\x00 d \
72		ieeeValues(+Infinity)
73	    binary scan \x7F\xF8\x00\x00\x00\x00\x00\x00 d \
74		ieeeValues(NaN)
75	    set ieeeValues(littleEndian) 0
76	    return 1
77	}
78	default {
79	    return 0
80	}
81    }
82}
83
84testConstraint ieeeFloatingPoint [testIEEE]
85testConstraint wideIs64bit [expr {wide(0x8000000000000000) < 0}]
86
87test scan-1.1 {BuildCharSet, CharInSet} {
88    list [scan foo {%[^o]} x] $x
89} {1 f}
90test scan-1.2 {BuildCharSet, CharInSet} {
91    list [scan \]foo {%[]f]} x] $x
92} {1 \]f}
93test scan-1.3 {BuildCharSet, CharInSet} {
94    list [scan abc-def {%[a-c]} x] $x
95} {1 abc}
96test scan-1.4 {BuildCharSet, CharInSet} {
97    list [scan abc-def {%[a-c]} x] $x
98} {1 abc}
99test scan-1.5 {BuildCharSet, CharInSet} {
100    list [scan -abc-def {%[-ac]} x] $x
101} {1 -a}
102test scan-1.6 {BuildCharSet, CharInSet} {
103    list [scan -abc-def {%[ac-]} x] $x
104} {1 -a}
105test scan-1.7 {BuildCharSet, CharInSet} {
106    list [scan abc-def {%[c-a]} x] $x
107} {1 abc}
108test scan-1.8 {BuildCharSet, CharInSet} {
109    list [scan def-abc {%[^c-a]} x] $x
110} {1 def-}
111test scan-1.9 {BuildCharSet, CharInSet no match} -setup {
112    unset -nocomplain x
113} -body {
114    list [scan {= f} {= %[TF]} x] [info exists x]
115} -result {0 0}
116
117test scan-2.1 {ReleaseCharSet} {
118    list [scan abcde {%[abc]} x] $x
119} {1 abc}
120test scan-2.2 {ReleaseCharSet} {
121    list [scan abcde {%[a-c]} x] $x
122} {1 abc}
123
124test scan-3.1 {ValidateFormat} -returnCodes error -body {
125    scan {} {%d%1$d} x
126} -result {cannot mix "%" and "%n$" conversion specifiers}
127test scan-3.2 {ValidateFormat} -returnCodes error -body {
128    scan {} {%d%1$d} x
129} -result {cannot mix "%" and "%n$" conversion specifiers}
130test scan-3.3 {ValidateFormat} -returnCodes error -body {
131    scan {} {%2$d%d} x
132} -result {"%n$" argument index out of range}
133test scan-3.4 {ValidateFormat} {
134    # degenerate case, before changed from 8.2 to 8.3
135    list [catch {scan {} %d} msg] $msg
136} {0 {}}
137test scan-3.5 {ValidateFormat} -returnCodes error -body {
138    scan {} {%10c} a
139} -result {field width may not be specified in %c conversion}
140test scan-3.6 {ValidateFormat} -returnCodes error -body {
141    scan {} {%*1$d} a
142} -result {bad scan conversion character "$"}
143test scan-3.7 {ValidateFormat} -returnCodes error -body {
144    scan {} {%1$d%1$d} a
145} -result {variable is assigned by multiple "%n$" conversion specifiers}
146test scan-3.8 {ValidateFormat} -returnCodes error -body {
147    scan {} a x
148} -result {variable is not assigned by any conversion specifiers}
149test scan-3.9 {ValidateFormat} -returnCodes error -body {
150    scan {} {%2$s} x y
151} -result {variable is not assigned by any conversion specifiers}
152test scan-3.10 {ValidateFormat} -returnCodes error -body {
153    scan {} {%[a} x
154} -result {unmatched [ in format string}
155test scan-3.11 {ValidateFormat} -returnCodes error -body {
156    scan {} {%[^a} x
157} -result {unmatched [ in format string}
158test scan-3.12 {ValidateFormat} -returnCodes error -body {
159    scan {} {%[]a} x
160} -result {unmatched [ in format string}
161test scan-3.13 {ValidateFormat} -returnCodes error -body {
162    scan {} {%[^]a} x
163} -result {unmatched [ in format string}
164
165test scan-4.1 {Tcl_ScanObjCmd, argument checks} -returnCodes error -body {
166    scan
167} -result {wrong # args: should be "scan string format ?varName ...?"}
168test scan-4.2 {Tcl_ScanObjCmd, argument checks} -returnCodes error -body {
169    scan string
170} -result {wrong # args: should be "scan string format ?varName ...?"}
171test scan-4.3 {Tcl_ScanObjCmd, argument checks} {
172    # degenerate case, before changed from 8.2 to 8.3
173    list [catch {scan string format} msg] $msg
174} {0 {}}
175test scan-4.4 {Tcl_ScanObjCmd, whitespace} {
176    list [scan {   abc   def   } {%s%s} x y] $x $y
177} {2 abc def}
178test scan-4.5 {Tcl_ScanObjCmd, whitespace} {
179    list [scan {   abc   def   } { %s %s } x y] $x $y
180} {2 abc def}
181test scan-4.6 {Tcl_ScanObjCmd, whitespace} {
182    list [scan {   abc   def   } { %s %s } x y] $x $y
183} {2 abc def}
184test scan-4.7 {Tcl_ScanObjCmd, literals} {
185    # degenerate case, before changed from 8.2 to 8.3
186    scan {   abc   def   } { abc def }
187} {}
188test scan-4.8 {Tcl_ScanObjCmd, literals} {
189    set x {}
190    list [scan {   abcg} { abc def %1s} x] $x
191} {0 {}}
192test scan-4.9 {Tcl_ScanObjCmd, literals} {
193    list [scan {   abc%defghi} { abc %% def%n } x] $x
194} {1 10}
195test scan-4.10 {Tcl_ScanObjCmd, assignment suppression} {
196    list [scan {   abc   def   } { %*c%s def } x] $x
197} {1 bc}
198test scan-4.11 {Tcl_ScanObjCmd, XPG3-style} {
199    list [scan {   abc   def   } {%2$s %1$s} x y] $x $y
200} {2 def abc}
201test scan-4.12 {Tcl_ScanObjCmd, width specifiers} {
202    list [scan {abc123456789012} {%3s%3d%3f%3[0-9]%s} a b c d e] $a $b $c $d $e
203} {5 abc 123 456.0 789 012}
204test scan-4.13 {Tcl_ScanObjCmd, width specifiers} {
205    list [scan {abc123456789012} {%3s%3d%3f%3[0-9]%s} a b c d e] $a $b $c $d $e
206} {5 abc 123 456.0 789 012}
207test scan-4.14 {Tcl_ScanObjCmd, underflow} {
208    set x {}
209    list [scan {a} {a%d} x] $x
210} {-1 {}}
211test scan-4.15 {Tcl_ScanObjCmd, underflow} {
212    set x {}
213    list [scan {} {a%d} x] $x
214} {-1 {}}
215test scan-4.16 {Tcl_ScanObjCmd, underflow} {
216    set x {}
217    list [scan {ab} {a%d} x] $x
218} {0 {}}
219test scan-4.17 {Tcl_ScanObjCmd, underflow} {
220    set x {}
221    list [scan {a   } {a%d} x] $x
222} {-1 {}}
223test scan-4.18 {Tcl_ScanObjCmd, skipping whitespace} {
224    list [scan {  b} {%c%s} x y] $x $y
225} {2 32 b}
226test scan-4.19 {Tcl_ScanObjCmd, skipping whitespace} {
227    list [scan {  b} {%[^b]%s} x y] $x $y
228} {2 {  } b}
229test scan-4.20 {Tcl_ScanObjCmd, string scanning} {
230    list [scan {abc def} {%s} x] $x
231} {1 abc}
232test scan-4.21 {Tcl_ScanObjCmd, string scanning} {
233    list [scan {abc def} {%0s} x] $x
234} {1 abc}
235test scan-4.22 {Tcl_ScanObjCmd, string scanning} {
236    list [scan {abc def} {%2s} x] $x
237} {1 ab}
238test scan-4.23 {Tcl_ScanObjCmd, string scanning} {
239    list [scan {abc def} {%*s%n} x] $x
240} {1 3}
241test scan-4.24 {Tcl_ScanObjCmd, charset scanning} {
242    list [scan {abcdef} {%[a-c]} x] $x
243} {1 abc}
244test scan-4.25 {Tcl_ScanObjCmd, charset scanning} {
245    list [scan {abcdef} {%0[a-c]} x] $x
246} {1 abc}
247test scan-4.26 {Tcl_ScanObjCmd, charset scanning} {
248    list [scan {abcdef} {%2[a-c]} x] $x
249} {1 ab}
250test scan-4.27 {Tcl_ScanObjCmd, charset scanning} {
251    list [scan {abcdef} {%*[a-c]%n} x] $x
252} {1 3}
253test scan-4.28 {Tcl_ScanObjCmd, character scanning} {
254    list [scan {abcdef} {%c} x] $x
255} {1 97}
256test scan-4.29 {Tcl_ScanObjCmd, character scanning} {
257    list [scan {abcdef} {%*c%n} x] $x
258} {1 1}
259
260test scan-4.30 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
261    set x {}
262} -body {
263    list [scan {1234567890a} {%3d} x] $x
264} -result {1 123}
265test scan-4.31 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
266    set x {}
267} -body {
268    list [scan {1234567890a} {%d} x] $x
269} -result {1 1234567890}
270test scan-4.32 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
271    set x {}
272} -body {
273    list [scan {01234567890a} {%d} x] $x
274} -result {1 1234567890}
275test scan-4.33 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
276    set x {}
277} -body {
278    list [scan {+01234} {%d} x] $x
279} -result {1 1234}
280test scan-4.34 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
281    set x {}
282} -body {
283    list [scan {-01234} {%d} x] $x
284} -result {1 -1234}
285test scan-4.35 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
286    set x {}
287} -body {
288    list [scan {a01234} {%d} x] $x
289} -result {0 {}}
290test scan-4.36 {Tcl_ScanObjCmd, base-10 integer scanning} -setup {
291    set x {}
292} -body {
293    list [scan {0x10} {%d} x] $x
294} -result {1 0}
295test scan-4.37 {Tcl_ScanObjCmd, base-8 integer scanning} -setup {
296    set x {}
297} -body {
298    list [scan {012345678} {%o} x] $x
299} -result {1 342391}
300test scan-4.38 {Tcl_ScanObjCmd, base-8 integer scanning} -setup {
301    set x {}
302} -body {
303    list [scan {+1238 -1239 123a} {%o%*s%o%*s%o} x y z] $x $y $z
304} -result {3 83 -83 83}
305test scan-4.39 {Tcl_ScanObjCmd, base-16 integer scanning} -setup {
306    set x {}
307} -body {
308    list [scan {+1238 -123a 0123} {%x%x%x} x y z] $x $y $z
309} -result {3 4664 -4666 291}
310test scan-4.40 {Tcl_ScanObjCmd, base-16 integer scanning} -setup {
311    set x {}
312} -body {
313    # The behavior changed in 8.4a4/8.3.4cvs (6 Feb) to correctly
314    # return '1' for 0x1 scanned via %x, to comply with 8.0 and C scanf.
315    # Bug #495213
316    list [scan {aBcDeF AbCdEf 0x1} {%x%x%x} x y z] $x $y $z
317} -result {3 11259375 11259375 1}
318test scan-4.40.1 {Tcl_ScanObjCmd, base-16 integer scanning} -setup {
319    set x {}
320} -body {
321    list [scan {0xF 0x00A0B 0X0XF} {%x %x %x} x y z] $x $y $z
322} -result {3 15 2571 0}
323test scan-4.40.2 {Tcl_ScanObjCmd, base-16 integer scanning} -setup {
324    unset -nocomplain x
325} -body {
326    list [scan {xF} {%x} x] [info exists x]
327} -result {0 0}
328test scan-4.40.3 {Tcl_ScanObjCmd, base-2 integer scanning} -setup {
329    set x {}
330} -body {
331    list [scan {1001 0b101 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000} {%b %b %llb} x y z] $x $y $z
332} -result {3 9 5 340282366920938463463374607431768211456}
333test scan-4.41 {Tcl_ScanObjCmd, base-unknown integer scanning} -setup {
334    set x {}
335} -body {
336    list [scan {10 010 0x10 0b10} {%i%i%i%i} x y z t] $x $y $z $t
337} -result {4 10 8 16 0}
338test scan-4.42 {Tcl_ScanObjCmd, base-unknown integer scanning} -setup {
339    set x {}
340} -body {
341    list [scan {10 010 0X10} {%i%i%i} x y z] $x $y $z
342} -result {3 10 8 16}
343test scan-4.43 {Tcl_ScanObjCmd, integer scanning, odd cases} -setup {
344    set x {}
345} -body {
346    list [scan {+ } {%i} x] $x
347} -result {0 {}}
348test scan-4.44 {Tcl_ScanObjCmd, integer scanning, odd cases} -setup {
349    set x {}
350} -body {
351    list [scan {+} {%i} x] $x
352} -result {-1 {}}
353test scan-4.45 {Tcl_ScanObjCmd, integer scanning, odd cases} -setup {
354    set x {}
355} -body {
356    list [scan {0x} {%i%s} x y] $x $y
357} -result {2 0 x}
358test scan-4.46 {Tcl_ScanObjCmd, integer scanning, odd cases} -setup {
359    set x {}
360} -body {
361    list [scan {0X} {%i%s} x y] $x $y
362} -result {2 0 X}
363test scan-4.47 {Tcl_ScanObjCmd, integer scanning, suppressed} -setup {
364    set x {}
365} -body {
366    list [scan {123def} {%*i%s} x] $x
367} -result {1 def}
368test scan-4.48 {Tcl_ScanObjCmd, float scanning} {
369    list [scan {1 2 3} {%e %f %g} x y z] $x $y $z
370} {3 1.0 2.0 3.0}
371test scan-4.49 {Tcl_ScanObjCmd, float scanning} {
372    list [scan {.1 0.2 3.} {%e %f %g} x y z] $x $y $z
373} {3 0.1 0.2 3.0}
374test scan-4.49-uc-1 {Tcl_ScanObjCmd, float scanning} {
375    list [scan {0.5*0.75} {%E%c%G} x y z] $x $y $z
376} {3 0.5 42 0.75}
377test scan-4.49-uc-2 {Tcl_ScanObjCmd, float scanning} {
378    list [scan {5e-1*75E-2} {%E%c%G} x y z] $x $y $z
379} {3 0.5 42 0.75}
380test scan-4.50 {Tcl_ScanObjCmd, float scanning} {
381    list [scan {1234567890a} %f x] $x
382} {1 1234567890.0}
383test scan-4.51 {Tcl_ScanObjCmd, float scanning} {
384    list [scan {+123+45} %f x] $x
385} {1 123.0}
386test scan-4.52 {Tcl_ScanObjCmd, float scanning} {
387    list [scan {-123+45} %f x] $x
388} {1 -123.0}
389test scan-4.53 {Tcl_ScanObjCmd, float scanning} {
390    list [scan {1.0e1} %f x] $x
391} {1 10.0}
392test scan-4.54 {Tcl_ScanObjCmd, float scanning} {
393    list [scan {1.0e-1} %f x] $x
394} {1 0.1}
395test scan-4.55 {Tcl_ScanObjCmd, odd cases} -setup {
396    set x {}
397} -body {
398    list [scan {+} %f x] $x
399} -result {-1 {}}
400test scan-4.56 {Tcl_ScanObjCmd, odd cases} -setup {
401    set x {}
402} -body {
403    list [scan {1.0e} %f%s x y] $x $y
404} -result {2 1.0 e}
405test scan-4.57 {Tcl_ScanObjCmd, odd cases} -setup {
406    set x {}
407} -body {
408    list [scan {1.0e+} %f%s x y] $x $y
409} -result {2 1.0 e+}
410test scan-4.58 {Tcl_ScanObjCmd, odd cases} -setup {
411    set x {}
412    set y {}
413} -body {
414    list [scan {e1} %f%s x y] $x $y
415} -result {0 {} {}}
416test scan-4.59 {Tcl_ScanObjCmd, float scanning} {
417    list [scan {1.0e-1x} %*f%n x] $x
418} {1 6}
419
420test scan-4.60 {Tcl_ScanObjCmd, set errors} -setup {
421    set x {}
422    set y {}
423    unset -nocomplain z
424} -body {
425    array set z {}
426    list [catch {scan {abc def ghi} {%s%s%s} x z y} msg] $msg $x $y
427} -cleanup {
428    unset -nocomplain z
429} -result {1 {can't set "z": variable is array} abc ghi}
430test scan-4.61 {Tcl_ScanObjCmd, set errors} -setup {
431    set x {}
432    unset -nocomplain y
433    unset -nocomplain z
434} -body {
435    array set y {}
436    array set z {}
437    list [catch {scan {abc def ghi} {%s%s%s} x z y} msg] $msg $x
438} -cleanup {
439    unset -nocomplain y
440    unset -nocomplain z
441} -result {1 {can't set "z": variable is array} abc}
442
443test scan-4.62 {scanning of large and negative octal integers} {
444    lassign [int_range] MIN_INT MAX_INT
445    set scanstring [format {%o %o %o} -1 $MIN_INT $MAX_INT]
446    list [scan $scanstring {%o %o %o} a b c] \
447	[expr { $a == -1 }] [expr { $b == $MIN_INT }] [expr { $c == $MAX_INT }]
448} {3 1 1 1}
449test scan-4.63 {scanning of large and negative hex integers} {
450    lassign [int_range] MIN_INT MAX_INT
451    set scanstring [format {%x %x %x} -1 $MIN_INT $MAX_INT]
452    list [scan $scanstring {%x %x %x} a b c] \
453	[expr { $a == -1 }] [expr { $b == $MIN_INT }] [expr { $c == $MAX_INT }]
454} {3 1 1 1}
455test scan-4.64 {scanning of hex with %X} {
456    scan "123 abc f78" %X%X%X
457} {291 2748 3960}
458
459test scan-5.1 {integer scanning} -setup {
460    set a {}; set b {}; set c {}; set d {}
461} -body {
462    list [scan "-20 1476 \n33 0" "%d %d %d %d" a b c d] $a $b $c $d
463} -result {4 -20 1476 33 0}
464test scan-5.2 {integer scanning} -setup {
465    set a {}; set b {}; set c {}
466} -body {
467    list [scan "-45 16 7890 +10" "%2d %*d %10d %d" a b c] $a $b $c
468} -result {3 -4 16 7890}
469test scan-5.3 {integer scanning} -setup {
470    set a {}; set b {}; set c {}; set d {}
471} -body {
472    list [scan "-45 16 +10 987" "%ld %d %ld %d" a b c d] $a $b $c $d
473} -result {4 -45 16 10 987}
474test scan-5.4 {integer scanning} -setup {
475    set a {}; set b {}; set c {}; set d {}
476} -body {
477    list [scan "14 1ab 62 10" "%d %x %lo %x" a b c d] $a $b $c $d
478} -result {4 14 427 50 16}
479test scan-5.5 {integer scanning} -setup {
480    set a {}; set b {}; set c {}; set d {}
481} -body {
482    list [scan "12345670 1234567890ab cdefg" "%o	 %o %x %lx" a b c d] \
483	    $a $b $c $d
484} -result {4 2739128 342391 561323 52719}
485test scan-5.6 {integer scanning} -setup {
486    set a {}; set b {}; set c {}; set d {}
487} -body {
488    list [scan "ab123-24642" "%2x %3x %3o %2o" a b c d] $a $b $c $d
489} -result {4 171 291 -20 52}
490test scan-5.7 {integer scanning} -setup {
491    set a {}; set b {}
492} -body {
493    list [scan "1234567 234 567  " "%*3x %x %*o %4o" a b] $a $b
494} -result {2 17767 375}
495test scan-5.8 {integer scanning} -setup {
496    set a {}; set b {}
497} -body {
498    list [scan "a	1234" "%d %d" a b] $a $b
499} -result {0 {} {}}
500test scan-5.9 {integer scanning} -setup {
501    set a {}; set b {}; set c {}; set d {}
502} -body {
503    list [scan "12345678" "%2d %2d %2ld %2d" a b c d] $a $b $c $d
504} -result {4 12 34 56 78}
505test scan-5.10 {integer scanning} -setup {
506    set a {}; set b {}; set c {}; set d {}
507} -body {
508    list [scan "1 2 " "%hd %d %d %d" a b c d] $a $b $c $d
509} -result {2 1 2 {} {}}
510#
511# The behavior for scaning intergers larger than MAX_INT is not defined by the
512# ANSI spec.  Some implementations wrap the input (-16) some return MAX_INT.
513#
514test scan-5.11 {integer scanning} -constraints {nonPortable} -setup {
515    set a {}; set b {}
516} -body {
517    list [scan "4294967280 4294967280" "%u %d" a b] $a \
518	    [expr {$b == -16 || $b == 0x7fffffff}]
519} -result {2 4294967280 1}
520test scan-5.12 {integer scanning} -constraints {wideIs64bit} -setup {
521    set a {}; set b {}; set c {}
522} -body {
523    list [scan "7810179016327718216,6c63546f6c6c6548,661432506755433062510" \
524	    %ld,%lx,%lo a b c] $a $b $c
525} -result {3 7810179016327718216 7810179016327718216 7810179016327718216}
526test scan-5.13 {integer scanning and overflow} {
527    # This test used to fail on some 64-bit systems. [Bug 1011860]
528    scan {300000000 3000000000 30000000000} {%ld %ld %ld}
529} {300000000 3000000000 30000000000}
530
531test scan-5.14 {integer scanning} {
532    scan 0xff %u
533} 0
534test scan-5.15 {Bug be003d570f} {
535    scan 0x40 %o
536} 0
537test scan-5.16 {Bug be003d570f} {
538    scan 0x40 %b
539} 0
540test scan-5.17 {bigint scanning} -setup {
541    set a {}; set b {}; set c {}
542} -body {
543    list [scan "207698809136909011942886895,abcdef0123456789abcdef,125715736004432126361152746757" \
544	    %lld,%llx,%llo a b c] $a $b $c
545} -result {3 207698809136909011942886895 207698809136909011942886895 207698809136909011942886895}
546test scan-5.18 {bigint scanning underflow} -setup {
547    set a {};
548} -body {
549    list [scan "-207698809136909011942886895" \
550	    %llu a] $a
551} -returnCodes 1 -result {unsigned bignum scans are invalid}
552test scan-5.19 {bigint scanning invalid} -setup {
553    set a {};
554} -body {
555    list [scan "207698809136909011942886895" \
556           %llu a] $a
557} -result {1 207698809136909011942886895}
558test scan-5.20 {ignore digit separators} -setup {
559    set a {}; set b {}; set c {};
560} -body {
561    list [scan "10_23_45" %d_%d_%d a b c] $a $b $c
562} -result {3 10 23 45}
563
564test scan-6.1 {floating-point scanning} -setup {
565    set a {}; set b {}; set c {}; set d {}
566} -body {
567    list [scan "2.1 -3.0e8 .99962 a" "%f%g%e%f" a b c d] $a $b $c $d
568} -result {3 2.1 -300000000.0 0.99962 {}}
569test scan-6.2 {floating-point scanning} -setup {
570    set a {}; set b {}; set c {}; set d {}
571} -body {
572    list [scan "-1.2345 +8.2 9" "%3e %3lf %f %f" a b c d] $a $b $c $d
573} -result {4 -1.0 234.0 5.0 8.2}
574test scan-6.3 {floating-point scanning} -setup {
575    set a {}; set b {}; set c {}
576} -body {
577    list [scan "1e00004 332E-4 3e+4" "%Lf %*2e %f %f" a b c] $a $c
578} -result {3 10000.0 30000.0}
579#
580# Some libc implementations consider 3.e- bad input.  The ANSI spec states
581# that digits must follow the - sign.
582#
583test scan-6.4 {floating-point scanning} -setup {
584    set a {}; set b {}; set c {}
585} -body {
586    list [scan "1. 47.6 2.e2 3.e-" "%f %*f %f %f" a b c] $a $b $c
587} -result {3 1.0 200.0 3.0}
588test scan-6.5 {floating-point scanning} -setup {
589    set a {}; set b {}; set c {}; set d {}
590} -body {
591    list [scan "4.6 99999.7 876.43e-1 118" "%f %f %f %e" a b c d] $a $b $c $d
592} -result {4 4.6 99999.7 87.643 118.0}
593test scan-6.6 {floating-point scanning} -setup {
594    set a {}; set b {}; set c {}; set d {}
595} -body {
596    list [scan "1.2345 697.0e-3 124 .00005" "%f %e %f %e" a b c d] $a $b $c $d
597} -result {4 1.2345 0.697 124.0 5e-5}
598test scan-6.7 {floating-point scanning} -setup {
599    set a {}; set b {}; set c {}; set d {}
600} -body {
601    list [scan "4.6abc" "%f %f %f %f" a b c d] $a $b $c $d
602} -result {1 4.6 {} {} {}}
603test scan-6.8 {floating-point scanning} -setup {
604    set a {}; set b {}; set c {}; set d {}
605} -body {
606    list [scan "4.6 5.2" "%f %f %f %f" a b c d] $a $b $c $d
607} -result {2 4.6 5.2 {} {}}
608test scan-6.8 {disallow diget separator in floating-point} -setup {
609    set a {}; set b {}; set c {};
610} -body {
611    list [scan "3.14_2.35_98.6" %f_%f_%f a b c ] $a $b $c
612} -result {3 3.14 2.35 98.6}
613
614test scan-7.1 {string and character scanning} -setup {
615    set a {}; set b {}; set c {}; set d {}
616} -body {
617    list [scan "abc defghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d
618} -result {4 abc def ghijk dum}
619test scan-7.2 {string and character scanning} -setup {
620    set a {}; set b {}; set c {}; set d {}
621} -body {
622    list [scan "a       bcdef" "%c%c%1s %s" a b c d] $a $b $c $d
623} -result {4 97 32 b cdef}
624test scan-7.3 {string and character scanning} -setup {
625    set a {}; set b {}; set c {}
626} -body {
627    list [scan "123456 test " "%*c%*s %s %s %s" a b c] $a $b $c
628} -result {1 test {} {}}
629test scan-7.4 {string and character scanning} -setup {
630    set a {}; set b {}; set c {}; set d {}
631} -body {
632    list [scan "ababcd01234  f 123450" {%4[abcd] %4[abcd] %[^abcdef] %[^0]} a b c d] $a $b $c $d
633} -result {4 abab cd {01234  } {f 12345}}
634test scan-7.5 {string and character scanning} -setup {
635    set a {}; set b {}; set c {}
636} -body {
637    list [scan "aaaaaabc aaabcdefg  + +  XYZQR" {%*4[a] %s %*4[a]%s%*4[ +]%c} a b c] $a $b $c
638} -result {3 aabc bcdefg 43}
639test scan-7.6 {string and character scanning, unicode} -setup {
640    set a {}; set b {}; set c {}; set d {}
641} -body {
642    list [scan "abc dÇfghijk dum " "%s %3s %20s %s" a b c d] $a $b $c $d
643} -result "4 abc dÇf ghijk dum"
644test scan-7.7 {string and character scanning, unicode} -setup {
645    set a {}; set b {}
646} -body {
647    list [scan "abÇcdef" "ab%c%c" a b] $a $b
648} -result "2 199 99"
649test scan-7.8 {string and character scanning, unicode} -setup {
650    set a {}; set b {}
651} -body {
652    list [scan "ab\uFEFFdef" "%\[ab\uFEFF\]" a] $a
653} -result "1 ab\uFEFF"
654
655test scan-8.1 {error conditions} -body {
656    scan a
657} -returnCodes error -match glob -result *
658test scan-8.2 {error conditions} -returnCodes error -body {
659    scan a
660} -result {wrong # args: should be "scan string format ?varName ...?"}
661test scan-8.3 {error conditions} -returnCodes error -body {
662    scan a %D x
663} -result {bad scan conversion character "D"}
664test scan-8.4 {error conditions} -returnCodes error -body {
665    scan a %O x
666} -result {bad scan conversion character "O"}
667test scan-8.5 {error conditions} -returnCodes error -body {
668    scan a %B x
669} -result {bad scan conversion character "B"}
670test scan-8.6 {error conditions} -returnCodes error -body {
671    scan a %F x
672} -result {bad scan conversion character "F"}
673test scan-8.7 {error conditions} -returnCodes error -body {
674    scan a %p x
675} -result {bad scan conversion character "p"}
676test scan-8.8 {error conditions} -returnCodes error -body {
677    scan a "%d %d" a
678} -result {different numbers of variable names and field specifiers}
679test scan-8.9 {error conditions} -returnCodes error -body {
680    scan a "%d %d" a b c
681} -result {variable is not assigned by any conversion specifiers}
682test scan-8.10 {error conditions} -setup {
683    set a {}; set b {}; set c {}; set d {}
684} -body {
685    list [expr {[scan "  a" " a %d %d %d %d" a b c d] <= 0}] $a $b $c $d
686} -result {1 {} {} {} {}}
687test scan-8.11 {error conditions} -setup {
688    set a {}; set b {}; set c {}; set d {}
689} -body {
690    list [scan "1 2" "%d %d %d %d" a b c d] $a $b $c $d
691} -result {2 1 2 {} {}}
692test scan-8.12 {error conditions} -setup {
693    unset -nocomplain a
694} -body {
695    set a(0) 44
696    scan 44 %d a
697} -returnCodes error -cleanup {
698    unset -nocomplain a
699} -result {can't set "a": variable is array}
700test scan-8.13 {error conditions} -setup {
701    unset -nocomplain a
702} -body {
703    set a(0) 44
704    scan 44 %c a
705} -returnCodes error -cleanup {
706    unset -nocomplain a
707} -result {can't set "a": variable is array}
708test scan-8.14 {error conditions} -setup {
709    unset -nocomplain a
710} -body {
711    set a(0) 44
712    scan 44 %s a
713} -returnCodes error -cleanup {
714    unset -nocomplain a
715} -result {can't set "a": variable is array}
716test scan-8.15 {error conditions} -setup {
717    unset -nocomplain a
718} -body {
719    set a(0) 44
720    scan 44 %f a
721} -returnCodes error -cleanup {
722    unset -nocomplain a
723} -result {can't set "a": variable is array}
724test scan-8.16 {error conditions} -setup {
725    unset -nocomplain a
726} -body {
727    set a(0) 44
728    scan 44 %f a
729} -returnCodes error -cleanup {
730    unset -nocomplain a
731} -result {can't set "a": variable is array}
732test scan-8.17 {error conditions} -returnCodes error -body {
733    scan 44 %2c a
734} -result {field width may not be specified in %c conversion}
735test scan-8.18 {error conditions} -returnCodes error -body {
736    scan abc {%[} x
737} -result {unmatched [ in format string}
738test scan-8.19 {error conditions} -returnCodes error -body {
739    scan abc {%[^a} x
740} -result {unmatched [ in format string}
741test scan-8.20 {error conditions} -returnCodes error -body {
742    scan abc {%[^]a} x
743} -result {unmatched [ in format string}
744test scan-8.21 {error conditions} -returnCodes error -body {
745    scan abc {%[]a} x
746} -result {unmatched [ in format string}
747
748test scan-9.1 {lots of arguments} {
749    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20
750} 20
751test scan-9.2 {lots of arguments} {
752    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20
753    set a20
754} 200
755
756test scan-10.1 {miscellaneous tests} -setup {
757    set a {}
758} -body {
759    list [scan ab16c ab%dc a] $a
760} -result {1 16}
761test scan-10.2 {miscellaneous tests} -setup {
762    set a {}
763} -body {
764    list [scan ax16c ab%dc a] $a
765} -result {0 {}}
766test scan-10.3 {miscellaneous tests} -setup {
767    set a {}
768} -body {
769    list [catch {scan ab%c114 ab%%c%d a} msg] $msg $a
770} -result {0 1 114}
771test scan-10.4 {miscellaneous tests} -setup {
772    set a {}
773} -body {
774    list [catch {scan ab%c14 ab%%c%d a} msg] $msg $a
775} -result {0 1 14}
776test scan-10.5 {miscellaneous tests} -setup {
777    unset -nocomplain arr
778} -body {
779    set arr(2) {}
780    list [catch {scan ab%c14 ab%%c%d arr(2)} msg] $msg $arr(2)
781} -result {0 1 14}
782test scan-10.6 {miscellaneous tests} {
783    scan 5a {%i%[a]}
784} {5 a}
785test scan-10.7 {miscellaneous tests} {
786    scan {5 a} {%i%[a]}
787} {5 {}}
788
789test scan-11.1 {alignment in results array (TCL_ALIGN)} {
790    scan "123 13.6" "%s %f" a b
791    set b
792} 13.6
793test scan-11.2 {alignment in results array (TCL_ALIGN)} {
794    scan "1234567 13.6" "%s %f" a b
795    set b
796} 13.6
797test scan-11.3 {alignment in results array (TCL_ALIGN)} {
798    scan "12345678901 13.6" "%s %f" a b
799    set b
800} 13.6
801test scan-11.4 {alignment in results array (TCL_ALIGN)} {
802    scan "123456789012345 13.6" "%s %f" a b
803    set b
804} 13.6
805test scan-11.5 {alignment in results array (TCL_ALIGN)} {
806    scan "1234567890123456789 13.6" "%s %f" a b
807    set b
808} 13.6
809
810test scan-12.1 {Tcl_ScanObjCmd, inline case} {
811    scan a %c
812} 97
813test scan-12.2 {Tcl_ScanObjCmd, inline case} {
814    scan abc %c%c%c%c
815} {97 98 99 {}}
816test scan-12.3 {Tcl_ScanObjCmd, inline case} {
817    scan abc %s%c
818} {abc {}}
819test scan-12.4 {Tcl_ScanObjCmd, inline case, underflow} {
820    scan abc abc%c
821} {}
822test scan-12.5 {Tcl_ScanObjCmd, inline case} {
823    scan abc bogus%c%c%c
824} {{} {} {}}
825test scan-12.6 {Tcl_ScanObjCmd, inline case} {
826    # degenerate case, behavior changed from 8.2 to 8.3
827    list [catch {scan foo foobar} msg] $msg
828} {0 {}}
829test scan-12.7 {Tcl_ScanObjCmd, inline case lots of arguments} {
830    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140\
831	    150 160 170 180 190 200" \
832	    "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d"
833} {10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 {}}
834
835test scan-13.1 {Tcl_ScanObjCmd, inline XPG case} {
836    scan a {%1$c}
837} 97
838test scan-13.2 {Tcl_ScanObjCmd, inline XPG case} {
839    scan abc {%1$c%2$c%3$c%4$c}
840} {97 98 99 {}}
841test scan-13.3 {Tcl_ScanObjCmd, inline XPG case} -returnCodes error -body {
842    scan abc {%1$c%1$c}
843} -result {variable is assigned by multiple "%n$" conversion specifiers}
844test scan-13.4 {Tcl_ScanObjCmd, inline XPG case} {
845    scan abc {%2$s%1$c}
846} {{} abc}
847test scan-13.5 {Tcl_ScanObjCmd, inline XPG case, underflow} {
848    scan abc {abc%5$c}
849} {}
850test scan-13.6 {Tcl_ScanObjCmd, inline XPG case} {
851    catch {scan abc {bogus%1$c%5$c%10$c}} msg
852    list [llength $msg] $msg
853} {10 {{} {} {} {} {} {} {} {} {} {}}}
854test scan-13.7 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
855    scan "10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200" {%20$d %18$d %17$d %16$d %15$d %14$d %13$d %12$d %11$d %10$d %9$d %8$d %7$d %6$d %5$d %4$d %3$d %2$d %1$d}
856} {190 180 170 160 150 140 130 120 110 100 90 80 70 60 50 40 30 20 {} 10}
857test scan-13.8 {Tcl_ScanObjCmd, inline XPG case lots of arguments} {
858    set msg [scan "10 20 30" {%100$d %5$d %200$d}]
859    list [llength $msg] [lindex $msg 99] [lindex $msg 4] [lindex $msg 199]
860} {200 10 20 30}
861
862# scan infinities - not working
863
864test scan-14.1 {positive infinity} {
865    scan Inf %g d
866    return $d
867} Inf
868test scan-14.2 {negative infinity} {
869    scan -Inf %g d
870    return $d
871} -Inf
872
873# TODO - also need to scan NaN's
874
875catch {rename int_range {}}
876
877# cleanup
878::tcltest::cleanupTests
879return
880
881# Local Variables:
882# mode: tcl
883# End:
884