Check-in [e61e828788]
Not logged in
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2018 Conference, Houston/TX, US, Oct 15-19
Send your abstracts to tclconference@googlegroups.com or submit via the online form
by Aug 20.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Completing the migration to jimtcl compadible code for codebale/cthluhu/fileutil Alter the search path rules for find-tclsh to prefer a native 8.6 to jimtcl
Timelines: family | ancestors | descendants | both | autosetup
Files: files | file ages | folders
SHA1: e61e828788a3a209d8262ff23b759f517bee77eb
User & Date: hypnotoad 2015-03-13 12:02:38
Context
2015-03-13
12:19
Adding fossil branches to build specs Added a "domake" to hijack make calls check-in: 556b736457 user: hypnotoad tags: autosetup
12:02
Completing the migration to jimtcl compadible code for codebale/cthluhu/fileutil Alter the search path rules for find-tclsh to prefer a native 8.6 to jimtcl check-in: e61e828788 user: hypnotoad tags: autosetup
11:59
Fix handling of the 64bit flag check-in: d461db3e3d user: hypnotoad tags: autosetup
Changes
Unified Diff Ignore Whitespace Patch
Changes to autosetup/find-tclsh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
# Looks for a suitable tclsh or jimsh in the PATH
# If not found, builds a bootstrap jimsh from source
d=`dirname "$0"`
{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
PATH="$PATH:$d"; export PATH
for tclsh in jimsh tclsh tclsh8.5 tclsh8.6; do
	{ $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
	{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
	"$d/jimsh0" "$d/test-tclsh" && exit 0
done





|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/sh
# Looks for a suitable tclsh or jimsh in the PATH
# If not found, builds a bootstrap jimsh from source
d=`dirname "$0"`
{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0
PATH="$PATH:$d/../../../bin:$d"; export PATH
for tclsh in tclsh8.6 tclsh86.exe  tclsh8.5 tclsh85.exe tclsh tclsh.exe jimsh  ; do
	{ $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0
done
echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0"
for cc in ${CC_FOR_BUILD:-cc} gcc; do
	{ $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue
	"$d/jimsh0" "$d/test-tclsh" && exit 0
done
Changes to autosetup/lib/codebale.tcl.
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

set col 0
use fileutil

###
# topic: e1d75c45e58cc525a0a70ce6f767717c
###
proc codebale__isdirectory name {
  return [file isdirectory $name]
}

###
# topic: d0663852b31759ce78f33cbc63379d84
###
proc codebale__istcl name {
  return [string match *.tcl $name]
}

###
# topic: ea4ac0a84ae990dafee965b995f48e63
###
proc codebale__istm name {
  return [string match *.tm $name]
}

###
# topic: ec0fd469c986351ea0d5a287d6f040d8
###
proc codebale_cases_finalize f {







|






|






|







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

set col 0
use fileutil

###
# topic: e1d75c45e58cc525a0a70ce6f767717c
###
proc codebale_isdirectory name {
  return [file isdirectory $name]
}

###
# topic: d0663852b31759ce78f33cbc63379d84
###
proc codebale_istcl name {
  return [string match *.tcl $name]
}

###
# topic: ea4ac0a84ae990dafee965b995f48e63
###
proc codebale_istm name {
  return [string match *.tm $name]
}

###
# topic: ec0fd469c986351ea0d5a287d6f040d8
###
proc codebale_cases_finalize f {
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
###
proc codebale_pkgindex_manifest base {
  set stack {}
  set output {}
  set base [file-normalize $base]
  set i    [string length  $base]

  foreach {file} [fileutil_find $base _istm] {
    set file [file-normalize $file]
    set fname [file rootname [file tail $file]]
    ###
    # Assume the package is correct in the filename
    ###
    set package [lindex [split $fname -] 0]
    set version [lindex [split $fname -] 1]







|







286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
###
proc codebale_pkgindex_manifest base {
  set stack {}
  set output {}
  set base [file-normalize $base]
  set i    [string length  $base]

  foreach {file} [fileutil_find $base codebale_istm] {
    set file [file-normalize $file]
    set fname [file rootname [file tail $file]]
    ###
    # Assume the package is correct in the filename
    ###
    set package [lindex [split $fname -] 0]
    set version [lindex [split $fname -] 1]
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
      if { [string range $line 0 9] != "# Package " } continue
      set package [lindex $line 2]
      set version [lindex $line 3]
      break
    }
    lappend output $package $version
  }
  foreach {file} [fileutil_find $base _istcl] {
    set file [file-normalize $file]
    set fin [open $file r]
    set dat [read $fin]
    close $fin
    if {![regexp "package provide" $dat]} continue
    set fname [file rootname [file tail $file]]
    set dir [string trimleft [string range [file dirname $file] $i end] /]







|







310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
      if { [string range $line 0 9] != "# Package " } continue
      set package [lindex $line 2]
      set version [lindex $line 3]
      break
    }
    lappend output $package $version
  }
  foreach {file} [fileutil_find $base codebale_istcl] {
    set file [file-normalize $file]
    set fin [open $file r]
    set dat [read $fin]
    close $fin
    if {![regexp "package provide" $dat]} continue
    set fname [file rootname [file tail $file]]
    set dir [string trimleft [string range [file dirname $file] $i end] /]
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  set stack {}
  set buffer {
lappend ::PATHSTACK $dir
  }
  set base [file-normalize $base]
  set i    [string length  $base]
  # Build a list of all of the paths
  set paths [fileutil_find $base _isdirectory]
  
  foreach path $paths {
    if {$path eq $base} continue
    set path_indexed($path) 0
    foreach idxname {pkgIndex.tcl} {
      if {[file exists [file join $path $idxname]]} {
        incr path_indexed($path)







|







342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  set stack {}
  set buffer {
lappend ::PATHSTACK $dir
  }
  set base [file-normalize $base]
  set i    [string length  $base]
  # Build a list of all of the paths
  set paths [fileutil_find $base codebale_isdirectory]
  
  foreach path $paths {
    if {$path eq $base} continue
    set path_indexed($path) 0
    foreach idxname {pkgIndex.tcl} {
      if {[file exists [file join $path $idxname]]} {
        incr path_indexed($path)
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
    if {[file exists $hfile] && [file mtime $hfile]>[file mtime $cfile]} continue
    set f [open $hfile w]
    fconfigure $f -translation crlf
    puts $f "/*** Automatically Generated Header File - Do Not Edit ***/"
    puts $f "  const static char *${prefix}_strs\[\] = \173"
    set lx [lsort  $cases($prefix)]
    foreach item $lx {
      detect_cases_put_item $f \"[string tolower $item]\",
    }
    detect_cases_put_item $f 0
    detect_cases_finalize $f
    puts $f "  \175;"
    puts $f "  enum ${prefix}_enum \173"
    foreach name $lx {
      regsub -all {@} $name {} name
      detect_cases_put_item $f ${prefix}_[string toupper $name],
    }
    detect_cases_finalize $f
    puts $f "  \175;"
    puts $f "\
  int index;
  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, \"METHOD ?ARG ...?\");
    return TCL_ERROR;
  }







|

|
|




|

|







705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
    if {[file exists $hfile] && [file mtime $hfile]>[file mtime $cfile]} continue
    set f [open $hfile w]
    fconfigure $f -translation crlf
    puts $f "/*** Automatically Generated Header File - Do Not Edit ***/"
    puts $f "  const static char *${prefix}_strs\[\] = \173"
    set lx [lsort  $cases($prefix)]
    foreach item $lx {
      codebale_detect_cases_put_item $f \"[string tolower $item]\",
    }
    codebale_detect_cases_put_item $f 0
    codebale_detect_cases_finalize $f
    puts $f "  \175;"
    puts $f "  enum ${prefix}_enum \173"
    foreach name $lx {
      regsub -all {@} $name {} name
      codebale_detect_cases_put_item $f ${prefix}_[string toupper $name],
    }
    codebale_detect_cases_finalize $f
    puts $f "  \175;"
    puts $f "\
  int index;
  if( objc<2 ){
    Tcl_WrongNumArgs(interp, 1, objv, \"METHOD ?ARG ...?\");
    return TCL_ERROR;
  }
Changes to autosetup/lib/cthulhu.tcl.
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  }
  ###
  # Build a list of all public header files that
  # need to be amalgamated into the publicly exported
  # version
  ###
  foreach file [lsort  [glob -nocomplain [file join $here *.h]]] {
    include_directory $here
    set fname [file tail $file]
    if {${cthulhu-ignore-hfiles} eq "*"} continue
    if { $fname in ${cthulhu-ignore-hfiles} } continue
    if {[string match *_cases.h $fname]} continue
    add_cheader $file
  }
  foreach file [lsort  [glob -nocomplain [file join $here *.c]]] {
    if {[file tail $file] in ${build-ignore-cfiles} } continue
    add_csource $file
  }
}

proc cthulhu_include_directory {here} {
   if { $here ni $::project(include_paths) } {
      lappend ::project(include_paths) $here
    }







|




|



|







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  }
  ###
  # Build a list of all public header files that
  # need to be amalgamated into the publicly exported
  # version
  ###
  foreach file [lsort  [glob -nocomplain [file join $here *.h]]] {
    cthulhu_include_directory $here
    set fname [file tail $file]
    if {${cthulhu-ignore-hfiles} eq "*"} continue
    if { $fname in ${cthulhu-ignore-hfiles} } continue
    if {[string match *_cases.h $fname]} continue
    cthulhu_add_cheader $file
  }
  foreach file [lsort  [glob -nocomplain [file join $here *.c]]] {
    if {[file tail $file] in ${build-ignore-cfiles} } continue
    cthulhu_add_csource $file
  }
}

proc cthulhu_include_directory {here} {
   if { $here ni $::project(include_paths) } {
      lappend ::project(include_paths) $here
    }
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517




518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
          break
        }
      }
    }
  }
}

proc cthulhu__find_mkhdr {} {
  set exename [lindex [find-an-executable mkhdr] 0]
  if {$exename ne {}} {
    return [list exec [::realpath $exename]]
  }
  if {[info exists ::odie(mkhdr)]} {
    if {[file exists [::realpath $::odie(mkhdr)]]} {
      return [list exec [::realpath $::odie(mkhdr)]]
    } 
  }




  error {mkhdr not available}
}


proc cthulhu_mkhdr args {
  set cmd [_find_mkhdr]
  {*}${cmd} {*}$args
}

array set ::project {
  include_paths {}
  sources {}
  tcl_sources {}
  modules {}
}









|









>
>
>
>





|











501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
          break
        }
      }
    }
  }
}

proc cthulhu_find_mkhdr {} {
  set exename [lindex [find-an-executable mkhdr] 0]
  if {$exename ne {}} {
    return [list exec [::realpath $exename]]
  }
  if {[info exists ::odie(mkhdr)]} {
    if {[file exists [::realpath $::odie(mkhdr)]]} {
      return [list exec [::realpath $::odie(mkhdr)]]
    } 
  }
  doexec $::odie(cc) -o mkhdr.o -c $::odie(odie_src_dir)/scripts/mkhdr.c
  doexec $::odie(cc) mkhdr.o -o mkhdr$::odie(exe_suffix)
  file copy -force mkhdr$::odie(exe_suffix) [::realpath $::odie(mkhdr)]
  return [list exec [::realpath $::odie(mkhdr)]]
  error {mkhdr not available}
}


proc cthulhu_mkhdr args {
  set cmd [cthulhu_find_mkhdr]
  {*}${cmd} {*}$args
}

array set ::project {
  include_paths {}
  sources {}
  tcl_sources {}
  modules {}
}


Changes to autosetup/lib/fileutil.tcl.
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    set result {}
    set filt   [string length $filtercmd]

    if {[file isfile $basedir]} {
	# The base is a file, and therefore only possible result,
	# modulo filtering.

	FADD $basedir

    } elseif {[file isdirectory $basedir]} {

	# For a directory as base we do an iterative recursion through
	# the directory hierarchy starting at the base. We use a queue
	# (Tcl list) of directories we have to check. We access it by
	# index, and stop when we have reached beyond the end of the







|







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    set result {}
    set filt   [string length $filtercmd]

    if {[file isfile $basedir]} {
	# The base is a file, and therefore only possible result,
	# modulo filtering.

	fileutil_FADD $basedir

    } elseif {[file isdirectory $basedir]} {

	# For a directory as base we do an iterative recursion through
	# the directory hierarchy starting at the base. We use a queue
	# (Tcl list) of directories we have to check. We access it by
	# index, and stop when we have reached beyond the end of the
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

	while {$at < [llength $pending]} {
	    # Get next directory not yet processed.
	    set current [lindex $pending $at]
	    incr at

	    # Is the directory accessible? Continue if not.
	    ACCESS $current

	    # Files first, then the sub-directories ...

	    foreach f [GLOBF $current] { FADD $f }

	    foreach f [GLOBD $current] {
		# Ignore current and parent directory, this needs
		# explicit filtering outside of the filter command.
		if {
		    [string equal [file tail $f]  "."] ||
		    [string equal [file tail $f] ".."]
		} continue

		# Extend result, modulo filtering.
		FADD $f

		# Detection of symlink loops via a portable path
		# normalization computing a canonical form of the path
		# followed by a check if that canonical form was
		# encountered before. If ok, record directory for
		# expansion in future iterations.








|



|

|








|







115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

	while {$at < [llength $pending]} {
	    # Get next directory not yet processed.
	    set current [lindex $pending $at]
	    incr at

	    # Is the directory accessible? Continue if not.
	    fileutil_ACCESS $current

	    # Files first, then the sub-directories ...

	    foreach f [fileutil_GLOBF $current] { fileutil_FADD $f }

	    foreach f [fileutil_GLOBD $current] {
		# Ignore current and parent directory, this needs
		# explicit filtering outside of the filter command.
		if {
		    [string equal [file tail $f]  "."] ||
		    [string equal [file tail $f] ".."]
		} continue

		# Extend result, modulo filtering.
		fileutil_FADD $f

		# Detection of symlink loops via a portable path
		# normalization computing a canonical form of the path
		# followed by a check if that canonical form was
		# encountered before. If ok, record directory for
		# expansion in future iterations.

507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
	# Normalized jail. Fully resolved sym links, if any. Our main
	# complication is that normalize does not resolve symlinks in the
	# last component of the path given to it, so we add a bogus
	# component, resolve, and then strip it off again. That is why the
	# code is so large and long.

	set njail [eval [list file join] [lrange [file split \
		[Normalize [file join $jail __dummy__]]] 0 end-1]]

	# Normalize filename. Fully resolved sym links, if
	# any. S.a. for an explanation of the complication.

	set nfile [eval [list file join] [lrange [file split \
		[Normalize [file join $filename __dummy__]]] 0 end-1]]

	if {[string match ${njail}* $nfile]} {
	    return $filename
	}

	# Outside the jail, put it inside. ... We normalize the input
	# path lexically for this, to prevent escapes still lurking in
	# the original path. (We cannot use the normalized path,
	# symlinks may have bent it out of shape in unrecognizable ways.

	return [eval [linsert [lrange [file split \
		[lexnormalize $filename]] 1 end] 0 file join [pwd] $jail]]
    } else {
	# The path is relative, consider it as outside
	# implicitly. Normalize it lexically! to prevent escapes, then
	# put the jail in front, use PWD to ensure absoluteness.

	return [eval [linsert [file split [lexnormalize $filename]] 0 \
		file join [pwd] $jail]]
    }
}


# ::fileutil_test --
#







|





|











|





|







507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
	# Normalized jail. Fully resolved sym links, if any. Our main
	# complication is that normalize does not resolve symlinks in the
	# last component of the path given to it, so we add a bogus
	# component, resolve, and then strip it off again. That is why the
	# code is so large and long.

	set njail [eval [list file join] [lrange [file split \
		[fileutil_Normalize [file join $jail __dummy__]]] 0 end-1]]

	# Normalize filename. Fully resolved sym links, if
	# any. S.a. for an explanation of the complication.

	set nfile [eval [list file join] [lrange [file split \
		[fileutil_Normalize [file join $filename __dummy__]]] 0 end-1]]

	if {[string match ${njail}* $nfile]} {
	    return $filename
	}

	# Outside the jail, put it inside. ... We normalize the input
	# path lexically for this, to prevent escapes still lurking in
	# the original path. (We cannot use the normalized path,
	# symlinks may have bent it out of shape in unrecognizable ways.

	return [eval [linsert [lrange [file split \
		[fileutil_lexnormalize $filename]] 1 end] 0 file join [pwd] $jail]]
    } else {
	# The path is relative, consider it as outside
	# implicitly. Normalize it lexically! to prevent escapes, then
	# put the jail in front, use PWD to ensure absoluteness.

	return [eval [linsert [file split [fileutil_lexnormalize $filename]] 0 \
		file join [pwd] $jail]]
    }
}


# ::fileutil_test --
#
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
# Arguments:
#   prefix     - a prefix for the filename, p
# Results:
#   returns a file name
#

proc fileutil_tempfile {{prefix {}}} {
    return [Normalize [TempFile $prefix]]
}

proc fileutil_TempFile {prefix} {
    set tmpdir [tempdir]

    set chars       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    set nrand_chars 10







|







1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
# Arguments:
#   prefix     - a prefix for the filename, p
# Results:
#   returns a file name
#

proc fileutil_tempfile {{prefix {}}} {
    return [fileutil_Normalize [TempFile $prefix]]
}

proc fileutil_TempFile {prefix} {
    set tmpdir [tempdir]

    set chars       "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
    set nrand_chars 10
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
    # Ensure that the link to directory 'dst' is properly done relative to
    # the directory 'base'.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
	return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [lexnormalize [file join [pwd] $base]]
    set dst  [lexnormalize [file join [pwd] $dst]]

    set save $dst
    set base [file split $base]
    set dst  [file split $dst]

    while {[string equal [lindex $dst 0] [lindex $base 0]]} {
	set dst  [lrange $dst  1 end]







|
|







1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
    # Ensure that the link to directory 'dst' is properly done relative to
    # the directory 'base'.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
	return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [fileutil_lexnormalize [file join [pwd] $base]]
    set dst  [fileutil_lexnormalize [file join [pwd] $dst]]

    set save $dst
    set base [file split $base]
    set dst  [file split $dst]

    while {[string equal [lindex $dst 0] [lindex $base 0]]} {
	set dst  [lrange $dst  1 end]
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
    # Like 'relative', but for links from _inside_ a file to a
    # different file.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
	return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [lexnormalize [file join [pwd] $base]]
    set dst  [lexnormalize [file join [pwd] $dst]]

    set basedir [file dirname $base]
    set dstdir  [file dirname $dst]

    set dstdir  [relative $basedir $dstdir]

    # dstdir == '.' on input => dstdir output has trailing './'. Strip







|
|







1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
    # Like 'relative', but for links from _inside_ a file to a
    # different file.

    if {![string equal [file pathtype $base] [file pathtype $dst]]} {
	return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)"
    }

    set base [fileutil_lexnormalize [file join [pwd] $base]]
    set dst  [fileutil_lexnormalize [file join [pwd] $dst]]

    set basedir [file dirname $base]
    set dstdir  [file dirname $dst]

    set dstdir  [relative $basedir $dstdir]

    # dstdir == '.' on input => dstdir output has trailing './'. Strip
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027


















































    # around a bug in the path handling on windows which can break the
    # core 'file-normalize' for symbolic links. This was exposed by
    # the find testsuite which could not reproduced outside. I believe
    # that there is some deep path bug in the core triggered under
    # special circumstances. Use of / likely forces a refresh through
    # the string rep and so avoids the problem with the path intrep.

    return [file dirname [Normalize $path/__dummy__]]
    #return [file dirname [Normalize [file join $path __dummy__]]]
}

























































|
|

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
    # around a bug in the path handling on windows which can break the
    # core 'file-normalize' for symbolic links. This was exposed by
    # the find testsuite which could not reproduced outside. I believe
    # that there is some deep path bug in the core triggered under
    # special circumstances. Use of / likely forces a refresh through
    # the string rep and so avoids the problem with the path intrep.

    return [file dirname [fileutil_Normalize $path/__dummy__]]
    #return [file dirname [fileutil_Normalize [file join $path __dummy__]]]
}

set tclver [package present Tcl]
if {$tclver ne {} && [package vsatisfies [package present Tcl] 8.5]} {
    # Tcl 8.5+.
    # We have to check readability of "current" on our own, glob
    # changed to error out instead of returning nothing.

    proc fileutil_ACCESS {args} {}

    proc fileutil_GLOBF {current} {
	if {![file readable $current]} {
	    return {}
	}
	if {([file type $current] eq "link") &&
	    !([file exists   [file readlink $current]] &&
	      [file readable [file readlink $current]])} {
	    return {}
	}

	set res [lsort -unique [concat \
		     [glob -nocomplain -directory $current -types f          -- *] \
		     [glob -nocomplain -directory $current -types {hidden f} -- *]]]

	# Look for broken links (They are reported as neither file nor directory).
	foreach l [lsort -unique [concat \
		       [glob -nocomplain -directory $current -types l          -- *] \
		       [glob -nocomplain -directory $current -types {hidden l} -- *]]] {
	    if {[file isfile      $l]} continue
	    if {[file isdirectory $l]} continue
	    lappend res $l
	}
	return [lsort -unique $res]
    }

    proc fileutil_GLOBD {current} {
	if {![file readable $current]} {
	    return {}
	}
	if {([file type $current] eq "link") &&
	    !([file exists   [file readlink $current]] &&
	      [file readable [file readlink $current]])} {
	    return {}
	}

	lsort -unique [concat \
	    [glob -nocomplain -directory $current -types d          -- *] \
	    [glob -nocomplain -directory $current -types {hidden d} -- *]]
    }

}