tclvfs000075500000000000000000000000001447560765400116765ustar00nobodynobodytclvfs/.fossil-settings000075500000000000000000000000001447560765400151115ustar00nobodynobodytclvfs/.fossil-settings/crlf-glob000064400000000000000000000000111447560765400167520ustar00nobodynobodywin/*.vc tclvfs/.fossil-settings/ignore-glob000064400000000000000000000001521447560765400173150ustar00nobodynobodywin/Debug* win/Release* win/version*.vc win/nmakehlp.exe win/nmakehlp.obj win/nmakehlp.out win/_junk.pch tclvfs/ChangeLog000064400000000000000000001362251447560765400135400ustar00nobodynobody2012-12-12 Andreas Kupries * library/template/collatevfs.tcl: Added missing provide command. * library/template/templatevfs.tcl: Fixed missing default status 0 in * pkgIndex.tcl.in: overriden exit command. Bumped to 1.5.5 * pkgIndex.tcl.in: Added the various template filesystems to the index. * pkgIndex.tcl.in: Long overdue bump of vfs::zip to * library/zipvfs.tcl: 1.0.4. (Since 2009-02-07 or earlier). * configure.in: Long overdue bump to version 1.4.2. * configure: (1.4.1 was in 2009-02-07). Regenerated. Please bump the patchlevel for any future bug fixes, of the relevant sub-package(s). 2012-07-12 Wojciech Kocjan * zipvfs.tcl: Fix for Tcl 8.6 not properly streaming large files with very big compression ratio, bug 3542959 2012-07-04 Wojciech Kocjan * zipvfs.tcl: Fix for streaming not working properly in certain zip files; refactoring of zip::Data to reuse header parsing code for streams 2012-03-15 Wojciech Kocjan * zipvfs.tcl: Fix for zip symlinks not supported anymore, bug 3505283 2011-11-28 Steve Huntley * vfslib.tcl: Applied contributed patch for bug 3412801. Clean up watch timers for memchan vfs. 2011-11-28 Steve Huntley * zipvfs.tcl: Applied contributed patch for bug 3395782. Enables extraction of contents of zip files created using Fossil. 2011-11-28 Steve Huntley * zipvfs.tcl: Reverted bug fix for 3224057. See bug ID 3303287. 2011-04-28 Steve Huntley * zipvfs.tcl: Added contributed patch to speed up zipvfs directory listing. See patch 3279418. 2011-03-30 Steve Huntley * vfslib.tcl, zipvfs.tcl: Added contributed patches to fix bugs 3160686 & 3224057. 2011-03-30 Steve Huntley * globfind.tcl: Updated to latest file version (1.5.3). 2010-12-31 Steve Huntley * vfs.tcl: Removed requirement for 8.6 for sourcing of vfslib.tcl, since that file contains 8.5-relevant utils for chan command. Vfslib.tcl includes adequate conditional checks for version-dependent commands. 2010-12-30 Steve Huntley * library/zipvfs.tcl: Wojciech Kocjan contributed tweaks to my latest "Frankenstein" patch, which I incorporated. 2010-12-30 Steve Huntley * pkgIndex.tcl.in, vfs.tcl: Switched "package require Tcl 8.4" statement to vfs.tcl to conform with accepted practice. 2010-12-30 Steve Huntley * library/zipvfs.tcl: Applied patch 3005441 to fix issue with UTF-8 detection for filename encoding. Applied patch 3132957 to enable streaming of large files. 2010-12-29 Steve Huntley * generic/vfs.c: include sys/stat.h so build under MinGW64 will succeed. See bug #3107382. * library/zipvfs.tcl: Fixed issues with clock handling, dealing with trying to [open] a directory, reading a zip file that has been appended to another file. See bugs 3103687, 3107380 2010-05-16 Steve Huntley * library/vfslib.tcl: Changed memchan condition from Tcl version 8.6 or greater to presence of chan command (since chan now in later 8.5 builds) 2010-02-01 Steve Huntley * Makefile.in (PKG_TCL_SOURCES): Added 'template/tclIndex' to the list of installed files. Required for vfs's based on template vfs to load. 2010-01-30 Steve Huntley * templatevfs.tcl: workaround for bug in how virtual volumes are mounted. Version bumped to 1.5.4. See: http://sf.net/tracker/?func=detail&aid=2886914&group_id=10894&atid=110894 2009-10-20 Steve Huntley * tclIndex: Corrected version number. * pkgIndex.tcl.in: Edited to replace function of deleted pkgIndex.tcl in template subdir. 2009-10-15 Steve Huntley vfs::template package update ver. 1.5.3: * templatevfs.tcl: Incorporated AK's fix below. * collatevfs.tcl: ensured binary file contents got written correctly, and ensured that not only file contents but also file attributes were updated to all write targets. 2009-07-06 Andreas Kupries * library/template/templatevfs.tcl (memchan): Fix result for * pkgIndex.tcl: unix. The bug was reported on the wiki. The fix there was wrong, did improper handling of the $args argument. Fixed here. Version bumped to 1.5.3. 2009-05-14 Pat Thoyts * library/zipvfs.tcl: Handle directory names that include * tests/vfsZip.test: glob chars. Added some tests. * win/makefile.vc: fix running the tests. 2009-02-06 Andreas Kupries * library/vfs.tcl.in: New file encapsulating the package load process. Cleaner than the loadvfs proc, and much more suitable for conversion to a teabag. * pkgIndex.tcl.in: Cleaned up the declarations for package 'vfs'. Removed the 'vfslib' package, it never was such. * Makefile.in: Added installation of library/vfs.tcl. * configure.in: Added library/vfs.tcl.in. * configure: Regenerated. * win/makefile.vc: Updated the windows build file to configure vfs.tcl.in, and install vfs.tcl. 2009-01-22 Pat Thoyts * tests/vfslib.test: Make use of the core zlib and refchan features * pkgIndex.tcl.in: by default for Tcl 8.6. * win/makefile.vc: Updated windows build files * win/rules.vc: * win/nmakehlp.c: * tests/*.test: Tidied up the tests. Added lots of zipfs tests. * library/zipvfs.tcl: Applied patch from [Bug 1011492] to ensure we handle zipfiles with a prefix block robustly. 2009-01-21 Andreas Kupries * pkgIndex.tcl.in: Incremented version of vfs::zip * library/zipvfs.tcl (zip::EndOfArchive): Fixed Schelte Bron's [Bug 2256740]. Trigger on outermost magic sequence, not an inner sequence from a n uncompressed zip archive stored in the zip. 2008-12-22 Pat Thoyts * library/mk4vfs.tcl: Fix vfs::zstream to support 8.6 core zlib * library/vfslib.tcl: 2008-12-12 Pat Thoyts * library/zipvfs.tcl: Cleaned up the zip stream read function to conform to the published specification more closely and avoid excess calls to the stat function. * pkgIndex.tcl.in: Incremented version of vfs::zip 2008-12-04 Jeff Hobbs * Makefile.in: change VPATH to ensure that configure munging of VPATH when configuring in the main directory does not break it. [Bug 2389466] 2008-12-03 Jeff Hobbs * tests/vfsFtp.test: correct unmount ordering * library/tclprocvfs.tcl (vfs::ns::matchindirectory): Handle the single item dir/file, and don't add a slash for single proc. 2008-12-02 Jeff Hobbs * tests/vfs.test (vfs-2.3,2.4,4.1): add tests for mount command not existing and for an issue with .. resolution. * pkgIndex.tcl.in, library/tclprocvfs.tcl: vfs::ns bump to 0.5.1 Correct glob of namespaces. [Bug 1280914] * generic/vfs.c (TCLVFS_POSIXERROR): note use of -1 return code to indicate a posix error passing through. * tclconfig/tcl.m4, generic/vfs.c, doc/vfs.n: * configure, configure.in: update to TEA 3.7, bump vfs to v1.4 * pkgIndex.tcl.in: this is now the sole pkgIndex.tcl script. vfs::loadvfs updated to source vfsUtils.tcl right after loading the dll. Package versions updated, removed mk4vfs and zipvfs compat packages. * Makefile.in, win/makefile.vc: update for removed files * library/template/*: add package provide 1.5.2 for each template * library/mk4vfscompat.tcl (removed): remove old compat pkg * library/zipvfscompat.tcl (removed): remove old compat pkg * library/tclIndex (removed): users should package require the appropriate driver, not rely on autoload * library/pkgIndex.tcl (removed): impotent index files * library/template/pkgIndex.tcl (removed): * tests/all.tcl (vfsCreateInterp): simplify the test to require vfs as the main interps do. * library/vfslib.tcl: remove vfs::normalize compat proc bump vfslib to 1.4 * library/mk4vfs.tcl: remove unused lassign defn * library/starkit.tcl (header): require namespace-based vfs driver (eg. vfs::mk4 instead of mk4vfs). bump starkit to v1.3.3 * mac/* (removed): removed outdated Mac classic pieces * Makefile.in (install-lib-binaries): use lib_BINARIES for the binary install list. [Bug 1699827] Install pkgIndex.tcl for static or shared build. [Bug 699176] (pkgIndex.tcl): add rebuild target 2008-11-20 Andreas Kupries * library/starkit.tcl (_startup, autoextend): Replaced the buggy 'vfs::filesystem fullynormalize' with the ok 'fullnormalize' defined in the same file. Now 'starkit::startup' handles sym-links to a starpack ok when detecting the wrap mode. 2008-10-17 Jeff Hobbs * pkgIndex.tcl.in, library/pkgIndex.tcl: update vfs::tar to 0.91 * library/tarvfs.tcl: update vfs::tar to use only its own namespace and not conflict with tcllib tar. [Bug 80465] 2008-10-10 Pat Thoyts * generic/vfs.c: Make use of CONST86 for 8.6a3 support. 2008-08-11 Pat Thoyts * http2.6/http.tcl: Merged zlib crc fix from Tcl. 2008-04-30 Pat Thoyts * win/makefile.vc: Updated the NMAKE build files. * win/rules.vc: * win/nmakehlp.c: 2008-04-15 Andreas Kupries * pkgIndex.tcl.in: Updated to handle the new files, and * Makefile.in: sync'd generated index with manual one. * library/pkgIndex.tcl: Moved the backward compatibility package * library/mkvfs.tcl: names (mk4vfs, zipvfs) into separate files, * library/zipvfs.tcl: as true packages. They properly load the new * library/mk4vfscompat.tcl: packages. The mess with one file * library/zipvfscompat.tcl: annoncing itself as two packages has been removed. Patchlevels bumped (1.10.1, 1.0.1 respectively), considering it as bug fix. 2008-04-11 Andreas Kupries * library/pkgIndex.tcl: Bumped version of starkit to 1.3.2. We * library/starkit.tcl: should have done that when we synchronized * pkgIndex.tcl.in: the mismatched version on 2005-11-09 anyway, because it was a bugfix, with attendant change to the version number. Without this bump we now have 1.3.1 floating around in two variants, i.e. it may or may not be mismatched with its package index, and the two variants cannot be distinguished. By bumping the patchlevel the correct version would have been easy to distinguish. Now it will. 2008-04-08 Pat Thoyts * configure: If building static then do not define USE_TCL_STUBS * configure.in: (needed to link tclkit with 8.6) 2008-03-21 Jeff Hobbs * http2.6/http.tcl, http2.6/pkgIndex.tcl: merge with tcl cvs 2.7 http changes, change this version to 2.6.8. 2008-03-10 Jeff Hobbs * http2.6/http.n, http2.6/http.tcl, http2.6/pkgIndex.tcl: merge with tcl cvs 2.5.5 http changes, correct whitespace differences, require Tcl 8.4. 2008-03-04 Steve Huntley vfs::template package update ver. 1.5.2: * templatevfs.tcl, deltavfs.tcl, versionvfs.tcl, quotavfs.tcl, fishvfs.tcl: added workaround to memchan bug that shows up when tclkit used. * pkgIndex.tcl, tclIndex: moved auto_index edits from former to latter to conform to Tcl package management standard practice. 2008-02-26 Steve Huntley vfs::template package update ver. 1.5.1: * deltavfs.tcl, versionvfs.tcl, quotavfs.tcl: minor bug fixes and reformatting. 2008-02-15 Steve Huntley vfs::template package update ver. 1.5: * Better formatting as Tcl package (added template/pkgIndex.tcl) * Added chrootvfs.tcl * Code refactored for simplicity and better performance * Added improved globfind package * Bug fixes. 2007-06-19 Andreas Kupries * library/starkit.tcl (header): See last entry. Simplified the helper command 'fullnormalize', replaced complex file split/lrange/join/eval operation with 'file dirname'. 2007-05-28 Andreas Kupries * library/starkit.tcl (header): Added helper command 'fullnormalize' and use it to resolve symlinks in the path to the file calling starkit::header. This makes it possible to run starkits and starpacks via symlinks. 2007-04-17 Andreas Kupries * library/zipvfs.tcl: "zip::DosTime" extended to handle bad timestamps without crashing. Force-fixed to nearest legal date/time. "zip::EndOfArchive" extended to find chunk even if a (long) zip archive comment is present. 2007-04-13 Pat Thoyts * Makefile.in: Applied patch #1589278 to include the template * pkgIndex.tcl.in: vfs files in the install. 2007-04-05 Pat Thoyts * Makefile.in: Was failing install the pkgIndex.tcl file 2007-03-12 Pat Thoyts * http2.6/http.tcl: Fixed some bugs (0 length body with chunked transfer) and added support for gzip encoding if zlib is available. Tested continued operation with Tcl 8.2. * library/webdavvfs.tcl: Encoding is now in the http package. * http2.6/pkgIndex.tcl: version to 2.6.6 2007-03-07 Pat Thoyts * library/webdavvfs.tcl: silence debug output * http2.6/http.tcl: merge in from tclsoap and jcw's webdav versions and merged in tcl8.5 changes. * http2.6/pkgIndex.tcl: version to 2.6.5 2006-12-28 Jean-Claude Wippler * configure: autoconf 2.59 * tclconfig/tcl.m4: based on tcl.m4,v 1.97 2006/12/19 01:20:55 das 2006-12-10 Steve Huntley * library/template/versionvfs.tcl: when time attribute is set, files created after set time are made invisible. 2006-11-14 Jean-Claude Wippler * library/mkclvfs.tcl: removed, now part of the vlerq extension again * library/pkgIndex.tcl, pkgIndex.tcl.in, Makefile.in: removed mkcl 2006-11-10 Steve Huntley * library/template/templatevfs.tcl: file delete on vfs mount point now causes vfs to unmount ; can now pass empty string as arbitrary attribute value * library/template/versionvfs.tcl: more efficient directory deletion code 2006-10-31 Steve Huntley * library/template/versionvfs.tcl: added code to ensure all subfiles of a directory are deleted before dir deletion. 2006-10-29 Steve Huntley Added comments and license info: * library/template/globfind.tcl * library/template/tdelta.tcl 2006-10-23 Steve Huntley Initial upload of template virtual filesystems in new subfolder: * library/template/collatevfs.tcl * library/template/deltavfs.tcl * library/template/fishvfs.tcl * library/template/quotavfs.tcl * library/template/templatevfs.tcl * library/template/versionvfs.tcl Plus helper utlities: * library/template/tdelta.tcl - required by deltavfs.tcl * library/template/globfind.tcl - required by quotavfs.tcl * library/pkgIndex.tcl - added "package ifneeded" statements for template virtual filesystems. 2006-09-29 Jeff Hobbs * library/httpvfs.tcl (vfs::http::geturl): wrapper around http::geturl that does 404 check. 2006-09-19 Jeff Hobbs * library/httpvfs.tcl (vfs::http::urlparse): add method to deconstruct the url using RFC 3986 semantics. (vfs::http::Mount): add support for HTTP basic auth if a user was passed in the url 2006-09-15 Jeff Hobbs * library/pkgIndex.tcl: bump vfs::http to 0.6 * library/httpvfs.tcl: Add urlname encoding to handle the translation of "/foo/my file (2).txt" as foo/my%20file%20%282%29.txt, per RFC 3986, for the user. This is controlled via a new ?-urlencode bool? mount option, default 1. **** POTENTIAL INCOMPATIBILITY **** **** if user was "working around" at [open] level **** 2006-09-14 Jeff Hobbs * library/httpvfs.tcl: rewritten to clean up http tokens and actually interpret data from them. (Mount): If a url doesn't return "ok" status, return failure. (stat, access): If HEAD returns 404 or status != ok, return ENOENT. * library/vfslib.tcl: code cleanup 2006-08-30 Jeff Hobbs * generic/vfs.c: move static globals to being thread-specific. If you wish to access a mount point or volume in a thread, you need to remount the file in the thread. This is a change from the previous behavior that would allow access across threads, which was unsafe and would potentially crash. **** POTENTIAL INCOMPATIBILITY **** 2006-06-22 Jean-Claude Wippler * library/mkclvfs.tcl: Updated to latest 1.4 revision 2006-05-26 Jeff Hobbs * generic/vfs.c (VfsOpenFileChannel): handle closing channels that were inherited as std channels. [Bug 1468291] 2006-03-12 Vince Darley * library/ftpvfs.tcl: provide caching of listings to improve performance for many standard use cases. 2006-02-27 Jean-Claude Wippler * library/mkclvfs.tcl: Small optimization so a writable starkit does not cause a real commit if no changes at all were made. 2006-01-25 Jeff Hobbs * configure, configure.in: update to TEA 3.5 * tclconfig/tcl.m4: TEA rcs 1.89 2006/01/25 21:25:02 2006-01-22 Jeff Hobbs * tclconfig/tcl.m4, configure: update to TEA 3.4 interim 2005-12-02 Jeff Hobbs * tclconfig/tcl.m4, configure.in, configure: update to TEA 3.4 2005-11-10 Jean-Claude Wippler * Makefile.in: added missing mkclvfs.tcl dependency 2005-11-09 Andreas Kupries * library/vfslib.tcl: Brought the version numbers of provide * library/starkit.tcl: and ifneeded commands back into sync. 2005-11-04 Jean-Claude Wippler * library/mkclvfs.tcl: some more thrill api mods * pkgIndex.tcl.in, library/pkgIndex.tcl: bumped to 1.2 2005-11-01 Jean-Claude Wippler * library/mkclvfs.tcl: renamed vlerq package to thrill * pkgIndex.tcl.in, library/pkgIndex.tcl: bumped to 1.1 2005-10-19 Jean-Claude Wippler * library/mk4vfs.tcl: added fallback to new vfs::mkcl * library/mkclvfs.tcl: new MK Compatible Lite driver * pkgIndex.tcl.in, library/pkgIndex.tcl: adjusted 2005-08-31 Vince Darley * generic/vfs.c: despite lack of documentation on this point, VfsMatchInDirectory should really allow a NULL interp, even in error situations. Tcl 8.5 now documents that this is allowed. 2005-03-18 Jeff Hobbs * Makefile.in (AR): use @AR@ * configure, tclconfig/tcl.m4: TEA 3.2 patch update 2005-02-14 Jean-Claude Wippler * configure, configure.in, tclconfig/tcl.m4: update from sample 2005-02-01 Jeff Hobbs * configure, configure.in, tclconfig/tcl.m4: update to TEA 3.2 2005-01-25 Jeff Hobbs * configure, configure.in (BUILD_vfs): correct from sample default 2005-01-20 Jean-Claude Wippler * library/mk4vfs.tcl: added return in periodicCommit 2004-11-22 Andreas Kupries * Makefile.in (PKG_TCL_SOURCES): Added 'tkvfs.tcl' to the list of installed files. It is listed in the package index, but was not installed. 2004-09-28 Vince Darley * win/makefile.vc: some cleanup of makefile to allow compilation with more than just VC++ 5.x. 2004-09-13 Vince Darley * generic/vfs.c: fix to crash if TclVfsAttr(Set|Get) are called with a NULL interp for error reporting. [Bug 1022202] 2004-08-05 Andreas Kupries * library/zipvfs.tcl (Data): Fixed [SF Tclvfs Bug 1003591]. This reverts an incomplete and unrecorded fix for handling dashes at the beginning of data, giving precedence to '2004-07-04 @ library/vfsUtils.tcl' instead, see below. The unrecorded fix was entered two days before and clashes with the other one. As it was incomplete the other fix was chosen, despite coming later. 2004-08-04 Andreas Kupries * library/zipvfs.tcl (EndOfArchive): Fixed [SF Tclvfs Bug 1003574]. Added code preventing us from seeking before the beginning of the zip file. 2004-07-15 Andreas Kupries * doc/vfs-fsapi.man: Clarified description of the close callback the handler method 'open' may set up. Especially noted that 'close' must not be called from within this callback, that it is done by the caller itself. 2004-07-15 Vince Darley * doc/*: fix to removedirectory docs which should say to return a posix EEXIST error if the directory is non-empty. 2004-07-04 Andreas Kupries * library/vfsUtils.tcl (crc, zip): Modified the Trf adapter commands. They are now adding in a "--" before the last argument they get, to ensure its interpretation as data instead of being misinterpreted as option should it begin with a dash. Without this adding a file beginning with a dash to a filesystem will fail. 2004-06-29 Vince Darley * library/zipvfs.tcl: fix to bug finding zip header (reported on Tcl'ers wiki). 2004-06-09 Jeff Hobbs * Makefile.in: corrected targets that use 'for' over what may be an empty list. Cleaned up echo output. * generic/vfs.c (Vfs_Init): added #ifndef PACKAGE_VERSION for non-TEA based build system. 2004-06-04 Jeff Hobbs * examples/simpleExamples.tcl: * tests/vfsUrl.test: s/scriptics.com/tcl.tk * library/zipvfs.tcl (zip::Data): add zip::stat call that correctly determines size for some zip files (Ferril). * generic/vfs.c: use PACKAGE_VERSION instead of hard-coded version info. * configure, configure.in, Makefile.in, tclconfig/tcl.m4: updated to the latest TEA3 spec * pkgIndex.tcl.in (added): move from library/ subdir * library/pkgIndex.tcl.in (removed): 2004-06-03 Jeff Hobbs * configure (regened): * tclconfig/tcl.m4 (TEA_TCL_64BIT_FLAGS): update to define TCL_WIDE_INT_IS_LONG when 'using long'. 2004-05-21 Vince Darley * win/makefile.vc: fix to compilation problem with new #includes in Tcl 8.5. 2004-05-21 Daniel Steffen * library/starkit.tcl: improved previous symbolic link patch by using [vfs::filesystem fullynormalize], as suggessted by Vince. * library/pkgIndex.tcl.in: brought back into sync with pkgIndex.tcl * library/pkgIndex.tcl: fixed spacing to be like pkgIndex.tcl.in 2004-05-19 Jean-Claude Wippler * library/starkit.tcl: added a patch from Bryan Schofield to properly resolve all symbolic links so starkit::startup detection works. * library/pkgIndex.tcl: bumped starkit version from 1.3 to 1.3.1 * ChangeLog: cleaned up a few tab-vs-space indentations 2004-04-18 Daniel Steffen * generic/vfs.c: continue to #include tclPort.h, otherwise compilation breaks against tcl 8.4.x. 2004-04-01 Vince Darley * generic/vfs.c: added #include tclInt.h given recent Tcl changes which broke compilation. Fix to privately reported vfs bug with 'glob -type d -dir . *' across a vfs boundary. No tests for this are currently possible without effectively moving tclvfs into Tcl's test suite. 2003-11-10 Jeff Hobbs * configure: regen * tclconfig/tcl.m4: update to latest TEA that corrects calling order of compiler and header checks. 2003-10-30 Vince Darley * library/tarvfs.tcl: fix to problem with relative paths (Thanks Stefan). 2003-10-21 Jean-Claude Wippler * starkit.tcl: add starkit::mode variable, which remembers the return value of starkit::startup (suggestion by Andreas Kupries) * pkgIndex.tcl: bumped starkit version from 1.2 to 1.3 * ChangeLog: cleaned up a few tab-vs-space indentations 2003-10-17 Vince Darley * generic/vfs.c: removed some compiler warnings on OS X. 2003-10-13 Vince Darley * generic/vfs.c: added support for TCL_GLOB_TYPE_MOUNT flag to the MatchInDirectory proc, which provides for more seamless boundaries between filesystems which allows for fixing Tcl's [Bug 800106]. This means (with a suitable version of Tcl) that 'glob */*' across a filesystem boundary will now work correctly. The code should work fine with Tcl 8.4 and 8.5, although with 8.4.4 the mount list will never be queried. * library/pkgIndex.tcl(.in): * DESCRIPTION.txt: * win/makefile.vc: * configure.in: updated version to 1.3.0 reflecting the above significant improvement. 2003-10-06 Jeff Hobbs * configure: updated to autoconf 2.5 * tclconfig/tcl.m4: updated to latest TEA spec with WinCE support and corrected defn of TCL_WIDE_INT_TYPE for compiling. * Makefile.in: add CFLAGS_WARNING and pedantic quoting 2003-09-28 Jean-Claude Wippler * starkit.tcl: added "package" and "pload" procs, to simplify loading compiled extensions from a platform-specific subdir. The naming conventions and code were adopted from Critcl. 2003-09-26 Jean-Claude Wippler * starkit.tcl: add file normalize around info nameofexe, fixes startup detection when exec'd in some cases (thx E Boudaillier). 2003-09-01 Vince Darley * library/mk4vfs.tcl: fix to Bug #796782. * library/zipvfs.tcl: * library/tarvfs.tcl: fix to similar bug in these filesystems. 2003-07-15 Vince Darley * tests/vfsZip.test: * tests/vfsTar.test: added some new tests for recently fixed bugs. * library/tarvfs.tcl: fix to bug when closing an empty archive. Also updated package to version 1.2.1 since a variety of bugs have been fixed since the 1.2 release 2003-07-06 Vince Darley * library/ftpvfs.tcl: fix to 'file stat' on a directory, which fixes a variety of problems (e.g. recurisve 'file copy' in a directory). Thanks to msofer for the detailed bug report and test script. * library/zipvfs.tcl: * library/tarvfs.tcl: ensure archive channel is closed if an error is encountered while trying to open it. 2003-07-03 Vince Darley * library/ftpvfs.tcl: added support for ports other than 21, patch from msofer -- thanks. 2003-06-16 Vince Darley * library/ftpvfs.tcl: added '-output ::vfs::log' to ftp initialisation code to avoid messages being dumped to stderr when errors occur. 2003-05-16 Vince Darley * library/tkvfs.tcl: added 'tk' widget hierarchy vfs. Use: package require vfs::tk vfs::tk::Mount .frame.a.b foo cd foo ... to examine. * library/pkgIndex.tcl(.in): added new package. 2003-05-15 Jeff Hobbs * library/pkgIndex.tcl.in: use vfs::dll var directly 2003-05-14 Vince Darley * library/vfsUtils.tcl: fix to package names * library/mk4vfs.tcl: fix to 'file attributes' implementation 2003-04-29 Vince Darley * library/zipvfs.tcl: patterns in 'glob' should be case-insensitive since everything else is. 2003-04-04 Andreas Kupries * configure.in: * tclconfig/tcl.m4: Updated to newest tcl.m4, regenerated configure's. 2003-03-17 Jean-Claude Wippler * pkgIndex.tcl, pkgIndex.tcl.in: mk4vfs rev bumped to 1.9 * mk4vfs.tcl: reverted to old translucent/readwrite open modes 2003-03-11 Andreas Kupries * doc/vfs.man: Added doctools documentation derived * doc/vfs-fsapi.man: from the original nroff-based * doc/vfs-filesystems.man: manpages. Approved by Vincent. 2003-03-11 Vince Darley * library/pkgIndex.tcl: * win/makefile.vc: updated for Tcl's incompatible change from 'd' to 'g' for debug builds. 2003-02-24 Jean-Claude Wippler * pkgIndex.tcl, pkgIndex.tcl.in: starkit rev bumped to 1.2 * starkit.tcl: more contexts, panic ok if "." already gone 2003-02-23 Jeff Hobbs * configure: regen * configure.in: * tclconfig/tcl.m4: regen from latest TEA setup * Makefile.in: only use pkgIndex.tcl with shared builds Handle RUNTIME_SOURCES properly when srcdir == top_builddir 2003-02-21 Vince Darley * doc/vfs.n: * library/*.tcl: added missing 'recursive' flag to most .tcl 'removedirectory' implementations. * library/mk4vfs.tcl: added catch around 'after cancel' 2003-02-21 Vince Darley * generic/vfs.c: some small cleanup * doc/vfs.n: better documentation for 'createdirectory' * library/mk4vfs.tcl: better posix adherence. * library/vfsUtils.tcl: typo fix. 2003-02-20 Vince Darley * generic/vfs.c: completed use of internalerror and posix handling for all functions. * doc/vfs.n: * doc/vfslib.n: more documentation regarding handling of errors and use of the 'internalerror' feature. Around the time Tcl 8.4.2 is released we should increment tclvfs's version to 1.3 and make a proper release. In the meantime, improvements to all .tcl implementations (esp. proper error handling) would be greatly appreciated. 2003-02-20 Andreas Kupries * library/mk4vfs.tcl: Switching to canceling the stored after id of the periodic commit in _unmount instead of canceling by script. The scripts in '_umount' and 'periodicCommit' were different, causing the cancel to fail, and thus an eternal commit, failing after the close; hanging the system. 2003-02-20 Vince Darley * generic/vfs.c: added new debugging feature 'vfs::filesystem internalerror ?script?' which can be used to specify a script to evaluate when any tclvfs implementation throws a standard Tcl error. Once implementation of all .tcl's is complete, they should only return TCL_OK or a posix error code (which has a Tcl return value of -1). Any other code will signal an unintended error which can be logged or reported using this new hook. If the script is not set, the behaviour of this extension is unchanged. For example: vfs::filesystem internalerror vfsreport proc vfsreport {} { puts "vfs bug found: $::errorInfo" } Note that this has only been applied to those VFS api's which are not currently able to pass an error message at the Tcl level. Some (open, matchindirectory, fileattributes with get/set) are already able to pass their errors up, so these cases are *not* passed to this handler. * library/mk4vfs.tcl: made one change to support the above feature. 2003-02-19 Vince Darley * library/mk4vfs.tcl: added 'commit' attribute * library/vfsUtils.tcl: * library/tarvfs.tcl: * library/zipvfs.tcl: * library/ftpvfs.tcl: added support for 'state' attribute of these filesystems. 2003-02-18 Vince Darley * generic/vfs.c: * library/*.tcl: clean up of posix error handling. * doc/vfs.n: added some more documentation. 2003-02-18 Vince Darley * generic/vfs.c: added 'vfs::filesystem posixerror' command to allow direct reporting of posix error codes to Tcl. * library/vfsUtils.tcl: added support for state switching between "readonly", "translucent" and "readwrite". * library/mk4vfs.tcl: * library/tarvfs.tcl: * library/zipvfs.tcl: * library/httpvfs.tcl: added support for proper reporting of read-only status of filesystem * library/tclIndex: regen. You can now switch an mk4 filesystem between translucent and readonly with 'vfs::attributes $mount -state readonly'. All errors etc are correctly reported as if the filesystem is read-only. 2003-02-17 Vince Darley * library/vfsUtils.tcl: added beginnings of interface for filesystem configuration. * library/mk4vfs.tcl: * library/tclIndex: regen. 2003-02-01 Jean-Claude Wippler * library/vfslib.tcl: fixed bug in new vfs::zstream code, preventing forward seeking from working properly * library/starkit.tcl: recognize if launched as NT service 2003-02-08 Vince Darley * library/*.tcl: made all 'matchindirectory' implementations robust to whether they are passed a directory with a trailing file-separator or not. (Tcl doesn't document whether there will be one, and optimisations to Tcl's filesystem require this flexibility. Also the use of 'file join' will actually make the entire filesystem *more* efficient soon). 2003-02-06 Andreas Kupries * tclconfig/tcl.m4: Added SC_TCL_EARLY_FLAGS and * configure.in: SC_TCL64BIT_FLAGS, copied from the Tcl * configure: configuration. Usage prevents mismatch between tcl core and tclvfs with regard to the selected types for wide integer and Tcl_StatBuf. Regenerated configure. 2003-02-04 Vince Darley * doc/vfs.n: * doc/vfslib.n: update docs to reflect last six months of changes. 2003-02-04 Andreas Kupries * library/mk4vfs.tcl: Fixed bad vfs::mk4::Mount change. 2003-02-04 Vince Darley * generic/vfs.c: fixed version of VfsFullyNormalizePath, should resolve some problems with symlinks. Tcl really needs a 'file normalized -full' and equivalent C api. 2003-02-04 Vince Darley * tests/*.test: cleanup Also updated version of the package to 1.2 (not 1.1 since there's a Windows binary floating around with that number, and we want to avoid confusion). It's been fixed at 1.0 for far too long. 2003-02-01 Jean-Claude Wippler * library/mk4vfs.tcl: fixed bad mk4vfs::_umount change 2003-02-01 Jean-Claude Wippler * library/pkgIndex.tcl.in: mk4vfs 1.8, starkit 1.1, vfslib 1.3.1 * library/pkgIndex.tcl: (shouldn't this be dropped from CVS now?) * library/mk4vfs.tcl: updated from tclkit project * library/starkit.tcl: updated from tclkit project * library/vfslib.tcl: updated from tclkit project 2003-01-30 Jeff Hobbs * Makefile.in: only install pkgIndex.tcl for shared builds 2003-01-29 Jeff Hobbs * library/pkgIndex.tcl.in (new): * library/pkgIndex.tcl: Replace pkgIndex.tcl with one that is * configure: generated by configure to include the right * configure.in: vfs dll name. Left the old one for * Makefile.in: non-configure users, but it can be wrong. Also added tarvfs.tcl to list of files to install. * library/vfsUtils.tcl: code cleanup 2003-01-28 Vince Darley * library/*.tcl: add 'package provide vfs::' to the virtual filesystems. These are the current versions: package ifneeded vfs::ftp 1.0 package ifneeded vfs::http 0.5 package ifneeded vfs::mk4 1.6 package ifneeded vfs::ns 0.5 package ifneeded vfs::tar 0.9 package ifneeded vfs::test 1.0 package ifneeded vfs::urltype 1.0 package ifneeded vfs::webdav 0.1 package ifneeded vfs::zip 1.0 I've used '0.1' to indicate a very preliminary version, 0.5 for something which has had some work, 0.9 for nearly complete and 1.0 or newer for something which is well used. There is no need to do 'package require vfs', simply do a package require of the particular vfs implementation you want from the above list. * DESCRIPTION.txt: * make55.tcl: new files for TIP55 compliance. (Steve Cassidy) * tests/*: * doc/tcllib.n: updated tests and docs for the above 'package' information. 2003-01-16 Vince Darley * library/tarvfs.tcl: * library/zipvfs.tcl: ::close .zip or .tar file when unmounting the filesystem. 2003-01-14 Vince Darley * library/tarvfs.tcl: new 'tar' filesystem courtesy of Stefan Vogel -- many thanks! The tar vfs is currently read-only and doesn't support .tgz. * library/tclIndex: * library/pkgIndex.tcl: * library/vfsUtils.tcl: updated for new tar vfs. 2003-01-06 Vince Darley * library/ftpvfs.tcl: allow 'file mtime' to set the modified time of a file, if the ftp package supports it. 2002-12-24 Vince Darley * library/ftpvfs.tcl: set the 'size' element in stat calls. (Bug reported on comp.lang.tcl). * library/vfsUtils.tcl: added '.kit' to the set of extensions which vfs::auto will recognise for auto-mounting. 2002-10-30 Andreas Kupries * library/pkgIndex.tcl: Changed 'tcl_platform' to '::tcl_platform'. Package index must not assume execution at global level. 2002-10-19 Jean-Claude Wippler * library/pkgIndex.tcl: * library/mk4vfs.tcl: merged 1.6 changes, periodic commit/flush 2002-10-18 Jeff Hobbs * Makefile.in: add tclIndex to install * library/mk4vfs.tcl: * library/starkit.tcl: * library/vfsUtils.tcl: * library/vfslib.tcl: * library/webdavvfs.tcl: whitespace cleanup * library/pkgIndex.tcl: remove 8.4 alpha checks, use vfs::dll var to store library name. 2002-10-15 Jeff Hobbs * tclconfig/tcl.m4: * configure: * configure.in: move the CFLAGS definition into TEA_ENABLE_SHARED and make it pick up the env CFLAGS at configure time. 2002-09-25 Jeff Hobbs * Makefile.in: replace the ancient build system * README.cygwin: with TEA 2002 build spec. * aclocal.m4: * config.guess (removed): * config.sub (removed): * configure: * configure.in: * install-sh (removed): * mkIndex.tcl.in (removed): * mkinstalldirs (removed): * tcl.m4 (removed): * tclconfig/README.txt (new): * tclconfig/install-sh (new): * tclconfig/tcl.m4 (new): * generic/vfs.c: changed BUILD_Vfs to BUILD_vfs 2002-09-10 Jean-Claude Wippler * library/pkgIndex.tcl: adjusted for two new packages, also fixed to use proper file name on unix (as shared lib) * library/starkit.tcl: added, new impl of scripdoc.tcl * library/vfslib.tcl: added back in, need by above 2002-07-18 Vince Darley * generic/vfs.c: ensure all mount activity is with fully normalized paths in which the last path element is not a link. Solves (together with latest cvs head changes) a problem in starting up a tclkit(sh) from a link. 2002-07-08 Vince Darley * generic/vfs.c: update for latest cvs head. * win/makefile.vc: compilation into Release and Debug directories as appropriate. 2002-06-22 Jean-Claude Wippler * mac/pkgIndex_mac.tcl: * library/pkgIndex.tcl: * library/mk4vfs.in: fix recursive file deletion, bump to 1.5 2002-05-29 Jean-Claude Wippler * Makefile.in: moved the definition of $(OBJEXT) up so the definition of vfs_OBJECTS works with more make's 2002-05-13 Vince Darley * library/webdavvfs.tcl: v. early implementation of a webdav vfs. (Note: this and the 'http' vfs need lots of work -- please help out!). This requires the '2.6' version of the http package which is distributed with tclvfs. 2002-05-13 Vince Darley * library/mk4vfs.tcl: newer version from tclkit. 2002-05-03 Vince Darley * tests/*: more test improvements, and new file vfsArchive.test which will test the running of the tests inside an archive. This requires recursive invocation of the 'tcltest' package, which may well cause some problems if it isn't designed to handle that (i.e. executing one test actually causes the execution of a lot of other tests). * library/pkgIndex.tcl: update to try to avoid the 'no such command vfs::*::Mount' error messages which you can get, if the relevant .tcl files are not on your auto_path. 2002-05-02 Vince Darley * tests/vfs.test: tests work independent of directory in which they run. Tests added to check that at least 'vfs::memchan' basically works, and vfs::zip, vfs::crc helpers do what they are supposed to. * tests/vfsZip.test: test to run all tests inside a zip. * mac/*: updated for removal of scripdoc.tcl and vfs.tcl 2002-04-25 Jean-Claude Wippler * library/*vfs.tcl: switching to vfs::{crc,memchan,zip} * library/vfsUtils.tcl: fixed env to be global, added unset so unmounting cleans up its list of mounted file systems, define Trf/memchan-based versions of vfs::{crc,memchan,zip} * library/{scripdoc.tcl,vfs.tcl}: removed, tclkit specific * library/pkgIndex.tcl: drop packages "scripdoc" and "vfslib" 2002-04-25 Vince Darley * tests/*: revamp of tests to be more robust, and to be able to run from inside a mounted virtual filesystem. 2002-04-09 Jean-Claude Wippler * configure: generated and added to project 2002-04-08 Daniel Steffen * mac/pkgIndex_mac.tcl: synced to generic/pkgIndex.tcl 2002-04-01 Vince Darley * Makefile.in: compilation fix from jcw. 2002-03-16 Vince Darley * generic/vfs.c: updated for latest cvs head of Tcl 8.4a5. * library/vfs.tcl: New version from jcw, with better handling of env(PATH). 2002-03-09 Vince Darley * library/mk4vfs.tcl: updated version from Jean-Claude Wippler. 2002-03-01 Vince Darley * library/*.tcl: completed and tested most changes from 02-19. 2002-02-19 Vince Darley * library/*.tcl: updated the vfs implementations to deal with the 2002-02-01 change below. More work needed. 2002-02-17 Vince Darley * generic/vfs.c: updated for TIP#72 application to cvs head. The 'file stat' implementation now deals with files of size greater than a 32 bit representation. This requires the very latest cvs head of Tcl 8.4a4, and is not compatible with previous releases (but that is fine, since we're still tracking alpha releases anyway). 2002-02-01 Vince Darley * generic/vfs.c: allow 'pattern' to be NULL in calls to Tcl_FSMatchInDirectory in preparation for fix of Tcl bug 511666. This will require additions to each individual filesystem to handle that special case (and thereby fix the bug that fully specified files were not matched against 'types'). 2002-01-28 Vince Darley * generic/vfs.c: const, MacOS fixes (also thanks Daniel Steffen). 2001-12-07 Vince Darley * various test, install fixes (unix) thanks to Larry Virden. 2001-12-02 Vince Darley * generic/vfs.c: minor code cleanup and simplification. Fix to problem with absolute paths on unix systems introduced in recent changes. 2001-11-21 Vince Darley * generic/vfs.c: added more comments to the code, and made mount point checking faster and simpler (we no longer need to modify strings temporarily). 2001-11-09 Vince Darley * tests/vfs*.test: better tests; more platform independent. 2001-11-08 Vince Darley * generic/vfs.c: made code thread-safe. Disallow safe interpreters from using vfs code since they can then mess with the filesystem across all interpreters. 2001-11-07 Vince Darley * generic/vfs.c: all mount information is now stored in a purpose built data structure ('vfs::mount' variable is gone), and the code handles multiple interpreters in a very robust fashion. Fixes crashing problem in pkg_mkIndex and general inconsistencies with multiple interps. Also, the '-volume' flag is no longer required for unmounting. Lastly added a lot more documentation in the code. * library/vfsUrl.tcl: remove '-volume' flag. * tests/vfs*.test: various new tests added * doc/vfs.n: documentation much improved, especially with respect to multiple interpreters. 2001-11-01 Vince Darley * generic/vfs.c: 'vfs::mount' no longer a string-literal * tests/vfs*.test: various new tests added 2001-10-31 Vince Darley * examples/simpleExamples.tcl: a demo * doc/vfslib.n: some documentation on the 'library' code. 2001-10-29 Vince Darley * win/makefile.vc: installation is better. * library/vfsUrl.tcl: improved urltype mounting. The following will now work in all cases: % vfs::urltype::Mount ftp % set listing [glob -dir ftp://ftp.scriptics.com/pub *] ... % vfs::urltype::Mount http % set fd [open http://sourceforge.net/projects/tcl] % set contents [read $fd] ; close $fd ... 2001-09-27 Vince Darley * library/mk4vfs.tcl: Update from Jean-Claude Wippler * library/vfsUtils.tcl: * generic/vfs.c: Moved 'list volumes' functionality entirely into C from Tcl (faster and easier for tclkit to make proper use of). This required the addition of a '-volume' flag to the mount/unmount commands, and meant we can remove the 'mountschanged' subcommand. 2001-09-07 Vince Darley * generic/vfs.c: Fixed '==' error * doc/vfs.n: Improved docs. * library/mk4vfs.tcl: Better mk support 2001-09-06 Vince Darley * Further minor improvements, unfortunately requires new release of Tcl from cvs (today). Also added 'install' target to vc++ makefile. 2001-08-29 Vince Darley * can now mount root volumes which end in separator characters (such as 'ftp://'). The code handles path separation in such cases. This means the 'urltype' vfs now works (the 8-22 changes below didn't quite complete the job). This requires the latest 8.4a4 release from cvs. 2001-08-22 Vince Darley * added ability to treat entire urls as file paths, so we can mount 'ftp://' as a root volume and examine its contents. This requires the latest 8.4a4 release from cvs. 2001-08-13 Vince Darley * ftp vfs works reasonably well now; try: % package require vfs % vfs::ftp::Mount ftp://ftp.ucsd.edu/pub/alpha/ local % cd local ; cd tcl ; source vfsTest.tcl 2001-08-10 Vince Darley * added a man page vfs.n * added 'utime' to various vfs * included mk4tcl vfs implementation which works * added some support files so this library can be used more easily with TclKit. * memory leak in file attributes get fixed. 2001-05-09 Vince Darley * initial distribution, zip vfs works tclvfs/DESCRIPTION.txt000064400000000000000000000007521447560765400143050ustar00nobodynobodyIdentifier: vfs Version: 1.3.0 Title: Interface to Virtual File Systems for Tcl 8.4 Creator: Vince Darley Description: The goal of this extension is to expose Tcl 8.4's new filesystem C API to the Tcl level. Rights: BSD URL: http://sourceforge.net/projects/tclvfs Date: 2003-10-08 Architecture: tcl Architecture: Linux-x86 Require: tcl 8.4 Recommend: tcl 8.5 Recommend: Trf Recommend: http 2.6 Recommend: base64 Recommend: Memchan Recommend: Mk4tcl Recommend: ftp Subject: filesystem tclvfs/Makefile.in000064400000000000000000000337041447560765400140310ustar00nobodynobody# Makefile.in -- # # This file is a Makefile for Sample TEA Extension. If it has the name # "Makefile.in" then it is a template for a Makefile; to generate the # actual Makefile, run "./configure", which is a configuration script # generated by the "autoconf" program (constructs like "@foo@" will get # replaced in the actual Makefile. # # Copyright (c) 1999 Scriptics Corporation. # # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: Makefile.in,v 1.31 2010/02/01 07:32:58 blacksqr Exp $ #======================================================================== # Edit the following few lines when writing a new extension #======================================================================== #======================================================================== # The names of the source files is defined in the configure script. # The object files are used for linking into the final library. # This will be used when a dist target is added to the Makefile. # It is not important to specify the directory, as long as it is the # $(srcdir) or in the generic, win or unix subdirectory. #======================================================================== PKG_SOURCES = @PKG_SOURCES@ PKG_OBJECTS = @PKG_OBJECTS@ PKG_STUB_SOURCES = @PKG_STUB_SOURCES@ PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@ #======================================================================== # PKG_TCL_SOURCES identifies Tcl runtime files that are associated with # this package that need to be installed, if any. #======================================================================== # vfs.tcl is found in the build, as it was generated by configure from # library/vfs.tcl.in. This necessitated extensions to the target # install-lib-binaries. PKG_TCL_SOURCES = @PKG_TCL_SOURCES@ \ ftpvfs.tcl httpvfs.tcl mk4vfs.tcl starkit.tcl \ tarvfs.tcl tclprocvfs.tcl testvfs.tcl \ vfsUrl.tcl vfsUtils.tcl vfslib.tcl \ webdavvfs.tcl zipvfs.tcl tkvfs.tcl \ template/collatevfs.tcl template/deltavfs.tcl \ template/fishvfs.tcl template/globfind.tcl \ template/quotavfs.tcl template/tdelta.tcl \ template/templatevfs.tcl template/versionvfs.tcl \ template/chrootvfs.tcl template/tclIndex vfs.tcl #======================================================================== # This is a list of public header files to be installed, if any. #======================================================================== PKG_HEADERS = @PKG_HEADERS@ #======================================================================== # "PKG_LIB_FILE" refers to the library (dynamic or static as per # configuration options) composed of the named objects. #======================================================================== PKG_LIB_FILE = @PKG_LIB_FILE@ PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@ lib_BINARIES = $(PKG_LIB_FILE) BINARIES = $(lib_BINARIES) pkgIndex.tcl SHELL = @SHELL@ srcdir = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ libdir = @libdir@ includedir = @includedir@ datarootdir = @datarootdir@ datadir = @datadir@ mandir = @mandir@ DESTDIR = PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION) pkgdatadir = $(datadir)/$(PKG_DIR) pkglibdir = $(libdir)/$(PKG_DIR) pkgincludedir = $(includedir)/$(PKG_DIR) top_builddir = . INSTALL = @INSTALL@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ CC = @CC@ CFLAGS_DEFAULT = @CFLAGS_DEFAULT@ CFLAGS_WARNING = @CFLAGS_WARNING@ CLEANFILES = @CLEANFILES@ EXEEXT = @EXEEXT@ LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@ MAKE_LIB = @MAKE_LIB@ MAKE_SHARED_LIB = @MAKE_SHARED_LIB@ MAKE_STATIC_LIB = @MAKE_STATIC_LIB@ MAKE_STUB_LIB = @MAKE_STUB_LIB@ OBJEXT = @OBJEXT@ RANLIB = @RANLIB@ RANLIB_STUB = @RANLIB_STUB@ SHLIB_CFLAGS = @SHLIB_CFLAGS@ SHLIB_LD = @SHLIB_LD@ SHLIB_LD_FLAGS = @SHLIB_LD_FLAGS@ SHLIB_LD_LIBS = @SHLIB_LD_LIBS@ STLIB_LD = @STLIB_LD@ TCL_DEFS = @TCL_DEFS@ TCL_BIN_DIR = @TCL_BIN_DIR@ TCL_SRC_DIR = @TCL_SRC_DIR@ # This is necessary for packages that use private Tcl headers TCL_TOP_DIR_NATIVE = @TCL_TOP_DIR_NATIVE@ # Not used, but retained for reference of what libs Tcl required TCL_LIBS = @TCL_LIBS@ #======================================================================== # TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our # package without installing. The other environment variables allow us # to test against an uninstalled Tcl. Add special env vars that you # require for testing here (like TCLX_LIBRARY). #======================================================================== EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR) TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library` \ @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \ VFS_LIBRARY="`@CYGPATH@ $(srcdir)/library`" \ PATH="$(EXTRA_PATH):$(PATH)" \ TCLLIBPATH="$(top_builddir)" TCLSH_PROG = @TCLSH_PROG@ TCLSH = $(TCLSH_ENV) $(TCLSH_PROG) SHARED_BUILD = @SHARED_BUILD@ INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ PKG_CFLAGS = @PKG_CFLAGS@ DEFS = @DEFS@ $(PKG_CFLAGS) CONFIG_CLEAN_FILES = Makefile CPPFLAGS = @CPPFLAGS@ LIBS = @PKG_LIBS@ @LIBS@ AR = @AR@ ## need to include the tcl source dir here for tclPort.h CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) #======================================================================== # Start of user-definable TARGETS section #======================================================================== #======================================================================== # TEA TARGETS. Please note that the "libraries:" target refers to platform # independent files, and the "binaries:" target includes executable programs and # platform-dependent libraries. Modify these targets so that they install # the various pieces of your package. The make and install rules # for the BINARIES that you specified above have already been done. #======================================================================== all: binaries libraries doc #======================================================================== # The binaries target builds executable programs, Windows .dll's, unix # shared/static libraries, and any other platform-dependent files. # The list of targets to build for "binaries:" is specified at the top # of the Makefile, in the "BINARIES" variable. #======================================================================== binaries: $(BINARIES) libraries: doc: install: all install-binaries install-libraries install-doc install-binaries: binaries install-lib-binaries install-bin-binaries #======================================================================== # This rule installs platform-independent files, such as header files. #======================================================================== install-libraries: libraries @mkdir -p $(DESTDIR)$(includedir) @echo "Installing header files in $(DESTDIR)$(includedir)" @list='$(PKG_HEADERS)'; for i in $$list; do \ echo " $$i" ; \ $(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \ done; #======================================================================== # Install documentation. Unix manpages should go in the $(mandir) # directory. #======================================================================== install-doc: doc @mkdir -p $(DESTDIR)$(mandir)/mann @echo "Installing documentation in $(DESTDIR)$(mandir)/mann" @list='$(srcdir)/doc/*.n'; for i in $$list; do \ echo " `basename $$i`"; \ rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \ $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \ done test: binaries libraries $(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS) shell: binaries libraries @$(TCLSH) $(SCRIPT) gdb: $(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT) depend: #======================================================================== # $(PKG_LIB_FILE) should be listed as part of the BINARIES variable # mentioned above. That will ensure that this target is built when you # run "make binaries". # # The $(PKG_OBJECTS) objects are created and linked into the final # library. In most cases these object files will correspond to the # source files above. #======================================================================== $(PKG_LIB_FILE): $(PKG_OBJECTS) -rm -f $(PKG_LIB_FILE) ${MAKE_LIB} $(RANLIB) $(PKG_LIB_FILE) $(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS) -rm -f $(PKG_STUB_LIB_FILE) ${MAKE_STUB_LIB} $(RANLIB_STUB) $(PKG_STUB_LIB_FILE) #======================================================================== # We need to enumerate the list of .c to .o lines here. # # In the following lines, $(srcdir) refers to the toplevel directory # containing your extension. If your sources are in a subdirectory, # you will have to modify the paths to reflect this: # # sample.$(OBJEXT): $(srcdir)/generic/sample.c # $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@ # # Setting the VPATH variable to a list of paths will cause the makefile # to look into these paths when resolving .c to .obj dependencies. # As necessary, add $(srcdir):$(srcdir)/compat:.... # # The first $(srcdir) isn't necessary, but configure will strip it the # first $(srcdir) it sees in VPATH when configuring in the toplevel dir. #======================================================================== VPATH = $(srcdir):$(srcdir)/generic .c.@OBJEXT@: $(COMPILE) -c `@CYGPATH@ $<` -o $@ #======================================================================== # Create the pkgIndex.tcl file. # It is usually easiest to let Tcl do this for you with pkg_mkIndex, but # you may find that you need to customize the package. If so, either # modify the -hand version, or create a pkgIndex.tcl.in file and have # the configure script output the pkgIndex.tcl by editing configure.in. #======================================================================== #pkgIndex.tcl: # ( echo pkg_mkIndex . $(PKG_LIB_FILE) \; exit; ) | $(TCLSH) pkgIndex.tcl: $(srcdir)/pkgIndex.tcl.in cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status #======================================================================== # Don't modify the file to clean here. Instead, set the "CLEANFILES" # variable in configure.in #======================================================================== clean: -test -z "$(BINARIES)" || rm -f $(BINARIES) -rm -f *.$(OBJEXT) core *.core -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean: clean -rm -f *.tab.c -rm -f $(CONFIG_CLEAN_FILES) -rm -f config.cache config.log config.status #======================================================================== # Install binary object libraries. On Windows this includes both .dll and # .lib files. Because the .lib files are not explicitly listed anywhere, # we need to deduce their existence from the .dll file of the same name. # Additionally, the .dll files go into the bin directory, but the .lib # files go into the lib directory. On Unix platforms, all library files # go into the lib directory. In addition, this will generate the pkgIndex.tcl # file in the install location (assuming it can find a usable tclsh8.2 shell) # # You should not have to modify this target. #======================================================================== install-lib-binaries: @mkdir -p $(DESTDIR)$(pkglibdir) @list='$(lib_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo "Installing $$p in $(DESTDIR)$(pkglibdir)"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(pkglibdir)/$$p; \ stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \ if test "x$$stub" = "xstub"; then \ echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \ else \ echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \ $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \ fi; \ ext=`echo $$p|sed -e "s/.*\.//"`; \ if test "x$$ext" = "xdll"; then \ lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \ if test -f $$lib; then \ echo "Install $$lib in $(DESTDIR)$(pkglibdir)"; \ $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \ fi; \ fi; \ fi; \ done @echo "Installing library files in $(DESTDIR)$(pkglibdir)"; @list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ if test -f $(srcdir)/library/$$p; then \ destd=`dirname $$p`; \ echo " $$p"; \ mkdir -p $(DESTDIR)$(pkglibdir)/$$destd; \ $(INSTALL_DATA) $(srcdir)/library/$$p $(DESTDIR)$(pkglibdir)/$$p; \ elif test -f $(top_builddir)/library/$$p; then \ destd=`dirname $$p`; \ echo " $$p (generated)"; \ mkdir -p $(DESTDIR)$(pkglibdir)/$$destd; \ $(INSTALL_DATA) $(top_builddir)/library/$$p $(DESTDIR)$(pkglibdir)/$$p; \ fi; \ done @echo "Installing pkgIndex.tcl in $(DESTDIR)$(pkglibdir)"; @$(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); #======================================================================== # Install binary executables (e.g. .exe files) # # You should not have to modify this target. #======================================================================== install-bin-binaries: @mkdir -p $(DESTDIR)$(bindir) @list='$(bin_BINARIES)'; for p in $$list; do \ if test -f $$p; then \ echo "Installing $$p in $(DESTDIR)$(bindir)"; \ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \ fi; \ done .SUFFIXES: .c .$(OBJEXT) Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status cd $(top_builddir) \ && CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status uninstall-binaries: list='$(BINARIES)'; for p in $$list; do \ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ done list='$(PKG_TCL_SOURCES)'; for p in $$list; do \ p=`basename $$p`; \ rm -f $(DESTDIR)$(pkglibdir)/$$p; \ done list='$(bin_BINARIES)'; for p in $$list; do \ rm -f $(DESTDIR)$(bindir)/$$p; \ done .PHONY: all binaries clean depend distclean doc install libraries test # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: tclvfs/README.cygwin000064400000000000000000000002251447560765400141330ustar00nobodynobodyThe contents of this file were out of date and misleading. They have been removed until someone contributes something which works and is up to date. tclvfs/Readme.txt000064400000000000000000000165741447560765400137300ustar00nobodynobodyHello! The code here has evolved from ideas and excellent work by Matt Newman, Jean-Claude Wippler, TclKit etc. To make this really successful, we need a group of volunteers to enhance what we have and build a new way of writing and distributing Tcl code. Introduction ------------ This is an implementation of a 'vfs' extension (and a 'vfs' package, including a small library of Tcl code). The goal of this extension is to expose Tcl 8.4's new filesystem C API to the Tcl level. Using this extension, the editor Alphatk can actually auto-mount, view and edit (but not save, since they're read-only) the contents of .zip files directly (see ), and you can do things like: file copy ftp://ftp.foo.com/pub/readme.txt . With 'Tkhtml' and this extension, writing a web-browser in Tcl should be pretty trivial. None of the vfs's included are 100% complete or optimal yet, so if only for that reason, code contributions are very welcome. Many of them still contain various debugging code, etc. This will be gradually removed and the code completely cleaned up and documented as the package evolves. -- Vince Darley, April 2002-February 2003 Compile/build ------------- The standard 'configure ; make ; make install' should work, but if it doesn't, I'm afraid I can't help --- I am not an expert on these issues and find it amazing that to compile a single C file (generic/vfs.c) a dozen or so TEA 'helper' files are required. I believe 'gmake' may be required on some platforms. For windows, there is a VC++ makefile in the win directory ('nmake -f makefile.vc') should do the trick. Tests and installation ---------------------- The tests/vfs*.test files should all pass (provided you have an active internet connection). To install, you probably want to rename the directory 'library' to 'vfs1.0' and place it in your Tcl hierarchy, with the necessary shared library inside (improvements to makefiles to streamline this much appreciated). On Windows 'nmake -f makefile.vc install' should do everything for you. Current implementation ---------------------- Some of the provided vfs's require the Memchan extension for any operation which involves opening files. The zip vfs also require 'Trf' (for its 'zip' command). The vfs's currently available are: package vfs::ftp 1.0 package vfs::http 0.5 package vfs::mk4 1.6 package vfs::ns 0.5 package vfs::tar 0.9 package vfs::test 1.0 package vfs::urltype 1.0 package vfs::webdav 0.1 package vfs::zip 1.0 --------+----------------------------------------------------------------- vfs | example mount command --------+----------------------------------------------------------------- zip | vfs::zip::Mount my.zip local ftp | vfs::ftp::Mount ftp://user:pass@ftp.foo.com/dir/name/ local mk4 | vfs::mk4::Mount myMk4database local urltype | vfs::urltype::Mount ftp test | vfs::test::Mount ... --------+----------------------------------------------------------------- These are also available, but not so heavily debugged: --------+----------------------------------------------------------------- ns | vfs::ns::Mount ::tcl local webdav | vfs::webdav::Mount http://user:pass@foo.com/blah local http | vfs::http::Mount http://foo.com/blah local --------+----------------------------------------------------------------- For file-systems which make use of a local file (e.g. mounting zip or mk4 archives), it is often most simple to have 'local' be the same name as the archive itself. The result of this is that Tcl will then see the archive as a directory, rather than a file. Otherwise you might wish to create a dummy file/directory called 'local' before mounting. C versus Tcl ------------ It may be worth writing a vfs for commonly used formats like 'zip' in C. This would make it easier to create single-file executables because with this extension we have a bootstrap problem: to mount the executable (assuming it has a .zip archive appended to it) we need to have 'vfs::zip::Mount' and related procedures loaded, but this means that those procedures would have to be stored in the executable outside the zip archive, wasting space. Note: Richard Hipp has written 'zvfs' which uses the older, less-complete vfs support in Tcl 8.3. It is GNU-licensed, which makes distributing binary versions a little more complex. Also Prowrap contains a similar zip-vfs implementation using the same old APIs (it is BSD-licensed). Either of these can probably be modified to work with the new APIs quite easily. Helping! -------- Any help is much appreciated! The current code has very much _evolved_ which means it isn't necessarily even particular well thought out, so if you wish to contribute a single line of code or a complete re-write, I'd be very happy! Future thoughts --------------- See: http://developer.gnome.org/doc/API/gnome-vfs/ http://www.appwatch.com/lists/gnome-announce/2001-May/000267.html http://www.lh.com/~oleg/ftp/HTTP-VFS.html http://www.atnf.csiro.au/~rgooch/linux/vfs.txt for some ideas. It would be good to accumulate ideas on the limitations of the current VFS support so we can plan out what vfs 2.0 will look like (and what changes will be needed in Tcl's core to support it). "Asynchronicity" -- Obvious things which come to mind are asynchronicity: 'file copy' from a mounted remote site (ftp or http) is going to be very slow and simply block the application. Commands like that should have new asynchronous versions which can be used when desired (for example, 'file copy from to -callback foo' would be one approach to handling this). "exec" -- this Tcl command effectively boils down to forking off a variety of processes and hooking their input/output/errors up appropriately. Most of this code is quite generic, and ends up in 'TclpCreateProcess' for the actual forking and execution of another process (whose name is given by 'argv[0]' in TclpCreateProcess). Would it be possible to make a Tcl_FSCreateProcess which can pass the command on either to the native filesystem or to virtual filesystems? The simpler answer is "yes", given that we can simply examine 'argv[0]' and see if it is it is a path in a virtual filesystem and then hand it off appropriately, but could a vfs actually implement anything sensible? The kind of thing I'm thinking of is this: we mount an ftp site and would then like to execute various ftp commands directly. Now, we could use 'ftp::Quote' (from the ftp package) to send commands directly, but why not 'exec' them? If my ftp site is mounted at /tcl/ftppub, why couldn't "exec /tcl/ftppub FOO arg1 arg2" attempt a verbatim "FOO arg1 arg2" command on the ftp connection? (Or would perhaps "exec /tcl/ftppub/FOO arg1 arg2" be the command?). Similarly a Tcl 'namespace' filesystem could use 'exec' to evaluate code in the relevant namespace (of course you could just use 'namespace eval' directly, but then you couldn't hook the code up to input/output pipes). Debugging virtual filesystems ----------------------------- Bugs in Tcl vfs's are hard to track down, since error _messages_ can't necessarily propagate to the toplevel (errors of course do propagate and result in a filesystem action failing, but informative error messages cannot usually be provided, since Tcl is only expecting one of the standard POSIX error codes). We could add a debugging command to this extension so unexpected errors are logged somewhere. Alternatively the 'reporting' filesystem in Tcl's test suite can be used to aid debugging. tclvfs/aclocal.m4000064400000000000000000000000421447560765400136110ustar00nobodynobodybuiltin(include,tclconfig/tcl.m4) tclvfs/configure000075500000000000000000010357601447560765400137000ustar00nobodynobody#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.71 for vfs 1.4.2. # # # Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="as_nop=: if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else \$as_nop case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else \$as_nop exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else $as_nop as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else $as_nop as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else $as_nop if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_nop # --------- # Do nothing but, unlike ":", preserve the value of $?. as_fn_nop () { return $? } as_nop=as_fn_nop # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='vfs' PACKAGE_TARNAME='vfs' PACKAGE_VERSION='1.4.2' PACKAGE_STRING='vfs 1.4.2' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_STDIO_H # include #endif #ifdef HAVE_STDLIB_H # include #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_c_list= ac_subst_vars='LTLIBOBJS TCLSH_PROG VC_MANIFEST_EMBED_EXE VC_MANIFEST_EMBED_DLL RANLIB_STUB MAKE_STUB_LIB MAKE_STATIC_LIB MAKE_SHARED_LIB MAKE_LIB EGREP GREP LDFLAGS_DEFAULT CFLAGS_DEFAULT LD_LIBRARY_PATH_VAR SHLIB_CFLAGS SHLIB_LD_LIBS SHLIB_LD STLIB_LD LDFLAGS_OPTIMIZE LDFLAGS_DEBUG CFLAGS_WARNING CFLAGS_OPTIMIZE CFLAGS_DEBUG LIBOBJS RC AR STUBS_BUILD SHARED_BUILD TCL_THREADS TCL_TOP_DIR_NATIVE TCL_INCLUDES PKG_OBJECTS PKG_SOURCES RANLIB SET_MAKE CPP TCL_SHLIB_LD_LIBS TCL_LD_FLAGS TCL_EXTRA_CFLAGS TCL_DEFS TCL_LIBS CLEANFILES OBJEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG TCL_STUB_LIB_FILE TCL_LIB_SPEC TCL_LIB_FLAG TCL_LIB_FILE TCL_SRC_DIR TCL_BIN_DIR TCL_PATCH_LEVEL TCL_VERSION INSTALL_LIBRARY INSTALL_SCRIPT INSTALL_PROGRAM INSTALL_DATA INSTALL_DATA_DIR INSTALL PKG_CFLAGS PKG_LIBS PKG_INCLUDES PKG_HEADERS PKG_TCL_SOURCES PKG_STUB_OBJECTS PKG_STUB_SOURCES PKG_STUB_LIB_FILE PKG_LIB_FILE9 PKG_LIB_FILE8 PKG_LIB_FILE EXEEXT CYGPATH target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking with_tcl with_tcl8 with_tclinclude enable_threads enable_shared enable_stubs enable_64bit enable_64bit_vis enable_rpath enable_symbols ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: \`$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures vfs 1.4.2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/vfs] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of vfs 1.4.2:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-threads build with threads (default: on) --enable-shared build and link with shared libraries (default: on) --enable-stubs build and link with stub libraries. Always true for shared builds (default: on) --enable-64bit enable 64bit support (default: off) --enable-64bit-vis enable 64bit Sparc VIS support (default: off) --disable-rpath disable rpath support (default: on) --enable-symbols build with debugging symbols (default: off) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-tcl directory containing tcl configuration (tclConfig.sh) --with-tcl8 Compile for Tcl8 in Tcl9 environment --with-tclinclude directory containing the public Tcl header files Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF vfs configure 1.4.2 generated by GNU Autoconf 2.71 Copyright (C) 2021 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to run conftest.$ac_ext, and return whether this succeeded. Assumes that # executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: program exited with status $ac_status" >&5 printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext } then : ac_retval=0 else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 printf %s "checking for $2... " >&6; } if eval test \${$3+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. */ #include #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main (void) { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : eval "$3=yes" else $as_nop eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 printf "%s\n" "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by vfs $as_me 1.4.2, which was generated by GNU Autoconf 2.71. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Test code for whether the C compiler supports C89 (global declarations) ac_c_conftest_c89_globals=' /* Does the compiler advertise C89 conformance? Do not test the value of __STDC__, because some compilers set it to 0 while being otherwise adequately conformant. */ #if !defined __STDC__ # error "Compiler does not advertise C89 conformance" #endif #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7 src/conf.sh. */ struct buf { int x; }; struct buf * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not \xHH hex character constants. These do not provoke an error unfortunately, instead are silently treated as an "x". The following induces an error, until -std is added to get proper ANSI mode. Curiously \x00 != x always comes out true, for an array size at least. It is necessary to write \x00 == 0 to get something that is true only with -std. */ int osf4_cc_array ['\''\x00'\'' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) '\''x'\'' int xlc6_cc_array[FOO(a) == '\''x'\'' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, int *(*)(struct buf *, struct stat *, int), int, int);' # Test code for whether the C compiler supports C89 (body of main). ac_c_conftest_c89_main=' ok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]); ' # Test code for whether the C compiler supports C99 (global declarations) ac_c_conftest_c99_globals=' // Does the compiler advertise C99 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L # error "Compiler does not advertise C99 conformance" #endif #include extern int puts (const char *); extern int printf (const char *, ...); extern int dprintf (int, const char *, ...); extern void *malloc (size_t); // Check varargs macros. These examples are taken from C99 6.10.3.5. // dprintf is used instead of fprintf to avoid needing to declare // FILE and stderr. #define debug(...) dprintf (2, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK #error "your preprocessor is broken" #endif #if BIG_OK #else #error "your preprocessor is broken" #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\''\0'\''; ++i) continue; return 0; } // Check varargs and va_copy. static bool test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str = ""; int number = 0; float fnumber = 0; while (*format) { switch (*format++) { case '\''s'\'': // string str = va_arg (args_copy, const char *); break; case '\''d'\'': // int number = va_arg (args_copy, int); break; case '\''f'\'': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); return *str && number && fnumber; } ' # Test code for whether the C compiler supports C99 (body of main). ac_c_conftest_c99_main=' // Check bool. _Bool success = false; success |= (argc != 0); // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. success &= test_varargs ("s, d'\'' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[0] = argv[0][0]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\''x'\'' || dynamic_array[ni.number - 1] != 543); ' # Test code for whether the C compiler supports C11 (global declarations) ac_c_conftest_c11_globals=' // Does the compiler advertise C11 conformance? #if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L # error "Compiler does not advertise C11 conformance" #endif // Check _Alignas. char _Alignas (double) aligned_as_double; char _Alignas (0) no_special_alignment; extern char aligned_as_int; char _Alignas (0) _Alignas (int) aligned_as_int; // Check _Alignof. enum { int_alignment = _Alignof (int), int_array_alignment = _Alignof (int[100]), char_alignment = _Alignof (char) }; _Static_assert (0 < -_Alignof (int), "_Alignof is signed"); // Check _Noreturn. int _Noreturn does_not_return (void) { for (;;) continue; } // Check _Static_assert. struct test_static_assert { int x; _Static_assert (sizeof (int) <= sizeof (long int), "_Static_assert does not work in struct"); long int y; }; // Check UTF-8 literals. #define u8 syntax error! char const utf8_literal[] = u8"happens to be ASCII" "another string"; // Check duplicate typedefs. typedef long *long_ptr; typedef long int *long_ptr; typedef long_ptr long_ptr; // Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1. struct anonymous { union { struct { int i; int j; }; struct { int k; long int l; } w; }; int m; } v1; ' # Test code for whether the C compiler supports C11 (body of main). ac_c_conftest_c11_main=' _Static_assert ((offsetof (struct anonymous, i) == offsetof (struct anonymous, w.k)), "Anonymous union alignment botch"); v1.i = 2; v1.w.k = 5; ok |= v1.i != 5; ' # Test code for whether the C compiler supports C11 (complete). ac_c_conftest_c11_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} ${ac_c_conftest_c11_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} ${ac_c_conftest_c11_main} return ok; } " # Test code for whether the C compiler supports C99 (complete). ac_c_conftest_c99_program="${ac_c_conftest_c89_globals} ${ac_c_conftest_c99_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} ${ac_c_conftest_c99_main} return ok; } " # Test code for whether the C compiler supports C89 (complete). ac_c_conftest_c89_program="${ac_c_conftest_c89_globals} int main (int argc, char **argv) { int ok = 0; ${ac_c_conftest_c89_main} return ok; } " as_fn_append ac_header_c_list " stdio.h stdio_h HAVE_STDIO_H" as_fn_append ac_header_c_list " stdlib.h stdlib_h HAVE_STDLIB_H" as_fn_append ac_header_c_list " string.h string_h HAVE_STRING_H" as_fn_append ac_header_c_list " inttypes.h inttypes_h HAVE_INTTYPES_H" as_fn_append ac_header_c_list " stdint.h stdint_h HAVE_STDINT_H" as_fn_append ac_header_c_list " strings.h strings_h HAVE_STRINGS_H" as_fn_append ac_header_c_list " sys/stat.h sys_stat_h HAVE_SYS_STAT_H" as_fn_append ac_header_c_list " sys/types.h sys_types_h HAVE_SYS_TYPES_H" as_fn_append ac_header_c_list " unistd.h unistd_h HAVE_UNISTD_H" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: \`$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`${MAKE-make} distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_VERSION="3.13" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking TEA configuration" >&5 printf %s "checking TEA configuration... " >&6; } if test x"${PACKAGE_NAME}" = x ; then as_fn_error $? " The PACKAGE_NAME variable must be defined by your TEA configure.ac" "$LINENO" 5 fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok (TEA ${TEA_VERSION})" >&5 printf "%s\n" "ok (TEA ${TEA_VERSION})" >&6; } # If the user did not set CFLAGS, set it now to keep macros # like AC_PROG_CC and AC_TRY_COMPILE from adding "-g -O2". if test "${CFLAGS+set}" != "set" ; then CFLAGS="" fi case "`uname -s`" in *win32*|*WIN32*|*MINGW32_*|*MINGW64_*|*MSYS_*) # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CYGPATH+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 printf "%s\n" "$CYGPATH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi EXEEXT=".exe" TEA_PLATFORM="windows" ;; *CYGWIN_*) EXEEXT=".exe" # CYGPATH and TEA_PLATFORM are determined later in LOAD_TCLCONFIG ;; *) CYGPATH=echo # Maybe we are cross-compiling.... case ${host_alias} in *mingw32*) EXEEXT=".exe" TEA_PLATFORM="windows" ;; *) EXEEXT="" TEA_PLATFORM="unix" ;; esac ;; esac # Check if exec_prefix is set. If not use fall back to prefix. # Note when adjusted, so that TEA_PREFIX can correct for this. # This is needed for recursive configures, since autoconf propagates # $prefix, but not $exec_prefix (doh!). if test x$exec_prefix = xNONE ; then exec_prefix_default=yes exec_prefix=$prefix fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&5 printf "%s\n" "$as_me: configuring ${PACKAGE_NAME} ${PACKAGE_VERSION}" >&6;} # This package name must be replaced statically for AC_SUBST to work # Substitute STUB_LIB_FILE in case package creates a stub library too. # We AC_SUBST these here to ensure they are subst'ed, # in case the user doesn't call TEA_ADD_... # Configure the installer. INSTALL='$(SHELL) $(srcdir)/tclconfig/install-sh -c' INSTALL_DATA_DIR='${INSTALL} -d -m 755' INSTALL_DATA='${INSTALL} -m 644' INSTALL_PROGRAM='${INSTALL} -m 755' INSTALL_SCRIPT='${INSTALL} -m 755' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version" >&5 printf %s "checking system version... " >&6; } if test ${tcl_cv_sys_version+y} then : printf %s "(cached) " >&6 else $as_nop # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 printf "%s\n" "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 printf "%s\n" "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version case $system in HP-UX-*) INSTALL_LIBRARY='${INSTALL} -m 755' ;; *) INSTALL_LIBRARY='${INSTALL} -m 644' ;; esac # # Ok, lets find the tcl configuration # First, look for one uninstalled. # the alternative search directory is invoked by --with-tcl # if test x"${no_tcl}" = x ; then # we reset no_tcl in case something fails here no_tcl=true # Check whether --with-tcl was given. if test ${with_tcl+y} then : withval=$with_tcl; with_tclconfig="${withval}" fi # Check whether --with-tcl8 was given. if test ${with_tcl8+y} then : withval=$with_tcl8; with_tcl8="${withval}" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Tcl configuration" >&5 printf %s "checking for Tcl configuration... " >&6; } if test ${ac_cv_c_tclconfig+y} then : printf %s "(cached) " >&6 else $as_nop # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then case "${with_tclconfig}" in */tclConfig.sh ) if test -f "${with_tclconfig}"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&5 printf "%s\n" "$as_me: WARNING: --with-tcl argument should refer to directory containing tclConfig.sh, not to tclConfig.sh itself" >&2;} with_tclconfig="`echo "${with_tclconfig}" | sed 's!/tclConfig\.sh$!!'`" fi ;; esac if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd "${with_tclconfig}"; pwd)`" else as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 fi fi # then check for a private Tcl installation if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ../tcl \ `ls -dr ../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../tcl[8-9].[0-9]* 2>/dev/null` \ ../../tcl \ `ls -dr ../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../tcl[8-9].[0-9]* 2>/dev/null` \ ../../../tcl \ `ls -dr ../../../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ../../../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi # on Darwin, check in Framework installation locations if test "`uname -s`" = "Darwin" -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ~/Library/Frameworks 2>/dev/null` \ `ls -d /Library/Frameworks 2>/dev/null` \ `ls -d /Network/Library/Frameworks 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Network/Library/Frameworks/Tcl.framework 2>/dev/null` \ `ls -d /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Tcl.framework 2>/dev/null` \ ; do if test -f "$i/Tcl.framework/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/Tcl.framework; pwd)`" break fi done fi # TEA specific: on Windows, check in common installation locations if test "${TEA_PLATFORM}" = "windows" \ -a x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d C:/Tcl/lib 2>/dev/null` \ `ls -d C:/Progra~1/Tcl/lib 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few common install locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in `ls -d ${libdir} 2>/dev/null` \ `ls -d ${exec_prefix}/lib 2>/dev/null` \ `ls -d ${prefix}/lib 2>/dev/null` \ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" break fi done fi # check in a few other private locations if test x"${ac_cv_c_tclconfig}" = x ; then for i in \ ${srcdir}/../tcl \ `ls -dr ${srcdir}/../tcl[8-9].[0-9].[0-9]* 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9] 2>/dev/null` \ `ls -dr ${srcdir}/../tcl[8-9].[0-9]* 2>/dev/null` ; do if test "${TEA_PLATFORM}" = "windows" \ -a -f "$i/win/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/win; pwd)`" break fi if test -f "$i/unix/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i/unix; pwd)`" break fi done fi fi if test x"${ac_cv_c_tclconfig}" = x ; then TCL_BIN_DIR="# no Tcl configs found" as_fn_error $? "Can't find Tcl configuration definitions. Use --with-tcl to specify a directory containing tclConfig.sh" "$LINENO" 5 else no_tcl= TCL_BIN_DIR="${ac_cv_c_tclconfig}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: found ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf "%s\n" "found ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 printf %s "checking whether the C compiler works... " >&6; } ac_link_default=`printf "%s\n" "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test ${ac_cv_exeext+y} && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else $as_nop ac_file='' fi if test -z "$ac_file" then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 printf %s "checking for C compiler default output file name... " >&6; } { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 printf "%s\n" "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 printf %s "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 printf "%s\n" "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 printf %s "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 printf "%s\n" "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 printf %s "checking for suffix of object files... " >&6; } if test ${ac_cv_objext+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_nop printf "%s\n" "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 printf "%s\n" "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for existence of ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf %s "checking for existence of ${TCL_BIN_DIR}/tclConfig.sh... " >&6; } if test -f "${TCL_BIN_DIR}/tclConfig.sh" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: loading" >&5 printf "%s\n" "loading" >&6; } . "${TCL_BIN_DIR}/tclConfig.sh" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: could not find ${TCL_BIN_DIR}/tclConfig.sh" >&5 printf "%s\n" "could not find ${TCL_BIN_DIR}/tclConfig.sh" >&6; } fi # If the TCL_BIN_DIR is the build directory (not the install directory), # then set the common variable name to the value of the build variables. # For example, the variable TCL_LIB_SPEC will be set to the value # of TCL_BUILD_LIB_SPEC. An extension should make use of TCL_LIB_SPEC # instead of TCL_BUILD_LIB_SPEC since it will work with both an # installed and uninstalled version of Tcl. if test -f "${TCL_BIN_DIR}/Makefile" ; then TCL_LIB_SPEC="${TCL_BUILD_LIB_SPEC}" TCL_STUB_LIB_SPEC="${TCL_BUILD_STUB_LIB_SPEC}" TCL_STUB_LIB_PATH="${TCL_BUILD_STUB_LIB_PATH}" elif test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use the libraries # from the framework at the given location so that linking works # against Tcl.framework installed in an arbitrary location. case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -f "${TCL_BIN_DIR}/${TCL_LIB_FILE}"; then for i in "`cd "${TCL_BIN_DIR}"; pwd`" \ "`cd "${TCL_BIN_DIR}"/../..; pwd`"; do if test "`basename "$i"`" = "${TCL_LIB_FILE}.framework"; then TCL_LIB_SPEC="-F`dirname "$i" | sed -e 's/ /\\\\ /g'` -framework ${TCL_LIB_FILE}" break fi done fi if test -f "${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}"; then TCL_STUB_LIB_SPEC="-L`echo "${TCL_BIN_DIR}" | sed -e 's/ /\\\\ /g'` ${TCL_STUB_LIB_FLAG}" TCL_STUB_LIB_PATH="${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}" fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking platform" >&5 printf %s "checking platform... " >&6; } hold_cc=$CC; CC="$TCL_CC" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifdef _WIN32 #error win32 #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # first test we've already retrieved platform (cross-compile), fallback to unix otherwise: TEA_PLATFORM="${TEA_PLATFORM-unix}" CYGPATH=echo else $as_nop TEA_PLATFORM="windows" # Extract the first word of "cygpath", so it can be a program name with args. set dummy cygpath; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CYGPATH+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CYGPATH"; then ac_cv_prog_CYGPATH="$CYGPATH" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CYGPATH="cygpath -m" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_CYGPATH" && ac_cv_prog_CYGPATH="echo" fi fi CYGPATH=$ac_cv_prog_CYGPATH if test -n "$CYGPATH"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 printf "%s\n" "$CYGPATH" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CC=$hold_cc { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $TEA_PLATFORM" >&5 printf "%s\n" "$TEA_PLATFORM" >&6; } # The BUILD_$pkg is to define the correct extern storage class # handling when making this package printf "%s\n" "#define BUILD_${PACKAGE_NAME} /**/" >>confdefs.h # Do this here as we have fully defined TEA_PLATFORM now if test "${TEA_PLATFORM}" = "windows" ; then EXEEXT=".exe" CLEANFILES="$CLEANFILES *.lib *.dll *.pdb *.exp" fi # TEA specific: if test "${prefix}" = "NONE"; then prefix_default=yes if test x"${TCL_PREFIX}" != x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&5 printf "%s\n" "$as_me: --prefix defaulting to TCL_PREFIX ${TCL_PREFIX}" >&6;} prefix=${TCL_PREFIX} else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --prefix defaulting to /usr/local" >&5 printf "%s\n" "$as_me: --prefix defaulting to /usr/local" >&6;} prefix=/usr/local fi fi if test "${exec_prefix}" = "NONE" -a x"${prefix_default}" = x"yes" \ -o x"${exec_prefix_default}" = x"yes" ; then if test x"${TCL_EXEC_PREFIX}" != x; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&5 printf "%s\n" "$as_me: --exec-prefix defaulting to TCL_EXEC_PREFIX ${TCL_EXEC_PREFIX}" >&6;} exec_prefix=${TCL_EXEC_PREFIX} else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: --exec-prefix defaulting to ${prefix}" >&5 printf "%s\n" "$as_me: --exec-prefix defaulting to ${prefix}" >&6;} exec_prefix=$prefix fi fi # Don't put any macros that use the compiler (e.g. AC_TRY_COMPILE) # in this macro, they need to go into TEA_SETUP_COMPILER instead. ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then if test "$as_dir$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}clang", so it can be a program name with args. set dummy ${ac_tool_prefix}clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 printf "%s\n" "$CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "clang", so it can be a program name with args. set dummy clang; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_CC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="clang" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 printf "%s\n" "$ac_ct_CC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi fi test -z "$CC" && { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion -version; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" printf "%s\n" "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C" >&5 printf %s "checking whether the compiler supports GNU C... " >&6; } if test ${ac_cv_c_compiler_gnu+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_compiler_gnu=yes else $as_nop ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 printf "%s\n" "$ac_cv_c_compiler_gnu" >&6; } ac_compiler_gnu=$ac_cv_c_compiler_gnu if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+y} ac_save_CFLAGS=$CFLAGS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 printf %s "checking whether $CC accepts -g... " >&6; } if test ${ac_cv_prog_cc_g+y} then : printf %s "(cached) " >&6 else $as_nop ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes else $as_nop CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : else $as_nop ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 printf "%s\n" "$ac_cv_prog_cc_g" >&6; } if test $ac_test_CFLAGS; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi ac_prog_cc_stdc=no if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features" >&5 printf %s "checking for $CC option to enable C11 features... " >&6; } if test ${ac_cv_prog_cc_c11+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c11=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c11_program _ACEOF for ac_arg in '' -std=gnu11 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c11=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c11" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c11" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c11" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11" >&5 printf "%s\n" "$ac_cv_prog_cc_c11" >&6; } CC="$CC $ac_cv_prog_cc_c11" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11 ac_prog_cc_stdc=c11 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features" >&5 printf %s "checking for $CC option to enable C99 features... " >&6; } if test ${ac_cv_prog_cc_c99+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c99_program _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99= do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c99" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c99" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 printf "%s\n" "$ac_cv_prog_cc_c99" >&6; } CC="$CC $ac_cv_prog_cc_c99" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99 ac_prog_cc_stdc=c99 fi fi if test x$ac_prog_cc_stdc = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features" >&5 printf %s "checking for $CC option to enable C89 features... " >&6; } if test ${ac_cv_prog_cc_c89+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_c_conftest_c89_program _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO" then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext conftest.beam test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi if test "x$ac_cv_prog_cc_c89" = xno then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 printf "%s\n" "unsupported" >&6; } else $as_nop if test "x$ac_cv_prog_cc_c89" = x then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 printf "%s\n" "none needed" >&6; } else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 printf "%s\n" "$ac_cv_prog_cc_c89" >&6; } CC="$CC $ac_cv_prog_cc_c89" fi ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89 ac_prog_cc_stdc=c89 fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 printf %s "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if test ${ac_cv_prog_CPP+y} then : printf %s "(cached) " >&6 else $as_nop # Double quotes because $CC needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" cpp /lib/cpp do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 printf "%s\n" "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO" then : else $as_nop # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO" then : # Broken: success on invalid input. continue else $as_nop # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok then : else $as_nop { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu #-------------------------------------------------------------------- # Checks to see if the make program sets the $MAKE variable. #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 printf %s "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`printf "%s\n" "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval test \${ac_cv_prog_make_${ac_make}_set+y} then : printf %s "(cached) " >&6 else $as_nop cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } SET_MAKE= else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi #-------------------------------------------------------------------- # Find ranlib #-------------------------------------------------------------------- if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi #-------------------------------------------------------------------- # Determines the correct binary file extension (.o, .obj, .exe etc.) #-------------------------------------------------------------------- ac_header= ac_cache= for ac_item in $ac_header_c_list do if test $ac_cache; then ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then printf "%s\n" "#define $ac_item 1" >> confdefs.h fi ac_header= ac_cache= elif test $ac_header; then ac_cache=$ac_item else ac_header=$ac_item fi done if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes then : printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h fi # Any macros that use the compiler (e.g. AC_TRY_COMPILE) have to go here. #------------------------------------------------------------------------ # If we're using GCC, see if the compiler understands -pipe. If so, use it. # It makes compiling go faster. (This is only a performance feature.) #------------------------------------------------------------------------ if test -z "$no_pipe" -a -n "$GCC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 printf %s "checking if the compiler understands -pipe... " >&6; } if test ${tcl_cv_cc_pipe+y} then : printf %s "(cached) " >&6 else $as_nop hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_cc_pipe=yes else $as_nop tcl_cv_cc_pipe=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext CFLAGS=$hold_cflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 printf "%s\n" "$tcl_cv_cc_pipe" >&6; } if test $tcl_cv_cc_pipe = yes; then CFLAGS="$CFLAGS -pipe" fi fi #-------------------------------------------------------------------- # Common compiler flag setup #-------------------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 printf %s "checking whether byte ordering is bigendian... " >&6; } if test ${ac_cv_c_bigendian+y} then : printf %s "(cached) " >&6 else $as_nop ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO" then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_c_bigendian=yes else $as_nop ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ unsigned short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; unsigned short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } unsigned short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; unsigned short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main (void) { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main (void) { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO" then : ac_cv_c_bigendian=no else $as_nop ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 printf "%s\n" "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) printf "%s\n" "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) printf "%s\n" "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac vars="vfs.c" for i in $vars; do case $i in \$*) # allow $-var names PKG_SOURCES="$PKG_SOURCES $i" PKG_OBJECTS="$PKG_OBJECTS $i" ;; *) # check for existence - allows for generic/win/unix VPATH # To add more dirs here (like 'src'), you have to update VPATH # in Makefile.in as well if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find source file '$i'" "$LINENO" 5 fi PKG_SOURCES="$PKG_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_OBJECTS="$PKG_OBJECTS $j" ;; esac done vars="" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find header file '${srcdir}/$i'" "$LINENO" 5 fi PKG_HEADERS="$PKG_HEADERS $i" done vars="-I\"$(${CYGPATH} ${TCL_SRC_DIR}/generic)\"" for i in $vars; do PKG_INCLUDES="$PKG_INCLUDES $i" done vars="" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done PKG_CFLAGS="$PKG_CFLAGS " vars="" for i in $vars; do # check for existence - allows for generic/win/unix VPATH if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ -a ! -f "${srcdir}/macosx/$i" \ ; then as_fn_error $? "could not find stub source file '$i'" "$LINENO" 5 fi PKG_STUB_SOURCES="$PKG_STUB_SOURCES $i" # this assumes it is in a VPATH dir i=`basename $i` # handle user calling this before or after TEA_SETUP_COMPILER if test x"${OBJEXT}" != x ; then j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" else j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" fi PKG_STUB_OBJECTS="$PKG_STUB_OBJECTS $j" done vars="" for i in $vars; do # check for existence, be strict because it is installed if test ! -f "${srcdir}/$i" ; then as_fn_error $? "could not find tcl source file '${srcdir}/$i'" "$LINENO" 5 fi PKG_TCL_SOURCES="$PKG_TCL_SOURCES $i" done #TEA_PUBLIC_TCL_HEADERS { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Tcl public headers" >&5 printf %s "checking for Tcl public headers... " >&6; } # Check whether --with-tclinclude was given. if test ${with_tclinclude+y} then : withval=$with_tclinclude; with_tclinclude=${withval} fi if test ${ac_cv_c_tclh+y} then : printf %s "(cached) " >&6 else $as_nop # Use the value from --with-tclinclude, if it was given if test x"${with_tclinclude}" != x ; then if test -f "${with_tclinclude}/tcl.h" ; then ac_cv_c_tclh=${with_tclinclude} else as_fn_error $? "${with_tclinclude} directory does not contain tcl.h" "$LINENO" 5 fi else list="" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers directory case ${TCL_DEFS} in *TCL_FRAMEWORK*) list="`ls -d ${TCL_BIN_DIR}/Headers 2>/dev/null`" ;; esac fi # Look in the source dir only if Tcl is not installed, # and in that situation, look there before installed locations. if test -f "${TCL_BIN_DIR}/Makefile" ; then list="$list `ls -d ${TCL_SRC_DIR}/generic 2>/dev/null`" fi # Check order: pkg --prefix location, Tcl's --prefix location, # relative to directory of tclConfig.sh. eval "temp_includedir=${includedir}" list="$list \ `ls -d ${temp_includedir} 2>/dev/null` \ `ls -d ${TCL_PREFIX}/include 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/../include 2>/dev/null`" if test "${TEA_PLATFORM}" != "windows" -o "$GCC" = "yes"; then list="$list /usr/local/include /usr/include" if test x"${TCL_INCLUDE_SPEC}" != x ; then d=`echo "${TCL_INCLUDE_SPEC}" | sed -e 's/^-I//'` list="$list `ls -d ${d} 2>/dev/null`" fi fi for i in $list ; do if test -f "$i/tcl.h" ; then ac_cv_c_tclh=$i break fi done fi fi # Print a message based on how we determined the include path if test x"${ac_cv_c_tclh}" = x ; then as_fn_error $? "tcl.h not found. Please specify its location with --with-tclinclude" "$LINENO" 5 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${ac_cv_c_tclh}" >&5 printf "%s\n" "${ac_cv_c_tclh}" >&6; } fi # Convert to a native path and substitute into the output files. INCLUDE_DIR_NATIVE=`${CYGPATH} ${ac_cv_c_tclh}` TCL_INCLUDES=-I\"${INCLUDE_DIR_NATIVE}\" # Allow for --with-tclinclude to take effect and define ${ac_cv_c_tclh} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for Tcl private include files" >&5 printf %s "checking for Tcl private include files... " >&6; } TCL_SRC_DIR_NATIVE=`${CYGPATH} ${TCL_SRC_DIR}` TCL_TOP_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}\" # Check to see if tclPort.h isn't already with the public headers # Don't look for tclInt.h because that resides with tcl.h in the core # sources, but the Port headers are in a different directory if test "${TEA_PLATFORM}" = "windows" -a \ -f "${ac_cv_c_tclh}/tclWinPort.h"; then result="private headers found with public headers" elif test "${TEA_PLATFORM}" = "unix" -a \ -f "${ac_cv_c_tclh}/tclUnixPort.h"; then result="private headers found with public headers" else TCL_GENERIC_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/generic\" if test "${TEA_PLATFORM}" = "windows"; then TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/win\" else TCL_PLATFORM_DIR_NATIVE=\"${TCL_SRC_DIR_NATIVE}/unix\" fi # Overwrite the previous TCL_INCLUDES as this should capture both # public and private headers in the same set. # We want to ensure these are substituted so as not to require # any *_NATIVE vars be defined in the Makefile TCL_INCLUDES="-I${TCL_GENERIC_DIR_NATIVE} -I${TCL_PLATFORM_DIR_NATIVE}" if test "`uname -s`" = "Darwin"; then # If Tcl was built as a framework, attempt to use # the framework's Headers and PrivateHeaders directories case ${TCL_DEFS} in *TCL_FRAMEWORK*) if test -d "${TCL_BIN_DIR}/Headers" -a \ -d "${TCL_BIN_DIR}/PrivateHeaders"; then TCL_INCLUDES="-I\"${TCL_BIN_DIR}/Headers\" -I\"${TCL_BIN_DIR}/PrivateHeaders\" ${TCL_INCLUDES}" else TCL_INCLUDES="${TCL_INCLUDES} ${TCL_INCLUDE_SPEC} `echo "${TCL_INCLUDE_SPEC}" | sed -e 's/Headers/PrivateHeaders/'`" fi ;; esac result="Using ${TCL_INCLUDES}" else if test ! -f "${TCL_SRC_DIR}/generic/tclInt.h" ; then as_fn_error $? "Cannot find private header tclInt.h in ${TCL_SRC_DIR}" "$LINENO" 5 fi result="Using srcdir found in tclConfig.sh: ${TCL_SRC_DIR}" fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${result}" >&5 printf "%s\n" "${result}" >&6; } #-------------------------------------------------------------------- # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_VFS in this case) so # that we create the export library with the dll. See sha1.h on how # to use this. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # Define any extra compiler flags in the PACKAGE_CFLAGS variable. # These will be appended to the current set of compiler flags for # your system. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" ; then printf "%s\n" "#define BUILD_vfs 1" >>confdefs.h CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch" else CLEANFILES="pkgIndex.tcl" fi # Check whether --enable-threads was given. if test ${enable_threads+y} then : enableval=$enable_threads; tcl_ok=$enableval else $as_nop tcl_ok=yes fi if test "${enable_threads+set}" = set; then enableval="$enable_threads" tcl_ok=$enableval else tcl_ok=yes fi if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then TCL_THREADS=1 if test "${TEA_PLATFORM}" != "windows" ; then # We are always OK on Windows, so check what this platform wants: # USE_THREAD_ALLOC tells us to try the special thread-based # allocator that significantly reduces lock contention printf "%s\n" "#define USE_THREAD_ALLOC 1" >>confdefs.h printf "%s\n" "#define _REENTRANT 1" >>confdefs.h if test "`uname -s`" = "SunOS" ; then printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h fi printf "%s\n" "#define _THREAD_SAFE 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 printf %s "checking for pthread_mutex_init in -lpthread... " >&6; } if test ${ac_cv_lib_pthread_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pthread_mutex_init (); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pthread_pthread_mutex_init=yes else $as_nop ac_cv_lib_pthread_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi if test "$tcl_ok" = "no"; then # Check a little harder for __pthread_mutex_init in the same # library, as some systems hide it there until pthread.h is # defined. We could alternatively do an AC_TRY_COMPILE with # pthread.h, but that will work with libpthread really doesn't # exist, like AIX 4.2. [Bug: 4359] { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 printf %s "checking for __pthread_mutex_init in -lpthread... " >&6; } if test ${ac_cv_lib_pthread___pthread_mutex_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpthread $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char __pthread_mutex_init (); int main (void) { return __pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pthread___pthread_mutex_init=yes else $as_nop ac_cv_lib_pthread___pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthread" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 printf %s "checking for pthread_mutex_init in -lpthreads... " >&6; } if test ${ac_cv_lib_pthreads_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lpthreads $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pthread_mutex_init (); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_pthreads_pthread_mutex_init=yes else $as_nop ac_cv_lib_pthreads_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -lpthreads" else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 printf %s "checking for pthread_mutex_init in -lc... " >&6; } if test ${ac_cv_lib_c_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pthread_mutex_init (); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_c_pthread_mutex_init=yes else $as_nop ac_cv_lib_c_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_c_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi if test "$tcl_ok" = "no"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 printf %s "checking for pthread_mutex_init in -lc_r... " >&6; } if test ${ac_cv_lib_c_r_pthread_mutex_init+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lc_r $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char pthread_mutex_init (); int main (void) { return pthread_mutex_init (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_c_r_pthread_mutex_init=yes else $as_nop ac_cv_lib_c_r_pthread_mutex_init=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 printf "%s\n" "$ac_cv_lib_c_r_pthread_mutex_init" >&6; } if test "x$ac_cv_lib_c_r_pthread_mutex_init" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi if test "$tcl_ok" = "yes"; then # The space is needed THREADS_LIBS=" -pthread" else TCL_THREADS=0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&5 printf "%s\n" "$as_me: WARNING: Do not know how to find pthread lib on your system - thread support disabled" >&2;} fi fi fi fi fi else TCL_THREADS=0 fi # Do checking message here to not mess up interleaved configure output { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 printf %s "checking for building with threads... " >&6; } if test "${TCL_THREADS}" = 1; then printf "%s\n" "#define TCL_THREADS 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (default)" >&5 printf "%s\n" "yes (default)" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi # TCL_THREADS sanity checking. See if our request for building with # threads is the same as the way Tcl was built. If not, warn the user. case ${TCL_DEFS} in *THREADS=1*) if test "${TCL_THREADS}" = "0"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&5 printf "%s\n" "$as_me: WARNING: Building ${PACKAGE_NAME} without threads enabled, but building against Tcl that IS thread-enabled. It is recommended to use --enable-threads." >&2;} fi ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 printf %s "checking how to build libraries... " >&6; } # Check whether --enable-shared was given. if test ${enable_shared+y} then : enableval=$enable_shared; shared_ok=$enableval else $as_nop shared_ok=yes fi if test "${enable_shared+set}" = set; then enableval="$enable_shared" shared_ok=$enableval else shared_ok=yes fi # Check whether --enable-stubs was given. if test ${enable_stubs+y} then : enableval=$enable_stubs; stubs_ok=$enableval else $as_nop stubs_ok=yes fi if test "${enable_stubs+set}" = set; then enableval="$enable_stubs" stubs_ok=$enableval else stubs_ok=yes fi # Stubs are always enabled for shared builds if test "$shared_ok" = "yes" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: shared" >&5 printf "%s\n" "shared" >&6; } SHARED_BUILD=1 STUBS_BUILD=1 else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: static" >&5 printf "%s\n" "static" >&6; } SHARED_BUILD=0 printf "%s\n" "#define STATIC_BUILD 1" >>confdefs.h if test "$stubs_ok" = "yes" ; then STUBS_BUILD=1 else STUBS_BUILD=0 fi fi if test "${STUBS_BUILD}" = "1" ; then printf "%s\n" "#define USE_TCL_STUBS 1" >>confdefs.h printf "%s\n" "#define USE_TCLOO_STUBS 1" >>confdefs.h if test "${TEA_WINDOWINGSYSTEM}" != ""; then printf "%s\n" "#define USE_TK_STUBS 1" >>confdefs.h fi fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 printf "%s\n" "$RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RANLIB+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 printf "%s\n" "$ac_ct_RANLIB" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi # Step 0.a: Enable 64 bit support? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 printf %s "checking if 64bit support is requested... " >&6; } # Check whether --enable-64bit was given. if test ${enable_64bit+y} then : enableval=$enable_64bit; do64bit=$enableval else $as_nop do64bit=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 printf "%s\n" "$do64bit" >&6; } # Step 0.b: Enable Solaris 64 bit VIS support? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 printf %s "checking if 64bit Sparc VIS support is requested... " >&6; } # Check whether --enable-64bit-vis was given. if test ${enable_64bit_vis+y} then : enableval=$enable_64bit_vis; do64bitVIS=$enableval else $as_nop do64bitVIS=no fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 printf "%s\n" "$do64bitVIS" >&6; } # Force 64bit on with VIS if test "$do64bitVIS" = "yes" then : do64bit=yes fi # Step 0.c: Check if visibility support is available. Do this here so # that platform specific alternatives can be used below if this fails. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 printf %s "checking if compiler supports visibility \"hidden\"... " >&6; } if test ${tcl_cv_cc_visibility_hidden+y} then : printf %s "(cached) " >&6 else $as_nop hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -Werror" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ extern __attribute__((__visibility__("hidden"))) void f(void); void f(void) {} int main (void) { f(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_visibility_hidden=yes else $as_nop tcl_cv_cc_visibility_hidden=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 printf "%s\n" "$tcl_cv_cc_visibility_hidden" >&6; } if test $tcl_cv_cc_visibility_hidden = yes then : printf "%s\n" "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h printf "%s\n" "#define HAVE_HIDDEN 1" >>confdefs.h fi # Step 0.d: Disable -rpath support? { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 printf %s "checking if rpath support is requested... " >&6; } # Check whether --enable-rpath was given. if test ${enable_rpath+y} then : enableval=$enable_rpath; doRpath=$enableval else $as_nop doRpath=yes fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 printf "%s\n" "$doRpath" >&6; } # Set the variable "system" to hold the name and version number # for the system. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking system version" >&5 printf %s "checking system version... " >&6; } if test ${tcl_cv_sys_version+y} then : printf %s "(cached) " >&6 else $as_nop # TEA specific: if test "${TEA_PLATFORM}" = "windows" ; then tcl_cv_sys_version=windows else tcl_cv_sys_version=`uname -s`-`uname -r` if test "$?" -ne 0 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 printf "%s\n" "$as_me: WARNING: can't find uname command" >&2;} tcl_cv_sys_version=unknown else if test "`uname -s`" = "AIX" ; then tcl_cv_sys_version=AIX-`uname -v`.`uname -r` fi if test "`uname -s`" = "NetBSD" -a -f /etc/debian_version ; then tcl_cv_sys_version=NetBSD-Debian fi fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 printf "%s\n" "$tcl_cv_sys_version" >&6; } system=$tcl_cv_sys_version # Require ranlib early so we can override it in special cases below. # Set configuration options based on system name and version. # This is similar to Tcl's unix/tcl.m4 except that we've added a # "windows" case and removed some core-only vars. do64bit_ok=no # default to '{$LIBS}' and set to "" on per-platform necessary basis SHLIB_LD_LIBS='${LIBS}' # When ld needs options to work in 64-bit mode, put them in # LDFLAGS_ARCH so they eventually end up in LDFLAGS even if [load] # is disabled by the user. [Bug 1016796] LDFLAGS_ARCH="" UNSHARED_LIB_SUFFIX="" # TEA specific: use PACKAGE_VERSION instead of VERSION TCL_TRIM_DOTS='`echo ${PACKAGE_VERSION} | tr -d .`' ECHO_VERSION='`echo ${PACKAGE_VERSION}`' TCL_LIB_VERSIONS_OK=ok CFLAGS_DEBUG=-g if test "$GCC" = yes then : CFLAGS_OPTIMIZE=-O2 CFLAGS_WARNING="-Wall" else $as_nop CFLAGS_OPTIMIZE=-O CFLAGS_WARNING="" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_AR="${ac_tool_prefix}ar" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 printf "%s\n" "$AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_AR+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="ar" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 printf "%s\n" "$ac_ct_AR" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi STLIB_LD='${AR} cr' LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH" if test "x$SHLIB_VERSION" = x then : SHLIB_VERSION="" else $as_nop SHLIB_VERSION=".$SHLIB_VERSION" fi case $system in # TEA specific: windows) MACHINE="X86" if test "$do64bit" != "no" ; then case "$do64bit" in amd64|x64|yes) MACHINE="AMD64" ; # default to AMD64 64-bit build ;; arm64|aarch64) MACHINE="ARM64" ;; ia64) MACHINE="IA64" ;; esac fi if test "$GCC" != "yes" ; then if test "${SHARED_BUILD}" = "0" ; then runtime=-MT else runtime=-MD fi case "x`echo \${VisualStudioVersion}`" in x1[4-9]*) lflags="${lflags} -nodefaultlib:libucrt.lib" vars="ucrt.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done ;; *) ;; esac if test "$do64bit" != "no" ; then CC="cl.exe" RC="rc.exe" lflags="${lflags} -nologo -MACHINE:${MACHINE} " LINKBIN="link.exe" CFLAGS_DEBUG="-nologo -Zi -Od -W3 ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" # Avoid 'unresolved external symbol __security_cookie' # errors, c.f. http://support.microsoft.com/?id=894573 vars="bufferoverflowU.lib" for i in $vars; do if test "${TEA_PLATFORM}" = "windows" -a "$GCC" = "yes" ; then # Convert foo.lib to -lfoo for GCC. No-op if not *.lib i=`echo "$i" | sed -e 's/^\([^-].*\)\.[lL][iI][bB]$/-l\1/'` fi PKG_LIBS="$PKG_LIBS $i" done else RC="rc" lflags="${lflags} -nologo" LINKBIN="link" CFLAGS_DEBUG="-nologo -Z7 -Od -W3 -WX ${runtime}d" CFLAGS_OPTIMIZE="-nologo -O2 -W2 ${runtime}" fi fi if test "$GCC" = "yes"; then # mingw gcc mode if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}windres", so it can be a program name with args. set dummy ${ac_tool_prefix}windres; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_RC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$RC"; then ac_cv_prog_RC="$RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_RC="${ac_tool_prefix}windres" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RC=$ac_cv_prog_RC if test -n "$RC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $RC" >&5 printf "%s\n" "$RC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_prog_RC"; then ac_ct_RC=$RC # Extract the first word of "windres", so it can be a program name with args. set dummy windres; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_ac_ct_RC+y} then : printf %s "(cached) " >&6 else $as_nop if test -n "$ac_ct_RC"; then ac_cv_prog_ac_ct_RC="$ac_ct_RC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RC="windres" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RC=$ac_cv_prog_ac_ct_RC if test -n "$ac_ct_RC"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RC" >&5 printf "%s\n" "$ac_ct_RC" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_ct_RC" = x; then RC="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RC=$ac_ct_RC fi else RC="$ac_cv_prog_RC" fi CFLAGS_DEBUG="-g" CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" SHLIB_LD='${CC} -shared' UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' LDFLAGS_CONSOLE="-wl,--subsystem,console ${lflags}" LDFLAGS_WINDOW="-wl,--subsystem,windows ${lflags}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 printf %s "checking for cross-compile version of gcc... " >&6; } if test ${ac_cv_cross+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef _WIN32 #error cross-compiler #endif int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : ac_cv_cross=yes else $as_nop ac_cv_cross=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 printf "%s\n" "$ac_cv_cross" >&6; } if test "$ac_cv_cross" = "yes"; then case "$do64bit" in amd64|x64|yes) CC="x86_64-w64-mingw32-${CC}" LD="x86_64-w64-mingw32-ld" AR="x86_64-w64-mingw32-ar" RANLIB="x86_64-w64-mingw32-ranlib" RC="x86_64-w64-mingw32-windres" ;; arm64|aarch64) CC="aarch64-w64-mingw32-clang" LD="aarch64-w64-mingw32-ld" AR="aarch64-w64-mingw32-ar" RANLIB="aarch64-w64-mingw32-ranlib" RC="aarch64-w64-mingw32-windres" ;; *) CC="i686-w64-mingw32-${CC}" LD="i686-w64-mingw32-ld" AR="i686-w64-mingw32-ar" RANLIB="i686-w64-mingw32-ranlib" RC="i686-w64-mingw32-windres" ;; esac fi else SHLIB_LD="${LINKBIN} -dll ${lflags}" # link -lib only works when -lib is the first arg STLIB_LD="${LINKBIN} -lib ${lflags}" UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.lib' PATHTYPE=-w # For information on what debugtype is most useful, see: # http://msdn.microsoft.com/library/en-us/dnvc60/html/gendepdebug.asp # and also # http://msdn2.microsoft.com/en-us/library/y0zzbyt4%28VS.80%29.aspx # This essentially turns it all on. LDFLAGS_DEBUG="-debug -debugtype:cv" LDFLAGS_OPTIMIZE="-release" LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" fi SHLIB_SUFFIX=".dll" SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.dll' TCL_LIB_VERSIONS_OK=nodots ;; AIX-*) if test "$GCC" != "yes" then : # AIX requires the _r compiler when gcc isn't being used case "${CC}" in *_r|*_r\ *) # ok ... ;; *) # Make sure only first arg gets _r CC=`echo "$CC" | sed -e 's/^\([^ ]*\)/\1_r/'` ;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 printf "%s\n" "Using $CC for compiling with threads" >&6; } fi LIBS="$LIBS -lc" SHLIB_CFLAGS="" SHLIB_SUFFIX=".so" LD_LIBRARY_PATH_VAR="LIBPATH" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes then : if test "$GCC" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} else $as_nop do64bit_ok=yes CFLAGS="$CFLAGS -q64" LDFLAGS_ARCH="-q64" RANLIB="${RANLIB} -X64" AR="${AR} -X64" SHLIB_LD_FLAGS="-b64" fi fi if test "`uname -m`" = ia64 then : # AIX-5 uses ELF style dynamic libraries on IA-64, but not PPC SHLIB_LD="/usr/ccs/bin/ld -G -z text" if test "$GCC" = yes then : CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' else $as_nop CC_SEARCH_FLAGS='"-R${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' else $as_nop if test "$GCC" = yes then : SHLIB_LD='${CC} -shared -Wl,-bexpall' else $as_nop SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" LDFLAGS="$LDFLAGS -brtl" fi SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" CC_SEARCH_FLAGS='"-L${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; BeOS*) SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} -nostart' SHLIB_SUFFIX=".so" #----------------------------------------------------------- # Check for inet_ntoa in -lbind, for BeOS (which also needs # -lsocket, even if the network functions are in -lnet which # is always linked to, for compatibility. #----------------------------------------------------------- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 printf %s "checking for inet_ntoa in -lbind... " >&6; } if test ${ac_cv_lib_bind_inet_ntoa+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lbind $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char inet_ntoa (); int main (void) { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_bind_inet_ntoa=yes else $as_nop ac_cv_lib_bind_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_bind_inet_ntoa" >&6; } if test "x$ac_cv_lib_bind_inet_ntoa" = xyes then : LIBS="$LIBS -lbind -lsocket" fi ;; BSD/OS-2.1*|BSD/OS-3*) SHLIB_CFLAGS="" SHLIB_LD="shlicc -r" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; BSD/OS-4.*) SHLIB_CFLAGS="-export-dynamic -fPIC" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; CYGWIN_*) SHLIB_CFLAGS="" SHLIB_LD='${CC} -shared' SHLIB_SUFFIX=".dll" SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -Wl,--out-implib,\$@.a" EXEEXT=".exe" do64bit_ok=yes CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; dgux*) SHLIB_CFLAGS="-K PIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; Haiku*) LDFLAGS="$LDFLAGS -Wl,--export-dynamic" SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS} -shared' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 printf %s "checking for inet_ntoa in -lnetwork... " >&6; } if test ${ac_cv_lib_network_inet_ntoa+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-lnetwork $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char inet_ntoa (); int main (void) { return inet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_network_inet_ntoa=yes else $as_nop ac_cv_lib_network_inet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 printf "%s\n" "$ac_cv_lib_network_inet_ntoa" >&6; } if test "x$ac_cv_lib_network_inet_ntoa" = xyes then : LIBS="$LIBS -lnetwork" fi ;; HP-UX-*.11.*) # Use updated header definitions where possible printf "%s\n" "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h # TEA specific: Needed by Tcl, but not most extensions #AC_DEFINE(_XOPEN_SOURCE, 1, [Do we want to use the XOPEN network library?]) #LIBS="$LIBS -lxnet" # Use the XOPEN network library if test "`uname -m`" = ia64 then : SHLIB_SUFFIX=".so" else $as_nop SHLIB_SUFFIX=".sl" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char shl_load (); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else $as_nop ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi if test "$tcl_ok" = yes then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi if test "$GCC" = yes then : SHLIB_LD='${CC} -shared' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else $as_nop CFLAGS="$CFLAGS -z" fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = "yes" then : if test "$GCC" = yes then : case `${CC} -dumpmachine` in hppa64*) # 64-bit gcc in use. Fix flags for GNU ld. do64bit_ok=yes SHLIB_LD='${CC} -shared' if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} ;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} ;; esac else $as_nop do64bit_ok=yes CFLAGS="$CFLAGS +DD64" LDFLAGS_ARCH="+DD64" fi fi ;; HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) SHLIB_SUFFIX=".sl" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 printf %s "checking for shl_load in -ldld... " >&6; } if test ${ac_cv_lib_dld_shl_load+y} then : printf %s "(cached) " >&6 else $as_nop ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ char shl_load (); int main (void) { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : ac_cv_lib_dld_shl_load=yes else $as_nop ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 printf "%s\n" "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes then : tcl_ok=yes else $as_nop tcl_ok=no fi if test "$tcl_ok" = yes then : SHLIB_CFLAGS="+z" SHLIB_LD="ld -b" SHLIB_LD_LIBS="" LDFLAGS="$LDFLAGS -Wl,-E" CC_SEARCH_FLAGS='"-Wl,+s,+b,${LIB_RUNTIME_DIR}:."' LD_SEARCH_FLAGS='+s +b "${LIB_RUNTIME_DIR}:."' LD_LIBRARY_PATH_VAR="SHLIB_PATH" fi ;; IRIX-5.*) SHLIB_CFLAGS="" SHLIB_LD="ld -shared -rdata_shared" SHLIB_SUFFIX=".so" case " $LIBOBJS " in *" mkstemp.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mkstemp.$ac_objext" ;; esac if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi ;; IRIX-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi if test "$GCC" = yes then : CFLAGS="$CFLAGS -mabi=n32" LDFLAGS="$LDFLAGS -mabi=n32" else $as_nop case $system in IRIX-6.3) # Use to build 6.2 compatible binaries on 6.3. CFLAGS="$CFLAGS -n32 -D_OLD_TERMIOS" ;; *) CFLAGS="$CFLAGS -n32" ;; esac LDFLAGS="$LDFLAGS -n32" fi ;; IRIX64-6.*) SHLIB_CFLAGS="" SHLIB_LD="ld -n32 -shared -rdata_shared" SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath "${LIB_RUNTIME_DIR}"' fi # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes then : if test "$GCC" = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} else $as_nop do64bit_ok=yes SHLIB_LD="ld -64 -shared -rdata_shared" CFLAGS="$CFLAGS -64" LDFLAGS_ARCH="-64" fi fi ;; Linux*|GNU*|NetBSD-Debian|DragonFly-*|FreeBSD-*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" # TEA specific: CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} ${CFLAGS} ${LDFLAGS_DEFAULT} -shared' LDFLAGS="$LDFLAGS -Wl,--export-dynamic" case $system in DragonFly-*|FreeBSD-*) if test "${TCL_THREADS}" = "1" then : # The -pthread needs to go in the LDFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LDFLAGS="$LDFLAGS $PTHREAD_LIBS" fi ;; esac if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "`uname -m`" = "alpha" then : CFLAGS="$CFLAGS -mieee" fi if test $do64bit = yes then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 printf %s "checking if compiler accepts -m64 flag... " >&6; } if test ${tcl_cv_cc_m64+y} then : printf %s "(cached) " >&6 else $as_nop hold_cflags=$CFLAGS CFLAGS="$CFLAGS -m64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_m64=yes else $as_nop tcl_cv_cc_m64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 printf "%s\n" "$tcl_cv_cc_m64" >&6; } if test $tcl_cv_cc_m64 = yes then : CFLAGS="$CFLAGS -m64" do64bit_ok=yes fi fi # The combo of gcc + glibc has a bug related to inlining of # functions like strtod(). The -fno-builtin flag should address # this problem but it does not work. The -fno-inline flag is kind # of overkill but it works. Disable inlining only when one of the # files in compat/*.c is being linked in. if test x"${USE_COMPAT}" != x then : CFLAGS="$CFLAGS -fno-inline" fi ;; Lynx*) SHLIB_CFLAGS="-fPIC" SHLIB_SUFFIX=".so" CFLAGS_OPTIMIZE=-02 SHLIB_LD='${CC} -shared' LD_FLAGS="-Wl,--export-dynamic" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi ;; OpenBSD-*) arch=`arch -s` case "$arch" in alpha|sparc64) SHLIB_CFLAGS="-fPIC" ;; *) SHLIB_CFLAGS="-fpic" ;; esac SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so${SHLIB_VERSION}' LDFLAGS="$LDFLAGS -Wl,-export-dynamic" CFLAGS_OPTIMIZE="-O2" # On OpenBSD: Compile with -pthread # Don't link with -lpthread LIBS=`echo $LIBS | sed s/-lpthread//` CFLAGS="$CFLAGS -pthread" # OpenBSD doesn't do version numbers with dots. UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' TCL_LIB_VERSIONS_OK=nodots ;; NetBSD-*) # NetBSD has ELF and can use 'cc -shared' to build shared libs SHLIB_CFLAGS="-fPIC" SHLIB_LD='${CC} ${SHLIB_CFLAGS} -shared' SHLIB_SUFFIX=".so" LDFLAGS="$LDFLAGS -export-dynamic" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' fi LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} # The -pthread needs to go in the CFLAGS, not LIBS LIBS=`echo $LIBS | sed s/-pthread//` CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" ;; Darwin-*) CFLAGS_OPTIMIZE="-Os" SHLIB_CFLAGS="-fno-common" # To avoid discrepancies between what headers configure sees during # preprocessing tests and compiling tests, move any -isysroot and # -mmacosx-version-min flags from CFLAGS to CPPFLAGS: CPPFLAGS="${CPPFLAGS} `echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if ($i~/^(isysroot|mmacosx-version-min)/) print "-"$i}'`" CFLAGS="`echo " ${CFLAGS}" | \ awk 'BEGIN {FS=" +-";ORS=" "}; {for (i=2;i<=NF;i++) \ if (!($i~/^(isysroot|mmacosx-version-min)/)) print "-"$i}'`" if test $do64bit = yes then : case `arch` in ppc) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 printf %s "checking if compiler accepts -arch ppc64 flag... " >&6; } if test ${tcl_cv_cc_arch_ppc64+y} then : printf %s "(cached) " >&6 else $as_nop hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_arch_ppc64=yes else $as_nop tcl_cv_cc_arch_ppc64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 printf "%s\n" "$tcl_cv_cc_arch_ppc64" >&6; } if test $tcl_cv_cc_arch_ppc64 = yes then : CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" do64bit_ok=yes fi;; i386) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 printf %s "checking if compiler accepts -arch x86_64 flag... " >&6; } if test ${tcl_cv_cc_arch_x86_64+y} then : printf %s "(cached) " >&6 else $as_nop hold_cflags=$CFLAGS CFLAGS="$CFLAGS -arch x86_64" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_cc_arch_x86_64=yes else $as_nop tcl_cv_cc_arch_x86_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext CFLAGS=$hold_cflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 printf "%s\n" "$tcl_cv_cc_arch_x86_64" >&6; } if test $tcl_cv_cc_arch_x86_64 = yes then : CFLAGS="$CFLAGS -arch x86_64" do64bit_ok=yes fi;; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 printf "%s\n" "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; esac else $as_nop # Check for combined 32-bit and 64-bit fat build if echo "$CFLAGS " |grep -E -q -- '-arch (ppc64|x86_64) ' \ && echo "$CFLAGS " |grep -E -q -- '-arch (ppc|i386) ' then : fat_32_64=yes fi fi # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS_DEFAULT}' { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 printf %s "checking if ld accepts -single_module flag... " >&6; } if test ${tcl_cv_ld_single_module+y} then : printf %s "(cached) " >&6 else $as_nop hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_ld_single_module=yes else $as_nop tcl_cv_ld_single_module=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 printf "%s\n" "$tcl_cv_ld_single_module" >&6; } if test $tcl_cv_ld_single_module = yes then : SHLIB_LD="${SHLIB_LD} -Wl,-single_module" fi # TEA specific: link shlib with current and compatibility version flags vers=`echo ${PACKAGE_VERSION} | sed -e 's/^\([0-9]\{1,5\}\)\(\(\.[0-9]\{1,3\}\)\{0,2\}\).*$/\1\2/p' -e d` SHLIB_LD="${SHLIB_LD} -current_version ${vers:-0} -compatibility_version ${vers:-0}" SHLIB_SUFFIX=".dylib" LDFLAGS="$LDFLAGS -headerpad_max_install_names" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 printf %s "checking if ld accepts -search_paths_first flag... " >&6; } if test ${tcl_cv_ld_search_paths_first+y} then : printf %s "(cached) " >&6 else $as_nop hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-search_paths_first" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_ld_search_paths_first=yes else $as_nop tcl_cv_ld_search_paths_first=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 printf "%s\n" "$tcl_cv_ld_search_paths_first" >&6; } if test $tcl_cv_ld_search_paths_first = yes then : LDFLAGS="$LDFLAGS -Wl,-search_paths_first" fi if test "$tcl_cv_cc_visibility_hidden" != yes then : printf "%s\n" "#define MODULE_SCOPE __private_extern__" >>confdefs.h tcl_cv_cc_visibility_hidden=yes fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" # TEA specific: for combined 32 & 64 bit fat builds of Tk # extensions, verify that 64-bit build is possible. if test "$fat_32_64" = yes && test -n "${TK_BIN_DIR}" then : if test "${TEA_WINDOWINGSYSTEM}" = x11 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit X11" >&5 printf %s "checking for 64-bit X11... " >&6; } if test ${tcl_cv_lib_x11_64+y} then : printf %s "(cached) " >&6 else $as_nop for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -I/usr/X11R6/include" LDFLAGS="$LDFLAGS -L/usr/X11R6/lib -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { XrmInitialize(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_lib_x11_64=yes else $as_nop tcl_cv_lib_x11_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_x11_64" >&5 printf "%s\n" "$tcl_cv_lib_x11_64" >&6; } fi if test "${TEA_WINDOWINGSYSTEM}" = aqua then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit Tk" >&5 printf %s "checking for 64-bit Tk... " >&6; } if test ${tcl_cv_lib_tk_64+y} then : printf %s "(cached) " >&6 else $as_nop for v in CFLAGS CPPFLAGS LDFLAGS; do eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc / /g" -e "s/-arch i386 / /g"`"' done CPPFLAGS="$CPPFLAGS -DUSE_TCL_STUBS=1 -DUSE_TK_STUBS=1 ${TCL_INCLUDES} ${TK_INCLUDES}" LDFLAGS="$LDFLAGS ${TCL_STUB_LIB_SPEC} ${TK_STUB_LIB_SPEC}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { Tk_InitStubs(NULL, "", 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_lib_tk_64=yes else $as_nop tcl_cv_lib_tk_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="$hold_'$v'"' done fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_tk_64" >&5 printf "%s\n" "$tcl_cv_lib_tk_64" >&6; } fi # remove 64-bit arch flags from CFLAGS et al. if configuration # does not support 64-bit. if test "$tcl_cv_lib_tk_64" = no -o "$tcl_cv_lib_x11_64" = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: Removing 64-bit architectures from compiler & linker flags" >&5 printf "%s\n" "$as_me: Removing 64-bit architectures from compiler & linker flags" >&6;} for v in CFLAGS CPPFLAGS LDFLAGS; do eval $v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' done fi fi ;; OS/390-*) CFLAGS_OPTIMIZE="" # Optimizer is buggy printf "%s\n" "#define _OE_SOCKETS 1" >>confdefs.h ;; OSF1-V*) # Digital OSF/1 SHLIB_CFLAGS="" if test "$SHARED_BUILD" = 1 then : SHLIB_LD='ld -shared -expect_unresolved "*"' else $as_nop SHLIB_LD='ld -non_shared -expect_unresolved "*"' fi SHLIB_SUFFIX=".so" if test $doRpath = yes then : CC_SEARCH_FLAGS='"-Wl,-rpath,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-rpath ${LIB_RUNTIME_DIR}' fi if test "$GCC" = yes then : CFLAGS="$CFLAGS -mieee" else $as_nop CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" fi # see pthread_intro(3) for pthread support on osf1, k.furukawa CFLAGS="$CFLAGS -DHAVE_PTHREAD_ATTR_SETSTACKSIZE" CFLAGS="$CFLAGS -DTCL_THREAD_STACK_MIN=PTHREAD_STACK_MIN*64" LIBS=`echo $LIBS | sed s/-lpthreads//` if test "$GCC" = yes then : LIBS="$LIBS -lpthread -lmach -lexc" else $as_nop CFLAGS="$CFLAGS -pthread" LDFLAGS="$LDFLAGS -pthread" fi ;; QNX-6*) # QNX RTP # This may work for all QNX, but it was only reported for v6. SHLIB_CFLAGS="-fPIC" SHLIB_LD="ld -Bshareable -x" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SCO_SV-3.2*) if test "$GCC" = yes then : SHLIB_CFLAGS="-fPIC -melf" LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" else $as_nop SHLIB_CFLAGS="-Kpic -belf" LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" fi SHLIB_LD="ld -G" SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; SunOS-5.[0-6]) # Careful to not let 5.10+ fall into this case # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. printf "%s\n" "#define _REENTRANT 1" >>confdefs.h printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" SHLIB_SUFFIX=".so" if test "$GCC" = yes then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} else $as_nop SHLIB_LD="/usr/ccs/bin/ld -G -z text" CC_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} fi ;; SunOS-5*) # Note: If _REENTRANT isn't defined, then Solaris # won't define thread-safe library routines. printf "%s\n" "#define _REENTRANT 1" >>confdefs.h printf "%s\n" "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h SHLIB_CFLAGS="-KPIC" # Check to enable 64-bit flags for compiler/linker if test "$do64bit" = yes then : arch=`isainfo` if test "$arch" = "sparcv9 sparc" then : if test "$GCC" = yes then : if test "`${CC} -dumpversion | awk -F. '{print $1}'`" -lt 3 then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} else $as_nop do64bit_ok=yes CFLAGS="$CFLAGS -m64 -mcpu=v9" LDFLAGS="$LDFLAGS -m64 -mcpu=v9" SHLIB_CFLAGS="-fPIC" fi else $as_nop do64bit_ok=yes if test "$do64bitVIS" = yes then : CFLAGS="$CFLAGS -xarch=v9a" LDFLAGS_ARCH="-xarch=v9a" else $as_nop CFLAGS="$CFLAGS -xarch=v9" LDFLAGS_ARCH="-xarch=v9" fi # Solaris 64 uses this as well #LD_LIBRARY_PATH_VAR="LD_LIBRARY_PATH_64" fi else $as_nop if test "$arch" = "amd64 i386" then : if test "$GCC" = yes then : case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) do64bit_ok=yes CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; esac else $as_nop do64bit_ok=yes case $system in SunOS-5.1[1-9]*|SunOS-5.[2-9][0-9]*) CFLAGS="$CFLAGS -m64" LDFLAGS="$LDFLAGS -m64";; *) CFLAGS="$CFLAGS -xarch=amd64" LDFLAGS="$LDFLAGS -xarch=amd64";; esac fi else $as_nop { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 printf "%s\n" "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} fi fi fi SHLIB_SUFFIX=".so" if test "$GCC" = yes then : SHLIB_LD='${CC} -shared' CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} if test "$do64bit_ok" = yes then : if test "$arch" = "sparcv9 sparc" then : # We need to specify -static-libgcc or we need to # add the path to the sparv9 libgcc. # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -mcpu=v9 -static-libgcc" # for finding sparcv9 libgcc, get the regular libgcc # path, remove so name and append 'sparcv9' #v9gcclibdir="`gcc -print-file-name=libgcc_s.so` | ..." #CC_SEARCH_FLAGS="${CC_SEARCH_FLAGS},-R,$v9gcclibdir" else $as_nop if test "$arch" = "amd64 i386" then : # JH: static-libgcc is necessary for core Tcl, but may # not be necessary for extensions. SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" fi fi fi else $as_nop case $system in SunOS-5.[1-9][0-9]*) # TEA specific: use LDFLAGS_DEFAULT instead of LDFLAGS SHLIB_LD='${CC} -G -z text ${LDFLAGS_DEFAULT}';; *) SHLIB_LD='/usr/ccs/bin/ld -G -z text';; esac CC_SEARCH_FLAGS='"-Wl,-R,${LIB_RUNTIME_DIR}"' LD_SEARCH_FLAGS='-R "${LIB_RUNTIME_DIR}"' fi ;; UNIX_SV* | UnixWare-5*) SHLIB_CFLAGS="-KPIC" SHLIB_LD='${CC} -G' SHLIB_LD_LIBS="" SHLIB_SUFFIX=".so" # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers # that don't grok the -Bexport option. Test that it does. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 printf %s "checking for ld accepts -Bexport flag... " >&6; } if test ${tcl_cv_ld_Bexport+y} then : printf %s "(cached) " >&6 else $as_nop hold_ldflags=$LDFLAGS LDFLAGS="$LDFLAGS -Wl,-Bexport" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { int i; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : tcl_cv_ld_Bexport=yes else $as_nop tcl_cv_ld_Bexport=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$hold_ldflags fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 printf "%s\n" "$tcl_cv_ld_Bexport" >&6; } if test $tcl_cv_ld_Bexport = yes then : LDFLAGS="$LDFLAGS -Wl,-Bexport" fi CC_SEARCH_FLAGS="" LD_SEARCH_FLAGS="" ;; esac if test "$do64bit" = yes -a "$do64bit_ok" = no then : { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 printf "%s\n" "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} fi # Add in the arch flags late to ensure it wasn't removed. # Not necessary in TEA, but this is aligned with core LDFLAGS="$LDFLAGS $LDFLAGS_ARCH" # If we're running gcc, then change the C flags for compiling shared # libraries to the right flags for gcc, instead of those for the # standard manufacturer compiler. if test "$GCC" = yes then : case $system in AIX-*) ;; BSD/OS*) ;; CYGWIN_*|MINGW32_*|MINGW64_*|MSYS_*) ;; IRIX*) ;; NetBSD-*|DragonFly-*|FreeBSD-*|OpenBSD-*) ;; Darwin-*) ;; SCO_SV-3.2*) ;; windows) ;; *) SHLIB_CFLAGS="-fPIC" ;; esac fi if test "$tcl_cv_cc_visibility_hidden" != yes then : printf "%s\n" "#define MODULE_SCOPE extern" >>confdefs.h fi if test "$SHARED_LIB_SUFFIX" = "" then : # TEA specific: use PACKAGE_VERSION instead of VERSION SHARED_LIB_SUFFIX='${PACKAGE_VERSION}${SHLIB_SUFFIX}' fi if test "$UNSHARED_LIB_SUFFIX" = "" then : # TEA specific: use PACKAGE_VERSION instead of VERSION UNSHARED_LIB_SUFFIX='${PACKAGE_VERSION}.a' fi if test "${GCC}" = "yes" -a ${SHLIB_SUFFIX} = ".dll"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 printf %s "checking for SEH support in compiler... " >&6; } if test ${tcl_cv_seh+y} then : printf %s "(cached) " >&6 else $as_nop if test "$cross_compiling" = yes then : tcl_cv_seh=no else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main(int argc, char** argv) { int a, b = 0; __try { a = 666 / b; } __except (EXCEPTION_EXECUTE_HANDLER) { return 0; } return 1; } _ACEOF if ac_fn_c_try_run "$LINENO" then : tcl_cv_seh=yes else $as_nop tcl_cv_seh=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 printf "%s\n" "$tcl_cv_seh" >&6; } if test "$tcl_cv_seh" = "no" ; then printf "%s\n" "#define HAVE_NO_SEH 1" >>confdefs.h fi # # Check to see if the excpt.h include file provided contains the # definition for EXCEPTION_DISPOSITION; if not, which is the case # with Cygwin's version as of 2002-04-10, define it to be int, # sufficient for getting the current code to work. # { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 printf %s "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } if test ${tcl_cv_eh_disposition+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define WIN32_LEAN_AND_MEAN # include # undef WIN32_LEAN_AND_MEAN int main (void) { EXCEPTION_DISPOSITION x; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_eh_disposition=yes else $as_nop tcl_cv_eh_disposition=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 printf "%s\n" "$tcl_cv_eh_disposition" >&6; } if test "$tcl_cv_eh_disposition" = "no" ; then printf "%s\n" "#define EXCEPTION_DISPOSITION int" >>confdefs.h fi # Check to see if winnt.h defines CHAR, SHORT, and LONG # even if VOID has already been #defined. The win32api # used by mingw and cygwin is known to do this. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 printf %s "checking for winnt.h that ignores VOID define... " >&6; } if test ${tcl_cv_winnt_ignore_void+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define VOID void #define WIN32_LEAN_AND_MEAN #include #undef WIN32_LEAN_AND_MEAN int main (void) { CHAR c; SHORT s; LONG l; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_winnt_ignore_void=yes else $as_nop tcl_cv_winnt_ignore_void=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 printf "%s\n" "$tcl_cv_winnt_ignore_void" >&6; } if test "$tcl_cv_winnt_ignore_void" = "yes" ; then printf "%s\n" "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h fi fi # See if the compiler supports casting to a union type. # This is used to stop gcc from printing a compiler # warning when initializing a union member. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 printf %s "checking for cast to union support... " >&6; } if test ${tcl_cv_cast_to_union+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { union foo { int i; double d; }; union foo f = (union foo) (int) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_cast_to_union=yes else $as_nop tcl_cv_cast_to_union=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 printf "%s\n" "$tcl_cv_cast_to_union" >&6; } if test "$tcl_cv_cast_to_union" = "yes"; then printf "%s\n" "#define HAVE_CAST_TO_UNION 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "stdbool.h" "ac_cv_header_stdbool_h" "$ac_includes_default" if test "x$ac_cv_header_stdbool_h" = xyes then : printf "%s\n" "#define HAVE_STDBOOL_H 1" >>confdefs.h fi # These must be called after we do the basic CFLAGS checks and # verify any possible 64-bit or similar switches are necessary { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for required early compiler flags" >&5 printf %s "checking for required early compiler flags... " >&6; } tcl_flags="" if test ${tcl_cv_flag__isoc99_source+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__isoc99_source=no else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _ISOC99_SOURCE 1 #include int main (void) { char *p = (char *)strtoll; char *q = (char *)strtoull; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__isoc99_source=yes else $as_nop tcl_cv_flag__isoc99_source=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "x${tcl_cv_flag__isoc99_source}" = "xyes" ; then printf "%s\n" "#define _ISOC99_SOURCE 1" >>confdefs.h tcl_flags="$tcl_flags _ISOC99_SOURCE" fi if test "${TCL_MAJOR_VERSION}" -ne 8 ; then if test ${tcl_cv_flag__file_offset_bits+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__file_offset_bits=no else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include int main (void) { switch (0) { case 0: case (sizeof(off_t)==sizeof(long long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_flag__file_offset_bits=yes else $as_nop tcl_cv_flag__file_offset_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "x${tcl_cv_flag__file_offset_bits}" = "xyes" ; then printf "%s\n" "#define _FILE_OFFSET_BITS 64" >>confdefs.h tcl_flags="$tcl_flags _FILE_OFFSET_BITS" fi fi if test "x${tcl_flags}" = "x" ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: none" >&5 printf "%s\n" "none" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${tcl_flags}" >&5 printf "%s\n" "${tcl_flags}" >&6; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit integer type" >&5 printf %s "checking for 64-bit integer type... " >&6; } if test ${tcl_cv_type_64bit+y} then : printf %s "(cached) " >&6 else $as_nop tcl_cv_type_64bit=none # See if the compiler knows natively about __int64 cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { __int64 value = (__int64) 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_type_64bit=__int64 else $as_nop tcl_type_64bit="long long" fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext # See if we could use long anyway Note that we substitute in the # type that is our current guess for a 64-bit type inside this check # program, so it should be modified only carefully... cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main (void) { switch (0) { case 1: case (sizeof(${tcl_type_64bit})==sizeof(long)): ; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_type_64bit=${tcl_type_64bit} fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "${tcl_cv_type_64bit}" = none ; then printf "%s\n" "#define TCL_WIDE_INT_IS_LONG 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } elif test "${tcl_cv_type_64bit}" = "__int64" \ -a "${TEA_PLATFORM}" = "windows" ; then # TEA specific: We actually want to use the default tcl.h checks in # this case to handle both TCL_WIDE_INT_TYPE and TCL_LL_MODIFIER* { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: using Tcl header defaults" >&5 printf "%s\n" "using Tcl header defaults" >&6; } else printf "%s\n" "#define TCL_WIDE_INT_TYPE ${tcl_cv_type_64bit}" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${tcl_cv_type_64bit}" >&5 printf "%s\n" "${tcl_cv_type_64bit}" >&6; } # Now check for auxiliary declarations if test "${TCL_MAJOR_VERSION}" -ne 8 ; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for 64-bit time_t" >&5 printf %s "checking for 64-bit time_t... " >&6; } if test ${tcl_cv_time_t_64+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_time_t_64=yes else $as_nop tcl_cv_time_t_64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_time_t_64" >&5 printf "%s\n" "$tcl_cv_time_t_64" >&6; } if test "x${tcl_cv_time_t_64}" = "xno" ; then # Note that _TIME_BITS=64 requires _FILE_OFFSET_BITS=64 # which SC_TCL_EARLY_FLAGS has defined if necessary. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if _TIME_BITS=64 enables 64-bit time_t" >&5 printf %s "checking if _TIME_BITS=64 enables 64-bit time_t... " >&6; } if test ${tcl_cv__time_bits+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _TIME_BITS 64 #include int main (void) { switch (0) {case 0: case (sizeof(time_t)==sizeof(long long)): ;} ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv__time_bits=yes else $as_nop tcl_cv__time_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv__time_bits" >&5 printf "%s\n" "$tcl_cv__time_bits" >&6; } if test "x${tcl_cv__time_bits}" = "xyes" ; then printf "%s\n" "#define _TIME_BITS 64" >>confdefs.h fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct dirent64" >&5 printf %s "checking for struct dirent64... " >&6; } if test ${tcl_cv_struct_dirent64+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct dirent64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_struct_dirent64=yes else $as_nop tcl_cv_struct_dirent64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_dirent64" >&5 printf "%s\n" "$tcl_cv_struct_dirent64" >&6; } if test "x${tcl_cv_struct_dirent64}" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_DIRENT64 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for DIR64" >&5 printf %s "checking for DIR64... " >&6; } if test ${tcl_cv_DIR64+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main (void) { struct dirent64 *p; DIR64 d = opendir64("."); p = readdir64(d); rewinddir64(d); closedir64(d); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_DIR64=yes else $as_nop tcl_cv_DIR64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_DIR64" >&5 printf "%s\n" "$tcl_cv_DIR64" >&6; } if test "x${tcl_cv_DIR64}" = "xyes" ; then printf "%s\n" "#define HAVE_DIR64 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for struct stat64" >&5 printf %s "checking for struct stat64... " >&6; } if test ${tcl_cv_struct_stat64+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { struct stat64 p; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_struct_stat64=yes else $as_nop tcl_cv_struct_stat64=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_struct_stat64" >&5 printf "%s\n" "$tcl_cv_struct_stat64" >&6; } if test "x${tcl_cv_struct_stat64}" = "xyes" ; then printf "%s\n" "#define HAVE_STRUCT_STAT64 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "open64" "ac_cv_func_open64" if test "x$ac_cv_func_open64" = xyes then : printf "%s\n" "#define HAVE_OPEN64 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "lseek64" "ac_cv_func_lseek64" if test "x$ac_cv_func_lseek64" = xyes then : printf "%s\n" "#define HAVE_LSEEK64 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for off64_t" >&5 printf %s "checking for off64_t... " >&6; } if test ${tcl_cv_type_off64_t+y} then : printf %s "(cached) " >&6 else $as_nop cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main (void) { off64_t offset; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO" then : tcl_cv_type_off64_t=yes else $as_nop tcl_cv_type_off64_t=no fi rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test "x${tcl_cv_type_off64_t}" = "xyes" && \ test "x${ac_cv_func_lseek64}" = "xyes" && \ test "x${ac_cv_func_open64}" = "xyes" ; then printf "%s\n" "#define HAVE_TYPE_OFF64_T 1" >>confdefs.h { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for build with symbols" >&5 printf %s "checking for build with symbols... " >&6; } # Check whether --enable-symbols was given. if test ${enable_symbols+y} then : enableval=$enable_symbols; tcl_ok=$enableval else $as_nop tcl_ok=no fi if test "$tcl_ok" = "no"; then CFLAGS_DEFAULT="${CFLAGS_OPTIMIZE} -DNDEBUG" LDFLAGS_DEFAULT="${LDFLAGS_OPTIMIZE}" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } printf "%s\n" "#define TCL_CFG_OPTIMIZED 1" >>confdefs.h else CFLAGS_DEFAULT="${CFLAGS_DEBUG}" LDFLAGS_DEFAULT="${LDFLAGS_DEBUG}" if test "$tcl_ok" = "yes"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes (standard debugging)" >&5 printf "%s\n" "yes (standard debugging)" >&6; } fi fi if test "$tcl_ok" = "mem" -o "$tcl_ok" = "all"; then printf "%s\n" "#define TCL_MEM_DEBUG 1" >>confdefs.h fi if test "$tcl_ok" != "yes" -a "$tcl_ok" != "no"; then if test "$tcl_ok" = "all"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled symbols mem debugging" >&5 printf "%s\n" "enabled symbols mem debugging" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabled $tcl_ok debugging" >&5 printf "%s\n" "enabled $tcl_ok debugging" >&6; } fi fi if test "${SHARED_BUILD}" = "1"; then printf "%s\n" "#define USE_TCL_STUBS 1" >>confdefs.h fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 printf %s "checking for grep that handles long lines and -e... " >&6; } if test ${ac_cv_path_GREP+y} then : printf %s "(cached) " >&6 else $as_nop if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in grep ggrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 printf "%s\n" "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 printf %s "checking for egrep... " >&6; } if test ${ac_cv_path_EGREP+y} then : printf %s "(cached) " >&6 else $as_nop if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_prog in egrep do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 printf %s 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" printf "%s\n" 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 printf "%s\n" "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" if test "${TEA_PLATFORM}" = "windows" -a "$GCC" != "yes"; then MAKE_STATIC_LIB="\${STLIB_LD} -out:\$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -out:\$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined(_MSC_VER) && _MSC_VER >= 1400 print("manifest needed") #endif _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "manifest needed" >/dev/null 2>&1 then : # Could do a CHECK_PROG for mt, but should always be with MSVC8+ VC_MANIFEST_EMBED_DLL="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;2 ; fi" VC_MANIFEST_EMBED_EXE="if test -f \$@.manifest ; then mt.exe -nologo -manifest \$@.manifest -outputresource:\$@\;1 ; fi" MAKE_SHARED_LIB="${MAKE_SHARED_LIB} ; ${VC_MANIFEST_EMBED_DLL}" CLEANFILES="$CLEANFILES *.manifest" fi rm -rf conftest* MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@ \$(PKG_STUB_OBJECTS)" else MAKE_STATIC_LIB="\${STLIB_LD} \$@ \$(PKG_OBJECTS)" MAKE_SHARED_LIB="\${SHLIB_LD} \${LDFLAGS} \${LDFLAGS_DEFAULT} -o \$@ \$(PKG_OBJECTS) \${SHLIB_LD_LIBS}" MAKE_STUB_LIB="\${STLIB_LD} \$@ \$(PKG_STUB_OBJECTS)" fi if test "${SHARED_BUILD}" = "1" ; then MAKE_LIB="${MAKE_SHARED_LIB} " else MAKE_LIB="${MAKE_STATIC_LIB} " fi #-------------------------------------------------------------------- # Shared libraries and static libraries have different names. # Use the double eval to make sure any variables in the suffix is # substituted. (@@@ Might not be necessary anymore) #-------------------------------------------------------------------- PACKAGE_LIB_PREFIX8="${PACKAGE_LIB_PREFIX}" PACKAGE_LIB_PREFIX9="${PACKAGE_LIB_PREFIX}tcl9" if test "${TCL_MAJOR_VERSION}" -gt 8 -a x"${with_tcl8}" == x; then PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX9}" else PACKAGE_LIB_PREFIX="${PACKAGE_LIB_PREFIX8}" printf "%s\n" "#define TCL_MAJOR_VERSION 8" >>confdefs.h fi if test "${TEA_PLATFORM}" = "windows" ; then if test "${SHARED_BUILD}" = "1" ; then # We force the unresolved linking of symbols that are really in # the private libraries of Tcl and Tk. if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TK_BIN_DIR}/${TK_STUB_LIB_FILE}`\"" fi SHLIB_LD_LIBS="${SHLIB_LD_LIBS} \"`${CYGPATH} ${TCL_BIN_DIR}/${TCL_STUB_LIB_FILE}`\"" if test "$GCC" = "yes"; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} -static-libgcc" fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" else if test "$GCC" = "yes"; then PACKAGE_LIB_PREFIX=lib${PACKAGE_LIB_PREFIX} fi eval eval "PKG_LIB_FILE8=${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" if test "$GCC" = "yes"; then PKG_STUB_LIB_FILE=lib${PKG_STUB_LIB_FILE} fi # These aren't needed on Windows (either MSVC or gcc) RANLIB=: RANLIB_STUB=: else RANLIB_STUB="${RANLIB}" if test "${SHARED_BUILD}" = "1" ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TCL_STUB_LIB_SPEC}" if test x"${TK_BIN_DIR}" != x ; then SHLIB_LD_LIBS="${SHLIB_LD_LIBS} ${TK_STUB_LIB_SPEC}" fi eval eval "PKG_LIB_FILE8=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE9=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${SHARED_LIB_SUFFIX}" RANLIB=: else eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX9}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" eval eval "PKG_LIB_FILE=lib${PACKAGE_LIB_PREFIX}${PACKAGE_NAME}${UNSHARED_LIB_SUFFIX}" fi # Some packages build their own stubs libraries eval eval "PKG_STUB_LIB_FILE=lib${PACKAGE_LIB_PREFIX8}${PACKAGE_NAME}stub${UNSHARED_LIB_SUFFIX}" fi # These are escaped so that only CFLAGS is picked up at configure time. # The other values will be substituted at make time. CFLAGS="${CFLAGS} \${CFLAGS_DEFAULT} \${CFLAGS_WARNING}" if test "${SHARED_BUILD}" = "1" ; then CFLAGS="${CFLAGS} \${SHLIB_CFLAGS}" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 printf %s "checking for tclsh... " >&6; } if test -f "${TCL_BIN_DIR}/Makefile" ; then # tclConfig.sh is in Tcl build directory if test "${TEA_PLATFORM}" = "windows"; then if test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}s${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}t${EXEEXT}" elif test -f "${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" ; then TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}st${EXEEXT}" fi else TCLSH_PROG="${TCL_BIN_DIR}/tclsh" fi else # tclConfig.sh is in install location if test "${TEA_PLATFORM}" = "windows"; then TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${EXEEXT}" else TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}" fi list="`ls -d ${TCL_BIN_DIR}/../bin 2>/dev/null` \ `ls -d ${TCL_BIN_DIR}/.. 2>/dev/null` \ `ls -d ${TCL_PREFIX}/bin 2>/dev/null`" for i in $list ; do if test -f "$i/${TCLSH_PROG}" ; then REAL_TCL_BIN_DIR="`cd "$i"; pwd`/" break fi done TCLSH_PROG="${REAL_TCL_BIN_DIR}${TCLSH_PROG}" fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 printf "%s\n" "${TCLSH_PROG}" >&6; } ac_config_files="$ac_config_files Makefile pkgIndex.tcl library/vfs.tcl" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\[/\\&/g s/\]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs CFLAGS="${CFLAGS} ${CPPFLAGS}"; CPPFLAGS="" : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh as_nop=: if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else $as_nop case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else $as_nop as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else $as_nop as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by vfs $as_me 1.4.2, which was generated by GNU Autoconf 2.71. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to the package provider." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ vfs config.status 1.4.2 configured by $0, generated by GNU Autoconf 2.71, with options \\"\$ac_cs_config\\" Copyright (C) 2021 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "pkgIndex.tcl") CONFIG_FILES="$CONFIG_FILES pkgIndex.tcl" ;; "library/vfs.tcl") CONFIG_FILES="$CONFIG_FILES library/vfs.tcl" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi tclvfs/configure.ac000064400000000000000000000047571447560765400142600ustar00nobodynobody#!/bin/bash -norc dnl This file is an input file used by the GNU "autoconf" program to dnl generate the file "configure", which is run during Tcl installation dnl to configure the system for the local environment. # # RCS: @(#) $Id: configure.in,v 1.20 2012/12/12 21:24:47 andreas_kupries Exp $ #-------------------------------------------------------------------- # This configure.in is based on the Tcl Extension Architecture (TEA) # v3 spec. See the sampleextension module for a fully commented # version of the configure.in and makefiles to build your own extension. # http://tcl.sourceforge.net/ 'sampleextension' cvs module # http://www.tcl.tk/ Tcl Developer Exchange #-------------------------------------------------------------------- AC_INIT([vfs],[1.4.2]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- TEA_INIT([3.7]) AC_CONFIG_AUX_DIR(tclconfig) TEA_PATH_TCLCONFIG TEA_LOAD_TCLCONFIG TEA_PREFIX TEA_SETUP_COMPILER TEA_ADD_SOURCES([vfs.c]) TEA_ADD_HEADERS([]) TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${TCL_SRC_DIR}/generic)\"]) TEA_ADD_LIBS([]) TEA_ADD_CFLAGS([]) TEA_ADD_STUB_SOURCES([]) TEA_ADD_TCL_SOURCES([]) #TEA_PUBLIC_TCL_HEADERS TEA_PRIVATE_TCL_HEADERS #-------------------------------------------------------------------- # A few miscellaneous platform-specific items: # # Define a special symbol for Windows (BUILD_VFS in this case) so # that we create the export library with the dll. See sha1.h on how # to use this. # # Windows creates a few extra files that need to be cleaned up. # You can add more files to clean if your extension creates any extra # files. # # Define any extra compiler flags in the PACKAGE_CFLAGS variable. # These will be appended to the current set of compiler flags for # your system. #-------------------------------------------------------------------- if test "${TEA_PLATFORM}" = "windows" ; then AC_DEFINE(BUILD_vfs) CLEANFILES="pkgIndex.tcl *.lib *.dll *.exp *.ilk *.pdb vc*.pch" else CLEANFILES="pkgIndex.tcl" fi AC_SUBST(CLEANFILES) TEA_ENABLE_THREADS TEA_ENABLE_SHARED TEA_CONFIG_CFLAGS TEA_ENABLE_SYMBOLS if test "${SHARED_BUILD}" = "1"; then AC_DEFINE(USE_TCL_STUBS) fi TEA_MAKE_LIB TEA_PROG_TCLSH AC_CONFIG_FILES([Makefile pkgIndex.tcl library/vfs.tcl]) AC_OUTPUT tclvfs/doc000075500000000000000000000000001447560765400124435ustar00nobodynobodytclvfs/doc/vfs-filesystems.man000064400000000000000000000055301447560765400163650ustar00nobodynobody[comment {-*- tcl -*- doctools manpage}] [manpage_begin vfs-filesystems n 1.0] [copyright {2001-2003 Vince Darley }] [copyright {2003 Andreas Kupries }] [moddesc {Tcl-level Virtual Filesystems}] [titledesc {Filesystems provided by tclvfs}] [require Tcl 8.4] [require vfs [opt 1.2.1]] [require vfs::zip [opt 1.0]] [require vfs::mk4 [opt 1.6]] [require vfs::tar [opt 0.9]] [require vfs::ftp [opt 1.0]] [require vfs::ns [opt 1.0]] [require vfs::webdav [opt 0.1]] [require vfs::http [opt 0.5]] [require vfs::urltype [opt 1.0]] [description] The package [package vfs] provides not only the means to implement a virtual filesystem at the tcl level, but also a number of ready to be used filesystems as well. [para] Each of these filesystem exists as its own package, and can be accessed through [cmd {package require vfs::NAME}]. The whole set of these virtual filesystems is known informally as '[term vfslib]'. [section {SUPPORTED VFS TYPES}] Currently supported are ftp, tar, http, zip, mk4, ns, and webdav. In addition there is the ability to mount any 'urltype' as a new directory, provided an appropriate vfs is supported. This means that you can treat urls based on the schemes [emph ftp://], [emph http://] and [emph file://] as files. To do this, simply evaluate the command [cmd {vfs::urltype::Mount ftp}] for example. Any access inside the new volume will result in an attempt to require a package through [cmd {package require vfs::${type}}], which must therefore exist, or errors will be thrown. If a filesystem is loaded, use the associated command listed below to mount a source for that filesystem as a tcl directory. [list_begin definitions] [call [cmd vfs::zip::Mount] [arg path] [arg to]] Mount the zip file [arg path] as directory [arg to]. [call [cmd vfs::mk4::Mount] [arg path] [arg to]] Mount the metakit database file file [arg path] as directory [arg to]. [call [cmd vfs::tar::Mount] [arg path] [arg to]] Mount the tar file [arg path] as directory [arg to]. [call [cmd vfs::ftp::Mount] [arg path] [arg to]] Mount the ftp url [arg path] as directory [arg to]. [call [cmd vfs::ns::Mount] [arg path] [arg to]] Mount the tcl namespace [arg path] as directory [arg to]. [call [cmd vfs::webdav::Mount] [arg path] [arg to]] Mount the webdav url [arg path] as directory [arg to]. [call [cmd vfs::http::Mount] [arg path] [arg to]] Mount the http url [arg path] as directory [arg to]. [call [cmd vfs::urltype::Mount] [arg path] [arg to]] Mount the url [arg path], of type [arg urltype] as directory [arg to]. [list_end] [section LIMITATIONS] Most of the vfs types listed above have not been very well debugged as yet. Please test them! [see_also vfs vfs-fsapi] [keywords vfs filesystem file vfslib zip tar webdav ftp http namespace metakit] [manpage_end] tclvfs/doc/vfs-fsapi.man000064400000000000000000000324111447560765400151160ustar00nobodynobody[comment {-*- tcl -*- doctools manpage}] [manpage_begin vfs-fsapi n 1.0] [copyright {2001-2003 Vince Darley }] [copyright {2003 Andreas Kupries }] [moddesc {Tcl-level Virtual Filesystems}] [titledesc {API for the implementation of a filesystem in Tcl}] [require Tcl 8.4] [require vfs [opt 1.2.1]] [description] This document explains the API used by the package [package vfs] to communicate with filesystem implementations written in tcl. [section {HANDLER OVERVIEW}] The package [package vfs] intercepts every filesystem operation which falls within a given mount point, and passes the operation on to the mount point's [cmd vfshandler] command in the interpreter which registered it. [para] If the handler takes appropriate action for each of the cases it is called for, a complete, perfect virtual filesystem will be achieved, indistinguishable to Tcl from the native filesystem. (CAVEATS: Right now [package vfs] does not expose to Tcl all the permission-related flags of [cmd glob]). [para] [list_begin definitions] [call [cmd vfshandler] [arg subcmd] [arg root] [arg relative] [arg actualpath] [arg args]...] The first argument specifies the operation to perform on behalf of the filesystem code in the tcl core, the remainder specify the file path on which to operate, in different forms, and parts, and any additional arguments which may be required to carry out the action. [nl] To demonstrate the treatment of a path by the generic layer we use [file C:/foo/bar/mount.zip/xxx/yyy] as an example and additionally assume that the following conditions are true: [list_begin enum] [enum] [file mount.zip] is a zip archive which has been mounted on top of itself, [enum] said zip archive contains a file with path [file xxx/yyy], [enum] the current working directory of the application is inside of directory [file xxx], [enum] and the command executed is [cmd {file exists yyy}]. [list_end] [nl] The file separator between [arg root] and [arg relative] is omitted. Most filesystem operations need only the [arg relative] argument for their correct operation, but some actually require the other parts of the path. [list_begin definitions] [lst_item [arg subcmd]] This argument of the handler can be one of the following [method access], [method createdirectory], [method deletefile], [method fileattributes], [method matchindirectory], [method open], [method removedirectory], [method stat], or [method utime]. [nl] The generic layer expects that the subcommands of a handler signal error conditions by calling [cmd {vfs::filesystem posixerror}] with the appropriate posix error code instead of throwing a tcl error. If the latter is done nevertheless it will be treated as an unknown posix error. [nl] There are three exceptions to the rule above: If any of [method open] (when an interpreter is given), [method matchindirectory], and [method fileattributes] (for a set or get operation only) throw a tcl error, this error will be passed up to the caller of the filesystem command which invoked the handler. Note that this does not preclude the ability of these subcommands to use the command [cmd {vfs::filesystem posixerror}] to report more regular filesystem errors. [lst_item [arg root]] Part of the specification of the path to operate upon. It contains the part of the path which lies outside this filesystem's mount point. For example outlined above its value will be [file C:/foo/bar/mount.zip]. [lst_item [arg relative]] Part of the specification of the path to operate upon. It contains the part of the path which lies inside this filesystem. For example outlined above its value will be [file xxx/yyy]. [lst_item [arg actualpath]] Part of the specification of the path to operate upon. It contains the original (unnormalized) name of the path which was used in the current command wherever it originated (in Tcl or C). For example outlined above its value will be [file yyy]. [list_end] [list_end] [section {HANDLER METHODS}] [list_begin definitions] [call [cmd vfshandler] [method access] [arg root] [arg relative] [arg actualpath] [arg mode]] Signal a posix error if the specified access [arg mode] (an integer number) is not compatible with the file or directory described by the path. The generic layer will ignore any non-empty return value. [nl] The command [cmd vfs::accessMode] (see section [sectref {HANDLER ENVIRONMENT}]) can be used to convert the integer [arg mode] into an easier to check string value. [call [cmd vfshandler] [method createdirectory] [arg root] [arg relative] [arg actualpath]] Create a directory with the given name. The command can assume that all sub-directories in the path exist and are valid, and that the actual desired path does not yet exist (Tcl takes care of all of that for us). [call [cmd vfshandler] [method deletefile] [arg root] [arg relative] [arg actualpath]] Delete the given file. [call [cmd vfshandler] [method fileattributes] [arg root] [arg relative] [arg actualpath] [opt [arg index]] [opt [arg value]]] The command has to return a list containing the names of all acceptable attributes, if neither [arg index] nor [arg value] were specified. [nl] The command has to return the value of the [arg index]'th attribute if the [arg index] is specified, but not the [arg value]. The attributes are counted in the same order as their names appear in the list returned by a call where neither [arg index] nor [arg value] were specified. The first attribute is has the index [const 0]. [nl] The command has to set the value of the [arg index]'th attribute to [arg value] if both [arg index] and [arg value] were specified for the call. [call [cmd vfshandler] [method matchindirectory] [arg root] [arg relative] [arg actualpath] [arg pattern] [arg types]] Return the list of files or directories in the given path which match the glob [arg pattern] and are compatible with the specified list of [arg types]. The specified path is always the name of an existing directory. [nl] [emph Note:] As Tcl generates requests for directory-only matches from the filesystems involved when performing any type of recursive globbing this subcommand absolutely has to handle such (and file-only) requests correctly or bad things (TM) will happen. [nl] The commands [cmd vfs::matchDirectories] and [cmd vfs::matchFiles] (see section [sectref {HANDLER ENVIRONMENT}]) can aid the implementation greatly in this task. [call [cmd vfshandler] [method open] [arg root] [arg relative] [arg actualpath] [arg mode] [arg permissions]] Either returns a list describing the successfully opened file, or throws an error describing how the operation failed. [nl] The list returned upon success contains at least one and at most two elements. The first, obligatory, element is always the handle of the channel which was created to allow access to the contents of the file. [nl] If specified the second element will be interpreted as a callback, i.e. a command prefix. This prefix will always be executed as is, i.e. without additional arguments. Any required arguments have to be returned as part of the result of the call to [method open]. [nl] If present the specified callback will be evaluated just before the channel is closed [emph {by the generic filesystem layer}]. The callback itself [emph {must not}] call [cmd close]. [nl] The channel however is live enough to allow [cmd seek] and [cmd read] operations. In addition all available data will have been flushed into it already. This means, for example, that the callback can seek to the beginning of the said channel, read its contents and then store the gathered data elsewhere. In other words, this callback is not only crucial to the cleanup of any resources associated with an opened file, but also for the ability to implement a filesystem which can be written to. [nl] Under normal circumstances return code and any errors thrown by the callback itself are ignored. In that case errors have to be signaled asychronously, for example by calling [cmd bgerror]. However if, through a call of the subcommand [method internalerror], an error handling script has been specified for the file system, all errors thrown here will be passed to that script for further action. [list_begin definitions] [lst_item [arg mode]] can be any of [const r], [const w], [const a], [const w+], or [const a+]. [lst_item [arg permissions]] determines the native mode the openend file is created with. Relevant only of the open [arg mode] actually requests the creation of a non-existing file, i.e. is not [const r]. [list_end] [nl] [call [cmd vfshandler] [method removedirectory] [arg root] [arg relative] [arg actualpath] [arg recursive]] Delete the given directory. Argument [arg recursive] is a boolean. If the specified value is [const true] then even if the directory is non-empty, an attempt has to be made to recursively delete it and its contents. If the spcified value is [const false] and the directory is non-empty, a posix error ([const EEXIST]) has to be thrown. [call [cmd vfshandler] [method stat] [arg root] [arg relative] [arg actualpath]] The result has to be a list of keys and values, in a format acceptable to the builtin command [cmd {array set}]. It describes the contents of a stat structure. The order of the keys in the list is not important. [nl] Given this the subcommand should use something like [example {return [list dev 0 type file mtime 1234 ...].}] as the last command of its implementation. [nl] The following keys and their values have to be supplied by the filesystem: [list_begin definitions] [lst_item [const dev]] A long integer number, the device number of the path stat was called for. [lst_item [const ino]] A long integer number, the inode number of the path stat was called for. Each path handled by the filesystem should be uniquely identified by the combination of device and inode number. Violating this principle will cause higher-level algorithms which(have to) keep track of device and inode information to fail in all manners possible. [nl] An example of such an algorithm would be a directory walker using device/inode information to keep itself out of infinite loops generated through symbolic links. Returning non-unique device/inode information will most likely cause such a walker to skip over paths under the wrong assumption of having them seen already. [lst_item [const mode]] An integer number, the access mode of the path. It is this mode which is checked by the subcommand [method access]. [lst_item [const nlink]] A long integer number, the number of hard links to the specified path. [lst_item [const uid]] A long integer number, the id of the user owning the virtual path. [lst_item [const gid]] A long integer number, the id of the user group the virtual path belongs to. [lst_item [const size]] A long integer number, the true size of the virtual path, in bytes. [lst_item [const atime]] A long integer number, the time of the latest access to the path, in seconds since the epoch. Convertible into a readable date/time by the command [cmd {clock format}]. [lst_item [const mtime]] A long integer number, the time of the latest modification of the path, in seconds since the epoch. Convertible into a readable date/time by the command [cmd {clock format}]. [lst_item [const ctime]] A long integer number, the time of the path was created, in seconds since the epoch. Convertible into a readable date/time by the command [cmd {clock format}]. [lst_item [const type]] A string, either [const directory], or [const file], describing the type of the given path. [list_end] [nl] [call [cmd vfshandler] [method utime] [arg root] [arg relative] [arg actualpath] [arg actime] [arg mtime]] Set the access and modification times of the given file (these are read with [method stat]). [list_end] [section {HANDLER ENVIRONMENT}] The implementation of a filesystem handler can rely on the existence of the following utility commands: [list_begin definitions] [call [cmd vfs::accessMode] [arg mode]] This commands converts an access [arg mode] given as integer into a string, one of [const F], [const X], [const W], [const XW], [const R], [const RX], and [const RW]. [call [cmd vfs::matchDirectories] [arg types]] Checks if the glob types specification ask for the inclusion of directories. Returns a boolean result. [const true] is returned if types does ask for directories, else [const false]. [call [cmd vfs::matchFiles] [arg types]] Checks if the glob types specification ask for the inclusion of files. Returns a boolean result. [const true] is returned if types does ask for directories, else [const false]. [call [cmd vfs::matchCorrectTypes] [arg types] [arg filelist] [opt [arg inDir]]] Returns that subset of the [arg filelist] which are compatible with the [arg types] given. The elements of [arg filelist] are either absolute paths, or names of files in the directory [arg indir]. The latter interpretation is taken if and only if the argument [arg indir] is specified. [list_end] [section {FILESYSTEM DEBUGGING}] To debug a problem in the implementation of a filesystem use code as shown below. This registers the command [cmd report] as the error handler for the filesystem, which in turn prints out the error stack provided by tcl. [para] [example {vfs::filesystem internalerror report proc report {} { puts stderr $::errorInfo }}] [see_also vfs vfs-filesystems] [keywords vfs filesystem file] [manpage_end] tclvfs/doc/vfs.man000064400000000000000000000147631447560765400140300ustar00nobodynobody[comment {-*- tcl -*- doctools manpage}] [manpage_begin vfs n 1.0] [copyright {2001-2003 Vince Darley }] [copyright {2003 Andreas Kupries }] [moddesc {Tcl-level Virtual Filesystems}] [titledesc {Filesystem management in Tcl}] [require Tcl 8.4] [require vfs [opt 1.2.1]] [description] The package [package vfs] provides commands to query, mount and unmount virtual filesystems implemented in Tcl. This is further facilitated through the provison of helper commands in a tcl script library. See section "HANDLER ENVIRONMENT" of [cmd vfs-fsapi] for more information. [para] Once a virtual filesystem is in place, the standard Tcl commands, like [cmd file], [cmd glob], [cmd cd], [cmd pwd], [cmd open], including all their C APIs in the Tcl library (e.g. [fun Tcl_FSOpenFileChannel], [fun Tcl_FSMatchInDirectory], ...), can be used within the filesystem (and indeed, properly written extensions such as [package Tk] which may open or read files will also transparently access the virtual filesystem). [para] Because all of Tcl's filesystem activity passes through a single layer, every operation can be intercepted. This package does just that. This is also quite different from simply overloading the [cmd file] command in Tcl. We are actually providing replacements for C commands like [syscmd access], [syscmd stat], etc. By implementing a small number of low-level commands we ensure that all commands at higher levels will function irrespective of what is going on inside the filesystem layer. [para] Tcl's filesystem hooks operate on a per-process basis. This means every Tcl interpreter in the same process/application will see the same filesystem, including any virtual filesystems. [para] To access this package use the command [cmd {package require vfs}]. This automatically registers the vfs hooks into Tcl's filesystem and provides the command [cmd vfs::filesystem]. The latter allows the registration of actual virtual filesystems. More in the upcoming section [sectref API]. The hooks will not be removed until Tcl exits. If desired, control over this could be exposed to Tcl in the future. By and in itself the command above will have no further effect. Only after filesystem implementations have been registered and filesystems using them been mounted filesystem commands will actually be intercepted, and handled by the Tcl code of the mounted virtual filesystem. [section API] [list_begin definitions] [call [cmd vfs::filesystem] [method mount] [opt [option -volume]] [arg path] [arg command]] [term Mount]s a virtual filesystem at [arg path], making it useable. After completion of the call any access to a subdirectory of [arg path] will be handled by that filesystem. The filesystem is represented here by the [arg command] prefix which will be executed whenever an operation on a file or directory within [arg path] has to be performed. [nl] Whether the [arg command] is implemented in C or Tcl is of no relevance as long as it adheres to the API specified in [cmd vfs-fsapi] and is present in the interpreter where the mount operation is executed. [nl] If the option [option -volume] is specified the new mount point is also registered with Tcl as a new volume and will therefore from then on appear in the output of the command [cmd {file volumes}]. This is useful (and required for reasonable operation) for mounts like [const ftp://]. It should not be used for paths mounted inside the native filesystem. [nl] The new filesystem mounts will be observed immediately in all interpreters in the current process. If the interpreter is later deleted, all mounts which are intercepted by it will be automatically removed (and will therefore affect the view of the filesystem seen by all interpreters). [call [cmd vfs::filesystem] [method unmount] [arg path]] This unmounts the virtual filesystem which was mounted at [arg path]. An error is thrown if no filesystem was mounted there. After the completion of the operation the filesystem is not visible anymore, and any previous filesystem accessible through this path becomes accessible again. [call [cmd vfs::filesystem] [method info] [opt [arg path]]] A list of all filesystems mounted in all interpreters is returned, if no [arg path] argument was specified. Else the filesystem responsible for that [arg path] is examined and the command prefix used to handle all filesystem operations returned. An error is thrown if no filesystem is mounted for that [arg path]. [nl] There is currently no facility for examining in which interpreter each command will be evaluated. [call [cmd vfs::filesystem] [method fullynormalize] [arg path]] Performs a full expansion of [arg path], (as per [cmd {file normalize}]). This includes the following of any links in the last element of [arg path]. [call [cmd vfs::filesystem] [method posixerror] [arg int]] This command can be called by filesystem implementations during the execution of a filesystem operation to signal the posix error code of a failure. See also [syscmd vfs-fsapi]. [call [cmd vfs::filesystem] [method internalerror] [arg command]] When used the specified [arg command] is registerd as the command to trap and report any internal errors thrown by filesystem implementations. [list_end] [section LIMITATIONS] The code of the package [package vfs] has only a few limitations. [para] [list_begin enum] [enum] One subtlety one has to be aware of is that mixing case-(in)sensitive filesystems and application code may yield unexpected results. [nl] For example mounting a case-sensitive virtual filesystem into a case-insensitive system (like the standard Windows or MacOS filesystems) and then using this with code relying on case-insensitivity problems will appear when accessing the virtual filesystem. [nl] Note that application code relying on case-insensitivity will not under Unix either, i.e. is inherently non-portable, and should be fixed. [enum] The C-API's for [method link] and [method lstat] are currently not exposed to the Tcl level. This may be done in the future to allow virtual filesystems implemented in Tcl to support the reading and writing of links. [enum] The public C-API filesystem function [fun Tcl_FSMatchInDirectory] is given a variety of type information in a [term Tcl_GlobTypeData] structure. Currently only the [term type] field of said strcuture is exposed to the tcl-level. Fields like [term permissions] and MacOS [term type/creator] are ignored. [list_end] [see_also vfs-filesystems vfs-fsapi] [keywords vfs filesystem file] [manpage_end] tclvfs/doc/vfs.n000064400000000000000000000324461447560765400135100ustar00nobodynobody'\" '\" Copyright (c) 2001-2003, Vince Darley '\" '\" .so man.macros .TH vfs n 1.4 Vfs "Tcl-only Virtual File Systems" .BS '\" Note: do not modify the .sh NAME line immediately below! .SH NAME ::vfs \- Commands and Procedures to create virtual filesystems .SH SYNOPSIS .BS .sp \fBpackage require Tcl\fR .sp \fBpackage require vfs ?1.4?\fR .sp \fBvfs::filesystem\fR \fIinfo\fR .sp \fBvfs::filesystem\fR \fImount\fR .sp \fBvfs::filesystem\fR \fIunmount\fR .sp \fBvfs::accessMode\fR \fImode\fR .sp \fBvfs::matchDirectories\fR \fItypes\fR .sp \fBvfs::matchFiles\fR \fItypes\fR .sp \fBvfs::matchCorrectTypes\fR \fItypes\fR \fIfilelist\fR \fI?inDir?\fR .sp .BE .SH DESCRIPTION .PP The \fB::vfs\fR package provides commands to query, mount and unmount virtual filesystems, and provides as Tcl libraries some facilities for helping the writing of new virtual filesystems in Tcl. Once a virtual filesystem is in place, the standard Tcl \fBfile\fP, \fBglob\fP, \fBcd\fP, \fBpwd\fP, \fBopen\fP commands, including all their C APIs in the Tcl library (e.g. \fBTcl_FSOpenFileChannel\fR, \fBTcl_FSMatchInDirectory\fR,...), can be used within the filesystem (and indeed, properly written extensions such as Tk which may open or read files will also transparently access the virtual filesystem). Because all of Tcl's FS activity passes through a single layer, it can all be intercepted. This package does just that. Notice that this is quite different to overloading the \fBfile\fP command in Tcl. We are actually providing vfs replacements for C commands like \fBaccess\fP, \fBstat\fP. By implementing just a handful of commands at this low level, we ensure that all commands at higher levels function irrespective of what is going on inside the FS layer. .PP Tcl's filesystem hooks operate on a per-process basis. This means every Tcl interpreter in the same process/application sees the same filesystem, including any virtual filesystems. .PP The \fBpackage require vfs\fP command should be used to access this library. It automatically registers the vfs hooks into Tcl's filesystem, and these will not be removed until Tcl exits (if desired, control over this could be exposed to Tcl in the future). However, the vfs package will at that stage not have any new filesystems mounted, so it will have little effect. Note that \fBpackage require vfs\fP has two effects. First of all, when it is issued in \fBany\fR Tcl interpreter it will ensure the vfs hooks have been registered with Tcl's core just once (and if any of those interpreters are later deleted, the vfs hooks will still remain registered - they remain until Tcl exits). The second effect is to provide the command \fBvfs::filesystem\fR which allows the interpreter to intercept filesystem commands and handle them with Tcl code in that interpreter. .PP There are three somewhat unsupported subcommands of \fBvfs::filesystem\fR, \fBfullynormalize path\fR, \fBposixerror int\fR, \fBinternalerror ?script?\fR, which are used to normalize a path (including any final symlink), to register a posix error code with a Tcl error, and to trap/report internal errors in tclvfs implementations respectively. .TP \fBvfs::filesystem\fR \fImount\fR \fI?-volume?\fR \fIpath\fR \fIcommand\fR To use a virtual filesystem, it must be 'mounted'. Mounting involves declaring to the vfs package that any subdirectories of a given \fIpath\fR in the filesystem should be handled by the given \fIcommand\fR which should be a Tcl command or procedure in the interpreter in which the \fBvfs::filesystem\fR is executed. If the \fI?-volume?\fR flag is given, the given mount point is also registered with Tcl as a new volume (like a new drive which will appear in \fIfile volumes\fR). This is useful (and required for reasonable operation) for mounts like \fIftp://\fR. For paths mounted inside the native filesystem, it should of course not be given. The new filesystem mounts will be observed immediately in all interpreters in the current process. If the interpreter is later deleted, all mounts which are intercepted by it will be automatically removed (and will therefore affect the view of the filesystem seen by all interpreters). .TP \fBvfs::filesystem\fR \fIunmount\fR \fIpath\fR This unmounts the virtual filesystem which was mounted at \fIpath\fR (hence removing it from Tcl's filesystem), or throws an error if no filesystem was mounted there. .TP \fBvfs::filesystem\fR \fIinfo\fR \fI?path?\fR If no arguments are given, this returns a list of all filesystems mounted (in all interpreters). If a path argument is given, then the \fIcommand\fR to be used for that path is returned, or an error is thrown if no vfs is mounted for that path. There is currently no facility for examining in which interpreter each command will be evaluated. .TP \fBvfs::filesystem\fR \fIfullynormalize\fR \fIpath\fR Performs a full expansion of \fIpath\fR, (as per 'file normalize'), but including following any links in the last element of path. .PP .SH IMPLEMENTING A TCL ONLY VFS .PP The vfs package will intercept every filesystem operation which falls within a given mount point, and pass the operation on to the mount point's \fIcommand\fR in the interpreter which registered it. In general this occurs by the C equivalent of an evaluation like this: \fIeval $command [list $subcmd $root $relative $actualpath] $args\fR. .PP Here \fIsubcmd\fR may be any of the following: \fIaccess\fR, \fIcreatedirectory\fR, \fIdeletefile\fR, \fIfileattributes\fR, \fImatchindirectory\fR, \fIopen\fR, \fIremovedirectory\fR, \fIstat\fR, \fIutime\fR. If \fIcommand\fR takes appropriate action for each of these cases, a complete, perfect virtual filesystem will be achieved, indistinguishable to Tcl from the native filesystem. (CAVEATS: right now I don't expose to Tcl all the permission-related flags of 'glob'). .PP The remaining arguments specify a file path on which to operate (all commands operate on one of these), and any additional arguments which may be required to carry out the action. The file path is specified by three arguments: \fIroot\fR is the part of the path which lies outside this filesystem's mount point, \fIrelative\fR is the part of the path which lies inside this filesytem, and \fIactualpath\fR is the original (unnormalized) name of the path which was used in the current command wherever it originated (in Tcl or C). For example, if \fIC:/foo/bar/mount.zip/xxx/yyy\fR is a path in your filesystem, where \fImount.zip\fR is a zip archive which has been mounted (on top of itself) and contains \fIxxx/yyy\fR, and the current working directory is inside \fIxxx\fR, and we evaluate a command like \fIfile exists yyy\fR, then \fIroot\R will be \fIC:/foo/bar/mount.zip\fR, \fIrelative\fR will be \fIxxx/yyy\fR, and \fIactualpath\fR will be \fIyyy\fR. The file separator between the \fIroot\fR and \fIrelative\fR is omitted. .PP Note that most filesystem operations will only require the \fIrelative\fR argument to work correctly, but the other arguments are actually required for correct operation of some subcommands. .PP Almost all of these commands should either return correctly (i.e. with a TCL_OK result at the C level) or they should use vfs::filesystem posixerror to signal the appropriate posix error code. If a Tcl error is thrown, that should be considered a bug, but it will be interpreted as an unknown posix error in the filesystem call. The exceptions to these rules are those filesystem commands which are able to specify a Tcl error message directly: open (when an interpreter is given), matchindirectory and fileattributes (for a set or get operation only). These three commands are allowed to throw any Tcl error message which will be passed along to the caller, or they may throw a posix error which will be handled appropriately. .PP The actual commands are as follows (where \fIr-r-a\fR represents the standard argument triplet of \fIroot\fR, \fIrelative\fR and \fIactualpath\fR): .TP \fIcommand\fR \fIaccess\fR \fIr-r-a\fR \fImode\fR Return TCL_OK or throw a posix error depending on whether the given access mode (which is an integer) is compatible with the file. .TP \fIcommand\fR \fIcreatedirectory\fR \fIr-r-a\fR Create a directory with the given name. The command can assume that all sub-directories in the path exist and are valid, and that the actual desired path does not yet exist (Tcl takes care of all of that for us). .TP \fIcommand\fR \fIdeletefile\fR \fIr-r-a\fR Delete the given file. .TP \fIcommand\fR \fIfileattributes\fR \fIr-r-a\fR \fI?index?\fR \fI?value?\fR If neither index nor value is given, then return a list of all acceptable attribute names. If \fIindex\fR is given, but no value, then retrieve the value of the \fIindex\fR'th attribute (counting in order over the list returned when no argument is given) for the given file. If a value is also given then set the \fIindex\fR'th attribute of the given file to that value. .TP \fIcommand\fR \fImatchindirectory\fR \fIr-r-a\fR \fIpattern\fR \fItypes\fR Return the list of files or directories in the given path (which is always the name of an existing directory), which match the \fIpattern\fR and are compatible with the \fItypes\fR given. It is very important that the command correctly handle \fItypes\fR requests for directories only (and files only), because to handle any kind of recursive globbing, Tcl will actually generate requests for directory-only matches from the filesystem. See \fBvfs::matchDirectories\fR below for help. .TP \fIcommand\fR \fIopen\fR \fIr-r-a\fR \fImode\fR \fIpermissions\fR For this command, \fImode\fR is any of "r", "w", "a", "w+", "a+". If the open involves creating a file, then \fIpermissions\fR dictates what modes to create it with. If the open operation was not successful, an error should be thrown. If the open operation is successful, the command should return a list of either one or two items. The first item (which is obligatory) is the name of the channel which has been created. The second item, if given, is a Tcl-callback to be used when the channel is closed, so that the vfs can clean up as appropriate. This callback will be evaluated by Tcl just before the channel is closed. The channel will still exist, and all available data will have been flushed into it. The callback can, for example, seek to the beginning of the channel, read its contents and store that contents elsewhere (e.g. compressed or on a remote ftp site, etc). The return code or any errors returned by the callback are ignored (if the callback wishes to signal an error, it must do so asycnhronously, with bgerror, for example), unless the 'internalerror' script has been specified, when they are passed to that script for further action. .TP \fIcommand\fR \fIremovedirectory\fR \fIr-r-a\fR \fIrecursive\fR Delete the given directory. \fIrecursive\fR is either 0 or 1. If it is 1 then even if the directory is non-empty, an attempt should be made to recursively delete it and its contents. If it is 0 and the directory is non-empty, a posix error (EEXIST) should be thrown. .TP \fIcommand\fR \fIstat\fR \fIr-r-a\fR Return a list of even length containing field-name and value pairs for the contents of a stat structure. The order is not important. The option names are dev (long), ino (long), mode (int), nlink (long), uid (long), gid (long), size (long), atime (long), mtime (long), ctime (long), type (string which is either "directory" or "file"), where the type of each argument is given in brackets. The procedure should therefore return with something like \fIreturn [list dev 0 type file mtime 1234 ...]\fR. .TP \fIcommand\fR \fIutime\fR \fIr-r-a\fR \fIactime\fR \fImtime\fR Set the access and modification times of the given file (these are read with 'stat'). .SH VFS HELPERS .PP The vfslib provides a number of Tcl procedures which can help with writing command procedures to handle the above possibilities. These are: .TP \fBvfs::accessMode\fR \fImode\fR converts an integer \fIaccess\fR mode to a somewhat more preferable string, any of F X W XW R RX RW. .TP \fBvfs::matchDirectories\fR \fItypes\fR Does \fItypes\fR want directories included? .TP \fBvfs::matchFiles\fR \fItypes\fR Does \fItypes\fR want files included? .TP \fBvfs::matchCorrectTypes\fR \fItypes\fR \fIfilelist\fR \fI?inDir?\fR Returns that subset of the \fIfilelist\fR (which are either absolute paths or names of files in \fIinDir\fR) which are compatible with the \fItypes\fR given. .SH VFS DEBUGGING .PP Use something like this to debug problems in your implementation: vfs::filesystem internalerror report ; proc report {} { puts stderr $::errorInfo } .SH LIMITATIONS .PP There are very few limitations to the vfs code. One subtlety that you may encounter is if you mount a case-sensitive virtual filesystem into a case-insensitive system (e.g. the standard Windows or MacOS fs) and your code relies on case-insensitivity, then it will not run properly in the virtual filesystem. Of course if your code relies on case-insensitivity, it wouldn't run under Tcl on Unix either, so the best solution is to fix your code! .PP We may add \fIlink\fR and \fIlstat\fR commands in the future to allow virtual filesystems to support reading and writing links - this is supported by the C API, but has simply not been exposed to Tcl in this extension, yet. .PP The Tcl 'Tcl_FSMatchInDirectory' function takes a variety of type information in a Tcl_GlobTypeData structure. We currently only expose the 'type' field from that structure (so the 'permissions' and MacOS type/creator fields are ignored). .SH KEYWORDS vfs, filesystem, file tclvfs/doc/vfslib.n000064400000000000000000000040331447560765400141660ustar00nobodynobody'\" '\" Copyright (c) 2001, Vince Darley '\" '\" .so man.macros .TH vfslib n 1.0 Vfslib "Tcl-only Virtual File Systems" .BS '\" Note: do not modify the .sh NAME line immediately below! .SH NAME ::vfslib \- Procedures to interact with virtual filesystems .SH SYNOPSIS .BS .sp \fBpackage require Tcl\fR .sp \fBpackage require vfs ?1.2.1?\fR .sp \fBpackage require vfs::zip ?1.0?\fR .sp \fBpackage require vfs::mk4 ?1.6?\fR .sp \fBpackage require vfs::tar ?0.9?\fR .sp \fBpackage require vfs::ftp ?1.0?\fR .sp \fBpackage require vfs::ns ?1.0?\fR .sp \fBpackage require vfs::webdav ?0.1?\fR .sp \fBpackage require vfs::http ?0.5?\fR .sp \fBpackage require vfs::urltype ?1.0?\fR .sp \fBvfs::zip::Mount\fR \fIpath\fR \fIto\fR .sp \fBvfs::ftp::Mount\fR \fIpath\fR \fIto\fR .sp \fBvfs::tar::Mount\fR \fIpath\fR \fIto\fR .sp \fBvfs::http::Mount\fR \fIpath\fR \fIto\fR .sp \fBvfs::mk4::Mount\fR \fIpath\fR \fIto\fR .sp \fBvfs::ns::Mount\fR \fIpath\fR \fIto\fR .sp \fBvfs::urltype::Mount\fR \fItype\fR .sp .BE .SH DESCRIPTION .PP The \fB::vfs\fR package includes a library of Tcl code, implementing a number of different virtual filesystems. Each of these exists as its own package, and can be accessed through \fBpackage require vfs::NAME\fP. The whole set of virtual filesystems is known informally as 'vfslib' .PP .SH SUPPORTED VFS TYPES .PP The current supported types are ftp, tar, http, zip, mk4, ns, webdav. In addition there is the ability to mount any 'urltype' as a new volume, provided an appropriate vfs is supported. This means that you can treat 'ftp://', 'http://' and 'file://' urls as files. To do this, simply evaluate the command .PP \fIvfs::urltype::Mount ftp\fR .PP for instance. Any access inside the new volume will result in an attempt to require a package through 'package require vfs::${type}', which must therefore exist, or errors will be thrown. .PP .SH LIMITATIONS .PP Most of the vfs types listed above have not been very well debugged as yet. Please test them! .SH KEYWORDS vfs, vfslib, filesystem, zip, tar, webdav, namespace, ftp, http, file tclvfs/examples000075500000000000000000000000001447560765400135145ustar00nobodynobodytclvfs/examples/simpleExamples.tcl000064400000000000000000000025471447560765400172770ustar00nobodynobody#!/bin/sh #-*-tcl-*- # the next line restarts using wish \ exec tclsh "$0" ${1+"$@"} catch {console show} puts "(pwd is '[pwd]', file volumes is '[file volumes]')" package require vfs package require vfs::zip package require vfs::urltype package require vfs::ftp package require vfs::http puts "Adding ftp:// volume..." vfs::urltype::Mount ftp set listing [glob -dir ftp://ftp.tcl.tk/pub *] puts "ftp.tcl.tk/pub listing" puts "$listing" puts "----" puts "(file volumes is '[file volumes]')" puts "Adding http:// volume..." vfs::urltype::Mount http set fd [open http://sourceforge.net/projects/tcl] set contents [read $fd] ; close $fd puts "Contents of web page" puts [string range $contents 0 100] puts "(first 100 out of [string length $contents] characters)" puts "----" puts "(file volumes is '[file volumes]')" puts "Mounting ftp://ftp.ucsd.edu/pub/alpha/ ..." vfs::ftp::Mount ftp://ftp.ucsd.edu/pub/alpha/ localmount cd localmount ; cd tcl puts "(pwd is now '[pwd]' which is effectively a transparent link\ to a remote ftp site)" puts "Contents of remote directory is:" foreach file [glob -nocomplain *] { puts "\t$file" } puts "sourcing remote file 'vfsTest.tcl', using 'source vfsTest.tcl'" # This will actually source the contents of a file on the # remote ftp site (which is now the 'pwd'). source vfsTest.tcl puts "Done" tclvfs/generic000075500000000000000000000000001447560765400133125ustar00nobodynobodytclvfs/generic/vfs.c000064400000000000000000001655261447560765400143520ustar00nobodynobody/* * vfs.c -- * * This file contains the implementation of the Vfs extension * to Tcl. It provides a script level interface to Tcl's * virtual file system support, and therefore allows * vfs's to be implemented in Tcl. * * Some of this file could be used as a basis for a hard-coded * vfs implemented in C (e.g. a zipvfs). * * The code is thread-safe. Although under normal use only * one interpreter will be used to add/remove mounts and volumes, * it does cope with multiple interpreters in multiple threads. * * Copyright (c) 2001-2004 Vince Darley. * Copyright (c) 2006 ActiveState Software Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */ #ifdef HAVE_SYS_STAT_H # include #endif /* Required to access the 'stat' structure fields, and TclInExit() */ #include "tclInt.h" #include "tclPort.h" /* * Windows needs to know which symbols to export. Unix does not. * BUILD_vfs should be undefined for Unix. */ #ifdef BUILD_vfs #undef TCL_STORAGE_CLASS #define TCL_STORAGE_CLASS DLLEXPORT #endif /* BUILD_vfs */ #ifndef TCL_GLOB_TYPE_MOUNT #define TCL_GLOB_TYPE_MOUNT (1<<7) #endif /* * tclvfs will return this code instead of TCL_OK/ERROR/etc. to propagate * through the Tcl_Eval* calls to indicate a posix error has been raised by * some vfs implementation. -1 is what Tcl expects, adopts from posix's * standard error value. */ #define TCLVFS_POSIXERROR (-1) #ifndef CONST86 # if TCL_MAJOR_VERSION > 8 # define CONST86 const # else # define CONST86 # endif #endif #if TCL_MAJOR_VERSION < 9 && TCL_MINOR_VERSION < 7 # define Tcl_Size int #endif #if TCL_MAJOR_VERSION > 8 typedef Tcl_Obj *Tcl_SavedResult; #define Tcl_SaveResult(i, r) Tcl_IncrRefCount((*(r) = Tcl_GetObjResult(i))) #define Tcl_RestoreResult(i, r) do {Tcl_SetObjResult(i, *(r)); Tcl_DecrRefCount(*(r));} while (0) #define Tcl_DiscardResult(r) Tcl_DecrRefCount(*(r)) #endif /* * Only the _Init function is exported. */ EXTERN int Vfs_Init(Tcl_Interp*); /* * Functions to add and remove a volume from the list of volumes. * These aren't currently exported, but could be in the future. */ static void Vfs_AddVolume(Tcl_Obj*); static int Vfs_RemoveVolume(Tcl_Obj*); /* * struct Vfs_InterpCmd -- * * Any vfs action which is exposed to Tcl requires both an interpreter * and a command prefix for evaluation. To carry out any filesystem * action inside a vfs, this extension will lappend various additional * parameters to the command string, evaluate it in the interpreter and * then extract the result (the way the result is handled is documented * in each individual vfs callback below). * * We retain a refCount on the 'mountCmd' object, but there is no need * for us to register our interpreter reference, since we will be * made invalid when the interpreter disappears. Also, Tcl_Objs of * "path" type which use one of these structures as part of their * internal representation also do not need to add to any refCounts, * because if this object disappears, all internal representations will * be made invalid. */ typedef struct Vfs_InterpCmd { Tcl_Obj *mountCmd; /* The Tcl command prefix which will be used * to perform all filesystem actions on this * file. */ Tcl_Interp *interp; /* The Tcl interpreter in which the above * command will be evaluated. */ } Vfs_InterpCmd; /* * struct VfsNativeRep -- * * Structure used for the native representation of a path in a Tcl vfs. * To fully specify a file, the string representation is also required. * * When a Tcl interpreter is deleted, all mounts whose callbacks * are in it are removed and freed. This also means that the * global filesystem epoch that Tcl retains is modified, and all * path internal representations are therefore discarded. Therefore we * don't have to worry about vfs files containing stale VfsNativeRep * structures (but it also means we mustn't touch the fsCmd field * of one of these structures if the interpreter has gone). This * means when we free one of these structures, we just free the * memory allocated, and ignore the fsCmd pointer (which may or may * not point to valid memory). */ typedef struct VfsNativeRep { Tcl_Size splitPosition;/* The index into the string representation * of the file which indicates where the * vfs filesystem is mounted. */ Vfs_InterpCmd* fsCmd; /* The Tcl interpreter and command pair * which will be used to perform all filesystem * actions on this file. */ } VfsNativeRep; /* * struct VfsChannelCleanupInfo -- * * Structure we use to retain sufficient information about * a channel that we can properly clean up all resources * when the channel is closed. This is required when using * 'open' on things inside the vfs. * * When the channel in question is begin closed, we will * temporarily register the channel with the given interpreter, * evaluate the closeCallBack, and then detach the channel * from the interpreter and return (allowing Tcl to continue * closing the channel as normal). * * Nothing in the callback can prevent the channel from * being closed. */ typedef struct VfsChannelCleanupInfo { Tcl_Channel channel; /* The channel which needs cleaning up */ Tcl_Obj* closeCallback; /* The Tcl command string to evaluate * when the channel is closing, which will * carry out any cleanup that is necessary. */ Tcl_Interp* interp; /* The interpreter in which to evaluate the * cleanup operation. */ } VfsChannelCleanupInfo; /* * Forward declarations for procedures defined later in this file: */ static int VfsFilesystemObjCmd(ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* * Now we define the virtual filesystem callbacks. Note that some * of these callbacks are passed a Tcl_Interp for error messages. * We will copy over the error messages from the vfs interp to the * calling interp. Currently this is done directly, but we * could investigate using 'TclTransferResult' which would allow * error traces to be copied over as well. */ static Tcl_FSStatProc VfsStat; static Tcl_FSAccessProc VfsAccess; static Tcl_FSOpenFileChannelProc VfsOpenFileChannel; static Tcl_FSMatchInDirectoryProc VfsMatchInDirectory; static Tcl_FSDeleteFileProc VfsDeleteFile; static Tcl_FSCreateDirectoryProc VfsCreateDirectory; static Tcl_FSRemoveDirectoryProc VfsRemoveDirectory; static Tcl_FSFileAttrStringsProc VfsFileAttrStrings; static Tcl_FSFileAttrsGetProc VfsFileAttrsGet; static Tcl_FSFileAttrsSetProc VfsFileAttrsSet; static Tcl_FSUtimeProc VfsUtime; static Tcl_FSPathInFilesystemProc VfsPathInFilesystem; static Tcl_FSFilesystemPathTypeProc VfsFilesystemPathType; static Tcl_FSFilesystemSeparatorProc VfsFilesystemSeparator; static Tcl_FSFreeInternalRepProc VfsFreeInternalRep; static Tcl_FSDupInternalRepProc VfsDupInternalRep; static Tcl_FSListVolumesProc VfsListVolumes; static Tcl_Filesystem vfsFilesystem = { "tclvfs", sizeof(Tcl_Filesystem), TCL_FILESYSTEM_VERSION_1, &VfsPathInFilesystem, &VfsDupInternalRep, &VfsFreeInternalRep, /* No internal to normalized, since we don't create any * pure 'internal' Tcl_Obj path representations */ NULL, /* No create native rep function, since we don't use it * or 'Tcl_FSNewNativePath' */ NULL, /* Normalize path isn't needed - we assume paths only have * one representation */ NULL, &VfsFilesystemPathType, &VfsFilesystemSeparator, &VfsStat, &VfsAccess, &VfsOpenFileChannel, &VfsMatchInDirectory, &VfsUtime, /* We choose not to support symbolic links inside our vfs's */ NULL, &VfsListVolumes, &VfsFileAttrStrings, &VfsFileAttrsGet, &VfsFileAttrsSet, &VfsCreateDirectory, &VfsRemoveDirectory, &VfsDeleteFile, /* No copy file - fallback will occur at Tcl level */ NULL, /* No rename file - fallback will occur at Tcl level */ NULL, /* No copy directory - fallback will occur at Tcl level */ NULL, /* Use stat for lstat */ NULL, /* No load - fallback on core implementation */ NULL, /* We don't need a getcwd or chdir - fallback on Tcl's versions */ NULL, NULL }; /* * struct VfsMount -- * * Each filesystem mount point which is registered will result in * the allocation of one of these structures. They are stored * in a linked list whose head is 'listOfMounts'. */ typedef struct VfsMount { const char* mountPoint; Tcl_Size mountLen; int isVolume; Vfs_InterpCmd interpCmd; struct VfsMount* nextMount; } VfsMount; #define TCL_TSD_INIT(keyPtr) (ThreadSpecificData *)Tcl_GetThreadData((keyPtr), sizeof(ThreadSpecificData)) /* * Declare a thread-specific list of vfs mounts and volumes. * * Stores the list of volumes registered with the vfs (and therefore * also registered with Tcl). It is maintained as a valid Tcl list at * all times, or NULL if there are none (we don't keep it as an empty * list just as a slight optimisation to improve Tcl's efficiency in * determining whether paths are absolute or relative). * * We keep a refCount on this object whenever it is non-NULL. * * internalErrorScript is evaluated when an internal error is detected in * a tclvfs implementation. This is most useful for debugging. * * When it is not NULL we keep a refCount on it. */ typedef struct ThreadSpecificData { VfsMount *listOfMounts; Tcl_Obj *vfsVolumes; Tcl_Obj *internalErrorScript; } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; /* We might wish to consider exporting these in the future */ static int Vfs_AddMount(Tcl_Obj* mountPoint, int isVolume, Tcl_Interp *interp, Tcl_Obj* mountCmd); static int Vfs_RemoveMount(Tcl_Obj* mountPoint, Tcl_Interp* interp); static Vfs_InterpCmd* Vfs_FindMount(Tcl_Obj *pathMount, Tcl_Size mountLen); static Tcl_Obj* Vfs_ListMounts(void); static void Vfs_UnregisterWithInterp(ClientData, Tcl_Interp*); static void Vfs_RegisterWithInterp(Tcl_Interp*); /* Some private helper procedures */ static VfsNativeRep* VfsGetNativePath(Tcl_Obj* pathPtr); static Tcl_CloseProc VfsCloseProc; static void VfsExitProc(ClientData clientData); static void VfsThreadExitProc(ClientData clientData); static Tcl_Obj* VfsFullyNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr); static Tcl_Obj* VfsBuildCommandForPath(Tcl_Interp **iRef, const char* cmd, Tcl_Obj * pathPtr); static void VfsInternalError(Tcl_Interp* interp); /* * Hard-code platform dependencies. We do not need to worry * about backslash-separators on windows, because a normalized * path will never contain them. */ #ifdef MAC_TCL #define VFS_SEPARATOR ':' #else #define VFS_SEPARATOR '/' #endif /* *---------------------------------------------------------------------- * * Vfs_Init -- * * This procedure is the main initialisation point of the Vfs * extension. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Adds a command to the Tcl interpreter. * *---------------------------------------------------------------------- */ #if TCL_MAJOR_VERSION > 8 # define MIN_TCL_VERSION "9.0" #else # define MIN_TCL_VERSION "8.4" #endif int Vfs_Init( Tcl_Interp *interp) /* Interpreter for application. */ { if (Tcl_InitStubs(interp, MIN_TCL_VERSION, 0) == NULL) { return TCL_ERROR; } if (Tcl_PkgRequire(interp, "Tcl", MIN_TCL_VERSION, 0) == NULL) { return TCL_ERROR; } /* * Safe interpreters are not allowed to modify the filesystem! * (Since those modifications will affect other interpreters). */ if (Tcl_IsSafe(interp)) { return TCL_ERROR; } #ifndef PACKAGE_VERSION /* keep in sync with actual version */ #define PACKAGE_VERSION "1.4" #endif if (Tcl_PkgProvide(interp, "vfs", PACKAGE_VERSION) == TCL_ERROR) { return TCL_ERROR; } /* * Create 'vfs::filesystem' command, and interpreter-specific * initialisation. */ Tcl_CreateObjCommand(interp, "vfs::filesystem", VfsFilesystemObjCmd, (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL); Vfs_RegisterWithInterp(interp); return TCL_OK; } /* *---------------------------------------------------------------------- * * Vfs_RegisterWithInterp -- * * Allow the given interpreter to be used to handle vfs callbacks. * * Results: * None. * * Side effects: * May register the entire vfs code (if not previously registered). * Registers some cleanup action for when this interpreter is * deleted. * *---------------------------------------------------------------------- */ static void Vfs_RegisterWithInterp( Tcl_Interp *interp) { ClientData vfsAlreadyRegistered; /* * We need to know if the interpreter is deleted, so we can * remove all interp-specific mounts. */ Tcl_SetAssocData(interp, "vfs::inUse", (Tcl_InterpDeleteProc*) Vfs_UnregisterWithInterp, (ClientData) 1); /* * Perform one-off registering of our filesystem if that * has not happened before. */ vfsAlreadyRegistered = Tcl_FSData(&vfsFilesystem); if (vfsAlreadyRegistered == NULL) { Tcl_FSRegister((ClientData)1, &vfsFilesystem); Tcl_CreateExitHandler(VfsExitProc, (ClientData)NULL); Tcl_CreateThreadExitHandler(VfsThreadExitProc, NULL); } } /* *---------------------------------------------------------------------- * * Vfs_UnregisterWithInterp -- * * Remove all of the mount points that this interpreter handles. * * Results: * None. * * Side effects: * None. * *---------------------------------------------------------------------- */ static void Vfs_UnregisterWithInterp( ClientData dummy, Tcl_Interp *interp) { int res = TCL_OK; /* Remove all of this interpreters mount points */ while (res == TCL_OK) { res = Vfs_RemoveMount(NULL, interp); } } /* *---------------------------------------------------------------------- * * Vfs_AddMount -- * * Adds a new vfs mount point. After this call all filesystem * access within that mount point will be redirected to the * interpreter/mountCmd pair. * * This command must not be called unless 'interp' has already * been registered with 'Vfs_RegisterWithInterp' above. This * usually happens automatically with a 'package require vfs'. * * Results: * TCL_OK unless the inputs are bad or a memory allocation * error occurred, or the interpreter is not vfs-registered. * * Side effects: * A new volume may be added to the list of available volumes. * Future filesystem access inside the mountPoint will be * redirected. Tcl is informed that a new mount has been added * and this will make all cached path representations invalid. * *---------------------------------------------------------------------- */ static int Vfs_AddMount( Tcl_Obj* mountPoint, int isVolume, Tcl_Interp* interp, Tcl_Obj* mountCmd) { char *strRep; Tcl_Size len; VfsMount *newMount; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (mountPoint == NULL || interp == NULL || mountCmd == NULL) { return TCL_ERROR; } /* * Check whether this interpreter can properly clean up * mounts on exit. If not, throw an error. */ if (Tcl_GetAssocData(interp, "vfs::inUse", NULL) == NULL) { return TCL_ERROR; } newMount = (VfsMount*) ckalloc(sizeof(VfsMount)); if (newMount == NULL) { return TCL_ERROR; } strRep = Tcl_GetStringFromObj(mountPoint, &len); newMount->mountPoint = (char*) ckalloc(1+len); newMount->mountLen = len; if (newMount->mountPoint == NULL) { ckfree((char*)newMount); return TCL_ERROR; } strcpy((char*)newMount->mountPoint, strRep); newMount->interpCmd.mountCmd = mountCmd; newMount->interpCmd.interp = interp; newMount->isVolume = isVolume; Tcl_IncrRefCount(mountCmd); newMount->nextMount = tsdPtr->listOfMounts; tsdPtr->listOfMounts = newMount; if (isVolume) { Vfs_AddVolume(mountPoint); } Tcl_FSMountsChanged(&vfsFilesystem); return TCL_OK; } /* *---------------------------------------------------------------------- * * Vfs_RemoveMount -- * * This procedure searches for a matching mount point and removes * it if one is found. If 'mountPoint' is given, then both it and * the interpreter must match for a mount point to be removed. * * If 'mountPoint' is NULL, then the first mount point for the * given interpreter is removed (if any). * * Results: * TCL_OK if a mount was removed, TCL_ERROR otherwise. * * Side effects: * A volume may be removed from the current list of volumes * (as returned by 'file volumes'). A vfs may be removed from * the filesystem. If successful, Tcl will be informed that * the list of current mounts has changed, and all cached file * representations will be made invalid. * *---------------------------------------------------------------------- */ static int Vfs_RemoveMount( Tcl_Obj* mountPoint, Tcl_Interp *interp) { /* These two are only used if mountPoint is non-NULL */ char *strRep = NULL; Tcl_Size len = 0; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); VfsMount *mountIter; /* Set to NULL just to avoid warnings */ VfsMount *lastMount = NULL; if (mountPoint != NULL) { strRep = Tcl_GetStringFromObj(mountPoint, &len); } mountIter = tsdPtr->listOfMounts; while (mountIter != NULL) { if ((interp == mountIter->interpCmd.interp) && ((mountPoint == NULL) || (mountIter->mountLen == len && !strcmp(mountIter->mountPoint, strRep)))) { /* We've found the mount. */ if (mountIter == tsdPtr->listOfMounts) { tsdPtr->listOfMounts = mountIter->nextMount; } else { lastMount->nextMount = mountIter->nextMount; } /* Free the allocated memory */ if (mountIter->isVolume) { if (mountPoint == NULL) { Tcl_Obj *volObj = Tcl_NewStringObj(mountIter->mountPoint, mountIter->mountLen); Tcl_IncrRefCount(volObj); Vfs_RemoveVolume(volObj); Tcl_DecrRefCount(volObj); } else { Vfs_RemoveVolume(mountPoint); } } ckfree((char*)mountIter->mountPoint); Tcl_DecrRefCount(mountIter->interpCmd.mountCmd); ckfree((char*)mountIter); Tcl_FSMountsChanged(&vfsFilesystem); return TCL_OK; } lastMount = mountIter; mountIter = mountIter->nextMount; } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * Vfs_FindMount -- * * This procedure searches all currently mounted paths for one * which matches the given path. The given path must be the * absolute, normalized, unique representation for the given path. * If 'len' is -1, we use the entire string representation of the * mountPoint, otherwise we treat 'len' as the length of the mount * we are comparing. * * Results: * Returns the interpreter, command-prefix pair for the given * mount point, if one is found, otherwise NULL. * * Side effects: * None. * *---------------------------------------------------------------------- */ static Vfs_InterpCmd* Vfs_FindMount( Tcl_Obj *pathMount, Tcl_Size mountLen) { VfsMount *mountIter; char *mountStr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (pathMount == NULL) { return NULL; } if (mountLen < 0) { mountStr = Tcl_GetStringFromObj(pathMount, &mountLen); } else { mountStr = Tcl_GetString(pathMount); } mountIter = tsdPtr->listOfMounts; while (mountIter != NULL) { if (mountIter->mountLen == mountLen && !strncmp(mountIter->mountPoint, mountStr, (size_t)mountLen)) { Vfs_InterpCmd *ret = &mountIter->interpCmd; return ret; } mountIter = mountIter->nextMount; } return NULL; } /* *---------------------------------------------------------------------- * * Vfs_ListMounts -- * * Returns a valid Tcl list, with refCount of zero, containing * all currently mounted paths. * *---------------------------------------------------------------------- */ static Tcl_Obj* Vfs_ListMounts(void) { VfsMount *mountIter; Tcl_Obj *res = Tcl_NewObj(); ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* Build list of mounts */ mountIter = tsdPtr->listOfMounts; while (mountIter != NULL) { Tcl_Obj* mount = Tcl_NewStringObj(mountIter->mountPoint, mountIter->mountLen); Tcl_ListObjAppendElement(NULL, res, mount); mountIter = mountIter->nextMount; } return res; } /* *---------------------------------------------------------------------- * * VfsFilesystemObjCmd -- * * This procedure implements the "vfs::filesystem" command. It is * used to mount/unmount particular interfaces to new filesystems, * or to query for what is mounted where. * * Results: * A standard Tcl result. * * Side effects: * Inserts or removes a filesystem from Tcl's stack. * *---------------------------------------------------------------------- */ static int VfsFilesystemObjCmd( ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]) { int index; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); static const char *optionStrings[] = { "info", "internalerror", "mount", "unmount", "fullynormalize", "posixerror", NULL }; enum options { VFS_INFO, VFS_INTERNAL_ERROR, VFS_MOUNT, VFS_UNMOUNT, VFS_NORMALIZE, VFS_POSIXERROR }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } switch ((enum options) index) { case VFS_INTERNAL_ERROR: { if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "?script?"); return TCL_ERROR; } if (objc == 2) { /* Return the current script */ if (tsdPtr->internalErrorScript != NULL) { Tcl_SetObjResult(interp, tsdPtr->internalErrorScript); } } else { /* Set the script */ Tcl_Size len; if (tsdPtr->internalErrorScript != NULL) { Tcl_DecrRefCount(tsdPtr->internalErrorScript); } Tcl_GetStringFromObj(objv[2], &len); if (len == 0) { /* Clear our script */ tsdPtr->internalErrorScript = NULL; } else { /* Set it */ tsdPtr->internalErrorScript = objv[2]; Tcl_IncrRefCount(tsdPtr->internalErrorScript); } } return TCL_OK; } case VFS_POSIXERROR: { int posixError = -1; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "errorcode"); return TCL_ERROR; } if (Tcl_GetIntFromObj(NULL, objv[2], &posixError) != TCL_OK) { return TCL_ERROR; } Tcl_SetErrno(posixError); /* * This special error code propagate to the Tcl_Eval* calls in * other parts of the vfs C code to indicate a posix error * being raised by some vfs implementation. */ return TCLVFS_POSIXERROR; } case VFS_NORMALIZE: { Tcl_Obj *path; if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "path"); return TCL_ERROR; } path = VfsFullyNormalizePath(interp, objv[2]); if (path == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "not a valid path \"", Tcl_GetString(objv[2]), "\"", (char *) NULL); } else { Tcl_SetObjResult(interp, path); Tcl_DecrRefCount(path); return TCL_OK; } } case VFS_MOUNT: { if (objc < 4 || objc > 5) { Tcl_WrongNumArgs(interp, 1, objv, "mount ?-volume? path cmd"); return TCL_ERROR; } if (objc == 5) { char *option = Tcl_GetString(objv[2]); if (strcmp("-volume", option)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", option, "\": must be -volume", (char *) NULL); return TCL_ERROR; } return Vfs_AddMount(objv[3], 1, interp, objv[4]); } else { Tcl_Obj *path; int retVal; path = VfsFullyNormalizePath(interp, objv[2]); retVal = Vfs_AddMount(path, 0, interp, objv[3]); if (path != NULL) { Tcl_DecrRefCount(path); } return retVal; } break; } case VFS_INFO: { if (objc > 3) { Tcl_WrongNumArgs(interp, 2, objv, "path"); return TCL_ERROR; } if (objc == 2) { Tcl_SetObjResult(interp, Vfs_ListMounts()); } else { Vfs_InterpCmd *val; val = Vfs_FindMount(objv[2], -1); if (val == NULL) { Tcl_Obj *path; path = VfsFullyNormalizePath(interp, objv[2]); val = Vfs_FindMount(path, -1); Tcl_DecrRefCount(path); if (val == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such mount \"", Tcl_GetString(objv[2]), "\"", (char *) NULL); return TCL_ERROR; } } Tcl_SetObjResult(interp, val->mountCmd); } break; } case VFS_UNMOUNT: { if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "path"); return TCL_ERROR; } if (Vfs_RemoveMount(objv[2], interp) == TCL_ERROR) { Tcl_Obj *path; int retVal; path = VfsFullyNormalizePath(interp, objv[2]); retVal = Vfs_RemoveMount(path, interp); Tcl_DecrRefCount(path); if (retVal == TCL_ERROR) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "no such mount \"", Tcl_GetString(objv[2]), "\"", (char *) NULL); return TCL_ERROR; } } return TCL_OK; } } return TCL_OK; } /* Handle an error thrown by a tcl vfs implementation */ static void VfsInternalError(Tcl_Interp* interp) { if (interp != NULL) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->internalErrorScript != NULL) { Tcl_EvalObjEx(interp, tsdPtr->internalErrorScript, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); } } } /* Return fully normalized path owned by the caller */ static Tcl_Obj* VfsFullyNormalizePath(Tcl_Interp *interp, Tcl_Obj *pathPtr) { Tcl_Obj *path; int counter = 0; Tcl_IncrRefCount(pathPtr); while (1) { path = Tcl_FSLink(pathPtr,NULL,0); if (path == NULL) { break; } if (Tcl_FSGetPathType(path) != TCL_PATH_ABSOLUTE) { /* * This is more complex, we need to find the path * relative to the original file, effectively: * * file join [file dirname $pathPtr] $path * * or * * file join $pathPtr .. $path * * So... */ Tcl_Obj *dotdotPtr, *joinedPtr; Tcl_Obj *joinElements[2]; dotdotPtr = Tcl_NewStringObj("..",2); Tcl_IncrRefCount(dotdotPtr); joinElements[0] = dotdotPtr; joinElements[1] = path; joinedPtr = Tcl_FSJoinToPath(pathPtr, 2, joinElements); if (joinedPtr != NULL) { Tcl_IncrRefCount(joinedPtr); Tcl_DecrRefCount(path); path = joinedPtr; } else { /* We failed, and our action is undefined */ } Tcl_DecrRefCount(dotdotPtr); } Tcl_DecrRefCount(pathPtr); pathPtr = path; counter++; if (counter > 10) { /* Too many links */ Tcl_DecrRefCount(pathPtr); return NULL; } } path = Tcl_FSGetNormalizedPath(interp, pathPtr); Tcl_IncrRefCount(path); Tcl_DecrRefCount(pathPtr); return path; } /* *---------------------------------------------------------------------- * * VfsPathInFilesystem -- * * Check whether a path is in any of the mounted points in this * vfs. * * If it is in the vfs, set the clientData given to our private * internal representation for a vfs path. * * Results: * Returns TCL_OK on success, or 'TCLVFS_POSIXERROR' on failure. * If Tcl is exiting, we always return a failure code. * * Side effects: * On success, we allocate some memory for our internal * representation structure. Tcl will call us to free this * when necessary. * *---------------------------------------------------------------------- */ static int VfsPathInFilesystem(Tcl_Obj *pathPtr, ClientData *clientDataPtr) { Tcl_Obj *normedObj; Tcl_Size len, splitPosition; char *normed; VfsNativeRep *nativeRep; Vfs_InterpCmd *interpCmd = NULL; if (TclInExit()) { /* * Even Tcl_FSGetNormalizedPath may fail due to lack of system * encodings, so we just say we can't handle anything if we are * in the middle of the exit sequence. We could perhaps be * more subtle than this! */ return TCLVFS_POSIXERROR; } normedObj = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (normedObj == NULL) { return TCLVFS_POSIXERROR; } normed = Tcl_GetStringFromObj(normedObj, &len); splitPosition = len; /* * Find the most specific mount point for this path. * Mount points are specified by unique strings, so * we have to use a unique normalised path for the * checks here. * * Given mount points are paths, 'most specific' means * longest path, so we scan from end to beginning * checking for valid mount points at each separator. */ while (1) { /* * We need this test here both for an empty string being * passed in above, and so that if we are testing a unix * absolute path /foo/bar we will come around the loop * with splitPosition at 0 for the last iteration, and we * must return then. */ if (splitPosition == 0) { return TCLVFS_POSIXERROR; } /* Is the path up to 'splitPosition' a valid moint point? */ interpCmd = Vfs_FindMount(normedObj, splitPosition); if (interpCmd != NULL) break; while (normed[--splitPosition] != VFS_SEPARATOR) { if (splitPosition == 0) { /* * We've reached the beginning of the string without * finding a mount, so we've failed. */ return TCLVFS_POSIXERROR; } } /* * We now know that normed[splitPosition] is a separator. * However, we might have mounted a root filesystem with a * name (for example 'ftp://') which actually includes a * separator. Therefore we test whether the path with * a separator is a mount point. * * Since we must have decremented splitPosition at least once * already (above) 'splitPosition+1 <= len' so this won't * access invalid memory. */ interpCmd = Vfs_FindMount(normedObj, splitPosition+1); if (interpCmd != NULL) { splitPosition++; break; } } /* * If we reach here we have a valid mount point, since the * only way to escape the above loop is through a 'break' when * an interpCmd is non-NULL. */ nativeRep = (VfsNativeRep*) ckalloc(sizeof(VfsNativeRep)); nativeRep->splitPosition = splitPosition; nativeRep->fsCmd = interpCmd; *clientDataPtr = (ClientData)nativeRep; return TCL_OK; } /* * Simple helper function to extract the native vfs representation of a * path object, or NULL if no such representation exists. */ static VfsNativeRep* VfsGetNativePath(Tcl_Obj* pathPtr) { return (VfsNativeRep*) Tcl_FSGetInternalRep(pathPtr, &vfsFilesystem); } static void VfsFreeInternalRep(ClientData clientData) { VfsNativeRep *nativeRep = (VfsNativeRep*)clientData; if (nativeRep != NULL) { /* Free the native memory allocation */ ckfree((char*)nativeRep); } } static ClientData VfsDupInternalRep(ClientData clientData) { VfsNativeRep *original = (VfsNativeRep*)clientData; VfsNativeRep *nativeRep = (VfsNativeRep*) ckalloc(sizeof(VfsNativeRep)); nativeRep->splitPosition = original->splitPosition; nativeRep->fsCmd = original->fsCmd; return (ClientData)nativeRep; } static Tcl_Obj* VfsFilesystemPathType(Tcl_Obj *pathPtr) { VfsNativeRep* nativeRep = VfsGetNativePath(pathPtr); if (nativeRep == NULL) { return NULL; } else { return nativeRep->fsCmd->mountCmd; } } static Tcl_Obj* VfsFilesystemSeparator(Tcl_Obj* pathPtr) { char sep=VFS_SEPARATOR; return Tcl_NewStringObj(&sep,1); } static int VfsStat( Tcl_Obj *pathPtr, /* Path of file to stat (in current CP). */ Tcl_StatBuf *bufPtr) /* Filled with results of stat call. */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "stat", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } Tcl_SaveResult(interp, &savedResult); /* Now we execute this mount point's callback. */ returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal == TCL_OK) { Tcl_Size statListLength; Tcl_Obj* resPtr = Tcl_GetObjResult(interp); if (Tcl_ListObjLength(interp, resPtr, &statListLength) == TCL_ERROR) { returnVal = TCL_ERROR; } else if (statListLength & 1) { /* It is odd! */ returnVal = TCL_ERROR; } else { /* * The st_mode field is set part by the 'mode' * and part by the 'type' stat fields. */ bufPtr->st_mode = 0; while (statListLength > 0) { Tcl_Obj *field, *val; char *fieldName; statListLength -= 2; Tcl_ListObjIndex(interp, resPtr, statListLength, &field); Tcl_ListObjIndex(interp, resPtr, statListLength+1, &val); fieldName = Tcl_GetString(field); if (!strcmp(fieldName,"dev")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_dev = v; } else if (!strcmp(fieldName,"ino")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_ino = (unsigned short)v; } else if (!strcmp(fieldName,"mode")) { int v; if (Tcl_GetIntFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_mode |= v; } else if (!strcmp(fieldName,"nlink")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_nlink = (short)v; } else if (!strcmp(fieldName,"uid")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_uid = (short)v; } else if (!strcmp(fieldName,"gid")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_gid = (short)v; } else if (!strcmp(fieldName,"size")) { Tcl_WideInt v; if (Tcl_GetWideIntFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_size = v; } else if (!strcmp(fieldName,"atime")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_atime = v; } else if (!strcmp(fieldName,"mtime")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_mtime = v; } else if (!strcmp(fieldName,"ctime")) { long v; if (Tcl_GetLongFromObj(interp, val, &v) != TCL_OK) { returnVal = TCL_ERROR; break; } bufPtr->st_ctime = v; } else if (!strcmp(fieldName,"type")) { char *str; str = Tcl_GetString(val); if (!strcmp(str,"directory")) { bufPtr->st_mode |= S_IFDIR; } else if (!strcmp(str,"file")) { bufPtr->st_mode |= S_IFREG; #ifdef S_ISLNK } else if (!strcmp(str,"link")) { bufPtr->st_mode |= S_IFLNK; #endif } else { /* * Do nothing. This means we do not currently * support anything except files and directories */ } } else { /* Ignore additional stat arguments */ } } } } if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { Tcl_SetErrno(ENOENT); return TCLVFS_POSIXERROR; } else { return returnVal; } } static int VfsAccess( Tcl_Obj *pathPtr, /* Path of file to access (in current CP). */ int mode) /* Permission setting. */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "access", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewIntObj(mode)); /* Now we execute this mount point's callback. */ Tcl_SaveResult(interp, &savedResult); returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); if (returnVal != 0) { Tcl_SetErrno(ENOENT); return TCLVFS_POSIXERROR; } else { return returnVal; } } static Tcl_Obj* VfsGetMode(int mode) { Tcl_Obj *ret = Tcl_NewObj(); if (mode & O_RDONLY) { Tcl_AppendToObj(ret, "r", 1); } else if (mode & O_WRONLY || mode & O_RDWR) { if (mode & O_TRUNC) { Tcl_AppendToObj(ret, "w", 1); } else { Tcl_AppendToObj(ret, "a", 1); } if (mode & O_RDWR) { Tcl_AppendToObj(ret, "+", 1); } } return ret; } static Tcl_Channel VfsOpenFileChannel( Tcl_Interp *cmdInterp, /* Interpreter for error reporting; * can be NULL. */ Tcl_Obj *pathPtr, /* Name of file to open. */ int mode, /* POSIX open mode. */ int permissions) /* If the open involves creating a * file, with what modes to create * it? */ { Tcl_Channel chan = NULL; Tcl_Obj *mountCmd = NULL; Tcl_Obj *closeCallback = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "open", pathPtr); if (mountCmd == NULL) { return NULL; } Tcl_ListObjAppendElement(interp, mountCmd, VfsGetMode(mode)); Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewIntObj(permissions)); Tcl_SaveResult(interp, &savedResult); /* Now we execute this mount point's callback. */ returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal == TCL_OK) { Tcl_Size reslen; Tcl_Obj *resultObj; /* * There may be file channel leaks on these two * error conditions, if the open command actually * created a channel, but then passed us a bogus list. */ resultObj = Tcl_GetObjResult(interp); if ((Tcl_ListObjLength(interp, resultObj, &reslen) == TCL_ERROR) || (reslen > 2) || (reslen == 0)) { returnVal = TCL_ERROR; } else { Tcl_Obj *element; Tcl_ListObjIndex(interp, resultObj, 0, &element); chan = Tcl_GetChannel(interp, Tcl_GetString(element), 0); if (chan == NULL) { returnVal = TCL_ERROR; } else { if (reslen == 2) { Tcl_ListObjIndex(interp, resultObj, 1, &element); closeCallback = element; Tcl_IncrRefCount(closeCallback); } } } Tcl_RestoreResult(interp, &savedResult); } else { /* Leave an error message if the cmdInterp is non NULL */ if (cmdInterp != NULL) { if (returnVal == TCLVFS_POSIXERROR) { Tcl_ResetResult(cmdInterp); Tcl_AppendResult(cmdInterp, "couldn't open \"", Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(cmdInterp), (char *) NULL); } else { Tcl_Obj* error = Tcl_GetObjResult(interp); /* * Copy over the error message to cmdInterp, * duplicating it in case of threading issues. */ Tcl_SetObjResult(cmdInterp, Tcl_DuplicateObj(error)); } } else { /* Report any error, since otherwise it is lost */ if (returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } } if (interp == cmdInterp) { /* * We want our error message to propagate up, * so we want to forget this result */ Tcl_DiscardResult(&savedResult); } else { Tcl_RestoreResult(interp, &savedResult); } } Tcl_DecrRefCount(mountCmd); if (chan != NULL) { /* * We got the Channel from some Tcl code. This means it was * registered with the interpreter. But we want a pristine * channel which hasn't been registered with anyone. We use * Tcl_DetachChannel to do this for us. We must use the * correct interpreter. */ if (Tcl_IsStandardChannel(chan)) { /* * If we have somehow ended up with a VFS channel being a std * channel, it is likely auto-inherited, which we need to reverse. * [Bug 1468291] */ if (chan == Tcl_GetStdChannel(TCL_STDIN)) { Tcl_SetStdChannel(NULL, TCL_STDIN); } else if (chan == Tcl_GetStdChannel(TCL_STDOUT)) { Tcl_SetStdChannel(NULL, TCL_STDOUT); } else if (chan == Tcl_GetStdChannel(TCL_STDERR)) { Tcl_SetStdChannel(NULL, TCL_STDERR); } Tcl_UnregisterChannel(NULL, chan); } Tcl_DetachChannel(interp, chan); if (closeCallback != NULL) { VfsChannelCleanupInfo *channelRet = NULL; channelRet = (VfsChannelCleanupInfo*) ckalloc(sizeof(VfsChannelCleanupInfo)); channelRet->channel = chan; channelRet->interp = interp; channelRet->closeCallback = closeCallback; /* The channelRet structure will be freed in the callback */ Tcl_CreateCloseHandler(chan, &VfsCloseProc, (ClientData)channelRet); } } return chan; } /* * IMPORTANT: This procedure must *not* modify the interpreter's result * this leads to the objResultPtr being corrupted (somehow), and curious * crashes in the future (which are very hard to debug ;-). * * This is particularly important since we are evaluating arbitrary * Tcl code in the callback. * * Also note we are relying on the close-callback to occur just before * the channel is about to be properly closed, but after all output * has been flushed. That way we can, in the callback, read in the * entire contents of the channel and, say, compress it for storage * into a tclkit or zip archive. */ static void VfsCloseProc(ClientData clientData) { VfsChannelCleanupInfo * channelRet = (VfsChannelCleanupInfo*) clientData; int returnVal; Tcl_SavedResult savedResult; Tcl_Channel chan = channelRet->channel; Tcl_Interp * interp = channelRet->interp; Tcl_SaveResult(interp, &savedResult); /* * The interpreter needs to know about the channel, else the Tcl * callback will fail, so we register the channel (this allows * the Tcl code to use the channel's string-name). */ if (!Tcl_IsStandardChannel(chan)) { Tcl_RegisterChannel(interp, chan); } if (!(Tcl_GetChannelMode(chan) & TCL_READABLE)) { /* * We need to make this channel readable, since tclvfs * documents that close callbacks are allowed to read * from the channels we create. */ /* Currently if we reach here we have a bug */ } returnVal = Tcl_EvalObjEx(interp, channelRet->closeCallback, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK) { VfsInternalError(interp); } Tcl_DecrRefCount(channelRet->closeCallback); /* * More complications; we can't just unregister the channel, * because it is in the middle of being cleaned up, and the cleanup * code doesn't like a channel to be closed again while it is * already being closed. So, we do the same trick as above to * unregister it without cleanup. */ if (!Tcl_IsStandardChannel(chan)) { Tcl_DetachChannel(interp, chan); } Tcl_RestoreResult(interp, &savedResult); ckfree((char*)channelRet); } static int VfsMatchInDirectory( Tcl_Interp *cmdInterp, /* Interpreter to receive error msgs. */ Tcl_Obj *returnPtr, /* Object to receive results. */ Tcl_Obj *dirPtr, /* Contains path to directory to search. */ const char *pattern, /* Pattern to match against. */ Tcl_GlobTypeData *types) /* Object containing list of acceptable types. * May be NULL. */ { if ((types != NULL) && (types->type & TCL_GLOB_TYPE_MOUNT)) { VfsMount *mountIter; Tcl_Size len; const char *prefix; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); prefix = Tcl_GetStringFromObj(Tcl_FSGetNormalizedPath(NULL, dirPtr), &len); if (prefix[len-1] == '/') { /* * It's a root directory; we must subtract one for * our comparisons below */ len--; } /* Build list of mounts */ mountIter = tsdPtr->listOfMounts; while (mountIter != NULL) { if (mountIter->mountLen > (len+1) && !strncmp(mountIter->mountPoint, prefix, (size_t)len) && mountIter->mountPoint[len] == '/' && strchr(mountIter->mountPoint+len+1, '/') == NULL && Tcl_StringCaseMatch(mountIter->mountPoint+len+1, pattern, 0)) { Tcl_Obj* mount = Tcl_NewStringObj(mountIter->mountPoint, mountIter->mountLen); Tcl_ListObjAppendElement(NULL, returnPtr, mount); } mountIter = mountIter->nextMount; } return TCL_OK; } else { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; int type = 0; Tcl_Obj *vfsResultPtr = NULL; mountCmd = VfsBuildCommandForPath(&interp, "matchindirectory", dirPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } if (types != NULL) { type = types->type; } if (pattern == NULL) { Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewObj()); } else { Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewStringObj(pattern,-1)); } Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewIntObj(type)); Tcl_SaveResult(interp, &savedResult); /* Now we execute this mount point's callback. */ returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCLVFS_POSIXERROR) { vfsResultPtr = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); if (vfsResultPtr != NULL) { if (returnVal == TCL_OK) { Tcl_IncrRefCount(vfsResultPtr); Tcl_ListObjAppendList(cmdInterp, returnPtr, vfsResultPtr); Tcl_DecrRefCount(vfsResultPtr); } else { if (cmdInterp != NULL) { Tcl_SetObjResult(cmdInterp, vfsResultPtr); } else { Tcl_DecrRefCount(vfsResultPtr); } } } return returnVal; } } static int VfsDeleteFile( Tcl_Obj *pathPtr) /* Pathname of file to be removed */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "deletefile", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } /* Now we execute this mount point's callback. */ Tcl_SaveResult(interp, &savedResult); returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); return returnVal; } static int VfsCreateDirectory( Tcl_Obj *pathPtr) /* Pathname of directory to create */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "createdirectory", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } /* Now we execute this mount point's callback. */ Tcl_SaveResult(interp, &savedResult); returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); return returnVal; } static int VfsRemoveDirectory( Tcl_Obj *pathPtr, /* Pathname of directory to be removed * (UTF-8). */ int recursive, /* If non-zero, removes directories that * are nonempty. Otherwise, will only remove * empty directories. */ Tcl_Obj **errorPtr) /* Location to store name of file * causing error. */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "removedirectory", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewIntObj(recursive)); /* Now we execute this mount point's callback. */ Tcl_SaveResult(interp, &savedResult); returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); if (returnVal == TCL_ERROR) { /* Assume there was a problem with the directory being non-empty */ if (errorPtr != NULL) { *errorPtr = pathPtr; Tcl_IncrRefCount(*errorPtr); } Tcl_SetErrno(EEXIST); } return returnVal; } static const char * CONST86 * VfsFileAttrStrings( Tcl_Obj* pathPtr, Tcl_Obj** objPtrRef) { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "fileattributes", pathPtr); if (mountCmd == NULL) { *objPtrRef = NULL; return NULL; } Tcl_SaveResult(interp, &savedResult); /* Now we execute this mount point's callback. */ returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } if (returnVal == TCL_OK) { *objPtrRef = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); } else { *objPtrRef = NULL; } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); return NULL; } static int VfsFileAttrsGet( Tcl_Interp *cmdInterp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *pathPtr, /* filename we are operating on. */ Tcl_Obj **objPtrRef) /* for output. */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "fileattributes", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewIntObj(index)); Tcl_SaveResult(interp, &savedResult); /* Now we execute this mount point's callback. */ returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCLVFS_POSIXERROR) { *objPtrRef = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); if (returnVal != TCLVFS_POSIXERROR) { if (returnVal == TCL_OK) { /* * Our caller expects a ref count of zero in * the returned object pointer. */ } else { /* Leave error message in correct interp */ if (cmdInterp != NULL) { Tcl_SetObjResult(cmdInterp, *objPtrRef); } else { Tcl_DecrRefCount(*objPtrRef); } *objPtrRef = NULL; } } else { if (cmdInterp != NULL) { Tcl_ResetResult(cmdInterp); Tcl_AppendResult(cmdInterp, "couldn't read attributes for \"", Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(cmdInterp), (char *) NULL); } } return returnVal; } static int VfsFileAttrsSet( Tcl_Interp *cmdInterp, /* The interpreter for error reporting. */ int index, /* index of the attribute command. */ Tcl_Obj *pathPtr, /* filename we are operating on. */ Tcl_Obj *objPtr) /* for input. */ { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; Tcl_Obj *errorPtr = NULL; mountCmd = VfsBuildCommandForPath(&interp, "fileattributes", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewIntObj(index)); Tcl_ListObjAppendElement(interp, mountCmd, objPtr); Tcl_SaveResult(interp, &savedResult); /* Now we execute this mount point's callback. */ returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCLVFS_POSIXERROR && returnVal != TCL_OK) { errorPtr = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); if (cmdInterp != NULL) { if (returnVal == TCLVFS_POSIXERROR) { Tcl_ResetResult(cmdInterp); Tcl_AppendResult(cmdInterp, "couldn't set attributes for \"", Tcl_GetString(pathPtr), "\": ", Tcl_PosixError(cmdInterp), (char *) NULL); } else if (errorPtr != NULL) { /* * Leave error message in correct interp, errorPtr was * duplicated above, in case of threading issues. */ Tcl_SetObjResult(cmdInterp, errorPtr); } } else if (errorPtr != NULL) { Tcl_DecrRefCount(errorPtr); } return returnVal; } static int VfsUtime( Tcl_Obj* pathPtr, struct utimbuf *tval) { Tcl_Obj *mountCmd = NULL; Tcl_SavedResult savedResult; int returnVal; Tcl_Interp* interp; mountCmd = VfsBuildCommandForPath(&interp, "utime", pathPtr); if (mountCmd == NULL) { return TCLVFS_POSIXERROR; } Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewLongObj(tval->actime)); Tcl_ListObjAppendElement(interp, mountCmd, Tcl_NewLongObj(tval->modtime)); /* Now we execute this mount point's callback. */ Tcl_SaveResult(interp, &savedResult); returnVal = Tcl_EvalObjEx(interp, mountCmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT); if (returnVal != TCL_OK && returnVal != TCLVFS_POSIXERROR) { VfsInternalError(interp); } Tcl_RestoreResult(interp, &savedResult); Tcl_DecrRefCount(mountCmd); return returnVal; } static Tcl_Obj* VfsListVolumes(void) { Tcl_Obj *retVal; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->vfsVolumes != NULL) { Tcl_IncrRefCount(tsdPtr->vfsVolumes); retVal = tsdPtr->vfsVolumes; } else { retVal = NULL; } return retVal; } static void Vfs_AddVolume( Tcl_Obj *volume) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); if (tsdPtr->vfsVolumes == NULL) { tsdPtr->vfsVolumes = Tcl_NewObj(); Tcl_IncrRefCount(tsdPtr->vfsVolumes); } else { #if 0 if (Tcl_IsShared(tsdPtr->vfsVolumes)) { /* * Another thread is using this object, so we duplicate the * object and reduce the refCount on the shared one. */ Tcl_Obj *oldVols = tsdPtr->vfsVolumes; tsdPtr->vfsVolumes = Tcl_DuplicateObj(oldVols); Tcl_IncrRefCount(tsdPtr->vfsVolumes); Tcl_DecrRefCount(oldVols); } #endif } Tcl_ListObjAppendElement(NULL, tsdPtr->vfsVolumes, volume); } static int Vfs_RemoveVolume( Tcl_Obj *volume) { Tcl_Size i, len; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Tcl_ListObjLength(NULL, tsdPtr->vfsVolumes, &len); for (i = 0;i < len; i++) { Tcl_Obj *vol; Tcl_ListObjIndex(NULL, tsdPtr->vfsVolumes, i, &vol); if (!strcmp(Tcl_GetString(vol),Tcl_GetString(volume))) { /* It's in the list, at index i */ if (len == 1) { /* An optimization here */ Tcl_DecrRefCount(tsdPtr->vfsVolumes); tsdPtr->vfsVolumes = NULL; } else { /* * Make ourselves the unique owner * XXX: May be unnecessary now that it is tsd */ if (Tcl_IsShared(tsdPtr->vfsVolumes)) { Tcl_Obj *oldVols = tsdPtr->vfsVolumes; tsdPtr->vfsVolumes = Tcl_DuplicateObj(oldVols); Tcl_IncrRefCount(tsdPtr->vfsVolumes); Tcl_DecrRefCount(oldVols); } /* Remove the element */ Tcl_ListObjReplace(NULL, tsdPtr->vfsVolumes, i, 1, 0, NULL); return TCL_OK; } } } return TCL_ERROR; } /* *---------------------------------------------------------------------- * * VfsBuildCommandForPath -- * * Given a path object which we know belongs to the vfs, and a * command string (one of the standard filesystem operations * "stat", "matchindirectory" etc), build the standard vfs * Tcl command and arguments to carry out that operation. * * If the command is successfully built, it is returned to the * caller with a refCount of 1. The caller also needs to know * which Tcl interpreter to evaluate the command in; this * is returned in the 'iRef' provided. * * Each mount-point dictates a command prefix to use for a * particular file. We start with that and then add 4 parameters, * as follows: * * (1) the 'cmd' to use * (2) the mount point of this path (which is the portion of the * path string which lies outside the vfs). * (3) the remainder of the path which lies inside the vfs * (4) the original (possibly unnormalized) path string used * in the command. * * Example (i): * * If 'C:/Apps/data.zip' is mounted on top of * itself, then if we do: * * cd C:/Apps * file exists data.zip/foo/bar.txt * * this will lead to: * * "access" C:/Apps/data.zip foo/bar.txt data.zip/foo/bar.txt * * Example (ii) * * If 'ftp://' is mounted as a new volume, * then 'glob -dir ftp://ftp.scriptics.com *' will lead to: * * "matchindirectory" ftp:// ftp.scriptics.com \ * ftp://ftp.scriptics.com * * * Results: * Returns a list containing the command, or NULL if an * error occurred. If the interpreter for this vfs command * is in the process of being deleted, we always return NULL. * * Side effects: * None except memory allocation. * *---------------------------------------------------------------------- */ static Tcl_Obj* VfsBuildCommandForPath(Tcl_Interp **iRef, const char* cmd, Tcl_Obj *pathPtr) { Tcl_Obj *normed; Tcl_Obj *mountCmd; Tcl_Size len; Tcl_Size splitPosition; Tcl_Size dummyLen; VfsNativeRep *nativeRep; Tcl_Interp *interp; char *normedString; nativeRep = VfsGetNativePath(pathPtr); if (nativeRep == NULL) { return NULL; } interp = nativeRep->fsCmd->interp; if (Tcl_InterpDeleted(interp)) { return NULL; } mountCmd = Tcl_DuplicateObj(nativeRep->fsCmd->mountCmd); Tcl_IncrRefCount(mountCmd); if (Tcl_ListObjLength(NULL, mountCmd, &dummyLen) == TCL_ERROR) { Tcl_DecrRefCount(mountCmd); return NULL; } splitPosition = nativeRep->splitPosition; normed = Tcl_FSGetNormalizedPath(NULL, pathPtr); normedString = Tcl_GetStringFromObj(normed, &len); Tcl_ListObjAppendElement(NULL, mountCmd, Tcl_NewStringObj(cmd,-1)); if (splitPosition == len) { Tcl_ListObjAppendElement(NULL, mountCmd, normed); Tcl_ListObjAppendElement(NULL, mountCmd, Tcl_NewStringObj("",0)); } else { Tcl_ListObjAppendElement(NULL, mountCmd, Tcl_NewStringObj(normedString,splitPosition)); if ((normedString[splitPosition] != VFS_SEPARATOR) || (VFS_SEPARATOR ==':')) { /* This will occur if we mount 'ftp://' */ splitPosition--; } Tcl_ListObjAppendElement(NULL, mountCmd, Tcl_NewStringObj(normedString+splitPosition+1, len-splitPosition-1)); } Tcl_ListObjAppendElement(NULL, mountCmd, pathPtr); if (iRef != NULL) { *iRef = interp; } return mountCmd; } static void VfsExitProc(ClientData clientData) { Tcl_FSUnregister(&vfsFilesystem); } static void VfsThreadExitProc(ClientData clientData) { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); /* * This is probably no longer needed, because each individual * interp's cleanup will trigger removal of all volumes which * belong to it. */ if (tsdPtr->vfsVolumes != NULL) { Tcl_DecrRefCount(tsdPtr->vfsVolumes); tsdPtr->vfsVolumes = NULL; } if (tsdPtr->internalErrorScript != NULL) { Tcl_DecrRefCount(tsdPtr->internalErrorScript); tsdPtr->internalErrorScript = NULL; } } tclvfs/http2.6000075500000000000000000000000001447560765400131035ustar00nobodynobodytclvfs/http2.6/http.n000064400000000000000000000476771447560765400143450ustar00nobodynobody'\" '\" Copyright (c) 1995-1997 Sun Microsystems, Inc. '\" Copyright (c) 1998-2000 by Ajuba Solutions. '\" '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" '\" RCS: @(#) $Id: http.n,v 1.2 2008/03/11 02:15:22 hobbs Exp $ '\" .so man.macros .TH "Http" n 8.4 Tcl "Tcl Built-In Commands" .BS '\" Note: do not modify the .SH NAME line immediately below! .SH NAME Http \- Client-side implementation of the HTTP/1.1 protocol. .SH SYNOPSIS \fBpackage require http ?2.6?\fP .sp \fB::http::config \fI?options?\fR .sp \fB::http::geturl \fIurl ?options?\fR .sp \fB::http::formatQuery \fIlist\fR .sp \fB::http::reset \fItoken\fR .sp \fB::http::wait \fItoken\fR .sp \fB::http::status \fItoken\fR .sp \fB::http::size \fItoken\fR .sp \fB::http::code \fItoken\fR .sp \fB::http::ncode \fItoken\fR .sp \fB::http::data \fItoken\fR .sp \fB::http::error \fItoken\fR .sp \fB::http::cleanup \fItoken\fR .sp \fB::http::register \fIproto port command\fR .sp \fB::http::unregister \fIproto\fR .BE .SH DESCRIPTION .PP The \fBhttp\fR package provides the client side of the HTTP/1.1 protocol. The package implements the GET, POST, and HEAD operations of HTTP/1.1. It allows configuration of a proxy host to get through firewalls. The package is compatible with the \fBSafesock\fR security policy, so it can be used by untrusted applets to do URL fetching from a restricted set of hosts. This package can be extened to support additional HTTP transport protocols, such as HTTPS, by providing a custom \fBsocket\fR command, via \fBhttp::register\fR. .PP The \fB::http::geturl\fR procedure does a HTTP transaction. Its \fIoptions \fR determine whether a GET, POST, or HEAD transaction is performed. The return value of \fB::http::geturl\fR is a token for the transaction. The value is also the name of an array in the ::http namespace that contains state information about the transaction. The elements of this array are described in the STATE ARRAY section. .PP If the \fB-command\fP option is specified, then the HTTP operation is done in the background. \fB::http::geturl\fR returns immediately after generating the HTTP request and the callback is invoked when the transaction completes. For this to work, the Tcl event loop must be active. In Tk applications this is always true. For pure-Tcl applications, the caller can use \fB::http::wait\fR after calling \fB::http::geturl\fR to start the event loop. .SH COMMANDS .TP \fB::http::config\fP ?\fIoptions\fR? The \fB::http::config\fR command is used to set and query the name of the proxy server and port, and the User-Agent name used in the HTTP requests. If no options are specified, then the current configuration is returned. If a single argument is specified, then it should be one of the flags described below. In this case the current value of that setting is returned. Otherwise, the options should be a set of flags and values that define the configuration: .RS .TP \fB\-accept\fP \fImimetypes\fP The Accept header of the request. The default is */*, which means that all types of documents are accepted. Otherwise you can supply a comma separated list of mime type patterns that you are willing to receive. For example, "image/gif, image/jpeg, text/*". .TP \fB\-proxyhost\fP \fIhostname\fP The name of the proxy host, if any. If this value is the empty string, the URL host is contacted directly. .TP \fB\-proxyport\fP \fInumber\fP The proxy port number. .TP \fB\-proxyfilter\fP \fIcommand\fP The command is a callback that is made during \fB::http::geturl\fR to determine if a proxy is required for a given host. One argument, a host name, is added to \fIcommand\fR when it is invoked. If a proxy is required, the callback should return a two element list containing the proxy server and proxy port. Otherwise the filter should return an empty list. The default filter returns the values of the \fB\-proxyhost\fR and \fB\-proxyport\fR settings if they are non-empty. .TP \fB\-useragent\fP \fIstring\fP The value of the User-Agent header in the HTTP request. The default is \fB"Tcl http client package 2.2."\fR .RE .TP \fB::http::geturl\fP \fIurl\fP ?\fIoptions\fP? The \fB::http::geturl\fR command is the main procedure in the package. The \fB\-query\fR option causes a POST operation and the \fB\-validate\fR option causes a HEAD operation; otherwise, a GET operation is performed. The \fB::http::geturl\fR command returns a \fItoken\fR value that can be used to get information about the transaction. See the STATE ARRAY and ERRORS section for details. The \fB::http::geturl\fR command blocks until the operation completes, unless the \fB\-command\fR option specifies a callback that is invoked when the HTTP transaction completes. \fB::http::geturl\fR takes several options: .RS .TP \fB\-binary\fP \fIboolean\fP Specifies whether to force interpreting the url data as binary. Normally this is auto-detected (anything not beginning with a \fBtext\fR content type or whose content encoding is \fBgzip\fR or \fBcompress\fR is considered binary data). .TP \fB\-blocksize\fP \fIsize\fP The blocksize used when reading the URL. At most \fIsize\fR bytes are read at once. After each block, a call to the \fB\-progress\fR callback is made (if that option is specified). .TP \fB\-channel\fP \fIname\fP Copy the URL contents to channel \fIname\fR instead of saving it in \fBstate(body)\fR. .TP \fB\-command\fP \fIcallback\fP Invoke \fIcallback\fP after the HTTP transaction completes. This option causes \fB::http::geturl\fP to return immediately. The \fIcallback\fP gets an additional argument that is the \fItoken\fR returned from \fB::http::geturl\fR. This token is the name of an array that is described in the STATE ARRAY section. Here is a template for the callback: .RS .CS proc httpCallback {token} { upvar #0 $token state # Access state as a Tcl array } .CE .RE .TP \fB\-handler\fP \fIcallback\fP Invoke \fIcallback\fP whenever HTTP data is available; if present, nothing else will be done with the HTTP data. This procedure gets two additional arguments: the socket for the HTTP data and the \fItoken\fR returned from \fB::http::geturl\fR. The token is the name of a global array that is described in the STATE ARRAY section. The procedure is expected to return the number of bytes read from the socket. Here is a template for the callback: .RS .CS proc httpHandlerCallback {socket token} { upvar #0 $token state # Access socket, and state as a Tcl array ... (example: set data [read $socket 1000];set nbytes [string length $data]) ... return nbytes } .CE .RE .TP \fB\-headers\fP \fIkeyvaluelist\fP This option is used to add extra headers to the HTTP request. The \fIkeyvaluelist\fR argument must be a list with an even number of elements that alternate between keys and values. The keys become header field names. Newlines are stripped from the values so the header cannot be corrupted. For example, if \fIkeyvaluelist\fR is \fBPragma no-cache\fR then the following header is included in the HTTP request: .CS Pragma: no-cache .CE .TP \fB\-progress\fP \fIcallback\fP The \fIcallback\fR is made after each transfer of data from the URL. The callback gets three additional arguments: the \fItoken\fR from \fB::http::geturl\fR, the expected total size of the contents from the \fBContent-Length\fR meta-data, and the current number of bytes transferred so far. The expected total size may be unknown, in which case zero is passed to the callback. Here is a template for the progress callback: .RS .CS proc httpProgress {token total current} { upvar #0 $token state } .CE .RE .TP \fB\-query\fP \fIquery\fP This flag causes \fB::http::geturl\fR to do a POST request that passes the \fIquery\fR to the server. The \fIquery\fR must be a x-url-encoding formatted query. The \fB::http::formatQuery\fR procedure can be used to do the formatting. .TP \fB\-queryblocksize\fP \fIsize\fP The blocksize used when posting query data to the URL. At most \fIsize\fR bytes are written at once. After each block, a call to the \fB\-queryprogress\fR callback is made (if that option is specified). .TP \fB\-querychannel\fP \fIchannelID\fP This flag causes \fB::http::geturl\fR to do a POST request that passes the data contained in \fIchannelID\fR to the server. The data contained in \fIchannelID\fR must be a x-url-encoding formatted query unless the \fB\-type\fP option below is used. If a Content-Length header is not specified via the \fB\-headers\fR options, \fB::http::geturl\fR attempts to determine the size of the post data in order to create that header. If it is unable to determine the size, it returns an error. .TP \fB\-queryprogress\fP \fIcallback\fP The \fIcallback\fR is made after each transfer of data to the URL (i.e. POST) and acts exactly like the \fB\-progress\fR option (the callback format is the same). .TP \fB\-timeout\fP \fImilliseconds\fP If \fImilliseconds\fR is non-zero, then \fB::http::geturl\fR sets up a timeout to occur after the specified number of milliseconds. A timeout results in a call to \fB::http::reset\fP and to the \fB-command\fP callback, if specified. The return value of \fB::http::status\fP is \fBtimeout\fP after a timeout has occurred. .TP \fB\-type\fP \fImime-type\fP Use \fImime-type\fR as the \fBContent-Type\fR value, instead of the default value (\fBapplication/x-www-form-urlencoded\fR) during a POST operation. .TP \fB\-validate\fP \fIboolean\fP If \fIboolean\fR is non-zero, then \fB::http::geturl\fR does an HTTP HEAD request. This request returns meta information about the URL, but the contents are not returned. The meta information is available in the \fBstate(meta) \fR variable after the transaction. See the STATE ARRAY section for details. .TP \fB\-protocol\fP \fIversion\fP Select the HTTP protocol version to use. This can really only be 1.0 or 1.1. The default is 1.1. Should only be necessary for servers that do not understand or otherwise complain about HTTP/1.1. .TP \fB\-keepalive\fP \fIboolean\fP If true, attempt to keep the connection open for servicing multiple requests. .TP \fB\-socketvar\fP \fIvariablename\fP Provide a name of a variable to hold the channel used for multiple requests. After the first HTTP transaction the named variable will contain the channel name. Further requests can be made on the open channel until either a request is made with the \fB-keepalive\fR flag set to false or until the remote host closes the connection. Once the connection is closed the variable will be reset to the empty string. See MULTIPLE REQUESTS. .RE .TP \fB::http::formatQuery\fP \fIkey value\fP ?\fIkey value\fP ...? This procedure does x-url-encoding of query data. It takes an even number of arguments that are the keys and values of the query. It encodes the keys and values, and generates one string that has the proper & and = separators. The result is suitable for the \fB\-query\fR value passed to \fB::http::geturl\fR. .TP \fB::http::reset\fP \fItoken\fP ?\fIwhy\fP? This command resets the HTTP transaction identified by \fItoken\fR, if any. This sets the \fBstate(status)\fP value to \fIwhy\fP, which defaults to \fBreset\fR, and then calls the registered \fB\-command\fR callback. .TP \fB::http::wait\fP \fItoken\fP This is a convenience procedure that blocks and waits for the transaction to complete. This only works in trusted code because it uses \fBvwait\fR. Also, it's not useful for the case where \fB::http::geturl\fP is called \fIwithout\fP the \fB-command\fP option because in this case the \fB::http::geturl\fP call doesn't return until the HTTP transaction is complete, and thus there's nothing to wait for. .TP \fB::http::data\fP \fItoken\fP This is a convenience procedure that returns the \fBbody\fP element (i.e., the URL data) of the state array. .TP \fB::http::error\fP \fItoken\fP This is a convenience procedure that returns the \fBerror\fP element of the state array. .TP \fB::http::status\fP \fItoken\fP This is a convenience procedure that returns the \fBstatus\fP element of the state array. .TP \fB::http::code\fP \fItoken\fP This is a convenience procedure that returns the \fBhttp\fP element of the state array. .TP \fB::http::ncode\fP \fItoken\fP This is a convenience procedure that returns just the numeric return code (200, 404, etc.) from the \fBhttp\fP element of the state array. .TP \fB::http::size\fP \fItoken\fP This is a convenience procedure that returns the \fBcurrentsize\fP element of the state array, which represents the number of bytes received from the URL in the \fB::http::geturl\fP call. .TP \fB::http::cleanup\fP \fItoken\fP This procedure cleans up the state associated with the connection identified by \fItoken\fP. After this call, the procedures like \fB::http::data\fP cannot be used to get information about the operation. It is \fIstrongly\fP recommended that you call this function after you're done with a given HTTP request. Not doing so will result in memory not being freed, and if your app calls \fB::http::geturl\fP enough times, the memory leak could cause a performance hit...or worse. .TP \fB::http::register\fP \fIproto port command\fP This procedure allows one to provide custom HTTP transport types such as HTTPS, by registering a prefix, the default port, and the command to execute to create the Tcl \fBchannel\fR. E.g.: .RS .CS package require http package require tls http::register https 443 ::tls::socket set token [http::geturl https://my.secure.site/] .CE .RE .TP \fB::http::unregister\fP \fIproto\fP This procedure unregisters a protocol handler that was previously registered via \fBhttp::register\fR. .SH "ERRORS" The \fBhttp::geturl\fP procedure will raise errors in the following cases: invalid command line options, an invalid URL, a URL on a non-existent host, or a URL at a bad port on an existing host. These errors mean that it cannot even start the network transaction. It will also raise an error if it gets an I/O error while writing out the HTTP request header. For synchronous \fB::http::geturl\fP calls (where \fB-command\fP is not specified), it will raise an error if it gets an I/O error while reading the HTTP reply headers or data. Because \fB::http::geturl\fP doesn't return a token in these cases, it does all the required cleanup and there's no issue of your app having to call \fB::http::cleanup\fP. .PP For asynchronous \fB::http::geturl\fP calls, all of the above error situations apply, except that if there's any error while reading the HTTP reply headers or data, no exception is thrown. This is because after writing the HTTP headers, \fB::http::geturl\fP returns, and the rest of the HTTP transaction occurs in the background. The command callback can check if any error occurred during the read by calling \fB::http::status\fP to check the status and if it's \fIerror\fP, calling \fB::http::error\fP to get the error message. .PP Alternatively, if the main program flow reaches a point where it needs to know the result of the asynchronous HTTP request, it can call \fB::http::wait\fP and then check status and error, just as the callback does. .PP In any case, you must still call \fBhttp::cleanup\fP to delete the state array when you're done. .PP There are other possible results of the HTTP transaction determined by examining the status from \fBhttp::status\fP. These are described below. .TP ok If the HTTP transaction completes entirely, then status will be \fBok\fP. However, you should still check the \fBhttp::code\fP value to get the HTTP status. The \fBhttp::ncode\fP procedure provides just the numeric error (e.g., 200, 404 or 500) while the \fBhttp::code\fP procedure returns a value like "HTTP 404 File not found". .TP eof If the server closes the socket without replying, then no error is raised, but the status of the transaction will be \fBeof\fP. .TP error The error message will also be stored in the \fBerror\fP status array element, accessible via \fB::http::error\fP. .PP Another error possibility is that \fBhttp::geturl\fP is unable to write all the post query data to the server before the server responds and closes the socket. The error message is saved in the \fBposterror\fP status array element and then \fBhttp::geturl\fP attempts to complete the transaction. If it can read the server's response it will end up with an \fBok\fP status, otherwise it will have an \fBeof\fP status. .SH "STATE ARRAY" The \fB::http::geturl\fR procedure returns a \fItoken\fR that can be used to get to the state of the HTTP transaction in the form of a Tcl array. Use this construct to create an easy-to-use array variable: .CS upvar #0 $token state .CE Once the data associated with the url is no longer needed, the state array should be unset to free up storage. The \fBhttp::cleanup\fP procedure is provided for that purpose. The following elements of the array are supported: .RS .TP \fBbody\fR The contents of the URL. This will be empty if the \fB\-channel\fR option has been specified. This value is returned by the \fB::http::data\fP command. .TP \fBcharset\fR The value of the charset attribute from the \fBContent-Type\fR meta-data value. If none was specified, this defaults to the RFC standard \fBiso8859-1\fR, or the value of \fB$::http::defaultCharset\fR. Incoming text data will be automatically converted from this charset to utf-8. .TP \fBcoding\fR A copy of the \fBContent-Encoding\fR meta-data value. .TP \fBcurrentsize\fR The current number of bytes fetched from the URL. This value is returned by the \fB::http::size\fP command. .TP \fBerror\fR If defined, this is the error string seen when the HTTP transaction was aborted. .TP \fBhttp\fR The HTTP status reply from the server. This value is returned by the \fB::http::code\fP command. The format of this value is: .RS .CS \fIHTTP/1.0 code string\fP .CE The \fIcode\fR is a three-digit number defined in the HTTP standard. A code of 200 is OK. Codes beginning with 4 or 5 indicate errors. Codes beginning with 3 are redirection errors. In this case the \fBLocation\fR meta-data specifies a new URL that contains the requested information. .RE .TP \fBmeta\fR The HTTP protocol returns meta-data that describes the URL contents. The \fBmeta\fR element of the state array is a list of the keys and values of the meta-data. This is in a format useful for initializing an array that just contains the meta-data: .RS .CS array set meta $state(meta) .CE Some of the meta-data keys are listed below, but the HTTP standard defines more, and servers are free to add their own. .TP \fBContent-Type\fR The type of the URL contents. Examples include \fBtext/html\fR, \fBimage/gif,\fR \fBapplication/postscript\fR and \fBapplication/x-tcl\fR. .TP \fBContent-Length\fR The advertised size of the contents. The actual size obtained by \fB::http::geturl\fR is available as \fBstate(size)\fR. .TP \fBLocation\fR An alternate URL that contains the requested data. .RE .TP \fBposterror\fR The error, if any, that occurred while writing the post query data to the server. .TP \fBstatus\fR Either \fBok\fR, for successful completion, \fBreset\fR for user-reset, \fBtimeout\fP if a timeout occurred before the transaction could complete, or \fBerror\fR for an error condition. During the transaction this value is the empty string. .TP \fBtotalsize\fR A copy of the \fBContent-Length\fR meta-data value. .TP \fBtype\fR A copy of the \fBContent-Type\fR meta-data value. .TP \fBurl\fR The requested URL. .RE .SH EXAMPLE .DS # Copy a URL to a file and print meta-data proc ::http::copy { url file {chunk 4096} } { set out [open $file w] set token [geturl $url -channel $out -progress ::http::Progress \\ -blocksize $chunk] close $out # This ends the line started by http::Progress puts stderr "" upvar #0 $token state set max 0 foreach {name value} $state(meta) { if {[string length $name] > $max} { set max [string length $name] } if {[regexp -nocase ^location$ $name]} { # Handle URL redirects puts stderr "Location:$value" return [copy [string trim $value] $file $chunk] } } incr max foreach {name value} $state(meta) { puts [format "%-*s %s" $max $name: $value] } return $token } proc ::http::Progress {args} { puts -nonewline stderr . ; flush stderr } .DE .SH "SEE ALSO" safe(n), socket(n), safesock(n) .SH KEYWORDS security policy, socket tclvfs/http2.6/http.tcl000064400000000000000000001173661447560765400146630ustar00nobodynobody# http.tcl -- # # Client-side HTTP for GET, POST, and HEAD commands. These routines can # be used in untrusted code that uses the Safesock security policy. These # procedures use a callback interface to avoid using vwait, which is not # defined in the safe base. # # See the file "license.terms" for information on usage and redistribution of # this file, and for a DISCLAIMER OF ALL WARRANTIES. # # RCS: @(#) $Id: http.tcl,v 1.8 2008/08/11 22:14:26 patthoyts Exp $ # Rough version history post-core-split: # 2.5 Added HTTP/1.1 support for persistent connections. New options # -protocol, -keepalive, -socketvar. (Pat Thoyts) # 2.6 Added support for HTTP/1.1 extensions. New option -method used # for WebDav. (Vince Darley) # 2.6.1 Synchronized with Tcl http 2.4.4 (encoding enhancements) # 2.6.2 Removed to -socketvar option and now handle socket usage internally # 2.6.3 Added support for chunked encoding. # 2.6.4 Merged in jcw's webdav mods to fix the chunked transfer # 2.6.5 Merged up to 2.5.3 from tcl cvs (formMap, url decomposition) # 2.6.6 Support content-encoding gzip. Handle 0 length body in chunked. # 2.6.7 Merged up to 2.5.5 from tcl cvs, whitespace corrections # 2.6.8 Merged with core version in 8.5.2 and 8.4.19 and above changes. # Core is 2.7, this v2.6.8 has defaultKeepalive 1 and different # default -useragent. # 2.6.9 Merged fix for zlib crc check on 64bit systems. package require Tcl # keep this in sync with pkgIndex.tcl package provide http 2.6.9 namespace eval http { # Allow resourcing to not clobber existing data variable http if {![info exists http]} { array set http { -accept */* -proxyhost {} -proxyport {} -proxyfilter http::ProxyRequired -urlencoding utf-8 } # Use a Mozilla compatible useragent header to avoid problems with # some web sites. set http(-useragent) \ "Mozilla/5.0 ([string totitle $::tcl_platform(platform)]; U;\ $::tcl_platform(os) $::tcl_platform(osVersion))\ http/[package provide http] Tcl/[package provide Tcl]" } proc init {} { # Set up the map for quoting chars. RFC3986 Section 2.3 say percent # encode all except: "... percent-encoded octets in the ranges of ALPHA # (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E), # underscore (%5F), or tilde (%7E) should not be created by URI # producers ..." for {set i 0} {$i <= 256} {incr i} { set c [format %c $i] if {![string match {[-._~a-zA-Z0-9]} $c]} { set map($c) %[format %.2x $i] } } # These are handled specially set map(\n) %0d%0a variable formMap [array get map] # Create a map for HTTP/1.1 open sockets variable socketmap if {[info exists socketmap]} { # Close but don't remove open sockets on re-init foreach {url sock} [array get socketmap] { catch {close $sock} } } array set socketmap {} } init variable urlTypes if {![info exists urlTypes]} { set urlTypes(http) [list 80 ::socket] } variable encodings [string tolower [encoding names]] # This can be changed, but iso8859-1 is the RFC standard. variable defaultCharset if {![info exists defaultCharset]} { set defaultCharset "iso8859-1" } # Force RFC 3986 strictness in geturl url verification? variable strict if {![info exists strict]} { set strict 1 } # Let user control default keepalive for compatibility variable defaultKeepalive if {![info exists defaultKeepalive]} { set defaultKeepalive 0 } namespace export geturl config reset wait formatQuery register unregister # Useful, but not exported: data size status code } # http::Log -- # # Debugging output -- define this to observe HTTP/1.1 socket usage. # Should echo any args received. # # Arguments: # msg Message to output # proc http::Log {args} {} # http::register -- # # See documentation for details. # # Arguments: # proto URL protocol prefix, e.g. https # port Default port for protocol # command Command to use to create socket # Results: # list of port and command that was registered. proc http::register {proto port command} { variable urlTypes set urlTypes($proto) [list $port $command] } # http::unregister -- # # Unregisters URL protocol handler # # Arguments: # proto URL protocol prefix, e.g. https # Results: # list of port and command that was unregistered. proc http::unregister {proto} { variable urlTypes if {![info exists urlTypes($proto)]} { return -code error "unsupported url type \"$proto\"" } set old $urlTypes($proto) unset urlTypes($proto) return $old } # http::config -- # # See documentation for details. # # Arguments: # args Options parsed by the procedure. # Results: # TODO proc http::config {args} { variable http set options [lsort [array names http -*]] set usage [join $options ", "] if {[llength $args] == 0} { set result {} foreach name $options { lappend result $name $http($name) } return $result } set options [string map {- ""} $options] set pat ^-([join $options |])$ if {[llength $args] == 1} { set flag [lindex $args 0] if {[regexp -- $pat $flag]} { return $http($flag) } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } } } # http::Finish -- # # Clean up the socket and eval close time callbacks # # Arguments: # token Connection token. # errormsg (optional) If set, forces status to error. # skipCB (optional) If set, don't call the -command callback. This # is useful when geturl wants to throw an exception instead # of calling the callback. That way, the same error isn't # reported to two places. # # Side Effects: # Closes the socket proc http::Finish { token {errormsg ""} {skipCB 0}} { variable $token upvar 0 $token state global errorInfo errorCode if {$errormsg ne ""} { set state(error) [list $errormsg $errorInfo $errorCode] set state(status) "error" } if {($state(status) eq "timeout") || ($state(status) eq "error") || ([info exists state(connection)] && ($state(connection) eq "close")) } { CloseSocket $state(sock) $token } if {[info exists state(after)]} { after cancel $state(after) } if {[info exists state(-command)] && !$skipCB} { if {[catch {eval $state(-command) {$token}} err]} { if {$errormsg eq ""} { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } # Command callback may already have unset our state unset -nocomplain state(-command) } } # http::CloseSocket - # # Close a socket and remove it from the persistent sockets table. # If possible an http token is included here but when we are called # from a fileevent on remote closure we need to find the correct # entry - hence the second section. proc ::http::CloseSocket {s {token {}}} { variable socketmap catch {fileevent $s readable {}} set conn_id {} if {$token ne ""} { variable $token upvar 0 $token state if {[info exists state(socketinfo)]} { set conn_id $state(socketinfo) } } else { set map [array get socketmap] set ndx [lsearch -exact $map $s] if {$ndx >= 0} { incr ndx -1 set conn_id [lindex $map $ndx] } } if {$conn_id eq {} || ![info exists socketmap($conn_id)]} { Log "Closing socket $s (no connection info)" if {[catch {close $s} err]} { Log "Error: $err" } } else { if {[info exists socketmap($conn_id)]} { Log "Closing connection $conn_id (sock $socketmap($conn_id))" if {[catch {close $socketmap($conn_id)} err]} { Log "Error: $err" } unset socketmap($conn_id) } else { Log "Cannot close connection $conn_id - no socket in socket map" } } } # http::reset -- # # See documentation for details. # # Arguments: # token Connection token. # why Status info. # # Side Effects: # See Finish proc http::reset { token {why reset} } { variable $token upvar 0 $token state set state(status) $why catch {fileevent $state(sock) readable {}} catch {fileevent $state(sock) writable {}} Finish $token if {[info exists state(error)]} { set errorlist $state(error) unset state eval ::error $errorlist } } # http::geturl -- # # Establishes a connection to a remote url via http. # # Arguments: # url The http URL to goget. # args Option value pairs. Valid options include: # -blocksize, -validate, -headers, -timeout # Results: # Returns a token for this connection. This token is the name of an array # that the caller should unset to garbage collect the state. proc http::geturl { url args } { variable http variable urlTypes variable defaultCharset variable defaultKeepalive variable strict # Initialize the state variable, an array. We'll return the name of this # array as the token for the transaction. if {![info exists http(uid)]} { set http(uid) 0 } set token [namespace current]::[incr http(uid)] variable $token upvar 0 $token state reset $token # Process command options. array set state { -binary false -blocksize 8192 -queryblocksize 8192 -validate 0 -headers {} -timeout 0 -type application/x-www-form-urlencoded -queryprogress {} -protocol 1.1 binary 0 state header meta {} coding {} currentsize 0 totalsize 0 querylength 0 queryoffset 0 type text/html body {} status "" http "" connection close } set state(-keepalive) $defaultKeepalive set state(-strict) $strict # These flags have their types verified [Bug 811170] array set type { -binary boolean -blocksize integer -queryblocksize integer -strict boolean -timeout integer -validate boolean } set state(charset) $defaultCharset set options { -binary -blocksize -channel -command -handler -headers -keepalive -method -myaddr -progress -protocol -query -queryblocksize -querychannel -queryprogress -strict -timeout -type -validate } set usage [join [lsort $options] ", "] set options [string map {- ""} $options] set pat ^-([join $options |])$ foreach {flag value} $args { if {[regexp -- $pat $flag]} { # Validate numbers if {[info exists type($flag)] && ![string is $type($flag) -strict $value]} { unset $token return -code error "Bad value for $flag ($value), must be $type($flag)" } set state($flag) $value } else { unset $token return -code error "Unknown option $flag, can be: $usage" } } # Make sure -query and -querychannel aren't both specified set isQueryChannel [info exists state(-querychannel)] set isQuery [info exists state(-query)] if {$isQuery && $isQueryChannel} { unset $token return -code error "Can't combine -query and -querychannel options!" } # Validate URL, determine the server host and port, and check proxy case # Recognize user:pass@host URLs also, although we do not do anything with # that info yet. # URLs have basically four parts. # First, before the colon, is the protocol scheme (e.g. http) # Second, for HTTP-like protocols, is the authority # The authority is preceded by // and lasts up to (but not including) # the following / and it identifies up to four parts, of which only one, # the host, is required (if an authority is present at all). All other # parts of the authority (user name, password, port number) are optional. # Third is the resource name, which is split into two parts at a ? # The first part (from the single "/" up to "?") is the path, and the # second part (from that "?" up to "#") is the query. *HOWEVER*, we do # not need to separate them; we send the whole lot to the server. # Fourth is the fragment identifier, which is everything after the first # "#" in the URL. The fragment identifier MUST NOT be sent to the server # and indeed, we don't bother to validate it (it could be an error to # pass it in here, but it's cheap to strip). # # An example of a URL that has all the parts: # http://jschmoe:xyzzy@www.bogus.net:8000/foo/bar.tml?q=foo#changes # The "http" is the protocol, the user is "jschmoe", the password is # "xyzzy", the host is "www.bogus.net", the port is "8000", the path is # "/foo/bar.tml", the query is "q=foo", and the fragment is "changes". # # Note that the RE actually combines the user and password parts, as # recommended in RFC 3986. Indeed, that RFC states that putting passwords # in URLs is a Really Bad Idea, something with which I would agree utterly. # Also note that we do not currently support IPv6 addresses. # # From a validation perspective, we need to ensure that the parts of the # URL that are going to the server are correctly encoded. # This is only done if $state(-strict) is true (inherited from # $::http::strict). set URLmatcher {(?x) # this is _expanded_ syntax ^ (?: (\w+) : ) ? # (?: // (?: ( [^@/\#?]+ # ) @ )? ( [^/:\#?]+ ) # (?: : (\d+) )? # )? ( / [^\#?]* (?: \? [^\#?]* )?)? # (including query) (?: \# (.*) )? # $ } # Phase one: parse if {![regexp -- $URLmatcher $url -> proto user host port srvurl]} { unset $token return -code error "Unsupported URL: $url" } # Phase two: validate if {$host eq ""} { # Caller has to provide a host name; we do not have a "default host" # that would enable us to handle relative URLs. unset $token return -code error "Missing host part: $url" # Note that we don't check the hostname for validity here; if it's # invalid, we'll simply fail to resolve it later on. } if {$port ne "" && $port > 65535} { unset $token return -code error "Invalid port number: $port" } # The user identification and resource identification parts of the URL can # have encoded characters in them; take care! if {$user ne ""} { # Check for validity according to RFC 3986, Appendix A set validityRE {(?xi) ^ (?: [-\w.~!$&'()*+,;=:] | %[0-9a-f][0-9a-f] )+ $ } if {$state(-strict) && ![regexp -- $validityRE $user]} { unset $token # Provide a better error message in this error case if {[regexp {(?i)%(?![0-9a-f][0-9a-f]).?.?} $user bad]} { return -code error \ "Illegal encoding character usage \"$bad\" in URL user" } return -code error "Illegal characters in URL user" } } if {$srvurl ne ""} { # Check for validity according to RFC 3986, Appendix A set validityRE {(?xi) ^ # Path part (already must start with / character) (?: [-\w.~!$&'()*+,;=:@/] | %[0-9a-f][0-9a-f] )* # Query part (optional, permits ? characters) (?: \? (?: [-\w.~!$&'()*+,;=:@/?] | %[0-9a-f][0-9a-f] )* )? $ } if {$state(-strict) && ![regexp -- $validityRE $srvurl]} { unset $token # Provide a better error message in this error case if {[regexp {(?i)%(?![0-9a-f][0-9a-f])..} $srvurl bad]} { return -code error \ "Illegal encoding character usage \"$bad\" in URL path" } return -code error "Illegal characters in URL path" } } else { set srvurl / } if {$proto eq ""} { set proto http } if {![info exists urlTypes($proto)]} { unset $token return -code error "Unsupported URL type \"$proto\"" } set defport [lindex $urlTypes($proto) 0] set defcmd [lindex $urlTypes($proto) 1] if {$port eq ""} { set port $defport } if {![catch {$http(-proxyfilter) $host} proxy]} { set phost [lindex $proxy 0] set pport [lindex $proxy 1] } # OK, now reassemble into a full URL set url ${proto}:// if {$user ne ""} { append url $user append url @ } append url $host if {$port != $defport} { append url : $port } append url $srvurl # Don't append the fragment! set state(url) $url # If a timeout is specified we set up the after event and arrange for an # asynchronous socket connection. set sockopts [list] if {$state(-timeout) > 0} { set state(after) [after $state(-timeout) \ [list http::reset $token timeout]] lappend sockopts -async } # If we are using the proxy, we must pass in the full URL that includes # the server name. if {[info exists phost] && ($phost ne "")} { set srvurl $url set targetAddr [list $phost $pport] } else { set targetAddr [list $host $port] } # Proxy connections aren't shared among different hosts. set state(socketinfo) $host:$port # See if we are supposed to use a previously opened channel. if {$state(-keepalive)} { variable socketmap if {[info exists socketmap($state(socketinfo))]} { if {[catch {fconfigure $socketmap($state(socketinfo))}]} { Log "WARNING: socket for $state(socketinfo) was closed" unset socketmap($state(socketinfo)) } else { set sock $socketmap($state(socketinfo)) Log "reusing socket $sock for $state(socketinfo)" catch {fileevent $sock writable {}} catch {fileevent $sock readable {}} } } # don't automatically close this connection socket set state(connection) {} } if {![info exists sock]} { # Pass -myaddr directly to the socket command if {[info exists state(-myaddr)]} { lappend sockopts -myaddr $state(-myaddr) } if {[catch {eval $defcmd $sockopts $targetAddr} sock]} { # something went wrong while trying to establish the # connection. Clean up after events and such, but DON'T call the # command callback (if available) because we're going to throw an # exception from here instead. set state(sock) $sock Finish $token "" 1 cleanup $token return -code error $sock } } set state(sock) $sock Log "Using $sock for $state(socketinfo)" \ [expr {$state(-keepalive)?"keepalive":""}] if {$state(-keepalive)} { set socketmap($state(socketinfo)) $sock } # Wait for the connection to complete. if {$state(-timeout) > 0} { fileevent $sock writable [list http::Connect $token] http::wait $token if {![info exists state]} { # If we timed out then Finish has been called and the users # command callback may have cleaned up the token. If so # we end up here with nothing left to do. return $token } elseif {$state(status) eq "error"} { # Something went wrong while trying to establish the connection. # Clean up after events and such, but DON'T call the command # callback (if available) because we're going to throw an # exception from here instead. set err [lindex $state(error) 0] cleanup $token return -code error $err } elseif {$state(status) ne "connect"} { # Likely to be connection timeout return $token } set state(status) "" } # Send data in cr-lf format, but accept any line terminators fconfigure $sock -translation {auto crlf} -buffersize $state(-blocksize) # The following is disallowed in safe interpreters, but the socket is # already in non-blocking mode in that case. catch {fconfigure $sock -blocking off} set how GET if {$isQuery} { set state(querylength) [string length $state(-query)] if {$state(querylength) > 0} { set how POST set contDone 0 } else { # There's no query data. unset state(-query) set isQuery 0 } } elseif {$state(-validate)} { set how HEAD } elseif {$isQueryChannel} { set how POST # The query channel must be blocking for the async Write to # work properly. fconfigure $state(-querychannel) -blocking 1 -translation binary set contDone 0 } if {[info exists state(-method)] && $state(-method) ne ""} { set how $state(-method) } if {[catch { puts $sock "$how $srvurl HTTP/$state(-protocol)" puts $sock "Accept: $http(-accept)" array set hdrs $state(-headers) if {[info exists hdrs(Host)]} { # Allow Host spoofing [Bug 928154] puts $sock "Host: $hdrs(Host)" } elseif {$port == $defport} { # Don't add port in this case, to handle broken servers. # [Bug #504508] puts $sock "Host: $host" } else { puts $sock "Host: $host:$port" } unset hdrs puts $sock "User-Agent: $http(-useragent)" if {$state(-protocol) == 1.0 && $state(-keepalive)} { puts $sock "Connection: keep-alive" } if {$state(-protocol) > 1.0 && !$state(-keepalive)} { puts $sock "Connection: close" ;# RFC2616 sec 8.1.2.1 } if {[info exists phost] && ($phost ne "") && $state(-keepalive)} { puts $sock "Proxy-Connection: Keep-Alive" } set accept_encoding_seen 0 foreach {key value} $state(-headers) { if {[string equal -nocase $key "host"]} { continue } if {[string equal -nocase $key "accept-encoding"]} { set accept_encoding_seen 1 } set value [string map [list \n "" \r ""] $value] set key [string trim $key] if {[string equal -nocase $key "content-length"]} { set contDone 1 set state(querylength) $value } if {[string length $key]} { puts $sock "$key: $value" } } # Soft zlib dependency check - no package require if {!$accept_encoding_seen && [llength [package provide zlib]] && !([info exists state(-channel)] || [info exists state(-handler)]) } { puts $sock "Accept-Encoding: gzip, identity, *;q=0.1" } if {$isQueryChannel && $state(querylength) == 0} { # Try to determine size of data in channel. If we cannot seek, the # surrounding catch will trap us set start [tell $state(-querychannel)] seek $state(-querychannel) 0 end set state(querylength) \ [expr {[tell $state(-querychannel)] - $start}] seek $state(-querychannel) $start } # Flush the request header and set up the fileevent that will either # push the POST data or read the response. # # fileevent note: # # It is possible to have both the read and write fileevents active at # this point. The only scenario it seems to affect is a server that # closes the connection without reading the POST data. (e.g., early # versions TclHttpd in various error cases). Depending on the platform, # the client may or may not be able to get the response from the server # because of the error it will get trying to write the post data. # Having both fileevents active changes the timing and the behavior, # but no two platforms (among Solaris, Linux, and NT) behave the same, # and none behave all that well in any case. Servers should always read # their POST data if they expect the client to read their response. if {$isQuery || $isQueryChannel} { puts $sock "Content-Type: $state(-type)" if {!$contDone} { puts $sock "Content-Length: $state(querylength)" } puts $sock "" fconfigure $sock -translation {auto binary} fileevent $sock writable [list http::Write $token] } else { puts $sock "" flush $sock fileevent $sock readable [list http::Event $sock $token] } if {! [info exists state(-command)]} { # geturl does EVERYTHING asynchronously, so if the user calls it # synchronously, we just do a wait here. wait $token if {$state(status) eq "error"} { # Something went wrong, so throw the exception, and the # enclosing catch will do cleanup. return -code error [lindex $state(error) 0] } } } err]} { # The socket probably was never connected, or the connection dropped # later. # Clean up after events and such, but DON'T call the command callback # (if available) because we're going to throw an exception from here # instead. # if state(status) is error, it means someone's already called Finish # to do the above-described clean up. if {$state(status) ne "error"} { Finish $token $err 1 } cleanup $token return -code error $err } return $token } # Data access functions: # Data - the URL data # Status - the transaction status: ok, reset, eof, timeout # Code - the HTTP transaction code, e.g., 200 # Size - the size of the URL data proc http::data {token} { variable $token upvar 0 $token state return $state(body) } proc http::status {token} { if {![info exists $token]} { return "error" } variable $token upvar 0 $token state return $state(status) } proc http::code {token} { variable $token upvar 0 $token state return $state(http) } proc http::ncode {token} { variable $token upvar 0 $token state if {[regexp {[0-9]{3}} $state(http) numeric_code]} { return $numeric_code } else { return $state(http) } } proc http::size {token} { variable $token upvar 0 $token state return $state(currentsize) } proc http::meta {token} { variable $token upvar 0 $token state return $state(meta) } proc http::error {token} { variable $token upvar 0 $token state if {[info exists state(error)]} { return $state(error) } return "" } # http::cleanup # # Garbage collect the state associated with a transaction # # Arguments # token The token returned from http::geturl # # Side Effects # unsets the state array proc http::cleanup {token} { variable $token upvar 0 $token state if {[info exists state]} { unset state } } # http::Connect # # This callback is made when an asyncronous connection completes. # # Arguments # token The token returned from http::geturl # # Side Effects # Sets the status of the connection, which unblocks # the waiting geturl call proc http::Connect {token} { variable $token upvar 0 $token state global errorInfo errorCode if {[eof $state(sock)] || [string length [fconfigure $state(sock) -error]]} { Finish $token "connect failed [fconfigure $state(sock) -error]" 1 } else { set state(status) connect fileevent $state(sock) writable {} } return } # http::Write # # Write POST query data to the socket # # Arguments # token The token for the connection # # Side Effects # Write the socket and handle callbacks. proc http::Write {token} { variable $token upvar 0 $token state set sock $state(sock) # Output a block. Tcl will buffer this if the socket blocks set done 0 if {[catch { # Catch I/O errors on dead sockets if {[info exists state(-query)]} { # Chop up large query strings so queryprogress callback can give # smooth feedback. puts -nonewline $sock \ [string range $state(-query) $state(queryoffset) \ [expr {$state(queryoffset) + $state(-queryblocksize) - 1}]] incr state(queryoffset) $state(-queryblocksize) if {$state(queryoffset) >= $state(querylength)} { set state(queryoffset) $state(querylength) puts $sock "" set done 1 } } else { # Copy blocks from the query channel set outStr [read $state(-querychannel) $state(-queryblocksize)] puts -nonewline $sock $outStr incr state(queryoffset) [string length $outStr] if {[eof $state(-querychannel)]} { set done 1 } } } err]} { # Do not call Finish here, but instead let the read half of the socket # process whatever server reply there is to get. set state(posterror) $err set done 1 } if {$done} { catch {flush $sock} fileevent $sock writable {} fileevent $sock readable [list http::Event $sock $token] } # Callback to the client after we've completely handled everything. if {[string length $state(-queryprogress)]} { eval $state(-queryprogress) \ [list $token $state(querylength) $state(queryoffset)] } } # http::Event # # Handle input on the socket # # Arguments # sock The socket receiving input. # token The token returned from http::geturl # # Side Effects # Read the socket and handle callbacks. proc http::Event {sock token} { variable $token upvar 0 $token state if {![info exists state]} { Log "Event $sock with invalid token '$token' - remote close?" if {! [eof $sock]} { if {[string length [set d [read $sock]]] != 0} { Log "WARNING: additional data left on closed socket" } } CloseSocket $sock return } if {$state(state) eq "header"} { if {[catch {gets $sock line} n]} { return [Finish $token $n] } elseif {$n == 0} { # We have now read all headers # We ignore HTTP/1.1 100 Continue returns. RFC2616 sec 8.2.3 if {$state(http) == "" || [lindex $state(http) 1] == 100} { return } set state(state) body # If doing a HEAD, then we won't get any body if {$state(-validate)} { Eof $token return } # For non-chunked transfer we may have no body -- in this case we # may get no further file event if the connection doesn't close and # no more data is sent. We can tell and must finish up now - not # later. if {!(([info exists state(connection)] && ($state(connection) eq "close")) || [info exists state(transfer)]) && $state(totalsize) == 0 } then { Log "body size is 0 and no events likely - complete." Eof $token return } # We have to use binary translation to count bytes properly. fconfigure $sock -translation binary if {$state(-binary) || ![string match -nocase text* $state(type)]} { # Turn off conversions for non-text data set state(binary) 1 } if {$state(binary) || [string match *gzip* $state(coding)] || [string match *compress* $state(coding)]} { if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } } if {[info exists state(-channel)] && ![info exists state(-handler)]} { # Initiate a sequence of background fcopies fileevent $sock readable {} CopyStart $sock $token return } } elseif {$n > 0} { # Process header lines if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { switch -- [string tolower $key] { content-type { set state(type) [string trim [string tolower $value]] # grab the optional charset information regexp -nocase {charset\s*=\s*(\S+?);?} \ $state(type) -> state(charset) } content-length { set state(totalsize) [string trim $value] } content-encoding { set state(coding) [string trim $value] } transfer-encoding { set state(transfer) \ [string trim [string tolower $value]] } proxy-connection - connection { set state(connection) \ [string trim [string tolower $value]] } } lappend state(meta) $key [string trim $value] } elseif {[string match HTTP* $line]} { set state(http) $line } } } else { # Now reading body if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) [list $sock $token]] } elseif {[info exists state(transfer_final)]} { set line [getTextLine $sock] set n [string length $line] if {$n > 0} { Log "found $n bytes following final chunk" append state(transfer_final) $line } else { Log "final chunk part" Eof $token } } elseif {[info exists state(transfer)] && $state(transfer) eq "chunked"} { set size 0 set chunk [getTextLine $sock] set n [string length $chunk] if {[string trim $chunk] ne ""} { scan $chunk %x size if {$size != 0} { set bl [fconfigure $sock -blocking] fconfigure $sock -blocking 1 set chunk [read $sock $size] fconfigure $sock -blocking $bl set n [string length $chunk] if {$n >= 0} { append state(body) $chunk } if {$size != [string length $chunk]} { Log "WARNING: mis-sized chunk:\ was [string length $chunk], should be $size" } getTextLine $sock } else { set state(transfer_final) {} } } } else { #Log "read non-chunk $state(currentsize) of $state(totalsize)" set block [read $sock $state(-blocksize)] set n [string length $block] if {$n >= 0} { append state(body) $block } } if {[info exists state]} { if {$n >= 0} { incr state(currentsize) $n } # If Content-Length - check for end of data. if {($state(totalsize) > 0) && ($state(currentsize) >= $state(totalsize))} { Eof $token } } } err]} { return [Finish $token $err] } else { if {[info exists state(-progress)]} { eval $state(-progress) \ [list $token $state(totalsize) $state(currentsize)] } } } # catch as an Eof above may have closed the socket already if {![catch {eof $sock} eof] && $eof} { if {[info exists $token]} { set state(connection) close Eof $token } else { # open connection closed on a token that has been cleaned up. CloseSocket $sock } return } } # http::getTextLine -- # # Get one line with the stream in blocking crlf mode # # Arguments # sock The socket receiving input. # # Results: # The line of text, without trailing newline proc http::getTextLine {sock} { set tr [fconfigure $sock -translation] set bl [fconfigure $sock -blocking] fconfigure $sock -translation crlf -blocking 1 set r [gets $sock] fconfigure $sock -translation $tr -blocking $bl return $r } # http::CopyStart # # Error handling wrapper around fcopy # # Arguments # sock The socket to copy from # token The token returned from http::geturl # # Side Effects # This closes the connection upon error proc http::CopyStart {sock token} { variable $token upvar 0 $token state if {[catch { fcopy $sock $state(-channel) -size $state(-blocksize) -command \ [list http::CopyDone $token] } err]} { Finish $token $err } } # http::CopyDone # # fcopy completion callback # # Arguments # token The token returned from http::geturl # count The amount transfered # # Side Effects # Invokes callbacks proc http::CopyDone {token count {error {}}} { variable $token upvar 0 $token state set sock $state(sock) incr state(currentsize) $count if {[info exists state(-progress)]} { eval $state(-progress) \ [list $token $state(totalsize) $state(currentsize)] } # At this point the token may have been reset if {[string length $error]} { Finish $token $error } elseif {[catch {eof $sock} iseof] || $iseof} { Eof $token } else { CopyStart $sock $token } } # http::Eof # # Handle eof on the socket # # Arguments # token The token returned from http::geturl # # Side Effects # Clean up the socket proc http::Eof {token {force 0}} { variable $token upvar 0 $token state if {$state(state) eq "header"} { # Premature eof set state(status) eof } else { set state(status) ok } if {($state(coding) eq "gzip") && [string length $state(body)] > 0} { if {[catch { set state(body) [Gunzip $state(body)] } err]} { return [Finish $token $err] } } if {!$state(binary)} { # If we are getting text, set the incoming channel's # encoding correctly. iso8859-1 is the RFC default, but # this could be any IANA charset. However, we only know # how to convert what we have encodings for. set enc [CharsetToEncoding $state(charset)] if {$enc ne "binary"} { set state(body) [encoding convertfrom $enc $state(body)] } # Translate text line endings. set state(body) [string map {\r\n \n \r \n} $state(body)] } Finish $token } # http::wait -- # # See documentation for details. # # Arguments: # token Connection token. # # Results: # The status after the wait. proc http::wait {token} { variable $token upvar 0 $token state if {![info exists state(status)] || $state(status) eq ""} { # We must wait on the original variable name, not the upvar alias vwait ${token}(status) } return [status $token] } # http::formatQuery -- # # See documentation for details. Call http::formatQuery with an even # number of arguments, where the first is a name, the second is a value, # the third is another name, and so on. # # Arguments: # args A list of name-value pairs. # # Results: # TODO proc http::formatQuery {args} { set result "" set sep "" foreach i $args { append result $sep [mapReply $i] if {$sep eq "="} { set sep & } else { set sep = } } return $result } # http::mapReply -- # # Do x-www-urlencoded character mapping # # Arguments: # string The string the needs to be encoded # # Results: # The encoded string proc http::mapReply {string} { variable http variable formMap # The spec says: "non-alphanumeric characters are replaced by '%HH'". Use # a pre-computed map and [string map] to do the conversion (much faster # than [regsub]/[subst]). [Bug 1020491] if {$http(-urlencoding) ne ""} { set string [encoding convertto $http(-urlencoding) $string] return [string map $formMap $string] } set converted [string map $formMap $string] if {[string match "*\[\u0100-\uffff\]*" $converted]} { regexp {[\u0100-\uffff]} $converted badChar # Return this error message for maximum compatability... :^/ return -code error \ "can't read \"formMap($badChar)\": no such element in array" } return $converted } # http::ProxyRequired -- # Default proxy filter. # # Arguments: # host The destination host # # Results: # The current proxy settings proc http::ProxyRequired {host} { variable http if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} { if {![info exists http(-proxyport)] || \ ![string length $http(-proxyport)]} { set http(-proxyport) 8080 } return [list $http(-proxyhost) $http(-proxyport)] } } # http::CharsetToEncoding -- # # Tries to map a given IANA charset to a tcl encoding. # If no encoding can be found, returns binary. # proc http::CharsetToEncoding {charset} { variable encodings set charset [string tolower $charset] if {[regexp {iso-?8859-([0-9]+)} $charset - num]} { set encoding "iso8859-$num" } elseif {[regexp {iso-?2022-(jp|kr)} $charset - ext]} { set encoding "iso2022-$ext" } elseif {[regexp {shift[-_]?js} $charset -]} { set encoding "shiftjis" } elseif {[regexp {(windows|cp)-?([0-9]+)} $charset - - num]} { set encoding "cp$num" } elseif {$charset eq "us-ascii"} { set encoding "ascii" } elseif {[regexp {(iso-?)?lat(in)?-?([0-9]+)} $charset - - - num]} { switch -- $num { 5 {set encoding "iso8859-9"} 1 - 2 - 3 {set encoding "iso8859-$num"} } } else { # other charset, like euc-xx, utf-8,... may directly maps to encoding set encoding $charset } set idx [lsearch -exact $encodings $encoding] if {$idx >= 0} { return $encoding } else { return "binary" } } # http::Gunzip -- # # Decompress data transmitted using the gzip transfer coding. # # FIX ME: redo using zlib sinflate proc http::Gunzip {data} { binary scan $data Scb5icc magic method flags time xfl os set pos 10 if {$magic != 0x1f8b} { return -code error "invalid data: supplied data is not in gzip format" } if {$method != 8} { return -code error "invalid compression method" } foreach {f_text f_crc f_extra f_name f_comment} [split $flags ""] break set extra "" if { $f_extra } { binary scan $data @${pos}S xlen incr pos 2 set extra [string range $data $pos $xlen] set pos [incr xlen] } set name "" if { $f_name } { set ndx [string first \0 $data $pos] set name [string range $data $pos $ndx] set pos [incr ndx] } set comment "" if { $f_comment } { set ndx [string first \0 $data $pos] set comment [string range $data $pos $ndx] set pos [incr ndx] } set fcrc "" if { $f_crc } { set fcrc [string range $data $pos [incr pos]] incr pos } binary scan [string range $data end-7 end] ii crc size set inflated [zlib inflate [string range $data $pos end-8]] set chk [zlib crc32 $inflated] if { ($crc & 0xffffffff) != ($chk & 0xffffffff)} { return -code error "invalid data: checksum mismatch $crc != $chk" } return $inflated } # Local variables: # indent-tabs-mode: t # End: tclvfs/http2.6/pkgIndex.tcl000064400000000000000000000006561447560765400154460ustar00nobodynobody# pkgIndex.tcl - index for http package # # Use to use lazy loading by defining the load command as: # package ifneeded http 2.6 [list tclPkgSetup $dir http 2.6 {{http.tcl source {::http::config ::http::formatQuery ::http::geturl ::http::reset ::http::wait ::http::register ::http::unregister}}}] # if {![package vsatisfies [package provide Tcl] 8.4]} {return} package ifneeded http 2.6.9 [list source [file join $dir http.tcl]] tclvfs/library000075500000000000000000000000001447560765400133425ustar00nobodynobodytclvfs/library/ftpvfs.tcl000064400000000000000000000215601447560765400154410ustar00nobodynobody package provide vfs::ftp 1.0 package require vfs 1.0 package require ftp namespace eval vfs::ftp { # Number of milliseconds for which to cache listings variable cacheListingsFor 1000 } proc vfs::ftp::Mount {dirurl local} { set dirurl [string trim $dirurl] ::vfs::log "ftp-vfs: attempt to mount $dirurl at $local" if {[string index $dirurl end] != "/"} { ::vfs::log "ftp-vfs: adding missing directory delimiter to mount point" append dirurl "/" } set urlRE {(?:ftp://)?(?:([^@:]*)(?::([^@]*))?@)?([^/:]+)(?::([0-9]*))?/(.*/)?$} if {![regexp $urlRE $dirurl - user pass host port path]} { return -code error "Sorry I didn't understand\ the url address \"$dirurl\"" } if {![string length $user]} { set user anonymous } if {![string length $port]} { set port 21 } set fd [::ftp::Open $host $user $pass -port $port -output ::vfs::ftp::log] if {$fd < 0} { error "Mount failed" } if {$path != ""} { if {[catch { ::ftp::Cd $fd $path } err]} { ftp::Close $fd error "Opened ftp connection, but then received error: $err" } } if {![catch {vfs::filesystem info $dirurl}]} { # unmount old mount ::vfs::log "ftp-vfs: unmounted old mount point at $dirurl" vfs::unmount $dirurl } ::vfs::log "ftp $host, $path mounted at $fd" vfs::filesystem mount $local [list vfs::ftp::handler $fd $path] # Register command to unmount vfs::RegisterMount $local [list ::vfs::ftp::Unmount $fd] return $fd } # Need this because vfs::log takes just one argument proc vfs::ftp::log {args} { ::vfs::log $args } proc vfs::ftp::Unmount {fd local} { vfs::filesystem unmount $local ::ftp::Close $fd } proc vfs::ftp::handler {fd path cmd root relative actualpath args} { if {$cmd == "matchindirectory"} { eval [list $cmd $fd $relative $actualpath] $args } else { eval [list $cmd $fd $relative] $args } } proc vfs::ftp::attributes {fd} { return [list "state"] } proc vfs::ftp::state {fd args} { vfs::attributeCantConfigure "state" "readwrite" $args } # If we implement the commands below, we will have a perfect # virtual file system for remote ftp sites. proc vfs::ftp::stat {fd name} { ::vfs::log "stat $name" if {$name == ""} { return [list type directory mtime 0 size 0 mode 0777 ino -1 \ depth 0 name "" dev -1 uid -1 gid -1 nlink 1] } # get information on the type of this file set ftpInfo [_findFtpInfo $fd $name] if {$ftpInfo == ""} { vfs::filesystem posixerror $::vfs::posix(ENOENT) } ::vfs::log $ftpInfo set perms [lindex $ftpInfo 0] if {[string index $perms 0] == "d"} { lappend res type directory size 0 set mtime 0 } else { lappend res type file size [ftp::FileSize $fd $name] set mtime [ftp::ModTime $fd $name] } lappend res dev -1 uid -1 gid -1 nlink 1 depth 0 \ atime $mtime ctime $mtime mtime $mtime mode 0777 return $res } proc vfs::ftp::access {fd name mode} { ::vfs::log "ftp-access $name $mode" if {$name == ""} { return 1 } set info [_findFtpInfo $fd $name] if {[string length $info]} { return 1 } else { vfs::filesystem posixerror $::vfs::posix(ENOENT) } } # We've chosen to implement these channels by using a memchan. # The alternative would be to use temporary files. proc vfs::ftp::open {fd name mode permissions} { ::vfs::log "open $name $mode $permissions" # return a list of two elements: # 1. first element is the Tcl channel name which has been opened # 2. second element (optional) is a command to evaluate when # the channel is closed. switch -glob -- $mode { "" - "r" { ftp::Get $fd $name -variable tmp set filed [vfs::memchan] fconfigure $filed -translation binary puts -nonewline $filed $tmp fconfigure $filed -translation auto seek $filed 0 return [list $filed] } "a" { # Try to append nothing to the file if {[catch [list ::ftp::Append $fd -data "" $name] err] || !$err} { error "Can't open $name for appending" } set filed [vfs::memchan] return [list $filed [list ::vfs::ftp::_closing $fd $name $filed Append]] } "w*" { # Try to write an empty file if {[catch [list ::ftp::Put $fd -data "" $name] err] || !$err} { error "Can't open $name for writing" } set filed [vfs::memchan] return [list $filed [list ::vfs::ftp::_closing $fd $name $filed Put]] } default { return -code error "illegal access mode \"$mode\"" } } } proc vfs::ftp::_closing {fd name filed action} { seek $filed 0 set contents [read $filed] set trans [fconfigure $filed -translation] if {$trans == "binary"} { set oldType [::ftp::Type $fd] ::ftp::Type $fd binary } if {![::ftp::$action $fd -data $contents $name]} { # Would be better if we could be more specific here, with # one of ENETRESET ENETDOWN ENETUNREACH or whatever. vfs::filesystem posixerror $::vfs::posix(EIO) #error "Failed to write to $name" } if {[info exists oldType]} { ::ftp::Type $fd $oldType } } proc vfs::ftp::_findFtpInfo {fd name} { ::vfs::log "findFtpInfo $fd $name" set ftpList [cachedList $fd [file dirname $name]] foreach p $ftpList { foreach {pname other} [_parseListLine $p] {} if {$pname == [file tail $name]} { return $other } } return "" } proc vfs::ftp::cachedList {fd dir} { variable cacheList variable cacheListingsFor # Caches response to prevent going back to the ftp server # for common use cases: foreach {f} [glob *] { file stat $f s } if {[info exists cacheList($dir)]} { return $cacheList($dir) } set listing [ftp::List $fd $dir] set cacheList($dir) $listing after $cacheListingsFor [list unset -nocomplain ::vfs::ftp::cacheList($dir)] return $listing } # Currently returns a list of name and a list of other # information. The other information is currently a # list of: # () permissions # () size proc vfs::ftp::_parseListLine {line} { # Check for filenames with spaces if {[regexp {([^ ]|[^0-9] )+$} $line name]} { # Check for links if {[set idx [string first " -> " $name]] >= 0} { incr idx -1 set name [string range $name 0 $idx] } } regsub -all "\[ \t\]+" $line " " line set items [split $line " "] if {![info exists name]} {set name [lindex $items end]} lappend other [lindex $items 0] if {[string is integer [lindex $items 4]]} { lappend other [lindex $items 4] } return [list $name $other] } proc vfs::ftp::matchindirectory {fd path actualpath pattern type} { ::vfs::log "matchindirectory $fd $path $actualpath $pattern $type" set res [list] if {![string length $pattern]} { # matching a single file set ftpInfo [_findFtpInfo $fd $path] if {$ftpInfo != ""} { # Now check if types match set perms [lindex $ftpInfo 0] if {[string index $perms 0] == "d"} { if {[::vfs::matchDirectories $type]} { lappend res $actualpath } } else { if {[::vfs::matchFiles $type]} { lappend res $actualpath } } } } else { # matching all files in the given directory set ftpList [cachedList $fd $path] ::vfs::log "ftpList: $ftpList" foreach p $ftpList { foreach {name perms} [_parseListLine $p] {} if {![string match $pattern $name]} { continue } if {[::vfs::matchDirectories $type]} { if {[string index $perms 0] == "d"} { lappend res [file join $actualpath $name] } } if {[::vfs::matchFiles $type]} { if {[string index $perms 0] != "d"} { lappend res [file join $actualpath $name] } } } } return $res } proc vfs::ftp::createdirectory {fd name} { ::vfs::log "createdirectory $name" if {![ftp::MkDir $fd $name]} { # Can we be more specific here? vfs::filesystem posixerror $::vfs::posix(EACCES) } } proc vfs::ftp::removedirectory {fd name recursive} { ::vfs::log "removedirectory $name $recursive" if {![ftp::RmDir $fd $name]} { # Can we be more specific here? if {$recursive} { vfs::filesystem posixerror $::vfs::posix(EACCES) } else { vfs::filesystem posixerror $::vfs::posix(EACCES) } } } proc vfs::ftp::deletefile {fd name} { ::vfs::log "deletefile $name" if {![ftp::Delete $fd $name]} { # Can we be more specific here? vfs::filesystem posixerror $::vfs::posix(EACCES) } } proc vfs::ftp::fileattributes {fd path args} { ::vfs::log "fileattributes $args" switch -- [llength $args] { 0 { # list strings return [list] } 1 { # get value set index [lindex $args 0] vfs::filesystem posixerror $::vfs::posix(ENODEV) } 2 { # set value set index [lindex $args 0] set val [lindex $args 1] vfs::filesystem posixerror $::vfs::posix(ENODEV) } } } proc vfs::ftp::utime {fd path actime mtime} { # Will throw an error if ftp package is old and only # handles 2 arguments. But that is ok -- Tcl will give the # user an appropriate error message. ftp::ModTime $fd $path $mtime } tclvfs/library/httpvfs.tcl000064400000000000000000000332271447560765400156320ustar00nobodynobody package provide vfs::http 0.6 package require vfs 1.0 package require http # This works for basic operations, using http GET and HEAD requests # to serve http data in a read-only file system. namespace eval vfs::http { # Allow for options when mounting an http URL variable options # -urlencode means automatically parse "foo/my file (2).txt" as # "foo/my%20file%20%282%29.txt", per RFC 3986, for the user. set options(-urlencode) 1 # -urlparse would further parse URLs for ? (query string) and # (anchor) # components, leaving those unencoded. Only works when -urlencode is true. set options(-urlparse) 0 } proc vfs::http::Mount {dirurl local args} { ::vfs::log "http-vfs: attempt to mount $dirurl at $local (args: $args)" variable options foreach {key val} $args { # only do exact option name matching for now # We could consider allowing general http options here, # but those would be per-mount if {[info exists options($key)]} { # currently only boolean values if {![string is boolean -strict $val]} { return -code error "invalid boolean value \"$val\" for $key" } set options($key) $val } } # Break the url into parts, verifying url array set parts [urlparse $dirurl] if {[info exists parts(query)] || [info exists parts(anchor)]} { return -code error "invalid url \"$dirurl\":\ no query string or anchor fragments allowed" } if {[info exists parts(user)]} { # At this point we need base64 for HTTP Basic AUTH package require base64 foreach {user passwd} [split $parts(user) :] { break } set auth "Basic [base64::encode $user:$passwd]" set headers [list Authorization $auth] } else { set headers "" } set token [::http::geturl $parts(url) -validate 1 -headers $headers] http::wait $token set status [http::status $token] http::cleanup $token if {$status ne "ok"} { # we'll take whatever http agrees is "ok" return -code error "received status \"$status\" for \"$parts(url)\"" } # Add a / to make sure the url and names are clearly separated later if {[string index $parts(url) end] ne "/"} { append parts(url) "/" } if {![catch {vfs::filesystem info $parts(url)}]} { # unmount old mount ::vfs::log "ftp-vfs: unmounted old mount point at $parts(url)" vfs::unmount $parts(url) } ::vfs::log "http $dirurl ($parts(url)) mounted at $local" # Pass headers along as they may include authentication vfs::filesystem mount $local \ [list vfs::http::handler $parts(url) $headers $parts(file)] # Register command to unmount - headers not needed vfs::RegisterMount $local [list ::vfs::http::Unmount $parts(url)] return $parts(url) } proc vfs::http::Unmount {url local} { vfs::filesystem unmount $local } proc vfs::http::handler {url headers path cmd root relative actualpath args} { if {$cmd eq "matchindirectory"} { eval [linsert $args 0 $cmd $url $headers $relative $actualpath] } else { eval [linsert $args 0 $cmd $url $headers $relative] } } proc vfs::http::urlparse {url} { # Taken from http 2.5.3 # Validate URL by parts. We suck out user:pass if it exists as the # core http package does not automate HTTP Basic Auth yet. # Returns data in [array get] format. The url, host and file keys are # guaranteed to exist. proto, port, query, anchor, and user should be # checked with [info exists]. (user may contain password) # URLs have basically four parts. # First, before the colon, is the protocol scheme (e.g. http) # Second, for HTTP-like protocols, is the authority # The authority is preceded by // and lasts up to (but not including) # the following / and it identifies up to four parts, of which only one, # the host, is required (if an authority is present at all). All other # parts of the authority (user name, password, port number) are optional. # Third is the resource name, which is split into two parts at a ? # The first part (from the single "/" up to "?") is the path, and the # second part (from that "?" up to "#") is the query. *HOWEVER*, we do # not need to separate them; we send the whole lot to the server. # Fourth is the fragment identifier, which is everything after the first # "#" in the URL. The fragment identifier MUST NOT be sent to the server # and indeed, we don't bother to validate it (it could be an error to # pass it in here, but it's cheap to strip). # # An example of a URL that has all the parts: # http://jschmoe:xyzzy@www.bogus.net:8000/foo/bar.tml?q=foo#changes # The "http" is the protocol, the user is "jschmoe", the password is # "xyzzy", the host is "www.bogus.net", the port is "8000", the path is # "/foo/bar.tml", the query is "q=foo", and the fragment is "changes". # # Note that the RE actually combines the user and password parts, as # recommended in RFC 3986. Indeed, that RFC states that putting passwords # in URLs is a Really Bad Idea, something with which I would agree utterly. # Also note that we do not currently support IPv6 addresses. # # From a validation perspective, we need to ensure that the parts of the # URL that are going to the server are correctly encoded. set URLmatcher {(?x) # this is _expanded_ syntax ^ (?: (\w+) : ) ? # (?: // (?: ( [^@/\#?]+ # ) @ )? ( [^/:\#?]+ ) # (?: : (\d+) )? # )? ( / [^\#?]* (?: \? [^\#?]* )?)? # (including query) (?: \# (.*) )? # (aka anchor) $ } # Phase one: parse if {![regexp -- $URLmatcher $url -> proto user host port srvurl anchor]} { unset $token return -code error "Unsupported URL: $url" } # Phase two: validate if {$host eq ""} { # Caller has to provide a host name; we do not have a "default host" # that would enable us to handle relative URLs. unset $token return -code error "Missing host part: $url" # Note that we don't check the hostname for validity here; if it's # invalid, we'll simply fail to resolve it later on. } if {$port ne "" && $port>65535} { unset $token return -code error "Invalid port number: $port" } # The user identification and resource identification parts of the URL can # have encoded characters in them; take care! if {$user ne ""} { # Check for validity according to RFC 3986, Appendix A set validityRE {(?xi) ^ (?: [-\w.~!$&'()*+,;=:] | %[0-9a-f][0-9a-f] )+ $ } if {![regexp -- $validityRE $user]} { unset $token # Provide a better error message in this error case if {[regexp {(?i)%(?![0-9a-f][0-9a-f]).?.?} $user bad]} { return -code error \ "Illegal encoding character usage \"$bad\" in URL user" } return -code error "Illegal characters in URL user" } } if {$srvurl ne ""} { # Check for validity according to RFC 3986, Appendix A set validityRE {(?xi) ^ # Path part (already must start with / character) (?: [-\w.~!$&'()*+,;=:@/] | %[0-9a-f][0-9a-f] )* # Query part (optional, permits ? characters) (?: \? (?: [-\w.~!$&'()*+,;=:@/?] | %[0-9a-f][0-9a-f] )* )? $ } if {![regexp -- $validityRE $srvurl]} { unset $token # Provide a better error message in this error case if {[regexp {(?i)%(?![0-9a-f][0-9a-f])..} $srvurl bad]} { return -code error \ "Illegal encoding character usage \"$bad\" in URL path" } return -code error "Illegal characters in URL path" } } else { set srvurl / } if {$proto eq ""} { set proto http } else { set result(proto) $proto } # Here we vary from core http # vfs::http - we only support http at this time. Perhaps https later? if {$proto ne "http"} { return -code error "Unsupported URL type \"$proto\"" } # OK, now reassemble into a full URL, with result containing the # parts that exist and will be returned to the user array set result {} set url ${proto}:// if {$user ne ""} { set result(user) $user # vfs::http will do HTTP basic auth on their existence, # but we pass these through as they are innocuous append url $user append url @ } append url $host set result(host) $host if {$port ne ""} { # don't bother with adding default port append url : $port set result(port) $port } append url $srvurl if {$anchor ne ""} { # XXX: Don't append see the anchor, as it is generally a client-side # XXX: item. The user can add it back if they want. #append url \# $anchor set result(anchor) $anchor } set idx [string first ? $srvurl] if {$idx >= 0} { set query [string range [expr {$idx+1}] end] set file [string range 0 [expr {$idx-1}]] set result(file) $file set result(query) $query } else { set result(file) $srvurl } set result(url) $url # return array format list of items return [array get result] } proc vfs::http::urlname {name} { # Parse the passed in name into a suitable URL name based on mount opts variable options if {$options(-urlencode)} { set querystr "" if {$options(-urlparse)} { # check for ? and split if necessary so that the query_string # part doesn't get encoded. Anchors come after this as well. set idx [string first ? $name] if {$idx >= 0} { set querystr [string range $name $idx end] ; # includes ? set name [string range $name 0 [expr {$idx-1}]] } } set urlparts [list] foreach part [file split $name] { lappend urlparts [http::mapReply $part] } set urlname "[join $urlparts /]$querystr" } else { set urlname $name } return $urlname } proc vfs::http::geturl {url args} { # a wrapper around http::geturl that handles 404 or !ok status check # returns error on no success, or a fully ready http token otherwise set token [eval [linsert $args 0 ::http::geturl $url]] http::wait $token if {[http::ncode $token] == 404 || [http::status $token] ne "ok"} { # 404 Not Found set code [http::code $token] http::cleanup $token vfs::filesystem posixerror $::vfs::posix(ENOENT) return -code error \ "could not read \"$url\": no such file or directory ($code)" } # treat returned token like a regular http token # call http::cleanup on it when done return $token } # If we implement the commands below, we will have a perfect # virtual file system for remote http sites. proc vfs::http::stat {dirurl headers name} { set urlname [urlname $name] ::vfs::log "stat $name ($urlname)" # get information on the type of this file. We describe everything # as a file (not a directory) since with http, even directories # really behave as the index.html they contain. # this will through an error if the file doesn't exist set token [geturl "$dirurl$urlname" -validate 1 -headers $headers] http::cleanup $token set mtime 0 lappend res type file lappend res dev -1 uid -1 gid -1 nlink 1 depth 0 \ atime $mtime ctime $mtime mtime $mtime mode 0777 return $res } proc vfs::http::access {dirurl headers name mode} { set urlname [urlname $name] ::vfs::log "access $name $mode ($urlname)" if {$mode & 2} { vfs::filesystem posixerror $::vfs::posix(EROFS) return -code error "read-only" } if {$name == ""} { return 1 } # this will through an error if the file doesn't exist set token [geturl "$dirurl$urlname" -validate 1 -headers $headers] http::cleanup $token return 1 } # We've chosen to implement these channels by using a memchan. # The alternative would be to use temporary files. proc vfs::http::open {dirurl headers name mode permissions} { set urlname [urlname $name] ::vfs::log "open $name $mode $permissions ($urlname)" # return a list of two elements: # 1. first element is the Tcl channel name which has been opened # 2. second element (optional) is a command to evaluate when # the channel is closed. switch -glob -- $mode { "" - "r" { set token [geturl "$dirurl$urlname" -headers $headers] set filed [vfs::memchan] fconfigure $filed -translation binary puts -nonewline $filed [::http::data $token] http::cleanup $token fconfigure $filed -translation auto seek $filed 0 # XXX: the close command should free vfs::memchan somehow?? return [list $filed] } "a" - "w*" { vfs::filesystem posixerror $::vfs::posix(EROFS) } default { return -code error "illegal access mode \"$mode\"" } } } proc vfs::http::matchindirectory {dirurl headers path actualpath pattern type} { ::vfs::log "matchindirectory $path $pattern $type" set res [list] if {[string length $pattern]} { # need to match all files in a given remote http site. } else { # single file if {![catch {access $dirurl $path 0}]} { lappend res $path } } return $res } proc vfs::http::createdirectory {dirurl headers name} { ::vfs::log "createdirectory $name" vfs::filesystem posixerror $::vfs::posix(EROFS) } proc vfs::http::removedirectory {dirurl headers name recursive} { ::vfs::log "removedirectory $name" vfs::filesystem posixerror $::vfs::posix(EROFS) } proc vfs::http::deletefile {dirurl headers name} { ::vfs::log "deletefile $name" vfs::filesystem posixerror $::vfs::posix(EROFS) } proc vfs::http::fileattributes {dirurl headers path args} { ::vfs::log "fileattributes $args" switch -- [llength $args] { 0 { # list strings return [list] } 1 { # get value set index [lindex $args 0] } 2 { # set value set index [lindex $args 0] set val [lindex $args 1] vfs::filesystem posixerror $::vfs::posix(EROFS) } } } proc vfs::http::utime {dirurl headers path actime mtime} { vfs::filesystem posixerror $::vfs::posix(EROFS) } tclvfs/library/mk4vfs.tcl000064400000000000000000000402351447560765400153430ustar00nobodynobody# mk4vfs.tcl -- Mk4tcl Virtual File System driver # Copyright (C) 1997-2003 Sensus Consulting Ltd. All Rights Reserved. # Matt Newman and Jean-Claude Wippler # # $Id: mk4vfs.tcl,v 1.43 2008/12/22 01:19:34 patthoyts Exp $ # # 05apr02 jcw 1.3 fixed append mode & close, # privatized memchan_handler # added zip, crc back in # 28apr02 jcw 1.4 reorged memchan and pkg dependencies # 22jun02 jcw 1.5 fixed recursive dir deletion # 16oct02 jcw 1.6 fixed periodic commit once a change is made # 20jan03 jcw 1.7 streamed zlib decompress mode, reduces memory usage # 01feb03 jcw 1.8 fix mounting a symlink, cleanup mount/unmount procs # 04feb03 jcw 1.8 whoops, restored vfs::mk4::Unmount logic # 17mar03 jcw 1.9 start with mode translucent or readwrite # 18oct05 jcw 1.10 add fallback to MK Compatible Lite driver (vfs::mkcl) # Removed provision of the backward compatible name. Moved to separate # file/package. package provide vfs::mk4 1.10.1 package require vfs # need this so init failure in interactive mode does not mess up errorInfo if {[info exists env(VFS_DEBUG)] && [info commands history] == ""} { proc history {args} {} } namespace eval vfs::mk4 { proc Mount {mkfile local args} { # 2005-10-19 switch to MK Compatible Lite driver if there is no Mk4tcl if {[catch { package require Mk4tcl }]} { package require vfs::mkcl return [eval [linsert $args 0 vfs::mkcl::Mount $mkfile $local]] } if {$mkfile != ""} { # dereference a symlink, otherwise mounting on it fails (why?) catch { set mkfile [file join [file dirname $mkfile] \ [file readlink $mkfile]] } set mkfile [file normalize $mkfile] } set db [eval [list ::mk4vfs::_mount $mkfile] $args] ::vfs::filesystem mount $local [list ::vfs::mk4::handler $db] ::vfs::RegisterMount $local [list ::vfs::mk4::Unmount $db] return $db } proc Unmount {db local} { vfs::filesystem unmount $local ::mk4vfs::_umount $db } proc attributes {db} { return [list "state" "commit"] } # Can use this to control commit/nocommit or whatever. # I'm not sure yet of what functionality jcw needs. proc commit {db args} { switch -- [llength $args] { 0 { if {$::mk4vfs::v::mode($db) == "readonly"} { return 0 } else { # To Do: read the commit state return 1 } } 1 { set val [lindex $args 0] if {$val != 0 && $val != 1} { return -code error \ "invalid commit value $val, must be 0,1" } # To Do: set the commit state. } default { return -code error "Wrong num args" } } } proc state {db args} { switch -- [llength $args] { 0 { return $::mk4vfs::v::mode($db) } 1 { set val [lindex $args 0] if {[lsearch -exact [::vfs::states] $val] < 0} { return -code error \ "invalid state $val, must be one of: [vfs::states]" } set ::mk4vfs::v::mode($db) $val ::mk4vfs::setupCommits $db } default { return -code error "Wrong num args" } } } proc handler {db cmd root relative actualpath args} { #puts stderr "handler: $db - $cmd - $root - $relative - $actualpath - $args" if {$cmd == "matchindirectory"} { eval [list $cmd $db $relative $actualpath] $args } elseif {$cmd == "fileattributes"} { eval [list $cmd $db $root $relative] $args } else { eval [list $cmd $db $relative] $args } } proc utime {db path actime modtime} { ::mk4vfs::stat $db $path sb if { $sb(type) == "file" } { mk::set $sb(ino) date $modtime } } proc matchindirectory {db path actualpath pattern type} { set newres [list] if {![string length $pattern]} { # check single file if {[catch {access $db $path 0}]} { return {} } set res [list $actualpath] set actualpath "" } else { set res [::mk4vfs::getdir $db $path $pattern] } foreach p [::vfs::matchCorrectTypes $type $res $actualpath] { lappend newres [file join $actualpath $p] } return $newres } proc stat {db name} { ::mk4vfs::stat $db $name sb set sb(ino) 0 array get sb } proc access {db name mode} { if {$mode & 2} { if {$::mk4vfs::v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } } # We can probably do this more efficiently, can't we? ::mk4vfs::stat $db $name sb } proc open {db file mode permissions} { # return a list of two elements: # 1. first element is the Tcl channel name which has been opened # 2. second element (optional) is a command to evaluate when # the channel is closed. switch -glob -- $mode { {} - r { ::mk4vfs::stat $db $file sb if { $sb(csize) != $sb(size) } { if {$::mk4vfs::zstreamed} { set fd [mk::channel $sb(ino) contents r] set fd [vfs::zstream decompress $fd $sb(csize) $sb(size)] } else { set fd [vfs::memchan] fconfigure $fd -translation binary set s [mk::get $sb(ino) contents] puts -nonewline $fd [vfs::zip -mode decompress $s] fconfigure $fd -translation auto seek $fd 0 } } elseif { $::mk4vfs::direct } { set fd [vfs::memchan] fconfigure $fd -translation binary puts -nonewline $fd [mk::get $sb(ino) contents] fconfigure $fd -translation auto seek $fd 0 } else { set fd [mk::channel $sb(ino) contents r] } return [list $fd] } a { if {$::mk4vfs::v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } if { [catch {::mk4vfs::stat $db $file sb }] } { # Create file ::mk4vfs::stat $db [file dirname $file] sb set tail [file tail $file] set fview $sb(ino).files if {[info exists mk4vfs::v::fcache($fview)]} { lappend mk4vfs::v::fcache($fview) $tail } set now [clock seconds] set sb(ino) [mk::row append $fview \ name $tail size 0 date $now ] if { [string match *z* $mode] || $mk4vfs::compress } { set sb(csize) -1 ;# HACK - force compression } else { set sb(csize) 0 } } set fd [vfs::memchan] fconfigure $fd -translation binary set s [mk::get $sb(ino) contents] if { $sb(csize) != $sb(size) && $sb(csize) > 0 } { append mode z puts -nonewline $fd [vfs::zip -mode decompress $s] } else { if { $mk4vfs::compress } { append mode z } puts -nonewline $fd $s #set fd [mk::channel $sb(ino) contents a] } fconfigure $fd -translation auto seek $fd 0 end return [list $fd [list mk4vfs::do_close $db $fd $mode $sb(ino)]] } w* { if {$::mk4vfs::v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } if { [catch {::mk4vfs::stat $db $file sb }] } { # Create file ::mk4vfs::stat $db [file dirname $file] sb set tail [file tail $file] set fview $sb(ino).files if {[info exists mk4vfs::v::fcache($fview)]} { lappend mk4vfs::v::fcache($fview) $tail } set now [clock seconds] set sb(ino) [mk::row append $fview \ name $tail size 0 date $now ] } if { [string match *z* $mode] || $mk4vfs::compress } { append mode z set fd [vfs::memchan] } else { set fd [mk::channel $sb(ino) contents w] } return [list $fd [list mk4vfs::do_close $db $fd $mode $sb(ino)]] } default { error "illegal access mode \"$mode\"" } } } proc createdirectory {db name} { mk4vfs::mkdir $db $name } proc removedirectory {db name recursive} { mk4vfs::delete $db $name $recursive } proc deletefile {db name} { mk4vfs::delete $db $name } proc fileattributes {db root relative args} { switch -- [llength $args] { 0 { # list strings return [::vfs::listAttributes] } 1 { # get value set index [lindex $args 0] return [::vfs::attributesGet $root $relative $index] } 2 { # set value if {$::mk4vfs::v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } set index [lindex $args 0] set val [lindex $args 1] return [::vfs::attributesSet $root $relative $index $val] } } } } namespace eval mk4vfs { variable compress 1 ;# HACK - needs to be part of "Super-Block" variable flush 5000 ;# Auto-Commit frequency variable direct 0 ;# read through a memchan, or from Mk4tcl if zero variable zstreamed 0 ;# decompress on the fly (needs zlib 1.1) namespace eval v { variable seq 0 variable mode ;# array key is db, value is mode # (readwrite/translucent/readonly) variable timer ;# array key is db, set to afterid, periodicCommit array set cache {} array set fcache {} array set mode {exe translucent} } proc init {db} { mk::view layout $db.dirs \ {name:S parent:I {files {name:S size:I date:I contents:M}}} if { [mk::view size $db.dirs] == 0 } { mk::row append $db.dirs name parent -1 } } proc _mount {{file ""} args} { set db mk4vfs[incr v::seq] if {$file == ""} { mk::file open $db init $db set v::mode($db) "translucent" } else { eval [list mk::file open $db $file] $args init $db set mode 0 foreach arg $args { switch -- $arg { -readonly { set mode 1 } -nocommit { set mode 2 } } } if {$mode == 0} { periodicCommit $db } set v::mode($db) [lindex {translucent readwrite readwrite} $mode] } return $db } proc periodicCommit {db} { variable flush set v::timer($db) [after $flush [list ::mk4vfs::periodicCommit $db]] mk::file commit $db return ;# 2005-01-20 avoid returning a value } proc _umount {db args} { catch {after cancel $v::timer($db)} array unset v::mode $db array unset v::timer $db array unset v::cache $db,* array unset v::fcache $db.* mk::file close $db } proc stat {db path {arr ""}} { set sp [::file split $path] set tail [lindex $sp end] set parent 0 set view $db.dirs set type directory foreach ele [lrange $sp 0 end-1] { if {[info exists v::cache($db,$parent,$ele)]} { set parent $v::cache($db,$parent,$ele) } else { set row [mk::select $view -count 1 parent $parent name $ele] if { $row == "" } { vfs::filesystem posixerror $::vfs::posix(ENOENT) } set v::cache($db,$parent,$ele) $row set parent $row } } # Now check if final comp is a directory or a file # CACHING is required - it can deliver a x15 speed-up! if { [string equal $tail "."] || [string equal $tail ":"] \ || [string equal $tail ""] } { set row $parent } elseif { [info exists v::cache($db,$parent,$tail)] } { set row $v::cache($db,$parent,$tail) } else { # File? set fview $view!$parent.files # create a name cache of files in this directory if {![info exists v::fcache($fview)]} { # cache only a limited number of directories if {[array size v::fcache] >= 10} { array unset v::fcache * } set v::fcache($fview) {} mk::loop c $fview { lappend v::fcache($fview) [mk::get $c name] } } set row [lsearch -exact $v::fcache($fview) $tail] #set row [mk::select $fview -count 1 name $tail] #if {$row == ""} { set row -1 } if { $row >= 0 } { set type file set view $view!$parent.files } else { # Directory? set row [mk::select $view -count 1 parent $parent name $tail] if { $row != "" } { set v::cache($db,$parent,$tail) $row } else { vfs::filesystem posixerror $::vfs::posix(ENOENT) } } } if {![string length $arr]} { # The caller doesn't need more detailed information. return 1 } set cur $view!$row upvar 1 $arr sb set sb(type) $type set sb(view) $view set sb(ino) $cur if { [string equal $type "directory"] } { set sb(atime) 0 set sb(ctime) 0 set sb(gid) 0 set sb(mode) 0777 set sb(mtime) 0 set sb(nlink) [expr { [mk::get $cur files] + 1 }] set sb(size) 0 set sb(csize) 0 set sb(uid) 0 } else { set mtime [mk::get $cur date] set sb(atime) $mtime set sb(ctime) $mtime set sb(gid) 0 set sb(mode) 0777 set sb(mtime) $mtime set sb(nlink) 1 set sb(size) [mk::get $cur size] set sb(csize) [mk::get $cur -size contents] set sb(uid) 0 } } proc do_close {db fd mode cur} { if {![regexp {[aw]} $mode]} { error "mk4vfs::do_close called with bad mode: $mode" } mk::set $cur size -1 date [clock seconds] flush $fd if { [string match *z* $mode] } { fconfigure $fd -translation binary seek $fd 0 set data [read $fd] set cdata [vfs::zip -mode compress $data] set len [string length $data] set clen [string length $cdata] if { $clen < $len } { mk::set $cur size $len contents $cdata } else { mk::set $cur size $len contents $data } } else { mk::set $cur size [mk::get $cur -size contents] } # 16oct02 new logic to start a periodic commit timer if not yet running setupCommits $db return "" } proc setupCommits {db} { if {$v::mode($db) eq "readwrite" && ![info exists v::timer($db)]} { periodicCommit $db mk::file autocommit $db } } proc mkdir {db path} { if {$v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } set sp [::file split $path] set parent 0 set view $db.dirs set npath {} # This actually does more work than is needed. Tcl's # vfs only requires us to create the last piece, and # Tcl already knows it is not a file. foreach ele $sp { set npath [file join $npath $ele] if {![catch {stat $db $npath sb}] } { if { $sb(type) != "directory" } { vfs::filesystem posixerror $::vfs::posix(EROFS) } set parent [mk::cursor position sb(ino)] continue } #set parent [mk::cursor position sb(ino)] set cur [mk::row append $view name $ele parent $parent] set parent [mk::cursor position cur] } setupCommits $db return "" } proc getdir {db path {pat *}} { if {[catch { stat $db $path sb }] || $sb(type) != "directory" } { return } # Match directories set parent [mk::cursor position sb(ino)] foreach row [mk::select $sb(view) parent $parent -glob name $pat] { set hits([mk::get $sb(view)!$row name]) 1 } # Match files set view $sb(view)!$parent.files foreach row [mk::select $view -glob name $pat] { set hits([mk::get $view!$row name]) 1 } return [lsort [array names hits]] } proc mtime {db path time} { if {$v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } stat $db $path sb if { $sb(type) == "file" } { mk::set $sb(ino) date $time } return $time } proc delete {db path {recursive 0}} { #puts stderr "mk4delete db $db path $path recursive $recursive" if {$v::mode($db) == "readonly"} { vfs::filesystem posixerror $::vfs::posix(EROFS) } stat $db $path sb if {$sb(type) == "file" } { mk::row delete $sb(ino) if {[regexp {(.*)!(\d+)} $sb(ino) - v r] \ && [info exists v::fcache($v)]} { set v::fcache($v) [lreplace $v::fcache($v) $r $r] } } else { # just mark dirs as deleted set contents [getdir $db $path *] if {$recursive} { # We have to delete these manually, else # they (or their cache) may conflict with # something later foreach f $contents { delete $db [file join $path $f] $recursive } } else { if {[llength $contents]} { vfs::filesystem posixerror $::vfs::posix(ENOTEMPTY) } } array unset v::cache \ "$db,[mk::get $sb(ino) parent],[file tail $path]" # flag with -99, because parent -1 is not reserved for the root dir # deleted entries never get re-used, should be cleaned up one day mk::set $sb(ino) parent -99 name "" # get rid of file entries to release the space in the datafile mk::view size $sb(ino).files 0 } setupCommits $db return "" } } # DEPRECATED - please don't use. namespace eval mk4vfs { namespace export mount umount # deprecated, use vfs::mk4::Mount (first two args are reversed!) proc mount {local mkfile args} { uplevel [list ::vfs::mk4::Mount $mkfile $local] $args } # deprecated: unmounts, but only if vfs was mounted on itself proc umount {local} { foreach {db path} [mk::file open] { if {[string equal $local $path]} { vfs::filesystem unmount $local _umount $db return } } tclLog "umount $local? [mk::file open]" } } tclvfs/library/starkit.tcl000064400000000000000000000113111447560765400156030ustar00nobodynobody# Starkit support, see http://www.equi4.com/starkit/ # by Jean-Claude Wippler, July 2002 package provide starkit 1.3.3 package require vfs # Starkit scripts can launched in a number of ways: # - wrapped or unwrapped # - using tclkit, or from tclsh/wish with a couple of pkgs installed # - with real MetaKit support, or with a read-only fake (ReadKit) # - as 2-file starkit deployment, or as 1-file starpack # # Furthermore, there are three variations: # current: starkits # older: VFS-based "scripted documents" # oldest: pre-VFS "scripted documents" # # The code in here is only called directly from the current starkits. namespace eval starkit { # these variables are defined after the call to starkit::startup # they are special in that a second call will not alter them # (as needed when a starkit sources others for more packages) variable topdir ;# root directory (while the starkit is mounted) variable mode ;# startup mode (starkit, sourced, etc) # called from the header of a starkit proc header {driver args} { if {[catch { set self [fullnormalize [info script]] package require vfs::${driver} eval [list ::vfs::${driver}::Mount $self $self] $args uplevel [list source [file join $self main.tcl]] }]} { panic $::errorInfo } } proc fullnormalize {path} { # SNARFED from tcllib, fileutil. # 8.5 # return [file join {expand}[lrange [file split # [file normalize [file join $path __dummy__]]] 0 end-1]] return [file dirname [file normalize [file join $path __dummy__]]] } # called from the startup script of a starkit to init topdir and auto_path # 2003/10/21, added in 1.3: remember startup mode in starkit::mode proc startup {} { if {![info exists starkit::mode]} { variable mode } set mode [_startup] } # returns how the script was launched: starkit, starpack, unwrapped, or # sourced (2003: also tclhttpd, plugin, or service) proc _startup {} { global argv0 # 2003/02/11: new behavior, if starkit::topdir exists, don't disturb it if {![info exists starkit::topdir]} { variable topdir } set script [fullnormalize [info script]] set topdir [file dirname $script] if {$topdir eq [fullnormalize [info nameofexe]]} { return starpack } # pkgs live in the $topdir/lib/ directory set lib [file join $topdir lib] if {[file isdir $lib]} { autoextend $lib } set a0 [fullnormalize $argv0] if {$topdir eq $a0} { return starkit } if {$script eq $a0} { return unwrapped } # detect when sourced from tclhttpd if {[info procs ::Httpd_Server] ne ""} { return tclhttpd } # detect when sourced from the plugin (tentative) if {[info exists ::embed_args]} { return plugin } # detect when run as an NT service if {[info exists ::tcl_service]} { return service } return sourced } # append an entry to auto_path if it's not yet listed proc autoextend {dir} { global auto_path set dir [fullnormalize $dir] if {[lsearch $auto_path $dir] < 0} { lappend auto_path $dir } } # remount a starkit with different options proc remount {args} { variable topdir foreach {drv arg} [vfs::filesystem info $topdir] { break } vfs::unmount $topdir eval [list [string map {handler Mount} $drv] $topdir $topdir] $args } # terminate with an error message, using most appropriate mechanism proc panic {msg} { if {[info commands wm] ne ""} { catch { wm withdraw . } tk_messageBox -icon error -message $msg -title "Fatal error" } elseif {[info commands ::eventlog] ne ""} { eventlog error $msg } else { puts stderr $msg } exit } # the following proc was copied from the critcl package: # return a platform designator, including both OS and machine # # only use first element of $tcl_platform(os) - we don't care # whether we are on "Windows NT" or "Windows XP" or whatever # # transforms $tcl_platform(machine) for some special cases # - on SunOS, matches for sun4* are transformed to sparc # - on all OS's matches for intel and i*86* are transformed to x86 # - on MacOS X "Power Macintosh" is transformed to ppc # proc platform {} { global tcl_platform set plat [lindex $tcl_platform(os) 0] set mach $tcl_platform(machine) switch -glob -- $mach { sun4* { set mach sparc } intel - i*86* { set mach x86 } "Power Macintosh" { set mach ppc } } switch -- $plat { AIX { set mach ppc } HP-UX { set mach hppa } } return "$plat-$mach" } # load extension from a platform-specific subdirectory proc pload {dir name args} { set f [file join $dir [platform] $name[info sharedlibext]] uplevel 1 [linsert $args 0 load $f] } } tclvfs/library/tarvfs.tcl000064400000000000000000000274701447560765400154440ustar00nobodynobody################################################################################ # This is the first try to provide access to tar-files via # the vfs-mechanism. # This file is copied and adapted from zipvfs.tcl # (and ftpvfs.tcl). The internal structure for the tar-data is stored # analog to zipvfs so that many functions can be the same as in zipvfs. # # Jan 13 2003: Stefan Vogel (stefan.vogel@avinci.de) # (reformatted to tabsize 8 by Vince). # # TODOs: # * add writable access (should be easy with tar-files) # * add gzip-support (?) # * more testing :-( ################################################################################ package require vfs package provide vfs::tar 0.91 # Using the vfs, memchan and Trf extensions, we're able # to write a Tcl-only tar filesystem. namespace eval vfs::tar {} proc vfs::tar::Mount {tarfile local} { set fd [vfs::tar::_open [::file normalize $tarfile]] vfs::filesystem mount $local [list ::vfs::tar::handler $fd] # Register command to unmount vfs::RegisterMount $local [list ::vfs::tar::Unmount $fd] return $fd } proc vfs::tar::Unmount {fd local} { vfs::filesystem unmount $local vfs::tar::_close $fd } proc vfs::tar::handler {tarfd cmd root relative actualpath args} { if {$cmd == "matchindirectory"} { # e.g. called from "glob *" eval [list $cmd $tarfd $relative $actualpath] $args } else { # called for all other commands: access, stat eval [list $cmd $tarfd $relative] $args } } proc vfs::tar::attributes {tarfd} { return [list "state"] } proc vfs::tar::state {tarfd args} { vfs::attributeCantConfigure "state" "readonly" $args } # If we implement the commands below, we will have a perfect # virtual file system for tar files. # Completely copied from zipvfs.tcl proc vfs::tar::matchindirectory {tarfd path actualpath pattern type} { # This call to vfs::tar::_getdir handles empty patterns properly as asking # for the existence of a single file $path only set res [vfs::tar::_getdir $tarfd $path $pattern] if {![string length $pattern]} { if {![vfs::tar::_exists $tarfd $path]} { return {} } set res [list $actualpath] set actualpath "" } set newres [list] foreach p [::vfs::matchCorrectTypes $type $res $actualpath] { lappend newres [file join $actualpath $p] } return $newres } # return the necessary "array" proc vfs::tar::stat {tarfd name} { vfs::tar::_stat $tarfd $name sb array get sb } proc vfs::tar::access {tarfd name mode} { if {$mode & 2} { vfs::filesystem posixerror $::vfs::posix(EROFS) } # Readable, Exists and Executable are treated as 'exists' # Could we get more information from the archive? if {[vfs::tar::_exists $tarfd $name]} { return 1 } else { error "No such file" } } proc vfs::tar::open {tarfd name mode permissions} { # return a list of two elements: # 1. first element is the Tcl channel name which has been opened # 2. second element (optional) is a command to evaluate when # the channel is closed. switch -- $mode { "" - "r" { if {![vfs::tar::_exists $tarfd $name]} { vfs::filesystem posixerror $::vfs::posix(ENOENT) } vfs::tar::_stat $tarfd $name sb set nfd [vfs::memchan] fconfigure $nfd -translation binary # get the starting point from structure seek $tarfd $sb(start) start vfs::tar::_data $tarfd sb data puts -nonewline $nfd $data fconfigure $nfd -translation auto seek $nfd 0 return [list $nfd] } default { vfs::filesystem posixerror $::vfs::posix(EROFS) } } } proc vfs::tar::createdirectory {tarfd name} { vfs::filesystem posixerror $::vfs::posix(EROFS) #error "tar-archives are read-only (not implemented)" } proc vfs::tar::removedirectory {tarfd name recursive} { #::vfs::log "removedirectory $name" vfs::filesystem posixerror $::vfs::posix(EROFS) #error "tar-archives are read-only (not implemented)" } proc vfs::tar::deletefile {tarfd name} { vfs::filesystem posixerror $::vfs::posix(EROFS) #error "tar-archives are read-only (not implemented)" } # don't care about platform-specific attributes proc vfs::tar::fileattributes {tarfd name args} { #::vfs::log "fileattributes $args" switch -- [llength $args] { 0 { # list strings return [list] } 1 { # get value set index [lindex $args 0] return "" } 2 { # set value set index [lindex $args 0] set val [lindex $args 1] vfs::filesystem posixerror $::vfs::posix(EROFS) } } } # set the 'mtime' of a file. proc vfs::tar::utime {fd path actime mtime} { vfs::filesystem posixerror $::vfs::posix(EROFS) } # # tar decoder: # # Format of tar file: # see http://www.gnu.org/manual/tar/html_node/tar_123.html # "comments" are put into the the arrays for readability # the fields in aPosixHeader are stored inside a # 512-byte-block. Not all header-fields are used here. # # Here are some excerpts from the above resource for information # only: # # name, linkname, magic, uname, and gname are null-terminated strings. # All other fileds are zero-filled octal numbers in ASCII. # Each numeric field of width w contains # w minus 2 digits, a space, and a null, # except size, and mtime, which do not contain the trailing null # mtime field is the modification time of the file at the time it was # archived. It is the ASCII representation of the octal value of the # last time the file was modified, represented as an integer number # of seconds since January 1, 1970, 00:00 Coordinated Universal Time namespace eval vfs::tar { set HEADER_SIZE 500 set BLOCK_SIZE 512 # fields of header with start/end-index in "comments": length of # field in bytes (just for documentation) prefix is the # "datatype": s == null-terminated string o == zero-filled octal # number (numeric but leave it octal e.g mode) n == numeric --> # integer change to decimal) "not used" is marked when the field # is not needed anywhere here array set aPosixHeader { name {s 0 99} # 100 mode {o 100 107} # "8 - not used now" uid {n 108 115} # 8 gid {n 116 123} # 8 size {n 124 135} # 12 mtime {n 136 147} # 12 chksum {o 148 155} # "8 - not used" typeflag {o 156 156} # 1 linkname {s 157 256} # "100 - not used" magic {s 257 262} # "6 - not used" version {o 263 264} # "2 - not used" uname {s 265 296} # "32 - not used" gname {s 297 328} # "32 - not used" devmajor {o 329 336} # "8 - not used" devminor {o 337 344} # "8 - not used" prefix {o 345 499} # "155 - not used" } # just for compatibility with posix-header # only DIRTYPE is used array set aTypeFlag { REGTYPE 0 # "regular file" AREGTYPE \000 # "regular file" LNKTYPE 1 # link SYMTYPE 2 # reserved CHRTYPE 3 # "character special" BLKTYPE 4 # "block special" DIRTYPE 5 # directory FIFOTYPE 6 # "FIFO special" CONTTYPE 7 # reserved } } proc vfs::tar::_data {fd arr {varPtr ""}} { upvar 1 $arr sb if {$varPtr eq ""} { seek $fd $sb(size) current } else { upvar 1 $varPtr data set data [read $fd $sb(size)] } } proc vfs::tar::TOC {fd arr toc} { variable aPosixHeader variable aTypeFlag variable HEADER_SIZE variable BLOCK_SIZE upvar 1 $arr sb upvar 1 $toc _toc set pos 0 set sb(nitems) 0 # loop through file in blocks of BLOCK_SIZE while {![eof $fd]} { seek $fd $pos set hdr [read $fd $BLOCK_SIZE] # read header-fields from block (see aPosixHeader) foreach key {name typeflag size mtime uid gid} { set type [lindex $aPosixHeader($key) 0] set positions [lrange $aPosixHeader($key) 1 2] switch $type { s { set $key [eval [list string range $hdr] $positions] # cut the trailing Nulls set $key [string range [set $key] 0 [expr [string first "\000" [set $key]]-1]] } o { # leave it as is (octal value) set $key [eval [list string range $hdr] $positions] } n { set $key [eval [list string range $hdr] $positions] # change to integer scan [set $key] "%o" $key # if not set, set default-value "0" # (size == "" is not a very good value) if {![string is integer [set $key]] || [set $key] == ""} { set $key 0 } } default { error "tar::TOC: '$fd' wrong type for header-field: '$type'" } } } # only the last three octals are interesting for mode # ignore mode now, should this be added?? # set mode 0[string range $mode end-3 end] # get the increment to the next valid block # (ignore file-blocks in between) # if size == 0 the minimum incr is 512 set incr [expr {int(ceil($size/double($BLOCK_SIZE)))*$BLOCK_SIZE+$BLOCK_SIZE}] set startPosition [expr {$pos+$BLOCK_SIZE}] # make it relative to this working-directory, remove the # leading "relative"-paths regexp -- {^(?:\.\.?/)*/?(.*)} $name -> name if {$name != ""} { incr sb(nitems) set sb($name,start) [expr {$pos+$BLOCK_SIZE}] set sb($name,size) $size set type "file" # the mode should be 0777?? or must be changed to decimal? if {$typeflag == $aTypeFlag(DIRTYPE)} { # directory! append this without / # leave mode: 0777 # (else we might not be able to walk through archive) set type "directory" lappend _toc([string trimright $name "/"]) \ name [string trimright $name "/"] \ type $type mtime $mtime size $size mode 0777 \ ino -1 start $startPosition \ depth [llength [file split $name]] \ uid $uid gid $gid } lappend _toc($name) \ name $name \ type $type mtime $mtime size $size mode 0777 \ ino -1 start $startPosition depth [llength [file split $name]] \ uid $uid gid $gid } incr pos $incr } return } proc vfs::tar::_open {path} { set fd [::open $path] if {[catch { upvar #0 vfs::tar::$fd.toc toc fconfigure $fd -translation binary ;#-buffering none vfs::tar::TOC $fd sb toc } err]} { close $fd return -code error $err } return $fd } proc vfs::tar::_exists {fd path} { #::vfs::log "$fd $path" if {$path == ""} { return 1 } else { upvar #0 vfs::tar::$fd.toc toc return [expr {[info exists toc($path)] || [info exists toc([string trimright $path "/"]/)]}] } } proc vfs::tar::_stat {fd path arr} { upvar #0 vfs::tar::$fd.toc toc upvar 1 $arr sb if { $path == "" || $path == "." } { array set sb { type directory mtime 0 size 0 mode 0777 ino -1 depth 0 name "" } } elseif {![info exists toc($path)] } { return -code error "could not read \"$path\": no such file or directory" } else { array set sb $toc($path) } # set missing attributes set sb(dev) -1 set sb(nlink) 1 set sb(atime) $sb(mtime) set sb(ctime) $sb(mtime) return "" } # Treats empty pattern as asking for a particular file only. # Directly copied from zipvfs. proc vfs::tar::_getdir {fd path {pat *}} { upvar #0 vfs::tar::$fd.toc toc if { $path == "." || $path == "" } { set path $pat } else { set path [string tolower $path] if {$pat != ""} { append path /$pat } } set depth [llength [file split $path]] if {$depth} { set ret {} foreach key [array names toc $path] { if {[string index $key end] eq "/"} { # Directories are listed twice: both with and without # the trailing '/', so we ignore the one with continue } array set sb $toc($key) if { $sb(depth) == $depth } { if {[info exists toc(${key}/)]} { array set sb $toc(${key}/) } # remove sb(name) (because == $key) lappend ret [file tail $key] } unset sb } return $ret } else { # just the 'root' of the zip archive. This obviously exists and # is a directory. return [list {}] } } proc vfs::tar::_close {fd} { variable $fd.toc unset -nocomplain $fd.toc ::close $fd } tclvfs/library/tclprocvfs.tcl000064400000000000000000000116771447560765400163260ustar00nobodynobody package provide vfs::ns 0.5.1 package require vfs 1.0 # Thanks to jcw for the idea here. This is a 'file system' which # is actually a representation of the Tcl command namespace hierarchy. # Namespaces are directories, and procedures are files. Tcl allows # procedures with the same name as a namespace, which are hidden in # a filesystem representation. namespace eval vfs::ns {} proc vfs::ns::Mount {ns local} { if {![namespace exists ::$ns]} { error "No such namespace" } ::vfs::log "ns $ns mounted at $local" vfs::filesystem mount $local [list vfs::ns::handler $ns] vfs::RegisterMount $local [list vfs::ns::Unmount] return $local } proc vfs::ns::Unmount {local} { vfs::filesystem unmount $local } proc vfs::ns::handler {ns cmd root relative actualpath args} { regsub -all / $relative :: relative if {$cmd == "matchindirectory"} { eval [list $cmd $ns $relative $actualpath] $args } else { eval [list $cmd $ns $relative] $args } } # If we implement the commands below, we will have a perfect # virtual file system for namespaces. proc vfs::ns::stat {ns name} { ::vfs::log "stat $name" if {[namespace exists ::${ns}::${name}]} { return [list type directory size 0 mode 0777 \ ino -1 depth 0 name $name atime 0 ctime 0 mtime 0 dev -1 \ uid -1 gid -1 nlink 1] } elseif {[llength [info procs ::${ns}::${name}]]} { return [list type file] } else { return -code error "could not read \"$name\": no such file or directory" } } proc vfs::ns::access {ns name mode} { ::vfs::log "access $name $mode" if {[namespace exists ::${ns}::${name}]} { return 1 } elseif {[llength [info procs ::${ns}::${name}]]} { if {$mode & 2} { error "read-only" } return 1 } else { error "No such file" } } proc vfs::ns::exists {ns name} { if {[namespace exists ::${ns}::${name}]} { return 1 } elseif {[llength [info procs ::${ns}::${name}]]} { return 1 } else { return 0 } } proc vfs::ns::open {ns name mode permissions} { ::vfs::log "open $name $mode $permissions" # return a list of two elements: # 1. first element is the Tcl channel name which has been opened # 2. second element (optional) is a command to evaluate when # the channel is closed. switch -- $mode { "" - "r" { set nfd [vfs::memchan] fconfigure $nfd -translation binary puts -nonewline $nfd [_generate ::${ns}::${name}] fconfigure $nfd -translation auto seek $nfd 0 return [list $nfd] } default { return -code error "illegal access mode \"$mode\"" } } } proc vfs::ns::_generate {p} { lappend a proc $p set argslist [list] foreach arg [info args $p] { if {[info default $p $arg v]} { lappend argslist [list $arg $v] } else { lappend argslist $arg } } lappend a $argslist [info body $p] } proc vfs::ns::matchindirectory {ns path actualpath pattern type} { ::vfs::log "matchindirectory $path $actualpath $pattern $type" set res [list] set ns ::[string trim $ns :] set nspath ${ns}::${path} if {![namespace exists $nspath]} {return {}} set slash 1 if {[::vfs::matchDirectories $type]} { # add matching directories to $res if {[string length $pattern]} { eval [linsert [namespace children $nspath $pattern] 0 lappend res] } elseif {[namespace exists $nspath]} { lappend res $nspath } } if {[::vfs::matchFiles $type]} { # add matching files to $res if {[string length $pattern]} { eval [linsert [info procs ${nspath}::$pattern] 0 lappend res] } elseif {[llength [info procs $nspath]]} { lappend res $nspath set slash 0 } } # There is a disconnect between 8.4 and 8.5 with the / handling # Make sure actualpath gets just one trailing / if {$slash && ![string match */ $actualpath]} { append actualpath / } set realres [list] foreach r $res { regsub "^(::)?${ns}(::)?${path}(::)?" $r $actualpath rr lappend realres $rr } #::vfs::log $realres return $realres } proc vfs::ns::createdirectory {ns name} { ::vfs::log "createdirectory $name" namespace eval ::${ns}::${name} {} } proc vfs::ns::removedirectory {ns name recursive} { ::vfs::log "removedirectory $name" namespace delete ::${ns}::${name} } proc vfs::ns::deletefile {ns name} { ::vfs::log "deletefile $name" rename ::${ns}::${name} {} } proc vfs::ns::fileattributes {ns name args} { ::vfs::log "fileattributes $args" switch -- [llength $args] { 0 { # list strings return [list -args -body] } 1 { # get value set index [lindex $args 0] switch -- $index { 0 { ::info args ::${ns}::${name} } 1 { ::info body ::${ns}::${name} } } } 2 { # set value set index [lindex $args 0] set val [lindex $args 1] switch -- $index { 0 { error "read-only" } 1 { error "unimplemented" } } } } } proc vfs::ns::utime {what name actime mtime} { ::vfs::log "utime $name" error "" } tclvfs/library/template000075500000000000000000000000001447560765400151555ustar00nobodynobodytclvfs/library/template/chrootvfs.tcl000064400000000000000000000074151447560765400177640ustar00nobodynobody#/usr/bin/env tclsh if 0 { ######################## chrootvfs.tcl -- Written by Stephen Huntley (stephen.huntley@alum.mit.edu) License: Tcl license Version 1.5 A chroot virtual filesystem. This virual filesystem has an effect similar to a "chroot" command; it makes the named existing directory appear to be the top of the filesystem and makes the rest of the real filesystem invisible. This vfs does not block access by the "exec" command to the real filesystem outside the chroot directory, or that of the "open" command when its command pipeline syntax is used. At the end of this file is example code showing one way to set up a safe slave interpreter suitable for running a process safely with limited filesystem access: its file access commands are re-enabled, the exec command remains disabled, the open command is aliased so that it can only open files and can't spawn new processes, and mounted volumes besides the volume on which the chroot directory resides are aliased so that they act as mirrors of the chroot directory. Such an interpreter should be advantageous for applications such as a web server: which requires some filesystem access but presents security threats that make access limitations desirable. Install: This code requires the vfs::template package included in the Tclvfs distribution. Usage: mount ?-volume? examples: mount $::env(HOME) / mount {C:\My Music} C:/ mount -volume /var/www/htdocs chroot:// ######################## } namespace eval ::vfs::template::chroot { package require vfs::template 1.5 package provide vfs::template::chroot 1.5.2 # read template procedures into current namespace. Do not edit: foreach templateProc [namespace eval ::vfs::template {info procs}] { set infoArgs [info args ::vfs::template::$templateProc] set infoBody [info body ::vfs::template::$templateProc] proc $templateProc $infoArgs $infoBody } proc file_attributes {file {attribute {}} args} {eval file attributes \$file $attribute $args} catch {rename redirect_handler {}} catch {rename handler redirect_handler} proc handler args { set path [lindex $args 0] set to [lindex $args 2] set volume [lindex $::vfs::template::mount($to) 1] if {$volume != "-volume"} {set volume {}} set startDir [pwd] ::vfs::filesystem unmount $to set err [catch {set rv [uplevel ::vfs::template::chroot::redirect_handler $args]} result] ; set errorCode $::errorCode eval ::vfs::filesystem mount $volume [list $to] \[list [namespace current]::handler \[file normalize \$path\]\] if {[pwd] != $startDir} {catch {cd $startDir}} if {$err && ([lindex $errorCode 0] == "POSIX")} {vfs::filesystem posixerror $::vfs::posix([lindex $errorCode 1])} if $err {return -code $err $result} return $rv } # Example code to set up a safe interpreter with limited filesystem access: proc chroot_slave {} { file mkdir /tmp package require vfs::template ::vfs::template::chroot::mount -volume /tmp C:/ set vols [lsort -unique [file volumes]] foreach vol $vols { if {$vol == "C:/"} {continue} ::vfs::template::mount C:/ $vol } set slave [interp create -safe] $slave expose cd $slave expose encoding $slave expose fconfigure $slave expose file $slave expose glob $slave expose load $slave expose pwd $slave expose socket $slave expose source $slave alias exit exit_safe $slave $slave alias open open_safe $slave interp share {} stdin $slave interp share {} stdout $slave interp share {} stderr $slave } proc exit_safe {slave} { interp delete $slave } proc open_safe {args} { set slave [lindex $args 0] set handle [lindex $args 1] set args [lrange $args 1 end] if {[string index $handle 0] != "|"} { eval [eval list interp invokehidden $slave open $args] } else { error "permission denied" } } } # end namespace ::vfs::template::chroot tclvfs/library/template/collatevfs.tcl000064400000000000000000000317171447560765400201130ustar00nobodynobodyif 0 { ######################## collatevfs.tcl -- Written by Stephen Huntley (stephen.huntley@alum.mit.edu) License: Tcl license Version 1.5.3 A collate/broadcast/collect/catchup virtual filesystem. Requires the template vfs in templatevfs.tcl. Collate: reads from multiple specified directories and presents the results as one at the mount location. Broadcast: applies all writes in the mount location to multiple specified directories. Collect: copies any file read from or written to any of the above locations to specified directories. Catchup: If any specified directory is not available during any write action, the action is recorded in a catchup queue. With each subsequent write action, the queue is examined, and if any directory has become available, the action is performed, allowing offline directories to "catch up." Usage: mount ?-read -write -collect -catchup ? Each pathname in is meant to stand individually, the symbol is not meant to indicate a Tcl list. The sets of specified locations are independent; they can overlap or not as desired. Note each option flag is optional, one could for example use only the -read flag to create a read-only directory. Directories do not have to exist and may go missing after mount, non-reachable locations will be ignored. Options: -read When an individual file is opened for reading, each of the directories specified is searched in order for the file; the first file found with the appropriate name is opened. When a subdirectory listing is generated, the combined files of the corresponding subdirectory of all specified directories are listed together. -write When an individual file is opened for writing, each of the directories specified is searched in order for the file; the first file found with the appropriate name is opened. If the file doesn't exist, it is created in the first specified write location. When the file is closed, a copy of it is distributed to each specified write directory. -collect Auto-generates one or more file caches; a copy of any file opened for reading or writing in any of the above specified directories is made to each directory specified with the -collect flag. Collect locations are not included in file or directory listings, and are not searched for read access; so in order to make an active read cache, for example, one would have to include one directory location in both the -read and -collect sets. -catchup If this flag is included, the catchup function is activated, and a copy of the catchup queue is stored in a file in each of the specified directories. File writes, directory creations and file/directory deletes are stored in the catchup queue if any write location is offline; at the next write/creation/delete the queue is examined, and if any skipped action can be completed due to a location becoming available again, it will be. A catchup attempt will be made at mount time if this flag is included. The values of each option can be changed dynamically after mount by using the "file attributes" command on the mount virtual directory. Each option is editable as an attribute; i.e., "file attributes C:/collate -write C:/tmp" The collate vfs inherits the -cache and -volume options of the template vfs. Example use: specify parallel locations on a hard drive, on a CD-ROM mount and an ftp vfs as the read list. Files will be read first from the hard drive, if not found there the CD-ROM and ftp site will be searched in turn. The hard drive can be specified as the single write location, and no writes to the CD-ROM or ftp site will ever be attempted: mount -read C:/install/package/docs CDROM:/package/docs FTP:/pub/releases/package/docs -write C:/install/package/docs C:/collate/docs Example collect location use: specify a single hard drive location as a read and collect directory. Specify a ftp vfs as a secondary read directory. As ftp files are downloaded they are copied to the collect directory; the local copies are accessed first on subsequent reads: hence the collect specification produces a self-generating local cache: mount -read C:/install/package/images FTP:/pub/releases/package/images -collect C:/install/package/images C:/collate/images ######################## } package require vfs::template 1.5 package provide vfs::template::collate 1.5.3 namespace eval ::vfs::template::collate { # read template procedures into current namespace. Do not edit: foreach templateProc [namespace eval ::vfs::template {info procs}] { set infoArgs [info args ::vfs::template::$templateProc] set infoBody [info body ::vfs::template::$templateProc] proc $templateProc $infoArgs $infoBody } # edit following procedures: proc close_ {channel} { upvar root root relative relative foreach file [lrange [WriteFile $root $relative close] 1 end] { if ![WriteTest $file] {continue} file mkdir [file dirname $file] set f [open $file w] fconfigure $f -translation binary seek $channel 0 fcopy $channel $f close $f } return } proc file_atime {file time} { upvar root root relative relative foreach file [WriteFile $root $relative open] { file atime $file $time } } proc file_mtime {file time} { upvar root root relative relative foreach file [WriteFile $root $relative open] { file mtime $file $time } } proc file_attributes {file {attribute {}} args} { upvar root root relative relative if {($relative == {}) && ([string map {-read 1 -write 1 -collect 1 -catchup 1} $attribute] == 1)} { set attribute [string range $attribute 1 end] if {$args == {}} {eval return \$::vfs::template::collate::${attribute}(\$root)} set ::vfs::template::collate::${attribute}($root) [lindex $args 0] set ::vfs::template::collate::catchup [file isdirectory [lindex $::vfs::template::collate::catchupstore 0]] return } if {$args != {}} { foreach file [WriteFile $root $relative open] { file attributes $file $attribute $args } return } set file [AcquireFile $root $relative] set returnValue [eval file attributes \$file $attribute $args] if {($relative == {}) && ($attribute == {})} {set returnValue [concat $returnValue [list -read $::vfs::template::collate::read($root) -write $::vfs::template::collate::write($root) -collect $::vfs::template::collate::collect($root) -catchup $::vfs::template::collate::catchupstore($root)]]} return $returnValue } proc file_delete {file} { upvar root root relative relative foreach file [WriteFile $root $relative delete] { file delete -force -- $file } } proc file_executable {file} { upvar root root relative relative set file [AcquireFile $root $relative] file executable $file } proc file_exists {file} { upvar root root relative relative expr ![catch {AcquireFile $root $relative}] } proc file_mkdir {file} { upvar root root relative relative foreach file [WriteFile $root $relative mkdir] { file mkdir $file } } proc file_readable {file} { upvar root root relative relative set file [AcquireFile $root $relative] file readable $file } proc file_stat {file array} { upvar root root relative relative set file [AcquireFile $root $relative] upvar $array fs ; file stat $file fs } proc file_writable {file} { upvar root root relative relative expr ![catch {WriteFile $root $relative open}] } proc glob_ {directory dir nocomplain tails types typeString dashes pattern} { upvar root root relative relative set allFiles {} set newFiles {} foreach path $::vfs::template::collate::read($root) { if ![file exists $path] {continue} set allFiles [concat $allFiles [glob -directory [file join $path $relative] -nocomplain -tails -types $typeString -- $pattern]] } set allFiles [lsort -unique $allFiles] return $allFiles } proc open_ {file mode} { upvar root root relative relative if [string match w* $mode] { set file [lindex [WriteFile $root $relative open] 0] file mkdir [file dirname $file] return [open $file $mode] } if [string match r* $mode] { set file [AcquireFile $root $relative] if {$mode == "r"} { foreach cpath $::vfs::template::collate::collect($root) { set cfile [file join $cpath $relative] if {$file == $cfile} {continue} if ![file exists $cpath] {continue} file mkdir [::file dirname $cfile] file copy -force -- $file $cfile } return [open $file r] } set wfile [lindex [WriteFile $root $relative open] 0] file mkdir [file dirname $wfile] if {$wfile != $file} {file copy -force -- $file $wfile} return [open $wfile $mode] } if [string match a* $mode] { set wfile [lindex [WriteFile $root $relative open] 0] file mkdir [file dirname $wfile] if ![catch {set file [AcquireFile $root $relative]}] { if {$wfile != $file} {file copy -force -- $file $wfile} } return [open $wfile $mode] } } proc MountProcedure {args} { upvar volume volume # take real and virtual directories from command line args. set to [lindex $args end] if [string equal $volume {}] {set to [::file normalize $to]} # add custom handling for new vfs args here. set ::vfs::template::collate::catchup($to) 0 set ::vfs::template::collate::read($to) {} set ::vfs::template::collate::write($to) {} set ::vfs::template::collate::collect($to) {} set ::vfs::template::collate::catchupstore($to) {} set args [lrange $args 0 end-1] set argsIndex [llength $args] for {set i 0} {$i < $argsIndex} {incr i} { set arg [lindex $args $i] switch -- $arg { -read { set type read } -write { set type write } -collect { set type collect } -catchup { set ::vfs::template::collate::catchup($to) 1 set type catchupstore } default { eval lappend ::vfs::template::collate::${type}(\$to) \[::file normalize \$arg\] } } } WriteFile $to {} mkdir # return two-item list consisting of real and virtual locations. lappend pathto {} lappend pathto $to return $pathto } proc UnmountProcedure {path to} { # add custom unmount handling of new vfs elements here. unset -nocomplain ::vfs::template::collate::read($to) unset -nocomplain ::vfs::template::collate::write($to) unset -nocomplain ::vfs::template::collate::collect($to) unset -nocomplain ::vfs::template::collate::catchup($to) unset -nocomplain ::vfs::template::collate::catchupstore($to) return } proc AcquireFile {root relative} { foreach path $::vfs::template::collate::read($root) { set file [::file join $path $relative] if [::file exists $file] { return $file } } vfs::filesystem posixerror $::vfs::posix(ENOENT) ; return -code error $::vfs::posix(ENOENT) } proc WriteFile {root relative action} { set allWriteLocations {} foreach awl [concat $::vfs::template::collate::write($root) $::vfs::template::collate::collect($root)] { if {[lsearch $allWriteLocations $awl] < 0} {lappend allWriteLocations $awl} } if ![llength $allWriteLocations] { vfs::filesystem posixerror $::vfs::posix(EROFS) ; return -code error $::vfs::posix(EROFS) } if {$vfs::template::collate::catchup($root) && ([file tail $relative] != ".vfs_catchup") && ($action != "open")} { set catchupActivate 1 set addCatchup {} set newCatchup {} } else { set catchupActivate 0 } set returnValue {} foreach path $allWriteLocations { if {$catchupActivate && ![file exists $path]} { append addCatchup "[list $action $path $relative]\n" continue } set rvfile [file join $path $relative] if {[lsearch $returnValue $rvfile] < 0} {lappend returnValue $rvfile} } if {$returnValue == {}} {vfs::filesystem posixerror $::vfs::posix(EROFS) ; return -code error $::vfs::posix(EROFS)} if $catchupActivate { set catchup {} set ::vfs::template::vfs_retrieve 1 foreach store $::vfs::template::collate::catchupstore($root) { set store [file join $store ".vfs_catchup"] if [file readable $store] { set f [open $store r] unset ::vfs::template::vfs_retrieve seek $f 0 set catchup [read $f] close $f break } } catch {set currentRead [AcquireFile $root {}]} result foreach {action path rel} $catchup { if {$relative == $rel} {continue} if ![file exists $path] {append newCatchup "[list $action $path $rel]\n" ; continue} if {[lsearch $allWriteLocations $path] < 0} {continue} switch -- $action { close { if {![info exists currentRead] || ([set source [file join $currentRead $rel]] == [set target [file join $path $rel]])} { append newCatchup "[list $action $path $rel]\n" ; continue } if ![file exists $source] {continue} file mkdir [file dirname $target] file copy -force -- $source $target } delete { file delete -force -- [file join $path $rel] } mkdir { file mkdir [file join $path $rel] } } } append newCatchup $addCatchup foreach path $::vfs::template::collate::catchupstore($root) { set vfscatchup [file join $path ".vfs_catchup"] set ::vfs::template::vfs_retrieve 1 set err [catch { if {$newCatchup != {}} { set f [open $vfscatchup w] puts $f $newCatchup close $f } else { file delete $vfscatchup } } result] unset ::vfs::template::vfs_retrieve } } return $returnValue } proc WriteTest {args} { return 1 } } # end namespace ::vfs::template::collate tclvfs/library/template/deltavfs.tcl000064400000000000000000000221261447560765400175530ustar00nobodynobodyif 0 { ######################## deltavfs.tcl -- Written by Stephen Huntley (stephen.huntley@alum.mit.edu) License: Tcl license Version 1.5.2 A delta virtual filesystem. Requires the template vfs in templatevfs.tcl. Mount the delta vfs first, then mount the versioning vfs using the virtual location created by the delta vfs as its existing directory. As the versioning filesystem generates a new separate file for every file edit, this filesystem will invisibly generate and manage deltas of the separate versions to save space. Usage: mount The delta vfs inherits the -cache and -volume options of the template vfs. ######################## } package require vfs::template 1.5 package require vfs::template::version 1.5 package provide vfs::template::version::delta 1.5.2 namespace eval ::vfs::template::version::delta { # read template procedures into current namespace. Do not edit: foreach templateProc [namespace eval ::vfs::template {info procs}] { set infoArgs [info args ::vfs::template::$templateProc] set infoBody [info body ::vfs::template::$templateProc] proc $templateProc $infoArgs $infoBody } # edit following procedures: proc close_ {channel} { upvar path path relative relative set file [file join $path $relative] set fileName $file set f [open $fileName w] fconfigure $f -translation binary seek $f 0 seek $channel 0 fcopy $channel $f close $f Delta $fileName return } proc file_atime {file time} { set file [GetFileName $file] file atime $file $time } proc file_mtime {file time} { set file [GetFileName $file] file mtime $file $time } proc file_attributes {file {attribute {}} args} { set file [GetFileName $file] eval file attributes \$file $attribute $args } proc file_delete {file} { if [file isdirectory $file] {catch {file delete $file}} set fileName [GetFileName $file] set timeStamp [lindex [split [file tail $fileName] \;] 1] if [string equal $timeStamp {}] { catch {file delete $fileName} result return } set targetFile [Reconstitute $fileName] set referenceFiles [glob -directory [file dirname $fileName] -nocomplain *vfs&delta$timeStamp] if {[lindex [file system $fileName] 0] != "tclvfs"} {append referenceFiles " [glob -directory [file dirname $fileName] -nocomplain -type hidden *vfs&delta$timeStamp]"} foreach referenceFile $referenceFiles { regsub {\;vfs&delta[0-9]*$} $referenceFile "" reconFile] set f [open $referenceFile r] fconfigure $f -translation binary set signature [read $f] close $f tpatch $targetFile $signature $reconFile file delete $referenceFile } close $targetFile file delete -force -- $fileName } proc file_executable {file} { set file [GetFileName $file] file executable $file } proc file_exists {file} { set file [GetFileName $file] file exists $file } proc file_mkdir {file} {file mkdir $file} proc file_readable {file} { set file [GetFileName $file] file readable $file } proc file_stat {file array} { upvar $array fs set fileName [GetFileName $file] set endtag [lindex [split $fileName \;] end] if {[string first "vfs&delta" $endtag] || [string equal "vfs&delta" $endtag]} {file stat $fileName fs ; return} set f [open $fileName r] fconfigure $f -translation binary set copyinstructions [read $f] close $f array set fileStats [lindex $copyinstructions 3] unset copyinstructions set size $fileStats(size) file stat $fileName fs set fs(size) $size return } proc file_writable {file} { set file [GetFileName $file] file writable $file } proc glob_ {directory dir nocomplain tails types typeString dashes pattern} { set globList [glob -directory $dir -nocomplain -tails -types $typeString -- $pattern] set newGlobList {} foreach gL $globList { regsub {\;vfs&delta.*$} $gL "" gL lappend newGlobList $gL } return $newGlobList } proc open_ {file mode} { set fileName [GetFileName $file] set newFile 0 if ![file exists $fileName] {set newFile 1} set fileName $file set channelID [Reconstitute $fileName] if [string equal $channelID {}] {set channelID [open $fileName $mode] ; close $channelID ; set channelID [memchan]} if $newFile {catch {file attributes $fileName -permissions $permissions}} return $channelID } proc MountProcedure {args} { upvar volume volume # take real and virtual directories from command line args. set to [lindex $args end] if [string equal $volume {}] {set to [::file normalize $to]} set path [::file normalize [lindex $args end-1]] # make sure mount location exists: ::file mkdir $path # add custom handling for new vfs args here. package require trsync namespace import -force ::trsync::tdelta ::trsync::tpatch # return two-item list consisting of real and virtual locations. lappend pathto $path lappend pathto $to return $pathto } proc UnmountProcedure {path to} { # add custom unmount handling of new vfs elements here. return } proc Delta {filename} { set fileRoot [lindex [split [file tail $filename] \;] 0] set fileNames [glob -nocomplain -path [file join [file dirname $filename] $fileRoot] *] if {[lindex [file system $filename] 0] != "tclvfs"} {append fileNames " [glob -nocomplain -path [file join [file dirname $filename] $fileRoot] -type hidden *]"} set nonDeltas {} foreach fn $fileNames { set endtag [lindex [split $fn \;] end] if ![string first "vfs&delta" $endtag] {continue} lappend nonDeltas $fn set atimes($fn) [file atime $fn] } if {[set deltaIndex [llength $nonDeltas]] < 2} {return} set nonDeltas [lsort -dictionary $nonDeltas] incr deltaIndex -1 set i 0 while {$i < $deltaIndex} { set referenceFile [lindex $nonDeltas $i] set targetFile [lindex $nonDeltas [incr i]] set signature [tdelta $referenceFile $targetFile $::trsync::blockSize 1 1] set targetTimeStamp [lindex [split $targetFile \;] 1] file stat $referenceFile fileStats set signatureSize [string length $signature] if {$signatureSize > $fileStats(size)} { set fileName $referenceFile\;vfs&delta file rename $referenceFile $fileName continue } array set fileStats [file attributes $referenceFile] set fileName $referenceFile\;vfs&delta$targetTimeStamp set f [open $fileName w] fconfigure $f -translation binary puts -nonewline $f $signature close $f file delete $referenceFile array set fileAttributes [file attributes $fileName] if [info exists fileAttributes(-readonly)] {catch {file attributes $fileName -readonly 0}} if [info exists fileAttributes(-permissions)] {catch {file attributes $fileName -permissions rw-rw-rw-}} catch {file attributes $fileName -owner $fileStats(uid)} catch {file attributes $fileName -group $fileStats(gid)} catch {file mtime $fileName $fileStats(mtime)} catch {file atime $fileName $fileStats(atime)} foreach attr [array names fileStats] { if [string first "-" $attr] {continue} if [string equal [array get fileStats $attr] [array get fileAttributes $attr]] {continue} if [string equal "-permissions" $attr] {continue} catch {file attributes $fileName $attr $fileStats($attr)} } catch {file attributes $fileName -permissions $fileStats(mode)} catch {file attributes $fileName -readonly $fileStats(-readonly)} } foreach fn [array names atimes] { if ![file exists $fn] {continue} file atime $fn $atimes($fn) } } proc GetFileName {file} { set isdir 0 if {([string first \; $file] < 0) && ![set isdir [file isdirectory $file]]} {return {}} if $isdir {return $file} set fileNames [glob -nocomplain -path $file *] if {[lindex [file system $file] 0] != "tclvfs"} {append fileNames " [glob -nocomplain -path $file -type hidden *]"} set fileName [lindex $fileNames 0] if [set i [expr [lsearch -exact $fileNames $file] + 1]] {set fileName [lindex $fileNames [incr i -1]]} return $fileName } proc Reconstitute {fileName} { if ![catch {set channelID [open $fileName r]}] {return $channelID} if ![catch {set channelID [open $fileName\;vfs&delta r]}] {return $channelID} set targetFiles [glob -nocomplain -path $fileName *] if {[lindex [file system $fileName] 0] != "tclvfs"} {append targetFiles " [glob -nocomplain -path $fileName -type hidden *]"} set targetFile [lindex $targetFiles 0] set targetFile [string trim $targetFile] if [string equal $targetFile {}] {return} set fileStack {} while {[string first "\;vfs&delta" $targetFile] > -1} { if ![regexp {\;vfs&delta([0-9]+)$} $targetFile trash targetTime] {break} set fileStack "[list $targetFile] $fileStack" set targetFiles [glob -directory [file dirname $fileName] *\;$targetTime*] if {[lindex [file system $fileName] 0] != "tclvfs"} {append targetFiles " [glob -directory [file dirname $fileName] -nocomplain -type hidden *\;$targetTime*]"} set targetFile [lindex $targetFiles 0] set atimes($targetFile) [file atime $targetFile] } set targetFile [open $targetFile r] foreach fs $fileStack { set f [open $fs r] fconfigure $f -translation binary set copyInstructions [read $f] close $f set fileToConstruct [memchan] tpatch $targetFile $copyInstructions $fileToConstruct catch {close $targetFile} set targetFile $fileToConstruct } foreach fn [array names atimes] { file atime $fn $atimes($fn) } fconfigure $targetFile -translation auto seek $targetFile 0 return $targetFile } } # end namespace ::vfs::template::version::delta tclvfs/library/template/fishvfs.tcl000064400000000000000000000445471447560765400174260ustar00nobodynobody#! /usr/bin/env tclsh if 0 { ######################## fishvfs.tcl -- A "FIles transferred over SHell" virtual filesystem This is not an official "FISH" protocol client as described at: http://mini.net/tcl/12792 but it utilizes the same concept of turning any computer that offers access via ssh, rsh or similar shell into a file server. Written by Stephen Huntley (stephen.huntley@alum.mit.edu) License: Tcl license Version 1.5.2 Usage: mount ?-volume? \ ?-cache ? \ # cache retention seconds ?-exec? \ # location of executable ?-transport ? \ # can be ssh, rsh or plink ?-user ? \ # remote computer login name ?-password ? \ # remote computer login password ?-host ? \ # remote computer domain name ?-port ? \ # override default port ?