Index: Makefile ================================================================== --- Makefile +++ Makefile @@ -3,82 +3,77 @@ include odieConfig.sh all: install core: install -install: - $(SHELL) scripts/make_skel.sh - $(SHELL) scripts/make_tcl.sh - ${ODIE_TCLSH} scripts/make_core.tcl - ${ODIE_TCLSH} scripts/make_basekit.tcl - $(ODIE_TCLSH) scripts/make_sqlite.tcl - $(ODIE_TCLSH) scripts/make_sherpa.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.tcl ${LOCAL_REPO}/lib/odieConfig.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.sh ${LOCAL_REPO}/lib/odieConfig.sh - -upgrade: - fossil update - ./config.status - ${ODIE_TCLSH} scripts/upgrade.tcl - ${ODIE_TCLSH} scripts/make_core.tcl - ${ODIE_TCLSH} scripts/make_basekit.tcl - $(ODIE_TCLSH) scripts/make_sqlite.tcl - $(ODIE_TCLSH) scripts/make_sherpa.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.tcl ${LOCAL_REPO}/lib/odieConfig.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.sh ${LOCAL_REPO}/lib/odieConfig.sh - -upgrade-tcl: - fossil update - ./config.status - $(SHELL) scripts/make_tcl.sh - ${ODIE_TCLSH} scripts/upgrade.tcl - ${ODIE_TCLSH} scripts/make_core.tcl - ${ODIE_TCLSH} scripts/make_basekit.tcl - $(ODIE_TCLSH) scripts/make_sqlite.tcl - $(ODIE_TCLSH) scripts/make_sherpa.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.tcl ${LOCAL_REPO}/lib/odieConfig.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.sh ${LOCAL_REPO}/lib/odieConfig.sh +reconfig: + rm -f autosetup/jimsh0.exe autosetup/jimsh0 + ODIE_BUILD_TCLSH=`autosetup/find-tclsh` + ${ODIE_BUILD_TCLSH} autosetup/autosetup $(ODIE_RECONFIG_OPTS) + cp -a ${ODIE_SRC_DIR}/odieConfig.tcl ${LOCAL_REPO}/lib/odieConfig.tcl + cp -a ${ODIE_SRC_DIR}/odieConfig.sh ${LOCAL_REPO}/lib/odieConfig.sh + +install: sherpa + $(SHELL) scripts/make_skel.sh + $(SHELL) scripts/make_tcl.sh + ODIE_BUILD_TCLSH=`autosetup/find-tclsh` + $(ODIE_BUILD_TCLSH) scripts/make_sherpa.tcl + $(SHERPA) upgrade sqlite odielib tcllib + ${ODIE_BUILD_TCLSH} scripts/make_basekit.tcl + +packages: sherpa + $(SHERPA) install sqlite odielib tcllib + +upgrade: + $(FOSSIL) update + ${ODIE_BUILD_TCLSH} scripts/upgrade.tcl + $(ODIE_BUILD_TCLSH) scripts/make_sherpa.tcl + $(SHERPA) upgrade sqlite odielib tcllib + ${ODIE_BUILD_TCLSH} scripts/make_basekit.tcl + +upgrade-tcl: + $(FOSSIL) update + $(SHELL) scripts/make_tcl.sh + ODIE_BUILD_TCLSH=`autosetup/find-tclsh` + ${ODIE_BUILD_TCLSH} scripts/upgrade.tcl + $(ODIE_BUILD_TCLSH) scripts/make_sherpa.tcl + $(SHERPA) upgrade sqlite odielib tcllib + ${ODIE_BUILD_TCLSH} scripts/make_basekit.tcl tcl: $(SHELL) scripts/make_tcl.sh rebuild: $(SHELL) scripts/make_distclean.sh - fossil update - ./config.status + $(FOSSIL) update $(SHELL) scripts/make_tcl.sh - ${ODIE_TCLSH} scripts/make_core.tcl - ${ODIE_TCLSH} scripts/make_basekit.tcl - $(ODIE_TCLSH) scripts/make_sqlite.tcl - $(ODIE_TCLSH) scripts/make_sherpa.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.tcl ${LOCAL_REPO}/lib/odieConfig.tcl - cp -a ${ODIE_SRC_DIR}/odieConfig.sh ${LOCAL_REPO}/lib/odieConfig.sh + $(ODIE_BUILD_TCLSH) scripts/make_sherpa.tcl + $(SHERPA) upgrade sqlite odielib tcllib + ${ODIE_BUILD_TCLSH} scripts/make_basekit.tcl distclean: $(SHELL) scripts/make_distclean.sh basekit: - ${ODIE_TCLSH} scripts/make_basekit.tcl - -odielib-rebuild: - make -C src/odielib distclean - ${ODIE_TCLSH} scripts/make_core.tcl - -odielib: - ${ODIE_TCLSH} scripts/make_core.tcl - -sqlite: - ${ODIE_TCLSH} scripts/make_sqlite.tcl - -sherpa: basekit sqlite odielib - $(ODIE_TCLSH) scripts/make_sherpa.tcl - + ${ODIE_BUILD_TCLSH} scripts/make_basekit.tcl + +sherpa: $ODIE_DOWNLOAD/sherpa/sherpa.tcl + +$ODIE_DOWNLOAD/sherpa/sherpa.tcl: + $(ODIE_BUILD_TCLSH) scripts/make_sherpa.tcl + +$(ODIE_MKHDR): + $(CC) -o mkhdr.o scripts/mkhdr.c + $(CC) mkhdr.o -o mkhdr${EXE_SUFFIX} + cp -f mkhdr@EXE@ $(ODIE_MKHDR) + +mkhdr: $(ODIE_MKHDR) mkdoc: $(TCLSH) scripts/mkdoc.tcl .PHONY: all binaries clean depend distclean doc install libraries test upgrade upgrade-tcl -.PHONY: core sherpa basekit odielib toadkit sqlite - +.PHONY: core sherpa basekit odielib toadkit sqlite reconfig mkhdr packages + # 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: Index: apps/sherpa/Makefile ================================================================== --- apps/sherpa/Makefile +++ apps/sherpa/Makefile @@ -43,16 +43,19 @@ eval ${ODIE_RM} ${APPNAME}.vfs manifest.txt plugin.zip mkdir -p ${APPNAME}.vfs mkdir -p ${APPNAME}.vfs/apps cp -a src/* ${APPNAME}.vfs/ - cp -a $(project-base)/modules ${APPNAME}.vfs/lib + cp -a $(project-base)/../odielib/modules ${APPNAME}.vfs/lib + cp -a $(project-base)/../sherpa/modules ${APPNAME}.vfs/lib + cp -a $(project-base)/../sherpa/recipes ${APPNAME}.vfs cp -a ../../../odie/odieConfig.tcl ${APPNAME}.vfs/ cp -a ../../../odie/odieConfig.sh ${APPNAME}.vfs/ cp ${ODIE_SRC_DIR}/apps/e.tcl ${APPNAME}.vfs/apps/edit.tcl cp ${ODIE_SRC_DIR}/apps/tkdiff.tcl ${APPNAME}.vfs/apps/diff.tcl cp ${ODIE_SRC_DIR}/scripts/rmdir.tcl ${APPNAME}.vfs/apps/rm.tcl + cp -a ../../recipes/ ${APPNAME}.vfs/recipes/ ${ODIE_TCLSH} ../sherpa.tcl vfs_install ${APPNAME}.vfs ${PACKAGES} ${ODIE_TCLSH} ../sherpa.tcl vfs_mkIndex ${APPNAME}.vfs install: ${APPNAME}${EXE} Index: apps/sherpa/src/main.tcl ================================================================== --- apps/sherpa/src/main.tcl +++ apps/sherpa/src/main.tcl @@ -58,12 +58,16 @@ # description: # Find package attempts to load packages live from source, and failing that # use an internal version ### proc ::find_package package { - if {[file exists [file join $::odie(odie_src_dir) modules $package index.tcl]]} { - uplevel #0 source [file join $::odie(odie_src_dir) modules $package index.tcl] + if {[file exists [file join $::odie(src_dir) modules $package index.tcl]]} { + uplevel #0 source [file join $::odie(src_dir) modules $package index.tcl] + } elseif {[file exists [file join $::odie(sandbox) odielib modules $package index.tcl]]} { + uplevel #0 source [file join $::odie(sandbox) odielib modules $package index.tcl] + } elseif {[file exists [file join $::odie(sandbox) sherpa modules $package index.tcl]]} { + uplevel #0 source [file join $::odie(sandbox) sherpa modules $package index.tcl] } elseif {[file exists [file join $::odie(sandbox) taolib modules $package index.tcl]]} { uplevel #0 source [file join $::odie(sandbox) taolib modules $package index.tcl] } else { uplevel #0 [list package require $package] } Index: apps/temple/src/main.tcl ================================================================== --- apps/temple/src/main.tcl +++ apps/temple/src/main.tcl @@ -39,16 +39,18 @@ proc ::find_package package { if {[file exists [file join $::odie(sandbox) tcllib modules $package index.tcl]]} { uplevel #0 source [file join $::odie(sandbox) tcllib modules $package index.tcl] } elseif {[file exists [file join $::odie(sandbox) tcllib modules $package $package.tcl]]} { uplevel #0 source [file join $::odie(sandbox) tcllib modules $package $package.tcl] - } elseif {[file exists [file join $::odie(odie_src_dir) modules $package index.tcl]]} { - uplevel #0 source [file join $::odie(odie_src_dir) modules $package index.tcl] - } elseif {[file exists [file join $::odie(odie_src_dir) modules $package index.tcl]]} { - uplevel #0 source [file join $::odie(odie_src_dir) modules $package $package.tcl] + } elseif {[file exists [file join $::odie(src_dir) modules $package index.tcl]]} { + uplevel #0 source [file join $::odie(src_dir) modules $package index.tcl] } elseif {[file exists [file join $::odie(sandbox) taolib modules $package index.tcl]]} { uplevel #0 source [file join $::odie(sandbox) taolib modules $package index.tcl] + } elseif {[file exists [file join $::odie(sandbox) odielib modules $package index.tcl]]} { + uplevel #0 source [file join $::odie(sandbox) odielib modules $package index.tcl] + } elseif {[file exists [file join $::odie(sandbox) sherpa modules $package index.tcl]]} { + uplevel #0 source [file join $::odie(sandbox) sherpa modules $package index.tcl] } else { uplevel #0 [list package require $package] } } ADDED auto.def Index: auto.def ================================================================== --- /dev/null +++ auto.def @@ -0,0 +1,282 @@ +### +# Odie autosetup script +### +use system + +options { + sandbox: with-sandbox: => {Writable location for builds} + download: with-download => {Writable location for downloading source} + tclbranch:release => {Branch of the Tcl core to build against} + tkbranch: => {Branch of the Tk core to build against + * defaults to tclbranch + * if "none" is specified, Tk is disabled} + windowsystem:native => {For platforms with multiple windowing systems, which system to target. +native - The native window system +x11 - An x11 emulation environment +none - Disable Tk support (equivilent to tkbranch=none) +} + 64bit:detect => {Enable 64 bit support (default detect)} + fossil: => {Location of native fossil executable (default detect)} + tclsh: => {Location of native tcl shell (default detect)} +} + +set ::odie(src_dir) [file dirname [file-normalize [info script]]] +use odie + +switch [opt-val 64bit] { + amd64 - + x64 - + x86_64 { + set ::odie(64bit) 1 + } + {} - + detect { + } + default { + set ::odie(64bit) [opt-bool 64bit] + } +} +set ::odie_config(64bit) $::odie(64bit) +set ::odie(host) [get-define host] +set ::odie(target) [get-define target] + +#-------------------------------------------------------------------- +# Determines the correct executable file extension (.exe) +#-------------------------------------------------------------------- +define EXE $::odie(exe_suffix) +define EXE_SUFFIX $::odie(exe_suffix) +define target [get-define target] + +set ::odie(sandbox) [opt-val sandbox] +if {$::odie(sandbox) eq {}} { + set ::odie(sandbox) [file join $::odie(prefix) sandbox] +} else { + set ::odie_config(sandbox) $::odie(sandbox) +} +set ::odie(sandbox_path) $::odie(sandbox) +set ::odie(download) [opt-val download] +if {$::odie(download) eq {}} { + set ::odie(download) [file join $::odie(prefix) download] +} else { + set ::odie_config(download) $::odie(download) +} +set ::odie(download_path) $::odie(download) + +set ::odie(fossil) [lindex [opt-val fossil] end] +if {$::odie(fossil) eq {}} { + set ::odie(fossil) [lindex [find-an-executable -required fossil] 0] +} else { + set ::odie_config(fossil) $::odie(fossil) +} +set ::odie_prog(fossil) $::odie(fossil) +define FOSSIL_PROG $::odie(fossil) + +set ::odie(build_tclsh) [lindex [opt-val tclsh] end] +if {$::odie(build_tclsh) eq {}} { + set ::odie(build_tclsh) [info nameofexecutable] +} else { + set ::odie_config(tclsh) $::odie(build_tclsh) +} +set ::odie_prog(tclsh) $::odie(build_tclsh) +define ODIE_BUILD_TCLSH $::odie(build_tclsh) + +use cc cc-lib odie + +foreach {program required domake} { + zip 1 0 + unzip 1 0 + tar 1 0 + git 0 1 + strip 0 0 + mkhdr 0 1 + sherpa 0 1 +} { + if {$required} { + set exename [lindex [find-an-executable -required $program] 0] + } else { + set exename [lindex [find-an-executable $program] 0] + } + if {$domake && $exename eq {}} { + set prog_build($program) 1 + set exename [file join $::odie(prefix) bin ${program}$::odie(exe_suffix)] + } else { + set prog_build($program) 0 + } + set odie_prog($program) [::realpath $exename] + define [string toupper ${program}_prog] [::cygpath $exename] +} + +# XXX SC_ODIE +# XXX SC_ENABLE_SHARED +# XXX ODIE_PROG_TCLSH +# XXX ODIE_PROG_WISH + +### +# Build Tcl/Tk +### + +set ::odie_tcl(fossil_branch) [opt-val tclbranch] +if {$::odie_tcl(fossil_branch) eq {}} { + set ::odie_tcl(fossil_branch) release +} +set ::odie_config(tclbranch) $::odie_tcl(fossil_branch) + + +if {$::odie(64bit)} { + lappend ::odie_tcl(config_flags) --enable-64bit +} else { + lappend ::odie_tcl(config_flags) --enable-64bit=no +} + +switch $::odie(teacup_os) { + "macosx" { + lappend ::odie_tcl(config_flags) --enable-corefoundation=no --enable-framework=no + } + "macosx10.5" { + lappend ::odie_tcl(config_flags) --enable-corefoundation=yes --enable-framework=no + } +} + +set ::odie(window_system) [opt-val windowsystem] +set ::odie_tk(fossil_branch) [opt-val tkbranch] +if { $::odie(window_system) eq "none" || $::odie_tk(fossil_branch) eq "none"} { + ### + # Tk support disabled + ### + set ::odie_tk(fossil_branch) none + set ::odie(window_system) none + set ::odie(tk_binary_platform) none +} else { + set ::odie_tk(config_flags) $::odie_tcl(config_flags) + if {$::odie_tk(fossil_branch) eq {}} { + set ::odie_tk(fossil_branch) $::odie_tcl(fossil_branch) + } + switch $::odie(os) { + "linux" { + set ::odie(window_system) x11 + lappend ::odie_tk(config_flags) --enable-xft=no --enable-xss=no + } + "macosx" { + ### + # Window system only matters on OSX + ### + if { [string compare "10.5" $::odie(os_version)] < 0 } { + # Pre 10.5 systems don't use a compadible cocoa + set ::odie(window_system) x11 + } + switch $::odie(window_system) { + windows { + set ::odie(window_system) windows + } + x11 { + set ::odie(window_system) x11 + set ::odie(teacup_profile) $::odie(teacup_os)-x11-$::odie(cpu) + lappend ::odie_tk(config_flags) --enable-aqua=no --x-includes=/opt/X11/include + } + default { + set ::odie(window_system) cocoa + set ::odie(teacup_profile_tk) $::odie(teacup_profile) + lappend ::odie_tk(config_flags) --enable-aqua=yes + } + } + } + } +} +set ::odie_config(tkbranch) $::odie_tk(fossil_branch) +set ::odie_config(windowsystem) $::odie(window_system) + +### +# Detect a CC to use +### +if {![info exists ::odie(cc)]} { + set ::odie(cc) [get-define CC] +} + +foreach {field value} [array get ::odie] { + define [string toupper ODIE_$field] $value +} +foreach {field value} [array get ::odie_tcl] { + define [string toupper TCL_$field] $value +} +foreach {field value} [array get ::odie_tk] { + define [string toupper TK_$field] $value +} +foreach {field value} [array get ::odie_prog] { + define [string toupper ODIE_PROG_$field] $value + define [string toupper ${field}_PROG] $value +} +define FOSSIL_CHECKOUT $::odie(fossil_checkout) +make-template odieConfig.sh.in odieConfig.sh +make-template odieConfig.tcl.in odieConfig.tcl + +set fout [open [file join $::odie(src_dir) odieConfig.tcl] a] +puts $fout "array set ::odie_config \{" +foreach {field} [lsort [array names ::odie_config]] { + puts $fout " [list $field $::odie_config($field)]" +} +puts $fout "\}" + +puts $fout "array set ::odie \{" +foreach {field} [lsort [array names ::odie]] { + puts $fout " [list $field $::odie($field)]" +} +puts $fout "\}" + +puts $fout "array set ::odie_tcl \{" +foreach {field} [lsort [array names ::odie_tcl]] { + puts $fout " [list $field $::odie_tcl($field)]" +} +puts $fout "\}" + +puts $fout "array set ::odie_tk \{" +foreach {field} [lsort [array names ::odie_tk]] { + puts $fout " [list $field $::odie_tk($field)]" +} +puts $fout "\}" + +puts $fout "array set ::odie_prog \{" +foreach {field} [lsort [array names ::odie_prog]] { + puts $fout " [list $field $::odie_prog($field)]" +} +puts $fout "\}" + +close $fout + +set fout [open [file join $::odie(src_dir) odieConfig.sh] a] +set opts {} +foreach {field} [lsort [array names ::odie_config]] { + set value $::odie_config($field) + lappend opts --${field}=$value + if {[llength $value]!=1} { + set value '$value' + } + puts $fout "ODIE_CONFIG_[string toupper $field]=$value" +} +puts $fout "ODIE_RECONFIG_OPTS=" +foreach opt $opts { + puts $fout "ODIE_RECONFIG_OPTS+=$opt" +} + +foreach {field} [lsort [array names ::odie]] { + set value $::odie($field) + if {[llength $value]!=1} { + set value '$value' + } + puts $fout "ODIE_[string toupper $field]=$value" +} +foreach {field} [lsort [array names ::odie_tcl]] { + set value $::odie_tcl($field) + if {[llength $value]!=1} { + set value '$value' + } + puts $fout "TCL_[string toupper $field]=$value" +} +foreach {field} [lsort [array names ::odie_tk]] { + set value $::odie_tk($field) + if {[llength $value]!=1} { + set value '$value' + } + puts $fout "TK_[string toupper $field]=$value" +} + +close $fout ADDED autosetup/LICENSE Index: autosetup/LICENSE ================================================================== --- /dev/null +++ autosetup/LICENSE @@ -0,0 +1,35 @@ +Unless explicitly stated, all files which form part of autosetup +are released under the following license: + +--------------------------------------------------------------------- +autosetup - A build environment "autoconfigurator" + +Copyright (c) 2010-2011, WorkWare Systems + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE WORKWARE SYSTEMS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WORKWARE +SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation +are those of the authors and should not be interpreted as representing +official policies, either expressed or implied, of WorkWare Systems. ADDED autosetup/Makefile Index: autosetup/Makefile ================================================================== --- /dev/null +++ autosetup/Makefile @@ -0,0 +1,22 @@ +# This is a convenience Makefile to do a few admin tasks +all: + @echo "Try 'make reference' or './autosetup --help'" + +VERSION := $(shell ./autosetup --version) + +dist: clean + @./autosetup --install=tmp/autosetup-$(VERSION) >/dev/null + @tar -C tmp -czf autosetup-$(VERSION).tar.gz autosetup-$(VERSION) + @rm -rf tmp + @echo Created autosetup-$(VERSION).tar.gz + +PAGER ?= less + +help: + ./autosetup --help + +ref reference: + ./autosetup --reference + +html: + ./autosetup --reference=asciidoc | asciidoc -o autosetup-reference.html - ADDED autosetup/README.autosetup Index: autosetup/README.autosetup ================================================================== --- /dev/null +++ autosetup/README.autosetup @@ -0,0 +1,1 @@ +This is autosetup v0.6.6. See http://msteveb.github.com/autosetup/ ADDED autosetup/README.md Index: autosetup/README.md ================================================================== --- /dev/null +++ autosetup/README.md @@ -0,0 +1,52 @@ +From the autosetup v0.6.2 User Manual... +======================================== + +autosetup is a tool, similar to autoconf, to configure a build system for +the appropriate environment, according to the system capabilities and the user +configuration. + +autosetup is designed to be light-weight, fast, simple and flexible. + +Notable features include: + + * Easily check for headers, functions, types for C/C++ + * Easily support user configuration options + * Can generate files based on templates, such as Makefile.in => Makefile + * Can generate header files based on checked features + * Excellent support for cross compilation + * Replacement for autoconf in many situations + * Runs with either Tcl 8.5+, Jim Tcl or just a C compiler (using the + included Jim Tcl source code!) + * autosetup is intended to be distributed with projects - no version + issues + +autosetup is particularly targeted towards building C/C++ applications on Unix +systems, however it can be extended for other environments as needed. + +autosetup is *not*: + + * A build system + * A replacement for automake + * Intended to replace all possible uses of autoconf + +Try: ./autosetup --help or ./autosetup --reference + +Or view the manual on github at: + + + +Quick Start +----------- + +To install autosetup into your project, 'cd' to the top level +of your project and run: + + <path-to-autosetup>/autosetup --install + +Once autosetup is installed, create auto.def, run: + + ./configure + +To migrate an autoconf-enabled project to autosetup: + + <path-to-autosetup>/migrate-autoconf ADDED autosetup/TODO Index: autosetup/TODO ================================================================== --- /dev/null +++ autosetup/TODO @@ -0,0 +1,15 @@ +Wed 15 Dec 2010 07:31:39 EST +---------------------------- + +Expand the examples + +Have 'autosetup --init' generate a typical Makefile.in if one doesn't exist. + +autosetup should have a "meta-parse" phase to check that auto.def +includes modules before options, and has an options section. + +Consider if we can get away without config.sub and config.guess. +Projects which need them could provide their own. +Many projects do not. + +Unit tests. ADDED autosetup/autosetup Index: autosetup/autosetup ================================================================== --- /dev/null +++ autosetup/autosetup @@ -0,0 +1,222 @@ +#!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: +# \ +dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@" + +set autosetup(version) 0.6.6 + +# Can be set to 1 to debug early-init problems +set autosetup(debug) 0 + +################################################################## +# +# Main flow of control, option handling +# +proc main {argv} { + global autosetup define + + # There are 3 potential directories involved: + # 1. The directory containing autosetup (this script) + # 2. The directory containing auto.def + # 3. The current directory + + # From this we need to determine: + # a. The path to this script (and related support files) + # b. The path to auto.def + # c. The build directory, where output files are created + + # This is also complicated by the fact that autosetup may + # have been run via the configure wrapper ([getenv WRAPPER] is set) + + # Here are the rules. + # a. This script is $::argv0 + # => dir, prog, exe, libdir + # b. auto.def is in the directory containing the configure wrapper, + # otherwise it is in the current directory. + # => srcdir, autodef + # c. The build directory is the current directory + # => builddir, [pwd] + + # 'misc' is needed before we can do anything, so set a temporary libdir + # in case this is the development version + set autosetup(libdir) [file dirname $::argv0]/lib + use misc + + # (a) + set autosetup(dir) [realdir [file dirname [realpath $::argv0]]] + set autosetup(prog) [file join $autosetup(dir) [file tail $::argv0]] + set autosetup(exe) [getenv WRAPPER $autosetup(prog)] + if {$autosetup(installed)} { + set autosetup(libdir) $autosetup(dir) + } else { + set autosetup(libdir) [file join $autosetup(dir) lib] + } + autosetup_add_dep $autosetup(prog) + + # (b) + if {[getenv WRAPPER ""] eq ""} { + # Invoked directly + set autosetup(srcdir) [pwd] + } else { + # Invoked via the configure wrapper + set autosetup(srcdir) [file dirname $autosetup(exe)] + } + set autosetup(autodef) [relative-path $autosetup(srcdir)/auto.def] + + # (c) + set autosetup(builddir) [pwd] + + set autosetup(argv) $argv + set autosetup(cmdline) {} + set autosetup(options) {} + set autosetup(optionhelp) {} + set autosetup(showhelp) 0 + + # Parse options + use getopt + + array set ::useropts [getopt argv] + + #"=Core Options:" + options-add { + help:=local => "display help and options. Optionally specify a module name, such as --help=system" + version => "display the version of autosetup" + ref:=text manual:=text + reference:=text => "display the autosetup command reference. 'text', 'wiki', 'asciidoc' or 'markdown'" + debug => "display debugging output as autosetup runs" + install:=. => "install autosetup to the current or given directory (in the 'autosetup/' subdirectory)" + force init:=help => "create initial auto.def, etc. Use --init=help for known types" + # Undocumented options + option-checking=1 + nopager + quiet + timing + conf: + } + + #parray ::useropts + if {[opt-bool version]} { + puts $autosetup(version) + exit 0 + } + + # autosetup --conf=alternate-auto.def + if {[opt-val conf] ne ""} { + set autosetup(autodef) [opt-val conf] + } + + # Debugging output (set this early) + incr autosetup(debug) [opt-bool debug] + incr autosetup(force) [opt-bool force] + incr autosetup(msg-quiet) [opt-bool quiet] + incr autosetup(msg-timing) [opt-bool timing] + + # If the local module exists, source it now to allow for + # project-local customisations + if {[file exists $autosetup(libdir)/local.tcl]} { + use local + } + + # Now any auto-load modules + foreach file [glob -nocomplain $autosetup(libdir)/*.auto $autosetup(libdir)/*/*.auto] { + automf_load source $file + } + + if {[opt-val help] ne ""} { + incr autosetup(showhelp) + use help + autosetup_help [opt-val help] + } + + if {[opt-val {manual ref reference}] ne ""} { + use help + autosetup_reference [opt-val {manual ref reference}] + } + + if {[opt-val init] ne ""} { + use init + autosetup_init [opt-val init] + } + + if {[opt-val install] ne ""} { + use install + autosetup_install [opt-val install] + } + + if {![file exists $autosetup(autodef)]} { + # Check for invalid option first + options {} + user-error "No auto.def found in \"$autosetup(srcdir)\" (use [file tail $::autosetup(exe)] --init to create one)" + } + + # Parse extra arguments into autosetup(cmdline) + foreach arg $argv { + if {[regexp {([^=]*)=(.*)} $arg -> n v]} { + dict set autosetup(cmdline) $n $v + define $n $v + } else { + user-error "Unexpected parameter: $arg" + } + } + + autosetup_add_dep $autosetup(autodef) + + set cmd [file-normalize $autosetup(exe)] + foreach arg $autosetup(argv) { + append cmd " [quote-if-needed $arg]" + } + define AUTOREMAKE $cmd + + # Log how we were invoked + configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]" + + # Note that auto.def is *not* loaded in the global scope + source $autosetup(autodef) + + # Could warn here if options {} was not specified + + show-notices + + if {$autosetup(debug)} { + msg-result "Writing all defines to config.log" + configlog "================ defines ======================" + foreach n [lsort [array names define]] { + configlog "define $n $define($n)" + } + } + + exit 0 +} + +# Initial settings +set autosetup(exe) $::argv0 +set autosetup(istcl) 1 +set autosetup(start) [clock millis] +set autosetup(installed) 0 +set autosetup(msg-checking) 0 +set autosetup(msg-quiet) 0 + +# Embedded modules are inserted below here +##-- CUT HERE --## +set corefile [file join [file dirname $::argv0] lib core.tcl] +if {[file exist $corefile]} { + source $corefile +} + +################################################################## +# +# Entry/Exit +# +if {$autosetup(debug)} { + main $argv +} +if {[catch {main $argv} msg opts] == 1} { + show-notices + autosetup-full-error [error-dump $msg $opts $::autosetup(debug)] + if {!$autosetup(debug)} { + puts stderr "Try: '[file tail $autosetup(exe)] --debug' for a full stack trace" + } + exit 1 +} ADDED autosetup/cc-db.tcl Index: autosetup/cc-db.tcl ================================================================== --- /dev/null +++ autosetup/cc-db.tcl @@ -0,0 +1,15 @@ +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc-db' module provides a knowledge based of system idiosyncracies +# In general, this module can always be included + +use cc + +module-options {} + +# openbsd needs sys/types.h to detect some system headers +cc-include-needs sys/socket.h sys/types.h +cc-include-needs netinet/in.h sys/types.h ADDED autosetup/cc-lib.tcl Index: autosetup/cc-lib.tcl ================================================================== --- /dev/null +++ autosetup/cc-lib.tcl @@ -0,0 +1,161 @@ +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# Provides a library of common tests on top of the 'cc' module. + +use cc + +module-options {} + +# @cc-check-lfs +# +# The equivalent of the AC_SYS_LARGEFILE macro +# +# defines 'HAVE_LFS' if LFS is available, +# and defines '_FILE_OFFSET_BITS=64' if necessary +# +# Returns 1 if 'LFS' is available or 0 otherwise +# +proc cc-check-lfs {} { + cc-check-includes sys/types.h + msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..." + set lfs 1 + if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} { + msg-result no + } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} { + define _FILE_OFFSET_BITS 64 + msg-result yes + } else { + set lfs 0 + msg-result none + } + define-feature lfs $lfs + return $lfs +} + +# @cc-check-endian +# +# The equivalent of the AC_C_BIGENDIAN macro +# +# defines 'HAVE_BIG_ENDIAN' if endian is known to be big, +# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little. +# +# Returns 1 if determined, or 0 if not. +# +proc cc-check-endian {} { + cc-check-includes sys/types.h sys/param.h + set rc 0 + msg-checking "Checking endian..." + cc-with {-includes {sys/types.h sys/param.h}} { + if {[cctest -code { + #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != BIG_ENDIAN + #error little + #endif + }]} { + define-feature big-endian + msg-result "big" + set rc 1 + } elseif {[cctest -code { + #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != LITTLE_ENDIAN + #error big + #endif + }]} { + define-feature little-endian + msg-result "little" + set rc 1 + } else { + msg-result "unknown" + } + } + return $rc +} + +# @cc-check-flags flag ?...? +# +# Checks whether the given C/C++ compiler flags can be used. Defines feature +# names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and +# appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'. +proc cc-check-flags {args} { + set result 1 + array set opts [cc-get-settings] + switch -exact -- $opts(-lang) { + c++ { + set lang C++ + set prefix CXXFLAG + } + c { + set lang C + set prefix CFLAG + } + default { + autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)" + } + } + foreach flag $args { + msg-checking "Checking whether the $lang compiler accepts $flag..." + if {[cctest -cflags $flag]} { + msg-result yes + define-feature $prefix$flag + cc-with [list -cflags [list $flag]] + define-append ${prefix}S $flag + } else { + msg-result no + set result 0 + } + } + return $result +} + +# @cc-check-standards ver ?...? +# +# Checks whether the C/C++ compiler accepts one of the specified '-std=$ver' +# options, and appends the first working one to '-cflags' and 'CFLAGS' or +# 'CXXFLAGS'. +proc cc-check-standards {args} { + array set opts [cc-get-settings] + foreach std $args { + if {[cc-check-flags -std=$std]} { + return $std + } + } + return "" +} + +# Checks whether $keyword is usable as alignof +proc cctest_alignof {keyword} { + msg-checking "Checking for $keyword..." + if {[cctest -code [subst -nobackslashes { + printf("minimum alignment is %d == %d\n", ${keyword}(char), ${keyword}('x')); + }]]} then { + msg-result ok + define-feature $keyword + } else { + msg-result "not found" + } +} + +# @cc-check-c11 +# +# Checks for several C11/C++11 extensions and their alternatives. Currently +# checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'. +proc cc-check-c11 {} { + msg-checking "Checking for _Static_assert..." + if {[cctest -code { + _Static_assert(1, "static assertions are available"); + }]} then { + msg-result ok + define-feature _Static_assert + } else { + msg-result "not found" + } + + cctest_alignof _Alignof + cctest_alignof __alignof__ + cctest_alignof __alignof +} ADDED autosetup/cc-shared.tcl Index: autosetup/cc-shared.tcl ================================================================== --- /dev/null +++ autosetup/cc-shared.tcl @@ -0,0 +1,112 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc-shared' module provides support for shared libraries and shared objects. +# It defines the following variables: +# +## SH_CFLAGS Flags to use compiling sources destined for a shared library +## SH_LDFLAGS Flags to use linking (creating) a shared library +## SH_SOPREFIX Prefix to use to set the soname when creating a shared library +## SH_SOEXT Extension for shared libs +## SH_SOEXTVER Format for versioned shared libs - %s = version +## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object +## SHOBJ_LDFLAGS Flags to use linking a shared object, undefined symbols allowed +## SHOBJ_LDFLAGS_R - as above, but all symbols must be resolved +## SH_LINKFLAGS Flags to use linking an executable which will load shared objects +## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries +## STRIPLIBFLAGS Arguments to strip to strip a dynamic library + +module-options {} + +# Defaults: gcc on unix +define SHOBJ_CFLAGS -fpic +define SHOBJ_LDFLAGS -shared +define SH_CFLAGS -fpic +define SH_LDFLAGS -shared +define SH_LINKFLAGS -rdynamic +define SH_SOEXT .so +define SH_SOEXTVER .so.%s +define SH_SOPREFIX -Wl,-soname, +define LD_LIBRARY_PATH LD_LIBRARY_PATH +define STRIPLIBFLAGS --strip-unneeded + +# Note: This is a helpful reference for identifying the toolchain +# http://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers + +switch -glob -- [get-define host] { + *-*-darwin* { + define SHOBJ_CFLAGS "-dynamic -fno-common" + define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup" + define SHOBJ_LDFLAGS_R -bundle + define SH_CFLAGS -dynamic + define SH_LDFLAGS -dynamiclib + define SH_LINKFLAGS "" + define SH_SOEXT .dylib + define SH_SOEXTVER .%s.dylib + define SH_SOPREFIX -Wl,-install_name, + define LD_LIBRARY_PATH DYLD_LIBRARY_PATH + define STRIPLIBFLAGS -x + } + *-*-ming* - *-*-cygwin - *-*-msys { + define SHOBJ_CFLAGS "" + define SHOBJ_LDFLAGS "-shared -static-libgcc -static-libstd++" + define SH_CFLAGS "" + define SH_LDFLAGS "-shared -static-libgcc -static-libstd++" + define SH_LINKFLAGS "" + define SH_SOEXT .dll + define SH_SOEXTVER .dll + define SH_SOPREFIX "" + define LD_LIBRARY_PATH PATH + } + sparc* { + if {[msg-quiet cc-check-decls __SUNPRO_C]} { + msg-result "Found sun stdio compiler" + # sun stdio compiler + # XXX: These haven't been fully tested. + define SHOBJ_CFLAGS -KPIC + define SHOBJ_LDFLAGS "-G" + define SH_CFLAGS -KPIC + define SH_LINKFLAGS -Wl,-export-dynamic + define SH_SOPREFIX -Wl,-h, + } else { + # sparc has a very small GOT table limit, so use -fPIC + define SH_CFLAGS -fPIC + define SHOBJ_CFLAGS -fPIC + } + } + *-*-solaris* { + if {[msg-quiet cc-check-decls __SUNPRO_C]} { + msg-result "Found sun stdio compiler" + # sun stdio compiler + # XXX: These haven't been fully tested. + define SHOBJ_CFLAGS -KPIC + define SHOBJ_LDFLAGS "-G" + define SH_CFLAGS -KPIC + define SH_LINKFLAGS -Wl,-export-dynamic + define SH_SOPREFIX -Wl,-h, + } + } + *-*-hpux { + # XXX: These haven't been tested + define SHOBJ_CFLAGS "+O3 +z" + define SHOBJ_LDFLAGS -b + define SH_CFLAGS +z + define SH_LINKFLAGS -Wl,+s + define LD_LIBRARY_PATH SHLIB_PATH + } + *-*-haiku { + define SHOBJ_CFLAGS "" + define SHOBJ_LDFLAGS -shared + define SH_CFLAGS "" + define SH_LDFLAGS -shared + define SH_LINKFLAGS "" + define SH_SOPREFIX "" + define LD_LIBRARY_PATH LIBRARY_PATH + } +} + +if {![is-defined SHOBJ_LDFLAGS_R]} { + define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS] +} ADDED autosetup/cc.tcl Index: autosetup/cc.tcl ================================================================== --- /dev/null +++ autosetup/cc.tcl @@ -0,0 +1,699 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc' module supports checking various 'features' of the C or C++ +# compiler/linker environment. Common commands are cc-check-includes, +# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template. +# +# The following environment variables are used if set: +# +## CC - C compiler +## CXX - C++ compiler +## CCACHE - Set to "none" to disable automatic use of ccache +## CFLAGS - Additional C compiler flags +## CXXFLAGS - Additional C++ compiler flags +## LDFLAGS - Additional compiler flags during linking +## LIBS - Additional libraries to use (for all tests) +## CROSS - Tool prefix for cross compilation +# +# The following variables are defined from the corresponding +# environment variables if set. +# +## CPPFLAGS +## LINKFLAGS +## CC_FOR_BUILD +## LD + +use system + +module-options {} + +# Note that the return code is not meaningful +proc cc-check-something {name code} { + uplevel 1 $code +} + +# Checks for the existence of the given function by linking +# +proc cctest_function {function} { + cctest -link 1 -declare "extern void $function\(void);" -code "$function\();" +} + +# Checks for the existence of the given type by compiling +proc cctest_type {type} { + cctest -code "$type _x;" +} + +# Checks for the existence of the given type/structure member. +# e.g. "struct stat.st_mtime" +proc cctest_member {struct_member} { + lassign [split $struct_member .] struct member + cctest -code "static $struct _s; return sizeof(_s.$member);" +} + +# Checks for the existence of the given define by compiling +# +proc cctest_define {name} { + cctest -code "#ifndef $name\n#error not defined\n#endif" +} + +# Checks for the existence of the given name either as +# a macro (#define) or an rvalue (such as an enum) +# +proc cctest_decl {name} { + cctest -code "#ifndef $name\n(void)$name;\n#endif" +} + +# @cc-check-sizeof type ... +# +# Checks the size of the given types (between 1 and 32, inclusive). +# Defines a variable with the size determined, or "unknown" otherwise. +# e.g. for type 'long long', defines SIZEOF_LONG_LONG. +# Returns the size of the last type. +# +proc cc-check-sizeof {args} { + foreach type $args { + msg-checking "Checking for sizeof $type..." + set size unknown + # Try the most common sizes first + foreach i {4 8 1 2 16 32} { + if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} { + set size $i + break + } + } + msg-result $size + set define [feature-define-name $type SIZEOF_] + define $define $size + } + # Return the last result + get-define $define +} + +# Checks for each feature in $list by using the given script. +# +# When the script is evaluated, $each is set to the feature +# being checked, and $extra is set to any additional cctest args. +# +# Returns 1 if all features were found, or 0 otherwise. +proc cc-check-some-feature {list script} { + set ret 1 + foreach each $list { + if {![check-feature $each $script]} { + set ret 0 + } + } + return $ret +} + +# @cc-check-includes includes ... +# +# Checks that the given include files can be used +proc cc-check-includes {args} { + cc-check-some-feature $args { + set with {} + if {[dict exists $::autosetup(cc-include-deps) $each]} { + set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]] + msg-quiet cc-check-includes {*}$deps + foreach i $deps { + if {[have-feature $i]} { + lappend with $i + } + } + } + if {[llength $with]} { + cc-with [list -includes $with] { + cctest -includes $each + } + } else { + cctest -includes $each + } + } +} + +# @cc-include-needs include required ... +# +# Ensures that when checking for 'include', a check is first +# made for each 'required' file, and if found, it is #included +proc cc-include-needs {file args} { + foreach depfile $args { + dict set ::autosetup(cc-include-deps) $file $depfile 1 + } +} + +# @cc-check-types type ... +# +# Checks that the types exist. +proc cc-check-types {args} { + cc-check-some-feature $args { + cctest_type $each + } +} + +# @cc-check-defines define ... +# +# Checks that the given preprocessor symbol is defined +proc cc-check-defines {args} { + cc-check-some-feature $args { + cctest_define $each + } +} + +# @cc-check-decls name ... +# +# Checks that each given name is either a preprocessor symbol or rvalue +# such as an enum. Note that the define used for a decl is HAVE_DECL_xxx +# rather than HAVE_xxx +proc cc-check-decls {args} { + set ret 1 + foreach name $args { + msg-checking "Checking for $name..." + set r [cctest_decl $name] + define-feature "decl $name" $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + set ret 0 + } + } + return $ret +} + +# @cc-check-functions function ... +# +# Checks that the given functions exist (can be linked) +proc cc-check-functions {args} { + cc-check-some-feature $args { + cctest_function $each + } +} + +# @cc-check-members type.member ... +# +# Checks that the given type/structure members exist. +# A structure member is of the form "struct stat.st_mtime" +proc cc-check-members {args} { + cc-check-some-feature $args { + cctest_member $each + } +} + +# @cc-check-function-in-lib function libs ?otherlibs? +# +# Checks that the given given function can be found in one of the libs. +# +# First checks for no library required, then checks each of the libraries +# in turn. +# +# If the function is found, the feature is defined and lib_$function is defined +# to -l$lib where the function was found, or "" if no library required. +# In addition, -l$lib is added to the LIBS define. +# +# If additional libraries may be needed for linking, they should be specified +# as $extralibs as "-lotherlib1 -lotherlib2". +# These libraries are not automatically added to LIBS. +# +# Returns 1 if found or 0 if not. +# +proc cc-check-function-in-lib {function libs {otherlibs {}}} { + msg-checking "Checking libs for $function..." + set found 0 + cc-with [list -libs $otherlibs] { + if {[cctest_function $function]} { + msg-result "none needed" + define lib_$function "" + incr found + } else { + foreach lib $libs { + cc-with [list -libs -l$lib] { + if {[cctest_function $function]} { + msg-result -l$lib + define lib_$function -l$lib + define-append LIBS -l$lib + incr found + break + } + } + } + } + } + if {$found} { + define [feature-define-name $function] + } else { + msg-result "no" + } + return $found +} + +# @cc-check-tools tool ... +# +# Checks for existence of the given compiler tools, taking +# into account any cross compilation prefix. +# +# For example, when checking for "ar", first AR is checked on the command +# line and then in the environment. If not found, "${host}-ar" or +# simply "ar" is assumed depending upon whether cross compiling. +# The path is searched for this executable, and if found AR is defined +# to the executable name. +# Note that even when cross compiling, the simple "ar" is used as a fallback, +# but a warning is generated. This is necessary for some toolchains. +# +# It is an error if the executable is not found. +# +proc cc-check-tools {args} { + foreach tool $args { + set TOOL [string toupper $tool] + set exe [get-env $TOOL [get-define cross]$tool] + if {[find-executable {*}$exe]} { + define $TOOL $exe + continue + } + if {[find-executable {*}$tool]} { + msg-result "Warning: Failed to find $exe, falling back to $tool which may be incorrect" + define $TOOL $tool + continue + } + user-error "Failed to find $exe" + } +} + +# @cc-check-progs prog ... +# +# Checks for existence of the given executables on the path. +# +# For example, when checking for "grep", the path is searched for +# the executable, 'grep', and if found GREP is defined as "grep". +# +# It the executable is not found, the variable is defined as false. +# Returns 1 if all programs were found, or 0 otherwise. +# +proc cc-check-progs {args} { + set failed 0 + foreach prog $args { + set PROG [string toupper $prog] + msg-checking "Checking for $prog..." + if {![find-executable $prog]} { + msg-result no + define $PROG false + incr failed + } else { + msg-result ok + define $PROG $prog + } + } + expr {!$failed} +} + +# Adds the given settings to $::autosetup(ccsettings) and +# returns the old settings. +# +proc cc-add-settings {settings} { + if {[llength $settings] % 2} { + autosetup-error "settings list is missing a value: $settings" + } + + set prev [cc-get-settings] + # workaround a bug in some versions of jimsh by forcing + # conversion of $prev to a list + llength $prev + + array set new $prev + + foreach {name value} $settings { + switch -exact -- $name { + -cflags - -includes { + # These are given as lists + lappend new($name) {*}$value + } + -declare { + lappend new($name) $value + } + -libs { + # Note that new libraries are added before previous libraries + set new($name) [list {*}$value {*}$new($name)] + } + -link - -lang - -nooutput { + set new($name) $value + } + -source - -sourcefile - -code { + # XXX: These probably are only valid directly from cctest + set new($name) $value + } + default { + autosetup-error "unknown cctest setting: $name" + } + } + } + + cc-store-settings [array get new] + + return $prev +} + +proc cc-store-settings {new} { + set ::autosetup(ccsettings) $new +} + +proc cc-get-settings {} { + return $::autosetup(ccsettings) +} + +# Similar to cc-add-settings, but each given setting +# simply replaces the existing value. +# +# Returns the previous settings +proc cc-update-settings {args} { + set prev [cc-get-settings] + cc-store-settings [dict merge $prev $args] + return $prev +} + +# @cc-with settings ?{ script }? +# +# Sets the given 'cctest' settings and then runs the tests in 'script'. +# Note that settings such as -lang replace the current setting, while +# those such as -includes are appended to the existing setting. +# +# If no script is given, the settings become the default for the remainder +# of the auto.def file. +# +## cc-with {-lang c++} { +## # This will check with the C++ compiler +## cc-check-types bool +## cc-with {-includes signal.h} { +## # This will check with the C++ compiler, signal.h and any existing includes. +## ... +## } +## # back to just the C++ compiler +## } +# +# The -libs setting is special in that newer values are added *before* earlier ones. +# +## cc-with {-libs {-lc -lm}} { +## cc-with {-libs -ldl} { +## cctest -libs -lsocket ... +## # libs will be in this order: -lsocket -ldl -lc -lm +## } +## } +proc cc-with {settings args} { + if {[llength $args] == 0} { + cc-add-settings $settings + } elseif {[llength $args] > 1} { + autosetup-error "usage: cc-with settings ?script?" + } else { + set save [cc-add-settings $settings] + set rc [catch {uplevel 1 [lindex $args 0]} result info] + cc-store-settings $save + if {$rc != 0} { + return -code [dict get $info -code] $result + } + return $result + } +} + +# @cctest ?settings? +# +# Low level C compiler checker. Compiles and or links a small C program +# according to the arguments and returns 1 if OK, or 0 if not. +# +# Supported settings are: +# +## -cflags cflags A list of flags to pass to the compiler +## -includes list A list of includes, e.g. {stdlib.h stdio.h} +## -declare code Code to declare before main() +## -link 1 Don't just compile, link too +## -lang c|c++ Use the C (default) or C++ compiler +## -libs liblist List of libraries to link, e.g. {-ldl -lm} +## -code code Code to compile in the body of main() +## -source code Compile a complete program. Ignore -includes, -declare and -code +## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] +## -nooutput 1 Treat any compiler output (e.g. a warning) as an error +# +# Unless -source or -sourcefile is specified, the C program looks like: +# +## #include /* same for remaining includes in the list */ +## +## declare-code /* any code in -declare, verbatim */ +## +## int main(void) { +## code /* any code in -code, verbatim */ +## return 0; +## } +# +# Any failures are recorded in 'config.log' +# +proc cctest {args} { + set src conftest__.c + set tmp conftest__ + + # Easiest way to merge in the settings + cc-with $args { + array set opts [cc-get-settings] + } + + if {[info exists opts(-sourcefile)]} { + set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"] + } + if {[info exists opts(-source)]} { + set lines $opts(-source) + } else { + foreach i $opts(-includes) { + if {$opts(-code) ne "" && ![feature-checked $i]} { + # Compiling real code with an unchecked header file + # Quickly (and silently) check for it now + + # Remove all -includes from settings before checking + set saveopts [cc-update-settings -includes {}] + msg-quiet cc-check-includes $i + cc-store-settings $saveopts + } + if {$opts(-code) eq "" || [have-feature $i]} { + lappend source "#include <$i>" + } + } + lappend source {*}$opts(-declare) + lappend source "int main(void) {" + lappend source $opts(-code) + lappend source "return 0;" + lappend source "}" + + set lines [join $source \n] + } + + # Build the command line + set cmdline {} + lappend cmdline {*}[get-define CCACHE] + switch -exact -- $opts(-lang) { + c++ { + lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS] + } + c { + lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] + } + default { + autosetup-error "cctest called with unknown language: $opts(-lang)" + } + } + + if {!$opts(-link)} { + set tmp conftest__.o + lappend cmdline -c + } + lappend cmdline {*}$opts(-cflags) {*}[get-define cc-default-debug ""] + + lappend cmdline $src -o $tmp {*}$opts(-libs) + + # At this point we have the complete command line and the + # complete source to be compiled. Get the result from cache if + # we can + if {[info exists ::cc_cache($cmdline,$lines)]} { + msg-checking "(cached) " + set ok $::cc_cache($cmdline,$lines) + if {$::autosetup(debug)} { + configlog "From cache (ok=$ok): [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + return $ok + } + + writefile $src $lines\n + + set ok 1 + set err [catch {exec-with-stderr {*}$cmdline} result errinfo] + if {$err || ($opts(-nooutput) && [string length $result])} { + configlog "Failed: [join $cmdline]" + configlog $result + configlog "============" + configlog "The failed code was:" + configlog $lines + configlog "============" + set ok 0 + } elseif {$::autosetup(debug)} { + configlog "Compiled OK: [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + file delete $src + file delete $tmp + + # cache it + set ::cc_cache($cmdline,$lines) $ok + + return $ok +} + +# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*? +# +# Deprecated - see make-config-header +proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} { + user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead" + make-config-header $file -auto $autopatterns -bare $barepatterns +} + +# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ... +# +# Examines all defined variables which match the given patterns +# and writes an include file, $file, which defines each of these. +# Variables which match '-auto' are output as follows: +# - defines which have the value "0" are ignored. +# - defines which have integer values are defined as the integer value. +# - any other value is defined as a string, e.g. "value" +# Variables which match '-bare' are defined as-is. +# Variables which match '-str' are defined as a string, e.g. "value" +# Variables which match '-none' are omitted. +# +# Note that order is important. The first pattern which matches is selected +# Default behaviour is: +# +# -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none * +# +# If the file would be unchanged, it is not written. +proc make-config-header {file args} { + set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]] + file mkdir [file dirname $file] + set lines {} + lappend lines "#ifndef $guard" + lappend lines "#define $guard" + + # Add some defaults + lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* + + foreach n [lsort [dict keys [all-defines]]] { + set value [get-define $n] + set type [calc-define-output-type $n $args] + switch -exact -- $type { + -bare { + # Just output the value unchanged + } + -none { + continue + } + -str { + set value \"[string map [list \\ \\\\ \" \\\"] $value]\" + } + -auto { + # Automatically determine the type + if {$value eq "0"} { + lappend lines "/* #undef $n */" + continue + } + if {![string is integer -strict $value]} { + set value \"[string map [list \\ \\\\ \" \\\"] $value]\" + } + } + "" { + continue + } + default { + autosetup-error "Unknown type in make-config-header: $type" + } + } + lappend lines "#define $n $value" + } + lappend lines "#endif" + set buf [join $lines \n] + write-if-changed $file $buf { + msg-result "Created $file" + } +} + +proc calc-define-output-type {name spec} { + foreach {type patterns} $spec { + foreach pattern $patterns { + if {[string match $pattern $name]} { + return $type + } + } + } + return "" +} + +# Initialise some values from the environment or commandline or default settings +foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"}} { + lassign $i var default + define $var [get-env $var $default] +} + +if {[env-is-set CC]} { + # Set by the user, so don't try anything else + set try [list [get-env CC ""]] +} else { + # Try some reasonable options + set try [list [get-define cross]cc [get-define cross]gcc] +} +define CC [find-an-executable {*}$try] +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CPP [get-env CPP "[get-define CC] -E"] + +# XXX: Could avoid looking for a C++ compiler until requested +# Note that if CXX isn't found, we just set it to "false". It might not be needed. +if {[env-is-set CXX]} { + define CXX [find-an-executable -required [get-env CXX ""]] +} else { + define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++ false] +} + +# CXXFLAGS default to CFLAGS if not specified +define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]] + +# May need a CC_FOR_BUILD, so look for one +define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false] + +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CCACHE [find-an-executable [get-env CCACHE ccache]] + +# Initial cctest settings +cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0} +set autosetup(cc-include-deps) {} + +msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]" +if {[get-define CXX] ne "false"} { + msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]" +} +msg-result "Build C compiler...[get-define CC_FOR_BUILD]" + +# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories +# but some compilers may not support it, so test here. +switch -glob -- [get-define host] { + *-*-darwin* { + if {[cctest -cflags {-g0}]} { + define cc-default-debug -g0 + } + } +} + +if {![cc-check-includes stdlib.h]} { + user-error "Compiler does not work. See config.log" +} ADDED autosetup/config.guess Index: autosetup/config.guess ================================================================== --- /dev/null +++ autosetup/config.guess @@ -0,0 +1,1511 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-09-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' HUP INT TERM + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" HUP INT PIPE TERM ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-tilera-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +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` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: ADDED autosetup/config.sub Index: autosetup/config.sub ================================================================== --- /dev/null +++ autosetup/config.sub @@ -0,0 +1,1743 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 +# Free Software Foundation, Inc. + +timestamp='2010-09-11' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu | strongarm \ + | tahoe | thumb | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile-* | tilegx-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + # This must be matched before tile*. + tilegx*) + basic_machine=tilegx-unknown + os=-linux-gnu + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: ADDED autosetup/default.auto Index: autosetup/default.auto ================================================================== --- /dev/null +++ autosetup/default.auto @@ -0,0 +1,25 @@ +# Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Auto-load module for 'make' build system integration + +use init + +autosetup_add_init_type make {Simple "make" build system} { + autosetup_check_create auto.def \ +{# Initial auto.def created by 'autosetup --init=make' + +use cc + +# Add any user options here +options { +} + +make-config-header config.h +make-template Makefile.in +} + + if {![file exists Makefile.in]} { + puts "Note: I don't see Makefile.in. You will probably need to create one." + } +} ADDED autosetup/find-tclsh Index: autosetup/find-tclsh ================================================================== --- /dev/null +++ autosetup/find-tclsh @@ -0,0 +1,16 @@ +#!/bin/sh +# Looks for a suitable tclsh or jimsh in the PATH +# If not found, builds a bootstrap jimsh from source +d=`dirname "$0"` +{ "$d/jimsh0" "$d/test-tclsh"; } 2>/dev/null && exit 0 +PATH="$PATH:$d/../../../bin:$d"; export PATH +for tclsh in tclsh8.6 tclsh86.exe tclsh8.5 tclsh85.exe tclsh tclsh.exe jimsh ; do + { $tclsh "$d/test-tclsh"; } 2>/dev/null && exit 0 +done +echo 1>&2 "No installed jimsh or tclsh, building local bootstrap jimsh0" +for cc in ${CC_FOR_BUILD:-cc} gcc; do + { $cc -o "$d/jimsh0" "$d/jimsh0.c"; } 2>/dev/null || continue + "$d/jimsh0" "$d/test-tclsh" && exit 0 +done +echo 1>&2 "No working C compiler found. Tried ${CC_FOR_BUILD:-cc} and gcc." +echo false ADDED autosetup/jimsh0.c Index: autosetup/jimsh0.c ================================================================== --- /dev/null +++ autosetup/jimsh0.c @@ -0,0 +1,21993 @@ +/* This is single source file, bootstrap version of Jim Tcl. See http://jim.tcl.tk/ */ +#define _GNU_SOURCE +#define JIM_TCL_COMPAT +#define JIM_REFERENCES +#define JIM_ANSIC +#define JIM_REGEXP +#define HAVE_NO_AUTOCONF +#define _JIMAUTOCONF_H +#define TCL_LIBRARY "." +#define jim_ext_bootstrap +#define jim_ext_aio +#define jim_ext_readdir +#define jim_ext_glob +#define jim_ext_regexp +#define jim_ext_file +#define jim_ext_exec +#define jim_ext_clock +#define jim_ext_array +#define jim_ext_stdlib +#define jim_ext_tclcompat +#if defined(_MSC_VER) +#define TCL_PLATFORM_OS "windows" +#define TCL_PLATFORM_PLATFORM "windows" +#define TCL_PLATFORM_PATH_SEPARATOR ";" +#define HAVE_MKDIR_ONE_ARG +#define HAVE_SYSTEM +#elif defined(__MINGW32__) +#define TCL_PLATFORM_OS "mingw" +#define TCL_PLATFORM_PLATFORM "windows" +#define TCL_PLATFORM_PATH_SEPARATOR ";" +#define HAVE_MKDIR_ONE_ARG +#define HAVE_SYSTEM +#define HAVE_SYS_TIME_H +#define HAVE_DIRENT_H +#define HAVE_UNISTD_H +#else +#define TCL_PLATFORM_OS "unknown" +#define TCL_PLATFORM_PLATFORM "unix" +#define TCL_PLATFORM_PATH_SEPARATOR ":" +#define HAVE_VFORK +#define HAVE_WAITPID +#define HAVE_ISATTY +#define HAVE_MKSTEMP +#define HAVE_LINK +#define HAVE_SYS_TIME_H +#define HAVE_DIRENT_H +#define HAVE_UNISTD_H +#endif +#define JIM_VERSION 76 +#ifndef JIM_WIN32COMPAT_H +#define JIM_WIN32COMPAT_H + + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if defined(_WIN32) || defined(WIN32) + +#define HAVE_DLOPEN +void *dlopen(const char *path, int mode); +int dlclose(void *handle); +void *dlsym(void *handle, const char *symbol); +char *dlerror(void); + + +#define JIM_SPRINTF_DOUBLE_NEEDS_FIX + +#ifdef _MSC_VER + + +#if _MSC_VER >= 1000 + #pragma warning(disable:4146) +#endif + +#include +#define jim_wide _int64 +#ifndef LLONG_MAX + #define LLONG_MAX 9223372036854775807I64 +#endif +#ifndef LLONG_MIN + #define LLONG_MIN (-LLONG_MAX - 1I64) +#endif +#define JIM_WIDE_MIN LLONG_MIN +#define JIM_WIDE_MAX LLONG_MAX +#define JIM_WIDE_MODIFIER "I64d" +#define strcasecmp _stricmp +#define strtoull _strtoui64 +#define snprintf _snprintf + +#include + +struct timeval { + long tv_sec; + long tv_usec; +}; + +int gettimeofday(struct timeval *tv, void *unused); + +#define HAVE_OPENDIR +struct dirent { + char *d_name; +}; + +typedef struct DIR { + long handle; + struct _finddata_t info; + struct dirent result; + char *name; +} DIR; + +DIR *opendir(const char *name); +int closedir(DIR *dir); +struct dirent *readdir(DIR *dir); + +#elif defined(__MINGW32__) + +#include +#define strtod __strtod + +#endif + +#endif + +#ifdef __cplusplus +} +#endif + +#endif +#ifndef UTF8_UTIL_H +#define UTF8_UTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define MAX_UTF8_LEN 4 + +int utf8_fromunicode(char *p, unsigned uc); + +#ifndef JIM_UTF8 +#include + + +#define utf8_strlen(S, B) ((B) < 0 ? strlen(S) : (B)) +#define utf8_tounicode(S, CP) (*(CP) = (unsigned char)*(S), 1) +#define utf8_getchars(CP, C) (*(CP) = (C), 1) +#define utf8_upper(C) toupper(C) +#define utf8_title(C) toupper(C) +#define utf8_lower(C) tolower(C) +#define utf8_index(C, I) (I) +#define utf8_charlen(C) 1 +#define utf8_prev_len(S, L) 1 + +#else + +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef __JIM__H +#define __JIM__H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include + + +#ifndef HAVE_NO_AUTOCONF +#endif + + + +#ifndef jim_wide +# ifdef HAVE_LONG_LONG +# define jim_wide long long +# ifndef LLONG_MAX +# define LLONG_MAX 9223372036854775807LL +# endif +# ifndef LLONG_MIN +# define LLONG_MIN (-LLONG_MAX - 1LL) +# endif +# define JIM_WIDE_MIN LLONG_MIN +# define JIM_WIDE_MAX LLONG_MAX +# else +# define jim_wide long +# define JIM_WIDE_MIN LONG_MIN +# define JIM_WIDE_MAX LONG_MAX +# endif + + +# ifdef HAVE_LONG_LONG +# define JIM_WIDE_MODIFIER "lld" +# else +# define JIM_WIDE_MODIFIER "ld" +# define strtoull strtoul +# endif +#endif + +#define UCHAR(c) ((unsigned char)(c)) + + +#define JIM_OK 0 +#define JIM_ERR 1 +#define JIM_RETURN 2 +#define JIM_BREAK 3 +#define JIM_CONTINUE 4 +#define JIM_SIGNAL 5 +#define JIM_EXIT 6 + +#define JIM_EVAL 7 + +#define JIM_MAX_CALLFRAME_DEPTH 1000 +#define JIM_MAX_EVAL_DEPTH 2000 + + +#define JIM_PRIV_FLAG_SHIFT 20 + +#define JIM_NONE 0 +#define JIM_ERRMSG 1 +#define JIM_ENUM_ABBREV 2 +#define JIM_UNSHARED 4 +#define JIM_MUSTEXIST 8 + + +#define JIM_SUBST_NOVAR 1 +#define JIM_SUBST_NOCMD 2 +#define JIM_SUBST_NOESC 4 +#define JIM_SUBST_FLAG 128 + + +#define JIM_CASESENS 0 +#define JIM_NOCASE 1 + + +#define JIM_PATH_LEN 1024 + + +#define JIM_NOTUSED(V) ((void) V) + +#define JIM_LIBPATH "auto_path" +#define JIM_INTERACTIVE "tcl_interactive" + + +typedef struct Jim_Stack { + int len; + int maxlen; + void **vector; +} Jim_Stack; + + +typedef struct Jim_HashEntry { + void *key; + union { + void *val; + int intval; + } u; + struct Jim_HashEntry *next; +} Jim_HashEntry; + +typedef struct Jim_HashTableType { + unsigned int (*hashFunction)(const void *key); + void *(*keyDup)(void *privdata, const void *key); + void *(*valDup)(void *privdata, const void *obj); + int (*keyCompare)(void *privdata, const void *key1, const void *key2); + void (*keyDestructor)(void *privdata, void *key); + void (*valDestructor)(void *privdata, void *obj); +} Jim_HashTableType; + +typedef struct Jim_HashTable { + Jim_HashEntry **table; + const Jim_HashTableType *type; + void *privdata; + unsigned int size; + unsigned int sizemask; + unsigned int used; + unsigned int collisions; + unsigned int uniq; +} Jim_HashTable; + +typedef struct Jim_HashTableIterator { + Jim_HashTable *ht; + Jim_HashEntry *entry, *nextEntry; + int index; +} Jim_HashTableIterator; + + +#define JIM_HT_INITIAL_SIZE 16 + + +#define Jim_FreeEntryVal(ht, entry) \ + if ((ht)->type->valDestructor) \ + (ht)->type->valDestructor((ht)->privdata, (entry)->u.val) + +#define Jim_SetHashVal(ht, entry, _val_) do { \ + if ((ht)->type->valDup) \ + (entry)->u.val = (ht)->type->valDup((ht)->privdata, (_val_)); \ + else \ + (entry)->u.val = (_val_); \ +} while(0) + +#define Jim_FreeEntryKey(ht, entry) \ + if ((ht)->type->keyDestructor) \ + (ht)->type->keyDestructor((ht)->privdata, (entry)->key) + +#define Jim_SetHashKey(ht, entry, _key_) do { \ + if ((ht)->type->keyDup) \ + (entry)->key = (ht)->type->keyDup((ht)->privdata, (_key_)); \ + else \ + (entry)->key = (void *)(_key_); \ +} while(0) + +#define Jim_CompareHashKeys(ht, key1, key2) \ + (((ht)->type->keyCompare) ? \ + (ht)->type->keyCompare((ht)->privdata, (key1), (key2)) : \ + (key1) == (key2)) + +#define Jim_HashKey(ht, key) ((ht)->type->hashFunction(key) + (ht)->uniq) + +#define Jim_GetHashEntryKey(he) ((he)->key) +#define Jim_GetHashEntryVal(he) ((he)->u.val) +#define Jim_GetHashTableCollisions(ht) ((ht)->collisions) +#define Jim_GetHashTableSize(ht) ((ht)->size) +#define Jim_GetHashTableUsed(ht) ((ht)->used) + + +typedef struct Jim_Obj { + char *bytes; + const struct Jim_ObjType *typePtr; + int refCount; + int length; + + union { + + jim_wide wideValue; + + int intValue; + + double doubleValue; + + void *ptr; + + struct { + void *ptr1; + void *ptr2; + } twoPtrValue; + + struct { + struct Jim_Var *varPtr; + unsigned long callFrameId; + int global; + } varValue; + + struct { + struct Jim_Obj *nsObj; + struct Jim_Cmd *cmdPtr; + unsigned long procEpoch; + } cmdValue; + + struct { + struct Jim_Obj **ele; + int len; + int maxLen; + } listValue; + + struct { + int maxLength; + int charLength; + } strValue; + + struct { + unsigned long id; + struct Jim_Reference *refPtr; + } refValue; + + struct { + struct Jim_Obj *fileNameObj; + int lineNumber; + } sourceValue; + + struct { + struct Jim_Obj *varNameObjPtr; + struct Jim_Obj *indexObjPtr; + } dictSubstValue; + + struct { + void *compre; + unsigned flags; + } regexpValue; + struct { + int line; + int argc; + } scriptLineValue; + } internalRep; + struct Jim_Obj *prevObjPtr; + struct Jim_Obj *nextObjPtr; +} Jim_Obj; + + +#define Jim_IncrRefCount(objPtr) \ + ++(objPtr)->refCount +#define Jim_DecrRefCount(interp, objPtr) \ + if (--(objPtr)->refCount <= 0) Jim_FreeObj(interp, objPtr) +#define Jim_IsShared(objPtr) \ + ((objPtr)->refCount > 1) + +#define Jim_FreeNewObj Jim_FreeObj + + +#define Jim_FreeIntRep(i,o) \ + if ((o)->typePtr && (o)->typePtr->freeIntRepProc) \ + (o)->typePtr->freeIntRepProc(i, o) + + +#define Jim_GetIntRepPtr(o) (o)->internalRep.ptr + + +#define Jim_SetIntRepPtr(o, p) \ + (o)->internalRep.ptr = (p) + + +struct Jim_Interp; + +typedef void (Jim_FreeInternalRepProc)(struct Jim_Interp *interp, + struct Jim_Obj *objPtr); +typedef void (Jim_DupInternalRepProc)(struct Jim_Interp *interp, + struct Jim_Obj *srcPtr, Jim_Obj *dupPtr); +typedef void (Jim_UpdateStringProc)(struct Jim_Obj *objPtr); + +typedef struct Jim_ObjType { + const char *name; + Jim_FreeInternalRepProc *freeIntRepProc; + Jim_DupInternalRepProc *dupIntRepProc; + Jim_UpdateStringProc *updateStringProc; + int flags; +} Jim_ObjType; + + +#define JIM_TYPE_NONE 0 +#define JIM_TYPE_REFERENCES 1 + +#define JIM_PRIV_FLAG_SHIFT 20 + + + +typedef struct Jim_CallFrame { + unsigned long id; + int level; + struct Jim_HashTable vars; + struct Jim_HashTable *staticVars; + struct Jim_CallFrame *parent; + Jim_Obj *const *argv; + int argc; + Jim_Obj *procArgsObjPtr; + Jim_Obj *procBodyObjPtr; + struct Jim_CallFrame *next; + Jim_Obj *nsObj; + Jim_Obj *fileNameObj; + int line; + Jim_Stack *localCommands; + int tailcall; + struct Jim_Obj *tailcallObj; + struct Jim_Cmd *tailcallCmd; +} Jim_CallFrame; + +typedef struct Jim_Var { + Jim_Obj *objPtr; + struct Jim_CallFrame *linkFramePtr; +} Jim_Var; + + +typedef int Jim_CmdProc(struct Jim_Interp *interp, int argc, + Jim_Obj *const *argv); +typedef void Jim_DelCmdProc(struct Jim_Interp *interp, void *privData); + + + +typedef struct Jim_Cmd { + int inUse; + int isproc; + struct Jim_Cmd *prevCmd; + union { + struct { + + Jim_CmdProc *cmdProc; + Jim_DelCmdProc *delProc; + void *privData; + } native; + struct { + + Jim_Obj *argListObjPtr; + Jim_Obj *bodyObjPtr; + Jim_HashTable *staticVars; + int argListLen; + int reqArity; + int optArity; + int argsPos; + int upcall; + struct Jim_ProcArg { + Jim_Obj *nameObjPtr; + Jim_Obj *defaultObjPtr; + } *arglist; + Jim_Obj *nsObj; + } proc; + } u; +} Jim_Cmd; + + +typedef struct Jim_PrngState { + unsigned char sbox[256]; + unsigned int i, j; +} Jim_PrngState; + +typedef struct Jim_Interp { + Jim_Obj *result; + int errorLine; + Jim_Obj *errorFileNameObj; + int addStackTrace; + int maxCallFrameDepth; + int maxEvalDepth; + int evalDepth; + int returnCode; + int returnLevel; + int exitCode; + long id; + int signal_level; + jim_wide sigmask; + int (*signal_set_result)(struct Jim_Interp *interp, jim_wide sigmask); + Jim_CallFrame *framePtr; + Jim_CallFrame *topFramePtr; + struct Jim_HashTable commands; + unsigned long procEpoch; /* Incremented every time the result + of procedures names lookup caching + may no longer be valid. */ + unsigned long callFrameEpoch; /* Incremented every time a new + callframe is created. This id is used for the + 'ID' field contained in the Jim_CallFrame + structure. */ + int local; + Jim_Obj *liveList; + Jim_Obj *freeList; + Jim_Obj *currentScriptObj; + Jim_Obj *nullScriptObj; + Jim_Obj *emptyObj; + Jim_Obj *trueObj; + Jim_Obj *falseObj; + unsigned long referenceNextId; + struct Jim_HashTable references; + unsigned long lastCollectId; /* reference max Id of the last GC + execution. It's set to -1 while the collection + is running as sentinel to avoid to recursive + calls via the [collect] command inside + finalizers. */ + time_t lastCollectTime; + Jim_Obj *stackTrace; + Jim_Obj *errorProc; + Jim_Obj *unknown; + int unknown_called; + int errorFlag; + void *cmdPrivData; /* Used to pass the private data pointer to + a command. It is set to what the user specified + via Jim_CreateCommand(). */ + + struct Jim_CallFrame *freeFramesList; + struct Jim_HashTable assocData; + Jim_PrngState *prngState; + struct Jim_HashTable packages; + Jim_Stack *loadHandles; +} Jim_Interp; + +#define Jim_InterpIncrProcEpoch(i) (i)->procEpoch++ +#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l)) +#define Jim_SetResultInt(i,intval) Jim_SetResult(i, Jim_NewIntObj(i,intval)) + +#define Jim_SetResultBool(i,b) Jim_SetResultInt(i, b) +#define Jim_SetEmptyResult(i) Jim_SetResult(i, (i)->emptyObj) +#define Jim_GetResult(i) ((i)->result) +#define Jim_CmdPrivData(i) ((i)->cmdPrivData) + +#define Jim_SetResult(i,o) do { \ + Jim_Obj *_resultObjPtr_ = (o); \ + Jim_IncrRefCount(_resultObjPtr_); \ + Jim_DecrRefCount(i,(i)->result); \ + (i)->result = _resultObjPtr_; \ +} while(0) + + +#define Jim_GetId(i) (++(i)->id) + + +#define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference + string representation must be fixed length. */ +typedef struct Jim_Reference { + Jim_Obj *objPtr; + Jim_Obj *finalizerCmdNamePtr; + char tag[JIM_REFERENCE_TAGLEN+1]; +} Jim_Reference; + + +#define Jim_NewEmptyStringObj(i) Jim_NewStringObj(i, "", 0) +#define Jim_FreeHashTableIterator(iter) Jim_Free(iter) + +#define JIM_EXPORT + + +JIM_EXPORT void *Jim_Alloc (int size); +JIM_EXPORT void *Jim_Realloc(void *ptr, int size); +JIM_EXPORT void Jim_Free (void *ptr); +JIM_EXPORT char * Jim_StrDup (const char *s); +JIM_EXPORT char *Jim_StrDupLen(const char *s, int l); + + +JIM_EXPORT char **Jim_GetEnviron(void); +JIM_EXPORT void Jim_SetEnviron(char **env); +JIM_EXPORT int Jim_MakeTempFile(Jim_Interp *interp, const char *template); + + +JIM_EXPORT int Jim_Eval(Jim_Interp *interp, const char *script); + + +JIM_EXPORT int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script); + +#define Jim_Eval_Named(I, S, F, L) Jim_EvalSource((I), (F), (L), (S)) + +JIM_EXPORT int Jim_EvalGlobal(Jim_Interp *interp, const char *script); +JIM_EXPORT int Jim_EvalFile(Jim_Interp *interp, const char *filename); +JIM_EXPORT int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename); +JIM_EXPORT int Jim_EvalObj (Jim_Interp *interp, Jim_Obj *scriptObjPtr); +JIM_EXPORT int Jim_EvalObjVector (Jim_Interp *interp, int objc, + Jim_Obj *const *objv); +JIM_EXPORT int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listObj); +JIM_EXPORT int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, + int objc, Jim_Obj *const *objv); +#define Jim_EvalPrefix(i, p, oc, ov) Jim_EvalObjPrefix((i), Jim_NewStringObj((i), (p), -1), (oc), (ov)) +JIM_EXPORT int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj); +JIM_EXPORT int Jim_SubstObj (Jim_Interp *interp, Jim_Obj *substObjPtr, + Jim_Obj **resObjPtrPtr, int flags); + + +JIM_EXPORT void Jim_InitStack(Jim_Stack *stack); +JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack); +JIM_EXPORT int Jim_StackLen(Jim_Stack *stack); +JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element); +JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack); +JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack); +JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr)); + + +JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht, + const Jim_HashTableType *type, void *privdata); +JIM_EXPORT void Jim_ExpandHashTable (Jim_HashTable *ht, + unsigned int size); +JIM_EXPORT int Jim_AddHashEntry (Jim_HashTable *ht, const void *key, + void *val); +JIM_EXPORT int Jim_ReplaceHashEntry (Jim_HashTable *ht, + const void *key, void *val); +JIM_EXPORT int Jim_DeleteHashEntry (Jim_HashTable *ht, + const void *key); +JIM_EXPORT int Jim_FreeHashTable (Jim_HashTable *ht); +JIM_EXPORT Jim_HashEntry * Jim_FindHashEntry (Jim_HashTable *ht, + const void *key); +JIM_EXPORT void Jim_ResizeHashTable (Jim_HashTable *ht); +JIM_EXPORT Jim_HashTableIterator *Jim_GetHashTableIterator + (Jim_HashTable *ht); +JIM_EXPORT Jim_HashEntry * Jim_NextHashEntry + (Jim_HashTableIterator *iter); + + +JIM_EXPORT Jim_Obj * Jim_NewObj (Jim_Interp *interp); +JIM_EXPORT void Jim_FreeObj (Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT void Jim_InvalidateStringRep (Jim_Obj *objPtr); +JIM_EXPORT Jim_Obj * Jim_DuplicateObj (Jim_Interp *interp, + Jim_Obj *objPtr); +JIM_EXPORT const char * Jim_GetString(Jim_Obj *objPtr, + int *lenPtr); +JIM_EXPORT const char *Jim_String(Jim_Obj *objPtr); +JIM_EXPORT int Jim_Length(Jim_Obj *objPtr); + + +JIM_EXPORT Jim_Obj * Jim_NewStringObj (Jim_Interp *interp, + const char *s, int len); +JIM_EXPORT Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, + const char *s, int charlen); +JIM_EXPORT Jim_Obj * Jim_NewStringObjNoAlloc (Jim_Interp *interp, + char *s, int len); +JIM_EXPORT void Jim_AppendString (Jim_Interp *interp, Jim_Obj *objPtr, + const char *str, int len); +JIM_EXPORT void Jim_AppendObj (Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *appendObjPtr); +JIM_EXPORT void Jim_AppendStrings (Jim_Interp *interp, + Jim_Obj *objPtr, ...); +JIM_EXPORT int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr); +JIM_EXPORT int Jim_StringMatchObj (Jim_Interp *interp, Jim_Obj *patternObjPtr, + Jim_Obj *objPtr, int nocase); +JIM_EXPORT Jim_Obj * Jim_StringRangeObj (Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, + Jim_Obj *lastObjPtr); +JIM_EXPORT Jim_Obj * Jim_FormatString (Jim_Interp *interp, + Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv); +JIM_EXPORT Jim_Obj * Jim_ScanString (Jim_Interp *interp, Jim_Obj *strObjPtr, + Jim_Obj *fmtObjPtr, int flags); +JIM_EXPORT int Jim_CompareStringImmediate (Jim_Interp *interp, + Jim_Obj *objPtr, const char *str); +JIM_EXPORT int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, + Jim_Obj *secondObjPtr, int nocase); +JIM_EXPORT int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, + Jim_Obj *secondObjPtr, int nocase); +JIM_EXPORT int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr); + + +JIM_EXPORT Jim_Obj * Jim_NewReference (Jim_Interp *interp, + Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr); +JIM_EXPORT Jim_Reference * Jim_GetReference (Jim_Interp *interp, + Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr); +JIM_EXPORT int Jim_GetFinalizer (Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr); + + +JIM_EXPORT Jim_Interp * Jim_CreateInterp (void); +JIM_EXPORT void Jim_FreeInterp (Jim_Interp *i); +JIM_EXPORT int Jim_GetExitCode (Jim_Interp *interp); +JIM_EXPORT const char *Jim_ReturnCode(int code); +JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...); + + +JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp); +JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp, + const char *cmdName, Jim_CmdProc cmdProc, void *privData, + Jim_DelCmdProc delProc); +JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp, + const char *cmdName); +JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp, + const char *oldName, const char *newName); +JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp, + Jim_Obj *objPtr, int flags); +JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr); +JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp, + const char *name, Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetGlobalVariableStr (Jim_Interp *interp, + const char *name, Jim_Obj *objPtr); +JIM_EXPORT int Jim_SetVariableStrWithStr (Jim_Interp *interp, + const char *name, const char *val); +JIM_EXPORT int Jim_SetVariableLink (Jim_Interp *interp, + Jim_Obj *nameObjPtr, Jim_Obj *targetNameObjPtr, + Jim_CallFrame *targetCallFrame); +JIM_EXPORT Jim_Obj * Jim_MakeGlobalNamespaceName(Jim_Interp *interp, + Jim_Obj *nameObjPtr); +JIM_EXPORT Jim_Obj * Jim_GetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); +JIM_EXPORT Jim_Obj * Jim_GetVariableStr (Jim_Interp *interp, + const char *name, int flags); +JIM_EXPORT Jim_Obj * Jim_GetGlobalVariableStr (Jim_Interp *interp, + const char *name, int flags); +JIM_EXPORT int Jim_UnsetVariable (Jim_Interp *interp, + Jim_Obj *nameObjPtr, int flags); + + +JIM_EXPORT Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, + Jim_Obj *levelObjPtr); + + +JIM_EXPORT int Jim_Collect (Jim_Interp *interp); +JIM_EXPORT void Jim_CollectIfNeeded (Jim_Interp *interp); + + +JIM_EXPORT int Jim_GetIndex (Jim_Interp *interp, Jim_Obj *objPtr, + int *indexPtr); + + +JIM_EXPORT Jim_Obj * Jim_NewListObj (Jim_Interp *interp, + Jim_Obj *const *elements, int len); +JIM_EXPORT void Jim_ListInsertElements (Jim_Interp *interp, + Jim_Obj *listPtr, int listindex, int objc, Jim_Obj *const *objVec); +JIM_EXPORT void Jim_ListAppendElement (Jim_Interp *interp, + Jim_Obj *listPtr, Jim_Obj *objPtr); +JIM_EXPORT void Jim_ListAppendList (Jim_Interp *interp, + Jim_Obj *listPtr, Jim_Obj *appendListPtr); +JIM_EXPORT int Jim_ListLength (Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT int Jim_ListIndex (Jim_Interp *interp, Jim_Obj *listPrt, + int listindex, Jim_Obj **objPtrPtr, int seterr); +JIM_EXPORT Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx); +JIM_EXPORT int Jim_SetListIndex (Jim_Interp *interp, + Jim_Obj *varNamePtr, Jim_Obj *const *indexv, int indexc, + Jim_Obj *newObjPtr); +JIM_EXPORT Jim_Obj * Jim_ConcatObj (Jim_Interp *interp, int objc, + Jim_Obj *const *objv); +JIM_EXPORT Jim_Obj *Jim_ListJoin(Jim_Interp *interp, + Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen); + + +JIM_EXPORT Jim_Obj * Jim_NewDictObj (Jim_Interp *interp, + Jim_Obj *const *elements, int len); +JIM_EXPORT int Jim_DictKey (Jim_Interp *interp, Jim_Obj *dictPtr, + Jim_Obj *keyPtr, Jim_Obj **objPtrPtr, int flags); +JIM_EXPORT int Jim_DictKeysVector (Jim_Interp *interp, + Jim_Obj *dictPtr, Jim_Obj *const *keyv, int keyc, + Jim_Obj **objPtrPtr, int flags); +JIM_EXPORT int Jim_SetDictKeysVector (Jim_Interp *interp, + Jim_Obj *varNamePtr, Jim_Obj *const *keyv, int keyc, + Jim_Obj *newObjPtr, int flags); +JIM_EXPORT int Jim_DictPairs(Jim_Interp *interp, + Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len); +JIM_EXPORT int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr); +JIM_EXPORT int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObj); +JIM_EXPORT int Jim_DictValues(Jim_Interp *interp, Jim_Obj *dictObjPtr, Jim_Obj *patternObjPtr); +JIM_EXPORT int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr); +JIM_EXPORT int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr); + + +JIM_EXPORT int Jim_GetReturnCode (Jim_Interp *interp, Jim_Obj *objPtr, + int *intPtr); + + +JIM_EXPORT int Jim_EvalExpression (Jim_Interp *interp, + Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr); +JIM_EXPORT int Jim_GetBoolFromExpr (Jim_Interp *interp, + Jim_Obj *exprObjPtr, int *boolPtr); + + +JIM_EXPORT int Jim_GetWide (Jim_Interp *interp, Jim_Obj *objPtr, + jim_wide *widePtr); +JIM_EXPORT int Jim_GetLong (Jim_Interp *interp, Jim_Obj *objPtr, + long *longPtr); +#define Jim_NewWideObj Jim_NewIntObj +JIM_EXPORT Jim_Obj * Jim_NewIntObj (Jim_Interp *interp, + jim_wide wideValue); + + +JIM_EXPORT int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, + double *doublePtr); +JIM_EXPORT void Jim_SetDouble(Jim_Interp *interp, Jim_Obj *objPtr, + double doubleValue); +JIM_EXPORT Jim_Obj * Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue); + + +JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc, + Jim_Obj *const *argv, const char *msg); +JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr, + const char * const *tablePtr, int *indexPtr, const char *name, int flags); +JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len, + char *stateCharPtr); +JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len); + + +typedef void (Jim_InterpDeleteProc)(Jim_Interp *interp, void *data); +JIM_EXPORT void * Jim_GetAssocData(Jim_Interp *interp, const char *key); +JIM_EXPORT int Jim_SetAssocData(Jim_Interp *interp, const char *key, + Jim_InterpDeleteProc *delProc, void *data); +JIM_EXPORT int Jim_DeleteAssocData(Jim_Interp *interp, const char *key); + + + +JIM_EXPORT int Jim_PackageProvide (Jim_Interp *interp, + const char *name, const char *ver, int flags); +JIM_EXPORT int Jim_PackageRequire (Jim_Interp *interp, + const char *name, int flags); + + +JIM_EXPORT void Jim_MakeErrorMessage (Jim_Interp *interp); + + +JIM_EXPORT int Jim_InteractivePrompt (Jim_Interp *interp); +JIM_EXPORT void Jim_HistoryLoad(const char *filename); +JIM_EXPORT void Jim_HistorySave(const char *filename); +JIM_EXPORT char *Jim_HistoryGetline(const char *prompt); +JIM_EXPORT void Jim_HistoryAdd(const char *line); +JIM_EXPORT void Jim_HistoryShow(void); + + +JIM_EXPORT int Jim_InitStaticExtensions(Jim_Interp *interp); +JIM_EXPORT int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); +JIM_EXPORT int Jim_IsBigEndian(void); + +#define Jim_CheckSignal(i) ((i)->signal_level && (i)->sigmask) + + +JIM_EXPORT int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); +JIM_EXPORT void Jim_FreeLoadHandles(Jim_Interp *interp); + + +JIM_EXPORT FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); + + +JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr); +JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr); + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef JIM_SUBCMD_H +#define JIM_SUBCMD_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +#define JIM_MODFLAG_HIDDEN 0x0001 +#define JIM_MODFLAG_FULLARGV 0x0002 + + + +typedef int jim_subcmd_function(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + +typedef struct { + const char *cmd; + const char *args; + jim_subcmd_function *function; + short minargs; + short maxargs; + unsigned short flags; +} jim_subcmd_type; + +const jim_subcmd_type * +Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type *command_table, int argc, Jim_Obj *const *argv); + +int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); + +int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_Obj *const *argv); + +#ifdef __cplusplus +} +#endif + +#endif +#ifndef JIMREGEXP_H +#define JIMREGEXP_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct { + int rm_so; + int rm_eo; +} regmatch_t; + + +typedef struct regexp { + + int re_nsub; + + + int cflags; + int err; + int regstart; + int reganch; + int regmust; + int regmlen; + int *program; + + + const char *regparse; + int p; + int proglen; + + + int eflags; + const char *start; + const char *reginput; + const char *regbol; + + + regmatch_t *pmatch; + int nmatch; +} regexp; + +typedef regexp regex_t; + +#define REG_EXTENDED 0 +#define REG_NEWLINE 1 +#define REG_ICASE 2 + +#define REG_NOTBOL 16 + +enum { + REG_NOERROR, + REG_NOMATCH, + REG_BADPAT, + REG_ERR_NULL_ARGUMENT, + REG_ERR_UNKNOWN, + REG_ERR_TOO_BIG, + REG_ERR_NOMEM, + REG_ERR_TOO_MANY_PAREN, + REG_ERR_UNMATCHED_PAREN, + REG_ERR_UNMATCHED_BRACES, + REG_ERR_BAD_COUNT, + REG_ERR_JUNK_ON_END, + REG_ERR_OPERAND_COULD_BE_EMPTY, + REG_ERR_NESTED_COUNT, + REG_ERR_INTERNAL, + REG_ERR_COUNT_FOLLOWS_NOTHING, + REG_ERR_TRAILING_BACKSLASH, + REG_ERR_CORRUPTED, + REG_ERR_NULL_CHAR, + REG_ERR_NUM +}; + +int regcomp(regex_t *preg, const char *regex, int cflags); +int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); +size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size); +void regfree(regex_t *preg); + +#ifdef __cplusplus +} +#endif + +#endif +int Jim_bootstrapInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "bootstrap", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "bootstrap.tcl", 1, +"\n" +"\n" +"proc package {args} {}\n" +); +} +int Jim_initjimshInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "initjimsh", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "initjimsh.tcl", 1, +"\n" +"\n" +"\n" +"proc _jimsh_init {} {\n" +" rename _jimsh_init {}\n" +" global jim::exe jim::argv0 tcl_interactive auto_path tcl_platform\n" +"\n" +"\n" +" if {[exists jim::argv0]} {\n" +" if {[string match \"*/*\" $jim::argv0]} {\n" +" set jim::exe [file join [pwd] $jim::argv0]\n" +" } else {\n" +" foreach path [split [env PATH \"\"] $tcl_platform(pathSeparator)] {\n" +" set exec [file join [pwd] [string map {\\\\ /} $path] $jim::argv0]\n" +" if {[file executable $exec]} {\n" +" set jim::exe $exec\n" +" break\n" +" }\n" +" }\n" +" }\n" +" }\n" +"\n" +"\n" +" lappend p {*}[split [env JIMLIB {}] $tcl_platform(pathSeparator)]\n" +" if {[exists jim::exe]} {\n" +" lappend p [file dirname $jim::exe]\n" +" }\n" +" lappend p {*}$auto_path\n" +" set auto_path $p\n" +"\n" +" if {$tcl_interactive && [env HOME {}] ne \"\"} {\n" +" foreach src {.jimrc jimrc.tcl} {\n" +" if {[file exists [env HOME]/$src]} {\n" +" uplevel #0 source [env HOME]/$src\n" +" break\n" +" }\n" +" }\n" +" }\n" +" return \"\"\n" +"}\n" +"\n" +"if {$tcl_platform(platform) eq \"windows\"} {\n" +" set jim::argv0 [string map {\\\\ /} $jim::argv0]\n" +"}\n" +"\n" +"_jimsh_init\n" +); +} +int Jim_globInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "glob", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "glob.tcl", 1, +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"package require readdir\n" +"\n" +"\n" +"proc glob.globdir {dir pattern} {\n" +" if {[file exists $dir/$pattern]} {\n" +"\n" +" return [list $pattern]\n" +" }\n" +"\n" +" set result {}\n" +" set files [readdir $dir]\n" +" lappend files . ..\n" +"\n" +" foreach name $files {\n" +" if {[string match $pattern $name]} {\n" +"\n" +" if {[string index $name 0] eq \".\" && [string index $pattern 0] ne \".\"} {\n" +" continue\n" +" }\n" +" lappend result $name\n" +" }\n" +" }\n" +"\n" +" return $result\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"proc glob.explode {pattern} {\n" +" set oldexp {}\n" +" set newexp {\"\"}\n" +"\n" +" while 1 {\n" +" set oldexp $newexp\n" +" set newexp {}\n" +" set ob [string first \\{ $pattern]\n" +" set cb [string first \\} $pattern]\n" +"\n" +" if {$ob < $cb && $ob != -1} {\n" +" set mid [string range $pattern 0 $ob-1]\n" +" set subexp [lassign [glob.explode [string range $pattern $ob+1 end]] pattern]\n" +" if {$pattern eq \"\"} {\n" +" error \"unmatched open brace in glob pattern\"\n" +" }\n" +" set pattern [string range $pattern 1 end]\n" +"\n" +" foreach subs $subexp {\n" +" foreach sub [split $subs ,] {\n" +" foreach old $oldexp {\n" +" lappend newexp $old$mid$sub\n" +" }\n" +" }\n" +" }\n" +" } elseif {$cb != -1} {\n" +" set suf [string range $pattern 0 $cb-1]\n" +" set rest [string range $pattern $cb end]\n" +" break\n" +" } else {\n" +" set suf $pattern\n" +" set rest \"\"\n" +" break\n" +" }\n" +" }\n" +"\n" +" foreach old $oldexp {\n" +" lappend newexp $old$suf\n" +" }\n" +" list $rest {*}$newexp\n" +"}\n" +"\n" +"\n" +"\n" +"proc glob.glob {base pattern} {\n" +" set dir [file dirname $pattern]\n" +" if {$pattern eq $dir || $pattern eq \"\"} {\n" +" return [list [file join $base $dir] $pattern]\n" +" } elseif {$pattern eq [file tail $pattern]} {\n" +" set dir \"\"\n" +" }\n" +"\n" +"\n" +" set dirlist [glob.glob $base $dir]\n" +" set pattern [file tail $pattern]\n" +"\n" +"\n" +" set result {}\n" +" foreach {realdir dir} $dirlist {\n" +" if {![file isdir $realdir]} {\n" +" continue\n" +" }\n" +" if {[string index $dir end] ne \"/\" && $dir ne \"\"} {\n" +" append dir /\n" +" }\n" +" foreach name [glob.globdir $realdir $pattern] {\n" +" lappend result [file join $realdir $name] $dir$name\n" +" }\n" +" }\n" +" return $result\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"proc glob {args} {\n" +" set nocomplain 0\n" +" set base \"\"\n" +" set tails 0\n" +"\n" +" set n 0\n" +" foreach arg $args {\n" +" if {[info exists param]} {\n" +" set $param $arg\n" +" unset param\n" +" incr n\n" +" continue\n" +" }\n" +" switch -glob -- $arg {\n" +" -d* {\n" +" set switch $arg\n" +" set param base\n" +" }\n" +" -n* {\n" +" set nocomplain 1\n" +" }\n" +" -ta* {\n" +" set tails 1\n" +" }\n" +" -- {\n" +" incr n\n" +" break\n" +" }\n" +" -* {\n" +" return -code error \"bad option \\\"$arg\\\": must be -directory, -nocomplain, -tails, or --\"\n" +" }\n" +" * {\n" +" break\n" +" }\n" +" }\n" +" incr n\n" +" }\n" +" if {[info exists param]} {\n" +" return -code error \"missing argument to \\\"$switch\\\"\"\n" +" }\n" +" if {[llength $args] <= $n} {\n" +" return -code error \"wrong # args: should be \\\"glob ?options? pattern ?pattern ...?\\\"\"\n" +" }\n" +"\n" +" set args [lrange $args $n end]\n" +"\n" +" set result {}\n" +" foreach pattern $args {\n" +" set escpattern [string map {\n" +" \\\\\\\\ \\x01 \\\\\\{ \\x02 \\\\\\} \\x03 \\\\, \\x04\n" +" } $pattern]\n" +" set patexps [lassign [glob.explode $escpattern] rest]\n" +" if {$rest ne \"\"} {\n" +" return -code error \"unmatched close brace in glob pattern\"\n" +" }\n" +" foreach patexp $patexps {\n" +" set patexp [string map {\n" +" \\x01 \\\\\\\\ \\x02 \\{ \\x03 \\} \\x04 ,\n" +" } $patexp]\n" +" foreach {realname name} [glob.glob $base $patexp] {\n" +" incr n\n" +" if {$tails} {\n" +" lappend result $name\n" +" } else {\n" +" lappend result [file join $base $name]\n" +" }\n" +" }\n" +" }\n" +" }\n" +"\n" +" if {!$nocomplain && [llength $result] == 0} {\n" +" set s $(([llength $args] > 1) ? \"s\" : \"\")\n" +" return -code error \"no files matched glob pattern$s \\\"[join $args]\\\"\"\n" +" }\n" +"\n" +" return $result\n" +"}\n" +); +} +int Jim_stdlibInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "stdlib", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "stdlib.tcl", 1, +"\n" +"\n" +"\n" +"proc lambda {arglist args} {\n" +" tailcall proc [ref {} function lambda.finalizer] $arglist {*}$args\n" +"}\n" +"\n" +"proc lambda.finalizer {name val} {\n" +" rename $name {}\n" +"}\n" +"\n" +"\n" +"proc curry {args} {\n" +" alias [ref {} function lambda.finalizer] {*}$args\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"proc function {value} {\n" +" return $value\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"proc stacktrace {{skip 0}} {\n" +" set trace {}\n" +" incr skip\n" +" foreach level [range $skip [info level]] {\n" +" lappend trace {*}[info frame -$level]\n" +" }\n" +" return $trace\n" +"}\n" +"\n" +"\n" +"proc stackdump {stacktrace} {\n" +" set lines {}\n" +" foreach {l f p} [lreverse $stacktrace] {\n" +" set line {}\n" +" if {$p ne \"\"} {\n" +" append line \"in procedure '$p' \"\n" +" if {$f ne \"\"} {\n" +" append line \"called \"\n" +" }\n" +" }\n" +" if {$f ne \"\"} {\n" +" append line \"at file \\\"$f\\\", line $l\"\n" +" }\n" +" if {$line ne \"\"} {\n" +" lappend lines $line\n" +" }\n" +" }\n" +" join $lines \\n\n" +"}\n" +"\n" +"\n" +"\n" +"proc errorInfo {msg {stacktrace \"\"}} {\n" +" if {$stacktrace eq \"\"} {\n" +"\n" +" set stacktrace [info stacktrace]\n" +"\n" +" lappend stacktrace {*}[stacktrace 1]\n" +" }\n" +" lassign $stacktrace p f l\n" +" if {$f ne \"\"} {\n" +" set result \"$f:$l: Error: \"\n" +" }\n" +" append result \"$msg\\n\"\n" +" append result [stackdump $stacktrace]\n" +"\n" +"\n" +" string trim $result\n" +"}\n" +"\n" +"\n" +"\n" +"proc {info nameofexecutable} {} {\n" +" if {[exists ::jim::exe]} {\n" +" return $::jim::exe\n" +" }\n" +"}\n" +"\n" +"\n" +"proc {dict with} {&dictVar {args key} script} {\n" +" set keys {}\n" +" foreach {n v} [dict get $dictVar {*}$key] {\n" +" upvar $n var_$n\n" +" set var_$n $v\n" +" lappend keys $n\n" +" }\n" +" catch {uplevel 1 $script} msg opts\n" +" if {[info exists dictVar] && ([llength $key] == 0 || [dict exists $dictVar {*}$key])} {\n" +" foreach n $keys {\n" +" if {[info exists var_$n]} {\n" +" dict set dictVar {*}$key $n [set var_$n]\n" +" } else {\n" +" dict unset dictVar {*}$key $n\n" +" }\n" +" }\n" +" }\n" +" return {*}$opts $msg\n" +"}\n" +"\n" +"\n" +"proc {dict update} {&varName args script} {\n" +" set keys {}\n" +" foreach {n v} $args {\n" +" upvar $v var_$v\n" +" if {[dict exists $varName $n]} {\n" +" set var_$v [dict get $varName $n]\n" +" }\n" +" }\n" +" catch {uplevel 1 $script} msg opts\n" +" if {[info exists varName]} {\n" +" foreach {n v} $args {\n" +" if {[info exists var_$v]} {\n" +" dict set varName $n [set var_$v]\n" +" } else {\n" +" dict unset varName $n\n" +" }\n" +" }\n" +" }\n" +" return {*}$opts $msg\n" +"}\n" +"\n" +"\n" +"\n" +"proc {dict merge} {dict args} {\n" +" foreach d $args {\n" +"\n" +" dict size $d\n" +" foreach {k v} $d {\n" +" dict set dict $k $v\n" +" }\n" +" }\n" +" return $dict\n" +"}\n" +"\n" +"proc {dict replace} {dictionary {args {key value}}} {\n" +" if {[llength ${key value}] % 2} {\n" +" tailcall {dict replace}\n" +" }\n" +" tailcall dict merge $dictionary ${key value}\n" +"}\n" +"\n" +"\n" +"proc {dict lappend} {varName key {args value}} {\n" +" upvar $varName dict\n" +" if {[exists dict] && [dict exists $dict $key]} {\n" +" set list [dict get $dict $key]\n" +" }\n" +" lappend list {*}$value\n" +" dict set dict $key $list\n" +"}\n" +"\n" +"\n" +"proc {dict append} {varName key {args value}} {\n" +" upvar $varName dict\n" +" if {[exists dict] && [dict exists $dict $key]} {\n" +" set str [dict get $dict $key]\n" +" }\n" +" append str {*}$value\n" +" dict set dict $key $str\n" +"}\n" +"\n" +"\n" +"proc {dict incr} {varName key {increment 1}} {\n" +" upvar $varName dict\n" +" if {[exists dict] && [dict exists $dict $key]} {\n" +" set value [dict get $dict $key]\n" +" }\n" +" incr value $increment\n" +" dict set dict $key $value\n" +"}\n" +"\n" +"\n" +"proc {dict remove} {dictionary {args key}} {\n" +" foreach k $key {\n" +" dict unset dictionary $k\n" +" }\n" +" return $dictionary\n" +"}\n" +"\n" +"\n" +"proc {dict values} {dictionary {pattern *}} {\n" +" dict keys [lreverse $dictionary] $pattern\n" +"}\n" +"\n" +"\n" +"proc {dict for} {vars dictionary script} {\n" +" if {[llength $vars] != 2} {\n" +" return -code error \"must have exactly two variable names\"\n" +" }\n" +" dict size $dictionary\n" +" tailcall foreach $vars $dictionary $script\n" +"}\n" +); +} +int Jim_tclcompatInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "tclcompat", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + return Jim_EvalSource(interp, "tclcompat.tcl", 1, +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"set env [env]\n" +"\n" +"\n" +"if {[info commands stdout] ne \"\"} {\n" +"\n" +" foreach p {gets flush close eof seek tell} {\n" +" proc $p {chan args} {p} {\n" +" tailcall $chan $p {*}$args\n" +" }\n" +" }\n" +" unset p\n" +"\n" +"\n" +"\n" +" proc puts {{-nonewline {}} {chan stdout} msg} {\n" +" if {${-nonewline} ni {-nonewline {}}} {\n" +" tailcall ${-nonewline} puts $msg\n" +" }\n" +" tailcall $chan puts {*}${-nonewline} $msg\n" +" }\n" +"\n" +"\n" +"\n" +"\n" +"\n" +" proc read {{-nonewline {}} chan} {\n" +" if {${-nonewline} ni {-nonewline {}}} {\n" +" tailcall ${-nonewline} read {*}${chan}\n" +" }\n" +" tailcall $chan read {*}${-nonewline}\n" +" }\n" +"\n" +" proc fconfigure {f args} {\n" +" foreach {n v} $args {\n" +" switch -glob -- $n {\n" +" -bl* {\n" +" $f ndelay $(!$v)\n" +" }\n" +" -bu* {\n" +" $f buffering $v\n" +" }\n" +" -tr* {\n" +"\n" +" }\n" +" default {\n" +" return -code error \"fconfigure: unknown option $n\"\n" +" }\n" +" }\n" +" }\n" +" }\n" +"}\n" +"\n" +"\n" +"proc fileevent {args} {\n" +" tailcall {*}$args\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"proc parray {arrayname {pattern *} {puts puts}} {\n" +" upvar $arrayname a\n" +"\n" +" set max 0\n" +" foreach name [array names a $pattern]] {\n" +" if {[string length $name] > $max} {\n" +" set max [string length $name]\n" +" }\n" +" }\n" +" incr max [string length $arrayname]\n" +" incr max 2\n" +" foreach name [lsort [array names a $pattern]] {\n" +" $puts [format \"%-${max}s = %s\" $arrayname\\($name\\) $a($name)]\n" +" }\n" +"}\n" +"\n" +"\n" +"proc {file copy} {{force {}} source target} {\n" +" try {\n" +" if {$force ni {{} -force}} {\n" +" error \"bad option \\\"$force\\\": should be -force\"\n" +" }\n" +"\n" +" set in [open $source rb]\n" +"\n" +" if {[file exists $target]} {\n" +" if {$force eq \"\"} {\n" +" error \"error copying \\\"$source\\\" to \\\"$target\\\": file already exists\"\n" +" }\n" +"\n" +" if {$source eq $target} {\n" +" return\n" +" }\n" +"\n" +"\n" +" file stat $source ss\n" +" file stat $target ts\n" +" if {$ss(dev) == $ts(dev) && $ss(ino) == $ts(ino) && $ss(ino)} {\n" +" return\n" +" }\n" +" }\n" +" set out [open $target wb]\n" +" $in copyto $out\n" +" $out close\n" +" } on error {msg opts} {\n" +" incr opts(-level)\n" +" return {*}$opts $msg\n" +" } finally {\n" +" catch {$in close}\n" +" }\n" +"}\n" +"\n" +"\n" +"\n" +"proc popen {cmd {mode r}} {\n" +" lassign [socket pipe] r w\n" +" try {\n" +" if {[string match \"w*\" $mode]} {\n" +" lappend cmd <@$r &\n" +" set pids [exec {*}$cmd]\n" +" $r close\n" +" set f $w\n" +" } else {\n" +" lappend cmd >@$w &\n" +" set pids [exec {*}$cmd]\n" +" $w close\n" +" set f $r\n" +" }\n" +" lambda {cmd args} {f pids} {\n" +" if {$cmd eq \"pid\"} {\n" +" return $pids\n" +" }\n" +" if {$cmd eq \"close\"} {\n" +" $f close\n" +"\n" +" foreach p $pids { os.wait $p }\n" +" return\n" +" }\n" +" tailcall $f $cmd {*}$args\n" +" }\n" +" } on error {error opts} {\n" +" $r close\n" +" $w close\n" +" error $error\n" +" }\n" +"}\n" +"\n" +"\n" +"local proc pid {{channelId {}}} {\n" +" if {$channelId eq \"\"} {\n" +" tailcall upcall pid\n" +" }\n" +" if {[catch {$channelId tell}]} {\n" +" return -code error \"can not find channel named \\\"$channelId\\\"\"\n" +" }\n" +" if {[catch {$channelId pid} pids]} {\n" +" return \"\"\n" +" }\n" +" return $pids\n" +"}\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"proc try {args} {\n" +" set catchopts {}\n" +" while {[string match -* [lindex $args 0]]} {\n" +" set args [lassign $args opt]\n" +" if {$opt eq \"--\"} {\n" +" break\n" +" }\n" +" lappend catchopts $opt\n" +" }\n" +" if {[llength $args] == 0} {\n" +" return -code error {wrong # args: should be \"try ?options? script ?argument ...?\"}\n" +" }\n" +" set args [lassign $args script]\n" +" set code [catch -eval {*}$catchopts {uplevel 1 $script} msg opts]\n" +"\n" +" set handled 0\n" +"\n" +" foreach {on codes vars script} $args {\n" +" switch -- $on \\\n" +" on {\n" +" if {!$handled && ($codes eq \"*\" || [info returncode $code] in $codes)} {\n" +" lassign $vars msgvar optsvar\n" +" if {$msgvar ne \"\"} {\n" +" upvar $msgvar hmsg\n" +" set hmsg $msg\n" +" }\n" +" if {$optsvar ne \"\"} {\n" +" upvar $optsvar hopts\n" +" set hopts $opts\n" +" }\n" +"\n" +" set code [catch {uplevel 1 $script} msg opts]\n" +" incr handled\n" +" }\n" +" } \\\n" +" finally {\n" +" set finalcode [catch {uplevel 1 $codes} finalmsg finalopts]\n" +" if {$finalcode} {\n" +"\n" +" set code $finalcode\n" +" set msg $finalmsg\n" +" set opts $finalopts\n" +" }\n" +" break\n" +" } \\\n" +" default {\n" +" return -code error \"try: expected 'on' or 'finally', got '$on'\"\n" +" }\n" +" }\n" +"\n" +" if {$code} {\n" +" incr opts(-level)\n" +" return {*}$opts $msg\n" +" }\n" +" return $msg\n" +"}\n" +"\n" +"\n" +"\n" +"proc throw {code {msg \"\"}} {\n" +" return -code $code $msg\n" +"}\n" +"\n" +"\n" +"proc {file delete force} {path} {\n" +" foreach e [readdir $path] {\n" +" file delete -force $path/$e\n" +" }\n" +" file delete $path\n" +"}\n" +); +} + + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#include +#endif + + +#if defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SELECT) && defined(HAVE_NETINET_IN_H) && defined(HAVE_NETDB_H) && defined(HAVE_ARPA_INET_H) +#include +#include +#include +#include +#ifdef HAVE_SYS_UN_H +#include +#endif +#else +#define JIM_ANSIC +#endif + + +#define AIO_CMD_LEN 32 +#define AIO_BUF_LEN 256 + +#ifndef HAVE_FTELLO + #define ftello ftell +#endif +#ifndef HAVE_FSEEKO + #define fseeko fseek +#endif + +#define AIO_KEEPOPEN 1 + +#if defined(JIM_IPV6) +#define IPV6 1 +#else +#define IPV6 0 +#ifndef PF_INET6 +#define PF_INET6 0 +#endif +#endif + + +typedef struct AioFile +{ + FILE *fp; + Jim_Obj *filename; + int type; + int openFlags; + int fd; + Jim_Obj *rEvent; + Jim_Obj *wEvent; + Jim_Obj *eEvent; + int addr_family; +} AioFile; + +static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv); +static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode); + + +static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name) +{ + if (name) { + Jim_SetResultFormatted(interp, "%#s: %s", name, strerror(errno)); + } + else { + Jim_SetResultString(interp, strerror(errno), -1); + } +} + +static void JimAioDelProc(Jim_Interp *interp, void *privData) +{ + AioFile *af = privData; + + JIM_NOTUSED(interp); + + Jim_DecrRefCount(interp, af->filename); + +#ifdef jim_ext_eventloop + + Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION); +#endif + + if (!(af->openFlags & AIO_KEEPOPEN)) { + fclose(af->fp); + } + + Jim_Free(af); +} + +static int JimCheckStreamError(Jim_Interp *interp, AioFile *af) +{ + if (!ferror(af->fp)) { + return JIM_OK; + } + clearerr(af->fp); + + if (feof(af->fp) || errno == EAGAIN || errno == EINTR) { + return JIM_OK; + } +#ifdef ECONNRESET + if (errno == ECONNRESET) { + return JIM_OK; + } +#endif +#ifdef ECONNABORTED + if (errno != ECONNABORTED) { + return JIM_OK; + } +#endif + JimAioSetError(interp, af->filename); + return JIM_ERR; +} + +static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char buf[AIO_BUF_LEN]; + Jim_Obj *objPtr; + int nonewline = 0; + jim_wide neededLen = -1; + + if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { + nonewline = 1; + argv++; + argc--; + } + if (argc == 1) { + if (Jim_GetWide(interp, argv[0], &neededLen) != JIM_OK) + return JIM_ERR; + if (neededLen < 0) { + Jim_SetResultString(interp, "invalid parameter: negative len", -1); + return JIM_ERR; + } + } + else if (argc) { + return -1; + } + objPtr = Jim_NewStringObj(interp, NULL, 0); + while (neededLen != 0) { + int retval; + int readlen; + + if (neededLen == -1) { + readlen = AIO_BUF_LEN; + } + else { + readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen); + } + retval = fread(buf, 1, readlen, af->fp); + if (retval > 0) { + Jim_AppendString(interp, objPtr, buf, retval); + if (neededLen != -1) { + neededLen -= retval; + } + } + if (retval != readlen) + break; + } + + if (JimCheckStreamError(interp, af)) { + Jim_FreeNewObj(interp, objPtr); + return JIM_ERR; + } + if (nonewline) { + int len; + const char *s = Jim_GetString(objPtr, &len); + + if (len > 0 && s[len - 1] == '\n') { + objPtr->length--; + objPtr->bytes[objPtr->length] = '\0'; + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + jim_wide count = 0; + jim_wide maxlen = JIM_WIDE_MAX; + FILE *outfh = Jim_AioFilehandle(interp, argv[0]); + + if (outfh == NULL) { + return JIM_ERR; + } + + if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &maxlen) != JIM_OK) { + return JIM_ERR; + } + } + + while (count < maxlen) { + int ch = fgetc(af->fp); + + if (ch == EOF || fputc(ch, outfh) == EOF) { + break; + } + count++; + } + + if (ferror(af->fp)) { + Jim_SetResultFormatted(interp, "error while reading: %s", strerror(errno)); + clearerr(af->fp); + return JIM_ERR; + } + + if (ferror(outfh)) { + Jim_SetResultFormatted(interp, "error while writing: %s", strerror(errno)); + clearerr(outfh); + return JIM_ERR; + } + + Jim_SetResultInt(interp, count); + + return JIM_OK; +} + +static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + char buf[AIO_BUF_LEN]; + Jim_Obj *objPtr; + int len; + + errno = 0; + + objPtr = Jim_NewStringObj(interp, NULL, 0); + while (1) { + buf[AIO_BUF_LEN - 1] = '_'; + if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL) + break; + + if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') { + Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN - 1); + } + else { + len = strlen(buf); + + if (len && (buf[len - 1] == '\n')) { + + len--; + } + + Jim_AppendString(interp, objPtr, buf, len); + break; + } + } + if (JimCheckStreamError(interp, af)) { + + Jim_FreeNewObj(interp, objPtr); + return JIM_ERR; + } + + if (argc) { + if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) { + Jim_FreeNewObj(interp, objPtr); + return JIM_ERR; + } + + len = Jim_Length(objPtr); + + if (len == 0 && feof(af->fp)) { + + len = -1; + } + Jim_SetResultInt(interp, len); + } + else { + Jim_SetResult(interp, objPtr); + } + return JIM_OK; +} + +static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int wlen; + const char *wdata; + Jim_Obj *strObj; + + if (argc == 2) { + if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) { + return -1; + } + strObj = argv[1]; + } + else { + strObj = argv[0]; + } + + wdata = Jim_GetString(strObj, &wlen); + if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) { + if (argc == 2 || putc('\n', af->fp) != EOF) { + return JIM_OK; + } + } + JimAioSetError(interp, af->filename); + return JIM_ERR; +} + +static int aio_cmd_isatty(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef HAVE_ISATTY + AioFile *af = Jim_CmdPrivData(interp); + Jim_SetResultInt(interp, isatty(fileno(af->fp))); +#else + Jim_SetResultInt(interp, 0); +#endif + + return JIM_OK; +} + + +static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + if (fflush(af->fp) == EOF) { + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + return JIM_OK; +} + +static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResultInt(interp, feof(af->fp)); + return JIM_OK; +} + +static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc == 3) { +#if !defined(JIM_ANSIC) && defined(HAVE_SHUTDOWN) + static const char * const options[] = { "r", "w", NULL }; + enum { OPT_R, OPT_W, }; + int option; + AioFile *af = Jim_CmdPrivData(interp); + + if (Jim_GetEnum(interp, argv[2], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + if (shutdown(af->fd, option == OPT_R ? SHUT_RD : SHUT_WR) == 0) { + return JIM_OK; + } + JimAioSetError(interp, NULL); +#else + Jim_SetResultString(interp, "async close not supported", -1); +#endif + return JIM_ERR; + } + + return Jim_DeleteCommand(interp, Jim_String(argv[0])); +} + +static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + int orig = SEEK_SET; + jim_wide offset; + + if (argc == 2) { + if (Jim_CompareStringImmediate(interp, argv[1], "start")) + orig = SEEK_SET; + else if (Jim_CompareStringImmediate(interp, argv[1], "current")) + orig = SEEK_CUR; + else if (Jim_CompareStringImmediate(interp, argv[1], "end")) + orig = SEEK_END; + else { + return -1; + } + } + if (Jim_GetWide(interp, argv[0], &offset) != JIM_OK) { + return JIM_ERR; + } + if (fseeko(af->fp, offset, orig) == -1) { + JimAioSetError(interp, af->filename); + return JIM_ERR; + } + return JIM_OK; +} + +static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResultInt(interp, ftello(af->fp)); + return JIM_OK; +} + +static int aio_cmd_filename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + Jim_SetResult(interp, af->filename); + return JIM_OK; +} + +#ifdef O_NDELAY +static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + int fmode = fcntl(af->fd, F_GETFL); + + if (argc) { + long nb; + + if (Jim_GetLong(interp, argv[0], &nb) != JIM_OK) { + return JIM_ERR; + } + if (nb) { + fmode |= O_NDELAY; + } + else { + fmode &= ~O_NDELAY; + } + (void)fcntl(af->fd, F_SETFL, fmode); + } + Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0); + return JIM_OK; +} +#endif + +static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + static const char * const options[] = { + "none", + "line", + "full", + NULL + }; + enum + { + OPT_NONE, + OPT_LINE, + OPT_FULL, + }; + int option; + + if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_NONE: + setvbuf(af->fp, NULL, _IONBF, 0); + break; + case OPT_LINE: + setvbuf(af->fp, NULL, _IOLBF, BUFSIZ); + break; + case OPT_FULL: + setvbuf(af->fp, NULL, _IOFBF, BUFSIZ); + break; + } + return JIM_OK; +} + +#ifdef jim_ext_eventloop +static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData) +{ + Jim_Obj **objPtrPtr = clientData; + + Jim_DecrRefCount(interp, *objPtrPtr); + *objPtrPtr = NULL; +} + +static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask) +{ + Jim_Obj **objPtrPtr = clientData; + + return Jim_EvalObjBackground(interp, *objPtrPtr); +} + +static int aio_eventinfo(Jim_Interp *interp, AioFile * af, unsigned mask, Jim_Obj **scriptHandlerObj, + int argc, Jim_Obj * const *argv) +{ + if (argc == 0) { + + if (*scriptHandlerObj) { + Jim_SetResult(interp, *scriptHandlerObj); + } + return JIM_OK; + } + + if (*scriptHandlerObj) { + + Jim_DeleteFileHandler(interp, af->fp, mask); + } + + + if (Jim_Length(argv[0]) == 0) { + + return JIM_OK; + } + + + Jim_IncrRefCount(argv[0]); + *scriptHandlerObj = argv[0]; + + Jim_CreateFileHandler(interp, af->fp, mask, + JimAioFileEventHandler, scriptHandlerObj, JimAioFileEventFinalizer); + + return JIM_OK; +} + +static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_READABLE, &af->rEvent, argc, argv); +} + +static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_WRITABLE, &af->wEvent, argc, argv); +} + +static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + AioFile *af = Jim_CmdPrivData(interp); + + return aio_eventinfo(interp, af, JIM_EVENT_EXCEPTION, &af->eEvent, argc, argv); +} +#endif + +static const jim_subcmd_type aio_command_table[] = { + { "read", + "?-nonewline? ?len?", + aio_cmd_read, + 0, + 2, + + }, + { "copyto", + "handle ?size?", + aio_cmd_copy, + 1, + 2, + + }, + { "gets", + "?var?", + aio_cmd_gets, + 0, + 1, + + }, + { "puts", + "?-nonewline? str", + aio_cmd_puts, + 1, + 2, + + }, + { "isatty", + NULL, + aio_cmd_isatty, + 0, + 0, + + }, + { "flush", + NULL, + aio_cmd_flush, + 0, + 0, + + }, + { "eof", + NULL, + aio_cmd_eof, + 0, + 0, + + }, + { "close", + "?r(ead)|w(rite)?", + aio_cmd_close, + 0, + 1, + JIM_MODFLAG_FULLARGV, + + }, + { "seek", + "offset ?start|current|end", + aio_cmd_seek, + 1, + 2, + + }, + { "tell", + NULL, + aio_cmd_tell, + 0, + 0, + + }, + { "filename", + NULL, + aio_cmd_filename, + 0, + 0, + + }, +#ifdef O_NDELAY + { "ndelay", + "?0|1?", + aio_cmd_ndelay, + 0, + 1, + + }, +#endif + { "buffering", + "none|line|full", + aio_cmd_buffering, + 1, + 1, + + }, +#ifdef jim_ext_eventloop + { "readable", + "?readable-script?", + aio_cmd_readable, + 0, + 1, + + }, + { "writable", + "?writable-script?", + aio_cmd_writable, + 0, + 1, + + }, + { "onexception", + "?exception-script?", + aio_cmd_onexception, + 0, + 1, + + }, +#endif + { NULL } +}; + +static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, aio_command_table, argc, argv), argc, argv); +} + +static int JimAioOpenCommand(Jim_Interp *interp, int argc, + Jim_Obj *const *argv) +{ + const char *mode; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); + return JIM_ERR; + } + + mode = (argc == 3) ? Jim_String(argv[2]) : "r"; + +#ifdef jim_ext_tclcompat + { + const char *filename = Jim_String(argv[1]); + + + if (*filename == '|') { + Jim_Obj *evalObj[3]; + + evalObj[0] = Jim_NewStringObj(interp, "::popen", -1); + evalObj[1] = Jim_NewStringObj(interp, filename + 1, -1); + evalObj[2] = Jim_NewStringObj(interp, mode, -1); + + return Jim_EvalObjVector(interp, 3, evalObj); + } + } +#endif + return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode); +} + +static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode) +{ + AioFile *af; + char buf[AIO_CMD_LEN]; + int openFlags = 0; + + if (fh) { + filename = Jim_NewStringObj(interp, hdlfmt, -1); + openFlags = AIO_KEEPOPEN; + } + + Jim_IncrRefCount(filename); + + if (fh == NULL) { +#if !defined(JIM_ANSIC) + if (fd >= 0) { + fh = fdopen(fd, mode); + } + else +#endif + fh = fopen(Jim_String(filename), mode); + + if (fh == NULL) { + JimAioSetError(interp, filename); +#if !defined(JIM_ANSIC) + if (fd >= 0) { + close(fd); + } +#endif + Jim_DecrRefCount(interp, filename); + return JIM_ERR; + } + } + + + af = Jim_Alloc(sizeof(*af)); + memset(af, 0, sizeof(*af)); + af->fp = fh; + af->fd = fileno(fh); + af->filename = filename; +#ifdef FD_CLOEXEC + if ((openFlags & AIO_KEEPOPEN) == 0) { + (void)fcntl(af->fd, F_SETFD, FD_CLOEXEC); + } +#endif + af->openFlags = openFlags; + af->addr_family = family; + snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp)); + Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc); + + Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1))); + + return JIM_OK; +} + +#if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && defined(HAVE_SYS_UN_H)) +static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename, + const char *hdlfmt, int family, const char *mode[2]) +{ + if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) { + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); + + if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) { + Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp)); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } + + + close(p[0]); + close(p[1]); + JimAioSetError(interp, NULL); + return JIM_ERR; +} +#endif + + +int Jim_MakeTempFile(Jim_Interp *interp, const char *template) +{ +#ifdef HAVE_MKSTEMP + int fd; + mode_t mask; + Jim_Obj *filenameObj; + + if (template == NULL) { + const char *tmpdir = getenv("TMPDIR"); + if (tmpdir == NULL || *tmpdir == '\0' || access(tmpdir, W_OK) != 0) { + tmpdir = "/tmp/"; + } + filenameObj = Jim_NewStringObj(interp, tmpdir, -1); + if (tmpdir[0] && tmpdir[strlen(tmpdir) - 1] != '/') { + Jim_AppendString(interp, filenameObj, "/", 1); + } + Jim_AppendString(interp, filenameObj, "tcl.tmp.XXXXXX", -1); + } + else { + filenameObj = Jim_NewStringObj(interp, template, -1); + } + + mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); + + + fd = mkstemp(filenameObj->bytes); + umask(mask); + if (fd < 0) { + JimAioSetError(interp, filenameObj); + Jim_FreeNewObj(interp, filenameObj); + return -1; + } + + Jim_SetResult(interp, filenameObj); + return fd; +#else + Jim_SetResultString(interp, "platform has no tempfile support", -1); + return -1; +#endif +} + +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) +{ + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); + + + if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) { + return ((AioFile *) cmdPtr->u.native.privData)->fp; + } + Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command); + return NULL; +} + +int Jim_aioInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); +#ifndef JIM_ANSIC + Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL); +#endif + + + JimMakeChannel(interp, stdin, -1, NULL, "stdin", 0, "r"); + JimMakeChannel(interp, stdout, -1, NULL, "stdout", 0, "w"); + JimMakeChannel(interp, stderr, -1, NULL, "stderr", 0, "w"); + + return JIM_OK; +} + +#include +#include +#include + + +#ifdef HAVE_DIRENT_H +#include +#endif + +int Jim_ReaddirCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *dirPath; + DIR *dirPtr; + struct dirent *entryPtr; + int nocomplain = 0; + + if (argc == 3 && Jim_CompareStringImmediate(interp, argv[1], "-nocomplain")) { + nocomplain = 1; + } + if (argc != 2 && !nocomplain) { + Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath"); + return JIM_ERR; + } + + dirPath = Jim_String(argv[1 + nocomplain]); + + dirPtr = opendir(dirPath); + if (dirPtr == NULL) { + if (nocomplain) { + return JIM_OK; + } + Jim_SetResultString(interp, strerror(errno), -1); + return JIM_ERR; + } + else { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + while ((entryPtr = readdir(dirPtr)) != NULL) { + if (entryPtr->d_name[0] == '.') { + if (entryPtr->d_name[1] == '\0') { + continue; + } + if ((entryPtr->d_name[1] == '.') && (entryPtr->d_name[2] == '\0')) + continue; + } + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, entryPtr->d_name, -1)); + } + closedir(dirPtr); + + Jim_SetResult(interp, listObj); + + return JIM_OK; + } +} + +int Jim_readdirInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "readdir", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL); + return JIM_OK; +} + +#include +#include + +#if defined(JIM_REGEXP) +#else + #include +#endif + +static void FreeRegexpInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + regfree(objPtr->internalRep.regexpValue.compre); + Jim_Free(objPtr->internalRep.regexpValue.compre); +} + +static const Jim_ObjType regexpObjType = { + "regexp", + FreeRegexpInternalRep, + NULL, + NULL, + JIM_TYPE_NONE +}; + +static regex_t *SetRegexpFromAny(Jim_Interp *interp, Jim_Obj *objPtr, unsigned flags) +{ + regex_t *compre; + const char *pattern; + int ret; + + + if (objPtr->typePtr == ®expObjType && + objPtr->internalRep.regexpValue.compre && objPtr->internalRep.regexpValue.flags == flags) { + + return objPtr->internalRep.regexpValue.compre; + } + + + + + pattern = Jim_String(objPtr); + compre = Jim_Alloc(sizeof(regex_t)); + + if ((ret = regcomp(compre, pattern, REG_EXTENDED | flags)) != 0) { + char buf[100]; + + regerror(ret, compre, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "couldn't compile regular expression pattern: %s", buf); + regfree(compre); + Jim_Free(compre); + return NULL; + } + + Jim_FreeIntRep(interp, objPtr); + + objPtr->typePtr = ®expObjType; + objPtr->internalRep.regexpValue.flags = flags; + objPtr->internalRep.regexpValue.compre = compre; + + return compre; +} + +int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int opt_indices = 0; + int opt_all = 0; + int opt_inline = 0; + regex_t *regex; + int match, i, j; + int offset = 0; + regmatch_t *pmatch = NULL; + int source_len; + int result = JIM_OK; + const char *pattern; + const char *source_str; + int num_matches = 0; + int num_vars; + Jim_Obj *resultListObj = NULL; + int regcomp_flags = 0; + int eflags = 0; + int option; + enum { + OPT_INDICES, OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_INLINE, OPT_START, OPT_END + }; + static const char * const options[] = { + "-indices", "-nocase", "-line", "-all", "-inline", "-start", "--", NULL + }; + + if (argc < 3) { + wrongNumArgs: + Jim_WrongNumArgs(interp, 1, argv, + "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?"); + return JIM_ERR; + } + + for (i = 1; i < argc; i++) { + const char *opt = Jim_String(argv[i]); + + if (*opt != '-') { + break; + } + if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + if (option == OPT_END) { + i++; + break; + } + switch (option) { + case OPT_INDICES: + opt_indices = 1; + break; + + case OPT_NOCASE: + regcomp_flags |= REG_ICASE; + break; + + case OPT_LINE: + regcomp_flags |= REG_NEWLINE; + break; + + case OPT_ALL: + opt_all = 1; + break; + + case OPT_INLINE: + opt_inline = 1; + break; + + case OPT_START: + if (++i == argc) { + goto wrongNumArgs; + } + if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) { + return JIM_ERR; + } + break; + } + } + if (argc - i < 2) { + goto wrongNumArgs; + } + + regex = SetRegexpFromAny(interp, argv[i], regcomp_flags); + if (!regex) { + return JIM_ERR; + } + + pattern = Jim_String(argv[i]); + source_str = Jim_GetString(argv[i + 1], &source_len); + + num_vars = argc - i - 2; + + if (opt_inline) { + if (num_vars) { + Jim_SetResultString(interp, "regexp match variables not allowed when using -inline", + -1); + result = JIM_ERR; + goto done; + } + num_vars = regex->re_nsub + 1; + } + + pmatch = Jim_Alloc((num_vars + 1) * sizeof(*pmatch)); + + if (offset) { + if (offset < 0) { + offset += source_len + 1; + } + if (offset > source_len) { + source_str += source_len; + } + else if (offset > 0) { + source_str += offset; + } + eflags |= REG_NOTBOL; + } + + if (opt_inline) { + resultListObj = Jim_NewListObj(interp, NULL, 0); + } + + next_match: + match = regexec(regex, source_str, num_vars + 1, pmatch, eflags); + if (match >= REG_BADPAT) { + char buf[100]; + + regerror(match, regex, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); + result = JIM_ERR; + goto done; + } + + if (match == REG_NOMATCH) { + goto done; + } + + num_matches++; + + if (opt_all && !opt_inline) { + + goto try_next_match; + } + + + j = 0; + for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) { + Jim_Obj *resultObj; + + if (opt_indices) { + resultObj = Jim_NewListObj(interp, NULL, 0); + } + else { + resultObj = Jim_NewStringObj(interp, "", 0); + } + + if (pmatch[j].rm_so == -1) { + if (opt_indices) { + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, -1)); + } + } + else { + int len = pmatch[j].rm_eo - pmatch[j].rm_so; + + if (opt_indices) { + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, + offset + pmatch[j].rm_so)); + Jim_ListAppendElement(interp, resultObj, Jim_NewIntObj(interp, + offset + pmatch[j].rm_so + len - 1)); + } + else { + Jim_AppendString(interp, resultObj, source_str + pmatch[j].rm_so, len); + } + } + + if (opt_inline) { + Jim_ListAppendElement(interp, resultListObj, resultObj); + } + else { + + result = Jim_SetVariable(interp, argv[i], resultObj); + + if (result != JIM_OK) { + Jim_FreeObj(interp, resultObj); + break; + } + } + } + + try_next_match: + if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) { + if (pmatch[0].rm_eo) { + offset += pmatch[0].rm_eo; + source_str += pmatch[0].rm_eo; + } + else { + source_str++; + offset++; + } + if (*source_str) { + eflags = REG_NOTBOL; + goto next_match; + } + } + + done: + if (result == JIM_OK) { + if (opt_inline) { + Jim_SetResult(interp, resultListObj); + } + else { + Jim_SetResultInt(interp, num_matches); + } + } + + Jim_Free(pmatch); + return result; +} + +#define MAX_SUB_MATCHES 50 + +int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int regcomp_flags = 0; + int regexec_flags = 0; + int opt_all = 0; + int offset = 0; + regex_t *regex; + const char *p; + int result; + regmatch_t pmatch[MAX_SUB_MATCHES + 1]; + int num_matches = 0; + + int i, j, n; + Jim_Obj *varname; + Jim_Obj *resultObj; + const char *source_str; + int source_len; + const char *replace_str; + int replace_len; + const char *pattern; + int option; + enum { + OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_END + }; + static const char * const options[] = { + "-nocase", "-line", "-all", "-start", "--", NULL + }; + + if (argc < 4) { + wrongNumArgs: + Jim_WrongNumArgs(interp, 1, argv, + "?switches? exp string subSpec ?varName?"); + return JIM_ERR; + } + + for (i = 1; i < argc; i++) { + const char *opt = Jim_String(argv[i]); + + if (*opt != '-') { + break; + } + if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + if (option == OPT_END) { + i++; + break; + } + switch (option) { + case OPT_NOCASE: + regcomp_flags |= REG_ICASE; + break; + + case OPT_LINE: + regcomp_flags |= REG_NEWLINE; + break; + + case OPT_ALL: + opt_all = 1; + break; + + case OPT_START: + if (++i == argc) { + goto wrongNumArgs; + } + if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) { + return JIM_ERR; + } + break; + } + } + if (argc - i != 3 && argc - i != 4) { + goto wrongNumArgs; + } + + regex = SetRegexpFromAny(interp, argv[i], regcomp_flags); + if (!regex) { + return JIM_ERR; + } + pattern = Jim_String(argv[i]); + + source_str = Jim_GetString(argv[i + 1], &source_len); + replace_str = Jim_GetString(argv[i + 2], &replace_len); + varname = argv[i + 3]; + + + resultObj = Jim_NewStringObj(interp, "", 0); + + if (offset) { + if (offset < 0) { + offset += source_len + 1; + } + if (offset > source_len) { + offset = source_len; + } + else if (offset < 0) { + offset = 0; + } + } + + + Jim_AppendString(interp, resultObj, source_str, offset); + + + n = source_len - offset; + p = source_str + offset; + do { + int match = regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags); + + if (match >= REG_BADPAT) { + char buf[100]; + + regerror(match, regex, buf, sizeof(buf)); + Jim_SetResultFormatted(interp, "error while matching pattern: %s", buf); + return JIM_ERR; + } + if (match == REG_NOMATCH) { + break; + } + + num_matches++; + + Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so); + + + for (j = 0; j < replace_len; j++) { + int idx; + int c = replace_str[j]; + + if (c == '&') { + idx = 0; + } + else if (c == '\\' && j < replace_len) { + c = replace_str[++j]; + if ((c >= '0') && (c <= '9')) { + idx = c - '0'; + } + else if ((c == '\\') || (c == '&')) { + Jim_AppendString(interp, resultObj, replace_str + j, 1); + continue; + } + else { + Jim_AppendString(interp, resultObj, replace_str + j - 1, 2); + continue; + } + } + else { + Jim_AppendString(interp, resultObj, replace_str + j, 1); + continue; + } + if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) { + Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so, + pmatch[idx].rm_eo - pmatch[idx].rm_so); + } + } + + p += pmatch[0].rm_eo; + n -= pmatch[0].rm_eo; + + + if (!opt_all || n == 0) { + break; + } + + + if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') { + break; + } + + + if (pattern[0] == '\0' && n) { + + Jim_AppendString(interp, resultObj, p, 1); + p++; + n--; + } + + regexec_flags |= REG_NOTBOL; + } while (n); + + Jim_AppendString(interp, resultObj, p, -1); + + + if (argc - i == 4) { + result = Jim_SetVariable(interp, varname, resultObj); + + if (result == JIM_OK) { + Jim_SetResultInt(interp, num_matches); + } + else { + Jim_FreeObj(interp, resultObj); + } + } + else { + Jim_SetResult(interp, resultObj); + result = JIM_OK; + } + + return result; +} + +int Jim_regexpInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "regexp", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL); + Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL); + return JIM_OK; +} + +#include +#include +#include +#include +#include +#include + + +#ifdef HAVE_UTIMES +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#elif defined(_MSC_VER) +#include +#define F_OK 0 +#define W_OK 2 +#define R_OK 4 +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) +#endif + +# ifndef MAXPATHLEN +# define MAXPATHLEN JIM_PATH_LEN +# endif + +#if defined(__MINGW32__) || defined(_MSC_VER) +#define ISWINDOWS 1 +#else +#define ISWINDOWS 0 +#endif + + +static const char *JimGetFileType(int mode) +{ + if (S_ISREG(mode)) { + return "file"; + } + else if (S_ISDIR(mode)) { + return "directory"; + } +#ifdef S_ISCHR + else if (S_ISCHR(mode)) { + return "characterSpecial"; + } +#endif +#ifdef S_ISBLK + else if (S_ISBLK(mode)) { + return "blockSpecial"; + } +#endif +#ifdef S_ISFIFO + else if (S_ISFIFO(mode)) { + return "fifo"; + } +#endif +#ifdef S_ISLNK + else if (S_ISLNK(mode)) { + return "link"; + } +#endif +#ifdef S_ISSOCK + else if (S_ISSOCK(mode)) { + return "socket"; + } +#endif + return "unknown"; +} + +static void AppendStatElement(Jim_Interp *interp, Jim_Obj *listObj, const char *key, jim_wide value) +{ + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, key, -1)); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); +} + +static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat *sb) +{ + + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + AppendStatElement(interp, listObj, "dev", sb->st_dev); + AppendStatElement(interp, listObj, "ino", sb->st_ino); + AppendStatElement(interp, listObj, "mode", sb->st_mode); + AppendStatElement(interp, listObj, "nlink", sb->st_nlink); + AppendStatElement(interp, listObj, "uid", sb->st_uid); + AppendStatElement(interp, listObj, "gid", sb->st_gid); + AppendStatElement(interp, listObj, "size", sb->st_size); + AppendStatElement(interp, listObj, "atime", sb->st_atime); + AppendStatElement(interp, listObj, "mtime", sb->st_mtime); + AppendStatElement(interp, listObj, "ctime", sb->st_ctime); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, "type", -1)); + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, JimGetFileType((int)sb->st_mode), -1)); + + + if (varName) { + Jim_Obj *objPtr = Jim_GetVariable(interp, varName, JIM_NONE); + if (objPtr) { + if (Jim_DictSize(interp, objPtr) < 0) { + + Jim_SetResultFormatted(interp, "can't set \"%#s(dev)\": variable isn't array", varName); + Jim_FreeNewObj(interp, listObj); + return JIM_ERR; + } + + if (Jim_IsShared(objPtr)) + objPtr = Jim_DuplicateObj(interp, objPtr); + + + Jim_ListAppendList(interp, objPtr, listObj); + Jim_DictSize(interp, objPtr); + Jim_InvalidateStringRep(objPtr); + + Jim_FreeNewObj(interp, listObj); + listObj = objPtr; + } + Jim_SetVariable(interp, varName, listObj); + } + + + Jim_SetResult(interp, listObj); + + return JIM_OK; +} + +static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *p = strrchr(path, '/'); + + if (!p && path[0] == '.' && path[1] == '.' && path[2] == '\0') { + Jim_SetResultString(interp, "..", -1); + } else if (!p) { + Jim_SetResultString(interp, ".", -1); + } + else if (p == path) { + Jim_SetResultString(interp, "/", -1); + } + else if (ISWINDOWS && p[-1] == ':') { + + Jim_SetResultString(interp, path, p - path + 1); + } + else { + Jim_SetResultString(interp, path, p - path); + } + return JIM_OK; +} + +static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + const char *p = strrchr(path, '.'); + + if (p == NULL || (lastSlash != NULL && lastSlash > p)) { + Jim_SetResult(interp, argv[0]); + } + else { + Jim_SetResultString(interp, path, p - path); + } + return JIM_OK; +} + +static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + const char *p = strrchr(path, '.'); + + if (p == NULL || (lastSlash != NULL && lastSlash >= p)) { + p = ""; + } + Jim_SetResultString(interp, p, -1); + return JIM_OK; +} + +static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + const char *lastSlash = strrchr(path, '/'); + + if (lastSlash) { + Jim_SetResultString(interp, lastSlash + 1, -1); + } + else { + Jim_SetResult(interp, argv[0]); + } + return JIM_OK; +} + +static int file_cmd_normalize(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef HAVE_REALPATH + const char *path = Jim_String(argv[0]); + char *newname = Jim_Alloc(MAXPATHLEN + 1); + + if (realpath(path, newname)) { + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, -1)); + return JIM_OK; + } + else { + Jim_Free(newname); + Jim_SetResultFormatted(interp, "can't normalize \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } +#else + Jim_SetResultString(interp, "Not implemented", -1); + return JIM_ERR; +#endif +} + +static int file_cmd_join(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + char *newname = Jim_Alloc(MAXPATHLEN + 1); + char *last = newname; + + *newname = 0; + + + for (i = 0; i < argc; i++) { + int len; + const char *part = Jim_GetString(argv[i], &len); + + if (*part == '/') { + + last = newname; + } + else if (ISWINDOWS && strchr(part, ':')) { + + last = newname; + } + else if (part[0] == '.') { + if (part[1] == '/') { + part += 2; + len -= 2; + } + else if (part[1] == 0 && last != newname) { + + continue; + } + } + + + if (last != newname && last[-1] != '/') { + *last++ = '/'; + } + + if (len) { + if (last + len - newname >= MAXPATHLEN) { + Jim_Free(newname); + Jim_SetResultString(interp, "Path too long", -1); + return JIM_ERR; + } + memcpy(last, part, len); + last += len; + } + + + if (last > newname + 1 && last[-1] == '/') { + + if (!ISWINDOWS || !(last > newname + 2 && last[-2] == ':')) { + *--last = 0; + } + } + } + + *last = 0; + + + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, newname, last - newname)); + + return JIM_OK; +} + +static int file_access(Jim_Interp *interp, Jim_Obj *filename, int mode) +{ + Jim_SetResultBool(interp, access(Jim_String(filename), mode) != -1); + + return JIM_OK; +} + +static int file_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], R_OK); +} + +static int file_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], W_OK); +} + +static int file_cmd_executable(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#ifdef X_OK + return file_access(interp, argv[0], X_OK); +#else + + Jim_SetResultBool(interp, 1); + return JIM_OK; +#endif +} + +static int file_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return file_access(interp, argv[0], F_OK); +} + +static int file_cmd_delete(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int force = Jim_CompareStringImmediate(interp, argv[0], "-force"); + + if (force || Jim_CompareStringImmediate(interp, argv[0], "--")) { + argc++; + argv--; + } + + while (argc--) { + const char *path = Jim_String(argv[0]); + + if (unlink(path) == -1 && errno != ENOENT) { + if (rmdir(path) == -1) { + + if (!force || Jim_EvalPrefix(interp, "file delete force", 1, argv) != JIM_OK) { + Jim_SetResultFormatted(interp, "couldn't delete file \"%s\": %s", path, + strerror(errno)); + return JIM_ERR; + } + } + } + argv++; + } + return JIM_OK; +} + +#ifdef HAVE_MKDIR_ONE_ARG +#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME) +#else +#define MKDIR_DEFAULT(PATHNAME) mkdir(PATHNAME, 0755) +#endif + +static int mkdir_all(char *path) +{ + int ok = 1; + + + goto first; + + while (ok--) { + + { + char *slash = strrchr(path, '/'); + + if (slash && slash != path) { + *slash = 0; + if (mkdir_all(path) != 0) { + return -1; + } + *slash = '/'; + } + } + first: + if (MKDIR_DEFAULT(path) == 0) { + return 0; + } + if (errno == ENOENT) { + + continue; + } + + if (errno == EEXIST) { + struct stat sb; + + if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { + return 0; + } + + errno = EEXIST; + } + + break; + } + return -1; +} + +static int file_cmd_mkdir(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + while (argc--) { + char *path = Jim_StrDup(Jim_String(argv[0])); + int rc = mkdir_all(path); + + Jim_Free(path); + if (rc != 0) { + Jim_SetResultFormatted(interp, "can't create directory \"%#s\": %s", argv[0], + strerror(errno)); + return JIM_ERR; + } + argv++; + } + return JIM_OK; +} + +static int file_cmd_tempfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int fd = Jim_MakeTempFile(interp, (argc >= 1) ? Jim_String(argv[0]) : NULL); + + if (fd < 0) { + return JIM_ERR; + } + close(fd); + + return JIM_OK; +} + +static int file_cmd_rename(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *source; + const char *dest; + int force = 0; + + if (argc == 3) { + if (!Jim_CompareStringImmediate(interp, argv[0], "-force")) { + return -1; + } + force++; + argv++; + argc--; + } + + source = Jim_String(argv[0]); + dest = Jim_String(argv[1]); + + if (!force && access(dest, F_OK) == 0) { + Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": target exists", argv[0], + argv[1]); + return JIM_ERR; + } + + if (rename(source, dest) != 0) { + Jim_SetResultFormatted(interp, "error renaming \"%#s\" to \"%#s\": %s", argv[0], argv[1], + strerror(errno)); + return JIM_ERR; + } + + return JIM_OK; +} + +#if defined(HAVE_LINK) && defined(HAVE_SYMLINK) +static int file_cmd_link(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + const char *source; + const char *dest; + static const char * const options[] = { "-hard", "-symbolic", NULL }; + enum { OPT_HARD, OPT_SYMBOLIC, }; + int option = OPT_HARD; + + if (argc == 3) { + if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + argv++; + argc--; + } + + dest = Jim_String(argv[0]); + source = Jim_String(argv[1]); + + if (option == OPT_HARD) { + ret = link(source, dest); + } + else { + ret = symlink(source, dest); + } + + if (ret != 0) { + Jim_SetResultFormatted(interp, "error linking \"%#s\" to \"%#s\": %s", argv[0], argv[1], + strerror(errno)); + return JIM_ERR; + } + + return JIM_OK; +} +#endif + +static int file_stat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) +{ + const char *path = Jim_String(filename); + + if (stat(path, sb) == -1) { + Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +#ifdef HAVE_LSTAT +static int file_lstat(Jim_Interp *interp, Jim_Obj *filename, struct stat *sb) +{ + const char *path = Jim_String(filename); + + if (lstat(path, sb) == -1) { + Jim_SetResultFormatted(interp, "could not read \"%#s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} +#else +#define file_lstat file_stat +#endif + +static int file_cmd_atime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_atime); + return JIM_OK; +} + +static int file_cmd_mtime(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (argc == 2) { +#ifdef HAVE_UTIMES + jim_wide newtime; + struct timeval times[2]; + + if (Jim_GetWide(interp, argv[1], &newtime) != JIM_OK) { + return JIM_ERR; + } + + times[1].tv_sec = times[0].tv_sec = newtime; + times[1].tv_usec = times[0].tv_usec = 0; + + if (utimes(Jim_String(argv[0]), times) != 0) { + Jim_SetResultFormatted(interp, "can't set time on \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } +#else + Jim_SetResultString(interp, "Not implemented", -1); + return JIM_ERR; +#endif + } + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_mtime); + return JIM_OK; +} + +static int file_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return Jim_EvalPrefix(interp, "file copy", argc, argv); +} + +static int file_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultInt(interp, sb.st_size); + return JIM_OK; +} + +static int file_cmd_isdirectory(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = S_ISDIR(sb.st_mode); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} + +static int file_cmd_isfile(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = S_ISREG(sb.st_mode); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} + +#ifdef HAVE_GETEUID +static int file_cmd_owned(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + int ret = 0; + + if (file_stat(interp, argv[0], &sb) == JIM_OK) { + ret = (geteuid() == sb.st_uid); + } + Jim_SetResultInt(interp, ret); + return JIM_OK; +} +#endif + +#if defined(HAVE_READLINK) +static int file_cmd_readlink(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path = Jim_String(argv[0]); + char *linkValue = Jim_Alloc(MAXPATHLEN + 1); + + int linkLength = readlink(path, linkValue, MAXPATHLEN); + + if (linkLength == -1) { + Jim_Free(linkValue); + Jim_SetResultFormatted(interp, "couldn't readlink \"%#s\": %s", argv[0], strerror(errno)); + return JIM_ERR; + } + linkValue[linkLength] = 0; + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, linkValue, linkLength)); + return JIM_OK; +} +#endif + +static int file_cmd_type(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_lstat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResultString(interp, JimGetFileType((int)sb.st_mode), -1); + return JIM_OK; +} + +#ifdef HAVE_LSTAT +static int file_cmd_lstat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_lstat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); +} +#else +#define file_cmd_lstat file_cmd_stat +#endif + +static int file_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct stat sb; + + if (file_stat(interp, argv[0], &sb) != JIM_OK) { + return JIM_ERR; + } + return StoreStatData(interp, argc == 2 ? argv[1] : NULL, &sb); +} + +static const jim_subcmd_type file_command_table[] = { + { "atime", + "name", + file_cmd_atime, + 1, + 1, + + }, + { "mtime", + "name ?time?", + file_cmd_mtime, + 1, + 2, + + }, + { "copy", + "?-force? source dest", + file_cmd_copy, + 2, + 3, + + }, + { "dirname", + "name", + file_cmd_dirname, + 1, + 1, + + }, + { "rootname", + "name", + file_cmd_rootname, + 1, + 1, + + }, + { "extension", + "name", + file_cmd_extension, + 1, + 1, + + }, + { "tail", + "name", + file_cmd_tail, + 1, + 1, + + }, + { "normalize", + "name", + file_cmd_normalize, + 1, + 1, + + }, + { "join", + "name ?name ...?", + file_cmd_join, + 1, + -1, + + }, + { "readable", + "name", + file_cmd_readable, + 1, + 1, + + }, + { "writable", + "name", + file_cmd_writable, + 1, + 1, + + }, + { "executable", + "name", + file_cmd_executable, + 1, + 1, + + }, + { "exists", + "name", + file_cmd_exists, + 1, + 1, + + }, + { "delete", + "?-force|--? name ...", + file_cmd_delete, + 1, + -1, + + }, + { "mkdir", + "dir ...", + file_cmd_mkdir, + 1, + -1, + + }, + { "tempfile", + "?template?", + file_cmd_tempfile, + 0, + 1, + + }, + { "rename", + "?-force? source dest", + file_cmd_rename, + 2, + 3, + + }, +#if defined(HAVE_LINK) && defined(HAVE_SYMLINK) + { "link", + "?-symbolic|-hard? newname target", + file_cmd_link, + 2, + 3, + + }, +#endif +#if defined(HAVE_READLINK) + { "readlink", + "name", + file_cmd_readlink, + 1, + 1, + + }, +#endif + { "size", + "name", + file_cmd_size, + 1, + 1, + + }, + { "stat", + "name ?var?", + file_cmd_stat, + 1, + 2, + + }, + { "lstat", + "name ?var?", + file_cmd_lstat, + 1, + 2, + + }, + { "type", + "name", + file_cmd_type, + 1, + 1, + + }, +#ifdef HAVE_GETEUID + { "owned", + "name", + file_cmd_owned, + 1, + 1, + + }, +#endif + { "isdirectory", + "name", + file_cmd_isdirectory, + 1, + 1, + + }, + { "isfile", + "name", + file_cmd_isfile, + 1, + 1, + + }, + { + NULL + } +}; + +static int Jim_CdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *path; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "dirname"); + return JIM_ERR; + } + + path = Jim_String(argv[1]); + + if (chdir(path) != 0) { + Jim_SetResultFormatted(interp, "couldn't change working directory to \"%s\": %s", path, + strerror(errno)); + return JIM_ERR; + } + return JIM_OK; +} + +static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *cwd = Jim_Alloc(MAXPATHLEN); + + if (getcwd(cwd, MAXPATHLEN) == NULL) { + Jim_SetResultString(interp, "Failed to get pwd", -1); + Jim_Free(cwd); + return JIM_ERR; + } + else if (ISWINDOWS) { + + char *p = cwd; + while ((p = strchr(p, '\\')) != NULL) { + *p++ = '/'; + } + } + + Jim_SetResultString(interp, cwd, -1); + + Jim_Free(cwd); + return JIM_OK; +} + +int Jim_fileInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "file", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL); + Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL); + Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL); + return JIM_OK; +} + +#include +#include + + +#if (!defined(HAVE_VFORK) || !defined(HAVE_WAITPID)) && !defined(__MINGW32__) +static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *cmdlineObj = Jim_NewEmptyStringObj(interp); + int i, j; + int rc; + + + for (i = 1; i < argc; i++) { + int len; + const char *arg = Jim_GetString(argv[i], &len); + + if (i > 1) { + Jim_AppendString(interp, cmdlineObj, " ", 1); + } + if (strpbrk(arg, "\\\" ") == NULL) { + + Jim_AppendString(interp, cmdlineObj, arg, len); + continue; + } + + Jim_AppendString(interp, cmdlineObj, "\"", 1); + for (j = 0; j < len; j++) { + if (arg[j] == '\\' || arg[j] == '"') { + Jim_AppendString(interp, cmdlineObj, "\\", 1); + } + Jim_AppendString(interp, cmdlineObj, &arg[j], 1); + } + Jim_AppendString(interp, cmdlineObj, "\"", 1); + } + rc = system(Jim_String(cmdlineObj)); + + Jim_FreeNewObj(interp, cmdlineObj); + + if (rc) { + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, 0)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, rc)); + Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); + return JIM_ERR; + } + + return JIM_OK; +} + +int Jim_execInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL); + return JIM_OK; +} +#else + + +#include +#include + +#if defined(__MINGW32__) + + #ifndef STRICT + #define STRICT + #endif + #define WIN32_LEAN_AND_MEAN + #include + #include + + typedef HANDLE fdtype; + typedef HANDLE pidtype; + #define JIM_BAD_FD INVALID_HANDLE_VALUE + #define JIM_BAD_PID INVALID_HANDLE_VALUE + #define JimCloseFd CloseHandle + + #define WIFEXITED(STATUS) 1 + #define WEXITSTATUS(STATUS) (STATUS) + #define WIFSIGNALED(STATUS) 0 + #define WTERMSIG(STATUS) 0 + #define WNOHANG 1 + + static fdtype JimFileno(FILE *fh); + static pidtype JimWaitPid(pidtype pid, int *status, int nohang); + static fdtype JimDupFd(fdtype infd); + static fdtype JimOpenForRead(const char *filename); + static FILE *JimFdOpenForRead(fdtype fd); + static int JimPipe(fdtype pipefd[2]); + static pidtype JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, + fdtype inputId, fdtype outputId, fdtype errorId); + static int JimErrno(void); +#else + #include + #include + #include + #include + + typedef int fdtype; + typedef int pidtype; + #define JimPipe pipe + #define JimErrno() errno + #define JIM_BAD_FD -1 + #define JIM_BAD_PID -1 + #define JimFileno fileno + #define JimReadFd read + #define JimCloseFd close + #define JimWaitPid waitpid + #define JimDupFd dup + #define JimFdOpenForRead(FD) fdopen((FD), "r") + #define JimOpenForRead(NAME) open((NAME), O_RDONLY, 0) + + #ifndef HAVE_EXECVPE + #define execvpe(ARG0, ARGV, ENV) execvp(ARG0, ARGV) + #endif +#endif + +static const char *JimStrError(void); +static char **JimSaveEnv(char **env); +static void JimRestoreEnv(char **env); +static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, + pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr); +static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr); +static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId); +static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len); +static fdtype JimOpenForWrite(const char *filename, int append); +static int JimRewindFd(fdtype fd); + +static void Jim_SetResultErrno(Jim_Interp *interp, const char *msg) +{ + Jim_SetResultFormatted(interp, "%s: %s", msg, JimStrError()); +} + +static const char *JimStrError(void) +{ + return strerror(JimErrno()); +} + +static void Jim_RemoveTrailingNewline(Jim_Obj *objPtr) +{ + int len; + const char *s = Jim_GetString(objPtr, &len); + + if (len > 0 && s[len - 1] == '\n') { + objPtr->length--; + objPtr->bytes[objPtr->length] = '\0'; + } +} + +static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strObj) +{ + char buf[256]; + FILE *fh = JimFdOpenForRead(fd); + if (fh == NULL) { + return JIM_ERR; + } + + while (1) { + int retval = fread(buf, 1, sizeof(buf), fh); + if (retval > 0) { + Jim_AppendString(interp, strObj, buf, retval); + } + if (retval != sizeof(buf)) { + break; + } + } + Jim_RemoveTrailingNewline(strObj); + fclose(fh); + return JIM_OK; +} + +static char **JimBuildEnv(Jim_Interp *interp) +{ + int i; + int size; + int num; + int n; + char **envptr; + char *envdata; + + Jim_Obj *objPtr = Jim_GetGlobalVariableStr(interp, "env", JIM_NONE); + + if (!objPtr) { + return Jim_GetEnviron(); + } + + + + num = Jim_ListLength(interp, objPtr); + if (num % 2) { + + num--; + } + size = Jim_Length(objPtr) + 2; + + envptr = Jim_Alloc(sizeof(*envptr) * (num / 2 + 1) + size); + envdata = (char *)&envptr[num / 2 + 1]; + + n = 0; + for (i = 0; i < num; i += 2) { + const char *s1, *s2; + Jim_Obj *elemObj; + + Jim_ListIndex(interp, objPtr, i, &elemObj, JIM_NONE); + s1 = Jim_String(elemObj); + Jim_ListIndex(interp, objPtr, i + 1, &elemObj, JIM_NONE); + s2 = Jim_String(elemObj); + + envptr[n] = envdata; + envdata += sprintf(envdata, "%s=%s", s1, s2); + envdata++; + n++; + } + envptr[n] = NULL; + *envdata = 0; + + return envptr; +} + +static void JimFreeEnv(char **env, char **original_environ) +{ + if (env != original_environ) { + Jim_Free(env); + } +} + +static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus) +{ + Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0); + int rc = JIM_ERR; + + if (WIFEXITED(waitStatus)) { + if (WEXITSTATUS(waitStatus) == 0) { + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1)); + rc = JIM_OK; + } + else { + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus))); + } + } + else { + const char *type; + const char *action; + + if (WIFSIGNALED(waitStatus)) { + type = "CHILDKILLED"; + action = "killed"; + } + else { + type = "CHILDSUSP"; + action = "suspended"; + } + + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1)); + +#ifdef jim_ext_signal + Jim_SetResultFormatted(interp, "child %s by signal %s", action, Jim_SignalId(WTERMSIG(waitStatus))); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1)); +#else + Jim_SetResultFormatted(interp, "child %s by signal %d", action, WTERMSIG(waitStatus)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus))); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid)); + Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus))); +#endif + } + Jim_SetGlobalVariableStr(interp, "errorCode", errorCode); + return rc; +} + + +struct WaitInfo +{ + pidtype pid; + int status; + int flags; +}; + +struct WaitInfoTable { + struct WaitInfo *info; + int size; + int used; +}; + + +#define WI_DETACHED 2 + +#define WAIT_TABLE_GROW_BY 4 + +static void JimFreeWaitInfoTable(struct Jim_Interp *interp, void *privData) +{ + struct WaitInfoTable *table = privData; + + Jim_Free(table->info); + Jim_Free(table); +} + +static struct WaitInfoTable *JimAllocWaitInfoTable(void) +{ + struct WaitInfoTable *table = Jim_Alloc(sizeof(*table)); + table->info = NULL; + table->size = table->used = 0; + + return table; +} + +static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + fdtype outputId; + fdtype errorId; + pidtype *pidPtr; + int numPids, result; + + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) { + Jim_Obj *listObj; + int i; + + argc--; + numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL); + if (numPids < 0) { + return JIM_ERR; + } + + listObj = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < numPids; i++) { + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, (long)pidPtr[i])); + } + Jim_SetResult(interp, listObj); + JimDetachPids(interp, numPids, pidPtr); + Jim_Free(pidPtr); + return JIM_OK; + } + + numPids = + JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId); + + if (numPids < 0) { + return JIM_ERR; + } + + Jim_SetResultString(interp, "", 0); + + result = JIM_OK; + if (outputId != JIM_BAD_FD) { + result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp)); + if (result < 0) { + Jim_SetResultErrno(interp, "error reading from output pipe"); + } + } + + if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) { + result = JIM_ERR; + } + return result; +} + +static void JimReapDetachedPids(struct WaitInfoTable *table) +{ + struct WaitInfo *waitPtr; + int count; + int dest; + + if (!table) { + return; + } + + waitPtr = table->info; + dest = 0; + for (count = table->used; count > 0; waitPtr++, count--) { + if (waitPtr->flags & WI_DETACHED) { + int status; + pidtype pid = JimWaitPid(waitPtr->pid, &status, WNOHANG); + if (pid == waitPtr->pid) { + + table->used--; + continue; + } + } + if (waitPtr != &table->info[dest]) { + table->info[dest] = *waitPtr; + } + dest++; + } +} + +static pidtype JimWaitForProcess(struct WaitInfoTable *table, pidtype pid, int *statusPtr) +{ + int i; + + + for (i = 0; i < table->used; i++) { + if (pid == table->info[i].pid) { + + JimWaitPid(pid, statusPtr, 0); + + + if (i != table->used - 1) { + table->info[i] = table->info[table->used - 1]; + } + table->used--; + return pid; + } + } + + + return JIM_BAD_PID; +} + +static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr) +{ + int j; + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + + for (j = 0; j < numPids; j++) { + + int i; + for (i = 0; i < table->used; i++) { + if (pidPtr[j] == table->info[i].pid) { + table->info[i].flags |= WI_DETACHED; + break; + } + } + } +} + +static FILE *JimGetAioFilehandle(Jim_Interp *interp, const char *name) +{ + FILE *fh; + Jim_Obj *fhObj; + + fhObj = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(fhObj); + fh = Jim_AioFilehandle(interp, fhObj); + Jim_DecrRefCount(interp, fhObj); + + return fh; +} + +static int +JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, pidtype **pidArrayPtr, + fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr) +{ + pidtype *pidPtr = NULL; /* Points to malloc-ed array holding all + * the pids of child processes. */ + int numPids = 0; /* Actual number of processes that exist + * at *pidPtr right now. */ + int cmdCount; /* Count of number of distinct commands + * found in argc/argv. */ + const char *input = NULL; /* Describes input for pipeline, depending + * on "inputFile". NULL means take input + * from stdin/pipe. */ + int input_len = 0; + +#define FILE_NAME 0 +#define FILE_APPEND 1 +#define FILE_HANDLE 2 +#define FILE_TEXT 3 + + int inputFile = FILE_NAME; /* 1 means input is name of input file. + * 2 means input is filehandle name. + * 0 means input holds actual + * text to be input to command. */ + + int outputFile = FILE_NAME; /* 0 means output is the name of output file. + * 1 means output is the name of output file, and append. + * 2 means output is filehandle name. + * All this is ignored if output is NULL + */ + int errorFile = FILE_NAME; /* 0 means error is the name of error file. + * 1 means error is the name of error file, and append. + * 2 means error is filehandle name. + * All this is ignored if error is NULL + */ + const char *output = NULL; /* Holds name of output file to pipe to, + * or NULL if output goes to stdout/pipe. */ + const char *error = NULL; /* Holds name of stderr file to pipe to, + * or NULL if stderr goes to stderr/pipe. */ + fdtype inputId = JIM_BAD_FD; + fdtype outputId = JIM_BAD_FD; + fdtype errorId = JIM_BAD_FD; + fdtype lastOutputId = JIM_BAD_FD; + fdtype pipeIds[2]; + int firstArg, lastArg; /* Indexes of first and last arguments in + * current command. */ + int lastBar; + int i; + pidtype pid; + char **save_environ; + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + + + char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1)); + int arg_count = 0; + + JimReapDetachedPids(table); + + if (inPipePtr != NULL) { + *inPipePtr = JIM_BAD_FD; + } + if (outPipePtr != NULL) { + *outPipePtr = JIM_BAD_FD; + } + if (errFilePtr != NULL) { + *errFilePtr = JIM_BAD_FD; + } + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + + cmdCount = 1; + lastBar = -1; + for (i = 0; i < argc; i++) { + const char *arg = Jim_String(argv[i]); + + if (arg[0] == '<') { + inputFile = FILE_NAME; + input = arg + 1; + if (*input == '<') { + inputFile = FILE_TEXT; + input_len = Jim_Length(argv[i]) - 2; + input++; + } + else if (*input == '@') { + inputFile = FILE_HANDLE; + input++; + } + + if (!*input && ++i < argc) { + input = Jim_GetString(argv[i], &input_len); + } + } + else if (arg[0] == '>') { + int dup_error = 0; + + outputFile = FILE_NAME; + + output = arg + 1; + if (*output == '>') { + outputFile = FILE_APPEND; + output++; + } + if (*output == '&') { + + output++; + dup_error = 1; + } + if (*output == '@') { + outputFile = FILE_HANDLE; + output++; + } + if (!*output && ++i < argc) { + output = Jim_String(argv[i]); + } + if (dup_error) { + errorFile = outputFile; + error = output; + } + } + else if (arg[0] == '2' && arg[1] == '>') { + error = arg + 2; + errorFile = FILE_NAME; + + if (*error == '@') { + errorFile = FILE_HANDLE; + error++; + } + else if (*error == '>') { + errorFile = FILE_APPEND; + error++; + } + if (!*error && ++i < argc) { + error = Jim_String(argv[i]); + } + } + else { + if (strcmp(arg, "|") == 0 || strcmp(arg, "|&") == 0) { + if (i == lastBar + 1 || i == argc - 1) { + Jim_SetResultString(interp, "illegal use of | or |& in command", -1); + goto badargs; + } + lastBar = i; + cmdCount++; + } + + arg_array[arg_count++] = (char *)arg; + continue; + } + + if (i >= argc) { + Jim_SetResultFormatted(interp, "can't specify \"%s\" as last word in command", arg); + goto badargs; + } + } + + if (arg_count == 0) { + Jim_SetResultString(interp, "didn't specify command to execute", -1); +badargs: + Jim_Free(arg_array); + return -1; + } + + + save_environ = JimSaveEnv(JimBuildEnv(interp)); + + if (input != NULL) { + if (inputFile == FILE_TEXT) { + inputId = JimCreateTemp(interp, input, input_len); + if (inputId == JIM_BAD_FD) { + goto error; + } + } + else if (inputFile == FILE_HANDLE) { + + FILE *fh = JimGetAioFilehandle(interp, input); + + if (fh == NULL) { + goto error; + } + inputId = JimDupFd(JimFileno(fh)); + } + else { + inputId = JimOpenForRead(input); + if (inputId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", input, JimStrError()); + goto error; + } + } + } + else if (inPipePtr != NULL) { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create input pipe for command"); + goto error; + } + inputId = pipeIds[0]; + *inPipePtr = pipeIds[1]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + + if (output != NULL) { + if (outputFile == FILE_HANDLE) { + FILE *fh = JimGetAioFilehandle(interp, output); + if (fh == NULL) { + goto error; + } + fflush(fh); + lastOutputId = JimDupFd(JimFileno(fh)); + } + else { + lastOutputId = JimOpenForWrite(output, outputFile == FILE_APPEND); + if (lastOutputId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", output, JimStrError()); + goto error; + } + } + } + else if (outPipePtr != NULL) { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create output pipe"); + goto error; + } + lastOutputId = pipeIds[1]; + *outPipePtr = pipeIds[0]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + + if (error != NULL) { + if (errorFile == FILE_HANDLE) { + if (strcmp(error, "1") == 0) { + + if (lastOutputId != JIM_BAD_FD) { + errorId = JimDupFd(lastOutputId); + } + else { + + error = "stdout"; + } + } + if (errorId == JIM_BAD_FD) { + FILE *fh = JimGetAioFilehandle(interp, error); + if (fh == NULL) { + goto error; + } + fflush(fh); + errorId = JimDupFd(JimFileno(fh)); + } + } + else { + errorId = JimOpenForWrite(error, errorFile == FILE_APPEND); + if (errorId == JIM_BAD_FD) { + Jim_SetResultFormatted(interp, "couldn't write file \"%s\": %s", error, JimStrError()); + goto error; + } + } + } + else if (errFilePtr != NULL) { + errorId = JimCreateTemp(interp, NULL, 0); + if (errorId == JIM_BAD_FD) { + goto error; + } + *errFilePtr = JimDupFd(errorId); + } + + + pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr)); + for (i = 0; i < numPids; i++) { + pidPtr[i] = JIM_BAD_PID; + } + for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) { + int pipe_dup_err = 0; + fdtype origErrorId = errorId; + + for (lastArg = firstArg; lastArg < arg_count; lastArg++) { + if (arg_array[lastArg][0] == '|') { + if (arg_array[lastArg][1] == '&') { + pipe_dup_err = 1; + } + break; + } + } + + arg_array[lastArg] = NULL; + if (lastArg == arg_count) { + outputId = lastOutputId; + } + else { + if (JimPipe(pipeIds) != 0) { + Jim_SetResultErrno(interp, "couldn't create pipe"); + goto error; + } + outputId = pipeIds[1]; + } + + + if (pipe_dup_err) { + errorId = outputId; + } + + + +#ifdef __MINGW32__ + pid = JimStartWinProcess(interp, &arg_array[firstArg], save_environ ? save_environ[0] : NULL, inputId, outputId, errorId); + if (pid == JIM_BAD_PID) { + Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]); + goto error; + } +#else + pid = vfork(); + if (pid < 0) { + Jim_SetResultErrno(interp, "couldn't fork child process"); + goto error; + } + if (pid == 0) { + + + if (inputId != -1) dup2(inputId, 0); + if (outputId != -1) dup2(outputId, 1); + if (errorId != -1) dup2(errorId, 2); + + for (i = 3; (i <= outputId) || (i <= inputId) || (i <= errorId); i++) { + close(i); + } + + + (void)signal(SIGPIPE, SIG_DFL); + + execvpe(arg_array[firstArg], &arg_array[firstArg], Jim_GetEnviron()); + + + fprintf(stderr, "couldn't exec \"%s\"\n", arg_array[firstArg]); + _exit(127); + } +#endif + + + + if (table->used == table->size) { + table->size += WAIT_TABLE_GROW_BY; + table->info = Jim_Realloc(table->info, table->size * sizeof(*table->info)); + } + + table->info[table->used].pid = pid; + table->info[table->used].flags = 0; + table->used++; + + pidPtr[numPids] = pid; + + + errorId = origErrorId; + + + if (inputId != JIM_BAD_FD) { + JimCloseFd(inputId); + } + if (outputId != JIM_BAD_FD) { + JimCloseFd(outputId); + } + inputId = pipeIds[0]; + pipeIds[0] = pipeIds[1] = JIM_BAD_FD; + } + *pidArrayPtr = pidPtr; + + + cleanup: + if (inputId != JIM_BAD_FD) { + JimCloseFd(inputId); + } + if (lastOutputId != JIM_BAD_FD) { + JimCloseFd(lastOutputId); + } + if (errorId != JIM_BAD_FD) { + JimCloseFd(errorId); + } + Jim_Free(arg_array); + + JimRestoreEnv(save_environ); + + return numPids; + + + error: + if ((inPipePtr != NULL) && (*inPipePtr != JIM_BAD_FD)) { + JimCloseFd(*inPipePtr); + *inPipePtr = JIM_BAD_FD; + } + if ((outPipePtr != NULL) && (*outPipePtr != JIM_BAD_FD)) { + JimCloseFd(*outPipePtr); + *outPipePtr = JIM_BAD_FD; + } + if ((errFilePtr != NULL) && (*errFilePtr != JIM_BAD_FD)) { + JimCloseFd(*errFilePtr); + *errFilePtr = JIM_BAD_FD; + } + if (pipeIds[0] != JIM_BAD_FD) { + JimCloseFd(pipeIds[0]); + } + if (pipeIds[1] != JIM_BAD_FD) { + JimCloseFd(pipeIds[1]); + } + if (pidPtr != NULL) { + for (i = 0; i < numPids; i++) { + if (pidPtr[i] != JIM_BAD_PID) { + JimDetachPids(interp, 1, &pidPtr[i]); + } + } + Jim_Free(pidPtr); + } + numPids = -1; + goto cleanup; +} + + +static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId) +{ + struct WaitInfoTable *table = Jim_CmdPrivData(interp); + int result = JIM_OK; + int i; + + for (i = 0; i < numPids; i++) { + int waitStatus = 0; + if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) { + if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus) != JIM_OK) { + result = JIM_ERR; + } + } + } + Jim_Free(pidPtr); + + if (errorId != JIM_BAD_FD) { + JimRewindFd(errorId); + if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) { + result = JIM_ERR; + } + } + + Jim_RemoveTrailingNewline(Jim_GetResult(interp)); + + return result; +} + +int Jim_execInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "exec", "1.0", JIM_ERRMSG)) + return JIM_ERR; + +#ifdef SIGPIPE + (void)signal(SIGPIPE, SIG_IGN); +#endif + + Jim_CreateCommand(interp, "exec", Jim_ExecCmd, JimAllocWaitInfoTable(), JimFreeWaitInfoTable); + return JIM_OK; +} + +#if defined(__MINGW32__) + + +static SECURITY_ATTRIBUTES *JimStdSecAttrs(void) +{ + static SECURITY_ATTRIBUTES secAtts; + + secAtts.nLength = sizeof(SECURITY_ATTRIBUTES); + secAtts.lpSecurityDescriptor = NULL; + secAtts.bInheritHandle = TRUE; + return &secAtts; +} + +static int JimErrno(void) +{ + switch (GetLastError()) { + case ERROR_FILE_NOT_FOUND: return ENOENT; + case ERROR_PATH_NOT_FOUND: return ENOENT; + case ERROR_TOO_MANY_OPEN_FILES: return EMFILE; + case ERROR_ACCESS_DENIED: return EACCES; + case ERROR_INVALID_HANDLE: return EBADF; + case ERROR_BAD_ENVIRONMENT: return E2BIG; + case ERROR_BAD_FORMAT: return ENOEXEC; + case ERROR_INVALID_ACCESS: return EACCES; + case ERROR_INVALID_DRIVE: return ENOENT; + case ERROR_CURRENT_DIRECTORY: return EACCES; + case ERROR_NOT_SAME_DEVICE: return EXDEV; + case ERROR_NO_MORE_FILES: return ENOENT; + case ERROR_WRITE_PROTECT: return EROFS; + case ERROR_BAD_UNIT: return ENXIO; + case ERROR_NOT_READY: return EBUSY; + case ERROR_BAD_COMMAND: return EIO; + case ERROR_CRC: return EIO; + case ERROR_BAD_LENGTH: return EIO; + case ERROR_SEEK: return EIO; + case ERROR_WRITE_FAULT: return EIO; + case ERROR_READ_FAULT: return EIO; + case ERROR_GEN_FAILURE: return EIO; + case ERROR_SHARING_VIOLATION: return EACCES; + case ERROR_LOCK_VIOLATION: return EACCES; + case ERROR_SHARING_BUFFER_EXCEEDED: return ENFILE; + case ERROR_HANDLE_DISK_FULL: return ENOSPC; + case ERROR_NOT_SUPPORTED: return ENODEV; + case ERROR_REM_NOT_LIST: return EBUSY; + case ERROR_DUP_NAME: return EEXIST; + case ERROR_BAD_NETPATH: return ENOENT; + case ERROR_NETWORK_BUSY: return EBUSY; + case ERROR_DEV_NOT_EXIST: return ENODEV; + case ERROR_TOO_MANY_CMDS: return EAGAIN; + case ERROR_ADAP_HDW_ERR: return EIO; + case ERROR_BAD_NET_RESP: return EIO; + case ERROR_UNEXP_NET_ERR: return EIO; + case ERROR_NETNAME_DELETED: return ENOENT; + case ERROR_NETWORK_ACCESS_DENIED: return EACCES; + case ERROR_BAD_DEV_TYPE: return ENODEV; + case ERROR_BAD_NET_NAME: return ENOENT; + case ERROR_TOO_MANY_NAMES: return ENFILE; + case ERROR_TOO_MANY_SESS: return EIO; + case ERROR_SHARING_PAUSED: return EAGAIN; + case ERROR_REDIR_PAUSED: return EAGAIN; + case ERROR_FILE_EXISTS: return EEXIST; + case ERROR_CANNOT_MAKE: return ENOSPC; + case ERROR_OUT_OF_STRUCTURES: return ENFILE; + case ERROR_ALREADY_ASSIGNED: return EEXIST; + case ERROR_INVALID_PASSWORD: return EPERM; + case ERROR_NET_WRITE_FAULT: return EIO; + case ERROR_NO_PROC_SLOTS: return EAGAIN; + case ERROR_DISK_CHANGE: return EXDEV; + case ERROR_BROKEN_PIPE: return EPIPE; + case ERROR_OPEN_FAILED: return ENOENT; + case ERROR_DISK_FULL: return ENOSPC; + case ERROR_NO_MORE_SEARCH_HANDLES: return EMFILE; + case ERROR_INVALID_TARGET_HANDLE: return EBADF; + case ERROR_INVALID_NAME: return ENOENT; + case ERROR_PROC_NOT_FOUND: return ESRCH; + case ERROR_WAIT_NO_CHILDREN: return ECHILD; + case ERROR_CHILD_NOT_COMPLETE: return ECHILD; + case ERROR_DIRECT_ACCESS_HANDLE: return EBADF; + case ERROR_SEEK_ON_DEVICE: return ESPIPE; + case ERROR_BUSY_DRIVE: return EAGAIN; + case ERROR_DIR_NOT_EMPTY: return EEXIST; + case ERROR_NOT_LOCKED: return EACCES; + case ERROR_BAD_PATHNAME: return ENOENT; + case ERROR_LOCK_FAILED: return EACCES; + case ERROR_ALREADY_EXISTS: return EEXIST; + case ERROR_FILENAME_EXCED_RANGE: return ENAMETOOLONG; + case ERROR_BAD_PIPE: return EPIPE; + case ERROR_PIPE_BUSY: return EAGAIN; + case ERROR_PIPE_NOT_CONNECTED: return EPIPE; + case ERROR_DIRECTORY: return ENOTDIR; + } + return EINVAL; +} + +static int JimPipe(fdtype pipefd[2]) +{ + if (CreatePipe(&pipefd[0], &pipefd[1], NULL, 0)) { + return 0; + } + return -1; +} + +static fdtype JimDupFd(fdtype infd) +{ + fdtype dupfd; + pidtype pid = GetCurrentProcess(); + + if (DuplicateHandle(pid, infd, pid, &dupfd, 0, TRUE, DUPLICATE_SAME_ACCESS)) { + return dupfd; + } + return JIM_BAD_FD; +} + +static int JimRewindFd(fdtype fd) +{ + return SetFilePointer(fd, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER ? -1 : 0; +} + +#if 0 +static int JimReadFd(fdtype fd, char *buffer, size_t len) +{ + DWORD num; + + if (ReadFile(fd, buffer, len, &num, NULL)) { + return num; + } + if (GetLastError() == ERROR_HANDLE_EOF || GetLastError() == ERROR_BROKEN_PIPE) { + return 0; + } + return -1; +} +#endif + +static FILE *JimFdOpenForRead(fdtype fd) +{ + return _fdopen(_open_osfhandle((int)fd, _O_RDONLY | _O_TEXT), "r"); +} + +static fdtype JimFileno(FILE *fh) +{ + return (fdtype)_get_osfhandle(_fileno(fh)); +} + +static fdtype JimOpenForRead(const char *filename) +{ + return CreateFile(filename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, + JimStdSecAttrs(), OPEN_EXISTING, 0, NULL); +} + +static fdtype JimOpenForWrite(const char *filename, int append) +{ + return CreateFile(filename, append ? FILE_APPEND_DATA : GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + JimStdSecAttrs(), append ? OPEN_ALWAYS : CREATE_ALWAYS, 0, (HANDLE) NULL); +} + +static FILE *JimFdOpenForWrite(fdtype fd) +{ + return _fdopen(_open_osfhandle((int)fd, _O_TEXT), "w"); +} + +static pidtype JimWaitPid(pidtype pid, int *status, int nohang) +{ + DWORD ret = WaitForSingleObject(pid, nohang ? 0 : INFINITE); + if (ret == WAIT_TIMEOUT || ret == WAIT_FAILED) { + + return JIM_BAD_PID; + } + GetExitCodeProcess(pid, &ret); + *status = ret; + CloseHandle(pid); + return pid; +} + +static HANDLE JimCreateTemp(Jim_Interp *interp, const char *contents, int len) +{ + char name[MAX_PATH]; + HANDLE handle; + + if (!GetTempPath(MAX_PATH, name) || !GetTempFileName(name, "JIM", 0, name)) { + return JIM_BAD_FD; + } + + handle = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, JimStdSecAttrs(), + CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, + NULL); + + if (handle == INVALID_HANDLE_VALUE) { + goto error; + } + + if (contents != NULL) { + + FILE *fh = JimFdOpenForWrite(JimDupFd(handle)); + if (fh == NULL) { + goto error; + } + + if (fwrite(contents, len, 1, fh) != 1) { + fclose(fh); + goto error; + } + fseek(fh, 0, SEEK_SET); + fclose(fh); + } + return handle; + + error: + Jim_SetResultErrno(interp, "failed to create temp file"); + CloseHandle(handle); + DeleteFile(name); + return JIM_BAD_FD; +} + +static int +JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH]) +{ + int i; + static char extensions[][5] = {".exe", "", ".bat"}; + + for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) { + lstrcpyn(fullPath, originalName, MAX_PATH - 5); + lstrcat(fullPath, extensions[i]); + + if (SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, NULL) == 0) { + continue; + } + if (GetFileAttributes(fullPath) & FILE_ATTRIBUTE_DIRECTORY) { + continue; + } + return 0; + } + + return -1; +} + +static char **JimSaveEnv(char **env) +{ + return env; +} + +static void JimRestoreEnv(char **env) +{ + JimFreeEnv(env, Jim_GetEnviron()); +} + +static Jim_Obj * +JimWinBuildCommandLine(Jim_Interp *interp, char **argv) +{ + char *start, *special; + int quote, i; + + Jim_Obj *strObj = Jim_NewStringObj(interp, "", 0); + + for (i = 0; argv[i]; i++) { + if (i > 0) { + Jim_AppendString(interp, strObj, " ", 1); + } + + if (argv[i][0] == '\0') { + quote = 1; + } + else { + quote = 0; + for (start = argv[i]; *start != '\0'; start++) { + if (isspace(UCHAR(*start))) { + quote = 1; + break; + } + } + } + if (quote) { + Jim_AppendString(interp, strObj, "\"" , 1); + } + + start = argv[i]; + for (special = argv[i]; ; ) { + if ((*special == '\\') && (special[1] == '\\' || + special[1] == '"' || (quote && special[1] == '\0'))) { + Jim_AppendString(interp, strObj, start, special - start); + start = special; + while (1) { + special++; + if (*special == '"' || (quote && *special == '\0')) { + + Jim_AppendString(interp, strObj, start, special - start); + break; + } + if (*special != '\\') { + break; + } + } + Jim_AppendString(interp, strObj, start, special - start); + start = special; + } + if (*special == '"') { + if (special == start) { + Jim_AppendString(interp, strObj, "\"", 1); + } + else { + Jim_AppendString(interp, strObj, start, special - start); + } + Jim_AppendString(interp, strObj, "\\\"", 2); + start = special + 1; + } + if (*special == '\0') { + break; + } + special++; + } + Jim_AppendString(interp, strObj, start, special - start); + if (quote) { + Jim_AppendString(interp, strObj, "\"", 1); + } + } + return strObj; +} + +static pidtype +JimStartWinProcess(Jim_Interp *interp, char **argv, char *env, fdtype inputId, fdtype outputId, fdtype errorId) +{ + STARTUPINFO startInfo; + PROCESS_INFORMATION procInfo; + HANDLE hProcess, h; + char execPath[MAX_PATH]; + pidtype pid = JIM_BAD_PID; + Jim_Obj *cmdLineObj; + + if (JimWinFindExecutable(argv[0], execPath) < 0) { + return JIM_BAD_PID; + } + argv[0] = execPath; + + hProcess = GetCurrentProcess(); + cmdLineObj = JimWinBuildCommandLine(interp, argv); + + + ZeroMemory(&startInfo, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); + startInfo.dwFlags = STARTF_USESTDHANDLES; + startInfo.hStdInput = INVALID_HANDLE_VALUE; + startInfo.hStdOutput= INVALID_HANDLE_VALUE; + startInfo.hStdError = INVALID_HANDLE_VALUE; + + if (inputId == JIM_BAD_FD) { + if (CreatePipe(&startInfo.hStdInput, &h, JimStdSecAttrs(), 0) != FALSE) { + CloseHandle(h); + } + } else { + DuplicateHandle(hProcess, inputId, hProcess, &startInfo.hStdInput, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdInput == JIM_BAD_FD) { + goto end; + } + + if (outputId == JIM_BAD_FD) { + startInfo.hStdOutput = CreateFile("NUL:", GENERIC_WRITE, 0, + JimStdSecAttrs(), OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + DuplicateHandle(hProcess, outputId, hProcess, &startInfo.hStdOutput, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdOutput == JIM_BAD_FD) { + goto end; + } + + if (errorId == JIM_BAD_FD) { + + startInfo.hStdError = CreateFile("NUL:", GENERIC_WRITE, 0, + JimStdSecAttrs(), OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + } else { + DuplicateHandle(hProcess, errorId, hProcess, &startInfo.hStdError, + 0, TRUE, DUPLICATE_SAME_ACCESS); + } + if (startInfo.hStdError == JIM_BAD_FD) { + goto end; + } + + if (!CreateProcess(NULL, (char *)Jim_String(cmdLineObj), NULL, NULL, TRUE, + 0, env, NULL, &startInfo, &procInfo)) { + goto end; + } + + + WaitForInputIdle(procInfo.hProcess, 5000); + CloseHandle(procInfo.hThread); + + pid = procInfo.hProcess; + + end: + Jim_FreeNewObj(interp, cmdLineObj); + if (startInfo.hStdInput != JIM_BAD_FD) { + CloseHandle(startInfo.hStdInput); + } + if (startInfo.hStdOutput != JIM_BAD_FD) { + CloseHandle(startInfo.hStdOutput); + } + if (startInfo.hStdError != JIM_BAD_FD) { + CloseHandle(startInfo.hStdError); + } + return pid; +} +#else + +static int JimOpenForWrite(const char *filename, int append) +{ + return open(filename, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0666); +} + +static int JimRewindFd(int fd) +{ + return lseek(fd, 0L, SEEK_SET); +} + +static int JimCreateTemp(Jim_Interp *interp, const char *contents, int len) +{ + int fd = Jim_MakeTempFile(interp, NULL); + + if (fd != JIM_BAD_FD) { + unlink(Jim_String(Jim_GetResult(interp))); + if (contents) { + if (write(fd, contents, len) != len) { + Jim_SetResultErrno(interp, "couldn't write temp file"); + close(fd); + return -1; + } + lseek(fd, 0L, SEEK_SET); + } + } + return fd; +} + +static char **JimSaveEnv(char **env) +{ + char **saveenv = Jim_GetEnviron(); + Jim_SetEnviron(env); + return saveenv; +} + +static void JimRestoreEnv(char **env) +{ + JimFreeEnv(Jim_GetEnviron(), env); + Jim_SetEnviron(env); +} +#endif +#endif + + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 500 +#endif + +#include +#include +#include +#include + + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +static int clock_cmd_format(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + + char buf[100]; + time_t t; + long seconds; + + const char *format = "%a %b %d %H:%M:%S %Z %Y"; + + if (argc == 2 || (argc == 3 && !Jim_CompareStringImmediate(interp, argv[1], "-format"))) { + return -1; + } + + if (argc == 3) { + format = Jim_String(argv[2]); + } + + if (Jim_GetLong(interp, argv[0], &seconds) != JIM_OK) { + return JIM_ERR; + } + t = seconds; + + if (strftime(buf, sizeof(buf), format, localtime(&t)) == 0) { + Jim_SetResultString(interp, "format string too long", -1); + return JIM_ERR; + } + + Jim_SetResultString(interp, buf, -1); + + return JIM_OK; +} + +#ifdef HAVE_STRPTIME +static int clock_cmd_scan(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char *pt; + struct tm tm; + time_t now = time(0); + + if (!Jim_CompareStringImmediate(interp, argv[1], "-format")) { + return -1; + } + + + localtime_r(&now, &tm); + + pt = strptime(Jim_String(argv[0]), Jim_String(argv[2]), &tm); + if (pt == 0 || *pt != 0) { + Jim_SetResultString(interp, "Failed to parse time according to format", -1); + return JIM_ERR; + } + + + Jim_SetResultInt(interp, mktime(&tm)); + + return JIM_OK; +} +#endif + +static int clock_cmd_seconds(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_SetResultInt(interp, time(NULL)); + + return JIM_OK; +} + +static int clock_cmd_micros(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec); + + return JIM_OK; +} + +static int clock_cmd_millis(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + Jim_SetResultInt(interp, (jim_wide) tv.tv_sec * 1000 + tv.tv_usec / 1000); + + return JIM_OK; +} + +static const jim_subcmd_type clock_command_table[] = { + { "seconds", + NULL, + clock_cmd_seconds, + 0, + 0, + + }, + { "clicks", + NULL, + clock_cmd_micros, + 0, + 0, + + }, + { "microseconds", + NULL, + clock_cmd_micros, + 0, + 0, + + }, + { "milliseconds", + NULL, + clock_cmd_millis, + 0, + 0, + + }, + { "format", + "seconds ?-format format?", + clock_cmd_format, + 1, + 3, + + }, +#ifdef HAVE_STRPTIME + { "scan", + "str -format format", + clock_cmd_scan, + 3, + 3, + + }, +#endif + { NULL } +}; + +int Jim_clockInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "clock", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL); + return JIM_OK; +} + +#include +#include +#include +#include +#include + + +static int array_cmd_exists(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + + Jim_SetResultInt(interp, Jim_GetVariable(interp, argv[0], 0) != 0); + return JIM_OK; +} + +static int array_cmd_get(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + Jim_Obj *patternObj; + + if (!objPtr) { + return JIM_OK; + } + + patternObj = (argc == 1) ? NULL : argv[1]; + + + if (patternObj == NULL || Jim_CompareStringImmediate(interp, patternObj, "*")) { + if (Jim_IsList(objPtr) && Jim_ListLength(interp, objPtr) % 2 == 0) { + + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } + + + return Jim_DictValues(interp, objPtr, patternObj); +} + +static int array_cmd_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (!objPtr) { + return JIM_OK; + } + + return Jim_DictKeys(interp, objPtr, argc == 1 ? NULL : argv[1]); +} + +static int array_cmd_unset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *resultObj; + Jim_Obj *objPtr; + Jim_Obj **dictValuesObj; + + if (argc == 1 || Jim_CompareStringImmediate(interp, argv[1], "*")) { + + Jim_UnsetVariable(interp, argv[0], JIM_NONE); + return JIM_OK; + } + + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + + if (objPtr == NULL) { + + return JIM_OK; + } + + if (Jim_DictPairs(interp, objPtr, &dictValuesObj, &len) != JIM_OK) { + return JIM_ERR; + } + + + resultObj = Jim_NewDictObj(interp, NULL, 0); + + for (i = 0; i < len; i += 2) { + if (!Jim_StringMatchObj(interp, argv[1], dictValuesObj[i], 0)) { + Jim_DictAddElement(interp, resultObj, dictValuesObj[i], dictValuesObj[i + 1]); + } + } + Jim_Free(dictValuesObj); + + Jim_SetVariable(interp, argv[0], resultObj); + return JIM_OK; +} + +static int array_cmd_size(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int len = 0; + + + objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + if (objPtr) { + len = Jim_DictSize(interp, objPtr); + if (len < 0) { + return JIM_ERR; + } + } + + Jim_SetResultInt(interp, len); + + return JIM_OK; +} + +static int array_cmd_stat(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[0], JIM_NONE); + if (objPtr) { + return Jim_DictInfo(interp, objPtr); + } + Jim_SetResultFormatted(interp, "\"%#s\" isn't an array", argv[0], NULL); + return JIM_ERR; +} + +static int array_cmd_set(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + int len; + Jim_Obj *listObj = argv[1]; + Jim_Obj *dictObj; + + len = Jim_ListLength(interp, listObj); + if (len % 2) { + Jim_SetResultString(interp, "list must have an even number of elements", -1); + return JIM_ERR; + } + + dictObj = Jim_GetVariable(interp, argv[0], JIM_UNSHARED); + if (!dictObj) { + + return Jim_SetVariable(interp, argv[0], listObj); + } + else if (Jim_DictSize(interp, dictObj) < 0) { + return JIM_ERR; + } + + if (Jim_IsShared(dictObj)) { + dictObj = Jim_DuplicateObj(interp, dictObj); + } + + for (i = 0; i < len; i += 2) { + Jim_Obj *nameObj; + Jim_Obj *valueObj; + + Jim_ListIndex(interp, listObj, i, &nameObj, JIM_NONE); + Jim_ListIndex(interp, listObj, i + 1, &valueObj, JIM_NONE); + + Jim_DictAddElement(interp, dictObj, nameObj, valueObj); + } + return Jim_SetVariable(interp, argv[0], dictObj); +} + +static const jim_subcmd_type array_command_table[] = { + { "exists", + "arrayName", + array_cmd_exists, + 1, + 1, + + }, + { "get", + "arrayName ?pattern?", + array_cmd_get, + 1, + 2, + + }, + { "names", + "arrayName ?pattern?", + array_cmd_names, + 1, + 2, + + }, + { "set", + "arrayName list", + array_cmd_set, + 2, + 2, + + }, + { "size", + "arrayName", + array_cmd_size, + 1, + 1, + + }, + { "stat", + "arrayName", + array_cmd_stat, + 1, + 1, + + }, + { "unset", + "arrayName ?pattern?", + array_cmd_unset, + 1, + 2, + + }, + { NULL + } +}; + +int Jim_arrayInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "array", "1.0", JIM_ERRMSG)) + return JIM_ERR; + + Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL); + return JIM_OK; +} +int Jim_InitStaticExtensions(Jim_Interp *interp) +{ +extern int Jim_bootstrapInit(Jim_Interp *); +extern int Jim_aioInit(Jim_Interp *); +extern int Jim_readdirInit(Jim_Interp *); +extern int Jim_globInit(Jim_Interp *); +extern int Jim_regexpInit(Jim_Interp *); +extern int Jim_fileInit(Jim_Interp *); +extern int Jim_execInit(Jim_Interp *); +extern int Jim_clockInit(Jim_Interp *); +extern int Jim_arrayInit(Jim_Interp *); +extern int Jim_stdlibInit(Jim_Interp *); +extern int Jim_tclcompatInit(Jim_Interp *); +Jim_bootstrapInit(interp); +Jim_aioInit(interp); +Jim_readdirInit(interp); +Jim_globInit(interp); +Jim_regexpInit(interp); +Jim_fileInit(interp); +Jim_execInit(interp); +Jim_clockInit(interp); +Jim_arrayInit(interp); +Jim_stdlibInit(interp); +Jim_tclcompatInit(interp); +return JIM_OK; +} +#define JIM_OPTIMIZATION + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_BACKTRACE +#include +#endif +#ifdef HAVE_CRT_EXTERNS_H +#include +#endif + + +#include + + + + + +#ifndef TCL_LIBRARY +#define TCL_LIBRARY "." +#endif +#ifndef TCL_PLATFORM_OS +#define TCL_PLATFORM_OS "unknown" +#endif +#ifndef TCL_PLATFORM_PLATFORM +#define TCL_PLATFORM_PLATFORM "unknown" +#endif +#ifndef TCL_PLATFORM_PATH_SEPARATOR +#define TCL_PLATFORM_PATH_SEPARATOR ":" +#endif + + + + + + + +#ifdef JIM_MAINTAINER +#define JIM_DEBUG_COMMAND +#define JIM_DEBUG_PANIC +#endif + + + +#define JIM_INTEGER_SPACE 24 + +const char *jim_tt_name(int type); + +#ifdef JIM_DEBUG_PANIC +static void JimPanicDump(int fail_condition, const char *fmt, ...); +#define JimPanic(X) JimPanicDump X +#else +#define JimPanic(X) +#endif + + +static char JimEmptyStringRep[] = ""; + +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action); +static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int listindex, Jim_Obj *newObjPtr, + int flags); +static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands); +static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr); +static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr); +static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len); +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name); +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv); +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr); +static int JimSign(jim_wide w); +static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr); +static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen); +static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len); + + + +#define JimWideValue(objPtr) (objPtr)->internalRep.wideValue + +#define JimObjTypeName(O) ((O)->typePtr ? (O)->typePtr->name : "none") + +static int utf8_tounicode_case(const char *s, int *uc, int upper) +{ + int l = utf8_tounicode(s, uc); + if (upper) { + *uc = utf8_upper(*uc); + } + return l; +} + + +#define JIM_CHARSET_SCAN 2 +#define JIM_CHARSET_GLOB 0 + +static const char *JimCharsetMatch(const char *pattern, int c, int flags) +{ + int not = 0; + int pchar; + int match = 0; + int nocase = 0; + + if (flags & JIM_NOCASE) { + nocase++; + c = utf8_upper(c); + } + + if (flags & JIM_CHARSET_SCAN) { + if (*pattern == '^') { + not++; + pattern++; + } + + + if (*pattern == ']') { + goto first; + } + } + + while (*pattern && *pattern != ']') { + + if (pattern[0] == '\\') { +first: + pattern += utf8_tounicode_case(pattern, &pchar, nocase); + } + else { + + int start; + int end; + + pattern += utf8_tounicode_case(pattern, &start, nocase); + if (pattern[0] == '-' && pattern[1]) { + + pattern += utf8_tounicode(pattern, &pchar); + pattern += utf8_tounicode_case(pattern, &end, nocase); + + + if ((c >= start && c <= end) || (c >= end && c <= start)) { + match = 1; + } + continue; + } + pchar = start; + } + + if (pchar == c) { + match = 1; + } + } + if (not) { + match = !match; + } + + return match ? pattern : NULL; +} + + + +static int JimGlobMatch(const char *pattern, const char *string, int nocase) +{ + int c; + int pchar; + while (*pattern) { + switch (pattern[0]) { + case '*': + while (pattern[1] == '*') { + pattern++; + } + pattern++; + if (!pattern[0]) { + return 1; + } + while (*string) { + + if (JimGlobMatch(pattern, string, nocase)) + return 1; + string += utf8_tounicode(string, &c); + } + return 0; + + case '?': + string += utf8_tounicode(string, &c); + break; + + case '[': { + string += utf8_tounicode(string, &c); + pattern = JimCharsetMatch(pattern + 1, c, nocase ? JIM_NOCASE : 0); + if (!pattern) { + return 0; + } + if (!*pattern) { + + continue; + } + break; + } + case '\\': + if (pattern[1]) { + pattern++; + } + + default: + string += utf8_tounicode_case(string, &c, nocase); + utf8_tounicode_case(pattern, &pchar, nocase); + if (pchar != c) { + return 0; + } + break; + } + pattern += utf8_tounicode_case(pattern, &pchar, nocase); + if (!*string) { + while (*pattern == '*') { + pattern++; + } + break; + } + } + if (!*pattern && !*string) { + return 1; + } + return 0; +} + +static int JimStringCompare(const char *s1, int l1, const char *s2, int l2) +{ + if (l1 < l2) { + return memcmp(s1, s2, l1) <= 0 ? -1 : 1; + } + else if (l2 < l1) { + return memcmp(s1, s2, l2) >= 0 ? 1 : -1; + } + else { + return JimSign(memcmp(s1, s2, l1)); + } +} + +static int JimStringCompareLen(const char *s1, const char *s2, int maxchars, int nocase) +{ + while (*s1 && *s2 && maxchars) { + int c1, c2; + s1 += utf8_tounicode_case(s1, &c1, nocase); + s2 += utf8_tounicode_case(s2, &c2, nocase); + if (c1 != c2) { + return JimSign(c1 - c2); + } + maxchars--; + } + if (!maxchars) { + return 0; + } + + if (*s1) { + return 1; + } + if (*s2) { + return -1; + } + return 0; +} + +static int JimStringFirst(const char *s1, int l1, const char *s2, int l2, int idx) +{ + int i; + int l1bytelen; + + if (!l1 || !l2 || l1 > l2) { + return -1; + } + if (idx < 0) + idx = 0; + s2 += utf8_index(s2, idx); + + l1bytelen = utf8_index(s1, l1); + + for (i = idx; i <= l2 - l1; i++) { + int c; + if (memcmp(s2, s1, l1bytelen) == 0) { + return i; + } + s2 += utf8_tounicode(s2, &c); + } + return -1; +} + +static int JimStringLast(const char *s1, int l1, const char *s2, int l2) +{ + const char *p; + + if (!l1 || !l2 || l1 > l2) + return -1; + + + for (p = s2 + l2 - 1; p != s2 - 1; p--) { + if (*p == *s1 && memcmp(s1, p, l1) == 0) { + return p - s2; + } + } + return -1; +} + +#ifdef JIM_UTF8 +static int JimStringLastUtf8(const char *s1, int l1, const char *s2, int l2) +{ + int n = JimStringLast(s1, utf8_index(s1, l1), s2, utf8_index(s2, l2)); + if (n > 0) { + n = utf8_strlen(s2, n); + } + return n; +} +#endif + +static int JimCheckConversion(const char *str, const char *endptr) +{ + if (str[0] == '\0' || str == endptr) { + return JIM_ERR; + } + + if (endptr[0] != '\0') { + while (*endptr) { + if (!isspace(UCHAR(*endptr))) { + return JIM_ERR; + } + endptr++; + } + } + return JIM_OK; +} + +static int JimNumberBase(const char *str, int *base, int *sign) +{ + int i = 0; + + *base = 10; + + while (isspace(UCHAR(str[i]))) { + i++; + } + + if (str[i] == '-') { + *sign = -1; + i++; + } + else { + if (str[i] == '+') { + i++; + } + *sign = 1; + } + + if (str[i] != '0') { + + return 0; + } + + + switch (str[i + 1]) { + case 'x': case 'X': *base = 16; break; + case 'o': case 'O': *base = 8; break; + case 'b': case 'B': *base = 2; break; + default: return 0; + } + i += 2; + + if (str[i] != '-' && str[i] != '+' && !isspace(UCHAR(str[i]))) { + + return i; + } + + *base = 10; + return 0; +} + +static long jim_strtol(const char *str, char **endptr) +{ + int sign; + int base; + int i = JimNumberBase(str, &base, &sign); + + if (base != 10) { + long value = strtol(str + i, endptr, base); + if (endptr == NULL || *endptr != str + i) { + return value * sign; + } + } + + + return strtol(str, endptr, 10); +} + + +static jim_wide jim_strtoull(const char *str, char **endptr) +{ +#ifdef HAVE_LONG_LONG + int sign; + int base; + int i = JimNumberBase(str, &base, &sign); + + if (base != 10) { + jim_wide value = strtoull(str + i, endptr, base); + if (endptr == NULL || *endptr != str + i) { + return value * sign; + } + } + + + return strtoull(str, endptr, 10); +#else + return (unsigned long)jim_strtol(str, endptr); +#endif +} + +int Jim_StringToWide(const char *str, jim_wide * widePtr, int base) +{ + char *endptr; + + if (base) { + *widePtr = strtoull(str, &endptr, base); + } + else { + *widePtr = jim_strtoull(str, &endptr); + } + + return JimCheckConversion(str, endptr); +} + +int Jim_StringToDouble(const char *str, double *doublePtr) +{ + char *endptr; + + + errno = 0; + + *doublePtr = strtod(str, &endptr); + + return JimCheckConversion(str, endptr); +} + +static jim_wide JimPowWide(jim_wide b, jim_wide e) +{ + jim_wide i, res = 1; + + if ((b == 0 && e != 0) || (e < 0)) + return 0; + for (i = 0; i < e; i++) { + res *= b; + } + return res; +} + +#ifdef JIM_DEBUG_PANIC +static void JimPanicDump(int condition, const char *fmt, ...) +{ + va_list ap; + + if (!condition) { + return; + } + + va_start(ap, fmt); + + fprintf(stderr, "\nJIM INTERPRETER PANIC: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n\n"); + va_end(ap); + +#ifdef HAVE_BACKTRACE + { + void *array[40]; + int size, i; + char **strings; + + size = backtrace(array, 40); + strings = backtrace_symbols(array, size); + for (i = 0; i < size; i++) + fprintf(stderr, "[backtrace] %s\n", strings[i]); + fprintf(stderr, "[backtrace] Include the above lines and the output\n"); + fprintf(stderr, "[backtrace] of 'nm ' in the bug report.\n"); + } +#endif + + exit(1); +} +#endif + + +void *Jim_Alloc(int size) +{ + return size ? malloc(size) : NULL; +} + +void Jim_Free(void *ptr) +{ + free(ptr); +} + +void *Jim_Realloc(void *ptr, int size) +{ + return realloc(ptr, size); +} + +char *Jim_StrDup(const char *s) +{ + return strdup(s); +} + +char *Jim_StrDupLen(const char *s, int l) +{ + char *copy = Jim_Alloc(l + 1); + + memcpy(copy, s, l + 1); + copy[l] = 0; + return copy; +} + + + +static jim_wide JimClock(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + return (jim_wide) tv.tv_sec * 1000000 + tv.tv_usec; +} + + + +static void JimExpandHashTableIfNeeded(Jim_HashTable *ht); +static unsigned int JimHashTableNextPower(unsigned int size); +static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace); + + + + +unsigned int Jim_IntHashFunction(unsigned int key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} + +unsigned int Jim_GenHashFunction(const unsigned char *buf, int len) +{ + unsigned int h = 0; + + while (len--) + h += (h << 3) + *buf++; + return h; +} + + + + +static void JimResetHashTable(Jim_HashTable *ht) +{ + ht->table = NULL; + ht->size = 0; + ht->sizemask = 0; + ht->used = 0; + ht->collisions = 0; +#ifdef JIM_RANDOMISE_HASH + ht->uniq = (rand() ^ time(NULL) ^ clock()); +#else + ht->uniq = 0; +#endif +} + +static void JimInitHashTableIterator(Jim_HashTable *ht, Jim_HashTableIterator *iter) +{ + iter->ht = ht; + iter->index = -1; + iter->entry = NULL; + iter->nextEntry = NULL; +} + + +int Jim_InitHashTable(Jim_HashTable *ht, const Jim_HashTableType *type, void *privDataPtr) +{ + JimResetHashTable(ht); + ht->type = type; + ht->privdata = privDataPtr; + return JIM_OK; +} + +void Jim_ResizeHashTable(Jim_HashTable *ht) +{ + int minimal = ht->used; + + if (minimal < JIM_HT_INITIAL_SIZE) + minimal = JIM_HT_INITIAL_SIZE; + Jim_ExpandHashTable(ht, minimal); +} + + +void Jim_ExpandHashTable(Jim_HashTable *ht, unsigned int size) +{ + Jim_HashTable n; + unsigned int realsize = JimHashTableNextPower(size), i; + + if (size <= ht->used) + return; + + Jim_InitHashTable(&n, ht->type, ht->privdata); + n.size = realsize; + n.sizemask = realsize - 1; + n.table = Jim_Alloc(realsize * sizeof(Jim_HashEntry *)); + + n.uniq = ht->uniq; + + + memset(n.table, 0, realsize * sizeof(Jim_HashEntry *)); + + n.used = ht->used; + for (i = 0; ht->used > 0; i++) { + Jim_HashEntry *he, *nextHe; + + if (ht->table[i] == NULL) + continue; + + + he = ht->table[i]; + while (he) { + unsigned int h; + + nextHe = he->next; + + h = Jim_HashKey(ht, he->key) & n.sizemask; + he->next = n.table[h]; + n.table[h] = he; + ht->used--; + + he = nextHe; + } + } + assert(ht->used == 0); + Jim_Free(ht->table); + + + *ht = n; +} + + +int Jim_AddHashEntry(Jim_HashTable *ht, const void *key, void *val) +{ + Jim_HashEntry *entry; + + entry = JimInsertHashEntry(ht, key, 0); + if (entry == NULL) + return JIM_ERR; + + + Jim_SetHashKey(ht, entry, key); + Jim_SetHashVal(ht, entry, val); + return JIM_OK; +} + + +int Jim_ReplaceHashEntry(Jim_HashTable *ht, const void *key, void *val) +{ + int existed; + Jim_HashEntry *entry; + + entry = JimInsertHashEntry(ht, key, 1); + if (entry->key) { + if (ht->type->valDestructor && ht->type->valDup) { + void *newval = ht->type->valDup(ht->privdata, val); + ht->type->valDestructor(ht->privdata, entry->u.val); + entry->u.val = newval; + } + else { + Jim_FreeEntryVal(ht, entry); + Jim_SetHashVal(ht, entry, val); + } + existed = 1; + } + else { + + Jim_SetHashKey(ht, entry, key); + Jim_SetHashVal(ht, entry, val); + existed = 0; + } + + return existed; +} + + +int Jim_DeleteHashEntry(Jim_HashTable *ht, const void *key) +{ + unsigned int h; + Jim_HashEntry *he, *prevHe; + + if (ht->used == 0) + return JIM_ERR; + h = Jim_HashKey(ht, key) & ht->sizemask; + he = ht->table[h]; + + prevHe = NULL; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) { + + if (prevHe) + prevHe->next = he->next; + else + ht->table[h] = he->next; + Jim_FreeEntryKey(ht, he); + Jim_FreeEntryVal(ht, he); + Jim_Free(he); + ht->used--; + return JIM_OK; + } + prevHe = he; + he = he->next; + } + return JIM_ERR; +} + + +int Jim_FreeHashTable(Jim_HashTable *ht) +{ + unsigned int i; + + + for (i = 0; ht->used > 0; i++) { + Jim_HashEntry *he, *nextHe; + + if ((he = ht->table[i]) == NULL) + continue; + while (he) { + nextHe = he->next; + Jim_FreeEntryKey(ht, he); + Jim_FreeEntryVal(ht, he); + Jim_Free(he); + ht->used--; + he = nextHe; + } + } + + Jim_Free(ht->table); + + JimResetHashTable(ht); + return JIM_OK; +} + +Jim_HashEntry *Jim_FindHashEntry(Jim_HashTable *ht, const void *key) +{ + Jim_HashEntry *he; + unsigned int h; + + if (ht->used == 0) + return NULL; + h = Jim_HashKey(ht, key) & ht->sizemask; + he = ht->table[h]; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) + return he; + he = he->next; + } + return NULL; +} + +Jim_HashTableIterator *Jim_GetHashTableIterator(Jim_HashTable *ht) +{ + Jim_HashTableIterator *iter = Jim_Alloc(sizeof(*iter)); + JimInitHashTableIterator(ht, iter); + return iter; +} + +Jim_HashEntry *Jim_NextHashEntry(Jim_HashTableIterator *iter) +{ + while (1) { + if (iter->entry == NULL) { + iter->index++; + if (iter->index >= (signed)iter->ht->size) + break; + iter->entry = iter->ht->table[iter->index]; + } + else { + iter->entry = iter->nextEntry; + } + if (iter->entry) { + iter->nextEntry = iter->entry->next; + return iter->entry; + } + } + return NULL; +} + + + + +static void JimExpandHashTableIfNeeded(Jim_HashTable *ht) +{ + if (ht->size == 0) + Jim_ExpandHashTable(ht, JIM_HT_INITIAL_SIZE); + if (ht->size == ht->used) + Jim_ExpandHashTable(ht, ht->size * 2); +} + + +static unsigned int JimHashTableNextPower(unsigned int size) +{ + unsigned int i = JIM_HT_INITIAL_SIZE; + + if (size >= 2147483648U) + return 2147483648U; + while (1) { + if (i >= size) + return i; + i *= 2; + } +} + +static Jim_HashEntry *JimInsertHashEntry(Jim_HashTable *ht, const void *key, int replace) +{ + unsigned int h; + Jim_HashEntry *he; + + + JimExpandHashTableIfNeeded(ht); + + + h = Jim_HashKey(ht, key) & ht->sizemask; + + he = ht->table[h]; + while (he) { + if (Jim_CompareHashKeys(ht, key, he->key)) + return replace ? he : NULL; + he = he->next; + } + + + he = Jim_Alloc(sizeof(*he)); + he->next = ht->table[h]; + ht->table[h] = he; + ht->used++; + he->key = NULL; + + return he; +} + + + +static unsigned int JimStringCopyHTHashFunction(const void *key) +{ + return Jim_GenHashFunction(key, strlen(key)); +} + +static void *JimStringCopyHTDup(void *privdata, const void *key) +{ + return Jim_StrDup(key); +} + +static int JimStringCopyHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + return strcmp(key1, key2) == 0; +} + +static void JimStringCopyHTKeyDestructor(void *privdata, void *key) +{ + Jim_Free(key); +} + +static const Jim_HashTableType JimPackageHashTableType = { + JimStringCopyHTHashFunction, + JimStringCopyHTDup, + NULL, + JimStringCopyHTKeyCompare, + JimStringCopyHTKeyDestructor, + NULL +}; + +typedef struct AssocDataValue +{ + Jim_InterpDeleteProc *delProc; + void *data; +} AssocDataValue; + +static void JimAssocDataHashTableValueDestructor(void *privdata, void *data) +{ + AssocDataValue *assocPtr = (AssocDataValue *) data; + + if (assocPtr->delProc != NULL) + assocPtr->delProc((Jim_Interp *)privdata, assocPtr->data); + Jim_Free(data); +} + +static const Jim_HashTableType JimAssocDataHashTableType = { + JimStringCopyHTHashFunction, + JimStringCopyHTDup, + NULL, + JimStringCopyHTKeyCompare, + JimStringCopyHTKeyDestructor, + JimAssocDataHashTableValueDestructor +}; + +void Jim_InitStack(Jim_Stack *stack) +{ + stack->len = 0; + stack->maxlen = 0; + stack->vector = NULL; +} + +void Jim_FreeStack(Jim_Stack *stack) +{ + Jim_Free(stack->vector); +} + +int Jim_StackLen(Jim_Stack *stack) +{ + return stack->len; +} + +void Jim_StackPush(Jim_Stack *stack, void *element) +{ + int neededLen = stack->len + 1; + + if (neededLen > stack->maxlen) { + stack->maxlen = neededLen < 20 ? 20 : neededLen * 2; + stack->vector = Jim_Realloc(stack->vector, sizeof(void *) * stack->maxlen); + } + stack->vector[stack->len] = element; + stack->len++; +} + +void *Jim_StackPop(Jim_Stack *stack) +{ + if (stack->len == 0) + return NULL; + stack->len--; + return stack->vector[stack->len]; +} + +void *Jim_StackPeek(Jim_Stack *stack) +{ + if (stack->len == 0) + return NULL; + return stack->vector[stack->len - 1]; +} + +void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr)) +{ + int i; + + for (i = 0; i < stack->len; i++) + freeFunc(stack->vector[i]); +} + + + +#define JIM_TT_NONE 0 +#define JIM_TT_STR 1 +#define JIM_TT_ESC 2 +#define JIM_TT_VAR 3 +#define JIM_TT_DICTSUGAR 4 +#define JIM_TT_CMD 5 + +#define JIM_TT_SEP 6 +#define JIM_TT_EOL 7 +#define JIM_TT_EOF 8 + +#define JIM_TT_LINE 9 +#define JIM_TT_WORD 10 + + +#define JIM_TT_SUBEXPR_START 11 +#define JIM_TT_SUBEXPR_END 12 +#define JIM_TT_SUBEXPR_COMMA 13 +#define JIM_TT_EXPR_INT 14 +#define JIM_TT_EXPR_DOUBLE 15 + +#define JIM_TT_EXPRSUGAR 16 + + +#define JIM_TT_EXPR_OP 20 + +#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF) + + +#define JIM_PS_DEF 0 +#define JIM_PS_QUOTE 1 +#define JIM_PS_DICTSUGAR 2 + +struct JimParseMissing { + int ch; + int line; +}; + +struct JimParserCtx +{ + const char *p; + int len; + int linenr; + const char *tstart; + const char *tend; + int tline; + int tt; + int eof; + int state; + int comment; + struct JimParseMissing missing; +}; + +static int JimParseScript(struct JimParserCtx *pc); +static int JimParseSep(struct JimParserCtx *pc); +static int JimParseEol(struct JimParserCtx *pc); +static int JimParseCmd(struct JimParserCtx *pc); +static int JimParseQuote(struct JimParserCtx *pc); +static int JimParseVar(struct JimParserCtx *pc); +static int JimParseBrace(struct JimParserCtx *pc); +static int JimParseStr(struct JimParserCtx *pc); +static int JimParseComment(struct JimParserCtx *pc); +static void JimParseSubCmd(struct JimParserCtx *pc); +static int JimParseSubQuote(struct JimParserCtx *pc); +static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc); + +static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int linenr) +{ + pc->p = prg; + pc->len = len; + pc->tstart = NULL; + pc->tend = NULL; + pc->tline = 0; + pc->tt = JIM_TT_NONE; + pc->eof = 0; + pc->state = JIM_PS_DEF; + pc->linenr = linenr; + pc->comment = 1; + pc->missing.ch = ' '; + pc->missing.line = linenr; +} + +static int JimParseScript(struct JimParserCtx *pc) +{ + while (1) { + if (!pc->len) { + pc->tstart = pc->p; + pc->tend = pc->p - 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*(pc->p)) { + case '\\': + if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) { + return JimParseSep(pc); + } + pc->comment = 0; + return JimParseStr(pc); + case ' ': + case '\t': + case '\r': + case '\f': + if (pc->state == JIM_PS_DEF) + return JimParseSep(pc); + pc->comment = 0; + return JimParseStr(pc); + case '\n': + case ';': + pc->comment = 1; + if (pc->state == JIM_PS_DEF) + return JimParseEol(pc); + return JimParseStr(pc); + case '[': + pc->comment = 0; + return JimParseCmd(pc); + case '$': + pc->comment = 0; + if (JimParseVar(pc) == JIM_ERR) { + + pc->tstart = pc->tend = pc->p++; + pc->len--; + pc->tt = JIM_TT_ESC; + } + return JIM_OK; + case '#': + if (pc->comment) { + JimParseComment(pc); + continue; + } + return JimParseStr(pc); + default: + pc->comment = 0; + return JimParseStr(pc); + } + return JIM_OK; + } +} + +static int JimParseSep(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (isspace(UCHAR(*pc->p)) || (*pc->p == '\\' && *(pc->p + 1) == '\n')) { + if (*pc->p == '\n') { + break; + } + if (*pc->p == '\\') { + pc->p++; + pc->len--; + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_SEP; + return JIM_OK; +} + +static int JimParseEol(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (isspace(UCHAR(*pc->p)) || *pc->p == ';') { + if (*pc->p == '\n') + pc->linenr++; + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_EOL; + return JIM_OK; +} + + +static void JimParseSubBrace(struct JimParserCtx *pc) +{ + int level = 1; + + + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + } + break; + + case '{': + level++; + break; + + case '}': + if (--level == 0) { + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return; + } + break; + + case '\n': + pc->linenr++; + break; + } + pc->p++; + pc->len--; + } + pc->missing.ch = '{'; + pc->missing.line = pc->tline; + pc->tend = pc->p - 1; +} + +static int JimParseSubQuote(struct JimParserCtx *pc) +{ + int tt = JIM_TT_STR; + int line = pc->tline; + + + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + tt = JIM_TT_ESC; + } + break; + + case '"': + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return tt; + + case '[': + JimParseSubCmd(pc); + tt = JIM_TT_ESC; + continue; + + case '\n': + pc->linenr++; + break; + + case '$': + tt = JIM_TT_ESC; + break; + } + pc->p++; + pc->len--; + } + pc->missing.ch = '"'; + pc->missing.line = line; + pc->tend = pc->p - 1; + return tt; +} + +static void JimParseSubCmd(struct JimParserCtx *pc) +{ + int level = 1; + int startofword = 1; + int line = pc->tline; + + + pc->p++; + pc->len--; + while (pc->len) { + switch (*pc->p) { + case '\\': + if (pc->len > 1) { + if (*++pc->p == '\n') { + pc->linenr++; + } + pc->len--; + } + break; + + case '[': + level++; + break; + + case ']': + if (--level == 0) { + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return; + } + break; + + case '"': + if (startofword) { + JimParseSubQuote(pc); + continue; + } + break; + + case '{': + JimParseSubBrace(pc); + startofword = 0; + continue; + + case '\n': + pc->linenr++; + break; + } + startofword = isspace(UCHAR(*pc->p)); + pc->p++; + pc->len--; + } + pc->missing.ch = '['; + pc->missing.line = line; + pc->tend = pc->p - 1; +} + +static int JimParseBrace(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + JimParseSubBrace(pc); + return JIM_OK; +} + +static int JimParseCmd(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JIM_TT_CMD; + JimParseSubCmd(pc); + return JIM_OK; +} + +static int JimParseQuote(struct JimParserCtx *pc) +{ + pc->tstart = pc->p + 1; + pc->tline = pc->linenr; + pc->tt = JimParseSubQuote(pc); + return JIM_OK; +} + +static int JimParseVar(struct JimParserCtx *pc) +{ + + pc->p++; + pc->len--; + +#ifdef EXPRSUGAR_BRACKET + if (*pc->p == '[') { + + JimParseCmd(pc); + pc->tt = JIM_TT_EXPRSUGAR; + return JIM_OK; + } +#endif + + pc->tstart = pc->p; + pc->tt = JIM_TT_VAR; + pc->tline = pc->linenr; + + if (*pc->p == '{') { + pc->tstart = ++pc->p; + pc->len--; + + while (pc->len && *pc->p != '}') { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + if (pc->len) { + pc->p++; + pc->len--; + } + } + else { + while (1) { + + if (pc->p[0] == ':' && pc->p[1] == ':') { + while (*pc->p == ':') { + pc->p++; + pc->len--; + } + continue; + } + if (isalnum(UCHAR(*pc->p)) || *pc->p == '_' || UCHAR(*pc->p) >= 0x80) { + pc->p++; + pc->len--; + continue; + } + break; + } + + if (*pc->p == '(') { + int count = 1; + const char *paren = NULL; + + pc->tt = JIM_TT_DICTSUGAR; + + while (count && pc->len) { + pc->p++; + pc->len--; + if (*pc->p == '\\' && pc->len >= 1) { + pc->p++; + pc->len--; + } + else if (*pc->p == '(') { + count++; + } + else if (*pc->p == ')') { + paren = pc->p; + count--; + } + } + if (count == 0) { + pc->p++; + pc->len--; + } + else if (paren) { + + paren++; + pc->len += (pc->p - paren); + pc->p = paren; + } +#ifndef EXPRSUGAR_BRACKET + if (*pc->tstart == '(') { + pc->tt = JIM_TT_EXPRSUGAR; + } +#endif + } + pc->tend = pc->p - 1; + } + if (pc->tstart == pc->p) { + pc->p--; + pc->len++; + return JIM_ERR; + } + return JIM_OK; +} + +static int JimParseStr(struct JimParserCtx *pc) +{ + if (pc->tt == JIM_TT_SEP || pc->tt == JIM_TT_EOL || + pc->tt == JIM_TT_NONE || pc->tt == JIM_TT_STR) { + + if (*pc->p == '{') { + return JimParseBrace(pc); + } + if (*pc->p == '"') { + pc->state = JIM_PS_QUOTE; + pc->p++; + pc->len--; + + pc->missing.line = pc->tline; + } + } + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (1) { + if (pc->len == 0) { + if (pc->state == JIM_PS_QUOTE) { + pc->missing.ch = '"'; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + switch (*pc->p) { + case '\\': + if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + if (pc->len >= 2) { + if (*(pc->p + 1) == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + else if (pc->len == 1) { + + pc->missing.ch = '\\'; + } + break; + case '(': + + if (pc->len > 1 && pc->p[1] != '$') { + break; + } + case ')': + + if (*pc->p == '(' || pc->tt == JIM_TT_VAR) { + if (pc->p == pc->tstart) { + + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + break; + + case '$': + case '[': + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + case ' ': + case '\t': + case '\n': + case '\r': + case '\f': + case ';': + if (pc->state == JIM_PS_DEF) { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + return JIM_OK; + } + else if (*pc->p == '\n') { + pc->linenr++; + } + break; + case '"': + if (pc->state == JIM_PS_QUOTE) { + pc->tend = pc->p - 1; + pc->tt = JIM_TT_ESC; + pc->p++; + pc->len--; + pc->state = JIM_PS_DEF; + return JIM_OK; + } + break; + } + pc->p++; + pc->len--; + } + return JIM_OK; +} + +static int JimParseComment(struct JimParserCtx *pc) +{ + while (*pc->p) { + if (*pc->p == '\\') { + pc->p++; + pc->len--; + if (pc->len == 0) { + pc->missing.ch = '\\'; + return JIM_OK; + } + if (*pc->p == '\n') { + pc->linenr++; + } + } + else if (*pc->p == '\n') { + pc->p++; + pc->len--; + pc->linenr++; + break; + } + pc->p++; + pc->len--; + } + return JIM_OK; +} + + +static int xdigitval(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int odigitval(int c) +{ + if (c >= '0' && c <= '7') + return c - '0'; + return -1; +} + +static int JimEscape(char *dest, const char *s, int slen) +{ + char *p = dest; + int i, len; + + if (slen == -1) + slen = strlen(s); + + for (i = 0; i < slen; i++) { + switch (s[i]) { + case '\\': + switch (s[i + 1]) { + case 'a': + *p++ = 0x7; + i++; + break; + case 'b': + *p++ = 0x8; + i++; + break; + case 'f': + *p++ = 0xc; + i++; + break; + case 'n': + *p++ = 0xa; + i++; + break; + case 'r': + *p++ = 0xd; + i++; + break; + case 't': + *p++ = 0x9; + i++; + break; + case 'u': + case 'U': + case 'x': + { + unsigned val = 0; + int k; + int maxchars = 2; + + i++; + + if (s[i] == 'U') { + maxchars = 8; + } + else if (s[i] == 'u') { + if (s[i + 1] == '{') { + maxchars = 6; + i++; + } + else { + maxchars = 4; + } + } + + for (k = 0; k < maxchars; k++) { + int c = xdigitval(s[i + k + 1]); + if (c == -1) { + break; + } + val = (val << 4) | c; + } + + if (s[i] == '{') { + if (k == 0 || val > 0x1fffff || s[i + k + 1] != '}') { + + i--; + k = 0; + } + else { + + k++; + } + } + if (k) { + + if (s[i] == 'x') { + *p++ = val; + } + else { + p += utf8_fromunicode(p, val); + } + i += k; + break; + } + + *p++ = s[i]; + } + break; + case 'v': + *p++ = 0xb; + i++; + break; + case '\0': + *p++ = '\\'; + i++; + break; + case '\n': + + *p++ = ' '; + do { + i++; + } while (s[i + 1] == ' ' || s[i + 1] == '\t'); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + + { + int val = 0; + int c = odigitval(s[i + 1]); + + val = c; + c = odigitval(s[i + 2]); + if (c == -1) { + *p++ = val; + i++; + break; + } + val = (val * 8) + c; + c = odigitval(s[i + 3]); + if (c == -1) { + *p++ = val; + i += 2; + break; + } + val = (val * 8) + c; + *p++ = val; + i += 3; + } + break; + default: + *p++ = s[i + 1]; + i++; + break; + } + break; + default: + *p++ = s[i]; + break; + } + } + len = p - dest; + *p = '\0'; + return len; +} + +static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc) +{ + const char *start, *end; + char *token; + int len; + + start = pc->tstart; + end = pc->tend; + if (start > end) { + len = 0; + token = Jim_Alloc(1); + token[0] = '\0'; + } + else { + len = (end - start) + 1; + token = Jim_Alloc(len + 1); + if (pc->tt != JIM_TT_ESC) { + + memcpy(token, start, len); + token[len] = '\0'; + } + else { + + len = JimEscape(token, start, len); + } + } + + return Jim_NewStringObjNoAlloc(interp, token, len); +} + +int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr) +{ + struct JimParserCtx parser; + + JimParserInit(&parser, s, len, 1); + while (!parser.eof) { + JimParseScript(&parser); + } + if (stateCharPtr) { + *stateCharPtr = parser.missing.ch; + } + return parser.missing.ch == ' '; +} + +static int JimParseListSep(struct JimParserCtx *pc); +static int JimParseListStr(struct JimParserCtx *pc); +static int JimParseListQuote(struct JimParserCtx *pc); + +static int JimParseList(struct JimParserCtx *pc) +{ + if (isspace(UCHAR(*pc->p))) { + return JimParseListSep(pc); + } + switch (*pc->p) { + case '"': + return JimParseListQuote(pc); + + case '{': + return JimParseBrace(pc); + + default: + if (pc->len) { + return JimParseListStr(pc); + } + break; + } + + pc->tstart = pc->tend = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; +} + +static int JimParseListSep(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + while (isspace(UCHAR(*pc->p))) { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = JIM_TT_SEP; + return JIM_OK; +} + +static int JimParseListQuote(struct JimParserCtx *pc) +{ + pc->p++; + pc->len--; + + pc->tstart = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + + while (pc->len) { + switch (*pc->p) { + case '\\': + pc->tt = JIM_TT_ESC; + if (--pc->len == 0) { + + pc->tend = pc->p; + return JIM_OK; + } + pc->p++; + break; + case '\n': + pc->linenr++; + break; + case '"': + pc->tend = pc->p - 1; + pc->p++; + pc->len--; + return JIM_OK; + } + pc->p++; + pc->len--; + } + + pc->tend = pc->p - 1; + return JIM_OK; +} + +static int JimParseListStr(struct JimParserCtx *pc) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + pc->tt = JIM_TT_STR; + + while (pc->len) { + if (isspace(UCHAR(*pc->p))) { + pc->tend = pc->p - 1; + return JIM_OK; + } + if (*pc->p == '\\') { + if (--pc->len == 0) { + + pc->tend = pc->p; + return JIM_OK; + } + pc->tt = JIM_TT_ESC; + pc->p++; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + return JIM_OK; +} + + + +Jim_Obj *Jim_NewObj(Jim_Interp *interp) +{ + Jim_Obj *objPtr; + + + if (interp->freeList != NULL) { + + objPtr = interp->freeList; + interp->freeList = objPtr->nextObjPtr; + } + else { + + objPtr = Jim_Alloc(sizeof(*objPtr)); + } + + objPtr->refCount = 0; + + + objPtr->prevObjPtr = NULL; + objPtr->nextObjPtr = interp->liveList; + if (interp->liveList) + interp->liveList->prevObjPtr = objPtr; + interp->liveList = objPtr; + + return objPtr; +} + +void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr) +{ + + JimPanic((objPtr->refCount != 0, "!!!Object %p freed with bad refcount %d, type=%s", objPtr, + objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "")); + + + Jim_FreeIntRep(interp, objPtr); + + if (objPtr->bytes != NULL) { + if (objPtr->bytes != JimEmptyStringRep) + Jim_Free(objPtr->bytes); + } + + if (objPtr->prevObjPtr) + objPtr->prevObjPtr->nextObjPtr = objPtr->nextObjPtr; + if (objPtr->nextObjPtr) + objPtr->nextObjPtr->prevObjPtr = objPtr->prevObjPtr; + if (interp->liveList == objPtr) + interp->liveList = objPtr->nextObjPtr; +#ifdef JIM_DISABLE_OBJECT_POOL + Jim_Free(objPtr); +#else + + objPtr->prevObjPtr = NULL; + objPtr->nextObjPtr = interp->freeList; + if (interp->freeList) + interp->freeList->prevObjPtr = objPtr; + interp->freeList = objPtr; + objPtr->refCount = -1; +#endif +} + + +void Jim_InvalidateStringRep(Jim_Obj *objPtr) +{ + if (objPtr->bytes != NULL) { + if (objPtr->bytes != JimEmptyStringRep) + Jim_Free(objPtr->bytes); + } + objPtr->bytes = NULL; +} + + +Jim_Obj *Jim_DuplicateObj(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *dupPtr; + + dupPtr = Jim_NewObj(interp); + if (objPtr->bytes == NULL) { + + dupPtr->bytes = NULL; + } + else if (objPtr->length == 0) { + + dupPtr->bytes = JimEmptyStringRep; + dupPtr->length = 0; + dupPtr->typePtr = NULL; + return dupPtr; + } + else { + dupPtr->bytes = Jim_Alloc(objPtr->length + 1); + dupPtr->length = objPtr->length; + + memcpy(dupPtr->bytes, objPtr->bytes, objPtr->length + 1); + } + + + dupPtr->typePtr = objPtr->typePtr; + if (objPtr->typePtr != NULL) { + if (objPtr->typePtr->dupIntRepProc == NULL) { + dupPtr->internalRep = objPtr->internalRep; + } + else { + + objPtr->typePtr->dupIntRepProc(interp, objPtr, dupPtr); + } + } + return dupPtr; +} + +const char *Jim_GetString(Jim_Obj *objPtr, int *lenPtr) +{ + if (objPtr->bytes == NULL) { + + JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); + objPtr->typePtr->updateStringProc(objPtr); + } + if (lenPtr) + *lenPtr = objPtr->length; + return objPtr->bytes; +} + + +int Jim_Length(Jim_Obj *objPtr) +{ + if (objPtr->bytes == NULL) { + + JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); + objPtr->typePtr->updateStringProc(objPtr); + } + return objPtr->length; +} + + +const char *Jim_String(Jim_Obj *objPtr) +{ + if (objPtr->bytes == NULL) { + + JimPanic((objPtr->typePtr == NULL, "UpdateStringProc called against typeless value.")); + JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); + objPtr->typePtr->updateStringProc(objPtr); + } + return objPtr->bytes; +} + +static void JimSetStringBytes(Jim_Obj *objPtr, const char *str) +{ + objPtr->bytes = Jim_StrDup(str); + objPtr->length = strlen(str); +} + +static void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); + +static const Jim_ObjType dictSubstObjType = { + "dict-substitution", + FreeDictSubstInternalRep, + DupDictSubstInternalRep, + NULL, + JIM_TYPE_NONE, +}; + +static void FreeInterpolatedInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); +} + +static const Jim_ObjType interpolatedObjType = { + "interpolated", + FreeInterpolatedInternalRep, + NULL, + NULL, + JIM_TYPE_NONE, +}; + +static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetStringFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType stringObjType = { + "string", + NULL, + DupStringInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +static void DupStringInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + + dupPtr->internalRep.strValue.maxLength = srcPtr->length; + dupPtr->internalRep.strValue.charLength = srcPtr->internalRep.strValue.charLength; +} + +static int SetStringFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &stringObjType) { + + if (objPtr->bytes == NULL) { + + JimPanic((objPtr->typePtr->updateStringProc == NULL, "UpdateStringProc called against '%s' type.", objPtr->typePtr->name)); + objPtr->typePtr->updateStringProc(objPtr); + } + + Jim_FreeIntRep(interp, objPtr); + + objPtr->typePtr = &stringObjType; + objPtr->internalRep.strValue.maxLength = objPtr->length; + + objPtr->internalRep.strValue.charLength = -1; + } + return JIM_OK; +} + +int Jim_Utf8Length(Jim_Interp *interp, Jim_Obj *objPtr) +{ +#ifdef JIM_UTF8 + SetStringFromAny(interp, objPtr); + + if (objPtr->internalRep.strValue.charLength < 0) { + objPtr->internalRep.strValue.charLength = utf8_strlen(objPtr->bytes, objPtr->length); + } + return objPtr->internalRep.strValue.charLength; +#else + return Jim_Length(objPtr); +#endif +} + + +Jim_Obj *Jim_NewStringObj(Jim_Interp *interp, const char *s, int len) +{ + Jim_Obj *objPtr = Jim_NewObj(interp); + + + if (len == -1) + len = strlen(s); + + if (len == 0) { + objPtr->bytes = JimEmptyStringRep; + } + else { + objPtr->bytes = Jim_Alloc(len + 1); + memcpy(objPtr->bytes, s, len); + objPtr->bytes[len] = '\0'; + } + objPtr->length = len; + + + objPtr->typePtr = NULL; + return objPtr; +} + + +Jim_Obj *Jim_NewStringObjUtf8(Jim_Interp *interp, const char *s, int charlen) +{ +#ifdef JIM_UTF8 + + int bytelen = utf8_index(s, charlen); + + Jim_Obj *objPtr = Jim_NewStringObj(interp, s, bytelen); + + + objPtr->typePtr = &stringObjType; + objPtr->internalRep.strValue.maxLength = bytelen; + objPtr->internalRep.strValue.charLength = charlen; + + return objPtr; +#else + return Jim_NewStringObj(interp, s, charlen); +#endif +} + +Jim_Obj *Jim_NewStringObjNoAlloc(Jim_Interp *interp, char *s, int len) +{ + Jim_Obj *objPtr = Jim_NewObj(interp); + + objPtr->bytes = s; + objPtr->length = (len == -1) ? strlen(s) : len; + objPtr->typePtr = NULL; + return objPtr; +} + +static void StringAppendString(Jim_Obj *objPtr, const char *str, int len) +{ + int needlen; + + if (len == -1) + len = strlen(str); + needlen = objPtr->length + len; + if (objPtr->internalRep.strValue.maxLength < needlen || + objPtr->internalRep.strValue.maxLength == 0) { + needlen *= 2; + + if (needlen < 7) { + needlen = 7; + } + if (objPtr->bytes == JimEmptyStringRep) { + objPtr->bytes = Jim_Alloc(needlen + 1); + } + else { + objPtr->bytes = Jim_Realloc(objPtr->bytes, needlen + 1); + } + objPtr->internalRep.strValue.maxLength = needlen; + } + memcpy(objPtr->bytes + objPtr->length, str, len); + objPtr->bytes[objPtr->length + len] = '\0'; + + if (objPtr->internalRep.strValue.charLength >= 0) { + + objPtr->internalRep.strValue.charLength += utf8_strlen(objPtr->bytes + objPtr->length, len); + } + objPtr->length += len; +} + +void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, int len) +{ + JimPanic((Jim_IsShared(objPtr), "Jim_AppendString called with shared object")); + SetStringFromAny(interp, objPtr); + StringAppendString(objPtr, str, len); +} + +void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) +{ + int len; + const char *str = Jim_GetString(appendObjPtr, &len); + Jim_AppendString(interp, objPtr, str, len); +} + +void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...) +{ + va_list ap; + + SetStringFromAny(interp, objPtr); + va_start(ap, objPtr); + while (1) { + const char *s = va_arg(ap, const char *); + + if (s == NULL) + break; + Jim_AppendString(interp, objPtr, s, -1); + } + va_end(ap); +} + +int Jim_StringEqObj(Jim_Obj *aObjPtr, Jim_Obj *bObjPtr) +{ + if (aObjPtr == bObjPtr) { + return 1; + } + else { + int Alen, Blen; + const char *sA = Jim_GetString(aObjPtr, &Alen); + const char *sB = Jim_GetString(bObjPtr, &Blen); + + return Alen == Blen && memcmp(sA, sB, Alen) == 0; + } +} + +int Jim_StringMatchObj(Jim_Interp *interp, Jim_Obj *patternObjPtr, Jim_Obj *objPtr, int nocase) +{ + return JimGlobMatch(Jim_String(patternObjPtr), Jim_String(objPtr), nocase); +} + +int Jim_StringCompareObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) +{ + int l1, l2; + const char *s1 = Jim_GetString(firstObjPtr, &l1); + const char *s2 = Jim_GetString(secondObjPtr, &l2); + + if (nocase) { + + return JimStringCompareLen(s1, s2, -1, nocase); + } + return JimStringCompare(s1, l1, s2, l2); +} + +int Jim_StringCompareLenObj(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *secondObjPtr, int nocase) +{ + const char *s1 = Jim_String(firstObjPtr); + const char *s2 = Jim_String(secondObjPtr); + + return JimStringCompareLen(s1, s2, Jim_Utf8Length(interp, firstObjPtr), nocase); +} + +static int JimRelToAbsIndex(int len, int idx) +{ + if (idx < 0) + return len + idx; + return idx; +} + +static void JimRelToAbsRange(int len, int *firstPtr, int *lastPtr, int *rangeLenPtr) +{ + int rangeLen; + + if (*firstPtr > *lastPtr) { + rangeLen = 0; + } + else { + rangeLen = *lastPtr - *firstPtr + 1; + if (rangeLen) { + if (*firstPtr < 0) { + rangeLen += *firstPtr; + *firstPtr = 0; + } + if (*lastPtr >= len) { + rangeLen -= (*lastPtr - (len - 1)); + *lastPtr = len - 1; + } + } + } + if (rangeLen < 0) + rangeLen = 0; + + *rangeLenPtr = rangeLen; +} + +static int JimStringGetRange(Jim_Interp *interp, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr, + int len, int *first, int *last, int *range) +{ + if (Jim_GetIndex(interp, firstObjPtr, first) != JIM_OK) { + return JIM_ERR; + } + if (Jim_GetIndex(interp, lastObjPtr, last) != JIM_OK) { + return JIM_ERR; + } + *first = JimRelToAbsIndex(len, *first); + *last = JimRelToAbsIndex(len, *last); + JimRelToAbsRange(len, first, last, range); + return JIM_OK; +} + +Jim_Obj *Jim_StringByteRangeObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) +{ + int first, last; + const char *str; + int rangeLen; + int bytelen; + + str = Jim_GetString(strObjPtr, &bytelen); + + if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, bytelen, &first, &last, &rangeLen) != JIM_OK) { + return NULL; + } + + if (first == 0 && rangeLen == bytelen) { + return strObjPtr; + } + return Jim_NewStringObj(interp, str + first, rangeLen); +} + +Jim_Obj *Jim_StringRangeObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr) +{ +#ifdef JIM_UTF8 + int first, last; + const char *str; + int len, rangeLen; + int bytelen; + + str = Jim_GetString(strObjPtr, &bytelen); + len = Jim_Utf8Length(interp, strObjPtr); + + if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) { + return NULL; + } + + if (first == 0 && rangeLen == len) { + return strObjPtr; + } + if (len == bytelen) { + + return Jim_NewStringObj(interp, str + first, rangeLen); + } + return Jim_NewStringObjUtf8(interp, str + utf8_index(str, first), rangeLen); +#else + return Jim_StringByteRangeObj(interp, strObjPtr, firstObjPtr, lastObjPtr); +#endif +} + +Jim_Obj *JimStringReplaceObj(Jim_Interp *interp, + Jim_Obj *strObjPtr, Jim_Obj *firstObjPtr, Jim_Obj *lastObjPtr, Jim_Obj *newStrObj) +{ + int first, last; + const char *str; + int len, rangeLen; + Jim_Obj *objPtr; + + len = Jim_Utf8Length(interp, strObjPtr); + + if (JimStringGetRange(interp, firstObjPtr, lastObjPtr, len, &first, &last, &rangeLen) != JIM_OK) { + return NULL; + } + + if (last < first) { + return strObjPtr; + } + + str = Jim_String(strObjPtr); + + + objPtr = Jim_NewStringObjUtf8(interp, str, first); + + + if (newStrObj) { + Jim_AppendObj(interp, objPtr, newStrObj); + } + + + Jim_AppendString(interp, objPtr, str + utf8_index(str, last + 1), len - last - 1); + + return objPtr; +} + +static void JimStrCopyUpperLower(char *dest, const char *str, int uc) +{ + while (*str) { + int c; + str += utf8_tounicode(str, &c); + dest += utf8_getchars(dest, uc ? utf8_upper(c) : utf8_lower(c)); + } + *dest = 0; +} + +static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf; + int len; + const char *str; + + SetStringFromAny(interp, strObjPtr); + + str = Jim_GetString(strObjPtr, &len); + +#ifdef JIM_UTF8 + len *= 2; +#endif + buf = Jim_Alloc(len + 1); + JimStrCopyUpperLower(buf, str, 0); + return Jim_NewStringObjNoAlloc(interp, buf, -1); +} + +static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf; + const char *str; + int len; + + if (strObjPtr->typePtr != &stringObjType) { + SetStringFromAny(interp, strObjPtr); + } + + str = Jim_GetString(strObjPtr, &len); + +#ifdef JIM_UTF8 + len *= 2; +#endif + buf = Jim_Alloc(len + 1); + JimStrCopyUpperLower(buf, str, 1); + return Jim_NewStringObjNoAlloc(interp, buf, -1); +} + +static Jim_Obj *JimStringToTitle(Jim_Interp *interp, Jim_Obj *strObjPtr) +{ + char *buf, *p; + int len; + int c; + const char *str; + + str = Jim_GetString(strObjPtr, &len); + if (len == 0) { + return strObjPtr; + } +#ifdef JIM_UTF8 + len *= 2; +#endif + buf = p = Jim_Alloc(len + 1); + + str += utf8_tounicode(str, &c); + p += utf8_getchars(p, utf8_title(c)); + + JimStrCopyUpperLower(p, str, 0); + + return Jim_NewStringObjNoAlloc(interp, buf, -1); +} + +static const char *utf8_memchr(const char *str, int len, int c) +{ +#ifdef JIM_UTF8 + while (len) { + int sc; + int n = utf8_tounicode(str, &sc); + if (sc == c) { + return str; + } + str += n; + len -= n; + } + return NULL; +#else + return memchr(str, c, len); +#endif +} + +static const char *JimFindTrimLeft(const char *str, int len, const char *trimchars, int trimlen) +{ + while (len) { + int c; + int n = utf8_tounicode(str, &c); + + if (utf8_memchr(trimchars, trimlen, c) == NULL) { + + break; + } + str += n; + len -= n; + } + return str; +} + +static const char *JimFindTrimRight(const char *str, int len, const char *trimchars, int trimlen) +{ + str += len; + + while (len) { + int c; + int n = utf8_prev_len(str, len); + + len -= n; + str -= n; + + n = utf8_tounicode(str, &c); + + if (utf8_memchr(trimchars, trimlen, c) == NULL) { + return str + n; + } + } + + return NULL; +} + +static const char default_trim_chars[] = " \t\n\r"; + +static int default_trim_chars_len = sizeof(default_trim_chars); + +static Jim_Obj *JimStringTrimLeft(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + int len; + const char *str = Jim_GetString(strObjPtr, &len); + const char *trimchars = default_trim_chars; + int trimcharslen = default_trim_chars_len; + const char *newstr; + + if (trimcharsObjPtr) { + trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); + } + + newstr = JimFindTrimLeft(str, len, trimchars, trimcharslen); + if (newstr == str) { + return strObjPtr; + } + + return Jim_NewStringObj(interp, newstr, len - (newstr - str)); +} + +static Jim_Obj *JimStringTrimRight(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + int len; + const char *trimchars = default_trim_chars; + int trimcharslen = default_trim_chars_len; + const char *nontrim; + + if (trimcharsObjPtr) { + trimchars = Jim_GetString(trimcharsObjPtr, &trimcharslen); + } + + SetStringFromAny(interp, strObjPtr); + + len = Jim_Length(strObjPtr); + nontrim = JimFindTrimRight(strObjPtr->bytes, len, trimchars, trimcharslen); + + if (nontrim == NULL) { + + return Jim_NewEmptyStringObj(interp); + } + if (nontrim == strObjPtr->bytes + len) { + + return strObjPtr; + } + + if (Jim_IsShared(strObjPtr)) { + strObjPtr = Jim_NewStringObj(interp, strObjPtr->bytes, (nontrim - strObjPtr->bytes)); + } + else { + + strObjPtr->bytes[nontrim - strObjPtr->bytes] = 0; + strObjPtr->length = (nontrim - strObjPtr->bytes); + } + + return strObjPtr; +} + +static Jim_Obj *JimStringTrim(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *trimcharsObjPtr) +{ + + Jim_Obj *objPtr = JimStringTrimLeft(interp, strObjPtr, trimcharsObjPtr); + + + strObjPtr = JimStringTrimRight(interp, objPtr, trimcharsObjPtr); + + + if (objPtr != strObjPtr && objPtr->refCount == 0) { + + Jim_FreeNewObj(interp, objPtr); + } + + return strObjPtr; +} + + +#ifdef HAVE_ISASCII +#define jim_isascii isascii +#else +static int jim_isascii(int c) +{ + return !(c & ~0x7f); +} +#endif + +static int JimStringIs(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *strClass, int strict) +{ + static const char * const strclassnames[] = { + "integer", "alpha", "alnum", "ascii", "digit", + "double", "lower", "upper", "space", "xdigit", + "control", "print", "graph", "punct", + NULL + }; + enum { + STR_IS_INTEGER, STR_IS_ALPHA, STR_IS_ALNUM, STR_IS_ASCII, STR_IS_DIGIT, + STR_IS_DOUBLE, STR_IS_LOWER, STR_IS_UPPER, STR_IS_SPACE, STR_IS_XDIGIT, + STR_IS_CONTROL, STR_IS_PRINT, STR_IS_GRAPH, STR_IS_PUNCT + }; + int strclass; + int len; + int i; + const char *str; + int (*isclassfunc)(int c) = NULL; + + if (Jim_GetEnum(interp, strClass, strclassnames, &strclass, "class", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + + str = Jim_GetString(strObjPtr, &len); + if (len == 0) { + Jim_SetResultBool(interp, !strict); + return JIM_OK; + } + + switch (strclass) { + case STR_IS_INTEGER: + { + jim_wide w; + Jim_SetResultBool(interp, JimGetWideNoErr(interp, strObjPtr, &w) == JIM_OK); + return JIM_OK; + } + + case STR_IS_DOUBLE: + { + double d; + Jim_SetResultBool(interp, Jim_GetDouble(interp, strObjPtr, &d) == JIM_OK && errno != ERANGE); + return JIM_OK; + } + + case STR_IS_ALPHA: isclassfunc = isalpha; break; + case STR_IS_ALNUM: isclassfunc = isalnum; break; + case STR_IS_ASCII: isclassfunc = jim_isascii; break; + case STR_IS_DIGIT: isclassfunc = isdigit; break; + case STR_IS_LOWER: isclassfunc = islower; break; + case STR_IS_UPPER: isclassfunc = isupper; break; + case STR_IS_SPACE: isclassfunc = isspace; break; + case STR_IS_XDIGIT: isclassfunc = isxdigit; break; + case STR_IS_CONTROL: isclassfunc = iscntrl; break; + case STR_IS_PRINT: isclassfunc = isprint; break; + case STR_IS_GRAPH: isclassfunc = isgraph; break; + case STR_IS_PUNCT: isclassfunc = ispunct; break; + default: + return JIM_ERR; + } + + for (i = 0; i < len; i++) { + if (!isclassfunc(str[i])) { + Jim_SetResultBool(interp, 0); + return JIM_OK; + } + } + Jim_SetResultBool(interp, 1); + return JIM_OK; +} + + + +static const Jim_ObjType comparedStringObjType = { + "compared-string", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +int Jim_CompareStringImmediate(Jim_Interp *interp, Jim_Obj *objPtr, const char *str) +{ + if (objPtr->typePtr == &comparedStringObjType && objPtr->internalRep.ptr == str) { + return 1; + } + else { + const char *objStr = Jim_String(objPtr); + + if (strcmp(str, objStr) != 0) + return 0; + + if (objPtr->typePtr != &comparedStringObjType) { + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &comparedStringObjType; + } + objPtr->internalRep.ptr = (char *)str; + return 1; + } +} + +static int qsortCompareStringPointers(const void *a, const void *b) +{ + char *const *sa = (char *const *)a; + char *const *sb = (char *const *)b; + + return strcmp(*sa, *sb); +} + + + +static void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); + +static const Jim_ObjType sourceObjType = { + "source", + FreeSourceInternalRep, + DupSourceInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +void FreeSourceInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.sourceValue.fileNameObj); +} + +void DupSourceInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + dupPtr->internalRep.sourceValue = srcPtr->internalRep.sourceValue; + Jim_IncrRefCount(dupPtr->internalRep.sourceValue.fileNameObj); +} + +static void JimSetSourceInfo(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *fileNameObj, int lineNumber) +{ + JimPanic((Jim_IsShared(objPtr), "JimSetSourceInfo called with shared object")); + JimPanic((objPtr->typePtr != NULL, "JimSetSourceInfo called with typed object")); + Jim_IncrRefCount(fileNameObj); + objPtr->internalRep.sourceValue.fileNameObj = fileNameObj; + objPtr->internalRep.sourceValue.lineNumber = lineNumber; + objPtr->typePtr = &sourceObjType; +} + +static const Jim_ObjType scriptLineObjType = { + "scriptline", + NULL, + NULL, + NULL, + JIM_NONE, +}; + +static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line) +{ + Jim_Obj *objPtr; + +#ifdef DEBUG_SHOW_SCRIPT + char buf[100]; + snprintf(buf, sizeof(buf), "line=%d, argc=%d", line, argc); + objPtr = Jim_NewStringObj(interp, buf, -1); +#else + objPtr = Jim_NewEmptyStringObj(interp); +#endif + objPtr->typePtr = &scriptLineObjType; + objPtr->internalRep.scriptLineValue.argc = argc; + objPtr->internalRep.scriptLineValue.line = line; + + return objPtr; +} + +static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); +static int JimParseCheckMissing(Jim_Interp *interp, int ch); + +static const Jim_ObjType scriptObjType = { + "script", + FreeScriptInternalRep, + DupScriptInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +typedef struct ScriptToken +{ + Jim_Obj *objPtr; + int type; +} ScriptToken; + +typedef struct ScriptObj +{ + ScriptToken *token; + Jim_Obj *fileNameObj; + int len; + int substFlags; + int inUse; /* Used to share a ScriptObj. Currently + only used by Jim_EvalObj() as protection against + shimmering of the currently evaluated object. */ + int firstline; + int linenr; + int missing; +} ScriptObj; + +void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int i; + struct ScriptObj *script = (void *)objPtr->internalRep.ptr; + + if (--script->inUse != 0) + return; + for (i = 0; i < script->len; i++) { + Jim_DecrRefCount(interp, script->token[i].objPtr); + } + Jim_Free(script->token); + Jim_DecrRefCount(interp, script->fileNameObj); + Jim_Free(script); +} + +void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(srcPtr); + + dupPtr->typePtr = NULL; +} + +typedef struct +{ + const char *token; + int len; + int type; + int line; +} ParseToken; + +typedef struct +{ + + ParseToken *list; + int size; + int count; + ParseToken static_list[20]; +} ParseTokenList; + +static void ScriptTokenListInit(ParseTokenList *tokenlist) +{ + tokenlist->list = tokenlist->static_list; + tokenlist->size = sizeof(tokenlist->static_list) / sizeof(ParseToken); + tokenlist->count = 0; +} + +static void ScriptTokenListFree(ParseTokenList *tokenlist) +{ + if (tokenlist->list != tokenlist->static_list) { + Jim_Free(tokenlist->list); + } +} + +static void ScriptAddToken(ParseTokenList *tokenlist, const char *token, int len, int type, + int line) +{ + ParseToken *t; + + if (tokenlist->count == tokenlist->size) { + + tokenlist->size *= 2; + if (tokenlist->list != tokenlist->static_list) { + tokenlist->list = + Jim_Realloc(tokenlist->list, tokenlist->size * sizeof(*tokenlist->list)); + } + else { + + tokenlist->list = Jim_Alloc(tokenlist->size * sizeof(*tokenlist->list)); + memcpy(tokenlist->list, tokenlist->static_list, + tokenlist->count * sizeof(*tokenlist->list)); + } + } + t = &tokenlist->list[tokenlist->count++]; + t->token = token; + t->len = len; + t->type = type; + t->line = line; +} + +static int JimCountWordTokens(ParseToken *t) +{ + int expand = 1; + int count = 0; + + + if (t->type == JIM_TT_STR && !TOKEN_IS_SEP(t[1].type)) { + if ((t->len == 1 && *t->token == '*') || (t->len == 6 && strncmp(t->token, "expand", 6) == 0)) { + + expand = -1; + t++; + } + } + + + while (!TOKEN_IS_SEP(t->type)) { + t++; + count++; + } + + return count * expand; +} + +static Jim_Obj *JimMakeScriptObj(Jim_Interp *interp, const ParseToken *t) +{ + Jim_Obj *objPtr; + + if (t->type == JIM_TT_ESC && memchr(t->token, '\\', t->len) != NULL) { + + int len = t->len; + char *str = Jim_Alloc(len + 1); + len = JimEscape(str, t->token, len); + objPtr = Jim_NewStringObjNoAlloc(interp, str, len); + } + else { + objPtr = Jim_NewStringObj(interp, t->token, t->len); + } + return objPtr; +} + +static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, + ParseTokenList *tokenlist) +{ + int i; + struct ScriptToken *token; + + int lineargs = 0; + + ScriptToken *linefirst; + int count; + int linenr; + +#ifdef DEBUG_SHOW_SCRIPT_TOKENS + printf("==== Tokens ====\n"); + for (i = 0; i < tokenlist->count; i++) { + printf("[%2d]@%d %s '%.*s'\n", i, tokenlist->list[i].line, jim_tt_name(tokenlist->list[i].type), + tokenlist->list[i].len, tokenlist->list[i].token); + } +#endif + + + count = tokenlist->count; + for (i = 0; i < tokenlist->count; i++) { + if (tokenlist->list[i].type == JIM_TT_EOL) { + count++; + } + } + linenr = script->firstline = tokenlist->list[0].line; + + token = script->token = Jim_Alloc(sizeof(ScriptToken) * count); + + + linefirst = token++; + + for (i = 0; i < tokenlist->count; ) { + + int wordtokens; + + + while (tokenlist->list[i].type == JIM_TT_SEP) { + i++; + } + + wordtokens = JimCountWordTokens(tokenlist->list + i); + + if (wordtokens == 0) { + + if (lineargs) { + linefirst->type = JIM_TT_LINE; + linefirst->objPtr = JimNewScriptLineObj(interp, lineargs, linenr); + Jim_IncrRefCount(linefirst->objPtr); + + + lineargs = 0; + linefirst = token++; + } + i++; + continue; + } + else if (wordtokens != 1) { + + token->type = JIM_TT_WORD; + token->objPtr = Jim_NewIntObj(interp, wordtokens); + Jim_IncrRefCount(token->objPtr); + token++; + if (wordtokens < 0) { + + i++; + wordtokens = -wordtokens - 1; + lineargs--; + } + } + + if (lineargs == 0) { + + linenr = tokenlist->list[i].line; + } + lineargs++; + + + while (wordtokens--) { + const ParseToken *t = &tokenlist->list[i++]; + + token->type = t->type; + token->objPtr = JimMakeScriptObj(interp, t); + Jim_IncrRefCount(token->objPtr); + + JimSetSourceInfo(interp, token->objPtr, script->fileNameObj, t->line); + token++; + } + } + + if (lineargs == 0) { + token--; + } + + script->len = token - script->token; + + JimPanic((script->len >= count, "allocated script array is too short")); + +#ifdef DEBUG_SHOW_SCRIPT + printf("==== Script (%s) ====\n", Jim_String(script->fileNameObj)); + for (i = 0; i < script->len; i++) { + const ScriptToken *t = &script->token[i]; + printf("[%2d] %s %s\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); + } +#endif + +} + +static int JimParseCheckMissing(Jim_Interp *interp, int ch) +{ + const char *msg; + + switch (ch) { + case '\\': + case ' ': + return JIM_OK; + + case '[': + msg = "unmatched \"[\""; + break; + case '{': + msg = "missing close-brace"; + break; + case '"': + default: + msg = "missing quote"; + break; + } + + Jim_SetResultString(interp, msg, -1); + return JIM_ERR; +} + +static void SubstObjAddTokens(Jim_Interp *interp, struct ScriptObj *script, + ParseTokenList *tokenlist) +{ + int i; + struct ScriptToken *token; + + token = script->token = Jim_Alloc(sizeof(ScriptToken) * tokenlist->count); + + for (i = 0; i < tokenlist->count; i++) { + const ParseToken *t = &tokenlist->list[i]; + + + token->type = t->type; + token->objPtr = JimMakeScriptObj(interp, t); + Jim_IncrRefCount(token->objPtr); + token++; + } + + script->len = i; +} + +static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int scriptTextLen; + const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); + struct JimParserCtx parser; + struct ScriptObj *script; + ParseTokenList tokenlist; + int line = 1; + + + if (objPtr->typePtr == &sourceObjType) { + line = objPtr->internalRep.sourceValue.lineNumber; + } + + + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, scriptText, scriptTextLen, line); + while (!parser.eof) { + JimParseScript(&parser); + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + + + ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0); + + + script = Jim_Alloc(sizeof(*script)); + memset(script, 0, sizeof(*script)); + script->inUse = 1; + if (objPtr->typePtr == &sourceObjType) { + script->fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + } + else { + script->fileNameObj = interp->emptyObj; + } + Jim_IncrRefCount(script->fileNameObj); + script->missing = parser.missing.ch; + script->linenr = parser.missing.line; + + ScriptObjAddTokens(interp, script, &tokenlist); + + + ScriptTokenListFree(&tokenlist); + + + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, script); + objPtr->typePtr = &scriptObjType; +} + +static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script); + +ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr == interp->emptyObj) { + + objPtr = interp->nullScriptObj; + } + + if (objPtr->typePtr != &scriptObjType || ((struct ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags) { + JimSetScriptFromAny(interp, objPtr); + } + + return (ScriptObj *)Jim_GetIntRepPtr(objPtr); +} + +static int JimScriptValid(Jim_Interp *interp, ScriptObj *script) +{ + if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) { + JimAddErrorToStack(interp, script); + return 0; + } + return 1; +} + + +static void JimIncrCmdRefCount(Jim_Cmd *cmdPtr) +{ + cmdPtr->inUse++; +} + +static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr) +{ + if (--cmdPtr->inUse == 0) { + if (cmdPtr->isproc) { + Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr); + Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr); + Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); + if (cmdPtr->u.proc.staticVars) { + Jim_FreeHashTable(cmdPtr->u.proc.staticVars); + Jim_Free(cmdPtr->u.proc.staticVars); + } + } + else { + + if (cmdPtr->u.native.delProc) { + cmdPtr->u.native.delProc(interp, cmdPtr->u.native.privData); + } + } + if (cmdPtr->prevCmd) { + + JimDecrCmdRefCount(interp, cmdPtr->prevCmd); + } + Jim_Free(cmdPtr); + } +} + + +static void JimVariablesHTValDestructor(void *interp, void *val) +{ + Jim_DecrRefCount(interp, ((Jim_Var *)val)->objPtr); + Jim_Free(val); +} + +static const Jim_HashTableType JimVariablesHashTableType = { + JimStringCopyHTHashFunction, + JimStringCopyHTDup, + NULL, + JimStringCopyHTKeyCompare, + JimStringCopyHTKeyDestructor, + JimVariablesHTValDestructor +}; + +static void JimCommandsHT_ValDestructor(void *interp, void *val) +{ + JimDecrCmdRefCount(interp, val); +} + +static const Jim_HashTableType JimCommandsHashTableType = { + JimStringCopyHTHashFunction, + JimStringCopyHTDup, + NULL, + JimStringCopyHTKeyCompare, + JimStringCopyHTKeyDestructor, + JimCommandsHT_ValDestructor +}; + + + +#ifdef jim_ext_namespace +static Jim_Obj *JimQualifyNameObj(Jim_Interp *interp, Jim_Obj *nsObj) +{ + const char *name = Jim_String(nsObj); + if (name[0] == ':' && name[1] == ':') { + + while (*++name == ':') { + } + nsObj = Jim_NewStringObj(interp, name, -1); + } + else if (Jim_Length(interp->framePtr->nsObj)) { + + nsObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); + Jim_AppendStrings(interp, nsObj, "::", name, NULL); + } + return nsObj; +} + +Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) +{ + Jim_Obj *resultObj; + + const char *name = Jim_String(nameObjPtr); + if (name[0] == ':' && name[1] == ':') { + return nameObjPtr; + } + Jim_IncrRefCount(nameObjPtr); + resultObj = Jim_NewStringObj(interp, "::", -1); + Jim_AppendObj(interp, resultObj, nameObjPtr); + Jim_DecrRefCount(interp, nameObjPtr); + + return resultObj; +} + +static const char *JimQualifyName(Jim_Interp *interp, const char *name, Jim_Obj **objPtrPtr) +{ + Jim_Obj *objPtr = interp->emptyObj; + + if (name[0] == ':' && name[1] == ':') { + + while (*++name == ':') { + } + } + else if (Jim_Length(interp->framePtr->nsObj)) { + + objPtr = Jim_DuplicateObj(interp, interp->framePtr->nsObj); + Jim_AppendStrings(interp, objPtr, "::", name, NULL); + name = Jim_String(objPtr); + } + Jim_IncrRefCount(objPtr); + *objPtrPtr = objPtr; + return name; +} + + #define JimFreeQualifiedName(INTERP, OBJ) Jim_DecrRefCount((INTERP), (OBJ)) + +#else + + #define JimQualifyName(INTERP, NAME, DUMMY) (((NAME)[0] == ':' && (NAME)[1] == ':') ? (NAME) + 2 : (NAME)) + #define JimFreeQualifiedName(INTERP, DUMMY) (void)(DUMMY) + +Jim_Obj *Jim_MakeGlobalNamespaceName(Jim_Interp *interp, Jim_Obj *nameObjPtr) +{ + return nameObjPtr; +} +#endif + +static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd) +{ + Jim_HashEntry *he = Jim_FindHashEntry(&interp->commands, name); + if (he) { + + Jim_InterpIncrProcEpoch(interp); + } + + if (he && interp->local) { + + cmd->prevCmd = Jim_GetHashEntryVal(he); + Jim_SetHashVal(&interp->commands, he, cmd); + } + else { + if (he) { + + Jim_DeleteHashEntry(&interp->commands, name); + } + + Jim_AddHashEntry(&interp->commands, name, cmd); + } + return JIM_OK; +} + + +int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr, + Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc) +{ + Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr)); + + + memset(cmdPtr, 0, sizeof(*cmdPtr)); + cmdPtr->inUse = 1; + cmdPtr->u.native.delProc = delProc; + cmdPtr->u.native.cmdProc = cmdProc; + cmdPtr->u.native.privData = privData; + + JimCreateCommand(interp, cmdNameStr, cmdPtr); + + return JIM_OK; +} + +static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr) +{ + int len, i; + + len = Jim_ListLength(interp, staticsListObjPtr); + if (len == 0) { + return JIM_OK; + } + + cmdPtr->u.proc.staticVars = Jim_Alloc(sizeof(Jim_HashTable)); + Jim_InitHashTable(cmdPtr->u.proc.staticVars, &JimVariablesHashTableType, interp); + for (i = 0; i < len; i++) { + Jim_Obj *objPtr, *initObjPtr, *nameObjPtr; + Jim_Var *varPtr; + int subLen; + + objPtr = Jim_ListGetIndex(interp, staticsListObjPtr, i); + + subLen = Jim_ListLength(interp, objPtr); + if (subLen == 1 || subLen == 2) { + nameObjPtr = Jim_ListGetIndex(interp, objPtr, 0); + if (subLen == 1) { + initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE); + if (initObjPtr == NULL) { + Jim_SetResultFormatted(interp, + "variable for initialization of static \"%#s\" not found in the local context", + nameObjPtr); + return JIM_ERR; + } + } + else { + initObjPtr = Jim_ListGetIndex(interp, objPtr, 1); + } + if (JimValidName(interp, "static variable", nameObjPtr) != JIM_OK) { + return JIM_ERR; + } + + varPtr = Jim_Alloc(sizeof(*varPtr)); + varPtr->objPtr = initObjPtr; + Jim_IncrRefCount(initObjPtr); + varPtr->linkFramePtr = NULL; + if (Jim_AddHashEntry(cmdPtr->u.proc.staticVars, + Jim_String(nameObjPtr), varPtr) != JIM_OK) { + Jim_SetResultFormatted(interp, + "static variable name \"%#s\" duplicated in statics list", nameObjPtr); + Jim_DecrRefCount(interp, initObjPtr); + Jim_Free(varPtr); + return JIM_ERR; + } + } + else { + Jim_SetResultFormatted(interp, "too many fields in static specifier \"%#s\"", + objPtr); + return JIM_ERR; + } + } + return JIM_OK; +} + +static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, const char *cmdname) +{ +#ifdef jim_ext_namespace + if (cmdPtr->isproc) { + + const char *pt = strrchr(cmdname, ':'); + if (pt && pt != cmdname && pt[-1] == ':') { + Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj); + cmdPtr->u.proc.nsObj = Jim_NewStringObj(interp, cmdname, pt - cmdname - 1); + Jim_IncrRefCount(cmdPtr->u.proc.nsObj); + + if (Jim_FindHashEntry(&interp->commands, pt + 1)) { + + Jim_InterpIncrProcEpoch(interp); + } + } + } +#endif +} + +static Jim_Cmd *JimCreateProcedureCmd(Jim_Interp *interp, Jim_Obj *argListObjPtr, + Jim_Obj *staticsListObjPtr, Jim_Obj *bodyObjPtr, Jim_Obj *nsObj) +{ + Jim_Cmd *cmdPtr; + int argListLen; + int i; + + argListLen = Jim_ListLength(interp, argListObjPtr); + + + cmdPtr = Jim_Alloc(sizeof(*cmdPtr) + sizeof(struct Jim_ProcArg) * argListLen); + memset(cmdPtr, 0, sizeof(*cmdPtr)); + cmdPtr->inUse = 1; + cmdPtr->isproc = 1; + cmdPtr->u.proc.argListObjPtr = argListObjPtr; + cmdPtr->u.proc.argListLen = argListLen; + cmdPtr->u.proc.bodyObjPtr = bodyObjPtr; + cmdPtr->u.proc.argsPos = -1; + cmdPtr->u.proc.arglist = (struct Jim_ProcArg *)(cmdPtr + 1); + cmdPtr->u.proc.nsObj = nsObj ? nsObj : interp->emptyObj; + Jim_IncrRefCount(argListObjPtr); + Jim_IncrRefCount(bodyObjPtr); + Jim_IncrRefCount(cmdPtr->u.proc.nsObj); + + + if (staticsListObjPtr && JimCreateProcedureStatics(interp, cmdPtr, staticsListObjPtr) != JIM_OK) { + goto err; + } + + + + for (i = 0; i < argListLen; i++) { + Jim_Obj *argPtr; + Jim_Obj *nameObjPtr; + Jim_Obj *defaultObjPtr; + int len; + + + argPtr = Jim_ListGetIndex(interp, argListObjPtr, i); + len = Jim_ListLength(interp, argPtr); + if (len == 0) { + Jim_SetResultString(interp, "argument with no name", -1); +err: + JimDecrCmdRefCount(interp, cmdPtr); + return NULL; + } + if (len > 2) { + Jim_SetResultFormatted(interp, "too many fields in argument specifier \"%#s\"", argPtr); + goto err; + } + + if (len == 2) { + + nameObjPtr = Jim_ListGetIndex(interp, argPtr, 0); + defaultObjPtr = Jim_ListGetIndex(interp, argPtr, 1); + } + else { + + nameObjPtr = argPtr; + defaultObjPtr = NULL; + } + + + if (Jim_CompareStringImmediate(interp, nameObjPtr, "args")) { + if (cmdPtr->u.proc.argsPos >= 0) { + Jim_SetResultString(interp, "'args' specified more than once", -1); + goto err; + } + cmdPtr->u.proc.argsPos = i; + } + else { + if (len == 2) { + cmdPtr->u.proc.optArity++; + } + else { + cmdPtr->u.proc.reqArity++; + } + } + + cmdPtr->u.proc.arglist[i].nameObjPtr = nameObjPtr; + cmdPtr->u.proc.arglist[i].defaultObjPtr = defaultObjPtr; + } + + return cmdPtr; +} + +int Jim_DeleteCommand(Jim_Interp *interp, const char *name) +{ + int ret = JIM_OK; + Jim_Obj *qualifiedNameObj; + const char *qualname = JimQualifyName(interp, name, &qualifiedNameObj); + + if (Jim_DeleteHashEntry(&interp->commands, qualname) == JIM_ERR) { + Jim_SetResultFormatted(interp, "can't delete \"%s\": command doesn't exist", name); + ret = JIM_ERR; + } + else { + Jim_InterpIncrProcEpoch(interp); + } + + JimFreeQualifiedName(interp, qualifiedNameObj); + + return ret; +} + +int Jim_RenameCommand(Jim_Interp *interp, const char *oldName, const char *newName) +{ + int ret = JIM_ERR; + Jim_HashEntry *he; + Jim_Cmd *cmdPtr; + Jim_Obj *qualifiedOldNameObj; + Jim_Obj *qualifiedNewNameObj; + const char *fqold; + const char *fqnew; + + if (newName[0] == 0) { + return Jim_DeleteCommand(interp, oldName); + } + + fqold = JimQualifyName(interp, oldName, &qualifiedOldNameObj); + fqnew = JimQualifyName(interp, newName, &qualifiedNewNameObj); + + + he = Jim_FindHashEntry(&interp->commands, fqold); + if (he == NULL) { + Jim_SetResultFormatted(interp, "can't rename \"%s\": command doesn't exist", oldName); + } + else if (Jim_FindHashEntry(&interp->commands, fqnew)) { + Jim_SetResultFormatted(interp, "can't rename to \"%s\": command already exists", newName); + } + else { + + cmdPtr = Jim_GetHashEntryVal(he); + JimIncrCmdRefCount(cmdPtr); + JimUpdateProcNamespace(interp, cmdPtr, fqnew); + Jim_AddHashEntry(&interp->commands, fqnew, cmdPtr); + + + Jim_DeleteHashEntry(&interp->commands, fqold); + + + Jim_InterpIncrProcEpoch(interp); + + ret = JIM_OK; + } + + JimFreeQualifiedName(interp, qualifiedOldNameObj); + JimFreeQualifiedName(interp, qualifiedNewNameObj); + + return ret; +} + + +static void FreeCommandInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.cmdValue.nsObj); +} + +static void DupCommandInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + dupPtr->internalRep.cmdValue = srcPtr->internalRep.cmdValue; + dupPtr->typePtr = srcPtr->typePtr; + Jim_IncrRefCount(dupPtr->internalRep.cmdValue.nsObj); +} + +static const Jim_ObjType commandObjType = { + "command", + FreeCommandInternalRep, + DupCommandInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + +Jim_Cmd *Jim_GetCommand(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + Jim_Cmd *cmd; + + if (objPtr->typePtr != &commandObjType || + objPtr->internalRep.cmdValue.procEpoch != interp->procEpoch +#ifdef jim_ext_namespace + || !Jim_StringEqObj(objPtr->internalRep.cmdValue.nsObj, interp->framePtr->nsObj) +#endif + ) { + + + + const char *name = Jim_String(objPtr); + Jim_HashEntry *he; + + if (name[0] == ':' && name[1] == ':') { + while (*++name == ':') { + } + } +#ifdef jim_ext_namespace + else if (Jim_Length(interp->framePtr->nsObj)) { + + Jim_Obj *nameObj = Jim_DuplicateObj(interp, interp->framePtr->nsObj); + Jim_AppendStrings(interp, nameObj, "::", name, NULL); + he = Jim_FindHashEntry(&interp->commands, Jim_String(nameObj)); + Jim_FreeNewObj(interp, nameObj); + if (he) { + goto found; + } + } +#endif + + + he = Jim_FindHashEntry(&interp->commands, name); + if (he == NULL) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "invalid command name \"%#s\"", objPtr); + } + return NULL; + } +#ifdef jim_ext_namespace +found: +#endif + cmd = Jim_GetHashEntryVal(he); + + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &commandObjType; + objPtr->internalRep.cmdValue.procEpoch = interp->procEpoch; + objPtr->internalRep.cmdValue.cmdPtr = cmd; + objPtr->internalRep.cmdValue.nsObj = interp->framePtr->nsObj; + Jim_IncrRefCount(interp->framePtr->nsObj); + } + else { + cmd = objPtr->internalRep.cmdValue.cmdPtr; + } + while (cmd->u.proc.upcall) { + cmd = cmd->prevCmd; + } + return cmd; +} + + + +#define JIM_DICT_SUGAR 100 + +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType variableObjType = { + "variable", + NULL, + NULL, + NULL, + JIM_TYPE_REFERENCES, +}; + +static int JimValidName(Jim_Interp *interp, const char *type, Jim_Obj *nameObjPtr) +{ + + if (nameObjPtr->typePtr != &variableObjType) { + int len; + const char *str = Jim_GetString(nameObjPtr, &len); + if (memchr(str, '\0', len)) { + Jim_SetResultFormatted(interp, "%s name contains embedded null", type); + return JIM_ERR; + } + } + return JIM_OK; +} + +static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + const char *varName; + Jim_CallFrame *framePtr; + Jim_HashEntry *he; + int global; + int len; + + + if (objPtr->typePtr == &variableObjType) { + framePtr = objPtr->internalRep.varValue.global ? interp->topFramePtr : interp->framePtr; + if (objPtr->internalRep.varValue.callFrameId == framePtr->id) { + + return JIM_OK; + } + + } + else if (objPtr->typePtr == &dictSubstObjType) { + return JIM_DICT_SUGAR; + } + else if (JimValidName(interp, "variable", objPtr) != JIM_OK) { + return JIM_ERR; + } + + + varName = Jim_GetString(objPtr, &len); + + + if (len && varName[len - 1] == ')' && strchr(varName, '(') != NULL) { + return JIM_DICT_SUGAR; + } + + if (varName[0] == ':' && varName[1] == ':') { + while (*++varName == ':') { + } + global = 1; + framePtr = interp->topFramePtr; + } + else { + global = 0; + framePtr = interp->framePtr; + } + + + he = Jim_FindHashEntry(&framePtr->vars, varName); + if (he == NULL) { + if (!global && framePtr->staticVars) { + + he = Jim_FindHashEntry(framePtr->staticVars, varName); + } + if (he == NULL) { + return JIM_ERR; + } + } + + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &variableObjType; + objPtr->internalRep.varValue.callFrameId = framePtr->id; + objPtr->internalRep.varValue.varPtr = Jim_GetHashEntryVal(he); + objPtr->internalRep.varValue.global = global; + return JIM_OK; +} + + +static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr); +static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags); + +static Jim_Var *JimCreateVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) +{ + const char *name; + Jim_CallFrame *framePtr; + int global; + + + Jim_Var *var = Jim_Alloc(sizeof(*var)); + + var->objPtr = valObjPtr; + Jim_IncrRefCount(valObjPtr); + var->linkFramePtr = NULL; + + name = Jim_String(nameObjPtr); + if (name[0] == ':' && name[1] == ':') { + while (*++name == ':') { + } + framePtr = interp->topFramePtr; + global = 1; + } + else { + framePtr = interp->framePtr; + global = 0; + } + + + Jim_AddHashEntry(&framePtr->vars, name, var); + + + Jim_FreeIntRep(interp, nameObjPtr); + nameObjPtr->typePtr = &variableObjType; + nameObjPtr->internalRep.varValue.callFrameId = framePtr->id; + nameObjPtr->internalRep.varValue.varPtr = var; + nameObjPtr->internalRep.varValue.global = global; + + return var; +} + + +int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr) +{ + int err; + Jim_Var *var; + + switch (SetVariableFromAny(interp, nameObjPtr)) { + case JIM_DICT_SUGAR: + return JimDictSugarSet(interp, nameObjPtr, valObjPtr); + + case JIM_ERR: + if (JimValidName(interp, "variable", nameObjPtr) != JIM_OK) { + return JIM_ERR; + } + JimCreateVariable(interp, nameObjPtr, valObjPtr); + break; + + case JIM_OK: + var = nameObjPtr->internalRep.varValue.varPtr; + if (var->linkFramePtr == NULL) { + Jim_IncrRefCount(valObjPtr); + Jim_DecrRefCount(interp, var->objPtr); + var->objPtr = valObjPtr; + } + else { + Jim_CallFrame *savedCallFrame; + + savedCallFrame = interp->framePtr; + interp->framePtr = var->linkFramePtr; + err = Jim_SetVariable(interp, var->objPtr, valObjPtr); + interp->framePtr = savedCallFrame; + if (err != JIM_OK) + return err; + } + } + return JIM_OK; +} + +int Jim_SetVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) +{ + Jim_Obj *nameObjPtr; + int result; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(nameObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, objPtr); + Jim_DecrRefCount(interp, nameObjPtr); + return result; +} + +int Jim_SetGlobalVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr) +{ + Jim_CallFrame *savedFramePtr; + int result; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + result = Jim_SetVariableStr(interp, name, objPtr); + interp->framePtr = savedFramePtr; + return result; +} + +int Jim_SetVariableStrWithStr(Jim_Interp *interp, const char *name, const char *val) +{ + Jim_Obj *nameObjPtr, *valObjPtr; + int result; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + valObjPtr = Jim_NewStringObj(interp, val, -1); + Jim_IncrRefCount(nameObjPtr); + Jim_IncrRefCount(valObjPtr); + result = Jim_SetVariable(interp, nameObjPtr, valObjPtr); + Jim_DecrRefCount(interp, nameObjPtr); + Jim_DecrRefCount(interp, valObjPtr); + return result; +} + +int Jim_SetVariableLink(Jim_Interp *interp, Jim_Obj *nameObjPtr, + Jim_Obj *targetNameObjPtr, Jim_CallFrame *targetCallFrame) +{ + const char *varName; + const char *targetName; + Jim_CallFrame *framePtr; + Jim_Var *varPtr; + + + switch (SetVariableFromAny(interp, nameObjPtr)) { + case JIM_DICT_SUGAR: + + Jim_SetResultFormatted(interp, "bad variable name \"%#s\": upvar won't create a scalar variable that looks like an array element", nameObjPtr); + return JIM_ERR; + + case JIM_OK: + varPtr = nameObjPtr->internalRep.varValue.varPtr; + + if (varPtr->linkFramePtr == NULL) { + Jim_SetResultFormatted(interp, "variable \"%#s\" already exists", nameObjPtr); + return JIM_ERR; + } + + + varPtr->linkFramePtr = NULL; + break; + } + + + + varName = Jim_String(nameObjPtr); + + if (varName[0] == ':' && varName[1] == ':') { + while (*++varName == ':') { + } + + framePtr = interp->topFramePtr; + } + else { + framePtr = interp->framePtr; + } + + targetName = Jim_String(targetNameObjPtr); + if (targetName[0] == ':' && targetName[1] == ':') { + while (*++targetName == ':') { + } + targetNameObjPtr = Jim_NewStringObj(interp, targetName, -1); + targetCallFrame = interp->topFramePtr; + } + Jim_IncrRefCount(targetNameObjPtr); + + if (framePtr->level < targetCallFrame->level) { + Jim_SetResultFormatted(interp, + "bad variable name \"%#s\": upvar won't create namespace variable that refers to procedure variable", + nameObjPtr); + Jim_DecrRefCount(interp, targetNameObjPtr); + return JIM_ERR; + } + + + if (framePtr == targetCallFrame) { + Jim_Obj *objPtr = targetNameObjPtr; + + + while (1) { + if (strcmp(Jim_String(objPtr), varName) == 0) { + Jim_SetResultString(interp, "can't upvar from variable to itself", -1); + Jim_DecrRefCount(interp, targetNameObjPtr); + return JIM_ERR; + } + if (SetVariableFromAny(interp, objPtr) != JIM_OK) + break; + varPtr = objPtr->internalRep.varValue.varPtr; + if (varPtr->linkFramePtr != targetCallFrame) + break; + objPtr = varPtr->objPtr; + } + } + + + Jim_SetVariable(interp, nameObjPtr, targetNameObjPtr); + + nameObjPtr->internalRep.varValue.varPtr->linkFramePtr = targetCallFrame; + Jim_DecrRefCount(interp, targetNameObjPtr); + return JIM_OK; +} + +Jim_Obj *Jim_GetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + switch (SetVariableFromAny(interp, nameObjPtr)) { + case JIM_OK:{ + Jim_Var *varPtr = nameObjPtr->internalRep.varValue.varPtr; + + if (varPtr->linkFramePtr == NULL) { + return varPtr->objPtr; + } + else { + Jim_Obj *objPtr; + + + Jim_CallFrame *savedCallFrame = interp->framePtr; + + interp->framePtr = varPtr->linkFramePtr; + objPtr = Jim_GetVariable(interp, varPtr->objPtr, flags); + interp->framePtr = savedCallFrame; + if (objPtr) { + return objPtr; + } + + } + } + break; + + case JIM_DICT_SUGAR: + + return JimDictSugarGet(interp, nameObjPtr, flags); + } + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "can't read \"%#s\": no such variable", nameObjPtr); + } + return NULL; +} + +Jim_Obj *Jim_GetGlobalVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + Jim_CallFrame *savedFramePtr; + Jim_Obj *objPtr; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + objPtr = Jim_GetVariable(interp, nameObjPtr, flags); + interp->framePtr = savedFramePtr; + + return objPtr; +} + +Jim_Obj *Jim_GetVariableStr(Jim_Interp *interp, const char *name, int flags) +{ + Jim_Obj *nameObjPtr, *varObjPtr; + + nameObjPtr = Jim_NewStringObj(interp, name, -1); + Jim_IncrRefCount(nameObjPtr); + varObjPtr = Jim_GetVariable(interp, nameObjPtr, flags); + Jim_DecrRefCount(interp, nameObjPtr); + return varObjPtr; +} + +Jim_Obj *Jim_GetGlobalVariableStr(Jim_Interp *interp, const char *name, int flags) +{ + Jim_CallFrame *savedFramePtr; + Jim_Obj *objPtr; + + savedFramePtr = interp->framePtr; + interp->framePtr = interp->topFramePtr; + objPtr = Jim_GetVariableStr(interp, name, flags); + interp->framePtr = savedFramePtr; + + return objPtr; +} + +int Jim_UnsetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int flags) +{ + Jim_Var *varPtr; + int retval; + Jim_CallFrame *framePtr; + + retval = SetVariableFromAny(interp, nameObjPtr); + if (retval == JIM_DICT_SUGAR) { + + return JimDictSugarSet(interp, nameObjPtr, NULL); + } + else if (retval == JIM_OK) { + varPtr = nameObjPtr->internalRep.varValue.varPtr; + + + if (varPtr->linkFramePtr) { + framePtr = interp->framePtr; + interp->framePtr = varPtr->linkFramePtr; + retval = Jim_UnsetVariable(interp, varPtr->objPtr, JIM_NONE); + interp->framePtr = framePtr; + } + else { + const char *name = Jim_String(nameObjPtr); + if (nameObjPtr->internalRep.varValue.global) { + name += 2; + framePtr = interp->topFramePtr; + } + else { + framePtr = interp->framePtr; + } + + retval = Jim_DeleteHashEntry(&framePtr->vars, name); + if (retval == JIM_OK) { + + framePtr->id = interp->callFrameEpoch++; + } + } + } + if (retval != JIM_OK && (flags & JIM_ERRMSG)) { + Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such variable", nameObjPtr); + } + return retval; +} + + + +static void JimDictSugarParseVarKey(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj **varPtrPtr, Jim_Obj **keyPtrPtr) +{ + const char *str, *p; + int len, keyLen; + Jim_Obj *varObjPtr, *keyObjPtr; + + str = Jim_GetString(objPtr, &len); + + p = strchr(str, '('); + JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str)); + + varObjPtr = Jim_NewStringObj(interp, str, p - str); + + p++; + keyLen = (str + len) - p; + if (str[len - 1] == ')') { + keyLen--; + } + + + keyObjPtr = Jim_NewStringObj(interp, p, keyLen); + + Jim_IncrRefCount(varObjPtr); + Jim_IncrRefCount(keyObjPtr); + *varPtrPtr = varObjPtr; + *keyPtrPtr = keyObjPtr; +} + +static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *valObjPtr) +{ + int err; + + SetDictSubstFromAny(interp, objPtr); + + err = Jim_SetDictKeysVector(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, + &objPtr->internalRep.dictSubstValue.indexObjPtr, 1, valObjPtr, JIM_MUSTEXIST); + + if (err == JIM_OK) { + + Jim_SetEmptyResult(interp); + } + else { + if (!valObjPtr) { + + if (Jim_GetVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE)) { + Jim_SetResultFormatted(interp, "can't unset \"%#s\": no such element in array", + objPtr); + return err; + } + } + + Jim_SetResultFormatted(interp, "can't %s \"%#s\": variable isn't array", + (valObjPtr ? "set" : "unset"), objPtr); + } + return err; +} + +static Jim_Obj *JimDictExpandArrayVariable(Jim_Interp *interp, Jim_Obj *varObjPtr, + Jim_Obj *keyObjPtr, int flags) +{ + Jim_Obj *dictObjPtr; + Jim_Obj *resObjPtr = NULL; + int ret; + + dictObjPtr = Jim_GetVariable(interp, varObjPtr, JIM_ERRMSG); + if (!dictObjPtr) { + return NULL; + } + + ret = Jim_DictKey(interp, dictObjPtr, keyObjPtr, &resObjPtr, JIM_NONE); + if (ret != JIM_OK) { + Jim_SetResultFormatted(interp, + "can't read \"%#s(%#s)\": %s array", varObjPtr, keyObjPtr, + ret < 0 ? "variable isn't" : "no such element in"); + } + else if ((flags & JIM_UNSHARED) && Jim_IsShared(dictObjPtr)) { + + Jim_SetVariable(interp, varObjPtr, Jim_DuplicateObj(interp, dictObjPtr)); + } + + return resObjPtr; +} + + +static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + SetDictSubstFromAny(interp, objPtr); + + return JimDictExpandArrayVariable(interp, + objPtr->internalRep.dictSubstValue.varNameObjPtr, + objPtr->internalRep.dictSubstValue.indexObjPtr, flags); +} + + + +void FreeDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr); + Jim_DecrRefCount(interp, objPtr->internalRep.dictSubstValue.indexObjPtr); +} + +void DupDictSubstInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + + dupPtr->internalRep.dictSubstValue.varNameObjPtr = + srcPtr->internalRep.dictSubstValue.varNameObjPtr; + dupPtr->internalRep.dictSubstValue.indexObjPtr = srcPtr->internalRep.dictSubstValue.indexObjPtr; + dupPtr->typePtr = &dictSubstObjType; +} + + +static void SetDictSubstFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &dictSubstObjType) { + Jim_Obj *varObjPtr, *keyObjPtr; + + if (objPtr->typePtr == &interpolatedObjType) { + + + varObjPtr = objPtr->internalRep.dictSubstValue.varNameObjPtr; + keyObjPtr = objPtr->internalRep.dictSubstValue.indexObjPtr; + + Jim_IncrRefCount(varObjPtr); + Jim_IncrRefCount(keyObjPtr); + } + else { + JimDictSugarParseVarKey(interp, objPtr, &varObjPtr, &keyObjPtr); + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &dictSubstObjType; + objPtr->internalRep.dictSubstValue.varNameObjPtr = varObjPtr; + objPtr->internalRep.dictSubstValue.indexObjPtr = keyObjPtr; + } +} + +static Jim_Obj *JimExpandDictSugar(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *resObjPtr = NULL; + Jim_Obj *substKeyObjPtr = NULL; + + SetDictSubstFromAny(interp, objPtr); + + if (Jim_SubstObj(interp, objPtr->internalRep.dictSubstValue.indexObjPtr, + &substKeyObjPtr, JIM_NONE) + != JIM_OK) { + return NULL; + } + Jim_IncrRefCount(substKeyObjPtr); + resObjPtr = + JimDictExpandArrayVariable(interp, objPtr->internalRep.dictSubstValue.varNameObjPtr, + substKeyObjPtr, 0); + Jim_DecrRefCount(interp, substKeyObjPtr); + + return resObjPtr; +} + +static Jim_Obj *JimExpandExprSugar(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_Obj *resultObjPtr; + + if (Jim_EvalExpression(interp, objPtr, &resultObjPtr) == JIM_OK) { + + resultObjPtr->refCount--; + return resultObjPtr; + } + return NULL; +} + + +static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *parent, Jim_Obj *nsObj) +{ + Jim_CallFrame *cf; + + if (interp->freeFramesList) { + cf = interp->freeFramesList; + interp->freeFramesList = cf->next; + + cf->argv = NULL; + cf->argc = 0; + cf->procArgsObjPtr = NULL; + cf->procBodyObjPtr = NULL; + cf->next = NULL; + cf->staticVars = NULL; + cf->localCommands = NULL; + cf->tailcall = 0; + cf->tailcallObj = NULL; + cf->tailcallCmd = NULL; + } + else { + cf = Jim_Alloc(sizeof(*cf)); + memset(cf, 0, sizeof(*cf)); + + Jim_InitHashTable(&cf->vars, &JimVariablesHashTableType, interp); + } + + cf->id = interp->callFrameEpoch++; + cf->parent = parent; + cf->level = parent ? parent->level + 1 : 0; + cf->nsObj = nsObj; + Jim_IncrRefCount(nsObj); + + return cf; +} + +static int JimDeleteLocalProcs(Jim_Interp *interp, Jim_Stack *localCommands) +{ + + if (localCommands) { + Jim_Obj *cmdNameObj; + + while ((cmdNameObj = Jim_StackPop(localCommands)) != NULL) { + Jim_HashEntry *he; + Jim_Obj *fqObjName; + Jim_HashTable *ht = &interp->commands; + + const char *fqname = JimQualifyName(interp, Jim_String(cmdNameObj), &fqObjName); + + he = Jim_FindHashEntry(ht, fqname); + + if (he) { + Jim_Cmd *cmd = Jim_GetHashEntryVal(he); + if (cmd->prevCmd) { + Jim_Cmd *prevCmd = cmd->prevCmd; + cmd->prevCmd = NULL; + + + JimDecrCmdRefCount(interp, cmd); + + + Jim_SetHashVal(ht, he, prevCmd); + } + else { + Jim_DeleteHashEntry(ht, fqname); + Jim_InterpIncrProcEpoch(interp); + } + } + Jim_DecrRefCount(interp, cmdNameObj); + JimFreeQualifiedName(interp, fqObjName); + } + Jim_FreeStack(localCommands); + Jim_Free(localCommands); + } + return JIM_OK; +} + + +#define JIM_FCF_FULL 0 +#define JIM_FCF_REUSE 1 +static void JimFreeCallFrame(Jim_Interp *interp, Jim_CallFrame *cf, int action) + { + JimDeleteLocalProcs(interp, cf->localCommands); + + if (cf->procArgsObjPtr) + Jim_DecrRefCount(interp, cf->procArgsObjPtr); + if (cf->procBodyObjPtr) + Jim_DecrRefCount(interp, cf->procBodyObjPtr); + Jim_DecrRefCount(interp, cf->nsObj); + if (action == JIM_FCF_FULL || cf->vars.size != JIM_HT_INITIAL_SIZE) + Jim_FreeHashTable(&cf->vars); + else { + int i; + Jim_HashEntry **table = cf->vars.table, *he; + + for (i = 0; i < JIM_HT_INITIAL_SIZE; i++) { + he = table[i]; + while (he != NULL) { + Jim_HashEntry *nextEntry = he->next; + Jim_Var *varPtr = Jim_GetHashEntryVal(he); + + Jim_DecrRefCount(interp, varPtr->objPtr); + Jim_Free(Jim_GetHashEntryKey(he)); + Jim_Free(varPtr); + Jim_Free(he); + table[i] = NULL; + he = nextEntry; + } + } + cf->vars.used = 0; + } + cf->next = interp->freeFramesList; + interp->freeFramesList = cf; +} + + +#ifdef JIM_REFERENCES + +static void JimReferencesHTValDestructor(void *interp, void *val) +{ + Jim_Reference *refPtr = (void *)val; + + Jim_DecrRefCount(interp, refPtr->objPtr); + if (refPtr->finalizerCmdNamePtr != NULL) { + Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); + } + Jim_Free(val); +} + +static unsigned int JimReferencesHTHashFunction(const void *key) +{ + + const unsigned long *widePtr = key; + unsigned int intValue = (unsigned int)*widePtr; + + return Jim_IntHashFunction(intValue); +} + +static void *JimReferencesHTKeyDup(void *privdata, const void *key) +{ + void *copy = Jim_Alloc(sizeof(unsigned long)); + + JIM_NOTUSED(privdata); + + memcpy(copy, key, sizeof(unsigned long)); + return copy; +} + +static int JimReferencesHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + JIM_NOTUSED(privdata); + + return memcmp(key1, key2, sizeof(unsigned long)) == 0; +} + +static void JimReferencesHTKeyDestructor(void *privdata, void *key) +{ + JIM_NOTUSED(privdata); + + Jim_Free(key); +} + +static const Jim_HashTableType JimReferencesHashTableType = { + JimReferencesHTHashFunction, + JimReferencesHTKeyDup, + NULL, + JimReferencesHTKeyCompare, + JimReferencesHTKeyDestructor, + JimReferencesHTValDestructor +}; + + + +#define JIM_REFERENCE_SPACE (35+JIM_REFERENCE_TAGLEN) + +static int JimFormatReference(char *buf, Jim_Reference *refPtr, unsigned long id) +{ + const char *fmt = ".%020lu>"; + + sprintf(buf, fmt, refPtr->tag, id); + return JIM_REFERENCE_SPACE; +} + +static void UpdateStringOfReference(struct Jim_Obj *objPtr); + +static const Jim_ObjType referenceObjType = { + "reference", + NULL, + NULL, + UpdateStringOfReference, + JIM_TYPE_REFERENCES, +}; + +static void UpdateStringOfReference(struct Jim_Obj *objPtr) +{ + char buf[JIM_REFERENCE_SPACE + 1]; + + JimFormatReference(buf, objPtr->internalRep.refValue.refPtr, objPtr->internalRep.refValue.id); + JimSetStringBytes(objPtr, buf); +} + +static int isrefchar(int c) +{ + return (c == '_' || isalnum(c)); +} + +static int SetReferenceFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + unsigned long value; + int i, len; + const char *str, *start, *end; + char refId[21]; + Jim_Reference *refPtr; + Jim_HashEntry *he; + char *endptr; + + + str = Jim_GetString(objPtr, &len); + + if (len < JIM_REFERENCE_SPACE) + goto badformat; + + start = str; + end = str + len - 1; + while (*start == ' ') + start++; + while (*end == ' ' && end > start) + end--; + if (end - start + 1 != JIM_REFERENCE_SPACE) + goto badformat; + + if (memcmp(start, "references, &value); + if (he == NULL) { + Jim_SetResultFormatted(interp, "invalid reference id \"%#s\"", objPtr); + return JIM_ERR; + } + refPtr = Jim_GetHashEntryVal(he); + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &referenceObjType; + objPtr->internalRep.refValue.id = value; + objPtr->internalRep.refValue.refPtr = refPtr; + return JIM_OK; + + badformat: + Jim_SetResultFormatted(interp, "expected reference but got \"%#s\"", objPtr); + return JIM_ERR; +} + +Jim_Obj *Jim_NewReference(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *tagPtr, Jim_Obj *cmdNamePtr) +{ + struct Jim_Reference *refPtr; + unsigned long id; + Jim_Obj *refObjPtr; + const char *tag; + int tagLen, i; + + + Jim_CollectIfNeeded(interp); + + refPtr = Jim_Alloc(sizeof(*refPtr)); + refPtr->objPtr = objPtr; + Jim_IncrRefCount(objPtr); + refPtr->finalizerCmdNamePtr = cmdNamePtr; + if (cmdNamePtr) + Jim_IncrRefCount(cmdNamePtr); + id = interp->referenceNextId++; + Jim_AddHashEntry(&interp->references, &id, refPtr); + refObjPtr = Jim_NewObj(interp); + refObjPtr->typePtr = &referenceObjType; + refObjPtr->bytes = NULL; + refObjPtr->internalRep.refValue.id = id; + refObjPtr->internalRep.refValue.refPtr = refPtr; + interp->referenceNextId++; + tag = Jim_GetString(tagPtr, &tagLen); + if (tagLen > JIM_REFERENCE_TAGLEN) + tagLen = JIM_REFERENCE_TAGLEN; + for (i = 0; i < JIM_REFERENCE_TAGLEN; i++) { + if (i < tagLen && isrefchar(tag[i])) + refPtr->tag[i] = tag[i]; + else + refPtr->tag[i] = '_'; + } + refPtr->tag[JIM_REFERENCE_TAGLEN] = '\0'; + return refObjPtr; +} + +Jim_Reference *Jim_GetReference(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &referenceObjType && SetReferenceFromAny(interp, objPtr) == JIM_ERR) + return NULL; + return objPtr->internalRep.refValue.refPtr; +} + +int Jim_SetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *cmdNamePtr) +{ + Jim_Reference *refPtr; + + if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) + return JIM_ERR; + Jim_IncrRefCount(cmdNamePtr); + if (refPtr->finalizerCmdNamePtr) + Jim_DecrRefCount(interp, refPtr->finalizerCmdNamePtr); + refPtr->finalizerCmdNamePtr = cmdNamePtr; + return JIM_OK; +} + +int Jim_GetFinalizer(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj **cmdNamePtrPtr) +{ + Jim_Reference *refPtr; + + if ((refPtr = Jim_GetReference(interp, objPtr)) == NULL) + return JIM_ERR; + *cmdNamePtrPtr = refPtr->finalizerCmdNamePtr; + return JIM_OK; +} + + + +static const Jim_HashTableType JimRefMarkHashTableType = { + JimReferencesHTHashFunction, + JimReferencesHTKeyDup, + NULL, + JimReferencesHTKeyCompare, + JimReferencesHTKeyDestructor, + NULL +}; + + +int Jim_Collect(Jim_Interp *interp) +{ + int collected = 0; + return collected; +} + +#define JIM_COLLECT_ID_PERIOD 5000 +#define JIM_COLLECT_TIME_PERIOD 300 + +void Jim_CollectIfNeeded(Jim_Interp *interp) +{ + unsigned long elapsedId; + int elapsedTime; + + elapsedId = interp->referenceNextId - interp->lastCollectId; + elapsedTime = time(NULL) - interp->lastCollectTime; + + + if (elapsedId > JIM_COLLECT_ID_PERIOD || elapsedTime > JIM_COLLECT_TIME_PERIOD) { + Jim_Collect(interp); + } +} +#endif + +int Jim_IsBigEndian(void) +{ + union { + unsigned short s; + unsigned char c[2]; + } uval = {0x0102}; + + return uval.c[0] == 1; +} + + +Jim_Interp *Jim_CreateInterp(void) +{ + Jim_Interp *i = Jim_Alloc(sizeof(*i)); + + memset(i, 0, sizeof(*i)); + + i->maxCallFrameDepth = JIM_MAX_CALLFRAME_DEPTH; + i->maxEvalDepth = JIM_MAX_EVAL_DEPTH; + i->lastCollectTime = time(NULL); + + Jim_InitHashTable(&i->commands, &JimCommandsHashTableType, i); +#ifdef JIM_REFERENCES + Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i); +#endif + Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i); + Jim_InitHashTable(&i->packages, &JimPackageHashTableType, NULL); + i->emptyObj = Jim_NewEmptyStringObj(i); + i->trueObj = Jim_NewIntObj(i, 1); + i->falseObj = Jim_NewIntObj(i, 0); + i->framePtr = i->topFramePtr = JimCreateCallFrame(i, NULL, i->emptyObj); + i->errorFileNameObj = i->emptyObj; + i->result = i->emptyObj; + i->stackTrace = Jim_NewListObj(i, NULL, 0); + i->unknown = Jim_NewStringObj(i, "unknown", -1); + i->errorProc = i->emptyObj; + i->currentScriptObj = Jim_NewEmptyStringObj(i); + i->nullScriptObj = Jim_NewEmptyStringObj(i); + Jim_IncrRefCount(i->emptyObj); + Jim_IncrRefCount(i->errorFileNameObj); + Jim_IncrRefCount(i->result); + Jim_IncrRefCount(i->stackTrace); + Jim_IncrRefCount(i->unknown); + Jim_IncrRefCount(i->currentScriptObj); + Jim_IncrRefCount(i->nullScriptObj); + Jim_IncrRefCount(i->errorProc); + Jim_IncrRefCount(i->trueObj); + Jim_IncrRefCount(i->falseObj); + + + Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY); + Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0"); + + Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS); + Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM); + Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR); + Jim_SetVariableStrWithStr(i, "tcl_platform(byteOrder)", Jim_IsBigEndian() ? "bigEndian" : "littleEndian"); + Jim_SetVariableStrWithStr(i, "tcl_platform(threaded)", "0"); + Jim_SetVariableStr(i, "tcl_platform(pointerSize)", Jim_NewIntObj(i, sizeof(void *))); + Jim_SetVariableStr(i, "tcl_platform(wordSize)", Jim_NewIntObj(i, sizeof(jim_wide))); + + return i; +} + +void Jim_FreeInterp(Jim_Interp *i) +{ + Jim_CallFrame *cf, *cfx; + + Jim_Obj *objPtr, *nextObjPtr; + + + for (cf = i->framePtr; cf; cf = cfx) { + cfx = cf->parent; + JimFreeCallFrame(i, cf, JIM_FCF_FULL); + } + + Jim_DecrRefCount(i, i->emptyObj); + Jim_DecrRefCount(i, i->trueObj); + Jim_DecrRefCount(i, i->falseObj); + Jim_DecrRefCount(i, i->result); + Jim_DecrRefCount(i, i->stackTrace); + Jim_DecrRefCount(i, i->errorProc); + Jim_DecrRefCount(i, i->unknown); + Jim_DecrRefCount(i, i->errorFileNameObj); + Jim_DecrRefCount(i, i->currentScriptObj); + Jim_DecrRefCount(i, i->nullScriptObj); + Jim_FreeHashTable(&i->commands); +#ifdef JIM_REFERENCES + Jim_FreeHashTable(&i->references); +#endif + Jim_FreeHashTable(&i->packages); + Jim_Free(i->prngState); + Jim_FreeHashTable(&i->assocData); + +#ifdef JIM_MAINTAINER + if (i->liveList != NULL) { + objPtr = i->liveList; + + printf("\n-------------------------------------\n"); + printf("Objects still in the free list:\n"); + while (objPtr) { + const char *type = objPtr->typePtr ? objPtr->typePtr->name : "string"; + + if (objPtr->bytes && strlen(objPtr->bytes) > 20) { + printf("%p (%d) %-10s: '%.20s...'\n", + (void *)objPtr, objPtr->refCount, type, objPtr->bytes); + } + else { + printf("%p (%d) %-10s: '%s'\n", + (void *)objPtr, objPtr->refCount, type, objPtr->bytes ? objPtr->bytes : "(null)"); + } + if (objPtr->typePtr == &sourceObjType) { + printf("FILE %s LINE %d\n", + Jim_String(objPtr->internalRep.sourceValue.fileNameObj), + objPtr->internalRep.sourceValue.lineNumber); + } + objPtr = objPtr->nextObjPtr; + } + printf("-------------------------------------\n\n"); + JimPanic((1, "Live list non empty freeing the interpreter! Leak?")); + } +#endif + + + objPtr = i->freeList; + while (objPtr) { + nextObjPtr = objPtr->nextObjPtr; + Jim_Free(objPtr); + objPtr = nextObjPtr; + } + + + for (cf = i->freeFramesList; cf; cf = cfx) { + cfx = cf->next; + if (cf->vars.table) + Jim_FreeHashTable(&cf->vars); + Jim_Free(cf); + } + + + Jim_Free(i); +} + +Jim_CallFrame *Jim_GetCallFrameByLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr) +{ + long level; + const char *str; + Jim_CallFrame *framePtr; + + if (levelObjPtr) { + str = Jim_String(levelObjPtr); + if (str[0] == '#') { + char *endptr; + + level = jim_strtol(str + 1, &endptr); + if (str[1] == '\0' || endptr[0] != '\0') { + level = -1; + } + } + else { + if (Jim_GetLong(interp, levelObjPtr, &level) != JIM_OK || level < 0) { + level = -1; + } + else { + + level = interp->framePtr->level - level; + } + } + } + else { + str = "1"; + level = interp->framePtr->level - 1; + } + + if (level == 0) { + return interp->topFramePtr; + } + if (level > 0) { + + for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { + if (framePtr->level == level) { + return framePtr; + } + } + } + + Jim_SetResultFormatted(interp, "bad level \"%s\"", str); + return NULL; +} + +static Jim_CallFrame *JimGetCallFrameByInteger(Jim_Interp *interp, Jim_Obj *levelObjPtr) +{ + long level; + Jim_CallFrame *framePtr; + + if (Jim_GetLong(interp, levelObjPtr, &level) == JIM_OK) { + if (level <= 0) { + + level = interp->framePtr->level + level; + } + + if (level == 0) { + return interp->topFramePtr; + } + + + for (framePtr = interp->framePtr; framePtr; framePtr = framePtr->parent) { + if (framePtr->level == level) { + return framePtr; + } + } + } + + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); + return NULL; +} + +static void JimResetStackTrace(Jim_Interp *interp) +{ + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = Jim_NewListObj(interp, NULL, 0); + Jim_IncrRefCount(interp->stackTrace); +} + +static void JimSetStackTrace(Jim_Interp *interp, Jim_Obj *stackTraceObj) +{ + int len; + + + Jim_IncrRefCount(stackTraceObj); + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = stackTraceObj; + interp->errorFlag = 1; + + len = Jim_ListLength(interp, interp->stackTrace); + if (len >= 3) { + if (Jim_Length(Jim_ListGetIndex(interp, interp->stackTrace, len - 2)) == 0) { + interp->addStackTrace = 1; + } + } +} + +static void JimAppendStackTrace(Jim_Interp *interp, const char *procname, + Jim_Obj *fileNameObj, int linenr) +{ + if (strcmp(procname, "unknown") == 0) { + procname = ""; + } + if (!*procname && !Jim_Length(fileNameObj)) { + + return; + } + + if (Jim_IsShared(interp->stackTrace)) { + Jim_DecrRefCount(interp, interp->stackTrace); + interp->stackTrace = Jim_DuplicateObj(interp, interp->stackTrace); + Jim_IncrRefCount(interp->stackTrace); + } + + + if (!*procname && Jim_Length(fileNameObj)) { + + int len = Jim_ListLength(interp, interp->stackTrace); + + if (len >= 3) { + Jim_Obj *objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 3); + if (Jim_Length(objPtr)) { + + objPtr = Jim_ListGetIndex(interp, interp->stackTrace, len - 2); + if (Jim_Length(objPtr) == 0) { + + ListSetIndex(interp, interp->stackTrace, len - 2, fileNameObj, 0); + ListSetIndex(interp, interp->stackTrace, len - 1, Jim_NewIntObj(interp, linenr), 0); + return; + } + } + } + } + + Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewStringObj(interp, procname, -1)); + Jim_ListAppendElement(interp, interp->stackTrace, fileNameObj); + Jim_ListAppendElement(interp, interp->stackTrace, Jim_NewIntObj(interp, linenr)); +} + +int Jim_SetAssocData(Jim_Interp *interp, const char *key, Jim_InterpDeleteProc * delProc, + void *data) +{ + AssocDataValue *assocEntryPtr = (AssocDataValue *) Jim_Alloc(sizeof(AssocDataValue)); + + assocEntryPtr->delProc = delProc; + assocEntryPtr->data = data; + return Jim_AddHashEntry(&interp->assocData, key, assocEntryPtr); +} + +void *Jim_GetAssocData(Jim_Interp *interp, const char *key) +{ + Jim_HashEntry *entryPtr = Jim_FindHashEntry(&interp->assocData, key); + + if (entryPtr != NULL) { + AssocDataValue *assocEntryPtr = Jim_GetHashEntryVal(entryPtr); + return assocEntryPtr->data; + } + return NULL; +} + +int Jim_DeleteAssocData(Jim_Interp *interp, const char *key) +{ + return Jim_DeleteHashEntry(&interp->assocData, key); +} + +int Jim_GetExitCode(Jim_Interp *interp) +{ + return interp->exitCode; +} + +static void UpdateStringOfInt(struct Jim_Obj *objPtr); +static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags); + +static const Jim_ObjType intObjType = { + "int", + NULL, + NULL, + UpdateStringOfInt, + JIM_TYPE_NONE, +}; + +static const Jim_ObjType coercedDoubleObjType = { + "coerced-double", + NULL, + NULL, + UpdateStringOfInt, + JIM_TYPE_NONE, +}; + + +static void UpdateStringOfInt(struct Jim_Obj *objPtr) +{ + char buf[JIM_INTEGER_SPACE + 1]; + jim_wide wideValue = JimWideValue(objPtr); + int pos = 0; + + if (wideValue == 0) { + buf[pos++] = '0'; + } + else { + char tmp[JIM_INTEGER_SPACE]; + int num = 0; + int i; + + if (wideValue < 0) { + buf[pos++] = '-'; + i = wideValue % 10; + tmp[num++] = (i > 0) ? (10 - i) : -i; + wideValue /= -10; + } + + while (wideValue) { + tmp[num++] = wideValue % 10; + wideValue /= 10; + } + + for (i = 0; i < num; i++) { + buf[pos++] = '0' + tmp[num - i - 1]; + } + } + buf[pos] = 0; + + JimSetStringBytes(objPtr, buf); +} + +static int SetIntFromAny(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + jim_wide wideValue; + const char *str; + + if (objPtr->typePtr == &coercedDoubleObjType) { + + objPtr->typePtr = &intObjType; + return JIM_OK; + } + + + str = Jim_String(objPtr); + + if (Jim_StringToWide(str, &wideValue, 0) != JIM_OK) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "expected integer but got \"%#s\"", objPtr); + } + return JIM_ERR; + } + if ((wideValue == JIM_WIDE_MIN || wideValue == JIM_WIDE_MAX) && errno == ERANGE) { + Jim_SetResultString(interp, "Integer value too big to be represented", -1); + return JIM_ERR; + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &intObjType; + objPtr->internalRep.wideValue = wideValue; + return JIM_OK; +} + +#ifdef JIM_OPTIMIZATION +static int JimIsWide(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &intObjType; +} +#endif + +int Jim_GetWide(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) +{ + if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_ERRMSG) == JIM_ERR) + return JIM_ERR; + *widePtr = JimWideValue(objPtr); + return JIM_OK; +} + + +static int JimGetWideNoErr(Jim_Interp *interp, Jim_Obj *objPtr, jim_wide * widePtr) +{ + if (objPtr->typePtr != &intObjType && SetIntFromAny(interp, objPtr, JIM_NONE) == JIM_ERR) + return JIM_ERR; + *widePtr = JimWideValue(objPtr); + return JIM_OK; +} + +int Jim_GetLong(Jim_Interp *interp, Jim_Obj *objPtr, long *longPtr) +{ + jim_wide wideValue; + int retval; + + retval = Jim_GetWide(interp, objPtr, &wideValue); + if (retval == JIM_OK) { + *longPtr = (long)wideValue; + return JIM_OK; + } + return JIM_ERR; +} + +Jim_Obj *Jim_NewIntObj(Jim_Interp *interp, jim_wide wideValue) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &intObjType; + objPtr->bytes = NULL; + objPtr->internalRep.wideValue = wideValue; + return objPtr; +} + +#define JIM_DOUBLE_SPACE 30 + +static void UpdateStringOfDouble(struct Jim_Obj *objPtr); +static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr); + +static const Jim_ObjType doubleObjType = { + "double", + NULL, + NULL, + UpdateStringOfDouble, + JIM_TYPE_NONE, +}; + +#ifndef HAVE_ISNAN +#undef isnan +#define isnan(X) ((X) != (X)) +#endif +#ifndef HAVE_ISINF +#undef isinf +#define isinf(X) (1.0 / (X) == 0.0) +#endif + +static void UpdateStringOfDouble(struct Jim_Obj *objPtr) +{ + double value = objPtr->internalRep.doubleValue; + + if (isnan(value)) { + JimSetStringBytes(objPtr, "NaN"); + return; + } + if (isinf(value)) { + if (value < 0) { + JimSetStringBytes(objPtr, "-Inf"); + } + else { + JimSetStringBytes(objPtr, "Inf"); + } + return; + } + { + char buf[JIM_DOUBLE_SPACE + 1]; + int i; + int len = sprintf(buf, "%.12g", value); + + + for (i = 0; i < len; i++) { + if (buf[i] == '.' || buf[i] == 'e') { +#if defined(JIM_SPRINTF_DOUBLE_NEEDS_FIX) + char *e = strchr(buf, 'e'); + if (e && (e[1] == '-' || e[1] == '+') && e[2] == '0') { + + e += 2; + memmove(e, e + 1, len - (e - buf)); + } +#endif + break; + } + } + if (buf[i] == '\0') { + buf[i++] = '.'; + buf[i++] = '0'; + buf[i] = '\0'; + } + JimSetStringBytes(objPtr, buf); + } +} + +static int SetDoubleFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + double doubleValue; + jim_wide wideValue; + const char *str; + + str = Jim_String(objPtr); + +#ifdef HAVE_LONG_LONG + +#define MIN_INT_IN_DOUBLE -(1LL << 53) +#define MAX_INT_IN_DOUBLE -(MIN_INT_IN_DOUBLE + 1) + + if (objPtr->typePtr == &intObjType + && JimWideValue(objPtr) >= MIN_INT_IN_DOUBLE + && JimWideValue(objPtr) <= MAX_INT_IN_DOUBLE) { + + + objPtr->typePtr = &coercedDoubleObjType; + return JIM_OK; + } + else +#endif + if (Jim_StringToWide(str, &wideValue, 10) == JIM_OK) { + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &coercedDoubleObjType; + objPtr->internalRep.wideValue = wideValue; + return JIM_OK; + } + else { + + if (Jim_StringToDouble(str, &doubleValue) != JIM_OK) { + Jim_SetResultFormatted(interp, "expected floating-point number but got \"%#s\"", objPtr); + return JIM_ERR; + } + + Jim_FreeIntRep(interp, objPtr); + } + objPtr->typePtr = &doubleObjType; + objPtr->internalRep.doubleValue = doubleValue; + return JIM_OK; +} + +int Jim_GetDouble(Jim_Interp *interp, Jim_Obj *objPtr, double *doublePtr) +{ + if (objPtr->typePtr == &coercedDoubleObjType) { + *doublePtr = JimWideValue(objPtr); + return JIM_OK; + } + if (objPtr->typePtr != &doubleObjType && SetDoubleFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + + if (objPtr->typePtr == &coercedDoubleObjType) { + *doublePtr = JimWideValue(objPtr); + } + else { + *doublePtr = objPtr->internalRep.doubleValue; + } + return JIM_OK; +} + +Jim_Obj *Jim_NewDoubleObj(Jim_Interp *interp, double doubleValue) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &doubleObjType; + objPtr->bytes = NULL; + objPtr->internalRep.doubleValue = doubleValue; + return objPtr; +} + +static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec); +static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr); +static void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfList(struct Jim_Obj *objPtr); +static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType listObjType = { + "list", + FreeListInternalRep, + DupListInternalRep, + UpdateStringOfList, + JIM_TYPE_NONE, +}; + +void FreeListInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int i; + + for (i = 0; i < objPtr->internalRep.listValue.len; i++) { + Jim_DecrRefCount(interp, objPtr->internalRep.listValue.ele[i]); + } + Jim_Free(objPtr->internalRep.listValue.ele); +} + +void DupListInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + int i; + + JIM_NOTUSED(interp); + + dupPtr->internalRep.listValue.len = srcPtr->internalRep.listValue.len; + dupPtr->internalRep.listValue.maxLen = srcPtr->internalRep.listValue.maxLen; + dupPtr->internalRep.listValue.ele = + Jim_Alloc(sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.maxLen); + memcpy(dupPtr->internalRep.listValue.ele, srcPtr->internalRep.listValue.ele, + sizeof(Jim_Obj *) * srcPtr->internalRep.listValue.len); + for (i = 0; i < dupPtr->internalRep.listValue.len; i++) { + Jim_IncrRefCount(dupPtr->internalRep.listValue.ele[i]); + } + dupPtr->typePtr = &listObjType; +} + +#define JIM_ELESTR_SIMPLE 0 +#define JIM_ELESTR_BRACE 1 +#define JIM_ELESTR_QUOTE 2 +static unsigned char ListElementQuotingType(const char *s, int len) +{ + int i, level, blevel, trySimple = 1; + + + if (len == 0) + return JIM_ELESTR_BRACE; + if (s[0] == '"' || s[0] == '{') { + trySimple = 0; + goto testbrace; + } + for (i = 0; i < len; i++) { + switch (s[i]) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case ';': + case '\\': + case '\r': + case '\n': + case '\t': + case '\f': + case '\v': + trySimple = 0; + case '{': + case '}': + goto testbrace; + } + } + return JIM_ELESTR_SIMPLE; + + testbrace: + + if (s[len - 1] == '\\') + return JIM_ELESTR_QUOTE; + level = 0; + blevel = 0; + for (i = 0; i < len; i++) { + switch (s[i]) { + case '{': + level++; + break; + case '}': + level--; + if (level < 0) + return JIM_ELESTR_QUOTE; + break; + case '[': + blevel++; + break; + case ']': + blevel--; + break; + case '\\': + if (s[i + 1] == '\n') + return JIM_ELESTR_QUOTE; + else if (s[i + 1] != '\0') + i++; + break; + } + } + if (blevel < 0) { + return JIM_ELESTR_QUOTE; + } + + if (level == 0) { + if (!trySimple) + return JIM_ELESTR_BRACE; + for (i = 0; i < len; i++) { + switch (s[i]) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case ';': + case '\\': + case '\r': + case '\n': + case '\t': + case '\f': + case '\v': + return JIM_ELESTR_BRACE; + break; + } + } + return JIM_ELESTR_SIMPLE; + } + return JIM_ELESTR_QUOTE; +} + +static int BackslashQuoteString(const char *s, int len, char *q) +{ + char *p = q; + + while (len--) { + switch (*s) { + case ' ': + case '$': + case '"': + case '[': + case ']': + case '{': + case '}': + case ';': + case '\\': + *p++ = '\\'; + *p++ = *s++; + break; + case '\n': + *p++ = '\\'; + *p++ = 'n'; + s++; + break; + case '\r': + *p++ = '\\'; + *p++ = 'r'; + s++; + break; + case '\t': + *p++ = '\\'; + *p++ = 't'; + s++; + break; + case '\f': + *p++ = '\\'; + *p++ = 'f'; + s++; + break; + case '\v': + *p++ = '\\'; + *p++ = 'v'; + s++; + break; + default: + *p++ = *s++; + break; + } + } + *p = '\0'; + + return p - q; +} + +static void JimMakeListStringRep(Jim_Obj *objPtr, Jim_Obj **objv, int objc) +{ + #define STATIC_QUOTING_LEN 32 + int i, bufLen, realLength; + const char *strRep; + char *p; + unsigned char *quotingType, staticQuoting[STATIC_QUOTING_LEN]; + + + if (objc > STATIC_QUOTING_LEN) { + quotingType = Jim_Alloc(objc); + } + else { + quotingType = staticQuoting; + } + bufLen = 0; + for (i = 0; i < objc; i++) { + int len; + + strRep = Jim_GetString(objv[i], &len); + quotingType[i] = ListElementQuotingType(strRep, len); + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + if (i != 0 || strRep[0] != '#') { + bufLen += len; + break; + } + + quotingType[i] = JIM_ELESTR_BRACE; + + case JIM_ELESTR_BRACE: + bufLen += len + 2; + break; + case JIM_ELESTR_QUOTE: + bufLen += len * 2; + break; + } + bufLen++; + } + bufLen++; + + + p = objPtr->bytes = Jim_Alloc(bufLen + 1); + realLength = 0; + for (i = 0; i < objc; i++) { + int len, qlen; + + strRep = Jim_GetString(objv[i], &len); + + switch (quotingType[i]) { + case JIM_ELESTR_SIMPLE: + memcpy(p, strRep, len); + p += len; + realLength += len; + break; + case JIM_ELESTR_BRACE: + *p++ = '{'; + memcpy(p, strRep, len); + p += len; + *p++ = '}'; + realLength += len + 2; + break; + case JIM_ELESTR_QUOTE: + if (i == 0 && strRep[0] == '#') { + *p++ = '\\'; + realLength++; + } + qlen = BackslashQuoteString(strRep, len, p); + p += qlen; + realLength += qlen; + break; + } + + if (i + 1 != objc) { + *p++ = ' '; + realLength++; + } + } + *p = '\0'; + objPtr->length = realLength; + + if (quotingType != staticQuoting) { + Jim_Free(quotingType); + } +} + +static void UpdateStringOfList(struct Jim_Obj *objPtr) +{ + JimMakeListStringRep(objPtr, objPtr->internalRep.listValue.ele, objPtr->internalRep.listValue.len); +} + +static int SetListFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + struct JimParserCtx parser; + const char *str; + int strLen; + Jim_Obj *fileNameObj; + int linenr; + + if (objPtr->typePtr == &listObjType) { + return JIM_OK; + } + + if (Jim_IsDict(objPtr) && objPtr->bytes == NULL) { + Jim_Obj **listObjPtrPtr; + int len; + int i; + + listObjPtrPtr = JimDictPairs(objPtr, &len); + for (i = 0; i < len; i++) { + Jim_IncrRefCount(listObjPtrPtr[i]); + } + + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &listObjType; + objPtr->internalRep.listValue.len = len; + objPtr->internalRep.listValue.maxLen = len; + objPtr->internalRep.listValue.ele = listObjPtrPtr; + + return JIM_OK; + } + + + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + linenr = objPtr->internalRep.sourceValue.lineNumber; + } + else { + fileNameObj = interp->emptyObj; + linenr = 1; + } + Jim_IncrRefCount(fileNameObj); + + + str = Jim_GetString(objPtr, &strLen); + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &listObjType; + objPtr->internalRep.listValue.len = 0; + objPtr->internalRep.listValue.maxLen = 0; + objPtr->internalRep.listValue.ele = NULL; + + + if (strLen) { + JimParserInit(&parser, str, strLen, linenr); + while (!parser.eof) { + Jim_Obj *elementPtr; + + JimParseList(&parser); + if (parser.tt != JIM_TT_STR && parser.tt != JIM_TT_ESC) + continue; + elementPtr = JimParserGetTokenObj(interp, &parser); + JimSetSourceInfo(interp, elementPtr, fileNameObj, parser.tline); + ListAppendElement(objPtr, elementPtr); + } + } + Jim_DecrRefCount(interp, fileNameObj); + return JIM_OK; +} + +Jim_Obj *Jim_NewListObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) +{ + Jim_Obj *objPtr; + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &listObjType; + objPtr->bytes = NULL; + objPtr->internalRep.listValue.ele = NULL; + objPtr->internalRep.listValue.len = 0; + objPtr->internalRep.listValue.maxLen = 0; + + if (len) { + ListInsertElements(objPtr, 0, len, elements); + } + + return objPtr; +} + +static void JimListGetElements(Jim_Interp *interp, Jim_Obj *listObj, int *listLen, + Jim_Obj ***listVec) +{ + *listLen = Jim_ListLength(interp, listObj); + *listVec = listObj->internalRep.listValue.ele; +} + + +static int JimSign(jim_wide w) +{ + if (w == 0) { + return 0; + } + else if (w < 0) { + return -1; + } + return 1; +} + + +struct lsort_info { + jmp_buf jmpbuf; + Jim_Obj *command; + Jim_Interp *interp; + enum { + JIM_LSORT_ASCII, + JIM_LSORT_NOCASE, + JIM_LSORT_INTEGER, + JIM_LSORT_REAL, + JIM_LSORT_COMMAND + } type; + int order; + int index; + int indexed; + int unique; + int (*subfn)(Jim_Obj **, Jim_Obj **); +}; + +static struct lsort_info *sort_info; + +static int ListSortIndexHelper(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + Jim_Obj *lObj, *rObj; + + if (Jim_ListIndex(sort_info->interp, *lhsObj, sort_info->index, &lObj, JIM_ERRMSG) != JIM_OK || + Jim_ListIndex(sort_info->interp, *rhsObj, sort_info->index, &rObj, JIM_ERRMSG) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + return sort_info->subfn(&lObj, &rObj); +} + + +static int ListSortString(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 0) * sort_info->order; +} + +static int ListSortStringNoCase(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + return Jim_StringCompareObj(sort_info->interp, *lhsObj, *rhsObj, 1) * sort_info->order; +} + +static int ListSortInteger(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + jim_wide lhs = 0, rhs = 0; + + if (Jim_GetWide(sort_info->interp, *lhsObj, &lhs) != JIM_OK || + Jim_GetWide(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + + return JimSign(lhs - rhs) * sort_info->order; +} + +static int ListSortReal(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + double lhs = 0, rhs = 0; + + if (Jim_GetDouble(sort_info->interp, *lhsObj, &lhs) != JIM_OK || + Jim_GetDouble(sort_info->interp, *rhsObj, &rhs) != JIM_OK) { + longjmp(sort_info->jmpbuf, JIM_ERR); + } + if (lhs == rhs) { + return 0; + } + if (lhs > rhs) { + return sort_info->order; + } + return -sort_info->order; +} + +static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) +{ + Jim_Obj *compare_script; + int rc; + + jim_wide ret = 0; + + + compare_script = Jim_DuplicateObj(sort_info->interp, sort_info->command); + Jim_ListAppendElement(sort_info->interp, compare_script, *lhsObj); + Jim_ListAppendElement(sort_info->interp, compare_script, *rhsObj); + + rc = Jim_EvalObj(sort_info->interp, compare_script); + + if (rc != JIM_OK || Jim_GetWide(sort_info->interp, Jim_GetResult(sort_info->interp), &ret) != JIM_OK) { + longjmp(sort_info->jmpbuf, rc); + } + + return JimSign(ret) * sort_info->order; +} + +static void ListRemoveDuplicates(Jim_Obj *listObjPtr, int (*comp)(Jim_Obj **lhs, Jim_Obj **rhs)) +{ + int src; + int dst = 0; + Jim_Obj **ele = listObjPtr->internalRep.listValue.ele; + + for (src = 1; src < listObjPtr->internalRep.listValue.len; src++) { + if (comp(&ele[dst], &ele[src]) == 0) { + + Jim_DecrRefCount(sort_info->interp, ele[dst]); + } + else { + + dst++; + } + ele[dst] = ele[src]; + } + + ele[++dst] = ele[src]; + + + listObjPtr->internalRep.listValue.len = dst; +} + + +static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsort_info *info) +{ + struct lsort_info *prev_info; + + typedef int (qsort_comparator) (const void *, const void *); + int (*fn) (Jim_Obj **, Jim_Obj **); + Jim_Obj **vector; + int len; + int rc; + + JimPanic((Jim_IsShared(listObjPtr), "ListSortElements called with shared object")); + SetListFromAny(interp, listObjPtr); + + + prev_info = sort_info; + sort_info = info; + + vector = listObjPtr->internalRep.listValue.ele; + len = listObjPtr->internalRep.listValue.len; + switch (info->type) { + case JIM_LSORT_ASCII: + fn = ListSortString; + break; + case JIM_LSORT_NOCASE: + fn = ListSortStringNoCase; + break; + case JIM_LSORT_INTEGER: + fn = ListSortInteger; + break; + case JIM_LSORT_REAL: + fn = ListSortReal; + break; + case JIM_LSORT_COMMAND: + fn = ListSortCommand; + break; + default: + fn = NULL; + JimPanic((1, "ListSort called with invalid sort type")); + } + + if (info->indexed) { + + info->subfn = fn; + fn = ListSortIndexHelper; + } + + if ((rc = setjmp(info->jmpbuf)) == 0) { + qsort(vector, len, sizeof(Jim_Obj *), (qsort_comparator *) fn); + + if (info->unique && len > 1) { + ListRemoveDuplicates(listObjPtr, fn); + } + + Jim_InvalidateStringRep(listObjPtr); + } + sort_info = prev_info; + + return rc; +} + +static void ListInsertElements(Jim_Obj *listPtr, int idx, int elemc, Jim_Obj *const *elemVec) +{ + int currentLen = listPtr->internalRep.listValue.len; + int requiredLen = currentLen + elemc; + int i; + Jim_Obj **point; + + if (requiredLen > listPtr->internalRep.listValue.maxLen) { + if (requiredLen < 2) { + + requiredLen = 4; + } + else { + requiredLen *= 2; + } + + listPtr->internalRep.listValue.ele = Jim_Realloc(listPtr->internalRep.listValue.ele, + sizeof(Jim_Obj *) * requiredLen); + + listPtr->internalRep.listValue.maxLen = requiredLen; + } + if (idx < 0) { + idx = currentLen; + } + point = listPtr->internalRep.listValue.ele + idx; + memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *)); + for (i = 0; i < elemc; ++i) { + point[i] = elemVec[i]; + Jim_IncrRefCount(point[i]); + } + listPtr->internalRep.listValue.len += elemc; +} + +static void ListAppendElement(Jim_Obj *listPtr, Jim_Obj *objPtr) +{ + ListInsertElements(listPtr, -1, 1, &objPtr); +} + +static void ListAppendList(Jim_Obj *listPtr, Jim_Obj *appendListPtr) +{ + ListInsertElements(listPtr, -1, + appendListPtr->internalRep.listValue.len, appendListPtr->internalRep.listValue.ele); +} + +void Jim_ListAppendElement(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *objPtr) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendElement called with shared object")); + SetListFromAny(interp, listPtr); + Jim_InvalidateStringRep(listPtr); + ListAppendElement(listPtr, objPtr); +} + +void Jim_ListAppendList(Jim_Interp *interp, Jim_Obj *listPtr, Jim_Obj *appendListPtr) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListAppendList called with shared object")); + SetListFromAny(interp, listPtr); + SetListFromAny(interp, appendListPtr); + Jim_InvalidateStringRep(listPtr); + ListAppendList(listPtr, appendListPtr); +} + +int Jim_ListLength(Jim_Interp *interp, Jim_Obj *objPtr) +{ + SetListFromAny(interp, objPtr); + return objPtr->internalRep.listValue.len; +} + +void Jim_ListInsertElements(Jim_Interp *interp, Jim_Obj *listPtr, int idx, + int objc, Jim_Obj *const *objVec) +{ + JimPanic((Jim_IsShared(listPtr), "Jim_ListInsertElement called with shared object")); + SetListFromAny(interp, listPtr); + if (idx >= 0 && idx > listPtr->internalRep.listValue.len) + idx = listPtr->internalRep.listValue.len; + else if (idx < 0) + idx = 0; + Jim_InvalidateStringRep(listPtr); + ListInsertElements(listPtr, idx, objc, objVec); +} + +Jim_Obj *Jim_ListGetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx) +{ + SetListFromAny(interp, listPtr); + if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || + (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { + return NULL; + } + if (idx < 0) + idx = listPtr->internalRep.listValue.len + idx; + return listPtr->internalRep.listValue.ele[idx]; +} + +int Jim_ListIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, Jim_Obj **objPtrPtr, int flags) +{ + *objPtrPtr = Jim_ListGetIndex(interp, listPtr, idx); + if (*objPtrPtr == NULL) { + if (flags & JIM_ERRMSG) { + Jim_SetResultString(interp, "list index out of range", -1); + } + return JIM_ERR; + } + return JIM_OK; +} + +static int ListSetIndex(Jim_Interp *interp, Jim_Obj *listPtr, int idx, + Jim_Obj *newObjPtr, int flags) +{ + SetListFromAny(interp, listPtr); + if ((idx >= 0 && idx >= listPtr->internalRep.listValue.len) || + (idx < 0 && (-idx - 1) >= listPtr->internalRep.listValue.len)) { + if (flags & JIM_ERRMSG) { + Jim_SetResultString(interp, "list index out of range", -1); + } + return JIM_ERR; + } + if (idx < 0) + idx = listPtr->internalRep.listValue.len + idx; + Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]); + listPtr->internalRep.listValue.ele[idx] = newObjPtr; + Jim_IncrRefCount(newObjPtr); + return JIM_OK; +} + +int Jim_ListSetIndex(Jim_Interp *interp, Jim_Obj *varNamePtr, + Jim_Obj *const *indexv, int indexc, Jim_Obj *newObjPtr) +{ + Jim_Obj *varObjPtr, *objPtr, *listObjPtr; + int shared, i, idx; + + varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG | JIM_UNSHARED); + if (objPtr == NULL) + return JIM_ERR; + if ((shared = Jim_IsShared(objPtr))) + varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); + for (i = 0; i < indexc - 1; i++) { + listObjPtr = objPtr; + if (Jim_GetIndex(interp, indexv[i], &idx) != JIM_OK) + goto err; + if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_ERRMSG) != JIM_OK) { + goto err; + } + if (Jim_IsShared(objPtr)) { + objPtr = Jim_DuplicateObj(interp, objPtr); + ListSetIndex(interp, listObjPtr, idx, objPtr, JIM_NONE); + } + Jim_InvalidateStringRep(listObjPtr); + } + if (Jim_GetIndex(interp, indexv[indexc - 1], &idx) != JIM_OK) + goto err; + if (ListSetIndex(interp, objPtr, idx, newObjPtr, JIM_ERRMSG) == JIM_ERR) + goto err; + Jim_InvalidateStringRep(objPtr); + Jim_InvalidateStringRep(varObjPtr); + if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) + goto err; + Jim_SetResult(interp, varObjPtr); + return JIM_OK; + err: + if (shared) { + Jim_FreeNewObj(interp, varObjPtr); + } + return JIM_ERR; +} + +Jim_Obj *Jim_ListJoin(Jim_Interp *interp, Jim_Obj *listObjPtr, const char *joinStr, int joinStrLen) +{ + int i; + int listLen = Jim_ListLength(interp, listObjPtr); + Jim_Obj *resObjPtr = Jim_NewEmptyStringObj(interp); + + for (i = 0; i < listLen; ) { + Jim_AppendObj(interp, resObjPtr, Jim_ListGetIndex(interp, listObjPtr, i)); + if (++i != listLen) { + Jim_AppendString(interp, resObjPtr, joinStr, joinStrLen); + } + } + return resObjPtr; +} + +Jim_Obj *Jim_ConcatObj(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + int i; + + for (i = 0; i < objc; i++) { + if (!Jim_IsList(objv[i])) + break; + } + if (i == objc) { + Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; i < objc; i++) + ListAppendList(objPtr, objv[i]); + return objPtr; + } + else { + + int len = 0, objLen; + char *bytes, *p; + + + for (i = 0; i < objc; i++) { + len += Jim_Length(objv[i]); + } + if (objc) + len += objc - 1; + + p = bytes = Jim_Alloc(len + 1); + for (i = 0; i < objc; i++) { + const char *s = Jim_GetString(objv[i], &objLen); + + + while (objLen && isspace(UCHAR(*s))) { + s++; + objLen--; + len--; + } + + while (objLen && isspace(UCHAR(s[objLen - 1]))) { + + if (objLen > 1 && s[objLen - 2] == '\\') { + break; + } + objLen--; + len--; + } + memcpy(p, s, objLen); + p += objLen; + if (i + 1 != objc) { + if (objLen) + *p++ = ' '; + else { + len--; + } + } + } + *p = '\0'; + return Jim_NewStringObjNoAlloc(interp, bytes, len); + } +} + +Jim_Obj *Jim_ListRange(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *firstObjPtr, + Jim_Obj *lastObjPtr) +{ + int first, last; + int len, rangeLen; + + if (Jim_GetIndex(interp, firstObjPtr, &first) != JIM_OK || + Jim_GetIndex(interp, lastObjPtr, &last) != JIM_OK) + return NULL; + len = Jim_ListLength(interp, listObjPtr); + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, &first, &last, &rangeLen); + if (first == 0 && last == len) { + return listObjPtr; + } + return Jim_NewListObj(interp, listObjPtr->internalRep.listValue.ele + first, rangeLen); +} + +static void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfDict(struct Jim_Obj *objPtr); +static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + + +static unsigned int JimObjectHTHashFunction(const void *key) +{ + int len; + const char *str = Jim_GetString((Jim_Obj *)key, &len); + return Jim_GenHashFunction((const unsigned char *)str, len); +} + +static int JimObjectHTKeyCompare(void *privdata, const void *key1, const void *key2) +{ + return Jim_StringEqObj((Jim_Obj *)key1, (Jim_Obj *)key2); +} + +static void *JimObjectHTKeyValDup(void *privdata, const void *val) +{ + Jim_IncrRefCount((Jim_Obj *)val); + return (void *)val; +} + +static void JimObjectHTKeyValDestructor(void *interp, void *val) +{ + Jim_DecrRefCount(interp, (Jim_Obj *)val); +} + +static const Jim_HashTableType JimDictHashTableType = { + JimObjectHTHashFunction, + JimObjectHTKeyValDup, + JimObjectHTKeyValDup, + JimObjectHTKeyCompare, + JimObjectHTKeyValDestructor, + JimObjectHTKeyValDestructor +}; + +static const Jim_ObjType dictObjType = { + "dict", + FreeDictInternalRep, + DupDictInternalRep, + UpdateStringOfDict, + JIM_TYPE_NONE, +}; + +void FreeDictInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + JIM_NOTUSED(interp); + + Jim_FreeHashTable(objPtr->internalRep.ptr); + Jim_Free(objPtr->internalRep.ptr); +} + +void DupDictInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + Jim_HashTable *ht, *dupHt; + Jim_HashTableIterator htiter; + Jim_HashEntry *he; + + + ht = srcPtr->internalRep.ptr; + dupHt = Jim_Alloc(sizeof(*dupHt)); + Jim_InitHashTable(dupHt, &JimDictHashTableType, interp); + if (ht->size != 0) + Jim_ExpandHashTable(dupHt, ht->size); + + JimInitHashTableIterator(ht, &htiter); + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { + Jim_AddHashEntry(dupHt, he->key, he->u.val); + } + + dupPtr->internalRep.ptr = dupHt; + dupPtr->typePtr = &dictObjType; +} + +static Jim_Obj **JimDictPairs(Jim_Obj *dictPtr, int *len) +{ + Jim_HashTable *ht; + Jim_HashTableIterator htiter; + Jim_HashEntry *he; + Jim_Obj **objv; + int i; + + ht = dictPtr->internalRep.ptr; + + + objv = Jim_Alloc((ht->used * 2) * sizeof(Jim_Obj *)); + JimInitHashTableIterator(ht, &htiter); + i = 0; + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { + objv[i++] = Jim_GetHashEntryKey(he); + objv[i++] = Jim_GetHashEntryVal(he); + } + *len = i; + return objv; +} + +static void UpdateStringOfDict(struct Jim_Obj *objPtr) +{ + + int len; + Jim_Obj **objv = JimDictPairs(objPtr, &len); + + + JimMakeListStringRep(objPtr, objv, len); + + Jim_Free(objv); +} + +static int SetDictFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int listlen; + + if (objPtr->typePtr == &dictObjType) { + return JIM_OK; + } + + if (Jim_IsList(objPtr) && Jim_IsShared(objPtr)) { + Jim_String(objPtr); + } + + + listlen = Jim_ListLength(interp, objPtr); + if (listlen % 2) { + Jim_SetResultString(interp, "missing value to go with key", -1); + return JIM_ERR; + } + else { + + Jim_HashTable *ht; + int i; + + ht = Jim_Alloc(sizeof(*ht)); + Jim_InitHashTable(ht, &JimDictHashTableType, interp); + + for (i = 0; i < listlen; i += 2) { + Jim_Obj *keyObjPtr = Jim_ListGetIndex(interp, objPtr, i); + Jim_Obj *valObjPtr = Jim_ListGetIndex(interp, objPtr, i + 1); + + Jim_ReplaceHashEntry(ht, keyObjPtr, valObjPtr); + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &dictObjType; + objPtr->internalRep.ptr = ht; + + return JIM_OK; + } +} + + + +static int DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) +{ + Jim_HashTable *ht = objPtr->internalRep.ptr; + + if (valueObjPtr == NULL) { + return Jim_DeleteHashEntry(ht, keyObjPtr); + } + Jim_ReplaceHashEntry(ht, keyObjPtr, valueObjPtr); + return JIM_OK; +} + +int Jim_DictAddElement(Jim_Interp *interp, Jim_Obj *objPtr, + Jim_Obj *keyObjPtr, Jim_Obj *valueObjPtr) +{ + JimPanic((Jim_IsShared(objPtr), "Jim_DictAddElement called with shared object")); + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return JIM_ERR; + } + Jim_InvalidateStringRep(objPtr); + return DictAddElement(interp, objPtr, keyObjPtr, valueObjPtr); +} + +Jim_Obj *Jim_NewDictObj(Jim_Interp *interp, Jim_Obj *const *elements, int len) +{ + Jim_Obj *objPtr; + int i; + + JimPanic((len % 2, "Jim_NewDictObj() 'len' argument must be even")); + + objPtr = Jim_NewObj(interp); + objPtr->typePtr = &dictObjType; + objPtr->bytes = NULL; + objPtr->internalRep.ptr = Jim_Alloc(sizeof(Jim_HashTable)); + Jim_InitHashTable(objPtr->internalRep.ptr, &JimDictHashTableType, interp); + for (i = 0; i < len; i += 2) + DictAddElement(interp, objPtr, elements[i], elements[i + 1]); + return objPtr; +} + +int Jim_DictKey(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj *keyPtr, + Jim_Obj **objPtrPtr, int flags) +{ + Jim_HashEntry *he; + Jim_HashTable *ht; + + if (SetDictFromAny(interp, dictPtr) != JIM_OK) { + return -1; + } + ht = dictPtr->internalRep.ptr; + if ((he = Jim_FindHashEntry(ht, keyPtr)) == NULL) { + if (flags & JIM_ERRMSG) { + Jim_SetResultFormatted(interp, "key \"%#s\" not known in dictionary", keyPtr); + } + return JIM_ERR; + } + *objPtrPtr = he->u.val; + return JIM_OK; +} + + +int Jim_DictPairs(Jim_Interp *interp, Jim_Obj *dictPtr, Jim_Obj ***objPtrPtr, int *len) +{ + if (SetDictFromAny(interp, dictPtr) != JIM_OK) { + return JIM_ERR; + } + *objPtrPtr = JimDictPairs(dictPtr, len); + + return JIM_OK; +} + + + +int Jim_DictKeysVector(Jim_Interp *interp, Jim_Obj *dictPtr, + Jim_Obj *const *keyv, int keyc, Jim_Obj **objPtrPtr, int flags) +{ + int i; + + if (keyc == 0) { + *objPtrPtr = dictPtr; + return JIM_OK; + } + + for (i = 0; i < keyc; i++) { + Jim_Obj *objPtr; + + int rc = Jim_DictKey(interp, dictPtr, keyv[i], &objPtr, flags); + if (rc != JIM_OK) { + return rc; + } + dictPtr = objPtr; + } + *objPtrPtr = dictPtr; + return JIM_OK; +} + +int Jim_SetDictKeysVector(Jim_Interp *interp, Jim_Obj *varNamePtr, + Jim_Obj *const *keyv, int keyc, Jim_Obj *newObjPtr, int flags) +{ + Jim_Obj *varObjPtr, *objPtr, *dictObjPtr; + int shared, i; + + varObjPtr = objPtr = Jim_GetVariable(interp, varNamePtr, flags); + if (objPtr == NULL) { + if (newObjPtr == NULL && (flags & JIM_MUSTEXIST)) { + + return JIM_ERR; + } + varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0); + if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) { + Jim_FreeNewObj(interp, varObjPtr); + return JIM_ERR; + } + } + if ((shared = Jim_IsShared(objPtr))) + varObjPtr = objPtr = Jim_DuplicateObj(interp, objPtr); + for (i = 0; i < keyc; i++) { + dictObjPtr = objPtr; + + + if (SetDictFromAny(interp, dictObjPtr) != JIM_OK) { + goto err; + } + + if (i == keyc - 1) { + + if (Jim_DictAddElement(interp, objPtr, keyv[keyc - 1], newObjPtr) != JIM_OK) { + if (newObjPtr || (flags & JIM_MUSTEXIST)) { + goto err; + } + } + break; + } + + + Jim_InvalidateStringRep(dictObjPtr); + if (Jim_DictKey(interp, dictObjPtr, keyv[i], &objPtr, + newObjPtr ? JIM_NONE : JIM_ERRMSG) == JIM_OK) { + if (Jim_IsShared(objPtr)) { + objPtr = Jim_DuplicateObj(interp, objPtr); + DictAddElement(interp, dictObjPtr, keyv[i], objPtr); + } + } + else { + if (newObjPtr == NULL) { + goto err; + } + objPtr = Jim_NewDictObj(interp, NULL, 0); + DictAddElement(interp, dictObjPtr, keyv[i], objPtr); + } + } + + Jim_InvalidateStringRep(objPtr); + Jim_InvalidateStringRep(varObjPtr); + if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) { + goto err; + } + Jim_SetResult(interp, varObjPtr); + return JIM_OK; + err: + if (shared) { + Jim_FreeNewObj(interp, varObjPtr); + } + return JIM_ERR; +} + +static void UpdateStringOfIndex(struct Jim_Obj *objPtr); +static int SetIndexFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType indexObjType = { + "index", + NULL, + NULL, + UpdateStringOfIndex, + JIM_TYPE_NONE, +}; + +static void UpdateStringOfIndex(struct Jim_Obj *objPtr) +{ + if (objPtr->internalRep.intValue == -1) { + JimSetStringBytes(objPtr, "end"); + } + else { + char buf[JIM_INTEGER_SPACE + 1]; + if (objPtr->internalRep.intValue >= 0) { + sprintf(buf, "%d", objPtr->internalRep.intValue); + } + else { + + sprintf(buf, "end%d", objPtr->internalRep.intValue + 1); + } + JimSetStringBytes(objPtr, buf); + } +} + +static int SetIndexFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int idx, end = 0; + const char *str; + char *endptr; + + + str = Jim_String(objPtr); + + + if (strncmp(str, "end", 3) == 0) { + end = 1; + str += 3; + idx = 0; + } + else { + idx = jim_strtol(str, &endptr); + + if (endptr == str) { + goto badindex; + } + str = endptr; + } + + + if (*str == '+' || *str == '-') { + int sign = (*str == '+' ? 1 : -1); + + idx += sign * jim_strtol(++str, &endptr); + if (str == endptr || *endptr) { + goto badindex; + } + str = endptr; + } + + while (isspace(UCHAR(*str))) { + str++; + } + if (*str) { + goto badindex; + } + if (end) { + if (idx > 0) { + idx = INT_MAX; + } + else { + + idx--; + } + } + else if (idx < 0) { + idx = -INT_MAX; + } + + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &indexObjType; + objPtr->internalRep.intValue = idx; + return JIM_OK; + + badindex: + Jim_SetResultFormatted(interp, + "bad index \"%#s\": must be integer?[+-]integer? or end?[+-]integer?", objPtr); + return JIM_ERR; +} + +int Jim_GetIndex(Jim_Interp *interp, Jim_Obj *objPtr, int *indexPtr) +{ + + if (objPtr->typePtr == &intObjType) { + jim_wide val = JimWideValue(objPtr); + + if (val < 0) + *indexPtr = -INT_MAX; + else if (val > INT_MAX) + *indexPtr = INT_MAX; + else + *indexPtr = (int)val; + return JIM_OK; + } + if (objPtr->typePtr != &indexObjType && SetIndexFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + *indexPtr = objPtr->internalRep.intValue; + return JIM_OK; +} + + + +static const char * const jimReturnCodes[] = { + "ok", + "error", + "return", + "break", + "continue", + "signal", + "exit", + "eval", + NULL +}; + +#define jimReturnCodesSize (sizeof(jimReturnCodes)/sizeof(*jimReturnCodes)) + +static const Jim_ObjType returnCodeObjType = { + "return-code", + NULL, + NULL, + NULL, + JIM_TYPE_NONE, +}; + +const char *Jim_ReturnCode(int code) +{ + if (code < 0 || code >= (int)jimReturnCodesSize) { + return "?"; + } + else { + return jimReturnCodes[code]; + } +} + +static int SetReturnCodeFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + int returnCode; + jim_wide wideValue; + + + if (JimGetWideNoErr(interp, objPtr, &wideValue) != JIM_ERR) + returnCode = (int)wideValue; + else if (Jim_GetEnum(interp, objPtr, jimReturnCodes, &returnCode, NULL, JIM_NONE) != JIM_OK) { + Jim_SetResultFormatted(interp, "expected return code but got \"%#s\"", objPtr); + return JIM_ERR; + } + + Jim_FreeIntRep(interp, objPtr); + objPtr->typePtr = &returnCodeObjType; + objPtr->internalRep.intValue = returnCode; + return JIM_OK; +} + +int Jim_GetReturnCode(Jim_Interp *interp, Jim_Obj *objPtr, int *intPtr) +{ + if (objPtr->typePtr != &returnCodeObjType && SetReturnCodeFromAny(interp, objPtr) == JIM_ERR) + return JIM_ERR; + *intPtr = objPtr->internalRep.intValue; + return JIM_OK; +} + +static int JimParseExprOperator(struct JimParserCtx *pc); +static int JimParseExprNumber(struct JimParserCtx *pc); +static int JimParseExprIrrational(struct JimParserCtx *pc); + + + + +enum +{ + + + JIM_EXPROP_MUL = JIM_TT_EXPR_OP, + JIM_EXPROP_DIV, + JIM_EXPROP_MOD, + JIM_EXPROP_SUB, + JIM_EXPROP_ADD, + JIM_EXPROP_LSHIFT, + JIM_EXPROP_RSHIFT, + JIM_EXPROP_ROTL, + JIM_EXPROP_ROTR, + JIM_EXPROP_LT, + JIM_EXPROP_GT, + JIM_EXPROP_LTE, + JIM_EXPROP_GTE, + JIM_EXPROP_NUMEQ, + JIM_EXPROP_NUMNE, + JIM_EXPROP_BITAND, + JIM_EXPROP_BITXOR, + JIM_EXPROP_BITOR, + + + JIM_EXPROP_LOGICAND, + JIM_EXPROP_LOGICAND_LEFT, + JIM_EXPROP_LOGICAND_RIGHT, + + + JIM_EXPROP_LOGICOR, + JIM_EXPROP_LOGICOR_LEFT, + JIM_EXPROP_LOGICOR_RIGHT, + + + + JIM_EXPROP_TERNARY, + JIM_EXPROP_TERNARY_LEFT, + JIM_EXPROP_TERNARY_RIGHT, + + + JIM_EXPROP_COLON, + JIM_EXPROP_COLON_LEFT, + JIM_EXPROP_COLON_RIGHT, + + JIM_EXPROP_POW, + + + JIM_EXPROP_STREQ, + JIM_EXPROP_STRNE, + JIM_EXPROP_STRIN, + JIM_EXPROP_STRNI, + + + JIM_EXPROP_NOT, + JIM_EXPROP_BITNOT, + JIM_EXPROP_UNARYMINUS, + JIM_EXPROP_UNARYPLUS, + + + JIM_EXPROP_FUNC_FIRST, + JIM_EXPROP_FUNC_INT = JIM_EXPROP_FUNC_FIRST, + JIM_EXPROP_FUNC_WIDE, + JIM_EXPROP_FUNC_ABS, + JIM_EXPROP_FUNC_DOUBLE, + JIM_EXPROP_FUNC_ROUND, + JIM_EXPROP_FUNC_RAND, + JIM_EXPROP_FUNC_SRAND, + + + JIM_EXPROP_FUNC_SIN, + JIM_EXPROP_FUNC_COS, + JIM_EXPROP_FUNC_TAN, + JIM_EXPROP_FUNC_ASIN, + JIM_EXPROP_FUNC_ACOS, + JIM_EXPROP_FUNC_ATAN, + JIM_EXPROP_FUNC_SINH, + JIM_EXPROP_FUNC_COSH, + JIM_EXPROP_FUNC_TANH, + JIM_EXPROP_FUNC_CEIL, + JIM_EXPROP_FUNC_FLOOR, + JIM_EXPROP_FUNC_EXP, + JIM_EXPROP_FUNC_LOG, + JIM_EXPROP_FUNC_LOG10, + JIM_EXPROP_FUNC_SQRT, + JIM_EXPROP_FUNC_POW, +}; + +struct JimExprState +{ + Jim_Obj **stack; + int stacklen; + int opcode; + int skip; +}; + + +typedef struct Jim_ExprOperator +{ + const char *name; + int (*funcop) (Jim_Interp *interp, struct JimExprState * e); + unsigned char precedence; + unsigned char arity; + unsigned char lazy; + unsigned char namelen; +} Jim_ExprOperator; + +static void ExprPush(struct JimExprState *e, Jim_Obj *obj) +{ + Jim_IncrRefCount(obj); + e->stack[e->stacklen++] = obj; +} + +static Jim_Obj *ExprPop(struct JimExprState *e) +{ + return e->stack[--e->stacklen]; +} + +static int JimExprOpNumUnary(Jim_Interp *interp, struct JimExprState *e) +{ + int intresult = 1; + int rc = JIM_OK; + Jim_Obj *A = ExprPop(e); + double dA, dC = 0; + jim_wide wA, wC = 0; + + if ((A->typePtr != &doubleObjType || A->bytes) && JimGetWideNoErr(interp, A, &wA) == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_INT: + case JIM_EXPROP_FUNC_WIDE: + case JIM_EXPROP_FUNC_ROUND: + case JIM_EXPROP_UNARYPLUS: + wC = wA; + break; + case JIM_EXPROP_FUNC_DOUBLE: + dC = wA; + intresult = 0; + break; + case JIM_EXPROP_FUNC_ABS: + wC = wA >= 0 ? wA : -wA; + break; + case JIM_EXPROP_UNARYMINUS: + wC = -wA; + break; + case JIM_EXPROP_NOT: + wC = !wA; + break; + default: + abort(); + } + } + else if ((rc = Jim_GetDouble(interp, A, &dA)) == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_INT: + case JIM_EXPROP_FUNC_WIDE: + wC = dA; + break; + case JIM_EXPROP_FUNC_ROUND: + wC = dA < 0 ? (dA - 0.5) : (dA + 0.5); + break; + case JIM_EXPROP_FUNC_DOUBLE: + case JIM_EXPROP_UNARYPLUS: + dC = dA; + intresult = 0; + break; + case JIM_EXPROP_FUNC_ABS: + dC = dA >= 0 ? dA : -dA; + intresult = 0; + break; + case JIM_EXPROP_UNARYMINUS: + dC = -dA; + intresult = 0; + break; + case JIM_EXPROP_NOT: + wC = !dA; + break; + default: + abort(); + } + } + + if (rc == JIM_OK) { + if (intresult) { + ExprPush(e, Jim_NewIntObj(interp, wC)); + } + else { + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + } + + Jim_DecrRefCount(interp, A); + + return rc; +} + +static double JimRandDouble(Jim_Interp *interp) +{ + unsigned long x; + JimRandomBytes(interp, &x, sizeof(x)); + + return (double)x / (unsigned long)~0; +} + +static int JimExprOpIntUnary(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *A = ExprPop(e); + jim_wide wA; + + int rc = Jim_GetWide(interp, A, &wA); + if (rc == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_BITNOT: + ExprPush(e, Jim_NewIntObj(interp, ~wA)); + break; + case JIM_EXPROP_FUNC_SRAND: + JimPrngSeed(interp, (unsigned char *)&wA, sizeof(wA)); + ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); + break; + default: + abort(); + } + } + + Jim_DecrRefCount(interp, A); + + return rc; +} + +static int JimExprOpNone(Jim_Interp *interp, struct JimExprState *e) +{ + JimPanic((e->opcode != JIM_EXPROP_FUNC_RAND, "JimExprOpNone only support rand()")); + + ExprPush(e, Jim_NewDoubleObj(interp, JimRandDouble(interp))); + + return JIM_OK; +} + +#ifdef JIM_MATH_FUNCTIONS +static int JimExprOpDoubleUnary(Jim_Interp *interp, struct JimExprState *e) +{ + int rc; + Jim_Obj *A = ExprPop(e); + double dA, dC; + + rc = Jim_GetDouble(interp, A, &dA); + if (rc == JIM_OK) { + switch (e->opcode) { + case JIM_EXPROP_FUNC_SIN: + dC = sin(dA); + break; + case JIM_EXPROP_FUNC_COS: + dC = cos(dA); + break; + case JIM_EXPROP_FUNC_TAN: + dC = tan(dA); + break; + case JIM_EXPROP_FUNC_ASIN: + dC = asin(dA); + break; + case JIM_EXPROP_FUNC_ACOS: + dC = acos(dA); + break; + case JIM_EXPROP_FUNC_ATAN: + dC = atan(dA); + break; + case JIM_EXPROP_FUNC_SINH: + dC = sinh(dA); + break; + case JIM_EXPROP_FUNC_COSH: + dC = cosh(dA); + break; + case JIM_EXPROP_FUNC_TANH: + dC = tanh(dA); + break; + case JIM_EXPROP_FUNC_CEIL: + dC = ceil(dA); + break; + case JIM_EXPROP_FUNC_FLOOR: + dC = floor(dA); + break; + case JIM_EXPROP_FUNC_EXP: + dC = exp(dA); + break; + case JIM_EXPROP_FUNC_LOG: + dC = log(dA); + break; + case JIM_EXPROP_FUNC_LOG10: + dC = log10(dA); + break; + case JIM_EXPROP_FUNC_SQRT: + dC = sqrt(dA); + break; + default: + abort(); + } + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + + Jim_DecrRefCount(interp, A); + + return rc; +} +#endif + + +static int JimExprOpIntBin(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + jim_wide wA, wB; + int rc = JIM_ERR; + + if (Jim_GetWide(interp, A, &wA) == JIM_OK && Jim_GetWide(interp, B, &wB) == JIM_OK) { + jim_wide wC; + + rc = JIM_OK; + + switch (e->opcode) { + case JIM_EXPROP_LSHIFT: + wC = wA << wB; + break; + case JIM_EXPROP_RSHIFT: + wC = wA >> wB; + break; + case JIM_EXPROP_BITAND: + wC = wA & wB; + break; + case JIM_EXPROP_BITXOR: + wC = wA ^ wB; + break; + case JIM_EXPROP_BITOR: + wC = wA | wB; + break; + case JIM_EXPROP_MOD: + if (wB == 0) { + wC = 0; + Jim_SetResultString(interp, "Division by zero", -1); + rc = JIM_ERR; + } + else { + int negative = 0; + + if (wB < 0) { + wB = -wB; + wA = -wA; + negative = 1; + } + wC = wA % wB; + if (wC < 0) { + wC += wB; + } + if (negative) { + wC = -wC; + } + } + break; + case JIM_EXPROP_ROTL: + case JIM_EXPROP_ROTR:{ + + unsigned long uA = (unsigned long)wA; + unsigned long uB = (unsigned long)wB; + const unsigned int S = sizeof(unsigned long) * 8; + + + uB %= S; + + if (e->opcode == JIM_EXPROP_ROTR) { + uB = S - uB; + } + wC = (unsigned long)(uA << uB) | (uA >> (S - uB)); + break; + } + default: + abort(); + } + ExprPush(e, Jim_NewIntObj(interp, wC)); + + } + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return rc; +} + + + +static int JimExprOpBin(Jim_Interp *interp, struct JimExprState *e) +{ + int intresult = 1; + int rc = JIM_OK; + double dA, dB, dC = 0; + jim_wide wA, wB, wC = 0; + + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + if ((A->typePtr != &doubleObjType || A->bytes) && + (B->typePtr != &doubleObjType || B->bytes) && + JimGetWideNoErr(interp, A, &wA) == JIM_OK && JimGetWideNoErr(interp, B, &wB) == JIM_OK) { + + + + switch (e->opcode) { + case JIM_EXPROP_POW: + case JIM_EXPROP_FUNC_POW: + wC = JimPowWide(wA, wB); + break; + case JIM_EXPROP_ADD: + wC = wA + wB; + break; + case JIM_EXPROP_SUB: + wC = wA - wB; + break; + case JIM_EXPROP_MUL: + wC = wA * wB; + break; + case JIM_EXPROP_DIV: + if (wB == 0) { + Jim_SetResultString(interp, "Division by zero", -1); + rc = JIM_ERR; + } + else { + if (wB < 0) { + wB = -wB; + wA = -wA; + } + wC = wA / wB; + if (wA % wB < 0) { + wC--; + } + } + break; + case JIM_EXPROP_LT: + wC = wA < wB; + break; + case JIM_EXPROP_GT: + wC = wA > wB; + break; + case JIM_EXPROP_LTE: + wC = wA <= wB; + break; + case JIM_EXPROP_GTE: + wC = wA >= wB; + break; + case JIM_EXPROP_NUMEQ: + wC = wA == wB; + break; + case JIM_EXPROP_NUMNE: + wC = wA != wB; + break; + default: + abort(); + } + } + else if (Jim_GetDouble(interp, A, &dA) == JIM_OK && Jim_GetDouble(interp, B, &dB) == JIM_OK) { + intresult = 0; + switch (e->opcode) { + case JIM_EXPROP_POW: + case JIM_EXPROP_FUNC_POW: +#ifdef JIM_MATH_FUNCTIONS + dC = pow(dA, dB); +#else + Jim_SetResultString(interp, "unsupported", -1); + rc = JIM_ERR; +#endif + break; + case JIM_EXPROP_ADD: + dC = dA + dB; + break; + case JIM_EXPROP_SUB: + dC = dA - dB; + break; + case JIM_EXPROP_MUL: + dC = dA * dB; + break; + case JIM_EXPROP_DIV: + if (dB == 0) { +#ifdef INFINITY + dC = dA < 0 ? -INFINITY : INFINITY; +#else + dC = (dA < 0 ? -1.0 : 1.0) * strtod("Inf", NULL); +#endif + } + else { + dC = dA / dB; + } + break; + case JIM_EXPROP_LT: + wC = dA < dB; + intresult = 1; + break; + case JIM_EXPROP_GT: + wC = dA > dB; + intresult = 1; + break; + case JIM_EXPROP_LTE: + wC = dA <= dB; + intresult = 1; + break; + case JIM_EXPROP_GTE: + wC = dA >= dB; + intresult = 1; + break; + case JIM_EXPROP_NUMEQ: + wC = dA == dB; + intresult = 1; + break; + case JIM_EXPROP_NUMNE: + wC = dA != dB; + intresult = 1; + break; + default: + abort(); + } + } + else { + + + + int i = Jim_StringCompareObj(interp, A, B, 0); + + switch (e->opcode) { + case JIM_EXPROP_LT: + wC = i < 0; + break; + case JIM_EXPROP_GT: + wC = i > 0; + break; + case JIM_EXPROP_LTE: + wC = i <= 0; + break; + case JIM_EXPROP_GTE: + wC = i >= 0; + break; + case JIM_EXPROP_NUMEQ: + wC = i == 0; + break; + case JIM_EXPROP_NUMNE: + wC = i != 0; + break; + default: + rc = JIM_ERR; + break; + } + } + + if (rc == JIM_OK) { + if (intresult) { + ExprPush(e, Jim_NewIntObj(interp, wC)); + } + else { + ExprPush(e, Jim_NewDoubleObj(interp, dC)); + } + } + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return rc; +} + +static int JimSearchList(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_Obj *valObj) +{ + int listlen; + int i; + + listlen = Jim_ListLength(interp, listObjPtr); + for (i = 0; i < listlen; i++) { + if (Jim_StringEqObj(Jim_ListGetIndex(interp, listObjPtr, i), valObj)) { + return 1; + } + } + return 0; +} + +static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + jim_wide wC; + + switch (e->opcode) { + case JIM_EXPROP_STREQ: + case JIM_EXPROP_STRNE: + wC = Jim_StringEqObj(A, B); + if (e->opcode == JIM_EXPROP_STRNE) { + wC = !wC; + } + break; + case JIM_EXPROP_STRIN: + wC = JimSearchList(interp, B, A); + break; + case JIM_EXPROP_STRNI: + wC = !JimSearchList(interp, B, A); + break; + default: + abort(); + } + ExprPush(e, Jim_NewIntObj(interp, wC)); + + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + + return JIM_OK; +} + +static int ExprBool(Jim_Interp *interp, Jim_Obj *obj) +{ + long l; + double d; + + if (Jim_GetLong(interp, obj, &l) == JIM_OK) { + return l != 0; + } + if (Jim_GetDouble(interp, obj, &d) == JIM_OK) { + return d != 0; + } + return -1; +} + +static int JimExprOpAndLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + + e->skip = JimWideValue(skip); + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + + break; + + case -1: + + rc = JIM_ERR; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpOrLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + + break; + + case 1: + + e->skip = JimWideValue(skip); + ExprPush(e, Jim_NewIntObj(interp, 1)); + break; + + case -1: + + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpAndOrRight(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + switch (ExprBool(interp, A)) { + case 0: + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + ExprPush(e, Jim_NewIntObj(interp, 1)); + break; + + case -1: + + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + + return rc; +} + +static int JimExprOpTernaryLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *A = ExprPop(e); + int rc = JIM_OK; + + + ExprPush(e, A); + + switch (ExprBool(interp, A)) { + case 0: + + e->skip = JimWideValue(skip); + + ExprPush(e, Jim_NewIntObj(interp, 0)); + break; + + case 1: + + break; + + case -1: + + rc = JIM_ERR; + break; + } + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, skip); + + return rc; +} + +static int JimExprOpColonLeft(Jim_Interp *interp, struct JimExprState *e) +{ + Jim_Obj *skip = ExprPop(e); + Jim_Obj *B = ExprPop(e); + Jim_Obj *A = ExprPop(e); + + + if (ExprBool(interp, A)) { + + e->skip = JimWideValue(skip); + + ExprPush(e, B); + } + + Jim_DecrRefCount(interp, skip); + Jim_DecrRefCount(interp, A); + Jim_DecrRefCount(interp, B); + return JIM_OK; +} + +static int JimExprOpNull(Jim_Interp *interp, struct JimExprState *e) +{ + return JIM_OK; +} + +enum +{ + LAZY_NONE, + LAZY_OP, + LAZY_LEFT, + LAZY_RIGHT +}; + +#define OPRINIT(N, P, A, F) {N, F, P, A, LAZY_NONE, sizeof(N) - 1} +#define OPRINIT_LAZY(N, P, A, F, L) {N, F, P, A, L, sizeof(N) - 1} + +static const struct Jim_ExprOperator Jim_ExprOperators[] = { + OPRINIT("*", 110, 2, JimExprOpBin), + OPRINIT("/", 110, 2, JimExprOpBin), + OPRINIT("%", 110, 2, JimExprOpIntBin), + + OPRINIT("-", 100, 2, JimExprOpBin), + OPRINIT("+", 100, 2, JimExprOpBin), + + OPRINIT("<<", 90, 2, JimExprOpIntBin), + OPRINIT(">>", 90, 2, JimExprOpIntBin), + + OPRINIT("<<<", 90, 2, JimExprOpIntBin), + OPRINIT(">>>", 90, 2, JimExprOpIntBin), + + OPRINIT("<", 80, 2, JimExprOpBin), + OPRINIT(">", 80, 2, JimExprOpBin), + OPRINIT("<=", 80, 2, JimExprOpBin), + OPRINIT(">=", 80, 2, JimExprOpBin), + + OPRINIT("==", 70, 2, JimExprOpBin), + OPRINIT("!=", 70, 2, JimExprOpBin), + + OPRINIT("&", 50, 2, JimExprOpIntBin), + OPRINIT("^", 49, 2, JimExprOpIntBin), + OPRINIT("|", 48, 2, JimExprOpIntBin), + + OPRINIT_LAZY("&&", 10, 2, NULL, LAZY_OP), + OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndLeft, LAZY_LEFT), + OPRINIT_LAZY(NULL, 10, 2, JimExprOpAndOrRight, LAZY_RIGHT), + + OPRINIT_LAZY("||", 9, 2, NULL, LAZY_OP), + OPRINIT_LAZY(NULL, 9, 2, JimExprOpOrLeft, LAZY_LEFT), + OPRINIT_LAZY(NULL, 9, 2, JimExprOpAndOrRight, LAZY_RIGHT), + + OPRINIT_LAZY("?", 5, 2, JimExprOpNull, LAZY_OP), + OPRINIT_LAZY(NULL, 5, 2, JimExprOpTernaryLeft, LAZY_LEFT), + OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), + + OPRINIT_LAZY(":", 5, 2, JimExprOpNull, LAZY_OP), + OPRINIT_LAZY(NULL, 5, 2, JimExprOpColonLeft, LAZY_LEFT), + OPRINIT_LAZY(NULL, 5, 2, JimExprOpNull, LAZY_RIGHT), + + OPRINIT("**", 250, 2, JimExprOpBin), + + OPRINIT("eq", 60, 2, JimExprOpStrBin), + OPRINIT("ne", 60, 2, JimExprOpStrBin), + + OPRINIT("in", 55, 2, JimExprOpStrBin), + OPRINIT("ni", 55, 2, JimExprOpStrBin), + + OPRINIT("!", 150, 1, JimExprOpNumUnary), + OPRINIT("~", 150, 1, JimExprOpIntUnary), + OPRINIT(NULL, 150, 1, JimExprOpNumUnary), + OPRINIT(NULL, 150, 1, JimExprOpNumUnary), + + + + OPRINIT("int", 200, 1, JimExprOpNumUnary), + OPRINIT("wide", 200, 1, JimExprOpNumUnary), + OPRINIT("abs", 200, 1, JimExprOpNumUnary), + OPRINIT("double", 200, 1, JimExprOpNumUnary), + OPRINIT("round", 200, 1, JimExprOpNumUnary), + OPRINIT("rand", 200, 0, JimExprOpNone), + OPRINIT("srand", 200, 1, JimExprOpIntUnary), + +#ifdef JIM_MATH_FUNCTIONS + OPRINIT("sin", 200, 1, JimExprOpDoubleUnary), + OPRINIT("cos", 200, 1, JimExprOpDoubleUnary), + OPRINIT("tan", 200, 1, JimExprOpDoubleUnary), + OPRINIT("asin", 200, 1, JimExprOpDoubleUnary), + OPRINIT("acos", 200, 1, JimExprOpDoubleUnary), + OPRINIT("atan", 200, 1, JimExprOpDoubleUnary), + OPRINIT("sinh", 200, 1, JimExprOpDoubleUnary), + OPRINIT("cosh", 200, 1, JimExprOpDoubleUnary), + OPRINIT("tanh", 200, 1, JimExprOpDoubleUnary), + OPRINIT("ceil", 200, 1, JimExprOpDoubleUnary), + OPRINIT("floor", 200, 1, JimExprOpDoubleUnary), + OPRINIT("exp", 200, 1, JimExprOpDoubleUnary), + OPRINIT("log", 200, 1, JimExprOpDoubleUnary), + OPRINIT("log10", 200, 1, JimExprOpDoubleUnary), + OPRINIT("sqrt", 200, 1, JimExprOpDoubleUnary), + OPRINIT("pow", 200, 2, JimExprOpBin), +#endif +}; +#undef OPRINIT +#undef OPRINIT_LAZY + +#define JIM_EXPR_OPERATORS_NUM \ + (sizeof(Jim_ExprOperators)/sizeof(struct Jim_ExprOperator)) + +static int JimParseExpression(struct JimParserCtx *pc) +{ + + while (isspace(UCHAR(*pc->p)) || (*(pc->p) == '\\' && *(pc->p + 1) == '\n')) { + if (*pc->p == '\n') { + pc->linenr++; + } + pc->p++; + pc->len--; + } + + + pc->tline = pc->linenr; + pc->tstart = pc->p; + + if (pc->len == 0) { + pc->tend = pc->p; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return JIM_OK; + } + switch (*(pc->p)) { + case '(': + pc->tt = JIM_TT_SUBEXPR_START; + goto singlechar; + case ')': + pc->tt = JIM_TT_SUBEXPR_END; + goto singlechar; + case ',': + pc->tt = JIM_TT_SUBEXPR_COMMA; +singlechar: + pc->tend = pc->p; + pc->p++; + pc->len--; + break; + case '[': + return JimParseCmd(pc); + case '$': + if (JimParseVar(pc) == JIM_ERR) + return JimParseExprOperator(pc); + else { + + if (pc->tt == JIM_TT_EXPRSUGAR) { + return JIM_ERR; + } + return JIM_OK; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + return JimParseExprNumber(pc); + case '"': + return JimParseQuote(pc); + case '{': + return JimParseBrace(pc); + + case 'N': + case 'I': + case 'n': + case 'i': + if (JimParseExprIrrational(pc) == JIM_ERR) + return JimParseExprOperator(pc); + break; + default: + return JimParseExprOperator(pc); + break; + } + return JIM_OK; +} + +static int JimParseExprNumber(struct JimParserCtx *pc) +{ + char *end; + + + pc->tt = JIM_TT_EXPR_INT; + + jim_strtoull(pc->p, (char **)&pc->p); + + if (strchr("eENnIi.", *pc->p) || pc->p == pc->tstart) { + if (strtod(pc->tstart, &end)) { } + if (end == pc->tstart) + return JIM_ERR; + if (end > pc->p) { + + pc->tt = JIM_TT_EXPR_DOUBLE; + pc->p = end; + } + } + pc->tend = pc->p - 1; + pc->len -= (pc->p - pc->tstart); + return JIM_OK; +} + +static int JimParseExprIrrational(struct JimParserCtx *pc) +{ + const char *irrationals[] = { "NaN", "nan", "NAN", "Inf", "inf", "INF", NULL }; + int i; + + for (i = 0; irrationals[i]; i++) { + const char *irr = irrationals[i]; + + if (strncmp(irr, pc->p, 3) == 0) { + pc->p += 3; + pc->len -= 3; + pc->tend = pc->p - 1; + pc->tt = JIM_TT_EXPR_DOUBLE; + return JIM_OK; + } + } + return JIM_ERR; +} + +static int JimParseExprOperator(struct JimParserCtx *pc) +{ + int i; + int bestIdx = -1, bestLen = 0; + + + for (i = 0; i < (signed)JIM_EXPR_OPERATORS_NUM; i++) { + const char * const opname = Jim_ExprOperators[i].name; + const int oplen = Jim_ExprOperators[i].namelen; + + if (opname == NULL || opname[0] != pc->p[0]) { + continue; + } + + if (oplen > bestLen && strncmp(opname, pc->p, oplen) == 0) { + bestIdx = i + JIM_TT_EXPR_OP; + bestLen = oplen; + } + } + if (bestIdx == -1) { + return JIM_ERR; + } + + + if (bestIdx >= JIM_EXPROP_FUNC_FIRST) { + const char *p = pc->p + bestLen; + int len = pc->len - bestLen; + + while (len && isspace(UCHAR(*p))) { + len--; + p++; + } + if (*p != '(') { + return JIM_ERR; + } + } + pc->tend = pc->p + bestLen - 1; + pc->p += bestLen; + pc->len -= bestLen; + + pc->tt = bestIdx; + return JIM_OK; +} + +static const struct Jim_ExprOperator *JimExprOperatorInfoByOpcode(int opcode) +{ + static Jim_ExprOperator dummy_op; + if (opcode < JIM_TT_EXPR_OP) { + return &dummy_op; + } + return &Jim_ExprOperators[opcode - JIM_TT_EXPR_OP]; +} + +const char *jim_tt_name(int type) +{ + static const char * const tt_names[JIM_TT_EXPR_OP] = + { "NIL", "STR", "ESC", "VAR", "ARY", "CMD", "SEP", "EOL", "EOF", "LIN", "WRD", "(((", ")))", ",,,", "INT", + "DBL", "$()" }; + if (type < JIM_TT_EXPR_OP) { + return tt_names[type]; + } + else { + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(type); + static char buf[20]; + + if (op->name) { + return op->name; + } + sprintf(buf, "(%d)", type); + return buf; + } +} + +static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr); + +static const Jim_ObjType exprObjType = { + "expression", + FreeExprInternalRep, + DupExprInternalRep, + NULL, + JIM_TYPE_REFERENCES, +}; + + +typedef struct ExprByteCode +{ + ScriptToken *token; + int len; + int inUse; +} ExprByteCode; + +static void ExprFreeByteCode(Jim_Interp *interp, ExprByteCode * expr) +{ + int i; + + for (i = 0; i < expr->len; i++) { + Jim_DecrRefCount(interp, expr->token[i].objPtr); + } + Jim_Free(expr->token); + Jim_Free(expr); +} + +static void FreeExprInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + ExprByteCode *expr = (void *)objPtr->internalRep.ptr; + + if (expr) { + if (--expr->inUse != 0) { + return; + } + + ExprFreeByteCode(interp, expr); + } +} + +static void DupExprInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + JIM_NOTUSED(interp); + JIM_NOTUSED(srcPtr); + + + dupPtr->typePtr = NULL; +} + + +static int ExprCheckCorrectness(ExprByteCode * expr) +{ + int i; + int stacklen = 0; + int ternary = 0; + + for (i = 0; i < expr->len; i++) { + ScriptToken *t = &expr->token[i]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + stacklen -= op->arity; + if (stacklen < 0) { + break; + } + if (t->type == JIM_EXPROP_TERNARY || t->type == JIM_EXPROP_TERNARY_LEFT) { + ternary++; + } + else if (t->type == JIM_EXPROP_COLON || t->type == JIM_EXPROP_COLON_LEFT) { + ternary--; + } + + + stacklen++; + } + if (stacklen != 1 || ternary != 0) { + return JIM_ERR; + } + return JIM_OK; +} + +static int ExprAddLazyOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) +{ + int i; + + int leftindex, arity, offset; + + + leftindex = expr->len - 1; + + arity = 1; + while (arity) { + ScriptToken *tt = &expr->token[leftindex]; + + if (tt->type >= JIM_TT_EXPR_OP) { + arity += JimExprOperatorInfoByOpcode(tt->type)->arity; + } + arity--; + if (--leftindex < 0) { + return JIM_ERR; + } + } + leftindex++; + + + memmove(&expr->token[leftindex + 2], &expr->token[leftindex], + sizeof(*expr->token) * (expr->len - leftindex)); + expr->len += 2; + offset = (expr->len - leftindex) - 1; + + expr->token[leftindex + 1].type = t->type + 1; + expr->token[leftindex + 1].objPtr = interp->emptyObj; + + expr->token[leftindex].type = JIM_TT_EXPR_INT; + expr->token[leftindex].objPtr = Jim_NewIntObj(interp, offset); + + + expr->token[expr->len].objPtr = interp->emptyObj; + expr->token[expr->len].type = t->type + 2; + expr->len++; + + + for (i = leftindex - 1; i > 0; i--) { + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(expr->token[i].type); + if (op->lazy == LAZY_LEFT) { + if (JimWideValue(expr->token[i - 1].objPtr) + i - 1 >= leftindex) { + JimWideValue(expr->token[i - 1].objPtr) += 2; + } + } + } + return JIM_OK; +} + +static int ExprAddOperator(Jim_Interp *interp, ExprByteCode * expr, ParseToken *t) +{ + struct ScriptToken *token = &expr->token[expr->len]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + if (op->lazy == LAZY_OP) { + if (ExprAddLazyOperator(interp, expr, t) != JIM_OK) { + Jim_SetResultFormatted(interp, "Expression has bad operands to %s", op->name); + return JIM_ERR; + } + } + else { + token->objPtr = interp->emptyObj; + token->type = t->type; + expr->len++; + } + return JIM_OK; +} + +static int ExprTernaryGetColonLeftIndex(ExprByteCode *expr, int right_index) +{ + int ternary_count = 1; + + right_index--; + + while (right_index > 1) { + if (expr->token[right_index].type == JIM_EXPROP_TERNARY_LEFT) { + ternary_count--; + } + else if (expr->token[right_index].type == JIM_EXPROP_COLON_RIGHT) { + ternary_count++; + } + else if (expr->token[right_index].type == JIM_EXPROP_COLON_LEFT && ternary_count == 1) { + return right_index; + } + right_index--; + } + + + return -1; +} + +static int ExprTernaryGetMoveIndices(ExprByteCode *expr, int right_index, int *prev_right_index, int *prev_left_index) +{ + int i = right_index - 1; + int ternary_count = 1; + + while (i > 1) { + if (expr->token[i].type == JIM_EXPROP_TERNARY_LEFT) { + if (--ternary_count == 0 && expr->token[i - 2].type == JIM_EXPROP_COLON_RIGHT) { + *prev_right_index = i - 2; + *prev_left_index = ExprTernaryGetColonLeftIndex(expr, *prev_right_index); + return 1; + } + } + else if (expr->token[i].type == JIM_EXPROP_COLON_RIGHT) { + if (ternary_count == 0) { + return 0; + } + ternary_count++; + } + i--; + } + return 0; +} + +static void ExprTernaryReorderExpression(Jim_Interp *interp, ExprByteCode *expr) +{ + int i; + + for (i = expr->len - 1; i > 1; i--) { + int prev_right_index; + int prev_left_index; + int j; + ScriptToken tmp; + + if (expr->token[i].type != JIM_EXPROP_COLON_RIGHT) { + continue; + } + + + if (ExprTernaryGetMoveIndices(expr, i, &prev_right_index, &prev_left_index) == 0) { + continue; + } + + tmp = expr->token[prev_right_index]; + for (j = prev_right_index; j < i; j++) { + expr->token[j] = expr->token[j + 1]; + } + expr->token[i] = tmp; + + JimWideValue(expr->token[prev_left_index-1].objPtr) += (i - prev_right_index); + + + i++; + } +} + +static ExprByteCode *ExprCreateByteCode(Jim_Interp *interp, const ParseTokenList *tokenlist, Jim_Obj *fileNameObj) +{ + Jim_Stack stack; + ExprByteCode *expr; + int ok = 1; + int i; + int prevtt = JIM_TT_NONE; + int have_ternary = 0; + + + int count = tokenlist->count - 1; + + expr = Jim_Alloc(sizeof(*expr)); + expr->inUse = 1; + expr->len = 0; + + Jim_InitStack(&stack); + + for (i = 0; i < tokenlist->count; i++) { + ParseToken *t = &tokenlist->list[i]; + const struct Jim_ExprOperator *op = JimExprOperatorInfoByOpcode(t->type); + + if (op->lazy == LAZY_OP) { + count += 2; + + if (t->type == JIM_EXPROP_TERNARY) { + have_ternary = 1; + } + } + } + + expr->token = Jim_Alloc(sizeof(ScriptToken) * count); + + for (i = 0; i < tokenlist->count && ok; i++) { + ParseToken *t = &tokenlist->list[i]; + + + struct ScriptToken *token = &expr->token[expr->len]; + + if (t->type == JIM_TT_EOL) { + break; + } + + switch (t->type) { + case JIM_TT_STR: + case JIM_TT_ESC: + case JIM_TT_VAR: + case JIM_TT_DICTSUGAR: + case JIM_TT_EXPRSUGAR: + case JIM_TT_CMD: + token->type = t->type; +strexpr: + token->objPtr = Jim_NewStringObj(interp, t->token, t->len); + if (t->type == JIM_TT_CMD) { + + JimSetSourceInfo(interp, token->objPtr, fileNameObj, t->line); + } + expr->len++; + break; + + case JIM_TT_EXPR_INT: + case JIM_TT_EXPR_DOUBLE: + { + char *endptr; + if (t->type == JIM_TT_EXPR_INT) { + token->objPtr = Jim_NewIntObj(interp, jim_strtoull(t->token, &endptr)); + } + else { + token->objPtr = Jim_NewDoubleObj(interp, strtod(t->token, &endptr)); + } + if (endptr != t->token + t->len) { + + Jim_FreeNewObj(interp, token->objPtr); + token->type = JIM_TT_STR; + goto strexpr; + } + token->type = t->type; + expr->len++; + } + break; + + case JIM_TT_SUBEXPR_START: + Jim_StackPush(&stack, t); + prevtt = JIM_TT_NONE; + continue; + + case JIM_TT_SUBEXPR_COMMA: + + continue; + + case JIM_TT_SUBEXPR_END: + ok = 0; + while (Jim_StackLen(&stack)) { + ParseToken *tt = Jim_StackPop(&stack); + + if (tt->type == JIM_TT_SUBEXPR_START) { + ok = 1; + break; + } + + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + goto err; + } + } + if (!ok) { + Jim_SetResultString(interp, "Unexpected close parenthesis", -1); + goto err; + } + break; + + + default:{ + + const struct Jim_ExprOperator *op; + ParseToken *tt; + + + if (prevtt == JIM_TT_NONE || prevtt >= JIM_TT_EXPR_OP) { + if (t->type == JIM_EXPROP_SUB) { + t->type = JIM_EXPROP_UNARYMINUS; + } + else if (t->type == JIM_EXPROP_ADD) { + t->type = JIM_EXPROP_UNARYPLUS; + } + } + + op = JimExprOperatorInfoByOpcode(t->type); + + + while ((tt = Jim_StackPeek(&stack)) != NULL) { + const struct Jim_ExprOperator *tt_op = + JimExprOperatorInfoByOpcode(tt->type); + + + + if (op->arity != 1 && tt_op->precedence >= op->precedence) { + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + ok = 0; + goto err; + } + Jim_StackPop(&stack); + } + else { + break; + } + } + Jim_StackPush(&stack, t); + break; + } + } + prevtt = t->type; + } + + + while (Jim_StackLen(&stack)) { + ParseToken *tt = Jim_StackPop(&stack); + + if (tt->type == JIM_TT_SUBEXPR_START) { + ok = 0; + Jim_SetResultString(interp, "Missing close parenthesis", -1); + goto err; + } + if (ExprAddOperator(interp, expr, tt) != JIM_OK) { + ok = 0; + goto err; + } + } + + if (have_ternary) { + ExprTernaryReorderExpression(interp, expr); + } + + err: + + Jim_FreeStack(&stack); + + for (i = 0; i < expr->len; i++) { + Jim_IncrRefCount(expr->token[i].objPtr); + } + + if (!ok) { + ExprFreeByteCode(interp, expr); + return NULL; + } + + return expr; +} + + +static int SetExprFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr) +{ + int exprTextLen; + const char *exprText; + struct JimParserCtx parser; + struct ExprByteCode *expr; + ParseTokenList tokenlist; + int line; + Jim_Obj *fileNameObj; + int rc = JIM_ERR; + + + if (objPtr->typePtr == &sourceObjType) { + fileNameObj = objPtr->internalRep.sourceValue.fileNameObj; + line = objPtr->internalRep.sourceValue.lineNumber; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + Jim_IncrRefCount(fileNameObj); + + exprText = Jim_GetString(objPtr, &exprTextLen); + + + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, exprText, exprTextLen, line); + while (!parser.eof) { + if (JimParseExpression(&parser) != JIM_OK) { + ScriptTokenListFree(&tokenlist); + invalidexpr: + Jim_SetResultFormatted(interp, "syntax error in expression: \"%#s\"", objPtr); + expr = NULL; + goto err; + } + + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + +#ifdef DEBUG_SHOW_EXPR_TOKENS + { + int i; + printf("==== Expr Tokens (%s) ====\n", Jim_String(fileNameObj)); + for (i = 0; i < tokenlist.count; i++) { + printf("[%2d]@%d %s '%.*s'\n", i, tokenlist.list[i].line, jim_tt_name(tokenlist.list[i].type), + tokenlist.list[i].len, tokenlist.list[i].token); + } + } +#endif + + if (JimParseCheckMissing(interp, parser.missing.ch) == JIM_ERR) { + ScriptTokenListFree(&tokenlist); + Jim_DecrRefCount(interp, fileNameObj); + return JIM_ERR; + } + + + expr = ExprCreateByteCode(interp, &tokenlist, fileNameObj); + + + ScriptTokenListFree(&tokenlist); + + if (!expr) { + goto err; + } + +#ifdef DEBUG_SHOW_EXPR + { + int i; + + printf("==== Expr ====\n"); + for (i = 0; i < expr->len; i++) { + ScriptToken *t = &expr->token[i]; + + printf("[%2d] %s '%s'\n", i, jim_tt_name(t->type), Jim_String(t->objPtr)); + } + } +#endif + + + if (ExprCheckCorrectness(expr) != JIM_OK) { + ExprFreeByteCode(interp, expr); + goto invalidexpr; + } + + rc = JIM_OK; + + err: + + Jim_DecrRefCount(interp, fileNameObj); + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, expr); + objPtr->typePtr = &exprObjType; + return rc; +} + +static ExprByteCode *JimGetExpression(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (objPtr->typePtr != &exprObjType) { + if (SetExprFromAny(interp, objPtr) != JIM_OK) { + return NULL; + } + } + return (ExprByteCode *) Jim_GetIntRepPtr(objPtr); +} + +#ifdef JIM_OPTIMIZATION +static Jim_Obj *JimExprIntValOrVar(Jim_Interp *interp, const ScriptToken *token) +{ + if (token->type == JIM_TT_EXPR_INT) + return token->objPtr; + else if (token->type == JIM_TT_VAR) + return Jim_GetVariable(interp, token->objPtr, JIM_NONE); + else if (token->type == JIM_TT_DICTSUGAR) + return JimExpandDictSugar(interp, token->objPtr); + else + return NULL; +} +#endif + +#define JIM_EE_STATICSTACK_LEN 10 + +int Jim_EvalExpression(Jim_Interp *interp, Jim_Obj *exprObjPtr, Jim_Obj **exprResultPtrPtr) +{ + ExprByteCode *expr; + Jim_Obj *staticStack[JIM_EE_STATICSTACK_LEN]; + int i; + int retcode = JIM_OK; + struct JimExprState e; + + expr = JimGetExpression(interp, exprObjPtr); + if (!expr) { + return JIM_ERR; + } + +#ifdef JIM_OPTIMIZATION + { + Jim_Obj *objPtr; + + + switch (expr->len) { + case 1: + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); + if (objPtr) { + Jim_IncrRefCount(objPtr); + *exprResultPtrPtr = objPtr; + return JIM_OK; + } + break; + + case 2: + if (expr->token[1].type == JIM_EXPROP_NOT) { + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); + + if (objPtr && JimIsWide(objPtr)) { + *exprResultPtrPtr = JimWideValue(objPtr) ? interp->falseObj : interp->trueObj; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + break; + + case 3: + objPtr = JimExprIntValOrVar(interp, &expr->token[0]); + if (objPtr && JimIsWide(objPtr)) { + Jim_Obj *objPtr2 = JimExprIntValOrVar(interp, &expr->token[1]); + if (objPtr2 && JimIsWide(objPtr2)) { + jim_wide wideValueA = JimWideValue(objPtr); + jim_wide wideValueB = JimWideValue(objPtr2); + int cmpRes; + switch (expr->token[2].type) { + case JIM_EXPROP_LT: + cmpRes = wideValueA < wideValueB; + break; + case JIM_EXPROP_LTE: + cmpRes = wideValueA <= wideValueB; + break; + case JIM_EXPROP_GT: + cmpRes = wideValueA > wideValueB; + break; + case JIM_EXPROP_GTE: + cmpRes = wideValueA >= wideValueB; + break; + case JIM_EXPROP_NUMEQ: + cmpRes = wideValueA == wideValueB; + break; + case JIM_EXPROP_NUMNE: + cmpRes = wideValueA != wideValueB; + break; + default: + goto noopt; + } + *exprResultPtrPtr = cmpRes ? interp->trueObj : interp->falseObj; + Jim_IncrRefCount(*exprResultPtrPtr); + return JIM_OK; + } + } + break; + } + } +noopt: +#endif + + expr->inUse++; + + + + if (expr->len > JIM_EE_STATICSTACK_LEN) + e.stack = Jim_Alloc(sizeof(Jim_Obj *) * expr->len); + else + e.stack = staticStack; + + e.stacklen = 0; + + + for (i = 0; i < expr->len && retcode == JIM_OK; i++) { + Jim_Obj *objPtr; + + switch (expr->token[i].type) { + case JIM_TT_EXPR_INT: + case JIM_TT_EXPR_DOUBLE: + case JIM_TT_STR: + ExprPush(&e, expr->token[i].objPtr); + break; + + case JIM_TT_VAR: + objPtr = Jim_GetVariable(interp, expr->token[i].objPtr, JIM_ERRMSG); + if (objPtr) { + ExprPush(&e, objPtr); + } + else { + retcode = JIM_ERR; + } + break; + + case JIM_TT_DICTSUGAR: + objPtr = JimExpandDictSugar(interp, expr->token[i].objPtr); + if (objPtr) { + ExprPush(&e, objPtr); + } + else { + retcode = JIM_ERR; + } + break; + + case JIM_TT_ESC: + retcode = Jim_SubstObj(interp, expr->token[i].objPtr, &objPtr, JIM_NONE); + if (retcode == JIM_OK) { + ExprPush(&e, objPtr); + } + break; + + case JIM_TT_CMD: + retcode = Jim_EvalObj(interp, expr->token[i].objPtr); + if (retcode == JIM_OK) { + ExprPush(&e, Jim_GetResult(interp)); + } + break; + + default:{ + + e.skip = 0; + e.opcode = expr->token[i].type; + + retcode = JimExprOperatorInfoByOpcode(e.opcode)->funcop(interp, &e); + + i += e.skip; + continue; + } + } + } + + expr->inUse--; + + if (retcode == JIM_OK) { + *exprResultPtrPtr = ExprPop(&e); + } + else { + for (i = 0; i < e.stacklen; i++) { + Jim_DecrRefCount(interp, e.stack[i]); + } + } + if (e.stack != staticStack) { + Jim_Free(e.stack); + } + return retcode; +} + +int Jim_GetBoolFromExpr(Jim_Interp *interp, Jim_Obj *exprObjPtr, int *boolPtr) +{ + int retcode; + jim_wide wideValue; + double doubleValue; + Jim_Obj *exprResultPtr; + + retcode = Jim_EvalExpression(interp, exprObjPtr, &exprResultPtr); + if (retcode != JIM_OK) + return retcode; + + if (JimGetWideNoErr(interp, exprResultPtr, &wideValue) != JIM_OK) { + if (Jim_GetDouble(interp, exprResultPtr, &doubleValue) != JIM_OK) { + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_ERR; + } + else { + Jim_DecrRefCount(interp, exprResultPtr); + *boolPtr = doubleValue != 0; + return JIM_OK; + } + } + *boolPtr = wideValue != 0; + + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_OK; +} + + + + +typedef struct ScanFmtPartDescr +{ + char *arg; + char *prefix; + size_t width; + int pos; + char type; + char modifier; +} ScanFmtPartDescr; + + +typedef struct ScanFmtStringObj +{ + jim_wide size; + char *stringRep; + size_t count; + size_t convCount; + size_t maxPos; + const char *error; + char *scratch; + ScanFmtPartDescr descr[1]; +} ScanFmtStringObj; + + +static void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr); +static void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr); +static void UpdateStringOfScanFmt(Jim_Obj *objPtr); + +static const Jim_ObjType scanFmtStringObjType = { + "scanformatstring", + FreeScanFmtInternalRep, + DupScanFmtInternalRep, + UpdateStringOfScanFmt, + JIM_TYPE_NONE, +}; + +void FreeScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *objPtr) +{ + JIM_NOTUSED(interp); + Jim_Free((char *)objPtr->internalRep.ptr); + objPtr->internalRep.ptr = 0; +} + +void DupScanFmtInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr) +{ + size_t size = (size_t) ((ScanFmtStringObj *) srcPtr->internalRep.ptr)->size; + ScanFmtStringObj *newVec = (ScanFmtStringObj *) Jim_Alloc(size); + + JIM_NOTUSED(interp); + memcpy(newVec, srcPtr->internalRep.ptr, size); + dupPtr->internalRep.ptr = newVec; + dupPtr->typePtr = &scanFmtStringObjType; +} + +static void UpdateStringOfScanFmt(Jim_Obj *objPtr) +{ + JimSetStringBytes(objPtr, ((ScanFmtStringObj *) objPtr->internalRep.ptr)->stringRep); +} + + +static int SetScanFmtFromAny(Jim_Interp *interp, Jim_Obj *objPtr) +{ + ScanFmtStringObj *fmtObj; + char *buffer; + int maxCount, i, approxSize, lastPos = -1; + const char *fmt = objPtr->bytes; + int maxFmtLen = objPtr->length; + const char *fmtEnd = fmt + maxFmtLen; + int curr; + + Jim_FreeIntRep(interp, objPtr); + + for (i = 0, maxCount = 0; i < maxFmtLen; ++i) + if (fmt[i] == '%') + ++maxCount; + + approxSize = sizeof(ScanFmtStringObj) + +(maxCount + 1) * sizeof(ScanFmtPartDescr) + +maxFmtLen * sizeof(char) + 3 + 1 + + maxFmtLen * sizeof(char) + 1 + + maxFmtLen * sizeof(char) + +(maxCount + 1) * sizeof(char) + +1; + fmtObj = (ScanFmtStringObj *) Jim_Alloc(approxSize); + memset(fmtObj, 0, approxSize); + fmtObj->size = approxSize; + fmtObj->maxPos = 0; + fmtObj->scratch = (char *)&fmtObj->descr[maxCount + 1]; + fmtObj->stringRep = fmtObj->scratch + maxFmtLen + 3 + 1; + memcpy(fmtObj->stringRep, fmt, maxFmtLen); + buffer = fmtObj->stringRep + maxFmtLen + 1; + objPtr->internalRep.ptr = fmtObj; + objPtr->typePtr = &scanFmtStringObjType; + for (i = 0, curr = 0; fmt < fmtEnd; ++fmt) { + int width = 0, skip; + ScanFmtPartDescr *descr = &fmtObj->descr[curr]; + + fmtObj->count++; + descr->width = 0; + + if (*fmt != '%' || fmt[1] == '%') { + descr->type = 0; + descr->prefix = &buffer[i]; + for (; fmt < fmtEnd; ++fmt) { + if (*fmt == '%') { + if (fmt[1] != '%') + break; + ++fmt; + } + buffer[i++] = *fmt; + } + buffer[i++] = 0; + } + + ++fmt; + + if (fmt >= fmtEnd) + goto done; + descr->pos = 0; + if (*fmt == '*') { + descr->pos = -1; + ++fmt; + } + else + fmtObj->convCount++; + + if (sscanf(fmt, "%d%n", &width, &skip) == 1) { + fmt += skip; + + if (descr->pos != -1 && *fmt == '$') { + int prev; + + ++fmt; + descr->pos = width; + width = 0; + + if ((lastPos == 0 && descr->pos > 0) + || (lastPos > 0 && descr->pos == 0)) { + fmtObj->error = "cannot mix \"%\" and \"%n$\" conversion specifiers"; + return JIM_ERR; + } + + for (prev = 0; prev < curr; ++prev) { + if (fmtObj->descr[prev].pos == -1) + continue; + if (fmtObj->descr[prev].pos == descr->pos) { + fmtObj->error = + "variable is assigned by multiple \"%n$\" conversion specifiers"; + return JIM_ERR; + } + } + + if (sscanf(fmt, "%d%n", &width, &skip) == 1) { + descr->width = width; + fmt += skip; + } + if (descr->pos > 0 && (size_t) descr->pos > fmtObj->maxPos) + fmtObj->maxPos = descr->pos; + } + else { + + descr->width = width; + } + } + + if (lastPos == -1) + lastPos = descr->pos; + + if (*fmt == '[') { + int swapped = 1, beg = i, end, j; + + descr->type = '['; + descr->arg = &buffer[i]; + ++fmt; + if (*fmt == '^') + buffer[i++] = *fmt++; + if (*fmt == ']') + buffer[i++] = *fmt++; + while (*fmt && *fmt != ']') + buffer[i++] = *fmt++; + if (*fmt != ']') { + fmtObj->error = "unmatched [ in format string"; + return JIM_ERR; + } + end = i; + buffer[i++] = 0; + + while (swapped) { + swapped = 0; + for (j = beg + 1; j < end - 1; ++j) { + if (buffer[j] == '-' && buffer[j - 1] > buffer[j + 1]) { + char tmp = buffer[j - 1]; + + buffer[j - 1] = buffer[j + 1]; + buffer[j + 1] = tmp; + swapped = 1; + } + } + } + } + else { + + if (strchr("hlL", *fmt) != 0) + descr->modifier = tolower((int)*fmt++); + + descr->type = *fmt; + if (strchr("efgcsndoxui", *fmt) == 0) { + fmtObj->error = "bad scan conversion character"; + return JIM_ERR; + } + else if (*fmt == 'c' && descr->width != 0) { + fmtObj->error = "field width may not be specified in %c " "conversion"; + return JIM_ERR; + } + else if (*fmt == 'u' && descr->modifier == 'l') { + fmtObj->error = "unsigned wide not supported"; + return JIM_ERR; + } + } + curr++; + } + done: + return JIM_OK; +} + + + +#define FormatGetCnvCount(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->convCount +#define FormatGetMaxPos(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->maxPos +#define FormatGetError(_fo_) \ + ((ScanFmtStringObj*)((_fo_)->internalRep.ptr))->error + +static Jim_Obj *JimScanAString(Jim_Interp *interp, const char *sdescr, const char *str) +{ + char *buffer = Jim_StrDup(str); + char *p = buffer; + + while (*str) { + int c; + int n; + + if (!sdescr && isspace(UCHAR(*str))) + break; + + n = utf8_tounicode(str, &c); + if (sdescr && !JimCharsetMatch(sdescr, c, JIM_CHARSET_SCAN)) + break; + while (n--) + *p++ = *str++; + } + *p = 0; + return Jim_NewStringObjNoAlloc(interp, buffer, p - buffer); +} + + +static int ScanOneEntry(Jim_Interp *interp, const char *str, int pos, int strLen, + ScanFmtStringObj * fmtObj, long idx, Jim_Obj **valObjPtr) +{ + const char *tok; + const ScanFmtPartDescr *descr = &fmtObj->descr[idx]; + size_t scanned = 0; + size_t anchor = pos; + int i; + Jim_Obj *tmpObj = NULL; + + + *valObjPtr = 0; + if (descr->prefix) { + for (i = 0; pos < strLen && descr->prefix[i]; ++i) { + + if (isspace(UCHAR(descr->prefix[i]))) + while (pos < strLen && isspace(UCHAR(str[pos]))) + ++pos; + else if (descr->prefix[i] != str[pos]) + break; + else + ++pos; + } + if (pos >= strLen) { + return -1; + } + else if (descr->prefix[i] != 0) + return 0; + } + + if (descr->type != 'c' && descr->type != '[' && descr->type != 'n') + while (isspace(UCHAR(str[pos]))) + ++pos; + + scanned = pos - anchor; + + + if (descr->type == 'n') { + + *valObjPtr = Jim_NewIntObj(interp, anchor + scanned); + } + else if (pos >= strLen) { + + return -1; + } + else if (descr->type == 'c') { + int c; + scanned += utf8_tounicode(&str[pos], &c); + *valObjPtr = Jim_NewIntObj(interp, c); + return scanned; + } + else { + + if (descr->width > 0) { + size_t sLen = utf8_strlen(&str[pos], strLen - pos); + size_t tLen = descr->width > sLen ? sLen : descr->width; + + tmpObj = Jim_NewStringObjUtf8(interp, str + pos, tLen); + tok = tmpObj->bytes; + } + else { + + tok = &str[pos]; + } + switch (descr->type) { + case 'd': + case 'o': + case 'x': + case 'u': + case 'i':{ + char *endp; + jim_wide w; + + int base = descr->type == 'o' ? 8 + : descr->type == 'x' ? 16 : descr->type == 'i' ? 0 : 10; + + + if (base == 0) { + w = jim_strtoull(tok, &endp); + } + else { + w = strtoull(tok, &endp, base); + } + + if (endp != tok) { + + *valObjPtr = Jim_NewIntObj(interp, w); + + + scanned += endp - tok; + } + else { + scanned = *tok ? 0 : -1; + } + break; + } + case 's': + case '[':{ + *valObjPtr = JimScanAString(interp, descr->arg, tok); + scanned += Jim_Length(*valObjPtr); + break; + } + case 'e': + case 'f': + case 'g':{ + char *endp; + double value = strtod(tok, &endp); + + if (endp != tok) { + + *valObjPtr = Jim_NewDoubleObj(interp, value); + + scanned += endp - tok; + } + else { + scanned = *tok ? 0 : -1; + } + break; + } + } + if (tmpObj) { + Jim_FreeNewObj(interp, tmpObj); + } + } + return scanned; +} + + +Jim_Obj *Jim_ScanString(Jim_Interp *interp, Jim_Obj *strObjPtr, Jim_Obj *fmtObjPtr, int flags) +{ + size_t i, pos; + int scanned = 1; + const char *str = Jim_String(strObjPtr); + int strLen = Jim_Utf8Length(interp, strObjPtr); + Jim_Obj *resultList = 0; + Jim_Obj **resultVec = 0; + int resultc; + Jim_Obj *emptyStr = 0; + ScanFmtStringObj *fmtObj; + + + JimPanic((fmtObjPtr->typePtr != &scanFmtStringObjType, "Jim_ScanString() for non-scan format")); + + fmtObj = (ScanFmtStringObj *) fmtObjPtr->internalRep.ptr; + + if (fmtObj->error != 0) { + if (flags & JIM_ERRMSG) + Jim_SetResultString(interp, fmtObj->error, -1); + return 0; + } + + emptyStr = Jim_NewEmptyStringObj(interp); + Jim_IncrRefCount(emptyStr); + + resultList = Jim_NewListObj(interp, NULL, 0); + if (fmtObj->maxPos > 0) { + for (i = 0; i < fmtObj->maxPos; ++i) + Jim_ListAppendElement(interp, resultList, emptyStr); + JimListGetElements(interp, resultList, &resultc, &resultVec); + } + + for (i = 0, pos = 0; i < fmtObj->count; ++i) { + ScanFmtPartDescr *descr = &(fmtObj->descr[i]); + Jim_Obj *value = 0; + + + if (descr->type == 0) + continue; + + if (scanned > 0) + scanned = ScanOneEntry(interp, str, pos, strLen, fmtObj, i, &value); + + if (scanned == -1 && i == 0) + goto eof; + + pos += scanned; + + + if (value == 0) + value = Jim_NewEmptyStringObj(interp); + + if (descr->pos == -1) { + Jim_FreeNewObj(interp, value); + } + else if (descr->pos == 0) + + Jim_ListAppendElement(interp, resultList, value); + else if (resultVec[descr->pos - 1] == emptyStr) { + + Jim_DecrRefCount(interp, resultVec[descr->pos - 1]); + Jim_IncrRefCount(value); + resultVec[descr->pos - 1] = value; + } + else { + + Jim_FreeNewObj(interp, value); + goto err; + } + } + Jim_DecrRefCount(interp, emptyStr); + return resultList; + eof: + Jim_DecrRefCount(interp, emptyStr); + Jim_FreeNewObj(interp, resultList); + return (Jim_Obj *)EOF; + err: + Jim_DecrRefCount(interp, emptyStr); + Jim_FreeNewObj(interp, resultList); + return 0; +} + + +static void JimPrngInit(Jim_Interp *interp) +{ +#define PRNG_SEED_SIZE 256 + int i; + unsigned int *seed; + time_t t = time(NULL); + + interp->prngState = Jim_Alloc(sizeof(Jim_PrngState)); + + seed = Jim_Alloc(PRNG_SEED_SIZE * sizeof(*seed)); + for (i = 0; i < PRNG_SEED_SIZE; i++) { + seed[i] = (rand() ^ t ^ clock()); + } + JimPrngSeed(interp, (unsigned char *)seed, PRNG_SEED_SIZE * sizeof(*seed)); + Jim_Free(seed); +} + + +static void JimRandomBytes(Jim_Interp *interp, void *dest, unsigned int len) +{ + Jim_PrngState *prng; + unsigned char *destByte = (unsigned char *)dest; + unsigned int si, sj, x; + + + if (interp->prngState == NULL) + JimPrngInit(interp); + prng = interp->prngState; + + for (x = 0; x < len; x++) { + prng->i = (prng->i + 1) & 0xff; + si = prng->sbox[prng->i]; + prng->j = (prng->j + si) & 0xff; + sj = prng->sbox[prng->j]; + prng->sbox[prng->i] = sj; + prng->sbox[prng->j] = si; + *destByte++ = prng->sbox[(si + sj) & 0xff]; + } +} + + +static void JimPrngSeed(Jim_Interp *interp, unsigned char *seed, int seedLen) +{ + int i; + Jim_PrngState *prng; + + + if (interp->prngState == NULL) + JimPrngInit(interp); + prng = interp->prngState; + + + for (i = 0; i < 256; i++) + prng->sbox[i] = i; + + for (i = 0; i < seedLen; i++) { + unsigned char t; + + t = prng->sbox[i & 0xFF]; + prng->sbox[i & 0xFF] = prng->sbox[seed[i]]; + prng->sbox[seed[i]] = t; + } + prng->i = prng->j = 0; + + for (i = 0; i < 256; i += seedLen) { + JimRandomBytes(interp, seed, seedLen); + } +} + + +static int Jim_IncrCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide wideValue, increment = 1; + Jim_Obj *intObjPtr; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?"); + return JIM_ERR; + } + if (argc == 3) { + if (Jim_GetWide(interp, argv[2], &increment) != JIM_OK) + return JIM_ERR; + } + intObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!intObjPtr) { + + wideValue = 0; + } + else if (Jim_GetWide(interp, intObjPtr, &wideValue) != JIM_OK) { + return JIM_ERR; + } + if (!intObjPtr || Jim_IsShared(intObjPtr)) { + intObjPtr = Jim_NewIntObj(interp, wideValue + increment); + if (Jim_SetVariable(interp, argv[1], intObjPtr) != JIM_OK) { + Jim_FreeNewObj(interp, intObjPtr); + return JIM_ERR; + } + } + else { + + Jim_InvalidateStringRep(intObjPtr); + JimWideValue(intObjPtr) = wideValue + increment; + + if (argv[1]->typePtr != &variableObjType) { + + Jim_SetVariable(interp, argv[1], intObjPtr); + } + } + Jim_SetResult(interp, intObjPtr); + return JIM_OK; +} + + +#define JIM_EVAL_SARGV_LEN 8 +#define JIM_EVAL_SINTV_LEN 8 + + +static int JimUnknown(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retcode; + + if (interp->unknown_called > 50) { + return JIM_ERR; + } + + + + if (Jim_GetCommand(interp, interp->unknown, JIM_NONE) == NULL) + return JIM_ERR; + + interp->unknown_called++; + + retcode = Jim_EvalObjPrefix(interp, interp->unknown, argc, argv); + interp->unknown_called--; + + return retcode; +} + +static int JimInvokeCommand(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + int retcode; + Jim_Cmd *cmdPtr; + +#if 0 + printf("invoke"); + int j; + for (j = 0; j < objc; j++) { + printf(" '%s'", Jim_String(objv[j])); + } + printf("\n"); +#endif + + if (interp->framePtr->tailcallCmd) { + + cmdPtr = interp->framePtr->tailcallCmd; + interp->framePtr->tailcallCmd = NULL; + } + else { + cmdPtr = Jim_GetCommand(interp, objv[0], JIM_ERRMSG); + if (cmdPtr == NULL) { + return JimUnknown(interp, objc, objv); + } + JimIncrCmdRefCount(cmdPtr); + } + + if (interp->evalDepth == interp->maxEvalDepth) { + Jim_SetResultString(interp, "Infinite eval recursion", -1); + retcode = JIM_ERR; + goto out; + } + interp->evalDepth++; + + + Jim_SetEmptyResult(interp); + if (cmdPtr->isproc) { + retcode = JimCallProcedure(interp, cmdPtr, objc, objv); + } + else { + interp->cmdPrivData = cmdPtr->u.native.privData; + retcode = cmdPtr->u.native.cmdProc(interp, objc, objv); + } + interp->evalDepth--; + +out: + JimDecrCmdRefCount(interp, cmdPtr); + + return retcode; +} + +int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) +{ + int i, retcode; + + + for (i = 0; i < objc; i++) + Jim_IncrRefCount(objv[i]); + + retcode = JimInvokeCommand(interp, objc, objv); + + + for (i = 0; i < objc; i++) + Jim_DecrRefCount(interp, objv[i]); + + return retcode; +} + +int Jim_EvalObjPrefix(Jim_Interp *interp, Jim_Obj *prefix, int objc, Jim_Obj *const *objv) +{ + int ret; + Jim_Obj **nargv = Jim_Alloc((objc + 1) * sizeof(*nargv)); + + nargv[0] = prefix; + memcpy(&nargv[1], &objv[0], sizeof(nargv[0]) * objc); + ret = Jim_EvalObjVector(interp, objc + 1, nargv); + Jim_Free(nargv); + return ret; +} + +static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script) +{ + if (!interp->errorFlag) { + + interp->errorFlag = 1; + Jim_IncrRefCount(script->fileNameObj); + Jim_DecrRefCount(interp, interp->errorFileNameObj); + interp->errorFileNameObj = script->fileNameObj; + interp->errorLine = script->linenr; + + JimResetStackTrace(interp); + + interp->addStackTrace++; + } + + + if (interp->addStackTrace > 0) { + + + JimAppendStackTrace(interp, Jim_String(interp->errorProc), script->fileNameObj, script->linenr); + + if (Jim_Length(script->fileNameObj)) { + interp->addStackTrace = 0; + } + + Jim_DecrRefCount(interp, interp->errorProc); + interp->errorProc = interp->emptyObj; + Jim_IncrRefCount(interp->errorProc); + } +} + +static int JimSubstOneToken(Jim_Interp *interp, const ScriptToken *token, Jim_Obj **objPtrPtr) +{ + Jim_Obj *objPtr; + + switch (token->type) { + case JIM_TT_STR: + case JIM_TT_ESC: + objPtr = token->objPtr; + break; + case JIM_TT_VAR: + objPtr = Jim_GetVariable(interp, token->objPtr, JIM_ERRMSG); + break; + case JIM_TT_DICTSUGAR: + objPtr = JimExpandDictSugar(interp, token->objPtr); + break; + case JIM_TT_EXPRSUGAR: + objPtr = JimExpandExprSugar(interp, token->objPtr); + break; + case JIM_TT_CMD: + switch (Jim_EvalObj(interp, token->objPtr)) { + case JIM_OK: + case JIM_RETURN: + objPtr = interp->result; + break; + case JIM_BREAK: + + return JIM_BREAK; + case JIM_CONTINUE: + + return JIM_CONTINUE; + default: + return JIM_ERR; + } + break; + default: + JimPanic((1, + "default token type (%d) reached " "in Jim_SubstObj().", token->type)); + objPtr = NULL; + break; + } + if (objPtr) { + *objPtrPtr = objPtr; + return JIM_OK; + } + return JIM_ERR; +} + +static Jim_Obj *JimInterpolateTokens(Jim_Interp *interp, const ScriptToken * token, int tokens, int flags) +{ + int totlen = 0, i; + Jim_Obj **intv; + Jim_Obj *sintv[JIM_EVAL_SINTV_LEN]; + Jim_Obj *objPtr; + char *s; + + if (tokens <= JIM_EVAL_SINTV_LEN) + intv = sintv; + else + intv = Jim_Alloc(sizeof(Jim_Obj *) * tokens); + + for (i = 0; i < tokens; i++) { + switch (JimSubstOneToken(interp, &token[i], &intv[i])) { + case JIM_OK: + case JIM_RETURN: + break; + case JIM_BREAK: + if (flags & JIM_SUBST_FLAG) { + + tokens = i; + continue; + } + + + case JIM_CONTINUE: + if (flags & JIM_SUBST_FLAG) { + intv[i] = NULL; + continue; + } + + + default: + while (i--) { + Jim_DecrRefCount(interp, intv[i]); + } + if (intv != sintv) { + Jim_Free(intv); + } + return NULL; + } + Jim_IncrRefCount(intv[i]); + Jim_String(intv[i]); + totlen += intv[i]->length; + } + + + if (tokens == 1 && intv[0] && intv == sintv) { + Jim_DecrRefCount(interp, intv[0]); + return intv[0]; + } + + objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0); + + if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC + && token[2].type == JIM_TT_VAR) { + + objPtr->typePtr = &interpolatedObjType; + objPtr->internalRep.dictSubstValue.varNameObjPtr = token[0].objPtr; + objPtr->internalRep.dictSubstValue.indexObjPtr = intv[2]; + Jim_IncrRefCount(intv[2]); + } + else if (tokens && intv[0] && intv[0]->typePtr == &sourceObjType) { + + JimSetSourceInfo(interp, objPtr, intv[0]->internalRep.sourceValue.fileNameObj, intv[0]->internalRep.sourceValue.lineNumber); + } + + + s = objPtr->bytes = Jim_Alloc(totlen + 1); + objPtr->length = totlen; + for (i = 0; i < tokens; i++) { + if (intv[i]) { + memcpy(s, intv[i]->bytes, intv[i]->length); + s += intv[i]->length; + Jim_DecrRefCount(interp, intv[i]); + } + } + objPtr->bytes[totlen] = '\0'; + + if (intv != sintv) { + Jim_Free(intv); + } + + return objPtr; +} + + +static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr) +{ + int retcode = JIM_OK; + + JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list.")); + + if (listPtr->internalRep.listValue.len) { + Jim_IncrRefCount(listPtr); + retcode = JimInvokeCommand(interp, + listPtr->internalRep.listValue.len, + listPtr->internalRep.listValue.ele); + Jim_DecrRefCount(interp, listPtr); + } + return retcode; +} + +int Jim_EvalObjList(Jim_Interp *interp, Jim_Obj *listPtr) +{ + SetListFromAny(interp, listPtr); + return JimEvalObjList(interp, listPtr); +} + +int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) +{ + int i; + ScriptObj *script; + ScriptToken *token; + int retcode = JIM_OK; + Jim_Obj *sargv[JIM_EVAL_SARGV_LEN], **argv = NULL; + Jim_Obj *prevScriptObj; + + if (Jim_IsList(scriptObjPtr) && scriptObjPtr->bytes == NULL) { + return JimEvalObjList(interp, scriptObjPtr); + } + + Jim_IncrRefCount(scriptObjPtr); + script = JimGetScript(interp, scriptObjPtr); + if (!JimScriptValid(interp, script)) { + Jim_DecrRefCount(interp, scriptObjPtr); + return JIM_ERR; + } + + Jim_SetEmptyResult(interp); + + token = script->token; + +#ifdef JIM_OPTIMIZATION + if (script->len == 0) { + Jim_DecrRefCount(interp, scriptObjPtr); + return JIM_OK; + } + if (script->len == 3 + && token[1].objPtr->typePtr == &commandObjType + && token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0 + && token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand + && token[2].objPtr->typePtr == &variableObjType) { + + Jim_Obj *objPtr = Jim_GetVariable(interp, token[2].objPtr, JIM_NONE); + + if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + JimWideValue(objPtr)++; + Jim_InvalidateStringRep(objPtr); + Jim_DecrRefCount(interp, scriptObjPtr); + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + } +#endif + + script->inUse++; + + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + interp->errorFlag = 0; + argv = sargv; + + for (i = 0; i < script->len && retcode == JIM_OK; ) { + int argc; + int j; + + + argc = token[i].objPtr->internalRep.scriptLineValue.argc; + script->linenr = token[i].objPtr->internalRep.scriptLineValue.line; + + + if (argc > JIM_EVAL_SARGV_LEN) + argv = Jim_Alloc(sizeof(Jim_Obj *) * argc); + + + i++; + + for (j = 0; j < argc; j++) { + long wordtokens = 1; + int expand = 0; + Jim_Obj *wordObjPtr = NULL; + + if (token[i].type == JIM_TT_WORD) { + wordtokens = JimWideValue(token[i++].objPtr); + if (wordtokens < 0) { + expand = 1; + wordtokens = -wordtokens; + } + } + + if (wordtokens == 1) { + + switch (token[i].type) { + case JIM_TT_ESC: + case JIM_TT_STR: + wordObjPtr = token[i].objPtr; + break; + case JIM_TT_VAR: + wordObjPtr = Jim_GetVariable(interp, token[i].objPtr, JIM_ERRMSG); + break; + case JIM_TT_EXPRSUGAR: + wordObjPtr = JimExpandExprSugar(interp, token[i].objPtr); + break; + case JIM_TT_DICTSUGAR: + wordObjPtr = JimExpandDictSugar(interp, token[i].objPtr); + break; + case JIM_TT_CMD: + retcode = Jim_EvalObj(interp, token[i].objPtr); + if (retcode == JIM_OK) { + wordObjPtr = Jim_GetResult(interp); + } + break; + default: + JimPanic((1, "default token type reached " "in Jim_EvalObj().")); + } + } + else { + wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE); + } + + if (!wordObjPtr) { + if (retcode == JIM_OK) { + retcode = JIM_ERR; + } + break; + } + + Jim_IncrRefCount(wordObjPtr); + i += wordtokens; + + if (!expand) { + argv[j] = wordObjPtr; + } + else { + + int len = Jim_ListLength(interp, wordObjPtr); + int newargc = argc + len - 1; + int k; + + if (len > 1) { + if (argv == sargv) { + if (newargc > JIM_EVAL_SARGV_LEN) { + argv = Jim_Alloc(sizeof(*argv) * newargc); + memcpy(argv, sargv, sizeof(*argv) * j); + } + } + else { + + argv = Jim_Realloc(argv, sizeof(*argv) * newargc); + } + } + + + for (k = 0; k < len; k++) { + argv[j++] = wordObjPtr->internalRep.listValue.ele[k]; + Jim_IncrRefCount(wordObjPtr->internalRep.listValue.ele[k]); + } + + Jim_DecrRefCount(interp, wordObjPtr); + + + j--; + argc += len - 1; + } + } + + if (retcode == JIM_OK && argc) { + + retcode = JimInvokeCommand(interp, argc, argv); + + if (Jim_CheckSignal(interp)) { + retcode = JIM_SIGNAL; + } + } + + + while (j-- > 0) { + Jim_DecrRefCount(interp, argv[j]); + } + + if (argv != sargv) { + Jim_Free(argv); + argv = sargv; + } + } + + + if (retcode == JIM_ERR) { + JimAddErrorToStack(interp, script); + } + + else if (retcode != JIM_RETURN || interp->returnCode != JIM_ERR) { + + interp->addStackTrace = 0; + } + + + interp->currentScriptObj = prevScriptObj; + + Jim_FreeIntRep(interp, scriptObjPtr); + scriptObjPtr->typePtr = &scriptObjType; + Jim_SetIntRepPtr(scriptObjPtr, script); + Jim_DecrRefCount(interp, scriptObjPtr); + + return retcode; +} + +static int JimSetProcArg(Jim_Interp *interp, Jim_Obj *argNameObj, Jim_Obj *argValObj) +{ + int retcode; + + const char *varname = Jim_String(argNameObj); + if (*varname == '&') { + + Jim_Obj *objPtr; + Jim_CallFrame *savedCallFrame = interp->framePtr; + + interp->framePtr = interp->framePtr->parent; + objPtr = Jim_GetVariable(interp, argValObj, JIM_ERRMSG); + interp->framePtr = savedCallFrame; + if (!objPtr) { + return JIM_ERR; + } + + + objPtr = Jim_NewStringObj(interp, varname + 1, -1); + Jim_IncrRefCount(objPtr); + retcode = Jim_SetVariableLink(interp, objPtr, argValObj, interp->framePtr->parent); + Jim_DecrRefCount(interp, objPtr); + } + else { + retcode = Jim_SetVariable(interp, argNameObj, argValObj); + } + return retcode; +} + +static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd) +{ + + Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0); + int i; + + for (i = 0; i < cmd->u.proc.argListLen; i++) { + Jim_AppendString(interp, argmsg, " ", 1); + + if (i == cmd->u.proc.argsPos) { + if (cmd->u.proc.arglist[i].defaultObjPtr) { + + Jim_AppendString(interp, argmsg, "?", 1); + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr); + Jim_AppendString(interp, argmsg, " ...?", -1); + } + else { + + Jim_AppendString(interp, argmsg, "?arg...?", -1); + } + } + else { + if (cmd->u.proc.arglist[i].defaultObjPtr) { + Jim_AppendString(interp, argmsg, "?", 1); + Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr); + Jim_AppendString(interp, argmsg, "?", 1); + } + else { + const char *arg = Jim_String(cmd->u.proc.arglist[i].nameObjPtr); + if (*arg == '&') { + arg++; + } + Jim_AppendString(interp, argmsg, arg, -1); + } + } + } + Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg); + Jim_FreeNewObj(interp, argmsg); +} + +#ifdef jim_ext_namespace +int Jim_EvalNamespace(Jim_Interp *interp, Jim_Obj *scriptObj, Jim_Obj *nsObj) +{ + Jim_CallFrame *callFramePtr; + int retcode; + + + callFramePtr = JimCreateCallFrame(interp, interp->framePtr, nsObj); + callFramePtr->argv = &interp->emptyObj; + callFramePtr->argc = 0; + callFramePtr->procArgsObjPtr = NULL; + callFramePtr->procBodyObjPtr = scriptObj; + callFramePtr->staticVars = NULL; + callFramePtr->fileNameObj = interp->emptyObj; + callFramePtr->line = 0; + Jim_IncrRefCount(scriptObj); + interp->framePtr = callFramePtr; + + + if (interp->framePtr->level == interp->maxCallFrameDepth) { + Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); + retcode = JIM_ERR; + } + else { + + retcode = Jim_EvalObj(interp, scriptObj); + } + + + interp->framePtr = interp->framePtr->parent; + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); + + return retcode; +} +#endif + +static int JimCallProcedure(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv) +{ + Jim_CallFrame *callFramePtr; + int i, d, retcode, optargs; + ScriptObj *script; + + + if (argc - 1 < cmd->u.proc.reqArity || + (cmd->u.proc.argsPos < 0 && argc - 1 > cmd->u.proc.reqArity + cmd->u.proc.optArity)) { + JimSetProcWrongArgs(interp, argv[0], cmd); + return JIM_ERR; + } + + if (Jim_Length(cmd->u.proc.bodyObjPtr) == 0) { + + return JIM_OK; + } + + + if (interp->framePtr->level == interp->maxCallFrameDepth) { + Jim_SetResultString(interp, "Too many nested calls. Infinite recursion?", -1); + return JIM_ERR; + } + + + callFramePtr = JimCreateCallFrame(interp, interp->framePtr, cmd->u.proc.nsObj); + callFramePtr->argv = argv; + callFramePtr->argc = argc; + callFramePtr->procArgsObjPtr = cmd->u.proc.argListObjPtr; + callFramePtr->procBodyObjPtr = cmd->u.proc.bodyObjPtr; + callFramePtr->staticVars = cmd->u.proc.staticVars; + + + script = JimGetScript(interp, interp->currentScriptObj); + callFramePtr->fileNameObj = script->fileNameObj; + callFramePtr->line = script->linenr; + + Jim_IncrRefCount(cmd->u.proc.argListObjPtr); + Jim_IncrRefCount(cmd->u.proc.bodyObjPtr); + interp->framePtr = callFramePtr; + + + optargs = (argc - 1 - cmd->u.proc.reqArity); + + + i = 1; + for (d = 0; d < cmd->u.proc.argListLen; d++) { + Jim_Obj *nameObjPtr = cmd->u.proc.arglist[d].nameObjPtr; + if (d == cmd->u.proc.argsPos) { + + Jim_Obj *listObjPtr; + int argsLen = 0; + if (cmd->u.proc.reqArity + cmd->u.proc.optArity < argc - 1) { + argsLen = argc - 1 - (cmd->u.proc.reqArity + cmd->u.proc.optArity); + } + listObjPtr = Jim_NewListObj(interp, &argv[i], argsLen); + + + if (cmd->u.proc.arglist[d].defaultObjPtr) { + nameObjPtr =cmd->u.proc.arglist[d].defaultObjPtr; + } + retcode = Jim_SetVariable(interp, nameObjPtr, listObjPtr); + if (retcode != JIM_OK) { + goto badargset; + } + + i += argsLen; + continue; + } + + + if (cmd->u.proc.arglist[d].defaultObjPtr == NULL || optargs-- > 0) { + retcode = JimSetProcArg(interp, nameObjPtr, argv[i++]); + } + else { + + retcode = Jim_SetVariable(interp, nameObjPtr, cmd->u.proc.arglist[d].defaultObjPtr); + } + if (retcode != JIM_OK) { + goto badargset; + } + } + + + retcode = Jim_EvalObj(interp, cmd->u.proc.bodyObjPtr); + +badargset: + + + interp->framePtr = interp->framePtr->parent; + JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE); + + if (interp->framePtr->tailcallObj) { + + if (interp->framePtr->tailcall++ == 0) { + + do { + Jim_Obj *tailcallObj = interp->framePtr->tailcallObj; + + interp->framePtr->tailcallObj = NULL; + + if (retcode == JIM_EVAL) { + retcode = Jim_EvalObjList(interp, tailcallObj); + if (retcode == JIM_RETURN) { + interp->returnLevel++; + } + } + Jim_DecrRefCount(interp, tailcallObj); + } while (interp->framePtr->tailcallObj); + + + if (interp->framePtr->tailcallCmd) { + JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd); + interp->framePtr->tailcallCmd = NULL; + } + } + interp->framePtr->tailcall--; + } + + + if (retcode == JIM_RETURN) { + if (--interp->returnLevel <= 0) { + retcode = interp->returnCode; + interp->returnCode = JIM_OK; + interp->returnLevel = 0; + } + } + else if (retcode == JIM_ERR) { + interp->addStackTrace++; + Jim_DecrRefCount(interp, interp->errorProc); + interp->errorProc = argv[0]; + Jim_IncrRefCount(interp->errorProc); + } + + return retcode; +} + +int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script) +{ + int retval; + Jim_Obj *scriptObjPtr; + + scriptObjPtr = Jim_NewStringObj(interp, script, -1); + Jim_IncrRefCount(scriptObjPtr); + + if (filename) { + Jim_Obj *prevScriptObj; + + JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), lineno); + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + retval = Jim_EvalObj(interp, scriptObjPtr); + + interp->currentScriptObj = prevScriptObj; + } + else { + retval = Jim_EvalObj(interp, scriptObjPtr); + } + Jim_DecrRefCount(interp, scriptObjPtr); + return retval; +} + +int Jim_Eval(Jim_Interp *interp, const char *script) +{ + return Jim_EvalObj(interp, Jim_NewStringObj(interp, script, -1)); +} + + +int Jim_EvalGlobal(Jim_Interp *interp, const char *script) +{ + int retval; + Jim_CallFrame *savedFramePtr = interp->framePtr; + + interp->framePtr = interp->topFramePtr; + retval = Jim_Eval(interp, script); + interp->framePtr = savedFramePtr; + + return retval; +} + +int Jim_EvalFileGlobal(Jim_Interp *interp, const char *filename) +{ + int retval; + Jim_CallFrame *savedFramePtr = interp->framePtr; + + interp->framePtr = interp->topFramePtr; + retval = Jim_EvalFile(interp, filename); + interp->framePtr = savedFramePtr; + + return retval; +} + +#include + +int Jim_EvalFile(Jim_Interp *interp, const char *filename) +{ + FILE *fp; + char *buf; + Jim_Obj *scriptObjPtr; + Jim_Obj *prevScriptObj; + struct stat sb; + int retcode; + int readlen; + + if (stat(filename, &sb) != 0 || (fp = fopen(filename, "rt")) == NULL) { + Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + if (sb.st_size == 0) { + fclose(fp); + return JIM_OK; + } + + buf = Jim_Alloc(sb.st_size + 1); + readlen = fread(buf, 1, sb.st_size, fp); + if (ferror(fp)) { + fclose(fp); + Jim_Free(buf); + Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno)); + return JIM_ERR; + } + fclose(fp); + buf[readlen] = 0; + + scriptObjPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen); + JimSetSourceInfo(interp, scriptObjPtr, Jim_NewStringObj(interp, filename, -1), 1); + Jim_IncrRefCount(scriptObjPtr); + + prevScriptObj = interp->currentScriptObj; + interp->currentScriptObj = scriptObjPtr; + + retcode = Jim_EvalObj(interp, scriptObjPtr); + + + if (retcode == JIM_RETURN) { + if (--interp->returnLevel <= 0) { + retcode = interp->returnCode; + interp->returnCode = JIM_OK; + interp->returnLevel = 0; + } + } + if (retcode == JIM_ERR) { + + interp->addStackTrace++; + } + + interp->currentScriptObj = prevScriptObj; + + Jim_DecrRefCount(interp, scriptObjPtr); + + return retcode; +} + +static void JimParseSubst(struct JimParserCtx *pc, int flags) +{ + pc->tstart = pc->p; + pc->tline = pc->linenr; + + if (pc->len == 0) { + pc->tend = pc->p; + pc->tt = JIM_TT_EOL; + pc->eof = 1; + return; + } + if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) { + JimParseCmd(pc); + return; + } + if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { + if (JimParseVar(pc) == JIM_OK) { + return; + } + + pc->tstart = pc->p; + flags |= JIM_SUBST_NOVAR; + } + while (pc->len) { + if (*pc->p == '$' && !(flags & JIM_SUBST_NOVAR)) { + break; + } + if (*pc->p == '[' && !(flags & JIM_SUBST_NOCMD)) { + break; + } + if (*pc->p == '\\' && pc->len > 1) { + pc->p++; + pc->len--; + } + pc->p++; + pc->len--; + } + pc->tend = pc->p - 1; + pc->tt = (flags & JIM_SUBST_NOESC) ? JIM_TT_STR : JIM_TT_ESC; +} + + +static int SetSubstFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr, int flags) +{ + int scriptTextLen; + const char *scriptText = Jim_GetString(objPtr, &scriptTextLen); + struct JimParserCtx parser; + struct ScriptObj *script = Jim_Alloc(sizeof(*script)); + ParseTokenList tokenlist; + + + ScriptTokenListInit(&tokenlist); + + JimParserInit(&parser, scriptText, scriptTextLen, 1); + while (1) { + JimParseSubst(&parser, flags); + if (parser.eof) { + + break; + } + ScriptAddToken(&tokenlist, parser.tstart, parser.tend - parser.tstart + 1, parser.tt, + parser.tline); + } + + + script->inUse = 1; + script->substFlags = flags; + script->fileNameObj = interp->emptyObj; + Jim_IncrRefCount(script->fileNameObj); + SubstObjAddTokens(interp, script, &tokenlist); + + + ScriptTokenListFree(&tokenlist); + +#ifdef DEBUG_SHOW_SUBST + { + int i; + + printf("==== Subst ====\n"); + for (i = 0; i < script->len; i++) { + printf("[%2d] %s '%s'\n", i, jim_tt_name(script->token[i].type), + Jim_String(script->token[i].objPtr)); + } + } +#endif + + + Jim_FreeIntRep(interp, objPtr); + Jim_SetIntRepPtr(objPtr, script); + objPtr->typePtr = &scriptObjType; + return JIM_OK; +} + +static ScriptObj *Jim_GetSubst(Jim_Interp *interp, Jim_Obj *objPtr, int flags) +{ + if (objPtr->typePtr != &scriptObjType || ((ScriptObj *)Jim_GetIntRepPtr(objPtr))->substFlags != flags) + SetSubstFromAny(interp, objPtr, flags); + return (ScriptObj *) Jim_GetIntRepPtr(objPtr); +} + +int Jim_SubstObj(Jim_Interp *interp, Jim_Obj *substObjPtr, Jim_Obj **resObjPtrPtr, int flags) +{ + ScriptObj *script = Jim_GetSubst(interp, substObjPtr, flags); + + Jim_IncrRefCount(substObjPtr); + script->inUse++; + + *resObjPtrPtr = JimInterpolateTokens(interp, script->token, script->len, flags); + + script->inUse--; + Jim_DecrRefCount(interp, substObjPtr); + if (*resObjPtrPtr == NULL) { + return JIM_ERR; + } + return JIM_OK; +} + +void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg) +{ + Jim_Obj *objPtr; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, argv, argc); + + if (*msg) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1)); + } + Jim_IncrRefCount(listObjPtr); + objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1); + Jim_DecrRefCount(interp, listObjPtr); + + Jim_IncrRefCount(objPtr); + Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr); + Jim_DecrRefCount(interp, objPtr); +} + +typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, + Jim_HashEntry *he, int type); + +#define JimTrivialMatch(pattern) (strpbrk((pattern), "*[?\\") == NULL) + +static Jim_Obj *JimHashtablePatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, + JimHashtableIteratorCallbackType *callback, int type) +{ + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + + if (patternObjPtr && JimTrivialMatch(Jim_String(patternObjPtr))) { + he = Jim_FindHashEntry(ht, Jim_String(patternObjPtr)); + if (he) { + callback(interp, listObjPtr, he, type); + } + } + else { + Jim_HashTableIterator htiter; + JimInitHashTableIterator(ht, &htiter); + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { + if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), he->key, 0)) { + callback(interp, listObjPtr, he, type); + } + } + } + return listObjPtr; +} + + +#define JIM_CMDLIST_COMMANDS 0 +#define JIM_CMDLIST_PROCS 1 +#define JIM_CMDLIST_CHANNELS 2 + +static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, + Jim_HashEntry *he, int type) +{ + Jim_Cmd *cmdPtr = Jim_GetHashEntryVal(he); + Jim_Obj *objPtr; + + if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) { + + return; + } + + objPtr = Jim_NewStringObj(interp, he->key, -1); + Jim_IncrRefCount(objPtr); + + if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, objPtr)) { + Jim_ListAppendElement(interp, listObjPtr, objPtr); + } + Jim_DecrRefCount(interp, objPtr); +} + + +static Jim_Obj *JimCommandsList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int type) +{ + return JimHashtablePatternMatch(interp, &interp->commands, patternObjPtr, JimCommandMatch, type); +} + + +#define JIM_VARLIST_GLOBALS 0 +#define JIM_VARLIST_LOCALS 1 +#define JIM_VARLIST_VARS 2 + +#define JIM_VARLIST_VALUES 0x1000 + +static void JimVariablesMatch(Jim_Interp *interp, Jim_Obj *listObjPtr, + Jim_HashEntry *he, int type) +{ + Jim_Var *varPtr = Jim_GetHashEntryVal(he); + + if (type != JIM_VARLIST_LOCALS || varPtr->linkFramePtr == NULL) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, he->key, -1)); + if (type & JIM_VARLIST_VALUES) { + Jim_ListAppendElement(interp, listObjPtr, varPtr->objPtr); + } + } +} + + +static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode) +{ + if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) { + return interp->emptyObj; + } + else { + Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr; + return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch, mode); + } +} + +static int JimInfoLevel(Jim_Interp *interp, Jim_Obj *levelObjPtr, + Jim_Obj **objPtrPtr, int info_level_cmd) +{ + Jim_CallFrame *targetCallFrame; + + targetCallFrame = JimGetCallFrameByInteger(interp, levelObjPtr); + if (targetCallFrame == NULL) { + return JIM_ERR; + } + + if (targetCallFrame == interp->topFramePtr) { + Jim_SetResultFormatted(interp, "bad level \"%#s\"", levelObjPtr); + return JIM_ERR; + } + if (info_level_cmd) { + *objPtrPtr = Jim_NewListObj(interp, targetCallFrame->argv, targetCallFrame->argc); + } + else { + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, listObj, targetCallFrame->argv[0]); + Jim_ListAppendElement(interp, listObj, targetCallFrame->fileNameObj); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, targetCallFrame->line)); + *objPtrPtr = listObj; + } + return JIM_OK; +} + + + +static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?-nonewline? string"); + return JIM_ERR; + } + if (argc == 3) { + if (!Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) { + Jim_SetResultString(interp, "The second argument must " "be -nonewline", -1); + return JIM_ERR; + } + else { + fputs(Jim_String(argv[2]), stdout); + } + } + else { + puts(Jim_String(argv[1])); + } + return JIM_OK; +} + + +static int JimAddMulHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) +{ + jim_wide wideValue, res; + double doubleValue, doubleRes; + int i; + + res = (op == JIM_EXPROP_ADD) ? 0 : 1; + + for (i = 1; i < argc; i++) { + if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) + goto trydouble; + if (op == JIM_EXPROP_ADD) + res += wideValue; + else + res *= wideValue; + } + Jim_SetResultInt(interp, res); + return JIM_OK; + trydouble: + doubleRes = (double)res; + for (; i < argc; i++) { + if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) + return JIM_ERR; + if (op == JIM_EXPROP_ADD) + doubleRes += doubleValue; + else + doubleRes *= doubleValue; + } + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; +} + + +static int JimSubDivHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int op) +{ + jim_wide wideValue, res = 0; + double doubleValue, doubleRes = 0; + int i = 2; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "number ?number ... number?"); + return JIM_ERR; + } + else if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) { + if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) { + return JIM_ERR; + } + else { + if (op == JIM_EXPROP_SUB) + doubleRes = -doubleValue; + else + doubleRes = 1.0 / doubleValue; + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; + } + } + if (op == JIM_EXPROP_SUB) { + res = -wideValue; + Jim_SetResultInt(interp, res); + } + else { + doubleRes = 1.0 / wideValue; + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + } + return JIM_OK; + } + else { + if (Jim_GetWide(interp, argv[1], &res) != JIM_OK) { + if (Jim_GetDouble(interp, argv[1], &doubleRes) + != JIM_OK) { + return JIM_ERR; + } + else { + goto trydouble; + } + } + } + for (i = 2; i < argc; i++) { + if (Jim_GetWide(interp, argv[i], &wideValue) != JIM_OK) { + doubleRes = (double)res; + goto trydouble; + } + if (op == JIM_EXPROP_SUB) + res -= wideValue; + else + res /= wideValue; + } + Jim_SetResultInt(interp, res); + return JIM_OK; + trydouble: + for (; i < argc; i++) { + if (Jim_GetDouble(interp, argv[i], &doubleValue) != JIM_OK) + return JIM_ERR; + if (op == JIM_EXPROP_SUB) + doubleRes -= doubleValue; + else + doubleRes /= doubleValue; + } + Jim_SetResult(interp, Jim_NewDoubleObj(interp, doubleRes)); + return JIM_OK; +} + + + +static int Jim_AddCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_ADD); +} + + +static int Jim_MulCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimAddMulHelper(interp, argc, argv, JIM_EXPROP_MUL); +} + + +static int Jim_SubCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_SUB); +} + + +static int Jim_DivCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimSubDivHelper(interp, argc, argv, JIM_EXPROP_DIV); +} + + +static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?newValue?"); + return JIM_ERR; + } + if (argc == 2) { + Jim_Obj *objPtr; + + objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + if (!objPtr) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + return JIM_OK; +} + +static int Jim_UnsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i = 1; + int complain = 1; + + while (i < argc) { + if (Jim_CompareStringImmediate(interp, argv[i], "--")) { + i++; + break; + } + if (Jim_CompareStringImmediate(interp, argv[i], "-nocomplain")) { + complain = 0; + i++; + continue; + } + break; + } + + while (i < argc) { + if (Jim_UnsetVariable(interp, argv[i], complain ? JIM_ERRMSG : JIM_NONE) != JIM_OK + && complain) { + return JIM_ERR; + } + i++; + } + return JIM_OK; +} + + +static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "condition body"); + return JIM_ERR; + } + + + while (1) { + int boolean, retval; + + if ((retval = Jim_GetBoolFromExpr(interp, argv[1], &boolean)) != JIM_OK) + return retval; + if (!boolean) + break; + + if ((retval = Jim_EvalObj(interp, argv[2])) != JIM_OK) { + switch (retval) { + case JIM_BREAK: + goto out; + break; + case JIM_CONTINUE: + continue; + break; + default: + return retval; + } + } + } + out: + Jim_SetEmptyResult(interp); + return JIM_OK; +} + + +static int Jim_ForCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + int boolean = 1; + Jim_Obj *varNamePtr = NULL; + Jim_Obj *stopVarNamePtr = NULL; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "start test next body"); + return JIM_ERR; + } + + + if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) { + return retval; + } + + retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); + + +#ifdef JIM_OPTIMIZATION + if (retval == JIM_OK && boolean) { + ScriptObj *incrScript; + ExprByteCode *expr; + jim_wide stop, currentVal; + Jim_Obj *objPtr; + int cmpOffset; + + + expr = JimGetExpression(interp, argv[2]); + incrScript = JimGetScript(interp, argv[3]); + + + if (incrScript == NULL || incrScript->len != 3 || !expr || expr->len != 3) { + goto evalstart; + } + + if (incrScript->token[1].type != JIM_TT_ESC || + expr->token[0].type != JIM_TT_VAR || + (expr->token[1].type != JIM_TT_EXPR_INT && expr->token[1].type != JIM_TT_VAR)) { + goto evalstart; + } + + if (expr->token[2].type == JIM_EXPROP_LT) { + cmpOffset = 0; + } + else if (expr->token[2].type == JIM_EXPROP_LTE) { + cmpOffset = 1; + } + else { + goto evalstart; + } + + + if (!Jim_CompareStringImmediate(interp, incrScript->token[1].objPtr, "incr")) { + goto evalstart; + } + + + if (!Jim_StringEqObj(incrScript->token[2].objPtr, expr->token[0].objPtr)) { + goto evalstart; + } + + + if (expr->token[1].type == JIM_TT_EXPR_INT) { + if (Jim_GetWide(interp, expr->token[1].objPtr, &stop) == JIM_ERR) { + goto evalstart; + } + } + else { + stopVarNamePtr = expr->token[1].objPtr; + Jim_IncrRefCount(stopVarNamePtr); + + stop = 0; + } + + + varNamePtr = expr->token[0].objPtr; + Jim_IncrRefCount(varNamePtr); + + objPtr = Jim_GetVariable(interp, varNamePtr, JIM_NONE); + if (objPtr == NULL || Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK) { + goto testcond; + } + + + while (retval == JIM_OK) { + + + + + if (stopVarNamePtr) { + objPtr = Jim_GetVariable(interp, stopVarNamePtr, JIM_NONE); + if (objPtr == NULL || Jim_GetWide(interp, objPtr, &stop) != JIM_OK) { + goto testcond; + } + } + + if (currentVal >= stop + cmpOffset) { + break; + } + + + retval = Jim_EvalObj(interp, argv[4]); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + retval = JIM_OK; + + objPtr = Jim_GetVariable(interp, varNamePtr, JIM_ERRMSG); + + + if (objPtr == NULL) { + retval = JIM_ERR; + goto out; + } + if (!Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + currentVal = ++JimWideValue(objPtr); + Jim_InvalidateStringRep(objPtr); + } + else { + if (Jim_GetWide(interp, objPtr, ¤tVal) != JIM_OK || + Jim_SetVariable(interp, varNamePtr, Jim_NewIntObj(interp, + ++currentVal)) != JIM_OK) { + goto evalnext; + } + } + } + } + goto out; + } + evalstart: +#endif + + while (boolean && (retval == JIM_OK || retval == JIM_CONTINUE)) { + + retval = Jim_EvalObj(interp, argv[4]); + + if (retval == JIM_OK || retval == JIM_CONTINUE) { + + evalnext: + retval = Jim_EvalObj(interp, argv[3]); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + + testcond: + retval = Jim_GetBoolFromExpr(interp, argv[2], &boolean); + } + } + } + out: + if (stopVarNamePtr) { + Jim_DecrRefCount(interp, stopVarNamePtr); + } + if (varNamePtr) { + Jim_DecrRefCount(interp, varNamePtr); + } + + if (retval == JIM_CONTINUE || retval == JIM_BREAK || retval == JIM_OK) { + Jim_SetEmptyResult(interp); + return JIM_OK; + } + + return retval; +} + + +static int Jim_LoopCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + jim_wide i; + jim_wide limit; + jim_wide incr = 1; + Jim_Obj *bodyObjPtr; + + if (argc != 5 && argc != 6) { + Jim_WrongNumArgs(interp, 1, argv, "var first limit ?incr? body"); + return JIM_ERR; + } + + if (Jim_GetWide(interp, argv[2], &i) != JIM_OK || + Jim_GetWide(interp, argv[3], &limit) != JIM_OK || + (argc == 6 && Jim_GetWide(interp, argv[4], &incr) != JIM_OK)) { + return JIM_ERR; + } + bodyObjPtr = (argc == 5) ? argv[4] : argv[5]; + + retval = Jim_SetVariable(interp, argv[1], argv[2]); + + while (((i < limit && incr > 0) || (i > limit && incr < 0)) && retval == JIM_OK) { + retval = Jim_EvalObj(interp, bodyObjPtr); + if (retval == JIM_OK || retval == JIM_CONTINUE) { + Jim_Obj *objPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + + retval = JIM_OK; + + + i += incr; + + if (objPtr && !Jim_IsShared(objPtr) && objPtr->typePtr == &intObjType) { + if (argv[1]->typePtr != &variableObjType) { + if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { + return JIM_ERR; + } + } + JimWideValue(objPtr) = i; + Jim_InvalidateStringRep(objPtr); + + if (argv[1]->typePtr != &variableObjType) { + if (Jim_SetVariable(interp, argv[1], objPtr) != JIM_OK) { + retval = JIM_ERR; + break; + } + } + } + else { + objPtr = Jim_NewIntObj(interp, i); + retval = Jim_SetVariable(interp, argv[1], objPtr); + if (retval != JIM_OK) { + Jim_FreeNewObj(interp, objPtr); + } + } + } + } + + if (retval == JIM_OK || retval == JIM_CONTINUE || retval == JIM_BREAK) { + Jim_SetEmptyResult(interp); + return JIM_OK; + } + return retval; +} + +typedef struct { + Jim_Obj *objPtr; + int idx; +} Jim_ListIter; + +static void JimListIterInit(Jim_ListIter *iter, Jim_Obj *objPtr) +{ + iter->objPtr = objPtr; + iter->idx = 0; +} + +static Jim_Obj *JimListIterNext(Jim_Interp *interp, Jim_ListIter *iter) +{ + if (iter->idx >= Jim_ListLength(interp, iter->objPtr)) { + return NULL; + } + return iter->objPtr->internalRep.listValue.ele[iter->idx++]; +} + +static int JimListIterDone(Jim_Interp *interp, Jim_ListIter *iter) +{ + return iter->idx >= Jim_ListLength(interp, iter->objPtr); +} + + +static int JimForeachMapHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int doMap) +{ + int result = JIM_OK; + int i, numargs; + Jim_ListIter twoiters[2]; + Jim_ListIter *iters; + Jim_Obj *script; + Jim_Obj *resultObj; + + if (argc < 4 || argc % 2 != 0) { + Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script"); + return JIM_ERR; + } + script = argv[argc - 1]; + numargs = (argc - 1 - 1); + + if (numargs == 2) { + iters = twoiters; + } + else { + iters = Jim_Alloc(numargs * sizeof(*iters)); + } + for (i = 0; i < numargs; i++) { + JimListIterInit(&iters[i], argv[i + 1]); + if (i % 2 == 0 && JimListIterDone(interp, &iters[i])) { + result = JIM_ERR; + } + } + if (result != JIM_OK) { + Jim_SetResultString(interp, "foreach varlist is empty", -1); + return result; + } + + if (doMap) { + resultObj = Jim_NewListObj(interp, NULL, 0); + } + else { + resultObj = interp->emptyObj; + } + Jim_IncrRefCount(resultObj); + + while (1) { + + for (i = 0; i < numargs; i += 2) { + if (!JimListIterDone(interp, &iters[i + 1])) { + break; + } + } + if (i == numargs) { + + break; + } + + + for (i = 0; i < numargs; i += 2) { + Jim_Obj *varName; + + + JimListIterInit(&iters[i], argv[i + 1]); + while ((varName = JimListIterNext(interp, &iters[i])) != NULL) { + Jim_Obj *valObj = JimListIterNext(interp, &iters[i + 1]); + if (!valObj) { + + valObj = interp->emptyObj; + } + + Jim_IncrRefCount(valObj); + result = Jim_SetVariable(interp, varName, valObj); + Jim_DecrRefCount(interp, valObj); + if (result != JIM_OK) { + goto err; + } + } + } + switch (result = Jim_EvalObj(interp, script)) { + case JIM_OK: + if (doMap) { + Jim_ListAppendElement(interp, resultObj, interp->result); + } + break; + case JIM_CONTINUE: + break; + case JIM_BREAK: + goto out; + default: + goto err; + } + } + out: + result = JIM_OK; + Jim_SetResult(interp, resultObj); + err: + Jim_DecrRefCount(interp, resultObj); + if (numargs > 2) { + Jim_Free(iters); + } + return result; +} + + +static int Jim_ForeachCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimForeachMapHelper(interp, argc, argv, 0); +} + + +static int Jim_LmapCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return JimForeachMapHelper(interp, argc, argv, 1); +} + + +static int Jim_LassignCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int result = JIM_ERR; + int i; + Jim_ListIter iter; + Jim_Obj *resultObj; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varList list ?varName ...?"); + return JIM_ERR; + } + + JimListIterInit(&iter, argv[1]); + + for (i = 2; i < argc; i++) { + Jim_Obj *valObj = JimListIterNext(interp, &iter); + result = Jim_SetVariable(interp, argv[i], valObj ? valObj : interp->emptyObj); + if (result != JIM_OK) { + return result; + } + } + + resultObj = Jim_NewListObj(interp, NULL, 0); + while (!JimListIterDone(interp, &iter)) { + Jim_ListAppendElement(interp, resultObj, JimListIterNext(interp, &iter)); + } + + Jim_SetResult(interp, resultObj); + + return JIM_OK; +} + + +static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int boolean, retval, current = 1, falsebody = 0; + + if (argc >= 3) { + while (1) { + + if (current >= argc) + goto err; + if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean)) + != JIM_OK) + return retval; + + if (current >= argc) + goto err; + if (Jim_CompareStringImmediate(interp, argv[current], "then")) + current++; + + if (current >= argc) + goto err; + if (boolean) + return Jim_EvalObj(interp, argv[current]); + + if (++current >= argc) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + return JIM_OK; + } + falsebody = current++; + if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) { + + if (current != argc - 1) + goto err; + return Jim_EvalObj(interp, argv[current]); + } + else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif")) + continue; + + else if (falsebody != argc - 1) + goto err; + return Jim_EvalObj(interp, argv[falsebody]); + } + return JIM_OK; + } + err: + Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody"); + return JIM_ERR; +} + + + +int Jim_CommandMatchObj(Jim_Interp *interp, Jim_Obj *commandObj, Jim_Obj *patternObj, + Jim_Obj *stringObj, int nocase) +{ + Jim_Obj *parms[4]; + int argc = 0; + long eq; + int rc; + + parms[argc++] = commandObj; + if (nocase) { + parms[argc++] = Jim_NewStringObj(interp, "-nocase", -1); + } + parms[argc++] = patternObj; + parms[argc++] = stringObj; + + rc = Jim_EvalObjVector(interp, argc, parms); + + if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) { + eq = -rc; + } + + return eq; +} + +enum +{ SWITCH_EXACT, SWITCH_GLOB, SWITCH_RE, SWITCH_CMD }; + + +static int Jim_SwitchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int matchOpt = SWITCH_EXACT, opt = 1, patCount, i; + Jim_Obj *command = 0, *const *caseList = 0, *strObj; + Jim_Obj *script = 0; + + if (argc < 3) { + wrongnumargs: + Jim_WrongNumArgs(interp, 1, argv, "?options? string " + "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}"); + return JIM_ERR; + } + for (opt = 1; opt < argc; ++opt) { + const char *option = Jim_String(argv[opt]); + + if (*option != '-') + break; + else if (strncmp(option, "--", 2) == 0) { + ++opt; + break; + } + else if (strncmp(option, "-exact", 2) == 0) + matchOpt = SWITCH_EXACT; + else if (strncmp(option, "-glob", 2) == 0) + matchOpt = SWITCH_GLOB; + else if (strncmp(option, "-regexp", 2) == 0) + matchOpt = SWITCH_RE; + else if (strncmp(option, "-command", 2) == 0) { + matchOpt = SWITCH_CMD; + if ((argc - opt) < 2) + goto wrongnumargs; + command = argv[++opt]; + } + else { + Jim_SetResultFormatted(interp, + "bad option \"%#s\": must be -exact, -glob, -regexp, -command procname or --", + argv[opt]); + return JIM_ERR; + } + if ((argc - opt) < 2) + goto wrongnumargs; + } + strObj = argv[opt++]; + patCount = argc - opt; + if (patCount == 1) { + Jim_Obj **vector; + + JimListGetElements(interp, argv[opt], &patCount, &vector); + caseList = vector; + } + else + caseList = &argv[opt]; + if (patCount == 0 || patCount % 2 != 0) + goto wrongnumargs; + for (i = 0; script == 0 && i < patCount; i += 2) { + Jim_Obj *patObj = caseList[i]; + + if (!Jim_CompareStringImmediate(interp, patObj, "default") + || i < (patCount - 2)) { + switch (matchOpt) { + case SWITCH_EXACT: + if (Jim_StringEqObj(strObj, patObj)) + script = caseList[i + 1]; + break; + case SWITCH_GLOB: + if (Jim_StringMatchObj(interp, patObj, strObj, 0)) + script = caseList[i + 1]; + break; + case SWITCH_RE: + command = Jim_NewStringObj(interp, "regexp", -1); + + case SWITCH_CMD:{ + int rc = Jim_CommandMatchObj(interp, command, patObj, strObj, 0); + + if (argc - opt == 1) { + Jim_Obj **vector; + + JimListGetElements(interp, argv[opt], &patCount, &vector); + caseList = vector; + } + + if (rc < 0) { + return -rc; + } + if (rc) + script = caseList[i + 1]; + break; + } + } + } + else { + script = caseList[i + 1]; + } + } + for (; i < patCount && Jim_CompareStringImmediate(interp, script, "-"); i += 2) + script = caseList[i + 1]; + if (script && Jim_CompareStringImmediate(interp, script, "-")) { + Jim_SetResultFormatted(interp, "no body specified for pattern \"%#s\"", caseList[i - 2]); + return JIM_ERR; + } + Jim_SetEmptyResult(interp); + if (script) { + return Jim_EvalObj(interp, script); + } + return JIM_OK; +} + + +static int Jim_ListCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + + listObjPtr = Jim_NewListObj(interp, argv + 1, argc - 1); + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} + + +static int Jim_LindexCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr, *listObjPtr; + int i; + int idx; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?"); + return JIM_ERR; + } + objPtr = argv[1]; + Jim_IncrRefCount(objPtr); + for (i = 2; i < argc; i++) { + listObjPtr = objPtr; + if (Jim_GetIndex(interp, argv[i], &idx) != JIM_OK) { + Jim_DecrRefCount(interp, listObjPtr); + return JIM_ERR; + } + if (Jim_ListIndex(interp, listObjPtr, idx, &objPtr, JIM_NONE) != JIM_OK) { + Jim_DecrRefCount(interp, listObjPtr); + Jim_SetEmptyResult(interp); + return JIM_OK; + } + Jim_IncrRefCount(objPtr); + Jim_DecrRefCount(interp, listObjPtr); + } + Jim_SetResult(interp, objPtr); + Jim_DecrRefCount(interp, objPtr); + return JIM_OK; +} + + +static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "list"); + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_ListLength(interp, argv[1])); + return JIM_OK; +} + + +static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static const char * const options[] = { + "-bool", "-not", "-nocase", "-exact", "-glob", "-regexp", "-all", "-inline", "-command", + NULL + }; + enum + { OPT_BOOL, OPT_NOT, OPT_NOCASE, OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_ALL, OPT_INLINE, + OPT_COMMAND }; + int i; + int opt_bool = 0; + int opt_not = 0; + int opt_nocase = 0; + int opt_all = 0; + int opt_inline = 0; + int opt_match = OPT_EXACT; + int listlen; + int rc = JIM_OK; + Jim_Obj *listObjPtr = NULL; + Jim_Obj *commandObj = NULL; + + if (argc < 3) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? list value"); + return JIM_ERR; + } + + for (i = 1; i < argc - 2; i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_BOOL: + opt_bool = 1; + opt_inline = 0; + break; + case OPT_NOT: + opt_not = 1; + break; + case OPT_NOCASE: + opt_nocase = 1; + break; + case OPT_INLINE: + opt_inline = 1; + opt_bool = 0; + break; + case OPT_ALL: + opt_all = 1; + break; + case OPT_COMMAND: + if (i >= argc - 2) { + goto wrongargs; + } + commandObj = argv[++i]; + + case OPT_EXACT: + case OPT_GLOB: + case OPT_REGEXP: + opt_match = option; + break; + } + } + + argv += i; + + if (opt_all) { + listObjPtr = Jim_NewListObj(interp, NULL, 0); + } + if (opt_match == OPT_REGEXP) { + commandObj = Jim_NewStringObj(interp, "regexp", -1); + } + if (commandObj) { + Jim_IncrRefCount(commandObj); + } + + listlen = Jim_ListLength(interp, argv[0]); + for (i = 0; i < listlen; i++) { + int eq = 0; + Jim_Obj *objPtr = Jim_ListGetIndex(interp, argv[0], i); + + switch (opt_match) { + case OPT_EXACT: + eq = Jim_StringCompareObj(interp, argv[1], objPtr, opt_nocase) == 0; + break; + + case OPT_GLOB: + eq = Jim_StringMatchObj(interp, argv[1], objPtr, opt_nocase); + break; + + case OPT_REGEXP: + case OPT_COMMAND: + eq = Jim_CommandMatchObj(interp, commandObj, argv[1], objPtr, opt_nocase); + if (eq < 0) { + if (listObjPtr) { + Jim_FreeNewObj(interp, listObjPtr); + } + rc = JIM_ERR; + goto done; + } + break; + } + + + if (!eq && opt_bool && opt_not && !opt_all) { + continue; + } + + if ((!opt_bool && eq == !opt_not) || (opt_bool && (eq || opt_all))) { + + Jim_Obj *resultObj; + + if (opt_bool) { + resultObj = Jim_NewIntObj(interp, eq ^ opt_not); + } + else if (!opt_inline) { + resultObj = Jim_NewIntObj(interp, i); + } + else { + resultObj = objPtr; + } + + if (opt_all) { + Jim_ListAppendElement(interp, listObjPtr, resultObj); + } + else { + Jim_SetResult(interp, resultObj); + goto done; + } + } + } + + if (opt_all) { + Jim_SetResult(interp, listObjPtr); + } + else { + + if (opt_bool) { + Jim_SetResultBool(interp, opt_not); + } + else if (!opt_inline) { + Jim_SetResultInt(interp, -1); + } + } + + done: + if (commandObj) { + Jim_DecrRefCount(interp, commandObj); + } + return rc; +} + + +static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + int shared, i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?"); + return JIM_ERR; + } + listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!listObjPtr) { + + listObjPtr = Jim_NewListObj(interp, NULL, 0); + if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { + Jim_FreeNewObj(interp, listObjPtr); + return JIM_ERR; + } + } + shared = Jim_IsShared(listObjPtr); + if (shared) + listObjPtr = Jim_DuplicateObj(interp, listObjPtr); + for (i = 2; i < argc; i++) + Jim_ListAppendElement(interp, listObjPtr, argv[i]); + if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) { + if (shared) + Jim_FreeNewObj(interp, listObjPtr); + return JIM_ERR; + } + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} + + +static int Jim_LinsertCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int idx, len; + Jim_Obj *listPtr; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "list index ?element ...?"); + return JIM_ERR; + } + listPtr = argv[1]; + if (Jim_IsShared(listPtr)) + listPtr = Jim_DuplicateObj(interp, listPtr); + if (Jim_GetIndex(interp, argv[2], &idx) != JIM_OK) + goto err; + len = Jim_ListLength(interp, listPtr); + if (idx >= len) + idx = len; + else if (idx < 0) + idx = len + idx + 1; + Jim_ListInsertElements(interp, listPtr, idx, argc - 3, &argv[3]); + Jim_SetResult(interp, listPtr); + return JIM_OK; + err: + if (listPtr != argv[1]) { + Jim_FreeNewObj(interp, listPtr); + } + return JIM_ERR; +} + + +static int Jim_LreplaceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int first, last, len, rangeLen; + Jim_Obj *listObj; + Jim_Obj *newListObj; + + if (argc < 4) { + Jim_WrongNumArgs(interp, 1, argv, "list first last ?element ...?"); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK || + Jim_GetIndex(interp, argv[3], &last) != JIM_OK) { + return JIM_ERR; + } + + listObj = argv[1]; + len = Jim_ListLength(interp, listObj); + + first = JimRelToAbsIndex(len, first); + last = JimRelToAbsIndex(len, last); + JimRelToAbsRange(len, &first, &last, &rangeLen); + + + + if (first < len) { + + } + else if (len == 0) { + + first = 0; + } + else { + Jim_SetResultString(interp, "list doesn't contain element ", -1); + Jim_AppendObj(interp, Jim_GetResult(interp), argv[2]); + return JIM_ERR; + } + + + newListObj = Jim_NewListObj(interp, listObj->internalRep.listValue.ele, first); + + + ListInsertElements(newListObj, -1, argc - 4, argv + 4); + + + ListInsertElements(newListObj, -1, len - first - rangeLen, listObj->internalRep.listValue.ele + first + rangeLen); + + Jim_SetResult(interp, newListObj); + return JIM_OK; +} + + +static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "listVar ?index...? newVal"); + return JIM_ERR; + } + else if (argc == 3) { + + if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + return JIM_OK; + } + return Jim_ListSetIndex(interp, argv[1], argv + 2, argc - 3, argv[argc - 1]); +} + + +static int Jim_LsortCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const argv[]) +{ + static const char * const options[] = { + "-ascii", "-nocase", "-increasing", "-decreasing", "-command", "-integer", "-real", "-index", "-unique", NULL + }; + enum + { OPT_ASCII, OPT_NOCASE, OPT_INCREASING, OPT_DECREASING, OPT_COMMAND, OPT_INTEGER, OPT_REAL, OPT_INDEX, OPT_UNIQUE }; + Jim_Obj *resObj; + int i; + int retCode; + + struct lsort_info info; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "?options? list"); + return JIM_ERR; + } + + info.type = JIM_LSORT_ASCII; + info.order = 1; + info.indexed = 0; + info.unique = 0; + info.command = NULL; + info.interp = interp; + + for (i = 1; i < (argc - 1); i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, JIM_ENUM_ABBREV | JIM_ERRMSG) + != JIM_OK) + return JIM_ERR; + switch (option) { + case OPT_ASCII: + info.type = JIM_LSORT_ASCII; + break; + case OPT_NOCASE: + info.type = JIM_LSORT_NOCASE; + break; + case OPT_INTEGER: + info.type = JIM_LSORT_INTEGER; + break; + case OPT_REAL: + info.type = JIM_LSORT_REAL; + break; + case OPT_INCREASING: + info.order = 1; + break; + case OPT_DECREASING: + info.order = -1; + break; + case OPT_UNIQUE: + info.unique = 1; + break; + case OPT_COMMAND: + if (i >= (argc - 2)) { + Jim_SetResultString(interp, "\"-command\" option must be followed by comparison command", -1); + return JIM_ERR; + } + info.type = JIM_LSORT_COMMAND; + info.command = argv[i + 1]; + i++; + break; + case OPT_INDEX: + if (i >= (argc - 2)) { + Jim_SetResultString(interp, "\"-index\" option must be followed by list index", -1); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[i + 1], &info.index) != JIM_OK) { + return JIM_ERR; + } + info.indexed = 1; + i++; + break; + } + } + resObj = Jim_DuplicateObj(interp, argv[argc - 1]); + retCode = ListSortElements(interp, resObj, &info); + if (retCode == JIM_OK) { + Jim_SetResult(interp, resObj); + } + else { + Jim_FreeNewObj(interp, resObj); + } + return retCode; +} + + +static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *stringObjPtr; + int i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?value ...?"); + return JIM_ERR; + } + if (argc == 2) { + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG); + if (!stringObjPtr) + return JIM_ERR; + } + else { + int freeobj = 0; + stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED); + if (!stringObjPtr) { + + stringObjPtr = Jim_NewEmptyStringObj(interp); + freeobj = 1; + } + else if (Jim_IsShared(stringObjPtr)) { + freeobj = 1; + stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr); + } + for (i = 2; i < argc; i++) { + Jim_AppendObj(interp, stringObjPtr, argv[i]); + } + if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) { + if (freeobj) { + Jim_FreeNewObj(interp, stringObjPtr); + } + return JIM_ERR; + } + } + Jim_SetResult(interp, stringObjPtr); + return JIM_OK; +} + + +static int Jim_DebugCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ +#if !defined(JIM_DEBUG_COMMAND) + Jim_SetResultString(interp, "unsupported", -1); + return JIM_ERR; +#endif +} + + +static int Jim_EvalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int rc; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "arg ?arg ...?"); + return JIM_ERR; + } + + if (argc == 2) { + rc = Jim_EvalObj(interp, argv[1]); + } + else { + rc = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + } + + if (rc == JIM_ERR) { + + interp->addStackTrace++; + } + return rc; +} + + +static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc >= 2) { + int retcode; + Jim_CallFrame *savedCallFrame, *targetCallFrame; + int savedTailcall; + const char *str; + + + savedCallFrame = interp->framePtr; + + + str = Jim_String(argv[1]); + if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') { + targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); + argc--; + argv++; + } + else { + targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); + } + if (targetCallFrame == NULL) { + return JIM_ERR; + } + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?"); + return JIM_ERR; + } + + interp->framePtr = targetCallFrame; + + savedTailcall = interp->framePtr->tailcall; + interp->framePtr->tailcall = 0; + if (argc == 2) { + retcode = Jim_EvalObj(interp, argv[1]); + } + else { + retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + } + interp->framePtr->tailcall = savedTailcall; + interp->framePtr = savedCallFrame; + return retcode; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?"); + return JIM_ERR; + } +} + + +static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *exprResultPtr; + int retcode; + + if (argc == 2) { + retcode = Jim_EvalExpression(interp, argv[1], &exprResultPtr); + } + else if (argc > 2) { + Jim_Obj *objPtr; + + objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1); + Jim_IncrRefCount(objPtr); + retcode = Jim_EvalExpression(interp, objPtr, &exprResultPtr); + Jim_DecrRefCount(interp, objPtr); + } + else { + Jim_WrongNumArgs(interp, 1, argv, "expression ?...?"); + return JIM_ERR; + } + if (retcode != JIM_OK) + return retcode; + Jim_SetResult(interp, exprResultPtr); + Jim_DecrRefCount(interp, exprResultPtr); + return JIM_OK; +} + + +static int Jim_BreakCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + return JIM_BREAK; +} + + +static int Jim_ContinueCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + return JIM_CONTINUE; +} + + +static int Jim_ReturnCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + Jim_Obj *stackTraceObj = NULL; + Jim_Obj *errorCodeObj = NULL; + int returnCode = JIM_OK; + long level = 1; + + for (i = 1; i < argc - 1; i += 2) { + if (Jim_CompareStringImmediate(interp, argv[i], "-code")) { + if (Jim_GetReturnCode(interp, argv[i + 1], &returnCode) == JIM_ERR) { + return JIM_ERR; + } + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-errorinfo")) { + stackTraceObj = argv[i + 1]; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-errorcode")) { + errorCodeObj = argv[i + 1]; + } + else if (Jim_CompareStringImmediate(interp, argv[i], "-level")) { + if (Jim_GetLong(interp, argv[i + 1], &level) != JIM_OK || level < 0) { + Jim_SetResultFormatted(interp, "bad level \"%#s\"", argv[i + 1]); + return JIM_ERR; + } + } + else { + break; + } + } + + if (i != argc - 1 && i != argc) { + Jim_WrongNumArgs(interp, 1, argv, + "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?"); + } + + + if (stackTraceObj && returnCode == JIM_ERR) { + JimSetStackTrace(interp, stackTraceObj); + } + + if (errorCodeObj && returnCode == JIM_ERR) { + Jim_SetGlobalVariableStr(interp, "errorCode", errorCodeObj); + } + interp->returnCode = returnCode; + interp->returnLevel = level; + + if (i == argc - 1) { + Jim_SetResult(interp, argv[i]); + } + return JIM_RETURN; +} + + +static int Jim_TailcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (interp->framePtr->level == 0) { + Jim_SetResultString(interp, "tailcall can only be called from a proc or lambda", -1); + return JIM_ERR; + } + else if (argc >= 2) { + + Jim_CallFrame *cf = interp->framePtr->parent; + + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); + if (cmdPtr == NULL) { + return JIM_ERR; + } + + JimPanic((cf->tailcallCmd != NULL, "Already have a tailcallCmd")); + + + JimIncrCmdRefCount(cmdPtr); + cf->tailcallCmd = cmdPtr; + + + JimPanic((cf->tailcallObj != NULL, "Already have a tailcallobj")); + + cf->tailcallObj = Jim_NewListObj(interp, argv + 1, argc - 1); + Jim_IncrRefCount(cf->tailcallObj); + + + return JIM_EVAL; + } + return JIM_OK; +} + +static int JimAliasCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *cmdList; + Jim_Obj *prefixListObj = Jim_CmdPrivData(interp); + + + cmdList = Jim_DuplicateObj(interp, prefixListObj); + Jim_ListInsertElements(interp, cmdList, Jim_ListLength(interp, cmdList), argc - 1, argv + 1); + + return JimEvalObjList(interp, cmdList); +} + +static void JimAliasCmdDelete(Jim_Interp *interp, void *privData) +{ + Jim_Obj *prefixListObj = privData; + Jim_DecrRefCount(interp, prefixListObj); +} + +static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *prefixListObj; + const char *newname; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?"); + return JIM_ERR; + } + + prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2); + Jim_IncrRefCount(prefixListObj); + newname = Jim_String(argv[1]); + if (newname[0] == ':' && newname[1] == ':') { + while (*++newname == ':') { + } + } + + Jim_SetResult(interp, argv[1]); + + return Jim_CreateCommand(interp, newname, JimAliasCmd, prefixListObj, JimAliasCmdDelete); +} + + +static int Jim_ProcCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Cmd *cmd; + + if (argc != 4 && argc != 5) { + Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body"); + return JIM_ERR; + } + + if (JimValidName(interp, "procedure", argv[1]) != JIM_OK) { + return JIM_ERR; + } + + if (argc == 4) { + cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL); + } + else { + cmd = JimCreateProcedureCmd(interp, argv[2], argv[3], argv[4], NULL); + } + + if (cmd) { + + Jim_Obj *qualifiedCmdNameObj; + const char *cmdname = JimQualifyName(interp, Jim_String(argv[1]), &qualifiedCmdNameObj); + + JimCreateCommand(interp, cmdname, cmd); + + + JimUpdateProcNamespace(interp, cmd, cmdname); + + JimFreeQualifiedName(interp, qualifiedCmdNameObj); + + + Jim_SetResult(interp, argv[1]); + return JIM_OK; + } + return JIM_ERR; +} + + +static int Jim_LocalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retcode; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); + return JIM_ERR; + } + + + interp->local++; + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + interp->local--; + + + + if (retcode == 0) { + Jim_Obj *cmdNameObj = Jim_GetResult(interp); + + if (Jim_GetCommand(interp, cmdNameObj, JIM_ERRMSG) == NULL) { + return JIM_ERR; + } + if (interp->framePtr->localCommands == NULL) { + interp->framePtr->localCommands = Jim_Alloc(sizeof(*interp->framePtr->localCommands)); + Jim_InitStack(interp->framePtr->localCommands); + } + Jim_IncrRefCount(cmdNameObj); + Jim_StackPush(interp->framePtr->localCommands, cmdNameObj); + } + + return retcode; +} + + +static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?"); + return JIM_ERR; + } + else { + int retcode; + + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG); + if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) { + Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]); + return JIM_ERR; + } + + cmdPtr->u.proc.upcall++; + JimIncrCmdRefCount(cmdPtr); + + + retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1); + + + cmdPtr->u.proc.upcall--; + JimDecrCmdRefCount(interp, cmdPtr); + + return retcode; + } +} + + +static int Jim_ApplyCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "lambdaExpr ?arg ...?"); + return JIM_ERR; + } + else { + int ret; + Jim_Cmd *cmd; + Jim_Obj *argListObjPtr; + Jim_Obj *bodyObjPtr; + Jim_Obj *nsObj = NULL; + Jim_Obj **nargv; + + int len = Jim_ListLength(interp, argv[1]); + if (len != 2 && len != 3) { + Jim_SetResultFormatted(interp, "can't interpret \"%#s\" as a lambda expression", argv[1]); + return JIM_ERR; + } + + if (len == 3) { +#ifdef jim_ext_namespace + + nsObj = JimQualifyNameObj(interp, Jim_ListGetIndex(interp, argv[1], 2)); +#else + Jim_SetResultString(interp, "namespaces not enabled", -1); + return JIM_ERR; +#endif + } + argListObjPtr = Jim_ListGetIndex(interp, argv[1], 0); + bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1); + + cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj); + + if (cmd) { + + nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv)); + nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1); + Jim_IncrRefCount(nargv[0]); + memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv)); + ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv); + Jim_DecrRefCount(interp, nargv[0]); + Jim_Free(nargv); + + JimDecrCmdRefCount(interp, cmd); + return ret; + } + return JIM_ERR; + } +} + + + +static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_ConcatObj(interp, argc - 1, argv + 1)); + return JIM_OK; +} + + +static int Jim_UpvarCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + Jim_CallFrame *targetCallFrame; + + + if (argc > 3 && (argc % 2 == 0)) { + targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]); + argc--; + argv++; + } + else { + targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL); + } + if (targetCallFrame == NULL) { + return JIM_ERR; + } + + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?"); + return JIM_ERR; + } + + + for (i = 1; i < argc; i += 2) { + if (Jim_SetVariableLink(interp, argv[i + 1], argv[i], targetCallFrame) != JIM_OK) + return JIM_ERR; + } + return JIM_OK; +} + + +static int Jim_GlobalCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int i; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?"); + return JIM_ERR; + } + + if (interp->framePtr->level == 0) + return JIM_OK; + for (i = 1; i < argc; i++) { + + const char *name = Jim_String(argv[i]); + if (name[0] != ':' || name[1] != ':') { + if (Jim_SetVariableLink(interp, argv[i], argv[i], interp->topFramePtr) != JIM_OK) + return JIM_ERR; + } + } + return JIM_OK; +} + +static Jim_Obj *JimStringMap(Jim_Interp *interp, Jim_Obj *mapListObjPtr, + Jim_Obj *objPtr, int nocase) +{ + int numMaps; + const char *str, *noMatchStart = NULL; + int strLen, i; + Jim_Obj *resultObjPtr; + + numMaps = Jim_ListLength(interp, mapListObjPtr); + if (numMaps % 2) { + Jim_SetResultString(interp, "list must contain an even number of elements", -1); + return NULL; + } + + str = Jim_String(objPtr); + strLen = Jim_Utf8Length(interp, objPtr); + + + resultObjPtr = Jim_NewStringObj(interp, "", 0); + while (strLen) { + for (i = 0; i < numMaps; i += 2) { + Jim_Obj *objPtr; + const char *k; + int kl; + + objPtr = Jim_ListGetIndex(interp, mapListObjPtr, i); + k = Jim_String(objPtr); + kl = Jim_Utf8Length(interp, objPtr); + + if (strLen >= kl && kl) { + int rc; + rc = JimStringCompareLen(str, k, kl, nocase); + if (rc == 0) { + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); + noMatchStart = NULL; + } + Jim_AppendObj(interp, resultObjPtr, Jim_ListGetIndex(interp, mapListObjPtr, i + 1)); + str += utf8_index(str, kl); + strLen -= kl; + break; + } + } + } + if (i == numMaps) { + int c; + if (noMatchStart == NULL) + noMatchStart = str; + str += utf8_tounicode(str, &c); + strLen--; + } + } + if (noMatchStart) { + Jim_AppendString(interp, resultObjPtr, noMatchStart, str - noMatchStart); + } + return resultObjPtr; +} + + +static int Jim_StringCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int len; + int opt_case = 1; + int option; + static const char * const options[] = { + "bytelength", "length", "compare", "match", "equal", "is", "byterange", "range", "replace", + "map", "repeat", "reverse", "index", "first", "last", "cat", + "trim", "trimleft", "trimright", "tolower", "toupper", "totitle", NULL + }; + enum + { + OPT_BYTELENGTH, OPT_LENGTH, OPT_COMPARE, OPT_MATCH, OPT_EQUAL, OPT_IS, OPT_BYTERANGE, OPT_RANGE, OPT_REPLACE, + OPT_MAP, OPT_REPEAT, OPT_REVERSE, OPT_INDEX, OPT_FIRST, OPT_LAST, OPT_CAT, + OPT_TRIM, OPT_TRIMLEFT, OPT_TRIMRIGHT, OPT_TOLOWER, OPT_TOUPPER, OPT_TOTITLE + }; + static const char * const nocase_options[] = { + "-nocase", NULL + }; + static const char * const nocase_length_options[] = { + "-nocase", "-length", NULL + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, + JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) + return JIM_ERR; + + switch (option) { + case OPT_LENGTH: + case OPT_BYTELENGTH: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + if (option == OPT_LENGTH) { + len = Jim_Utf8Length(interp, argv[2]); + } + else { + len = Jim_Length(argv[2]); + } + Jim_SetResultInt(interp, len); + return JIM_OK; + + case OPT_CAT:{ + Jim_Obj *objPtr; + if (argc == 3) { + + objPtr = argv[2]; + } + else { + int i; + + objPtr = Jim_NewStringObj(interp, "", 0); + + for (i = 2; i < argc; i++) { + Jim_AppendObj(interp, objPtr, argv[i]); + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_COMPARE: + case OPT_EQUAL: + { + + long opt_length = -1; + int n = argc - 4; + int i = 2; + while (n > 0) { + int subopt; + if (Jim_GetEnum(interp, argv[i++], nocase_length_options, &subopt, NULL, + JIM_ENUM_ABBREV) != JIM_OK) { +badcompareargs: + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? ?-length int? string1 string2"); + return JIM_ERR; + } + if (subopt == 0) { + + opt_case = 0; + n--; + } + else { + + if (n < 2) { + goto badcompareargs; + } + if (Jim_GetLong(interp, argv[i++], &opt_length) != JIM_OK) { + return JIM_ERR; + } + n -= 2; + } + } + if (n) { + goto badcompareargs; + } + argv += argc - 2; + if (opt_length < 0 && option != OPT_COMPARE && opt_case) { + + Jim_SetResultBool(interp, Jim_StringEqObj(argv[0], argv[1])); + } + else { + if (opt_length >= 0) { + n = JimStringCompareLen(Jim_String(argv[0]), Jim_String(argv[1]), opt_length, !opt_case); + } + else { + n = Jim_StringCompareObj(interp, argv[0], argv[1], !opt_case); + } + Jim_SetResultInt(interp, option == OPT_COMPARE ? n : n == 0); + } + return JIM_OK; + } + + case OPT_MATCH: + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? pattern string"); + return JIM_ERR; + } + if (opt_case == 0) { + argv++; + } + Jim_SetResultBool(interp, Jim_StringMatchObj(interp, argv[2], argv[3], !opt_case)); + return JIM_OK; + + case OPT_MAP:{ + Jim_Obj *objPtr; + + if (argc != 4 && + (argc != 5 || + Jim_GetEnum(interp, argv[2], nocase_options, &opt_case, NULL, + JIM_ENUM_ABBREV) != JIM_OK)) { + Jim_WrongNumArgs(interp, 2, argv, "?-nocase? mapList string"); + return JIM_ERR; + } + + if (opt_case == 0) { + argv++; + } + objPtr = JimStringMap(interp, argv[2], argv[3], !opt_case); + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_RANGE: + case OPT_BYTERANGE:{ + Jim_Obj *objPtr; + + if (argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "string first last"); + return JIM_ERR; + } + if (option == OPT_RANGE) { + objPtr = Jim_StringRangeObj(interp, argv[2], argv[3], argv[4]); + } + else + { + objPtr = Jim_StringByteRangeObj(interp, argv[2], argv[3], argv[4]); + } + + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_REPLACE:{ + Jim_Obj *objPtr; + + if (argc != 5 && argc != 6) { + Jim_WrongNumArgs(interp, 2, argv, "string first last ?string?"); + return JIM_ERR; + } + objPtr = JimStringReplaceObj(interp, argv[2], argv[3], argv[4], argc == 6 ? argv[5] : NULL); + if (objPtr == NULL) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + + case OPT_REPEAT:{ + Jim_Obj *objPtr; + jim_wide count; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string count"); + return JIM_ERR; + } + if (Jim_GetWide(interp, argv[3], &count) != JIM_OK) { + return JIM_ERR; + } + objPtr = Jim_NewStringObj(interp, "", 0); + if (count > 0) { + while (count--) { + Jim_AppendObj(interp, objPtr, argv[2]); + } + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + } + + case OPT_REVERSE:{ + char *buf, *p; + const char *str; + int len; + int i; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + + str = Jim_GetString(argv[2], &len); + buf = Jim_Alloc(len + 1); + p = buf + len; + *p = 0; + for (i = 0; i < len; ) { + int c; + int l = utf8_tounicode(str, &c); + memcpy(p - l, str, l); + p -= l; + i += l; + str += l; + } + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); + return JIM_OK; + } + + case OPT_INDEX:{ + int idx; + const char *str; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string index"); + return JIM_ERR; + } + if (Jim_GetIndex(interp, argv[3], &idx) != JIM_OK) { + return JIM_ERR; + } + str = Jim_String(argv[2]); + len = Jim_Utf8Length(interp, argv[2]); + if (idx != INT_MIN && idx != INT_MAX) { + idx = JimRelToAbsIndex(len, idx); + } + if (idx < 0 || idx >= len || str == NULL) { + Jim_SetResultString(interp, "", 0); + } + else if (len == Jim_Length(argv[2])) { + + Jim_SetResultString(interp, str + idx, 1); + } + else { + int c; + int i = utf8_index(str, idx); + Jim_SetResultString(interp, str + i, utf8_tounicode(str + i, &c)); + } + return JIM_OK; + } + + case OPT_FIRST: + case OPT_LAST:{ + int idx = 0, l1, l2; + const char *s1, *s2; + + if (argc != 4 && argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "subString string ?index?"); + return JIM_ERR; + } + s1 = Jim_String(argv[2]); + s2 = Jim_String(argv[3]); + l1 = Jim_Utf8Length(interp, argv[2]); + l2 = Jim_Utf8Length(interp, argv[3]); + if (argc == 5) { + if (Jim_GetIndex(interp, argv[4], &idx) != JIM_OK) { + return JIM_ERR; + } + idx = JimRelToAbsIndex(l2, idx); + } + else if (option == OPT_LAST) { + idx = l2; + } + if (option == OPT_FIRST) { + Jim_SetResultInt(interp, JimStringFirst(s1, l1, s2, l2, idx)); + } + else { +#ifdef JIM_UTF8 + Jim_SetResultInt(interp, JimStringLastUtf8(s1, l1, s2, idx)); +#else + Jim_SetResultInt(interp, JimStringLast(s1, l1, s2, idx)); +#endif + } + return JIM_OK; + } + + case OPT_TRIM: + case OPT_TRIMLEFT: + case OPT_TRIMRIGHT:{ + Jim_Obj *trimchars; + + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "string ?trimchars?"); + return JIM_ERR; + } + trimchars = (argc == 4 ? argv[3] : NULL); + if (option == OPT_TRIM) { + Jim_SetResult(interp, JimStringTrim(interp, argv[2], trimchars)); + } + else if (option == OPT_TRIMLEFT) { + Jim_SetResult(interp, JimStringTrimLeft(interp, argv[2], trimchars)); + } + else if (option == OPT_TRIMRIGHT) { + Jim_SetResult(interp, JimStringTrimRight(interp, argv[2], trimchars)); + } + return JIM_OK; + } + + case OPT_TOLOWER: + case OPT_TOUPPER: + case OPT_TOTITLE: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "string"); + return JIM_ERR; + } + if (option == OPT_TOLOWER) { + Jim_SetResult(interp, JimStringToLower(interp, argv[2])); + } + else if (option == OPT_TOUPPER) { + Jim_SetResult(interp, JimStringToUpper(interp, argv[2])); + } + else { + Jim_SetResult(interp, JimStringToTitle(interp, argv[2])); + } + return JIM_OK; + + case OPT_IS: + if (argc == 4 || (argc == 5 && Jim_CompareStringImmediate(interp, argv[3], "-strict"))) { + return JimStringIs(interp, argv[argc - 1], argv[2], argc == 5); + } + Jim_WrongNumArgs(interp, 2, argv, "class ?-strict? str"); + return JIM_ERR; + } + return JIM_OK; +} + + +static int Jim_TimeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + long i, count = 1; + jim_wide start, elapsed; + char buf[60]; + const char *fmt = "%" JIM_WIDE_MODIFIER " microseconds per iteration"; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "script ?count?"); + return JIM_ERR; + } + if (argc == 3) { + if (Jim_GetLong(interp, argv[2], &count) != JIM_OK) + return JIM_ERR; + } + if (count < 0) + return JIM_OK; + i = count; + start = JimClock(); + while (i-- > 0) { + int retval; + + retval = Jim_EvalObj(interp, argv[1]); + if (retval != JIM_OK) { + return retval; + } + } + elapsed = JimClock() - start; + sprintf(buf, fmt, count == 0 ? 0 : elapsed / count); + Jim_SetResultString(interp, buf, -1); + return JIM_OK; +} + + +static int Jim_ExitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + long exitCode = 0; + + if (argc > 2) { + Jim_WrongNumArgs(interp, 1, argv, "?exitCode?"); + return JIM_ERR; + } + if (argc == 2) { + if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK) + return JIM_ERR; + } + interp->exitCode = exitCode; + return JIM_EXIT; +} + + +static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int exitCode = 0; + int i; + int sig = 0; + + + jim_wide ignore_mask = (1 << JIM_EXIT) | (1 << JIM_EVAL) | (1 << JIM_SIGNAL); + static const int max_ignore_code = sizeof(ignore_mask) * 8; + + Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "NONE", -1)); + + for (i = 1; i < argc - 1; i++) { + const char *arg = Jim_String(argv[i]); + jim_wide option; + int ignore; + + + if (strcmp(arg, "--") == 0) { + i++; + break; + } + if (*arg != '-') { + break; + } + + if (strncmp(arg, "-no", 3) == 0) { + arg += 3; + ignore = 1; + } + else { + arg++; + ignore = 0; + } + + if (Jim_StringToWide(arg, &option, 10) != JIM_OK) { + option = -1; + } + if (option < 0) { + option = Jim_FindByName(arg, jimReturnCodes, jimReturnCodesSize); + } + if (option < 0) { + goto wrongargs; + } + + if (ignore) { + ignore_mask |= (1 << option); + } + else { + ignore_mask &= ~(1 << option); + } + } + + argc -= i; + if (argc < 1 || argc > 3) { + wrongargs: + Jim_WrongNumArgs(interp, 1, argv, + "?-?no?code ... --? script ?resultVarName? ?optionVarName?"); + return JIM_ERR; + } + argv += i; + + if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) { + sig++; + } + + interp->signal_level += sig; + if (Jim_CheckSignal(interp)) { + + exitCode = JIM_SIGNAL; + } + else { + exitCode = Jim_EvalObj(interp, argv[0]); + + interp->errorFlag = 0; + } + interp->signal_level -= sig; + + + if (exitCode >= 0 && exitCode < max_ignore_code && (((unsigned jim_wide)1 << exitCode) & ignore_mask)) { + + return exitCode; + } + + if (sig && exitCode == JIM_SIGNAL) { + + if (interp->signal_set_result) { + interp->signal_set_result(interp, interp->sigmask); + } + else { + Jim_SetResultInt(interp, interp->sigmask); + } + interp->sigmask = 0; + } + + if (argc >= 2) { + if (Jim_SetVariable(interp, argv[1], Jim_GetResult(interp)) != JIM_OK) { + return JIM_ERR; + } + if (argc == 3) { + Jim_Obj *optListObj = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-code", -1)); + Jim_ListAppendElement(interp, optListObj, + Jim_NewIntObj(interp, exitCode == JIM_RETURN ? interp->returnCode : exitCode)); + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-level", -1)); + Jim_ListAppendElement(interp, optListObj, Jim_NewIntObj(interp, interp->returnLevel)); + if (exitCode == JIM_ERR) { + Jim_Obj *errorCode; + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorinfo", + -1)); + Jim_ListAppendElement(interp, optListObj, interp->stackTrace); + + errorCode = Jim_GetGlobalVariableStr(interp, "errorCode", JIM_NONE); + if (errorCode) { + Jim_ListAppendElement(interp, optListObj, Jim_NewStringObj(interp, "-errorcode", -1)); + Jim_ListAppendElement(interp, optListObj, errorCode); + } + } + if (Jim_SetVariable(interp, argv[2], optListObj) != JIM_OK) { + return JIM_ERR; + } + } + } + Jim_SetResultInt(interp, exitCode); + return JIM_OK; +} + +#ifdef JIM_REFERENCES + + +static int Jim_RefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "string tag ?finalizer?"); + return JIM_ERR; + } + if (argc == 3) { + Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], NULL)); + } + else { + Jim_SetResult(interp, Jim_NewReference(interp, argv[1], argv[2], argv[3])); + } + return JIM_OK; +} + + +static int Jim_GetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Reference *refPtr; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "reference"); + return JIM_ERR; + } + if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) + return JIM_ERR; + Jim_SetResult(interp, refPtr->objPtr); + return JIM_OK; +} + + +static int Jim_SetrefCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Reference *refPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "reference newValue"); + return JIM_ERR; + } + if ((refPtr = Jim_GetReference(interp, argv[1])) == NULL) + return JIM_ERR; + Jim_IncrRefCount(argv[2]); + Jim_DecrRefCount(interp, refPtr->objPtr); + refPtr->objPtr = argv[2]; + Jim_SetResult(interp, argv[2]); + return JIM_OK; +} + + +static int Jim_CollectCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 1) { + Jim_WrongNumArgs(interp, 1, argv, ""); + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_Collect(interp)); + + + while (interp->freeList) { + Jim_Obj *nextObjPtr = interp->freeList->nextObjPtr; + Jim_Free(interp->freeList); + interp->freeList = nextObjPtr; + } + + return JIM_OK; +} + + +static int Jim_FinalizeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "reference ?finalizerProc?"); + return JIM_ERR; + } + if (argc == 2) { + Jim_Obj *cmdNamePtr; + + if (Jim_GetFinalizer(interp, argv[1], &cmdNamePtr) != JIM_OK) + return JIM_ERR; + if (cmdNamePtr != NULL) + Jim_SetResult(interp, cmdNamePtr); + } + else { + if (Jim_SetFinalizer(interp, argv[1], argv[2]) != JIM_OK) + return JIM_ERR; + Jim_SetResult(interp, argv[2]); + } + return JIM_OK; +} + + +static int JimInfoReferences(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listObjPtr; + Jim_HashTableIterator htiter; + Jim_HashEntry *he; + + listObjPtr = Jim_NewListObj(interp, NULL, 0); + + JimInitHashTableIterator(&interp->references, &htiter); + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { + char buf[JIM_REFERENCE_SPACE + 1]; + Jim_Reference *refPtr = Jim_GetHashEntryVal(he); + const unsigned long *refId = he->key; + + JimFormatReference(buf, refPtr, *refId); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, buf, -1)); + } + Jim_SetResult(interp, listObjPtr); + return JIM_OK; +} +#endif + + +static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "oldName newName"); + return JIM_ERR; + } + + if (JimValidName(interp, "new procedure", argv[2])) { + return JIM_ERR; + } + + return Jim_RenameCommand(interp, Jim_String(argv[1]), Jim_String(argv[2])); +} + +#define JIM_DICTMATCH_VALUES 0x0001 + +typedef void JimDictMatchCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type); + +static void JimDictMatchKeys(Jim_Interp *interp, Jim_Obj *listObjPtr, Jim_HashEntry *he, int type) +{ + Jim_ListAppendElement(interp, listObjPtr, (Jim_Obj *)he->key); + if (type & JIM_DICTMATCH_VALUES) { + Jim_ListAppendElement(interp, listObjPtr, Jim_GetHashEntryVal(he)); + } +} + +static Jim_Obj *JimDictPatternMatch(Jim_Interp *interp, Jim_HashTable *ht, Jim_Obj *patternObjPtr, + JimDictMatchCallbackType *callback, int type) +{ + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + + Jim_HashTableIterator htiter; + JimInitHashTableIterator(ht, &htiter); + while ((he = Jim_NextHashEntry(&htiter)) != NULL) { + if (patternObjPtr == NULL || JimGlobMatch(Jim_String(patternObjPtr), Jim_String((Jim_Obj *)he->key), 0)) { + callback(interp, listObjPtr, he, type); + } + } + + return listObjPtr; +} + + +int Jim_DictKeys(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) +{ + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, 0)); + return JIM_OK; +} + +int Jim_DictValues(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *patternObjPtr) +{ + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, JimDictPatternMatch(interp, objPtr->internalRep.ptr, patternObjPtr, JimDictMatchKeys, JIM_DICTMATCH_VALUES)); + return JIM_OK; +} + +int Jim_DictSize(Jim_Interp *interp, Jim_Obj *objPtr) +{ + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return -1; + } + return ((Jim_HashTable *)objPtr->internalRep.ptr)->used; +} + +int Jim_DictInfo(Jim_Interp *interp, Jim_Obj *objPtr) +{ + Jim_HashTable *ht; + unsigned int i; + + if (SetDictFromAny(interp, objPtr) != JIM_OK) { + return JIM_ERR; + } + + ht = (Jim_HashTable *)objPtr->internalRep.ptr; + + + printf("%d entries in table, %d buckets\n", ht->used, ht->size); + + for (i = 0; i < ht->size; i++) { + Jim_HashEntry *he = ht->table[i]; + + if (he) { + printf("%d: ", i); + + while (he) { + printf(" %s", Jim_String(he->key)); + he = he->next; + } + printf("\n"); + } + } + return JIM_OK; +} + +static int Jim_EvalEnsemble(Jim_Interp *interp, const char *basecmd, const char *subcmd, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *prefixObj = Jim_NewStringObj(interp, basecmd, -1); + + Jim_AppendString(interp, prefixObj, " ", 1); + Jim_AppendString(interp, prefixObj, subcmd, -1); + + return Jim_EvalObjPrefix(interp, prefixObj, argc, argv); +} + + +static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int option; + static const char * const options[] = { + "create", "get", "set", "unset", "exists", "keys", "size", "info", + "merge", "with", "append", "lappend", "incr", "remove", "values", "for", + "replace", "update", NULL + }; + enum + { + OPT_CREATE, OPT_GET, OPT_SET, OPT_UNSET, OPT_EXISTS, OPT_KEYS, OPT_SIZE, OPT_INFO, + OPT_MERGE, OPT_WITH, OPT_APPEND, OPT_LAPPEND, OPT_INCR, OPT_REMOVE, OPT_VALUES, OPT_FOR, + OPT_REPLACE, OPT_UPDATE, + }; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?arguments ...?"); + return JIM_ERR; + } + + if (Jim_GetEnum(interp, argv[1], options, &option, "subcommand", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + + switch (option) { + case OPT_GET: + if (argc < 3) { + Jim_WrongNumArgs(interp, 2, argv, "dictionary ?key ...?"); + return JIM_ERR; + } + if (Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, + JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; + + case OPT_SET: + if (argc < 5) { + Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...? value"); + return JIM_ERR; + } + return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG); + + case OPT_EXISTS: + if (argc < 4) { + Jim_WrongNumArgs(interp, 2, argv, "dictionary key ?key ...?"); + return JIM_ERR; + } + else { + int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_ERRMSG); + if (rc < 0) { + return JIM_ERR; + } + Jim_SetResultBool(interp, rc == JIM_OK); + return JIM_OK; + } + + case OPT_UNSET: + if (argc < 4) { + Jim_WrongNumArgs(interp, 2, argv, "varName key ?key ...?"); + return JIM_ERR; + } + if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, 0) != JIM_OK) { + return JIM_ERR; + } + return JIM_OK; + + case OPT_KEYS: + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "dictionary ?pattern?"); + return JIM_ERR; + } + return Jim_DictKeys(interp, argv[2], argc == 4 ? argv[3] : NULL); + + case OPT_SIZE: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "dictionary"); + return JIM_ERR; + } + else if (Jim_DictSize(interp, argv[2]) < 0) { + return JIM_ERR; + } + Jim_SetResultInt(interp, Jim_DictSize(interp, argv[2])); + return JIM_OK; + + case OPT_MERGE: + if (argc == 2) { + return JIM_OK; + } + if (Jim_DictSize(interp, argv[2]) < 0) { + return JIM_ERR; + } + + break; + + case OPT_UPDATE: + if (argc < 6 || argc % 2) { + + argc = 2; + } + break; + + case OPT_CREATE: + if (argc % 2) { + Jim_WrongNumArgs(interp, 2, argv, "?key value ...?"); + return JIM_ERR; + } + objPtr = Jim_NewDictObj(interp, argv + 2, argc - 2); + Jim_SetResult(interp, objPtr); + return JIM_OK; + + case OPT_INFO: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "dictionary"); + return JIM_ERR; + } + return Jim_DictInfo(interp, argv[2]); + } + + return Jim_EvalEnsemble(interp, "dict", options[option], argc - 2, argv + 2); +} + + +static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + static const char * const options[] = { + "-nobackslashes", "-nocommands", "-novariables", NULL + }; + enum + { OPT_NOBACKSLASHES, OPT_NOCOMMANDS, OPT_NOVARIABLES }; + int i; + int flags = JIM_SUBST_FLAG; + Jim_Obj *objPtr; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "?options? string"); + return JIM_ERR; + } + for (i = 1; i < (argc - 1); i++) { + int option; + + if (Jim_GetEnum(interp, argv[i], options, &option, NULL, + JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + switch (option) { + case OPT_NOBACKSLASHES: + flags |= JIM_SUBST_NOESC; + break; + case OPT_NOCOMMANDS: + flags |= JIM_SUBST_NOCMD; + break; + case OPT_NOVARIABLES: + flags |= JIM_SUBST_NOVAR; + break; + } + } + if (Jim_SubstObj(interp, argv[argc - 1], &objPtr, flags) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + + +static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int cmd; + Jim_Obj *objPtr; + int mode = 0; + + static const char * const commands[] = { + "body", "statics", "commands", "procs", "channels", "exists", "globals", "level", "frame", "locals", + "vars", "version", "patchlevel", "complete", "args", "hostname", + "script", "source", "stacktrace", "nameofexecutable", "returncodes", + "references", "alias", NULL + }; + enum + { INFO_BODY, INFO_STATICS, INFO_COMMANDS, INFO_PROCS, INFO_CHANNELS, INFO_EXISTS, INFO_GLOBALS, INFO_LEVEL, + INFO_FRAME, INFO_LOCALS, INFO_VARS, INFO_VERSION, INFO_PATCHLEVEL, INFO_COMPLETE, INFO_ARGS, + INFO_HOSTNAME, INFO_SCRIPT, INFO_SOURCE, INFO_STACKTRACE, INFO_NAMEOFEXECUTABLE, + INFO_RETURNCODES, INFO_REFERENCES, INFO_ALIAS, + }; + +#ifdef jim_ext_namespace + int nons = 0; + + if (argc > 2 && Jim_CompareStringImmediate(interp, argv[1], "-nons")) { + + argc--; + argv++; + nons = 1; + } +#endif + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "subcommand ?args ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], commands, &cmd, "subcommand", JIM_ERRMSG | JIM_ENUM_ABBREV) + != JIM_OK) { + return JIM_ERR; + } + + + switch (cmd) { + case INFO_EXISTS: + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "varName"); + return JIM_ERR; + } + Jim_SetResultBool(interp, Jim_GetVariable(interp, argv[2], 0) != NULL); + break; + + case INFO_ALIAS:{ + Jim_Cmd *cmdPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "command"); + return JIM_ERR; + } + if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { + return JIM_ERR; + } + if (cmdPtr->isproc || cmdPtr->u.native.cmdProc != JimAliasCmd) { + Jim_SetResultFormatted(interp, "command \"%#s\" is not an alias", argv[2]); + return JIM_ERR; + } + Jim_SetResult(interp, (Jim_Obj *)cmdPtr->u.native.privData); + return JIM_OK; + } + + case INFO_CHANNELS: + mode++; +#ifndef jim_ext_aio + Jim_SetResultString(interp, "aio not enabled", -1); + return JIM_ERR; +#endif + case INFO_PROCS: + mode++; + case INFO_COMMANDS: + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); + return JIM_ERR; + } +#ifdef jim_ext_namespace + if (!nons) { + if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) { + return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1); + } + } +#endif + Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode)); + break; + + case INFO_VARS: + mode++; + case INFO_LOCALS: + mode++; + case INFO_GLOBALS: + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "?pattern?"); + return JIM_ERR; + } +#ifdef jim_ext_namespace + if (!nons) { + if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimGlobMatch("::*", Jim_String(argv[2]), 0))) { + return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1); + } + } +#endif + Jim_SetResult(interp, JimVariablesList(interp, argc == 3 ? argv[2] : NULL, mode)); + break; + + case INFO_SCRIPT: + if (argc != 2) { + Jim_WrongNumArgs(interp, 2, argv, ""); + return JIM_ERR; + } + Jim_SetResult(interp, JimGetScript(interp, interp->currentScriptObj)->fileNameObj); + break; + + case INFO_SOURCE:{ + jim_wide line; + Jim_Obj *resObjPtr; + Jim_Obj *fileNameObj; + + if (argc != 3 && argc != 5) { + Jim_WrongNumArgs(interp, 2, argv, "source ?filename line?"); + return JIM_ERR; + } + if (argc == 5) { + if (Jim_GetWide(interp, argv[4], &line) != JIM_OK) { + return JIM_ERR; + } + resObjPtr = Jim_NewStringObj(interp, Jim_String(argv[2]), Jim_Length(argv[2])); + JimSetSourceInfo(interp, resObjPtr, argv[3], line); + } + else { + if (argv[2]->typePtr == &sourceObjType) { + fileNameObj = argv[2]->internalRep.sourceValue.fileNameObj; + line = argv[2]->internalRep.sourceValue.lineNumber; + } + else if (argv[2]->typePtr == &scriptObjType) { + ScriptObj *script = JimGetScript(interp, argv[2]); + fileNameObj = script->fileNameObj; + line = script->firstline; + } + else { + fileNameObj = interp->emptyObj; + line = 1; + } + resObjPtr = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, resObjPtr, fileNameObj); + Jim_ListAppendElement(interp, resObjPtr, Jim_NewIntObj(interp, line)); + } + Jim_SetResult(interp, resObjPtr); + break; + } + + case INFO_STACKTRACE: + Jim_SetResult(interp, interp->stackTrace); + break; + + case INFO_LEVEL: + case INFO_FRAME: + switch (argc) { + case 2: + Jim_SetResultInt(interp, interp->framePtr->level); + break; + + case 3: + if (JimInfoLevel(interp, argv[2], &objPtr, cmd == INFO_LEVEL) != JIM_OK) { + return JIM_ERR; + } + Jim_SetResult(interp, objPtr); + break; + + default: + Jim_WrongNumArgs(interp, 2, argv, "?levelNum?"); + return JIM_ERR; + } + break; + + case INFO_BODY: + case INFO_STATICS: + case INFO_ARGS:{ + Jim_Cmd *cmdPtr; + + if (argc != 3) { + Jim_WrongNumArgs(interp, 2, argv, "procname"); + return JIM_ERR; + } + if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) { + return JIM_ERR; + } + if (!cmdPtr->isproc) { + Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]); + return JIM_ERR; + } + switch (cmd) { + case INFO_BODY: + Jim_SetResult(interp, cmdPtr->u.proc.bodyObjPtr); + break; + case INFO_ARGS: + Jim_SetResult(interp, cmdPtr->u.proc.argListObjPtr); + break; + case INFO_STATICS: + if (cmdPtr->u.proc.staticVars) { + int mode = JIM_VARLIST_LOCALS | JIM_VARLIST_VALUES; + Jim_SetResult(interp, JimHashtablePatternMatch(interp, cmdPtr->u.proc.staticVars, + NULL, JimVariablesMatch, mode)); + } + break; + } + break; + } + + case INFO_VERSION: + case INFO_PATCHLEVEL:{ + char buf[(JIM_INTEGER_SPACE * 2) + 1]; + + sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100); + Jim_SetResultString(interp, buf, -1); + break; + } + + case INFO_COMPLETE: + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "script ?missing?"); + return JIM_ERR; + } + else { + int len; + const char *s = Jim_GetString(argv[2], &len); + char missing; + + Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing)); + if (missing != ' ' && argc == 4) { + Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1)); + } + } + break; + + case INFO_HOSTNAME: + + return Jim_Eval(interp, "os.gethostname"); + + case INFO_NAMEOFEXECUTABLE: + + return Jim_Eval(interp, "{info nameofexecutable}"); + + case INFO_RETURNCODES: + if (argc == 2) { + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; jimReturnCodes[i]; i++) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewIntObj(interp, i)); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, + jimReturnCodes[i], -1)); + } + + Jim_SetResult(interp, listObjPtr); + } + else if (argc == 3) { + long code; + const char *name; + + if (Jim_GetLong(interp, argv[2], &code) != JIM_OK) { + return JIM_ERR; + } + name = Jim_ReturnCode(code); + if (*name == '?') { + Jim_SetResultInt(interp, code); + } + else { + Jim_SetResultString(interp, name, -1); + } + } + else { + Jim_WrongNumArgs(interp, 2, argv, "?code?"); + return JIM_ERR; + } + break; + case INFO_REFERENCES: +#ifdef JIM_REFERENCES + return JimInfoReferences(interp, argc, argv); +#else + Jim_SetResultString(interp, "not supported", -1); + return JIM_ERR; +#endif + } + return JIM_OK; +} + + +static int Jim_ExistsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + int result = 0; + + static const char * const options[] = { + "-command", "-proc", "-alias", "-var", NULL + }; + enum + { + OPT_COMMAND, OPT_PROC, OPT_ALIAS, OPT_VAR + }; + int option; + + if (argc == 2) { + option = OPT_VAR; + objPtr = argv[1]; + } + else if (argc == 3) { + if (Jim_GetEnum(interp, argv[1], options, &option, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) { + return JIM_ERR; + } + objPtr = argv[2]; + } + else { + Jim_WrongNumArgs(interp, 1, argv, "?option? name"); + return JIM_ERR; + } + + if (option == OPT_VAR) { + result = Jim_GetVariable(interp, objPtr, 0) != NULL; + } + else { + + Jim_Cmd *cmd = Jim_GetCommand(interp, objPtr, JIM_NONE); + + if (cmd) { + switch (option) { + case OPT_COMMAND: + result = 1; + break; + + case OPT_ALIAS: + result = cmd->isproc == 0 && cmd->u.native.cmdProc == JimAliasCmd; + break; + + case OPT_PROC: + result = cmd->isproc; + break; + } + } + } + Jim_SetResultBool(interp, result); + return JIM_OK; +} + + +static int Jim_SplitCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *str, *splitChars, *noMatchStart; + int splitLen, strLen; + Jim_Obj *resObjPtr; + int c; + int len; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "string ?splitChars?"); + return JIM_ERR; + } + + str = Jim_GetString(argv[1], &len); + if (len == 0) { + return JIM_OK; + } + strLen = Jim_Utf8Length(interp, argv[1]); + + + if (argc == 2) { + splitChars = " \n\t\r"; + splitLen = 4; + } + else { + splitChars = Jim_String(argv[2]); + splitLen = Jim_Utf8Length(interp, argv[2]); + } + + noMatchStart = str; + resObjPtr = Jim_NewListObj(interp, NULL, 0); + + + if (splitLen) { + Jim_Obj *objPtr; + while (strLen--) { + const char *sc = splitChars; + int scLen = splitLen; + int sl = utf8_tounicode(str, &c); + while (scLen--) { + int pc; + sc += utf8_tounicode(sc, &pc); + if (c == pc) { + objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); + Jim_ListAppendElement(interp, resObjPtr, objPtr); + noMatchStart = str + sl; + break; + } + } + str += sl; + } + objPtr = Jim_NewStringObj(interp, noMatchStart, (str - noMatchStart)); + Jim_ListAppendElement(interp, resObjPtr, objPtr); + } + else { + Jim_Obj **commonObj = NULL; +#define NUM_COMMON (128 - 9) + while (strLen--) { + int n = utf8_tounicode(str, &c); +#ifdef JIM_OPTIMIZATION + if (c >= 9 && c < 128) { + + c -= 9; + if (!commonObj) { + commonObj = Jim_Alloc(sizeof(*commonObj) * NUM_COMMON); + memset(commonObj, 0, sizeof(*commonObj) * NUM_COMMON); + } + if (!commonObj[c]) { + commonObj[c] = Jim_NewStringObj(interp, str, 1); + } + Jim_ListAppendElement(interp, resObjPtr, commonObj[c]); + str++; + continue; + } +#endif + Jim_ListAppendElement(interp, resObjPtr, Jim_NewStringObjUtf8(interp, str, 1)); + str += n; + } + Jim_Free(commonObj); + } + + Jim_SetResult(interp, resObjPtr); + return JIM_OK; +} + + +static int Jim_JoinCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *joinStr; + int joinStrLen; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?"); + return JIM_ERR; + } + + if (argc == 2) { + joinStr = " "; + joinStrLen = 1; + } + else { + joinStr = Jim_GetString(argv[2], &joinStrLen); + } + Jim_SetResult(interp, Jim_ListJoin(interp, argv[1], joinStr, joinStrLen)); + return JIM_OK; +} + + +static int Jim_FormatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "formatString ?arg arg ...?"); + return JIM_ERR; + } + objPtr = Jim_FormatString(interp, argv[1], argc - 2, argv + 2); + if (objPtr == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + + +static int Jim_ScanCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *listPtr, **outVec; + int outc, i; + + if (argc < 3) { + Jim_WrongNumArgs(interp, 1, argv, "string format ?varName varName ...?"); + return JIM_ERR; + } + if (argv[2]->typePtr != &scanFmtStringObjType) + SetScanFmtFromAny(interp, argv[2]); + if (FormatGetError(argv[2]) != 0) { + Jim_SetResultString(interp, FormatGetError(argv[2]), -1); + return JIM_ERR; + } + if (argc > 3) { + int maxPos = FormatGetMaxPos(argv[2]); + int count = FormatGetCnvCount(argv[2]); + + if (maxPos > argc - 3) { + Jim_SetResultString(interp, "\"%n$\" argument index out of range", -1); + return JIM_ERR; + } + else if (count > argc - 3) { + Jim_SetResultString(interp, "different numbers of variable names and " + "field specifiers", -1); + return JIM_ERR; + } + else if (count < argc - 3) { + Jim_SetResultString(interp, "variable is not assigned by any " + "conversion specifiers", -1); + return JIM_ERR; + } + } + listPtr = Jim_ScanString(interp, argv[1], argv[2], JIM_ERRMSG); + if (listPtr == 0) + return JIM_ERR; + if (argc > 3) { + int rc = JIM_OK; + int count = 0; + + if (listPtr != 0 && listPtr != (Jim_Obj *)EOF) { + int len = Jim_ListLength(interp, listPtr); + + if (len != 0) { + JimListGetElements(interp, listPtr, &outc, &outVec); + for (i = 0; i < outc; ++i) { + if (Jim_Length(outVec[i]) > 0) { + ++count; + if (Jim_SetVariable(interp, argv[3 + i], outVec[i]) != JIM_OK) { + rc = JIM_ERR; + } + } + } + } + Jim_FreeNewObj(interp, listPtr); + } + else { + count = -1; + } + if (rc == JIM_OK) { + Jim_SetResultInt(interp, count); + } + return rc; + } + else { + if (listPtr == (Jim_Obj *)EOF) { + Jim_SetResult(interp, Jim_NewListObj(interp, 0, 0)); + return JIM_OK; + } + Jim_SetResult(interp, listPtr); + } + return JIM_OK; +} + + +static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "message ?stacktrace?"); + return JIM_ERR; + } + Jim_SetResult(interp, argv[1]); + if (argc == 3) { + JimSetStackTrace(interp, argv[2]); + return JIM_ERR; + } + interp->addStackTrace++; + return JIM_ERR; +} + + +static int Jim_LrangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + + if (argc != 4) { + Jim_WrongNumArgs(interp, 1, argv, "list first last"); + return JIM_ERR; + } + if ((objPtr = Jim_ListRange(interp, argv[1], argv[2], argv[3])) == NULL) + return JIM_ERR; + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + + +static int Jim_LrepeatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *objPtr; + long count; + + if (argc < 2 || Jim_GetLong(interp, argv[1], &count) != JIM_OK || count < 0) { + Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?"); + return JIM_ERR; + } + + if (count == 0 || argc == 2) { + return JIM_OK; + } + + argc -= 2; + argv += 2; + + objPtr = Jim_NewListObj(interp, argv, argc); + while (--count) { + ListInsertElements(objPtr, -1, argc, argv); + } + + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + +char **Jim_GetEnviron(void) +{ +#if defined(HAVE__NSGETENVIRON) + return *_NSGetEnviron(); +#else + #if !defined(NO_ENVIRON_EXTERN) + extern char **environ; + #endif + + return environ; +#endif +} + +void Jim_SetEnviron(char **env) +{ +#if defined(HAVE__NSGETENVIRON) + *_NSGetEnviron() = env; +#else + #if !defined(NO_ENVIRON_EXTERN) + extern char **environ; + #endif + + environ = env; +#endif +} + + +static int Jim_EnvCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const char *key; + const char *val; + + if (argc == 1) { + char **e = Jim_GetEnviron(); + + int i; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + for (i = 0; e[i]; i++) { + const char *equals = strchr(e[i], '='); + + if (equals) { + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, e[i], + equals - e[i])); + Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, equals + 1, -1)); + } + } + + Jim_SetResult(interp, listObjPtr); + return JIM_OK; + } + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "varName ?default?"); + return JIM_ERR; + } + key = Jim_String(argv[1]); + val = getenv(key); + if (val == NULL) { + if (argc < 3) { + Jim_SetResultFormatted(interp, "environment variable \"%#s\" does not exist", argv[1]); + return JIM_ERR; + } + val = Jim_String(argv[2]); + } + Jim_SetResult(interp, Jim_NewStringObj(interp, val, -1)); + return JIM_OK; +} + + +static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int retval; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "fileName"); + return JIM_ERR; + } + retval = Jim_EvalFile(interp, Jim_String(argv[1])); + if (retval == JIM_RETURN) + return JIM_OK; + return retval; +} + + +static int Jim_LreverseCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *revObjPtr, **ele; + int len; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "list"); + return JIM_ERR; + } + JimListGetElements(interp, argv[1], &len, &ele); + len--; + revObjPtr = Jim_NewListObj(interp, NULL, 0); + while (len >= 0) + ListAppendElement(revObjPtr, ele[len--]); + Jim_SetResult(interp, revObjPtr); + return JIM_OK; +} + +static int JimRangeLen(jim_wide start, jim_wide end, jim_wide step) +{ + jim_wide len; + + if (step == 0) + return -1; + if (start == end) + return 0; + else if (step > 0 && start > end) + return -1; + else if (step < 0 && end > start) + return -1; + len = end - start; + if (len < 0) + len = -len; + if (step < 0) + step = -step; + len = 1 + ((len - 1) / step); + if (len > INT_MAX) + len = INT_MAX; + return (int)((len < 0) ? -1 : len); +} + + +static int Jim_RangeCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide start = 0, end, step = 1; + int len, i; + Jim_Obj *objPtr; + + if (argc < 2 || argc > 4) { + Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?"); + return JIM_ERR; + } + if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &end) != JIM_OK) + return JIM_ERR; + } + else { + if (Jim_GetWide(interp, argv[1], &start) != JIM_OK || + Jim_GetWide(interp, argv[2], &end) != JIM_OK) + return JIM_ERR; + if (argc == 4 && Jim_GetWide(interp, argv[3], &step) != JIM_OK) + return JIM_ERR; + } + if ((len = JimRangeLen(start, end, step)) == -1) { + Jim_SetResultString(interp, "Invalid (infinite?) range specified", -1); + return JIM_ERR; + } + objPtr = Jim_NewListObj(interp, NULL, 0); + for (i = 0; i < len; i++) + ListAppendElement(objPtr, Jim_NewIntObj(interp, start + i * step)); + Jim_SetResult(interp, objPtr); + return JIM_OK; +} + + +static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + jim_wide min = 0, max = 0, len, maxMul; + + if (argc < 1 || argc > 3) { + Jim_WrongNumArgs(interp, 1, argv, "?min? max"); + return JIM_ERR; + } + if (argc == 1) { + max = JIM_WIDE_MAX; + } else if (argc == 2) { + if (Jim_GetWide(interp, argv[1], &max) != JIM_OK) + return JIM_ERR; + } else if (argc == 3) { + if (Jim_GetWide(interp, argv[1], &min) != JIM_OK || + Jim_GetWide(interp, argv[2], &max) != JIM_OK) + return JIM_ERR; + } + len = max-min; + if (len < 0) { + Jim_SetResultString(interp, "Invalid arguments (max < min)", -1); + return JIM_ERR; + } + maxMul = JIM_WIDE_MAX - (len ? (JIM_WIDE_MAX%len) : 0); + while (1) { + jim_wide r; + + JimRandomBytes(interp, &r, sizeof(jim_wide)); + if (r < 0 || r >= maxMul) continue; + r = (len == 0) ? 0 : r%len; + Jim_SetResultInt(interp, min+r); + return JIM_OK; + } +} + +static const struct { + const char *name; + Jim_CmdProc *cmdProc; +} Jim_CoreCommandsTable[] = { + {"alias", Jim_AliasCoreCommand}, + {"set", Jim_SetCoreCommand}, + {"unset", Jim_UnsetCoreCommand}, + {"puts", Jim_PutsCoreCommand}, + {"+", Jim_AddCoreCommand}, + {"*", Jim_MulCoreCommand}, + {"-", Jim_SubCoreCommand}, + {"/", Jim_DivCoreCommand}, + {"incr", Jim_IncrCoreCommand}, + {"while", Jim_WhileCoreCommand}, + {"loop", Jim_LoopCoreCommand}, + {"for", Jim_ForCoreCommand}, + {"foreach", Jim_ForeachCoreCommand}, + {"lmap", Jim_LmapCoreCommand}, + {"lassign", Jim_LassignCoreCommand}, + {"if", Jim_IfCoreCommand}, + {"switch", Jim_SwitchCoreCommand}, + {"list", Jim_ListCoreCommand}, + {"lindex", Jim_LindexCoreCommand}, + {"lset", Jim_LsetCoreCommand}, + {"lsearch", Jim_LsearchCoreCommand}, + {"llength", Jim_LlengthCoreCommand}, + {"lappend", Jim_LappendCoreCommand}, + {"linsert", Jim_LinsertCoreCommand}, + {"lreplace", Jim_LreplaceCoreCommand}, + {"lsort", Jim_LsortCoreCommand}, + {"append", Jim_AppendCoreCommand}, + {"debug", Jim_DebugCoreCommand}, + {"eval", Jim_EvalCoreCommand}, + {"uplevel", Jim_UplevelCoreCommand}, + {"expr", Jim_ExprCoreCommand}, + {"break", Jim_BreakCoreCommand}, + {"continue", Jim_ContinueCoreCommand}, + {"proc", Jim_ProcCoreCommand}, + {"concat", Jim_ConcatCoreCommand}, + {"return", Jim_ReturnCoreCommand}, + {"upvar", Jim_UpvarCoreCommand}, + {"global", Jim_GlobalCoreCommand}, + {"string", Jim_StringCoreCommand}, + {"time", Jim_TimeCoreCommand}, + {"exit", Jim_ExitCoreCommand}, + {"catch", Jim_CatchCoreCommand}, +#ifdef JIM_REFERENCES + {"ref", Jim_RefCoreCommand}, + {"getref", Jim_GetrefCoreCommand}, + {"setref", Jim_SetrefCoreCommand}, + {"finalize", Jim_FinalizeCoreCommand}, + {"collect", Jim_CollectCoreCommand}, +#endif + {"rename", Jim_RenameCoreCommand}, + {"dict", Jim_DictCoreCommand}, + {"subst", Jim_SubstCoreCommand}, + {"info", Jim_InfoCoreCommand}, + {"exists", Jim_ExistsCoreCommand}, + {"split", Jim_SplitCoreCommand}, + {"join", Jim_JoinCoreCommand}, + {"format", Jim_FormatCoreCommand}, + {"scan", Jim_ScanCoreCommand}, + {"error", Jim_ErrorCoreCommand}, + {"lrange", Jim_LrangeCoreCommand}, + {"lrepeat", Jim_LrepeatCoreCommand}, + {"env", Jim_EnvCoreCommand}, + {"source", Jim_SourceCoreCommand}, + {"lreverse", Jim_LreverseCoreCommand}, + {"range", Jim_RangeCoreCommand}, + {"rand", Jim_RandCoreCommand}, + {"tailcall", Jim_TailcallCoreCommand}, + {"local", Jim_LocalCoreCommand}, + {"upcall", Jim_UpcallCoreCommand}, + {"apply", Jim_ApplyCoreCommand}, + {NULL, NULL}, +}; + +void Jim_RegisterCoreCommands(Jim_Interp *interp) +{ + int i = 0; + + while (Jim_CoreCommandsTable[i].name != NULL) { + Jim_CreateCommand(interp, + Jim_CoreCommandsTable[i].name, Jim_CoreCommandsTable[i].cmdProc, NULL, NULL); + i++; + } +} + +void Jim_MakeErrorMessage(Jim_Interp *interp) +{ + Jim_Obj *argv[2]; + + argv[0] = Jim_NewStringObj(interp, "errorInfo", -1); + argv[1] = interp->result; + + Jim_EvalObjVector(interp, 2, argv); +} + +static void JimSetFailedEnumResult(Jim_Interp *interp, const char *arg, const char *badtype, + const char *prefix, const char *const *tablePtr, const char *name) +{ + int count; + char **tablePtrSorted; + int i; + + for (count = 0; tablePtr[count]; count++) { + } + + if (name == NULL) { + name = "option"; + } + + Jim_SetResultFormatted(interp, "%s%s \"%s\": must be ", badtype, name, arg); + tablePtrSorted = Jim_Alloc(sizeof(char *) * count); + memcpy(tablePtrSorted, tablePtr, sizeof(char *) * count); + qsort(tablePtrSorted, count, sizeof(char *), qsortCompareStringPointers); + for (i = 0; i < count; i++) { + if (i + 1 == count && count > 1) { + Jim_AppendString(interp, Jim_GetResult(interp), "or ", -1); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), prefix, tablePtrSorted[i], NULL); + if (i + 1 != count) { + Jim_AppendString(interp, Jim_GetResult(interp), ", ", -1); + } + } + Jim_Free(tablePtrSorted); +} + +int Jim_GetEnum(Jim_Interp *interp, Jim_Obj *objPtr, + const char *const *tablePtr, int *indexPtr, const char *name, int flags) +{ + const char *bad = "bad "; + const char *const *entryPtr = NULL; + int i; + int match = -1; + int arglen; + const char *arg = Jim_GetString(objPtr, &arglen); + + *indexPtr = -1; + + for (entryPtr = tablePtr, i = 0; *entryPtr != NULL; entryPtr++, i++) { + if (Jim_CompareStringImmediate(interp, objPtr, *entryPtr)) { + + *indexPtr = i; + return JIM_OK; + } + if (flags & JIM_ENUM_ABBREV) { + if (strncmp(arg, *entryPtr, arglen) == 0) { + if (*arg == '-' && arglen == 1) { + break; + } + if (match >= 0) { + bad = "ambiguous "; + goto ambiguous; + } + match = i; + } + } + } + + + if (match >= 0) { + *indexPtr = match; + return JIM_OK; + } + + ambiguous: + if (flags & JIM_ERRMSG) { + JimSetFailedEnumResult(interp, arg, bad, "", tablePtr, name); + } + return JIM_ERR; +} + +int Jim_FindByName(const char *name, const char * const array[], size_t len) +{ + int i; + + for (i = 0; i < (int)len; i++) { + if (array[i] && strcmp(array[i], name) == 0) { + return i; + } + } + return -1; +} + +int Jim_IsDict(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &dictObjType; +} + +int Jim_IsList(Jim_Obj *objPtr) +{ + return objPtr->typePtr == &listObjType; +} + +void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...) +{ + + int len = strlen(format); + int extra = 0; + int n = 0; + const char *params[5]; + char *buf; + va_list args; + int i; + + va_start(args, format); + + for (i = 0; i < len && n < 5; i++) { + int l; + + if (strncmp(format + i, "%s", 2) == 0) { + params[n] = va_arg(args, char *); + + l = strlen(params[n]); + } + else if (strncmp(format + i, "%#s", 3) == 0) { + Jim_Obj *objPtr = va_arg(args, Jim_Obj *); + + params[n] = Jim_GetString(objPtr, &l); + } + else { + if (format[i] == '%') { + i++; + } + continue; + } + n++; + extra += l; + } + + len += extra; + buf = Jim_Alloc(len + 1); + len = snprintf(buf, len + 1, format, params[0], params[1], params[2], params[3], params[4]); + + va_end(args); + + Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, len)); +} + + +#ifndef jim_ext_package +int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, int flags) +{ + return JIM_OK; +} +#endif +#ifndef jim_ext_aio +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *fhObj) +{ + Jim_SetResultString(interp, "aio not enabled", -1); + return NULL; +} +#endif + + +#include +#include + + +static int subcmd_null(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + + return JIM_OK; +} + +static const jim_subcmd_type dummy_subcmd = { + "dummy", NULL, subcmd_null, 0, 0, JIM_MODFLAG_HIDDEN +}; + +static void add_commands(Jim_Interp *interp, const jim_subcmd_type * ct, const char *sep) +{ + const char *s = ""; + + for (; ct->cmd; ct++) { + if (!(ct->flags & JIM_MODFLAG_HIDDEN)) { + Jim_AppendStrings(interp, Jim_GetResult(interp), s, ct->cmd, NULL); + s = sep; + } + } +} + +static void bad_subcmd(Jim_Interp *interp, const jim_subcmd_type * command_table, const char *type, + Jim_Obj *cmd, Jim_Obj *subcmd) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), ", ", type, + " command \"", Jim_String(subcmd), "\": should be ", NULL); + add_commands(interp, command_table, ", "); +} + +static void show_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * command_table, int argc, + Jim_Obj *const *argv) +{ + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Usage: \"", Jim_String(argv[0]), + " command ... \", where command is one of: ", NULL); + add_commands(interp, command_table, ", "); +} + +static void add_cmd_usage(Jim_Interp *interp, const jim_subcmd_type * ct, Jim_Obj *cmd) +{ + if (cmd) { + Jim_AppendStrings(interp, Jim_GetResult(interp), Jim_String(cmd), " ", NULL); + } + Jim_AppendStrings(interp, Jim_GetResult(interp), ct->cmd, NULL); + if (ct->args && *ct->args) { + Jim_AppendStrings(interp, Jim_GetResult(interp), " ", ct->args, NULL); + } +} + +static void set_wrong_args(Jim_Interp *interp, const jim_subcmd_type * command_table, Jim_Obj *subcmd) +{ + Jim_SetResultString(interp, "wrong # args: should be \"", -1); + add_cmd_usage(interp, command_table, subcmd); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); +} + +const jim_subcmd_type *Jim_ParseSubCmd(Jim_Interp *interp, const jim_subcmd_type * command_table, + int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct; + const jim_subcmd_type *partial = 0; + int cmdlen; + Jim_Obj *cmd; + const char *cmdstr; + const char *cmdname; + int help = 0; + + cmdname = Jim_String(argv[0]); + + if (argc < 2) { + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + Jim_AppendStrings(interp, Jim_GetResult(interp), "wrong # args: should be \"", cmdname, + " command ...\"\n", NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), "Use \"", cmdname, " -help ?command?\" for help", NULL); + return 0; + } + + cmd = argv[1]; + + + if (Jim_CompareStringImmediate(interp, cmd, "-help")) { + if (argc == 2) { + + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + help = 1; + + + cmd = argv[2]; + } + + + if (Jim_CompareStringImmediate(interp, cmd, "-commands")) { + + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + add_commands(interp, command_table, " "); + return &dummy_subcmd; + } + + cmdstr = Jim_GetString(cmd, &cmdlen); + + for (ct = command_table; ct->cmd; ct++) { + if (Jim_CompareStringImmediate(interp, cmd, ct->cmd)) { + + break; + } + if (strncmp(cmdstr, ct->cmd, cmdlen) == 0) { + if (partial) { + + if (help) { + + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + bad_subcmd(interp, command_table, "ambiguous", argv[0], argv[1 + help]); + return 0; + } + partial = ct; + } + continue; + } + + + if (partial && !ct->cmd) { + ct = partial; + } + + if (!ct->cmd) { + + if (help) { + + show_cmd_usage(interp, command_table, argc, argv); + return &dummy_subcmd; + } + bad_subcmd(interp, command_table, "unknown", argv[0], argv[1 + help]); + return 0; + } + + if (help) { + Jim_SetResultString(interp, "Usage: ", -1); + + add_cmd_usage(interp, ct, argv[0]); + return &dummy_subcmd; + } + + + if (argc - 2 < ct->minargs || (ct->maxargs >= 0 && argc - 2 > ct->maxargs)) { + Jim_SetResultString(interp, "wrong # args: should be \"", -1); + + add_cmd_usage(interp, ct, argv[0]); + Jim_AppendStrings(interp, Jim_GetResult(interp), "\"", NULL); + + return 0; + } + + + return ct; +} + +int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type * ct, int argc, Jim_Obj *const *argv) +{ + int ret = JIM_ERR; + + if (ct) { + if (ct->flags & JIM_MODFLAG_FULLARGV) { + ret = ct->function(interp, argc, argv); + } + else { + ret = ct->function(interp, argc - 2, argv + 2); + } + if (ret < 0) { + set_wrong_args(interp, ct, argv[0]); + ret = JIM_ERR; + } + } + return ret; +} + +int Jim_SubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + const jim_subcmd_type *ct = + Jim_ParseSubCmd(interp, (const jim_subcmd_type *)Jim_CmdPrivData(interp), argc, argv); + + return Jim_CallSubCmd(interp, ct, argc, argv); +} + +#include +#include +#include +#include +#include + + +int utf8_fromunicode(char *p, unsigned uc) +{ + if (uc <= 0x7f) { + *p = uc; + return 1; + } + else if (uc <= 0x7ff) { + *p++ = 0xc0 | ((uc & 0x7c0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 2; + } + else if (uc <= 0xffff) { + *p++ = 0xe0 | ((uc & 0xf000) >> 12); + *p++ = 0x80 | ((uc & 0xfc0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 3; + } + + else { + *p++ = 0xf0 | ((uc & 0x1c0000) >> 18); + *p++ = 0x80 | ((uc & 0x3f000) >> 12); + *p++ = 0x80 | ((uc & 0xfc0) >> 6); + *p = 0x80 | (uc & 0x3f); + return 4; + } +} + +#include +#include + + +#define JIM_INTEGER_SPACE 24 +#define MAX_FLOAT_WIDTH 320 + +Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) +{ + const char *span, *format, *formatEnd, *msg; + int numBytes = 0, objIndex = 0, gotXpg = 0, gotSequential = 0; + static const char * const mixedXPG = + "cannot mix \"%\" and \"%n$\" conversion specifiers"; + static const char * const badIndex[2] = { + "not enough arguments for all format specifiers", + "\"%n$\" argument index out of range" + }; + int formatLen; + Jim_Obj *resultPtr; + + char *num_buffer = NULL; + int num_buffer_size = 0; + + span = format = Jim_GetString(fmtObjPtr, &formatLen); + formatEnd = format + formatLen; + resultPtr = Jim_NewEmptyStringObj(interp); + + while (format != formatEnd) { + char *end; + int gotMinus, sawFlag; + int gotPrecision, useShort; + long width, precision; + int newXpg; + int ch; + int step; + int doubleType; + char pad = ' '; + char spec[2*JIM_INTEGER_SPACE + 12]; + char *p; + + int formatted_chars; + int formatted_bytes; + const char *formatted_buf; + + step = utf8_tounicode(format, &ch); + format += step; + if (ch != '%') { + numBytes += step; + continue; + } + if (numBytes) { + Jim_AppendString(interp, resultPtr, span, numBytes); + numBytes = 0; + } + + + step = utf8_tounicode(format, &ch); + if (ch == '%') { + span = format; + numBytes = step; + format += step; + continue; + } + + + newXpg = 0; + if (isdigit(ch)) { + int position = strtoul(format, &end, 10); + if (*end == '$') { + newXpg = 1; + objIndex = position - 1; + format = end + 1; + step = utf8_tounicode(format, &ch); + } + } + if (newXpg) { + if (gotSequential) { + msg = mixedXPG; + goto errorMsg; + } + gotXpg = 1; + } else { + if (gotXpg) { + msg = mixedXPG; + goto errorMsg; + } + gotSequential = 1; + } + if ((objIndex < 0) || (objIndex >= objc)) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + + p = spec; + *p++ = '%'; + + gotMinus = 0; + sawFlag = 1; + do { + switch (ch) { + case '-': + gotMinus = 1; + break; + case '0': + pad = ch; + break; + case ' ': + case '+': + case '#': + break; + default: + sawFlag = 0; + continue; + } + *p++ = ch; + format += step; + step = utf8_tounicode(format, &ch); + } while (sawFlag); + + + width = 0; + if (isdigit(ch)) { + width = strtoul(format, &end, 10); + format = end; + step = utf8_tounicode(format, &ch); + } else if (ch == '*') { + if (objIndex >= objc - 1) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + if (Jim_GetLong(interp, objv[objIndex], &width) != JIM_OK) { + goto error; + } + if (width < 0) { + width = -width; + if (!gotMinus) { + *p++ = '-'; + gotMinus = 1; + } + } + objIndex++; + format += step; + step = utf8_tounicode(format, &ch); + } + + + gotPrecision = precision = 0; + if (ch == '.') { + gotPrecision = 1; + format += step; + step = utf8_tounicode(format, &ch); + } + if (isdigit(ch)) { + precision = strtoul(format, &end, 10); + format = end; + step = utf8_tounicode(format, &ch); + } else if (ch == '*') { + if (objIndex >= objc - 1) { + msg = badIndex[gotXpg]; + goto errorMsg; + } + if (Jim_GetLong(interp, objv[objIndex], &precision) != JIM_OK) { + goto error; + } + + + if (precision < 0) { + precision = 0; + } + objIndex++; + format += step; + step = utf8_tounicode(format, &ch); + } + + + useShort = 0; + if (ch == 'h') { + useShort = 1; + format += step; + step = utf8_tounicode(format, &ch); + } else if (ch == 'l') { + + format += step; + step = utf8_tounicode(format, &ch); + if (ch == 'l') { + format += step; + step = utf8_tounicode(format, &ch); + } + } + + format += step; + span = format; + + + if (ch == 'i') { + ch = 'd'; + } + + doubleType = 0; + + switch (ch) { + case '\0': + msg = "format string ended in middle of field specifier"; + goto errorMsg; + case 's': { + formatted_buf = Jim_GetString(objv[objIndex], &formatted_bytes); + formatted_chars = Jim_Utf8Length(interp, objv[objIndex]); + if (gotPrecision && (precision < formatted_chars)) { + + formatted_chars = precision; + formatted_bytes = utf8_index(formatted_buf, precision); + } + break; + } + case 'c': { + jim_wide code; + + if (Jim_GetWide(interp, objv[objIndex], &code) != JIM_OK) { + goto error; + } + + formatted_bytes = utf8_getchars(spec, code); + formatted_buf = spec; + formatted_chars = 1; + break; + } + case 'b': { + unsigned jim_wide w; + int length; + int i; + int j; + + if (Jim_GetWide(interp, objv[objIndex], (jim_wide *)&w) != JIM_OK) { + goto error; + } + length = sizeof(w) * 8; + + + + if (num_buffer_size < length + 1) { + num_buffer_size = length + 1; + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); + } + + j = 0; + for (i = length; i > 0; ) { + i--; + if (w & ((unsigned jim_wide)1 << i)) { + num_buffer[j++] = '1'; + } + else if (j || i == 0) { + num_buffer[j++] = '0'; + } + } + num_buffer[j] = 0; + formatted_chars = formatted_bytes = j; + formatted_buf = num_buffer; + break; + } + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + doubleType = 1; + + case 'd': + case 'u': + case 'o': + case 'x': + case 'X': { + jim_wide w; + double d; + int length; + + + if (width) { + p += sprintf(p, "%ld", width); + } + if (gotPrecision) { + p += sprintf(p, ".%ld", precision); + } + + + if (doubleType) { + if (Jim_GetDouble(interp, objv[objIndex], &d) != JIM_OK) { + goto error; + } + length = MAX_FLOAT_WIDTH; + } + else { + if (Jim_GetWide(interp, objv[objIndex], &w) != JIM_OK) { + goto error; + } + length = JIM_INTEGER_SPACE; + if (useShort) { + if (ch == 'd') { + w = (short)w; + } + else { + w = (unsigned short)w; + } + } + *p++ = 'l'; +#ifdef HAVE_LONG_LONG + if (sizeof(long long) == sizeof(jim_wide)) { + *p++ = 'l'; + } +#endif + } + + *p++ = (char) ch; + *p = '\0'; + + + if (width > length) { + length = width; + } + if (gotPrecision) { + length += precision; + } + + + if (num_buffer_size < length + 1) { + num_buffer_size = length + 1; + num_buffer = Jim_Realloc(num_buffer, num_buffer_size); + } + + if (doubleType) { + snprintf(num_buffer, length + 1, spec, d); + } + else { + formatted_bytes = snprintf(num_buffer, length + 1, spec, w); + } + formatted_chars = formatted_bytes = strlen(num_buffer); + formatted_buf = num_buffer; + break; + } + + default: { + + spec[0] = ch; + spec[1] = '\0'; + Jim_SetResultFormatted(interp, "bad field specifier \"%s\"", spec); + goto error; + } + } + + if (!gotMinus) { + while (formatted_chars < width) { + Jim_AppendString(interp, resultPtr, &pad, 1); + formatted_chars++; + } + } + + Jim_AppendString(interp, resultPtr, formatted_buf, formatted_bytes); + + while (formatted_chars < width) { + Jim_AppendString(interp, resultPtr, &pad, 1); + formatted_chars++; + } + + objIndex += gotSequential; + } + if (numBytes) { + Jim_AppendString(interp, resultPtr, span, numBytes); + } + + Jim_Free(num_buffer); + return resultPtr; + + errorMsg: + Jim_SetResultString(interp, msg, -1); + error: + Jim_FreeNewObj(interp, resultPtr); + Jim_Free(num_buffer); + return NULL; +} + + +#if defined(JIM_REGEXP) +#include +#include +#include +#include + + + +#define REG_MAX_PAREN 100 + + + +#define END 0 +#define BOL 1 +#define EOL 2 +#define ANY 3 +#define ANYOF 4 +#define ANYBUT 5 +#define BRANCH 6 +#define BACK 7 +#define EXACTLY 8 +#define NOTHING 9 +#define REP 10 +#define REPMIN 11 +#define REPX 12 +#define REPXMIN 13 + +#define WORDA 15 +#define WORDZ 16 + +#define OPENNC 1000 +#define OPEN 1001 + + + + +#define CLOSENC 2000 +#define CLOSE 2001 +#define CLOSE_END (CLOSE+REG_MAX_PAREN) + +#define REG_MAGIC 0xFADED00D + + +#define OP(preg, p) (preg->program[p]) +#define NEXT(preg, p) (preg->program[p + 1]) +#define OPERAND(p) ((p) + 2) + + + + +#define FAIL(R,M) { (R)->err = (M); return (M); } +#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{') +#define META "^$.[()|?{+*" + +#define HASWIDTH 1 +#define SIMPLE 2 +#define SPSTART 4 +#define WORST 0 + +#define MAX_REP_COUNT 1000000 + +static int reg(regex_t *preg, int paren , int *flagp ); +static int regpiece(regex_t *preg, int *flagp ); +static int regbranch(regex_t *preg, int *flagp ); +static int regatom(regex_t *preg, int *flagp ); +static int regnode(regex_t *preg, int op ); +static int regnext(regex_t *preg, int p ); +static void regc(regex_t *preg, int b ); +static int reginsert(regex_t *preg, int op, int size, int opnd ); +static void regtail(regex_t *preg, int p, int val); +static void regoptail(regex_t *preg, int p, int val ); +static int regopsize(regex_t *preg, int p ); + +static int reg_range_find(const int *string, int c); +static const char *str_find(const char *string, int c, int nocase); +static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase); + + +#ifdef DEBUG +static int regnarrate = 0; +static void regdump(regex_t *preg); +static const char *regprop( int op ); +#endif + + +static int str_int_len(const int *seq) +{ + int n = 0; + while (*seq++) { + n++; + } + return n; +} + +int regcomp(regex_t *preg, const char *exp, int cflags) +{ + int scan; + int longest; + unsigned len; + int flags; + +#ifdef DEBUG + fprintf(stderr, "Compiling: '%s'\n", exp); +#endif + memset(preg, 0, sizeof(*preg)); + + if (exp == NULL) + FAIL(preg, REG_ERR_NULL_ARGUMENT); + + + preg->cflags = cflags; + preg->regparse = exp; + + + preg->proglen = (strlen(exp) + 1) * 5; + preg->program = malloc(preg->proglen * sizeof(int)); + if (preg->program == NULL) + FAIL(preg, REG_ERR_NOMEM); + + regc(preg, REG_MAGIC); + if (reg(preg, 0, &flags) == 0) { + return preg->err; + } + + + if (preg->re_nsub >= REG_MAX_PAREN) + FAIL(preg,REG_ERR_TOO_BIG); + + + preg->regstart = 0; + preg->reganch = 0; + preg->regmust = 0; + preg->regmlen = 0; + scan = 1; + if (OP(preg, regnext(preg, scan)) == END) { + scan = OPERAND(scan); + + + if (OP(preg, scan) == EXACTLY) { + preg->regstart = preg->program[OPERAND(scan)]; + } + else if (OP(preg, scan) == BOL) + preg->reganch++; + + if (flags&SPSTART) { + longest = 0; + len = 0; + for (; scan != 0; scan = regnext(preg, scan)) { + if (OP(preg, scan) == EXACTLY) { + int plen = str_int_len(preg->program + OPERAND(scan)); + if (plen >= len) { + longest = OPERAND(scan); + len = plen; + } + } + } + preg->regmust = longest; + preg->regmlen = len; + } + } + +#ifdef DEBUG + regdump(preg); +#endif + + return 0; +} + +static int reg(regex_t *preg, int paren , int *flagp ) +{ + int ret; + int br; + int ender; + int parno = 0; + int flags; + + *flagp = HASWIDTH; + + + if (paren) { + if (preg->regparse[0] == '?' && preg->regparse[1] == ':') { + + preg->regparse += 2; + parno = -1; + } + else { + parno = ++preg->re_nsub; + } + ret = regnode(preg, OPEN+parno); + } else + ret = 0; + + + br = regbranch(preg, &flags); + if (br == 0) + return 0; + if (ret != 0) + regtail(preg, ret, br); + else + ret = br; + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + while (*preg->regparse == '|') { + preg->regparse++; + br = regbranch(preg, &flags); + if (br == 0) + return 0; + regtail(preg, ret, br); + if (!(flags&HASWIDTH)) + *flagp &= ~HASWIDTH; + *flagp |= flags&SPSTART; + } + + + ender = regnode(preg, (paren) ? CLOSE+parno : END); + regtail(preg, ret, ender); + + + for (br = ret; br != 0; br = regnext(preg, br)) + regoptail(preg, br, ender); + + + if (paren && *preg->regparse++ != ')') { + preg->err = REG_ERR_UNMATCHED_PAREN; + return 0; + } else if (!paren && *preg->regparse != '\0') { + if (*preg->regparse == ')') { + preg->err = REG_ERR_UNMATCHED_PAREN; + return 0; + } else { + preg->err = REG_ERR_JUNK_ON_END; + return 0; + } + } + + return(ret); +} + +static int regbranch(regex_t *preg, int *flagp ) +{ + int ret; + int chain; + int latest; + int flags; + + *flagp = WORST; + + ret = regnode(preg, BRANCH); + chain = 0; + while (*preg->regparse != '\0' && *preg->regparse != ')' && + *preg->regparse != '|') { + latest = regpiece(preg, &flags); + if (latest == 0) + return 0; + *flagp |= flags&HASWIDTH; + if (chain == 0) { + *flagp |= flags&SPSTART; + } + else { + regtail(preg, chain, latest); + } + chain = latest; + } + if (chain == 0) + (void) regnode(preg, NOTHING); + + return(ret); +} + +static int regpiece(regex_t *preg, int *flagp) +{ + int ret; + char op; + int next; + int flags; + int min; + int max; + + ret = regatom(preg, &flags); + if (ret == 0) + return 0; + + op = *preg->regparse; + if (!ISMULT(op)) { + *flagp = flags; + return(ret); + } + + if (!(flags&HASWIDTH) && op != '?') { + preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY; + return 0; + } + + + if (op == '{') { + char *end; + + min = strtoul(preg->regparse + 1, &end, 10); + if (end == preg->regparse + 1) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + if (*end == '}') { + max = min; + } + else { + preg->regparse = end; + max = strtoul(preg->regparse + 1, &end, 10); + if (*end != '}') { + preg->err = REG_ERR_UNMATCHED_BRACES; + return 0; + } + } + if (end == preg->regparse + 1) { + max = MAX_REP_COUNT; + } + else if (max < min || max >= 100) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + if (min >= 100) { + preg->err = REG_ERR_BAD_COUNT; + return 0; + } + + preg->regparse = strchr(preg->regparse, '}'); + } + else { + min = (op == '+'); + max = (op == '?' ? 1 : MAX_REP_COUNT); + } + + if (preg->regparse[1] == '?') { + preg->regparse++; + next = reginsert(preg, flags & SIMPLE ? REPMIN : REPXMIN, 5, ret); + } + else { + next = reginsert(preg, flags & SIMPLE ? REP: REPX, 5, ret); + } + preg->program[ret + 2] = max; + preg->program[ret + 3] = min; + preg->program[ret + 4] = 0; + + *flagp = (min) ? (WORST|HASWIDTH) : (WORST|SPSTART); + + if (!(flags & SIMPLE)) { + int back = regnode(preg, BACK); + regtail(preg, back, ret); + regtail(preg, next, back); + } + + preg->regparse++; + if (ISMULT(*preg->regparse)) { + preg->err = REG_ERR_NESTED_COUNT; + return 0; + } + + return ret; +} + +static void reg_addrange(regex_t *preg, int lower, int upper) +{ + if (lower > upper) { + reg_addrange(preg, upper, lower); + } + + regc(preg, upper - lower + 1); + regc(preg, lower); +} + +static void reg_addrange_str(regex_t *preg, const char *str) +{ + while (*str) { + reg_addrange(preg, *str, *str); + str++; + } +} + +static int reg_utf8_tounicode_case(const char *s, int *uc, int upper) +{ + int l = utf8_tounicode(s, uc); + if (upper) { + *uc = utf8_upper(*uc); + } + return l; +} + +static int hexdigitval(int c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + +static int parse_hex(const char *s, int n, int *uc) +{ + int val = 0; + int k; + + for (k = 0; k < n; k++) { + int c = hexdigitval(*s++); + if (c == -1) { + break; + } + val = (val << 4) | c; + } + if (k) { + *uc = val; + } + return k; +} + +static int reg_decode_escape(const char *s, int *ch) +{ + int n; + const char *s0 = s; + + *ch = *s++; + + switch (*ch) { + case 'b': *ch = '\b'; break; + case 'e': *ch = 27; break; + case 'f': *ch = '\f'; break; + case 'n': *ch = '\n'; break; + case 'r': *ch = '\r'; break; + case 't': *ch = '\t'; break; + case 'v': *ch = '\v'; break; + case 'u': + if (*s == '{') { + + n = parse_hex(s + 1, 6, ch); + if (n > 0 && s[n + 1] == '}' && *ch >= 0 && *ch <= 0x1fffff) { + s += n + 2; + } + else { + + *ch = 'u'; + } + } + else if ((n = parse_hex(s, 4, ch)) > 0) { + s += n; + } + break; + case 'U': + if ((n = parse_hex(s, 8, ch)) > 0) { + s += n; + } + break; + case 'x': + if ((n = parse_hex(s, 2, ch)) > 0) { + s += n; + } + break; + case '\0': + s--; + *ch = '\\'; + break; + } + return s - s0; +} + +static int regatom(regex_t *preg, int *flagp) +{ + int ret; + int flags; + int nocase = (preg->cflags & REG_ICASE); + + int ch; + int n = reg_utf8_tounicode_case(preg->regparse, &ch, nocase); + + *flagp = WORST; + + preg->regparse += n; + switch (ch) { + + case '^': + ret = regnode(preg, BOL); + break; + case '$': + ret = regnode(preg, EOL); + break; + case '.': + ret = regnode(preg, ANY); + *flagp |= HASWIDTH|SIMPLE; + break; + case '[': { + const char *pattern = preg->regparse; + + if (*pattern == '^') { + ret = regnode(preg, ANYBUT); + pattern++; + } else + ret = regnode(preg, ANYOF); + + + if (*pattern == ']' || *pattern == '-') { + reg_addrange(preg, *pattern, *pattern); + pattern++; + } + + while (*pattern && *pattern != ']') { + + int start; + int end; + + pattern += reg_utf8_tounicode_case(pattern, &start, nocase); + if (start == '\\') { + pattern += reg_decode_escape(pattern, &start); + if (start == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + if (pattern[0] == '-' && pattern[1] && pattern[1] != ']') { + + pattern += utf8_tounicode(pattern, &end); + pattern += reg_utf8_tounicode_case(pattern, &end, nocase); + if (end == '\\') { + pattern += reg_decode_escape(pattern, &end); + if (end == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + + reg_addrange(preg, start, end); + continue; + } + if (start == '[') { + if (strncmp(pattern, ":alpha:]", 8) == 0) { + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + pattern += 8; + continue; + } + if (strncmp(pattern, ":alnum:]", 8) == 0) { + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + reg_addrange(preg, '0', '9'); + pattern += 8; + continue; + } + if (strncmp(pattern, ":space:]", 8) == 0) { + reg_addrange_str(preg, " \t\r\n\f\v"); + pattern += 8; + continue; + } + } + + reg_addrange(preg, start, start); + } + regc(preg, '\0'); + + if (*pattern) { + pattern++; + } + preg->regparse = pattern; + + *flagp |= HASWIDTH|SIMPLE; + } + break; + case '(': + ret = reg(preg, 1, &flags); + if (ret == 0) + return 0; + *flagp |= flags&(HASWIDTH|SPSTART); + break; + case '\0': + case '|': + case ')': + preg->err = REG_ERR_INTERNAL; + return 0; + case '?': + case '+': + case '*': + case '{': + preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING; + return 0; + case '\\': + switch (*preg->regparse++) { + case '\0': + preg->err = REG_ERR_TRAILING_BACKSLASH; + return 0; + case '<': + case 'm': + ret = regnode(preg, WORDA); + break; + case '>': + case 'M': + ret = regnode(preg, WORDZ); + break; + case 'd': + ret = regnode(preg, ANYOF); + reg_addrange(preg, '0', '9'); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + case 'w': + ret = regnode(preg, ANYOF); + if ((preg->cflags & REG_ICASE) == 0) { + reg_addrange(preg, 'a', 'z'); + } + reg_addrange(preg, 'A', 'Z'); + reg_addrange(preg, '0', '9'); + reg_addrange(preg, '_', '_'); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + case 's': + ret = regnode(preg, ANYOF); + reg_addrange_str(preg," \t\r\n\f\v"); + regc(preg, '\0'); + *flagp |= HASWIDTH|SIMPLE; + break; + + default: + + + preg->regparse--; + goto de_fault; + } + break; + de_fault: + default: { + int added = 0; + + + preg->regparse -= n; + + ret = regnode(preg, EXACTLY); + + + + while (*preg->regparse && strchr(META, *preg->regparse) == NULL) { + n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE)); + if (ch == '\\' && preg->regparse[n]) { + if (strchr("<>mMwds", preg->regparse[n])) { + + break; + } + n += reg_decode_escape(preg->regparse + n, &ch); + if (ch == 0) { + preg->err = REG_ERR_NULL_CHAR; + return 0; + } + } + + + if (ISMULT(preg->regparse[n])) { + + if (added) { + + break; + } + + regc(preg, ch); + added++; + preg->regparse += n; + break; + } + + + regc(preg, ch); + added++; + preg->regparse += n; + } + regc(preg, '\0'); + + *flagp |= HASWIDTH; + if (added == 1) + *flagp |= SIMPLE; + break; + } + break; + } + + return(ret); +} + +static void reg_grow(regex_t *preg, int n) +{ + if (preg->p + n >= preg->proglen) { + preg->proglen = (preg->p + n) * 2; + preg->program = realloc(preg->program, preg->proglen * sizeof(int)); + } +} + + +static int regnode(regex_t *preg, int op) +{ + reg_grow(preg, 2); + + + preg->program[preg->p++] = op; + preg->program[preg->p++] = 0; + + + return preg->p - 2; +} + +static void regc(regex_t *preg, int b ) +{ + reg_grow(preg, 1); + preg->program[preg->p++] = b; +} + +static int reginsert(regex_t *preg, int op, int size, int opnd ) +{ + reg_grow(preg, size); + + + memmove(preg->program + opnd + size, preg->program + opnd, sizeof(int) * (preg->p - opnd)); + + memset(preg->program + opnd, 0, sizeof(int) * size); + + preg->program[opnd] = op; + + preg->p += size; + + return opnd + size; +} + +static void regtail(regex_t *preg, int p, int val) +{ + int scan; + int temp; + int offset; + + + scan = p; + for (;;) { + temp = regnext(preg, scan); + if (temp == 0) + break; + scan = temp; + } + + if (OP(preg, scan) == BACK) + offset = scan - val; + else + offset = val - scan; + + preg->program[scan + 1] = offset; +} + + +static void regoptail(regex_t *preg, int p, int val ) +{ + + if (p != 0 && OP(preg, p) == BRANCH) { + regtail(preg, OPERAND(p), val); + } +} + + +static int regtry(regex_t *preg, const char *string ); +static int regmatch(regex_t *preg, int prog); +static int regrepeat(regex_t *preg, int p, int max); + +int regexec(regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) +{ + const char *s; + int scan; + + + if (preg == NULL || preg->program == NULL || string == NULL) { + return REG_ERR_NULL_ARGUMENT; + } + + + if (*preg->program != REG_MAGIC) { + return REG_ERR_CORRUPTED; + } + +#ifdef DEBUG + fprintf(stderr, "regexec: %s\n", string); + regdump(preg); +#endif + + preg->eflags = eflags; + preg->pmatch = pmatch; + preg->nmatch = nmatch; + preg->start = string; + + + for (scan = OPERAND(1); scan != 0; scan += regopsize(preg, scan)) { + int op = OP(preg, scan); + if (op == END) + break; + if (op == REPX || op == REPXMIN) + preg->program[scan + 4] = 0; + } + + + if (preg->regmust != 0) { + s = string; + while ((s = str_find(s, preg->program[preg->regmust], preg->cflags & REG_ICASE)) != NULL) { + if (prefix_cmp(preg->program + preg->regmust, preg->regmlen, s, preg->cflags & REG_ICASE) >= 0) { + break; + } + s++; + } + if (s == NULL) + return REG_NOMATCH; + } + + + preg->regbol = string; + + + if (preg->reganch) { + if (eflags & REG_NOTBOL) { + + goto nextline; + } + while (1) { + if (regtry(preg, string)) { + return REG_NOERROR; + } + if (*string) { +nextline: + if (preg->cflags & REG_NEWLINE) { + + string = strchr(string, '\n'); + if (string) { + preg->regbol = ++string; + continue; + } + } + } + return REG_NOMATCH; + } + } + + + s = string; + if (preg->regstart != '\0') { + + while ((s = str_find(s, preg->regstart, preg->cflags & REG_ICASE)) != NULL) { + if (regtry(preg, s)) + return REG_NOERROR; + s++; + } + } + else + + while (1) { + if (regtry(preg, s)) + return REG_NOERROR; + if (*s == '\0') { + break; + } + else { + int c; + s += utf8_tounicode(s, &c); + } + } + + + return REG_NOMATCH; +} + + +static int regtry( regex_t *preg, const char *string ) +{ + int i; + + preg->reginput = string; + + for (i = 0; i < preg->nmatch; i++) { + preg->pmatch[i].rm_so = -1; + preg->pmatch[i].rm_eo = -1; + } + if (regmatch(preg, 1)) { + preg->pmatch[0].rm_so = string - preg->start; + preg->pmatch[0].rm_eo = preg->reginput - preg->start; + return(1); + } else + return(0); +} + +static int prefix_cmp(const int *prog, int proglen, const char *string, int nocase) +{ + const char *s = string; + while (proglen && *s) { + int ch; + int n = reg_utf8_tounicode_case(s, &ch, nocase); + if (ch != *prog) { + return -1; + } + prog++; + s += n; + proglen--; + } + if (proglen == 0) { + return s - string; + } + return -1; +} + +static int reg_range_find(const int *range, int c) +{ + while (*range) { + + if (c >= range[1] && c <= (range[0] + range[1] - 1)) { + return 1; + } + range += 2; + } + return 0; +} + +static const char *str_find(const char *string, int c, int nocase) +{ + if (nocase) { + + c = utf8_upper(c); + } + while (*string) { + int ch; + int n = reg_utf8_tounicode_case(string, &ch, nocase); + if (c == ch) { + return string; + } + string += n; + } + return NULL; +} + +static int reg_iseol(regex_t *preg, int ch) +{ + if (preg->cflags & REG_NEWLINE) { + return ch == '\0' || ch == '\n'; + } + else { + return ch == '\0'; + } +} + +static int regmatchsimplerepeat(regex_t *preg, int scan, int matchmin) +{ + int nextch = '\0'; + const char *save; + int no; + int c; + + int max = preg->program[scan + 2]; + int min = preg->program[scan + 3]; + int next = regnext(preg, scan); + + if (OP(preg, next) == EXACTLY) { + nextch = preg->program[OPERAND(next)]; + } + save = preg->reginput; + no = regrepeat(preg, scan + 5, max); + if (no < min) { + return 0; + } + if (matchmin) { + + max = no; + no = min; + } + + while (1) { + if (matchmin) { + if (no > max) { + break; + } + } + else { + if (no < min) { + break; + } + } + preg->reginput = save + utf8_index(save, no); + reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); + + if (reg_iseol(preg, nextch) || c == nextch) { + if (regmatch(preg, next)) { + return(1); + } + } + if (matchmin) { + + no++; + } + else { + + no--; + } + } + return(0); +} + +static int regmatchrepeat(regex_t *preg, int scan, int matchmin) +{ + int *scanpt = preg->program + scan; + + int max = scanpt[2]; + int min = scanpt[3]; + + + if (scanpt[4] < min) { + + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + return 0; + } + if (scanpt[4] > max) { + return 0; + } + + if (matchmin) { + + if (regmatch(preg, regnext(preg, scan))) { + return 1; + } + + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + return 0; + } + + if (scanpt[4] < max) { + scanpt[4]++; + if (regmatch(preg, scan + 5)) { + return 1; + } + scanpt[4]--; + } + + return regmatch(preg, regnext(preg, scan)); +} + + +static int regmatch(regex_t *preg, int prog) +{ + int scan; + int next; + const char *save; + + scan = prog; + +#ifdef DEBUG + if (scan != 0 && regnarrate) + fprintf(stderr, "%s(\n", regprop(scan)); +#endif + while (scan != 0) { + int n; + int c; +#ifdef DEBUG + if (regnarrate) { + fprintf(stderr, "%3d: %s...\n", scan, regprop(OP(preg, scan))); + } +#endif + next = regnext(preg, scan); + n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE)); + + switch (OP(preg, scan)) { + case BOL: + if (preg->reginput != preg->regbol) + return(0); + break; + case EOL: + if (!reg_iseol(preg, c)) { + return(0); + } + break; + case WORDA: + + if ((!isalnum(UCHAR(c))) && c != '_') + return(0); + + if (preg->reginput > preg->regbol && + (isalnum(UCHAR(preg->reginput[-1])) || preg->reginput[-1] == '_')) + return(0); + break; + case WORDZ: + + if (preg->reginput > preg->regbol) { + + if (reg_iseol(preg, c) || !isalnum(UCHAR(c)) || c != '_') { + c = preg->reginput[-1]; + + if (isalnum(UCHAR(c)) || c == '_') { + break; + } + } + } + + return(0); + + case ANY: + if (reg_iseol(preg, c)) + return 0; + preg->reginput += n; + break; + case EXACTLY: { + int opnd; + int len; + int slen; + + opnd = OPERAND(scan); + len = str_int_len(preg->program + opnd); + + slen = prefix_cmp(preg->program + opnd, len, preg->reginput, preg->cflags & REG_ICASE); + if (slen < 0) { + return(0); + } + preg->reginput += slen; + } + break; + case ANYOF: + if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) == 0) { + return(0); + } + preg->reginput += n; + break; + case ANYBUT: + if (reg_iseol(preg, c) || reg_range_find(preg->program + OPERAND(scan), c) != 0) { + return(0); + } + preg->reginput += n; + break; + case NOTHING: + break; + case BACK: + break; + case BRANCH: + if (OP(preg, next) != BRANCH) + next = OPERAND(scan); + else { + do { + save = preg->reginput; + if (regmatch(preg, OPERAND(scan))) { + return(1); + } + preg->reginput = save; + scan = regnext(preg, scan); + } while (scan != 0 && OP(preg, scan) == BRANCH); + return(0); + + } + break; + case REP: + case REPMIN: + return regmatchsimplerepeat(preg, scan, OP(preg, scan) == REPMIN); + + case REPX: + case REPXMIN: + return regmatchrepeat(preg, scan, OP(preg, scan) == REPXMIN); + + case END: + return 1; + + case OPENNC: + case CLOSENC: + return regmatch(preg, next); + + default: + if (OP(preg, scan) >= OPEN+1 && OP(preg, scan) < CLOSE_END) { + save = preg->reginput; + if (regmatch(preg, next)) { + if (OP(preg, scan) < CLOSE) { + int no = OP(preg, scan) - OPEN; + if (no < preg->nmatch && preg->pmatch[no].rm_so == -1) { + preg->pmatch[no].rm_so = save - preg->start; + } + } + else { + int no = OP(preg, scan) - CLOSE; + if (no < preg->nmatch && preg->pmatch[no].rm_eo == -1) { + preg->pmatch[no].rm_eo = save - preg->start; + } + } + return(1); + } + return(0); + } + return REG_ERR_INTERNAL; + } + + scan = next; + } + + return REG_ERR_INTERNAL; +} + +static int regrepeat(regex_t *preg, int p, int max) +{ + int count = 0; + const char *scan; + int opnd; + int ch; + int n; + + scan = preg->reginput; + opnd = OPERAND(p); + switch (OP(preg, p)) { + case ANY: + + while (!reg_iseol(preg, *scan) && count < max) { + count++; + scan++; + } + break; + case EXACTLY: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (preg->program[opnd] != ch) { + break; + } + count++; + scan += n; + } + break; + case ANYOF: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) == 0) { + break; + } + count++; + scan += n; + } + break; + case ANYBUT: + while (count < max) { + n = reg_utf8_tounicode_case(scan, &ch, preg->cflags & REG_ICASE); + if (reg_iseol(preg, ch) || reg_range_find(preg->program + opnd, ch) != 0) { + break; + } + count++; + scan += n; + } + break; + default: + preg->err = REG_ERR_INTERNAL; + count = 0; + break; + } + preg->reginput = scan; + + return(count); +} + +static int regnext(regex_t *preg, int p ) +{ + int offset; + + offset = NEXT(preg, p); + + if (offset == 0) + return 0; + + if (OP(preg, p) == BACK) + return(p-offset); + else + return(p+offset); +} + +static int regopsize(regex_t *preg, int p ) +{ + + switch (OP(preg, p)) { + case REP: + case REPMIN: + case REPX: + case REPXMIN: + return 5; + + case ANYOF: + case ANYBUT: + case EXACTLY: { + int s = p + 2; + while (preg->program[s++]) { + } + return s - p; + } + } + return 2; +} + + +size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size) +{ + static const char *error_strings[] = { + "success", + "no match", + "bad pattern", + "null argument", + "unknown error", + "too big", + "out of memory", + "too many ()", + "parentheses () not balanced", + "braces {} not balanced", + "invalid repetition count(s)", + "extra characters", + "*+ of empty atom", + "nested count", + "internal error", + "count follows nothing", + "trailing backslash", + "corrupted program", + "contains null char", + }; + const char *err; + + if (errcode < 0 || errcode >= REG_ERR_NUM) { + err = "Bad error code"; + } + else { + err = error_strings[errcode]; + } + + return snprintf(errbuf, errbuf_size, "%s", err); +} + +void regfree(regex_t *preg) +{ + free(preg->program); +} + +#endif + +#if defined(_WIN32) || defined(WIN32) +#ifndef STRICT +#define STRICT +#endif +#define WIN32_LEAN_AND_MEAN +#include + +#if defined(HAVE_DLOPEN_COMPAT) +void *dlopen(const char *path, int mode) +{ + JIM_NOTUSED(mode); + + return (void *)LoadLibraryA(path); +} + +int dlclose(void *handle) +{ + FreeLibrary((HANDLE)handle); + return 0; +} + +void *dlsym(void *handle, const char *symbol) +{ + return GetProcAddress((HMODULE)handle, symbol); +} + +char *dlerror(void) +{ + static char msg[121]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), + LANG_NEUTRAL, msg, sizeof(msg) - 1, NULL); + return msg; +} +#endif + +#ifdef _MSC_VER + +#include + + +int gettimeofday(struct timeval *tv, void *unused) +{ + struct _timeb tb; + + _ftime(&tb); + tv->tv_sec = tb.time; + tv->tv_usec = tb.millitm * 1000; + + return 0; +} + + +DIR *opendir(const char *name) +{ + DIR *dir = 0; + + if (name && name[0]) { + size_t base_length = strlen(name); + const char *all = + strchr("/\\", name[base_length - 1]) ? "*" : "/*"; + + if ((dir = (DIR *) Jim_Alloc(sizeof *dir)) != 0 && + (dir->name = (char *)Jim_Alloc(base_length + strlen(all) + 1)) != 0) { + strcat(strcpy(dir->name, name), all); + + if ((dir->handle = (long)_findfirst(dir->name, &dir->info)) != -1) + dir->result.d_name = 0; + else { + Jim_Free(dir->name); + Jim_Free(dir); + dir = 0; + } + } + else { + Jim_Free(dir); + dir = 0; + errno = ENOMEM; + } + } + else { + errno = EINVAL; + } + return dir; +} + +int closedir(DIR * dir) +{ + int result = -1; + + if (dir) { + if (dir->handle != -1) + result = _findclose(dir->handle); + Jim_Free(dir->name); + Jim_Free(dir); + } + if (result == -1) + errno = EBADF; + return result; +} + +struct dirent *readdir(DIR * dir) +{ + struct dirent *result = 0; + + if (dir && dir->handle != -1) { + if (!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1) { + result = &dir->result; + result->d_name = dir->info.name; + } + } + else { + errno = EBADF; + } + return result; +} +#endif +#endif +#ifndef JIM_BOOTSTRAP_LIB_ONLY +#include +#include + + +#ifdef USE_LINENOISE +#include +#include "linenoise.h" +#else +#define MAX_LINE_LEN 512 +#endif + +char *Jim_HistoryGetline(const char *prompt) +{ +#ifdef USE_LINENOISE + return linenoise(prompt); +#else + int len; + char *line = malloc(MAX_LINE_LEN); + + fputs(prompt, stdout); + fflush(stdout); + + if (fgets(line, MAX_LINE_LEN, stdin) == NULL) { + free(line); + return NULL; + } + len = strlen(line); + if (len && line[len - 1] == '\n') { + line[len - 1] = '\0'; + } + return line; +#endif +} + +void Jim_HistoryLoad(const char *filename) +{ +#ifdef USE_LINENOISE + linenoiseHistoryLoad(filename); +#endif +} + +void Jim_HistoryAdd(const char *line) +{ +#ifdef USE_LINENOISE + linenoiseHistoryAdd(line); +#endif +} + +void Jim_HistorySave(const char *filename) +{ +#ifdef USE_LINENOISE + linenoiseHistorySave(filename); +#endif +} + +void Jim_HistoryShow(void) +{ +#ifdef USE_LINENOISE + + int i; + int len; + char **history = linenoiseHistory(&len); + for (i = 0; i < len; i++) { + printf("%4d %s\n", i + 1, history[i]); + } +#endif +} + +int Jim_InteractivePrompt(Jim_Interp *interp) +{ + int retcode = JIM_OK; + char *history_file = NULL; +#ifdef USE_LINENOISE + const char *home; + + home = getenv("HOME"); + if (home && isatty(STDIN_FILENO)) { + int history_len = strlen(home) + sizeof("/.jim_history"); + history_file = Jim_Alloc(history_len); + snprintf(history_file, history_len, "%s/.jim_history", home); + Jim_HistoryLoad(history_file); + } +#endif + + printf("Welcome to Jim version %d.%d\n", + JIM_VERSION / 100, JIM_VERSION % 100); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, "1"); + + while (1) { + Jim_Obj *scriptObjPtr; + const char *result; + int reslen; + char prompt[20]; + const char *str; + + if (retcode != 0) { + const char *retcodestr = Jim_ReturnCode(retcode); + + if (*retcodestr == '?') { + snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode); + } + else { + snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr); + } + } + else { + prompt[0] = '\0'; + } + strcat(prompt, ". "); + + scriptObjPtr = Jim_NewStringObj(interp, "", 0); + Jim_IncrRefCount(scriptObjPtr); + while (1) { + char state; + int len; + char *line; + + line = Jim_HistoryGetline(prompt); + if (line == NULL) { + if (errno == EINTR) { + continue; + } + Jim_DecrRefCount(interp, scriptObjPtr); + retcode = JIM_OK; + goto out; + } + if (Jim_Length(scriptObjPtr) != 0) { + Jim_AppendString(interp, scriptObjPtr, "\n", 1); + } + Jim_AppendString(interp, scriptObjPtr, line, -1); + free(line); + str = Jim_GetString(scriptObjPtr, &len); + if (len == 0) { + continue; + } + if (Jim_ScriptIsComplete(str, len, &state)) + break; + + snprintf(prompt, sizeof(prompt), "%c> ", state); + } +#ifdef USE_LINENOISE + if (strcmp(str, "h") == 0) { + + Jim_HistoryShow(); + Jim_DecrRefCount(interp, scriptObjPtr); + continue; + } + + Jim_HistoryAdd(Jim_String(scriptObjPtr)); + if (history_file) { + Jim_HistorySave(history_file); + } +#endif + retcode = Jim_EvalObj(interp, scriptObjPtr); + Jim_DecrRefCount(interp, scriptObjPtr); + + if (retcode == JIM_EXIT) { + retcode = JIM_EXIT; + break; + } + if (retcode == JIM_ERR) { + Jim_MakeErrorMessage(interp); + } + result = Jim_GetString(Jim_GetResult(interp), &reslen); + if (reslen) { + printf("%s\n", result); + } + } + out: + Jim_Free(history_file); + return retcode; +} + +#include +#include +#include + + + +extern int Jim_initjimshInit(Jim_Interp *interp); + +static void JimSetArgv(Jim_Interp *interp, int argc, char *const argv[]) +{ + int n; + Jim_Obj *listObj = Jim_NewListObj(interp, NULL, 0); + + + for (n = 0; n < argc; n++) { + Jim_Obj *obj = Jim_NewStringObj(interp, argv[n], -1); + + Jim_ListAppendElement(interp, listObj, obj); + } + + Jim_SetVariableStr(interp, "argv", listObj); + Jim_SetVariableStr(interp, "argc", Jim_NewIntObj(interp, argc)); +} + +static void JimPrintErrorMessage(Jim_Interp *interp) +{ + Jim_MakeErrorMessage(interp); + fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp))); +} + +int main(int argc, char *const argv[]) +{ + int retcode; + Jim_Interp *interp; + + if (argc > 1 && strcmp(argv[1], "--version") == 0) { + printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100); + return 0; + } + + + interp = Jim_CreateInterp(); + Jim_RegisterCoreCommands(interp); + + + if (Jim_InitStaticExtensions(interp) != JIM_OK) { + JimPrintErrorMessage(interp); + } + + Jim_SetVariableStrWithStr(interp, "jim::argv0", argv[0]); + Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0"); + retcode = Jim_initjimshInit(interp); + + if (argc == 1) { + if (retcode == JIM_ERR) { + JimPrintErrorMessage(interp); + } + if (retcode != JIM_EXIT) { + JimSetArgv(interp, 0, NULL); + retcode = Jim_InteractivePrompt(interp); + } + } + else { + if (argc > 2 && strcmp(argv[1], "-e") == 0) { + JimSetArgv(interp, argc - 3, argv + 3); + retcode = Jim_Eval(interp, argv[2]); + if (retcode != JIM_ERR) { + printf("%s\n", Jim_String(Jim_GetResult(interp))); + } + } + else { + Jim_SetVariableStr(interp, "argv0", Jim_NewStringObj(interp, argv[1], -1)); + JimSetArgv(interp, argc - 2, argv + 2); + retcode = Jim_EvalFile(interp, argv[1]); + } + if (retcode == JIM_ERR) { + JimPrintErrorMessage(interp); + } + } + if (retcode == JIM_EXIT) { + retcode = Jim_GetExitCode(interp); + } + else if (retcode == JIM_ERR) { + retcode = 1; + } + else { + retcode = 0; + } + Jim_FreeInterp(interp); + return retcode; +} +#endif ADDED autosetup/lib/README.autosetup-lib Index: autosetup/lib/README.autosetup-lib ================================================================== --- /dev/null +++ autosetup/lib/README.autosetup-lib @@ -0,0 +1,9 @@ +Files in this directory are optional modules which +can be loaded with the 'use' directive. + +Modules which are publically documented (@MODULE ...) are installed +stand-alone in order to facilitate understanding by autosetup +end-users. + +All other modules are private/internal and are combined with the +main script when installed. ADDED autosetup/lib/asciidoc-formatting.tcl Index: autosetup/lib/asciidoc-formatting.tcl ================================================================== --- /dev/null +++ autosetup/lib/asciidoc-formatting.tcl @@ -0,0 +1,65 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# asciidoc format + +use formatting + +proc para {text} { + regsub -all "\[ \t\n\]+" [string trim $text] " " +} +proc title {text} { + underline [para $text] = + nl +} +proc p {text} { + puts [para $text] + nl +} +proc code {text} { + foreach line [parse_code_block $text] { + puts " $line" + } + nl +} +proc codelines {lines} { + foreach line $lines { + puts " $line" + } + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[para $text]" - + nl +} +proc subsection {text} { + underline "$text" ~ + nl +} +proc bullet {text} { + puts "* [para $text]" +} +proc indent {text} { + puts " :: " + puts [para $text] +} +proc defn {first args} { + set sep "" + if {$first ne ""} { + puts "${first}::" + } else { + puts " :: " + } + set defn [string trim [join $args \n]] + regsub -all "\n\n" $defn "\n ::\n" defn + puts $defn +} ADDED autosetup/lib/cc-db.tcl Index: autosetup/lib/cc-db.tcl ================================================================== --- /dev/null +++ autosetup/lib/cc-db.tcl @@ -0,0 +1,15 @@ +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc-db' module provides a knowledge based of system idiosyncracies +# In general, this module can always be included + +use cc + +module-options {} + +# openbsd needs sys/types.h to detect some system headers +cc-include-needs sys/socket.h sys/types.h +cc-include-needs netinet/in.h sys/types.h ADDED autosetup/lib/cc-lib.tcl Index: autosetup/lib/cc-lib.tcl ================================================================== --- /dev/null +++ autosetup/lib/cc-lib.tcl @@ -0,0 +1,161 @@ +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# Provides a library of common tests on top of the 'cc' module. + +use cc + +module-options {} + +# @cc-check-lfs +# +# The equivalent of the AC_SYS_LARGEFILE macro +# +# defines 'HAVE_LFS' if LFS is available, +# and defines '_FILE_OFFSET_BITS=64' if necessary +# +# Returns 1 if 'LFS' is available or 0 otherwise +# +proc cc-check-lfs {} { + cc-check-includes sys/types.h + msg-checking "Checking if -D_FILE_OFFSET_BITS=64 is needed..." + set lfs 1 + if {[msg-quiet cc-with {-includes sys/types.h} {cc-check-sizeof off_t}] == 8} { + msg-result no + } elseif {[msg-quiet cc-with {-includes sys/types.h -cflags -D_FILE_OFFSET_BITS=64} {cc-check-sizeof off_t}] == 8} { + define _FILE_OFFSET_BITS 64 + msg-result yes + } else { + set lfs 0 + msg-result none + } + define-feature lfs $lfs + return $lfs +} + +# @cc-check-endian +# +# The equivalent of the AC_C_BIGENDIAN macro +# +# defines 'HAVE_BIG_ENDIAN' if endian is known to be big, +# or 'HAVE_LITTLE_ENDIAN' if endian is known to be little. +# +# Returns 1 if determined, or 0 if not. +# +proc cc-check-endian {} { + cc-check-includes sys/types.h sys/param.h + set rc 0 + msg-checking "Checking endian..." + cc-with {-includes {sys/types.h sys/param.h}} { + if {[cctest -code { + #if !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != BIG_ENDIAN + #error little + #endif + }]} { + define-feature big-endian + msg-result "big" + set rc 1 + } elseif {[cctest -code { + #if !defined(LITTLE_ENDIAN) || !defined(BYTE_ORDER) + #error unknown + #elif BYTE_ORDER != LITTLE_ENDIAN + #error big + #endif + }]} { + define-feature little-endian + msg-result "little" + set rc 1 + } else { + msg-result "unknown" + } + } + return $rc +} + +# @cc-check-flags flag ?...? +# +# Checks whether the given C/C++ compiler flags can be used. Defines feature +# names prefixed with 'HAVE_CFLAG' and 'HAVE_CXXFLAG' respectively, and +# appends working flags to '-cflags' and 'CFLAGS' or 'CXXFLAGS'. +proc cc-check-flags {args} { + set result 1 + array set opts [cc-get-settings] + switch -exact -- $opts(-lang) { + c++ { + set lang C++ + set prefix CXXFLAG + } + c { + set lang C + set prefix CFLAG + } + default { + autosetup-error "cc-check-flags failed with unknown language: $opts(-lang)" + } + } + foreach flag $args { + msg-checking "Checking whether the $lang compiler accepts $flag..." + if {[cctest -cflags $flag]} { + msg-result yes + define-feature $prefix$flag + cc-with [list -cflags [list $flag]] + define-append ${prefix}S $flag + } else { + msg-result no + set result 0 + } + } + return $result +} + +# @cc-check-standards ver ?...? +# +# Checks whether the C/C++ compiler accepts one of the specified '-std=$ver' +# options, and appends the first working one to '-cflags' and 'CFLAGS' or +# 'CXXFLAGS'. +proc cc-check-standards {args} { + array set opts [cc-get-settings] + foreach std $args { + if {[cc-check-flags -std=$std]} { + return $std + } + } + return "" +} + +# Checks whether $keyword is usable as alignof +proc cctest_alignof {keyword} { + msg-checking "Checking for $keyword..." + if {[cctest -code [subst -nobackslashes { + printf("minimum alignment is %d == %d\n", ${keyword}(char), ${keyword}('x')); + }]]} then { + msg-result ok + define-feature $keyword + } else { + msg-result "not found" + } +} + +# @cc-check-c11 +# +# Checks for several C11/C++11 extensions and their alternatives. Currently +# checks for '_Static_assert', '_Alignof', '__alignof__', '__alignof'. +proc cc-check-c11 {} { + msg-checking "Checking for _Static_assert..." + if {[cctest -code { + _Static_assert(1, "static assertions are available"); + }]} then { + msg-result ok + define-feature _Static_assert + } else { + msg-result "not found" + } + + cctest_alignof _Alignof + cctest_alignof __alignof__ + cctest_alignof __alignof +} ADDED autosetup/lib/cc-shared.tcl Index: autosetup/lib/cc-shared.tcl ================================================================== --- /dev/null +++ autosetup/lib/cc-shared.tcl @@ -0,0 +1,112 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc-shared' module provides support for shared libraries and shared objects. +# It defines the following variables: +# +## SH_CFLAGS Flags to use compiling sources destined for a shared library +## SH_LDFLAGS Flags to use linking (creating) a shared library +## SH_SOPREFIX Prefix to use to set the soname when creating a shared library +## SH_SOEXT Extension for shared libs +## SH_SOEXTVER Format for versioned shared libs - %s = version +## SHOBJ_CFLAGS Flags to use compiling sources destined for a shared object +## SHOBJ_LDFLAGS Flags to use linking a shared object, undefined symbols allowed +## SHOBJ_LDFLAGS_R - as above, but all symbols must be resolved +## SH_LINKFLAGS Flags to use linking an executable which will load shared objects +## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries +## STRIPLIBFLAGS Arguments to strip to strip a dynamic library + +module-options {} + +# Defaults: gcc on unix +define SHOBJ_CFLAGS -fpic +define SHOBJ_LDFLAGS -shared +define SH_CFLAGS -fpic +define SH_LDFLAGS -shared +define SH_LINKFLAGS -rdynamic +define SH_SOEXT .so +define SH_SOEXTVER .so.%s +define SH_SOPREFIX -Wl,-soname, +define LD_LIBRARY_PATH LD_LIBRARY_PATH +define STRIPLIBFLAGS --strip-unneeded + +# Note: This is a helpful reference for identifying the toolchain +# http://sourceforge.net/apps/mediawiki/predef/index.php?title=Compilers + +switch -glob -- [get-define host] { + *-*-darwin* { + define SHOBJ_CFLAGS "-dynamic -fno-common" + define SHOBJ_LDFLAGS "-bundle -undefined dynamic_lookup" + define SHOBJ_LDFLAGS_R -bundle + define SH_CFLAGS -dynamic + define SH_LDFLAGS -dynamiclib + define SH_LINKFLAGS "" + define SH_SOEXT .dylib + define SH_SOEXTVER .%s.dylib + define SH_SOPREFIX -Wl,-install_name, + define LD_LIBRARY_PATH DYLD_LIBRARY_PATH + define STRIPLIBFLAGS -x + } + *-*-ming* - *-*-cygwin - *-*-msys { + define SHOBJ_CFLAGS "" + define SHOBJ_LDFLAGS "-shared -static-libgcc" + define SH_CFLAGS "" + define SH_LDFLAGS "-shared -static-libgcc" + define SH_LINKFLAGS "" + define SH_SOEXT .dll + define SH_SOEXTVER .dll + define SH_SOPREFIX "" + define LD_LIBRARY_PATH PATH + } + sparc* { + if {[msg-quiet cc-check-decls __SUNPRO_C]} { + msg-result "Found sun stdio compiler" + # sun stdio compiler + # XXX: These haven't been fully tested. + define SHOBJ_CFLAGS -KPIC + define SHOBJ_LDFLAGS "-G" + define SH_CFLAGS -KPIC + define SH_LINKFLAGS -Wl,-export-dynamic + define SH_SOPREFIX -Wl,-h, + } else { + # sparc has a very small GOT table limit, so use -fPIC + define SH_CFLAGS -fPIC + define SHOBJ_CFLAGS -fPIC + } + } + *-*-solaris* { + if {[msg-quiet cc-check-decls __SUNPRO_C]} { + msg-result "Found sun stdio compiler" + # sun stdio compiler + # XXX: These haven't been fully tested. + define SHOBJ_CFLAGS -KPIC + define SHOBJ_LDFLAGS "-G" + define SH_CFLAGS -KPIC + define SH_LINKFLAGS -Wl,-export-dynamic + define SH_SOPREFIX -Wl,-h, + } + } + *-*-hpux { + # XXX: These haven't been tested + define SHOBJ_CFLAGS "+O3 +z" + define SHOBJ_LDFLAGS -b + define SH_CFLAGS +z + define SH_LINKFLAGS -Wl,+s + define LD_LIBRARY_PATH SHLIB_PATH + } + *-*-haiku { + define SHOBJ_CFLAGS "" + define SHOBJ_LDFLAGS -shared + define SH_CFLAGS "" + define SH_LDFLAGS -shared + define SH_LINKFLAGS "" + define SH_SOPREFIX "" + define LD_LIBRARY_PATH LIBRARY_PATH + } +} + +if {![is-defined SHOBJ_LDFLAGS_R]} { + define SHOBJ_LDFLAGS_R [get-define SHOBJ_LDFLAGS] +} ADDED autosetup/lib/cc.tcl Index: autosetup/lib/cc.tcl ================================================================== --- /dev/null +++ autosetup/lib/cc.tcl @@ -0,0 +1,699 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# The 'cc' module supports checking various 'features' of the C or C++ +# compiler/linker environment. Common commands are cc-check-includes, +# cc-check-types, cc-check-functions, cc-with, make-autoconf-h and make-template. +# +# The following environment variables are used if set: +# +## CC - C compiler +## CXX - C++ compiler +## CCACHE - Set to "none" to disable automatic use of ccache +## CFLAGS - Additional C compiler flags +## CXXFLAGS - Additional C++ compiler flags +## LDFLAGS - Additional compiler flags during linking +## LIBS - Additional libraries to use (for all tests) +## CROSS - Tool prefix for cross compilation +# +# The following variables are defined from the corresponding +# environment variables if set. +# +## CPPFLAGS +## LINKFLAGS +## CC_FOR_BUILD +## LD + +use system + +module-options {} + +# Note that the return code is not meaningful +proc cc-check-something {name code} { + uplevel 1 $code +} + +# Checks for the existence of the given function by linking +# +proc cctest_function {function} { + cctest -link 1 -declare "extern void $function\(void);" -code "$function\();" +} + +# Checks for the existence of the given type by compiling +proc cctest_type {type} { + cctest -code "$type _x;" +} + +# Checks for the existence of the given type/structure member. +# e.g. "struct stat.st_mtime" +proc cctest_member {struct_member} { + lassign [split $struct_member .] struct member + cctest -code "static $struct _s; return sizeof(_s.$member);" +} + +# Checks for the existence of the given define by compiling +# +proc cctest_define {name} { + cctest -code "#ifndef $name\n#error not defined\n#endif" +} + +# Checks for the existence of the given name either as +# a macro (#define) or an rvalue (such as an enum) +# +proc cctest_decl {name} { + cctest -code "#ifndef $name\n(void)$name;\n#endif" +} + +# @cc-check-sizeof type ... +# +# Checks the size of the given types (between 1 and 32, inclusive). +# Defines a variable with the size determined, or "unknown" otherwise. +# e.g. for type 'long long', defines SIZEOF_LONG_LONG. +# Returns the size of the last type. +# +proc cc-check-sizeof {args} { + foreach type $args { + msg-checking "Checking for sizeof $type..." + set size unknown + # Try the most common sizes first + foreach i {4 8 1 2 16 32} { + if {[cctest -code "static int _x\[sizeof($type) == $i ? 1 : -1\] = { 1 };"]} { + set size $i + break + } + } + msg-result $size + set define [feature-define-name $type SIZEOF_] + define $define $size + } + # Return the last result + get-define $define +} + +# Checks for each feature in $list by using the given script. +# +# When the script is evaluated, $each is set to the feature +# being checked, and $extra is set to any additional cctest args. +# +# Returns 1 if all features were found, or 0 otherwise. +proc cc-check-some-feature {list script} { + set ret 1 + foreach each $list { + if {![check-feature $each $script]} { + set ret 0 + } + } + return $ret +} + +# @cc-check-includes includes ... +# +# Checks that the given include files can be used +proc cc-check-includes {args} { + cc-check-some-feature $args { + set with {} + if {[dict exists $::autosetup(cc-include-deps) $each]} { + set deps [dict keys [dict get $::autosetup(cc-include-deps) $each]] + msg-quiet cc-check-includes {*}$deps + foreach i $deps { + if {[have-feature $i]} { + lappend with $i + } + } + } + if {[llength $with]} { + cc-with [list -includes $with] { + cctest -includes $each + } + } else { + cctest -includes $each + } + } +} + +# @cc-include-needs include required ... +# +# Ensures that when checking for 'include', a check is first +# made for each 'required' file, and if found, it is #included +proc cc-include-needs {file args} { + foreach depfile $args { + dict set ::autosetup(cc-include-deps) $file $depfile 1 + } +} + +# @cc-check-types type ... +# +# Checks that the types exist. +proc cc-check-types {args} { + cc-check-some-feature $args { + cctest_type $each + } +} + +# @cc-check-defines define ... +# +# Checks that the given preprocessor symbol is defined +proc cc-check-defines {args} { + cc-check-some-feature $args { + cctest_define $each + } +} + +# @cc-check-decls name ... +# +# Checks that each given name is either a preprocessor symbol or rvalue +# such as an enum. Note that the define used for a decl is HAVE_DECL_xxx +# rather than HAVE_xxx +proc cc-check-decls {args} { + set ret 1 + foreach name $args { + msg-checking "Checking for $name..." + set r [cctest_decl $name] + define-feature "decl $name" $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + set ret 0 + } + } + return $ret +} + +# @cc-check-functions function ... +# +# Checks that the given functions exist (can be linked) +proc cc-check-functions {args} { + cc-check-some-feature $args { + cctest_function $each + } +} + +# @cc-check-members type.member ... +# +# Checks that the given type/structure members exist. +# A structure member is of the form "struct stat.st_mtime" +proc cc-check-members {args} { + cc-check-some-feature $args { + cctest_member $each + } +} + +# @cc-check-function-in-lib function libs ?otherlibs? +# +# Checks that the given given function can be found in one of the libs. +# +# First checks for no library required, then checks each of the libraries +# in turn. +# +# If the function is found, the feature is defined and lib_$function is defined +# to -l$lib where the function was found, or "" if no library required. +# In addition, -l$lib is added to the LIBS define. +# +# If additional libraries may be needed for linking, they should be specified +# as $extralibs as "-lotherlib1 -lotherlib2". +# These libraries are not automatically added to LIBS. +# +# Returns 1 if found or 0 if not. +# +proc cc-check-function-in-lib {function libs {otherlibs {}}} { + msg-checking "Checking libs for $function..." + set found 0 + cc-with [list -libs $otherlibs] { + if {[cctest_function $function]} { + msg-result "none needed" + define lib_$function "" + incr found + } else { + foreach lib $libs { + cc-with [list -libs -l$lib] { + if {[cctest_function $function]} { + msg-result -l$lib + define lib_$function -l$lib + define-append LIBS -l$lib + incr found + break + } + } + } + } + } + if {$found} { + define [feature-define-name $function] + } else { + msg-result "no" + } + return $found +} + +# @cc-check-tools tool ... +# +# Checks for existence of the given compiler tools, taking +# into account any cross compilation prefix. +# +# For example, when checking for "ar", first AR is checked on the command +# line and then in the environment. If not found, "${host}-ar" or +# simply "ar" is assumed depending upon whether cross compiling. +# The path is searched for this executable, and if found AR is defined +# to the executable name. +# Note that even when cross compiling, the simple "ar" is used as a fallback, +# but a warning is generated. This is necessary for some toolchains. +# +# It is an error if the executable is not found. +# +proc cc-check-tools {args} { + foreach tool $args { + set TOOL [string toupper $tool] + set exe [get-env $TOOL [get-define cross]$tool] + if {[find-executable {*}$exe]} { + define $TOOL $exe + continue + } + if {[find-executable {*}$tool]} { + msg-result "Warning: Failed to find $exe, falling back to $tool which may be incorrect" + define $TOOL $tool + continue + } + user-error "Failed to find $exe" + } +} + +# @cc-check-progs prog ... +# +# Checks for existence of the given executables on the path. +# +# For example, when checking for "grep", the path is searched for +# the executable, 'grep', and if found GREP is defined as "grep". +# +# It the executable is not found, the variable is defined as false. +# Returns 1 if all programs were found, or 0 otherwise. +# +proc cc-check-progs {args} { + set failed 0 + foreach prog $args { + set PROG [string toupper $prog] + msg-checking "Checking for $prog..." + if {![find-executable $prog]} { + msg-result no + define $PROG false + incr failed + } else { + msg-result ok + define $PROG $prog + } + } + expr {!$failed} +} + +# Adds the given settings to $::autosetup(ccsettings) and +# returns the old settings. +# +proc cc-add-settings {settings} { + if {[llength $settings] % 2} { + autosetup-error "settings list is missing a value: $settings" + } + + set prev [cc-get-settings] + # workaround a bug in some versions of jimsh by forcing + # conversion of $prev to a list + llength $prev + + array set new $prev + + foreach {name value} $settings { + switch -exact -- $name { + -cflags - -includes { + # These are given as lists + lappend new($name) {*}$value + } + -declare { + lappend new($name) $value + } + -libs { + # Note that new libraries are added before previous libraries + set new($name) [list {*}$value {*}$new($name)] + } + -link - -lang - -nooutput { + set new($name) $value + } + -source - -sourcefile - -code { + # XXX: These probably are only valid directly from cctest + set new($name) $value + } + default { + autosetup-error "unknown cctest setting: $name" + } + } + } + + cc-store-settings [array get new] + + return $prev +} + +proc cc-store-settings {new} { + set ::autosetup(ccsettings) $new +} + +proc cc-get-settings {} { + return $::autosetup(ccsettings) +} + +# Similar to cc-add-settings, but each given setting +# simply replaces the existing value. +# +# Returns the previous settings +proc cc-update-settings {args} { + set prev [cc-get-settings] + cc-store-settings [dict merge $prev $args] + return $prev +} + +# @cc-with settings ?{ script }? +# +# Sets the given 'cctest' settings and then runs the tests in 'script'. +# Note that settings such as -lang replace the current setting, while +# those such as -includes are appended to the existing setting. +# +# If no script is given, the settings become the default for the remainder +# of the auto.def file. +# +## cc-with {-lang c++} { +## # This will check with the C++ compiler +## cc-check-types bool +## cc-with {-includes signal.h} { +## # This will check with the C++ compiler, signal.h and any existing includes. +## ... +## } +## # back to just the C++ compiler +## } +# +# The -libs setting is special in that newer values are added *before* earlier ones. +# +## cc-with {-libs {-lc -lm}} { +## cc-with {-libs -ldl} { +## cctest -libs -lsocket ... +## # libs will be in this order: -lsocket -ldl -lc -lm +## } +## } +proc cc-with {settings args} { + if {[llength $args] == 0} { + cc-add-settings $settings + } elseif {[llength $args] > 1} { + autosetup-error "usage: cc-with settings ?script?" + } else { + set save [cc-add-settings $settings] + set rc [catch {uplevel 1 [lindex $args 0]} result info] + cc-store-settings $save + if {$rc != 0} { + return -code [dict get $info -code] $result + } + return $result + } +} + +# @cctest ?settings? +# +# Low level C compiler checker. Compiles and or links a small C program +# according to the arguments and returns 1 if OK, or 0 if not. +# +# Supported settings are: +# +## -cflags cflags A list of flags to pass to the compiler +## -includes list A list of includes, e.g. {stdlib.h stdio.h} +## -declare code Code to declare before main() +## -link 1 Don't just compile, link too +## -lang c|c++ Use the C (default) or C++ compiler +## -libs liblist List of libraries to link, e.g. {-ldl -lm} +## -code code Code to compile in the body of main() +## -source code Compile a complete program. Ignore -includes, -declare and -code +## -sourcefile file Shorthand for -source [readfile [get-define srcdir]/$file] +## -nooutput 1 Treat any compiler output (e.g. a warning) as an error +# +# Unless -source or -sourcefile is specified, the C program looks like: +# +## #include /* same for remaining includes in the list */ +## +## declare-code /* any code in -declare, verbatim */ +## +## int main(void) { +## code /* any code in -code, verbatim */ +## return 0; +## } +# +# Any failures are recorded in 'config.log' +# +proc cctest {args} { + set src conftest__.c + set tmp conftest__ + + # Easiest way to merge in the settings + cc-with $args { + array set opts [cc-get-settings] + } + + if {[info exists opts(-sourcefile)]} { + set opts(-source) [readfile [get-define srcdir]/$opts(-sourcefile) "#error can't find $opts(-sourcefile)"] + } + if {[info exists opts(-source)]} { + set lines $opts(-source) + } else { + foreach i $opts(-includes) { + if {$opts(-code) ne "" && ![feature-checked $i]} { + # Compiling real code with an unchecked header file + # Quickly (and silently) check for it now + + # Remove all -includes from settings before checking + set saveopts [cc-update-settings -includes {}] + msg-quiet cc-check-includes $i + cc-store-settings $saveopts + } + if {$opts(-code) eq "" || [have-feature $i]} { + lappend source "#include <$i>" + } + } + lappend source {*}$opts(-declare) + lappend source "int main(void) {" + lappend source $opts(-code) + lappend source "return 0;" + lappend source "}" + + set lines [join $source \n] + } + + # Build the command line + set cmdline {} + lappend cmdline {*}[get-define CCACHE] + switch -exact -- $opts(-lang) { + c++ { + lappend cmdline {*}[get-define CXX] {*}[get-define CXXFLAGS] + } + c { + lappend cmdline {*}[get-define CC] {*}[get-define CFLAGS] + } + default { + autosetup-error "cctest called with unknown language: $opts(-lang)" + } + } + + if {!$opts(-link)} { + set tmp conftest__.o + lappend cmdline -c + } + lappend cmdline {*}$opts(-cflags) {*}[get-define cc-default-debug ""] + + lappend cmdline $src -o $tmp {*}$opts(-libs) + + # At this point we have the complete command line and the + # complete source to be compiled. Get the result from cache if + # we can + if {[info exists ::cc_cache($cmdline,$lines)]} { + msg-checking "(cached) " + set ok $::cc_cache($cmdline,$lines) + if {$::autosetup(debug)} { + configlog "From cache (ok=$ok): [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + return $ok + } + + writefile $src $lines\n + + set ok 1 + set err [catch {exec-with-stderr {*}$cmdline} result errinfo] + if {$err || ($opts(-nooutput) && [string length $result])} { + configlog "Failed: [join $cmdline]" + configlog $result + configlog "============" + configlog "The failed code was:" + configlog $lines + configlog "============" + set ok 0 + } elseif {$::autosetup(debug)} { + configlog "Compiled OK: [join $cmdline]" + configlog "============" + configlog $lines + configlog "============" + } + file delete $src + file delete $tmp + + # cache it + set ::cc_cache($cmdline,$lines) $ok + + return $ok +} + +# @make-autoconf-h outfile ?auto-patterns=HAVE_*? ?bare-patterns=SIZEOF_*? +# +# Deprecated - see make-config-header +proc make-autoconf-h {file {autopatterns {HAVE_*}} {barepatterns {SIZEOF_* HAVE_DECL_*}}} { + user-notice "*** make-autoconf-h is deprecated -- use make-config-header instead" + make-config-header $file -auto $autopatterns -bare $barepatterns +} + +# @make-config-header outfile ?-auto patternlist? ?-bare patternlist? ?-none patternlist? ?-str patternlist? ... +# +# Examines all defined variables which match the given patterns +# and writes an include file, $file, which defines each of these. +# Variables which match '-auto' are output as follows: +# - defines which have the value "0" are ignored. +# - defines which have integer values are defined as the integer value. +# - any other value is defined as a string, e.g. "value" +# Variables which match '-bare' are defined as-is. +# Variables which match '-str' are defined as a string, e.g. "value" +# Variables which match '-none' are omitted. +# +# Note that order is important. The first pattern which matches is selected +# Default behaviour is: +# +# -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* -none * +# +# If the file would be unchanged, it is not written. +proc make-config-header {file args} { + set guard _[string toupper [regsub -all {[^a-zA-Z0-9]} [file tail $file] _]] + file mkdir [file dirname $file] + set lines {} + lappend lines "#ifndef $guard" + lappend lines "#define $guard" + + # Add some defaults + lappend args -bare {SIZEOF_* HAVE_DECL_*} -auto HAVE_* + + foreach n [lsort [dict keys [all-defines]]] { + set value [get-define $n] + set type [calc-define-output-type $n $args] + switch -exact -- $type { + -bare { + # Just output the value unchanged + } + -none { + continue + } + -str { + set value \"[string map [list \\ \\\\ \" \\\"] $value]\" + } + -auto { + # Automatically determine the type + if {$value eq "0"} { + lappend lines "/* #undef $n */" + continue + } + if {![string is integer -strict $value]} { + set value \"[string map [list \\ \\\\ \" \\\"] $value]\" + } + } + "" { + continue + } + default { + autosetup-error "Unknown type in make-config-header: $type" + } + } + lappend lines "#define $n $value" + } + lappend lines "#endif" + set buf [join $lines \n] + write-if-changed $file $buf { + msg-result "Created $file" + } +} + +proc calc-define-output-type {name spec} { + foreach {type patterns} $spec { + foreach pattern $patterns { + if {[string match $pattern $name]} { + return $type + } + } + } + return "" +} + +# Initialise some values from the environment or commandline or default settings +foreach i {LDFLAGS LIBS CPPFLAGS LINKFLAGS {CFLAGS "-g -O2"}} { + lassign $i var default + define $var [get-env $var $default] +} + +if {[env-is-set CC]} { + # Set by the user, so don't try anything else + set try [list [get-env CC ""]] +} else { + # Try some reasonable options + set try [list [get-define cross]cc [get-define cross]gcc] +} +define CC [find-an-executable {*}$try] +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CPP [get-env CPP "[get-define CC] -E"] + +# XXX: Could avoid looking for a C++ compiler until requested +# Note that if CXX isn't found, we just set it to "false". It might not be needed. +if {[env-is-set CXX]} { + define CXX [find-an-executable -required [get-env CXX ""]] +} else { + define CXX [find-an-executable [get-define cross]c++ [get-define cross]g++ false] +} + +# CXXFLAGS default to CFLAGS if not specified +define CXXFLAGS [get-env CXXFLAGS [get-define CFLAGS]] + +# May need a CC_FOR_BUILD, so look for one +define CC_FOR_BUILD [find-an-executable [get-env CC_FOR_BUILD ""] cc gcc false] + +if {[get-define CC] eq ""} { + user-error "Could not find a C compiler. Tried: [join $try ", "]" +} + +define CCACHE [find-an-executable [get-env CCACHE ccache]] + +# Initial cctest settings +cc-store-settings {-cflags {} -includes {} -declare {} -link 0 -lang c -libs {} -code {} -nooutput 0} +set autosetup(cc-include-deps) {} + +msg-result "C compiler...[get-define CCACHE] [get-define CC] [get-define CFLAGS]" +if {[get-define CXX] ne "false"} { + msg-result "C++ compiler...[get-define CCACHE] [get-define CXX] [get-define CXXFLAGS]" +} +msg-result "Build C compiler...[get-define CC_FOR_BUILD]" + +# On Darwin, we prefer to use -g0 to avoid creating .dSYM directories +# but some compilers may not support it, so test here. +switch -glob -- [get-define host] { + *-*-darwin* { + if {[cctest -cflags {-g0}]} { + define cc-default-debug -g0 + } + } +} + +if {![cc-check-includes stdlib.h]} { + user-error "Compiler does not work. See config.log" +} ADDED autosetup/lib/codebale.tcl Index: autosetup/lib/codebale.tcl ================================================================== --- /dev/null +++ autosetup/lib/codebale.tcl @@ -0,0 +1,863 @@ +### +# codebale.tcl +# +# This file defines routines used to bundle and manage Tcl and C +# code repositories +# +# Copyright (c) 2014 Sean Woods +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +### +#::namespace eval ::codebale {} + +# @synopsis: +# +# CODEBALE modules adds autobuild utilities +# + +set col 0 +use fileutil + +### +# topic: e1d75c45e58cc525a0a70ce6f767717c +### +proc codebale_isdirectory name { + return [file isdirectory $name] +} + +### +# topic: d0663852b31759ce78f33cbc63379d84 +### +proc codebale_istcl name { + return [string match *.tcl $name] +} + +### +# topic: ea4ac0a84ae990dafee965b995f48e63 +### +proc codebale_istm name { + return [string match *.tm $name] +} + +### +# topic: ec0fd469c986351ea0d5a287d6f040d8 +### +proc codebale_cases_finalize f { + global col + if {$col>0} {puts $f {}} + set col 0 +} + +### +# topic: 78728b1f05577d4bc1276e7294ff2cc7 +### +proc codebale_cases_generate {prefix cases} { + global col + set col 0 + set f [open [file join $::project(path) build [string tolower ${prefix}_cases].h] w] + fconfigure $f -translation crlf + puts $f $::project(standard_header) + puts $f " const static char *${prefix}_strs\[\] = \173" + set lx [lsort $cases] + foreach item $lx { + cases_put $f \"[string tolower $item]\", + } + cases_put $f 0 + cases_finalize $f + puts $f " \175;" + puts $f " enum ${prefix}_enum \173" + foreach name $lx { + regsub -all {@} $name {} name + cases_put $f ${prefix}_[string toupper $name], + } + cases_finalize $f + puts $f " \175;" + puts $f "\ + int index; + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, \"METHOD ?ARG ...?\"); + return TCL_ERROR; + } + if( Tcl_GetIndexFromObj(interp, objv\[1\], ${prefix}_strs,\ + \"option\", 0, &index)){ + return TCL_ERROR; + } + switch( (enum ${prefix}_enum)index )" + close $f +} + +### +# topic: 545596e62faedfeda638c8bb703882b1 +### +proc codebale_cases_put {f x} { + global col + if {$col==0} {puts -nonewline $f " "} + if {$col<2} { + puts -nonewline $f [format " %-21s" $x] + incr col + } else { + puts $f $x + set col 0 + } +} + +### +# topic: 9dd91e4b98b001260e30671883da494b +# description: Generate function declarations +### +proc codebale_headers_csourcefile file { + ### + # Skip huge files + ### + if {[file size $file] > 500000} {return {}} + set fin [open $file r] + set dat [read $fin] + close $fin + set result [digest_csource $dat] + set functions {} + if [catch { + foreach {funcname info} [lsort -stride 2 [dictGetnull $result function]] { + dict with info { + if { "static" in $keywords } continue + append functions "$keywords $funcname\([join $arglist ", "]\)\x3b" \n + } + } + } err] { + puts "ERROR Parsing $file: $err" + return "/* +** $file +** Process cancelled because of errors +** $err +** Line number: $::readinglinenumber +** Line: $::readingline +*/ +" + } + return $functions +} + +### +# topic: c0304a049be6f31206a02d15813720ce +### +proc codebale_meta_output outfile { + set fout [open $outfile w] + puts "SAVING TO $outfile" + + #puts $fout "array set filemd5 \x7b" + #array set temp [array get ::filemd5] + #foreach {file md5} [lsort [array names temp]] { + # set md5 $temp($file) + # puts $fout " [list $file $md5]" + #} + #array unset temp + #puts $fout "\x7d" + puts $fout "helpdoc eval {begin transaction}" + helpdoc eval { + select handle,localpath from repository + } { + puts $fout [list ::helpdoc repository_restore $handle [list localpath $localpath]] + } + helpdoc eval { + select hash,fileid from file + } { + puts $fout [helpdoc file_serialize $fileid] + } + puts $fout [helpdoc node_serialize 0] + helpdoc eval { + select entryid from entry + where class='section' + order by name + } { + puts $fout [helpdoc node_serialize $entryid] + } + helpdoc eval { + select entryid from entry + where class!='section' + order by parent,class,name + } { + puts $fout [helpdoc node_serialize $entryid] + } + puts $fout "helpdoc eval {commit}" + close $fout +} + +### +# topic: cd6e815c2e68b751656a4c9bbe8918dd +# description: Filters extranous fields from meta data +### +proc codebale_meta_scrub {aliases info} { + foreach {c alist} $aliases { + foreach a $alist { + set canonical($a) $c + } + } + + set outfo {} + foreach {field val} $info { + if {[info exists canonical($field)]} { + set cname $canonical($field) + } else { + set cname $field + } + if {$cname eq {}} continue + if {[string length [string trim $val]]} { + dict set outfo $cname $val + } + } + return $outfo +} + +### +# topic: 51380132b6f872ed01830e34431931d4 +### +proc codebale_pkg_mkIndex base { + set stack {} + if {[file exists [file join $base pkgIndex.tcl]]} { + return + #file delete [file join $base pkgIndex.tcl] + } + set fout [open [file join $base pkgIndex.tcl.new] w] + fconfigure $fout -translation crlf + + set result [::codebale_sniffPath $base stack] + + puts $fout {# Tcl package index file, version 1.1 +# This file is generated by the "pkg_mkIndex" command +# and sourced either when an application starts up or +# by a "package unknown" script. It invokes the +# "package ifneeded" command to set up package-related +# information so that packages will be loaded automatically +# in response to "package require" commands. When this +# script is sourced, the variable $dir must contain the +# full path name of this file's directory. + } + + while {[llength $stack]} { + set stackpath [lindex $stack 0] + set stack [lrange $stack 1 end] + foreach {type file} [::codebale_sniffPath $stackpath stack] { + lappend result $type $file + } + } + set i [string length $base] + foreach {type file} $result { + switch $type { + module { + set fname [file rootname [file tail $file]] + set package [lindex [split $fname -] 0] + set version [lindex [split $fname -] 1] + set dir [string trimleft [string range [file dirname $file] $i end] /] + puts $fout "package ifneeded $package $version \[list source \[file join \$dir $dir [file tail $file]\]\]" + #::codebale_read_tclsourcefile $file + } + source { + if { $file == "$base/pkgIndex.tcl" } continue + if { $file == "$base/packages.tcl" } continue + if { $file == "$base/main.tcl" } continue + if { [file tail $file] == "version_info.tcl" } continue + set fin [open $file r] + set dat [read $fin] + close $fin + if {[regexp "package provide" $dat]} { + set fname [file rootname [file tail $file]] + + set dir [string trimleft [string range [file dirname $file] $i end] /] + + foreach line [split $dat \n] { + set line [string trim $line] + + if { [string range $line 0 14] != "package provide" } continue + set package [lindex $line 2] + set version [lindex $line 3] + if { $dir eq {} } { + puts $fout "package ifneeded $package $version \[list source \[file join \$dir [file tail $file]\]\]" + } else { + puts $fout "package ifneeded $package $version \[list source \[file join \$dir $dir [file tail $file]\]\]" + } + break + } + } + #::codebale_read_tclsourcefile $file + } + } + } + close $fout + file rename -force [file join $base pkgIndex.tcl.new] [file join $base pkgIndex.tcl] +} + +### +# topic: 924caf1f68529d8dbc329b85e391a1c1 +### +proc codebale_pkgindex_manifest base { + set stack {} + set output {} + set base [file-normalize $base] + set i [string length $base] + + foreach {file} [fileutil_find $base codebale_istm] { + set file [file-normalize $file] + set fname [file rootname [file tail $file]] + ### + # Assume the package is correct in the filename + ### + set package [lindex [split $fname -] 0] + set version [lindex [split $fname -] 1] + set path [string trimleft [string range [file dirname $file] $i end] /] + ### + # Read the file, and override assumptions as needed + ### + set fin [open $file r] + set dat [read $fin] + close $fin + foreach line [split $dat \n] { + set line [string trim $line] + if { [string range $line 0 9] != "# Package " } continue + set package [lindex $line 2] + set version [lindex $line 3] + break + } + lappend output $package $version + } + foreach {file} [fileutil_find $base codebale_istcl] { + set file [file-normalize $file] + set fin [open $file r] + set dat [read $fin] + close $fin + if {![regexp "package provide" $dat]} continue + set fname [file rootname [file tail $file]] + set dir [string trimleft [string range [file dirname $file] $i end] /] + + foreach line [split $dat \n] { + set line [string trim $line] + if { [string range $line 0 14] != "package provide" } continue + set package [lindex $line 2] + set version [lindex $line 3] + lappend output $package $version + break + } + } + return $output +} + +### +# topic: 929629f0ebaa554710f66410dfa51f8a +### +proc codebale_pkgindex_path base { + set stack {} + set buffer { +lappend ::PATHSTACK $dir + } + set base [file-normalize $base] + set i [string length $base] + # Build a list of all of the paths + set paths [fileutil_find $base codebale_isdirectory] + + foreach path $paths { + if {$path eq $base} continue + set path_indexed($path) 0 + foreach idxname {pkgIndex.tcl} { + if {[file exists [file join $path $idxname]]} { + incr path_indexed($path) + set dir [string trimleft [string range $path $i end] /] + append buffer " +set dir \[file join \[lindex \$::PATHSTACK end\] $dir\] \; source \[file join \[lindex \$::PATHSTACK end\] $dir $idxname\] +" + append buffer \n + } + } + } + + foreach path $paths { + if {$path_indexed($path)} continue + foreach file [glob -nocomplain $path/*.tm] { + set file [file-normalize $file] + set fname [file rootname [file tail $file]] + ### + # Assume the package is correct in the filename + ### + set package [lindex [split $fname -] 0] + set version [lindex [split $fname -] 1] + set path [string trimleft [string range [file dirname $file] $i end] /] + ### + # Read the file, and override assumptions as needed + ### + set fin [open $file r] + set dat [read $fin] + close $fin + foreach line [split $dat \n] { + set line [string trim $line] + if { [string range $line 0 9] != "# Package " } continue + set package [lindex $line 2] + set version [lindex $line 3] + break + } + append buffer "package ifneeded $package $version \[list source \[file join \[lindex \$::PATHSTACK end\] $path [file tail $file]\]\]" + append buffer \n + } + foreach file [glob -nocomplain $path/*.tcl] { + set file [file-normalize $file] + if { $file == [file join $base tcl8.6 package.tcl] } continue + if { $file == [file join $base packages.tcl] } continue + if { $file == [file join $base main.tcl] } continue + if { [file tail $file] == "version_info.tcl" } continue + set fin [open $file r] + set dat [read $fin] + close $fin + if {![regexp "package provide" $dat]} continue + set fname [file rootname [file tail $file]] + set dir [string trimleft [string range [file dirname $file] $i end] /] + + foreach line [split $dat \n] { + set line [string trim $line] + if { [string range $line 0 14] != "package provide" } continue + set package [lindex $line 2] + set version [lindex $line 3] + append buffer "package ifneeded $package $version \[list source \[file join \[lindex \$::PATHSTACK end\] $dir [file tail $file]\]\]" + append buffer \n + break + } + } + } + append buffer { +set dir [lindex $::PATHSTACK end] +set ::PATHSTACK [lrange $::PATHSTACK 0 end-1] +} + return $buffer +} + +### +# topic: 3a00781665184d1efb9e292dbdd1b35c +# title: Read the contents of an rc conf file +# description: +# This style of conf file is assumed to contain lines formatted +# set VARNAME VALUE +### +proc codebale_read_rc_file fname { + if {![file exists $fname]} { + return {} + } + if {![catch {source $fname} err]} { + # Could read as a Tcl file + # Fill the result with the contents of + # all of the local variables defined by + # that file + set vars [info vars] + ldelete vars fname + foreach var $vars { + dict set result $var [set $var] + } + return $result + } + # Parse the file the hard way... + set fin [open $fname r] + set thisline {} + while {[gets $fin line] >= 0} { + set line [string trim $line] + if {[string index $line 0] eq "#"} continue + append thisline \n $line + if {![info complete $thisline]} continue + # Remove leading \n + set thisline [string trimleft $thisline] + if {[string range $line 0 2] == "set"} { + dict set result [lindex $line 1] [lindex $line 2] + } else { + if {[llength $line] eq 2} { + dict set result [lindex $line 0] [lindex $line 1] + } + } + } + return $result +} + +### +# topic: cbb00d37108708e5968c8a38f73ec38a +### +proc codebale_read_sh_file {filename {localdat {}}} { + set fin [open $filename r] + set result {} + if {$localdat eq {}} { + set top 1 + set local [array get ::env] + dict set local EXE {} + } else { + set top 0 + set local $localdat + } + while {[gets $fin line] >= 0} { + set line [string trim $line] + if {[string index $line 0] eq "#"} continue + if {$line eq {}} continue + catch { + if {[string range $line 0 6] eq "export "} { + set eq [string first "=" $line] + set field [string trim [string range $line 6 [expr {$eq - 1}]]] + set value [read_sh_subst [string range $line [expr {$eq+1}] end] $local] + dict set result $field [read_sh_subst $value $local] + dict set local $field $value + } elseif {[string range $line 0 7] eq "include "} { + set subfile [read_sh_subst [string range $line 7 end] $local] + foreach {field value} [read_sh_file $subfile $local] { + dict set result $field $value + } + } else { + set eq [string first "=" $line] + if {$eq > 0} { + set field [read_sh_subst [string range $line 0 [expr {$eq - 1}]] $local] + set value [string trim [string range $line [expr {$eq+1}] end] '] + #set value [read_sh_subst [string range $line [expr {$eq+1}] end] $local] + dict set local $field $value + dict set result $field $value + } + } + } err opts + if {[dict get $opts -code] != 0} { + #puts $opts + puts "Error reading line:\n$line\nerr: $err\n***" + return $err {*}$opts + } + } + return $result +} + +### +# topic: 22c2e7ae33fbe0d87784ca9b16df0de4 +# description: Converts a XXX.sh file into a series of Tcl variables +### +proc codebale_read_sh_subst {line info} { + regsub -all {\x28} $line \x7B line + regsub -all {\x29} $line \x7D line + + #set line [string map $key [string trim $line]] + foreach {field value} $info { + catch {set $field $value} + } + if [catch {subst $line} result] { + return {} + } + set result [string trim $result] + return [string trim $result '] +} + +### +# topic: 45a5b1e3f8a8372363f1670642972c62 +### +proc codebale_shlib_fname {os pkgname pkgvers} { + if { $os eq "windows" } { + return lib${pkgname}[string map {. {}} ${pkgvers}].dll + + } else { + switch $os { + macosx { + set suffix .dylib + } + default { + set suffix .so + } + } + return lib${pkgname}${pkgvers}$suffix + } +} + +proc realpath path { + if { !$::odie(windows) } { + return $path + } + if {[string index $path 0] eq "/" && [string index $path 2] eq "/"} { + return [string index $path 1]:[string range $path 2 end] + } + return $path +} + +proc cygpath path { + if { !$::odie(windows) } { + return $path + } + if {[string index $path 1] != ":" } { + return $path + } + set path [file-normalize $path] + return /[string tolower [string index $path 0]][string range $path 2 end] +} + +proc cygrelative {base filename} { + set base [::cygpath $base] + set filename [::cygpath $filename] + return [::fileutil_relative $base $filename] +} + +### +# topic: a5992c7f8340ba02d40e386aac95b1b8 +# description: Records an alias for a Tcl keyword +### +proc codebale_alias {alias cname} { + global cnames + set cnames($alias) $cname +} + +### +# topic: 0e883f3583c0ccd3eddc6b297ac2ea77 +### +proc codebale_buffer_append {varname args} { + upvar 1 $varname result + if {![info exists result]} { + set result {} + } + if {[string length $result]} { + set result [string trimright $result \n] + append result \n + } + set priorarg {} + foreach arg $args { + if {[string length [string trim $arg]]==0} continue + #if {[string match $arg $priorarg]} continue + set priorarg $arg + append result \n [string trim $arg \n] \n + } + set result [string trim $result \n] + append result \n + return $result +} + +### +# topic: 926c564aa67884986f7489f37da3fb32 +### +proc codebale_buffer_merge args { + set result {} + set priorarg {} + foreach arg $args { + if {[string length [string trim $arg]]==0} continue + if {[string match $arg $priorarg]} continue + set priorarg $arg + append result [string trim $arg \n] \n + } + set result [string trim $result \n] + return $result +} + +### +# topic: c1e66f4a20e397a5d2541714575c165f +### +proc codebale_buffer_puts {varname args} { + upvar 1 $varname result + if {![info exists result]} { + set result {} + } + set result [string trimright $result \n] + #if {[string length $result]} { + # set result [string trimright $result \n] + #} + set priorarg {} + foreach arg $args { + #if {[string length [string trim $arg]]==0} continue + #if {[string match $arg $priorarg]} continue + #set priorarg $arg + append result \n $arg + #[string trim $arg \n] + } + #set result [string trim $result \n] + #append result \n + return $result +} + +### +# topic: 951f31f2cb24992f34d97e3deb16b43f +# description: Reports back the canonical name of a tcl keyword +### +proc codebale_canonical alias { + global cnames + if {[info exists cnames($alias)]} { + return $cnames($alias) + } + return $alias +} + +proc codebale_detect_cases_put_item {f x} { + upvar 1 col col + if {$col==0} {puts -nonewline $f " "} + if {$col<2} { + puts -nonewline $f [format " %-21s" $x] + incr col + } else { + puts $f $x + set col 0 + } +} + +proc codebale_detect_cases_finalize {f} { + upvar 1 col col + if {$col>0} {puts $f {}} + set col 0 +} + +### +# topic: aacfe07625f74f93dada2159f53fca32 +### +proc codebale_detect_cases cfile { + set dirname [file dirname $cfile] + set fin [open $cfile r] + while {[gets $fin line] >= 0} { + if {[regexp {^ *case *([A-Z]+)_([A-Z0-9_]+):} $line all prefix label]} { + lappend cases($prefix) $label + } + } + close $fin + + set col 0 + + foreach prefix [array names cases] { + set hfile [file join $dirname [string tolower $prefix]_cases.h] + if {[file exists $hfile] && [file mtime $hfile]>[file mtime $cfile]} continue + set f [open $hfile w] + fconfigure $f -translation crlf + puts $f "/*** Automatically Generated Header File - Do Not Edit ***/" + puts $f " const static char *${prefix}_strs\[\] = \173" + set lx [lsort $cases($prefix)] + foreach item $lx { + codebale_detect_cases_put_item $f \"[string tolower $item]\", + } + codebale_detect_cases_put_item $f 0 + codebale_detect_cases_finalize $f + puts $f " \175;" + puts $f " enum ${prefix}_enum \173" + foreach name $lx { + regsub -all {@} $name {} name + codebale_detect_cases_put_item $f ${prefix}_[string toupper $name], + } + codebale_detect_cases_finalize $f + puts $f " \175;" + puts $f "\ + int index; + if( objc<2 ){ + Tcl_WrongNumArgs(interp, 1, objv, \"METHOD ?ARG ...?\"); + return TCL_ERROR; + } + if( Tcl_GetIndexFromObj(interp, objv\[1\], ${prefix}_strs,\ + \"option\", 0, &index)){ + return TCL_ERROR; + } + switch( (enum ${prefix}_enum)index )" + close $f + } + set result {} + foreach item [array names cases] { + lappend result [string tolower ${item}_cases.h] + } + return $result +} + +### +# topic: 003ce0c0d69b74076e8433492deac920 +# description: +# Descends into a directory structure, returning +# a list of items found in the form of: +# type object +# where type is one of: csource source parent_name +# and object is the full path to the file +### +proc codebale_sniffPath {spath stackvar} { + upvar 1 $stackvar stack + set result {} + if { ![file isdirectory $spath] } { + switch [file extension $spath] { + .tm { + return [list parent_name $spath] + } + .tcl { + return [list source $spath] + } + .h { + return [list cheader $spath] + } + .c { + return [list csource $spath] + } + } + return + } + foreach f [glob -nocomplain $spath/*] { + if {[file isdirectory $f]} { + if {[file tail $f] in {CVS build} } continue + if {[file extension $f] eq ".vfs" } continue + set stack [linsert $stack 0 $f] + } + } + set idx 0 + foreach idxtype { + pkgIndex.tcl tclIndex + } { + if {[file exists [file join $spath $idxtype]]} { + lappend result index [file join $spath $idxtype] + } + } + if {[llength $result]} { + return $result + } + foreach f [glob -nocomplain $spath/*] { + if {![file isdirectory $f]} { + set stack [linsert $stack 0 $f] + } + } + return {} +} + + +# [dictGetnull] is like [dict get] but returns empty string for missing keys. +proc dictGetnull {dictionary args} { + if {[dict exists $dictionary {*}$args]} { + dict get $dictionary {*}$args + } +} + +#namespace ensemble configure dict -map [dict replace\ +# [namespace ensemble configure dict -map] getnull ::tcl::dict::getnull] + +if {[info command ::ldelete] eq {}} { +proc ldelete {varname args} { + upvar 1 $varname var + if ![info exists var] { + return + } + foreach item [lsort -unique $args] { + while {[set i [lsearch $var $item]]>=0} { + set var [lreplace $var $i $i] + } + } + return $var +} +} + + +### +# topic: 5b6897b1d60450332ff9f389b5ca952d +### +proc doexec args { + exec {*}$args >&@ stdout +} + +# Simpler version without the substitution +proc read_Config.sh {filename} { + set fin [open $filename r] + set result {} + while {[gets $fin line] >= 0} { + set line [string trim $line] + if {[string index $line 0] eq "#"} continue + if {$line eq {}} continue + catch { + set eq [string first "=" $line] + if {$eq > 0} { + set field [string range $line 0 [expr {$eq - 1}]] + set value [string trim [string range $line [expr {$eq+1}] end] '] + #set value [read_sh_subst [string range $line [expr {$eq+1}] end] $local] + dict set result $field $value + } + } err opts + if {[dict get $opts -code] != 0} { + #puts $opts + puts "Error reading line:\n$line\nerr: $err\n***" + return $err {*}$opts + } + } + return $result +} + ADDED autosetup/lib/core.tcl Index: autosetup/lib/core.tcl ================================================================== --- /dev/null +++ autosetup/lib/core.tcl @@ -0,0 +1,741 @@ + +# @opt-bool option ... +# +# Check each of the named, boolean options and return 1 if any of them have +# been set by the user. +# +proc opt-bool {args} { + option-check-names {*}$args + opt_bool ::useropts {*}$args +} + +# @opt-val option-list ?default=""? +# +# Returns a list containing all the values given for the non-boolean options in 'option-list'. +# There will be one entry in the list for each option given by the user, including if the +# same option was used multiple times. +# If only a single value is required, use something like: +# +## lindex [opt-val $names] end +# +# If no options were set, $default is returned (exactly, not as a list). +# +proc opt-val {names {default ""}} { + option-check-names {*}$names + join [opt_val ::useropts $names $default] +} + +proc option-check-names {args} { + foreach o $args { + if {$o ni $::autosetup(options)} { + autosetup-error "Request for undeclared option --$o" + } + } +} + +# Parse the option definition in $opts and update +# ::useropts() and ::autosetup(optionhelp) appropriately +# +proc options-add {opts {header ""}} { + global useropts autosetup + + # First weed out comment lines + set realopts {} + foreach line [split $opts \n] { + if {![string match "#*" [string trimleft $line]]} { + append realopts $line \n + } + } + set opts $realopts + + for {set i 0} {$i < [llength $opts]} {incr i} { + set opt [lindex $opts $i] + if {[string match =* $opt]} { + # This is a special heading + lappend autosetup(optionhelp) $opt "" + set header {} + continue + } + + #puts "i=$i, opt=$opt" + regexp {^([^:=]*)(:)?(=)?(.*)$} $opt -> name colon equal value + if {$name in $autosetup(options)} { + autosetup-error "Option $name already specified" + } + + #puts "$opt => $name $colon $equal $value" + + # Find the corresponding value in the user options + # and set the default if necessary + if {[string match "-*" $opt]} { + # This is a documentation-only option, like "-C " + set opthelp $opt + } elseif {$colon eq ""} { + # Boolean option + lappend autosetup(options) $name + + if {![info exists useropts($name)]} { + set useropts($name) $value + } + if {$value eq "1"} { + set opthelp "--disable-$name" + } else { + set opthelp "--$name" + } + } else { + # String option. + lappend autosetup(options) $name + + if {$equal eq "="} { + if {[info exists useropts($name)]} { + # If the user specified the option with no value, the value will be "1" + # Replace with the default + if {$useropts($name) eq "1"} { + set useropts($name) $value + } + } + set opthelp "--$name?=$value?" + } else { + set opthelp "--$name=$value" + } + } + + # Now create the help for this option if appropriate + if {[lindex $opts $i+1] eq "=>"} { + set desc [lindex $opts $i+2] + #string match \n* $desc + if {$header ne ""} { + lappend autosetup(optionhelp) $header "" + set header "" + } + # A multi-line description + lappend autosetup(optionhelp) $opthelp $desc + incr i 2 + } + } +} + +# @module-options optionlist +# +# Like 'options', but used within a module. +proc module-options {opts} { + set header "" + if {$::autosetup(showhelp) > 1 && [llength $opts]} { + set header "Module Options:" + } + options-add $opts $header + + if {$::autosetup(showhelp)} { + # Ensure that the module isn't executed on --help + # We are running under eval or source, so use break + # to prevent further execution + #return -code break -level 2 + return -code break + } +} + +proc max {a b} { + expr {$a > $b ? $a : $b} +} + +proc options-wrap-desc {text length firstprefix nextprefix initial} { + set len $initial + set space $firstprefix + foreach word [split $text] { + set word [string trim $word] + if {$word == ""} { + continue + } + if {$len && [string length $space$word] + $len >= $length} { + puts "" + set len 0 + set space $nextprefix + } + incr len [string length $space$word] + puts -nonewline $space$word + set space " " + } + if {$len} { + puts "" + } +} + +proc options-show {} { + # Determine the max option width + set max 0 + foreach {opt desc} $::autosetup(optionhelp) { + if {[string match =* $opt] || [string match \n* $desc]} { + continue + } + set max [max $max [string length $opt]] + } + set indent [string repeat " " [expr $max+4]] + set cols [getenv COLUMNS 80] + catch { + lassign [exec stty size] rows cols + } + incr cols -1 + # Now output + foreach {opt desc} $::autosetup(optionhelp) { + if {[string match =* $opt]} { + puts [string range $opt 1 end] + continue + } + puts -nonewline " [format %-${max}s $opt]" + if {[string match \n* $desc]} { + puts $desc + } else { + options-wrap-desc [string trim $desc] $cols " " $indent [expr $max + 2] + } + } +} + +# @options options-spec +# +# Specifies configuration-time options which may be selected by the user +# and checked with opt-val and opt-bool. The format of options-spec follows. +# +# A boolean option is of the form: +# +## name[=0|1] => "Description of this boolean option" +# +# The default is name=0, meaning that the option is disabled by default. +# If name=1 is used to make the option enabled by default, the description should reflect +# that with text like "Disable support for ...". +# +# An argument option (one which takes a parameter) is of the form: +# +## name:[=]value => "Description of this option" +# +# If the name:value form is used, the value must be provided with the option (as --name=myvalue). +# If the name:=value form is used, the value is optional and the given value is used as the default +# if is not provided. +# +# Undocumented options are also supported by omitting the "=> description. +# These options are not displayed with --help and can be useful for internal options or as aliases. +# +# For example, --disable-lfs is an alias for --disable=largefile: +# +## lfs=1 largefile=1 => "Disable large file support" +# +proc options {optlist} { + # Allow options as a list or args + options-add $optlist "Local Options:" + + if {$::autosetup(showhelp)} { + options-show + exit 0 + } + + # Check for invalid options + if {[opt-bool option-checking]} { + foreach o [array names ::useropts] { + if {$o ni $::autosetup(options)} { + user-error "Unknown option --$o" + } + } + } +} + +proc config_guess {} { + if {[file-isexec $::autosetup(dir)/config.guess]} { + exec-with-stderr sh $::autosetup(dir)/config.guess + if {[catch {exec-with-stderr sh $::autosetup(dir)/config.guess} alias]} { + user-error $alias + } + return $alias + } else { + configlog "No config.guess, so using uname" + string tolower [exec uname -p]-unknown-[exec uname -s][exec uname -r] + } +} + +proc config_sub {alias} { + if {[file-isexec $::autosetup(dir)/config.sub]} { + if {[catch {exec-with-stderr sh $::autosetup(dir)/config.sub $alias} alias]} { + user-error $alias + } + } + return $alias +} + +# @define name ?value=1? +# +# Defines the named variable to the given value. +# These (name, value) pairs represent the results of the configuration check +# and are available to be checked, modified and substituted. +# +proc define {name {value 1}} { + set ::define($name) $value + #dputs "$name <= $value" +} + +# @define-append name value ... +# +# Appends the given value(s) to the given 'defined' variable. +# If the variable is not defined or empty, it is set to $value. +# Otherwise the value is appended, separated by a space. +# Any extra values are similarly appended. +# If any value is already contained in the variable (as a substring) it is omitted. +# +proc define-append {name args} { + if {[get-define $name ""] ne ""} { + # Make a token attempt to avoid duplicates + foreach arg $args { + if {[string first $arg $::define($name)] == -1} { + append ::define($name) " " $arg + } + } + } else { + set ::define($name) [join $args] + } + #dputs "$name += [join $args] => $::define($name)" +} + +# @get-define name ?default=0? +# +# Returns the current value of the 'defined' variable, or $default +# if not set. +# +proc get-define {name {default 0}} { + if {[info exists ::define($name)]} { + #dputs "$name => $::define($name)" + return $::define($name) + } + #dputs "$name => $default" + return $default +} + +# @is-defined name +# +# Returns 1 if the given variable is defined. +# +proc is-defined {name} { + info exists ::define($name) +} + +# @all-defines +# +# Returns a dictionary (name value list) of all defined variables. +# +# This is suitable for use with 'dict', 'array set' or 'foreach' +# and allows for arbitrary processing of the defined variables. +# +proc all-defines {} { + array get ::define +} + + +# @get-env name default +# +# If $name was specified on the command line, return it. +# If $name was set in the environment, return it. +# Otherwise return $default. +# +proc get-env {name default} { + if {[dict exists $::autosetup(cmdline) $name]} { + return [dict get $::autosetup(cmdline) $name] + } + getenv $name $default +} + +# @env-is-set name +# +# Returns 1 if the $name was specified on the command line or in the environment. +# Note that an empty environment variable is not considered to be set. +# +proc env-is-set {name} { + if {[dict exists $::autosetup(cmdline) $name]} { + return 1 + } + if {[getenv $name ""] ne ""} { + return 1 + } + return 0 +} + +# @readfile filename ?default=""? +# +# Return the contents of the file, without the trailing newline. +# If the doesn't exist or can't be read, returns $default. +# +proc readfile {filename {default_value ""}} { + set result $default_value + catch { + set f [open $filename] + set result [read -nonewline $f] + close $f + } + return $result +} + +# @writefile filename value +# +# Creates the given file containing $value. +# Does not add an extra newline. +# +proc writefile {filename value} { + set f [open $filename w] + puts -nonewline $f $value + close $f +} + +proc quote-if-needed {str} { + if {[string match {*[\" ]*} $str]} { + return \"[string map [list \" \\" \\ \\\\] $str]\" + } + return $str +} + +proc quote-argv {argv} { + set args {} + foreach arg $argv { + lappend args [quote-if-needed $arg] + } + join $args +} + +# @suffix suf list +# +# Takes a list and returns a new list with $suf appended +# to each element +# +## suffix .c {a b c} => {a.c b.c c.c} +# +proc suffix {suf list} { + set result {} + foreach p $list { + lappend result $p$suf + } + return $result +} + +# @prefix pre list +# +# Takes a list and returns a new list with $pre prepended +# to each element +# +## prefix jim- {a.c b.c} => {jim-a.c jim-b.c} +# +proc prefix {pre list} { + set result {} + foreach p $list { + lappend result $pre$p + } + return $result +} + +# @find-executable name +# +# Searches the path for an executable with the given name. +# Note that the name may include some parameters, e.g. "cc -mbig-endian", +# in which case the parameters are ignored. +# Returns 1 if found, or 0 if not. +# +proc find-executable {name} { + # Ignore any parameters + set name [lindex $name 0] + if {$name eq ""} { + # The empty string is never a valid executable + return 0 + } + foreach p [split-path] { + dputs "Looking for $name in $p" + set exec [file join $p $name] + if {[file-isexec $exec]} { + dputs "Found $name -> $exec" + return 1 + } + } + return 0 +} + +# @find-an-executable ?-required? name ... +# +# Given a list of possible executable names, +# searches for one of these on the path. +# +# Returns the name found, or "" if none found. +# If the first parameter is '-required', an error is generated +# if no executable is found. +# +proc find-an-executable {args} { + set required 0 + if {[lindex $args 0] eq "-required"} { + set args [lrange $args 1 end] + incr required + } + foreach name $args { + if {[find-executable $name]} { + return $name + } + } + if {$required} { + if {[llength $args] == 1} { + user-error "failed to find: [join $args]" + } else { + user-error "failed to find one of: [join $args]" + } + } + return "" +} + +# @configlog msg +# +# Writes the given message to the configuration log, config.log +# +proc configlog {msg} { + if {![info exists ::autosetup(logfh)]} { + set ::autosetup(logfh) [open config.log w] + } + puts $::autosetup(logfh) $msg +} + +# @msg-checking msg +# +# Writes the message with no newline to stdout. +# +proc msg-checking {msg} { + if {$::autosetup(msg-quiet) == 0} { + maybe-show-timestamp + puts -nonewline $msg + set ::autosetup(msg-checking) 1 + } +} + +# @msg-result msg +# +# Writes the message to stdout. +# +proc msg-result {msg} { + if {$::autosetup(msg-quiet) == 0} { + maybe-show-timestamp + puts $msg + set ::autosetup(msg-checking) 0 + show-notices + } +} + +# @msg-quiet command ... +# +# msg-quiet evaluates it's arguments as a command with output +# from msg-checking and msg-result suppressed. +# +# This is useful if a check needs to run a subcheck which isn't +# of interest to the user. +proc msg-quiet {args} { + incr ::autosetup(msg-quiet) + set rc [uplevel 1 $args] + incr ::autosetup(msg-quiet) -1 + return $rc +} + +# Will be overridden by 'use misc' +proc error-stacktrace {msg} { + return $msg +} + +proc error-location {msg} { + return $msg +} + +################################################################## +# +# Debugging output +# +proc dputs {msg} { + if {$::autosetup(debug)} { + puts $msg + } +} + +################################################################## +# +# User and system warnings and errors +# +# Usage errors such as wrong command line options + +# @user-error msg +# +# Indicate incorrect usage to the user, including if required components +# or features are not found. +# autosetup exits with a non-zero return code. +# +proc user-error {msg} { + show-notices + puts stderr "Error: $msg" + puts stderr "Try: '[file tail $::autosetup(exe)] --help' for options" + exit 1 +} + +# @user-notice msg +# +# Output the given message to stderr. +# +proc user-notice {msg} { + lappend ::autosetup(notices) $msg +} + +# Incorrect usage in the auto.def file. Identify the location. +proc autosetup-error {msg} { + autosetup-full-error [error-location $msg] +} + +# Like autosetup-error, except $msg is the full error message. +proc autosetup-full-error {msg} { + show-notices + puts stderr $msg + exit 1 +} + +proc show-notices {} { + if {$::autosetup(msg-checking)} { + puts "" + set ::autosetup(msg-checking) 0 + } + flush stdout + if {[info exists ::autosetup(notices)]} { + puts stderr [join $::autosetup(notices) \n] + unset ::autosetup(notices) + } +} + +proc maybe-show-timestamp {} { + if {$::autosetup(msg-timing) && $::autosetup(msg-checking) == 0} { + puts -nonewline [format {[%6.2f] } [expr {([clock millis] - $::autosetup(start)) % 10000 / 1000.0}]] + } +} + +proc autosetup_version {} { + return "autosetup v$::autosetup(version)" +} + +################################################################## +# +# Directory/path handling +# + +proc realdir {dir} { + set oldpwd [pwd] + cd $dir + set pwd [pwd] + cd $oldpwd + return $pwd +} + +# Follow symlinks until we get to something which is not a symlink +proc realpath {path} { + while {1} { + if {[catch { + set path [file readlink $path] + }]} { + # Not a link + break + } + } + return $path +} + +# Convert absolute path, $path into a path relative +# to the given directory (or the current dir, if not given). +# +proc relative-path {path {pwd {}}} { + set diff 0 + set same 0 + set newf {} + set prefix {} + set path [file-normalize $path] + if {$pwd eq ""} { + set pwd [pwd] + } else { + set pwd [file-normalize $pwd] + } + + if {$path eq $pwd} { + return . + } + + # Try to make the filename relative to the current dir + foreach p [split $pwd /] f [split $path /] { + if {$p ne $f} { + incr diff + } elseif {!$diff} { + incr same + } + if {$diff} { + if {$p ne ""} { + # Add .. for sibling or parent dir + lappend prefix .. + } + if {$f ne ""} { + lappend newf $f + } + } + } + if {$same == 1 || [llength $prefix] > 3} { + return $path + } + + file join [join $prefix /] [join $newf /] +} + +# Add filename as a dependency to rerun autosetup +# The name will be normalised (converted to a full path) +# +proc autosetup_add_dep {filename} { + lappend ::autosetup(deps) [file-normalize $filename] +} + +################################################################## +# +# Library module support +# + +# @use module ... +# +# Load the given library modules. +# e.g. 'use cc cc-shared' +# +# Note that module 'X' is implemented in either 'autosetup/X.tcl' +# or 'autosetup/X/init.tcl' +# +# The latter form is useful for a complex module which requires additional +# support file. In this form, '$::usedir' is set to the module directory +# when it is loaded. +# +proc use {args} { + foreach m $args { + if {[info exists ::libmodule($m)]} { + continue + } + set ::libmodule($m) 1 + if {[info exists ::modsource($m)]} { + automf_load eval $::modsource($m) + } else { + set sources [list $::autosetup(libdir)/${m}.tcl $::autosetup(libdir)/${m}/init.tcl] + set found 0 + foreach source $sources { + if {[file exists $source]} { + incr found + break + } + } + if {$found} { + # For the convenience of the "use" source, point to the directory + # it is being loaded from + set ::usedir [file dirname $source] + automf_load source $source + autosetup_add_dep $source + } else { + autosetup-error "use: No such module: $m" + } + } + } +} + +# Load module source in the global scope by executing the given command +proc automf_load {args} { + if {[catch [list uplevel #0 $args] msg opts] ni {0 2 3}} { + autosetup-full-error [error-dump $msg $opts $::autosetup(debug)] + } +} ADDED autosetup/lib/cthulhu.tcl Index: autosetup/lib/cthulhu.tcl ================================================================== --- /dev/null +++ autosetup/lib/cthulhu.tcl @@ -0,0 +1,560 @@ +### +# Utilities for automating the build process of C extensions +### +use codebale + +# @synopsis: +# +# CTHULHU modules adds autobuild utilities +# + +#::namespace eval ::cthulhu {} + +### +# title: define which modules the source we are adding contributes to +### +proc cthulhu_config args { + set ::cthulhu_config [dict merge $::cthulhu_config $args] +} + +### +# topic: 9c0c2d73c1afa8ef83a739c5d01309d0 +# title: Signal for a C header to be read with mkhdr +### +proc cthulhu_add_cheader {filename {trace 0}} { + set hfilename [::cygrelative $::project(srcdir) $filename] + if {$hfilename in $::project(headers_verbatim)} { + return + } + if {$hfilename ni $::project(headers)} { + lappend ::project(headers) $hfilename + #::cthulhu_read_csourcefile $file + } +} + +### +# topic: c52ea7e1ff44f11f960d99a55e4ab998 +# title: Add the contents of a header file verbatim to the internal headers and public headers +### +proc cthulhu_add_cheader_verbatim {filename {trace 0}} { + set hfilename [::cygrelative $::project(srcdir) $filename] + ldelete ::project(headers) $hfilename + if {$hfilename ni $::project(headers_verbatim)} { + lappend ::project(headers_verbatim) $hfilename + } +} + +### +# topic: 91e4d7da8dd82d78af41561360deab10 +# title: Signal for a C source to be read with mkhdr +### +proc cthulhu_add_csource {filename {cmdconfig {}}} { + set config [dict merge $::cthulhu_config $cmdconfig] + + set cfilename [::cygrelative $::project(srcdir) $filename] + dict set ::thesources $cfilename $config + if {$cfilename ni $::project(sources)} { + lappend ::project(sources) $cfilename + } + if {[string is true [dictGetnull $config scan]]} { + if {$cfilename ni $::project(scanlist)} { + lappend ::project(scanlist) $cfilename + } + } +} + +### +# topic: f11da5f705442524715e8f8fe9af5276 +# title: Add a path containing C code +### +proc cthulhu_add_directory {here {cmdconfig {}}} { + set config [dict merge { + cthulhu-ignore-hfiles {} + cthulhu-ignore-cfiles {} + build-ignore-cfiles {} + cthulhu-trace-cfiles {} + } $::cthulhu_config $cmdconfig] + + dict with config {} + + set here [::realpath $here] + ### + # Execute any .tcl scripts in the generic directory + ### + foreach file [lsort [glob -nocomplain [file join $here *.tcl]]] { + if {[file tail $file] eq "pkgIndex.tcl"} continue + cd $here + uplevel #0 [list source $file] + } + ### + # Build a list of all public header files that + # need to be amalgamated into the publicly exported + # version + ### + foreach file [lsort [glob -nocomplain [file join $here *.h]]] { + cthulhu_include_directory $here + set fname [file tail $file] + if {${cthulhu-ignore-hfiles} eq "*"} continue + if { $fname in ${cthulhu-ignore-hfiles} } continue + if {[string match *_cases.h $fname]} continue + cthulhu_add_cheader $file + } + foreach file [lsort [glob -nocomplain [file join $here *.c]]] { + if {[file tail $file] in ${build-ignore-cfiles} } continue + cthulhu_add_csource $file + } +} + +proc cthulhu_include_directory {here} { + if { $here ni $::project(include_paths) } { + lappend ::project(include_paths) $here + } +} + +### +# topic: 1d3a911fd58337df92205759a6d092c3 +# title: Add a source file in Tcl that produces a C file +### +proc cthulhu_add_dynamic {csource tclscript} { + set cfilename [::cygrelative $::project(srcdir) $csource] + set tclfilename [::cygrelative $::project(srcdir) $tclscript] + dict set ::thesources $cfilename tclscript $tclfilename +} + +### +# topic: d10665e8da4dd0781bb0a9ced5486e40 +# title: Add a pure-tcl library +### +proc cthulhu_add_library {here {cmdconfig {}}} { + set config [dict merge { + cthulhu-ignore-tclfiles {} + } $::cthulhu_config $cmdconfig] + + dict with config {} + set here [::realpath $here] + foreach file [lsort [glob -nocomplain $here/*.tcl]] { + if {[file tail $file] in ${cthulhu-ignore-tclfiles}} continue + set libfilename [::cygrelative $::project(srcdir) $libfilename] + } +} + +### +# topic: ccfe65b26705afc498e08d3004031066 +# title: Detect where we need to produce a _cases.h file to automate a C source +### +proc cthulhu_detect_cases filename { + set cfilename [::cygrelative $::project(srcdir) $filename] + set cases [codebale_detect_cases $filename] + if {![llength $cases]} return + set dirname [file dirname $cfilename] + foreach case $cases { + lappend result [file join $dirname $case] + } + dict set ::thesources $cfilename cases $result +} + +### +# topic: 41d95037e5a1cab76939150efdef8939 +# title: Declare an end to modifications of ::project +# description: +# This directive is placed after the last set ::project(X) Y +# but before the first ::cthulhu_add_* +### +proc cthulhu_init args { + set ::cthulhu_config [dict merge { + target pkg + } $args] + set ::project(strlen) [string length $::project(path)/] + set ::project(cases) {} + set ::project(sources) {} + set ::project(headers) {} + set ::project(scanlist) {} + set ::project(headers_verbatim) {} +} + +### +# topic: 17c9931c3ec5ba115efafaaaa3cf61ed +### +proc cthulhu_mk_lib_init.c outfile { + global project cout + set cout [open $outfile w] + fconfigure $cout -translation crlf + puts $cout $::project(standard_header) + puts $cout "#include \"$::project(h_file_int)\"" + + puts $cout " + + extern int DLLEXPORT ${project(init_funct)}( Tcl_Interp *interp ) \{ + Tcl_Namespace *modPtr\; + " + puts $cout { + /* Initialise the stubs tables. */ + #ifdef USE_TCL_STUBS + if ( + !Tcl_InitStubs(interp, "8.3", 0) + ) { + return TCL_ERROR; + } + #endif + } + + foreach module $::project(modules) { + puts $cout " if(${module}(interp)) return TCL_ERROR\;" + } + foreach {nspace cmds} [lsort -stride 2 -dictionary [array get namespace_commands]] { + puts $cout " + modPtr=Tcl_FindNamespace(interp,\"$nspace\",NULL,TCL_NAMESPACE_ONLY)\; + if(!modPtr) { + modPtr = Tcl_CreateNamespace(interp, \"$nspace\", NULL, NULL); + } + " + foreach {command cfunct} [lsort -stride 2 -dictionary $cmds] { + puts $cout " Tcl_CreateObjCommand(interp,\"::${nspace}::${command}\",(Tcl_ObjCmdProc *)$cfunct,NULL,NULL);" + } + puts $cout { + Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); + Tcl_Export(interp, modPtr, "[a-z]*", 1); + } + } + + puts $cout { + /* Register the package. */} + puts $cout " if (Tcl_PkgProvide(interp, \"${project(pkgname)}\", \"${project(pkgvers)}\")) return TCL_ERROR\;" + + + puts $cout " return TCL_OK\;\n\}" + close $cout +} + +### +# topic: 17c9931c3ec5ba115efafaaaa3cf61ed +### +proc cthulhu_mk_app_init.c outfile { + global project cout + set cout [open $outfile w] + fconfigure $cout -translation crlf + puts $cout $::project(standard_header) + puts $cout "#include \"$::project(h_file_int)\"" + + puts $cout " + + int ${project(init_funct)}_static( Tcl_Interp *interp ) \{ + Tcl_Namespace *modPtr\; + " + + foreach module $::project(modules) { + puts $cout " + if(${module}(interp)) \{ + return TCL_ERROR\; + \} + " + } + foreach {nspace cmds} [lsort -stride 2 -dictionary [array get namespace_commands]] { + puts $cout " + modPtr=Tcl_FindNamespace(interp,\"$nspace\",NULL,TCL_NAMESPACE_ONLY)\; + if(!modPtr) { + modPtr = Tcl_CreateNamespace(interp, \"$nspace\", NULL, NULL); + } + " + foreach {command cfunct} [lsort -stride 2 -dictionary $cmds] { + puts $cout " Tcl_CreateObjCommand(interp,\"::${nspace}::${command}\",(Tcl_ObjCmdProc *)$cfunct,NULL,NULL);" + } + puts $cout { + Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); + Tcl_Export(interp, modPtr, "[a-z]*", 1); + } + } + + puts $cout { + /* Register the package. */} + puts $cout " if (Tcl_PkgProvide(interp, \"${project(pkgname)}\", \"${project(pkgvers)}\")) return TCL_ERROR\;" + + + puts $cout " return TCL_OK\;\n\}" + close $cout +} + +### +# topic: 06bca7e2bddebdca69537fc3a9a0735f +### +proc cthulhu_mk_sources {bldpath outfile} { + global project + file mkdir $bldpath + set fout [open $outfile w] + fconfigure $fout -translation crlf + set pkg_sources {} + set pkg_objects {} + foreach {csource} $::project(sources) { + set ofile [file join $bldpath [string trimleft [string map {/ _ .c .o .. {}} $csource] _]] + lappend pkg_sources $csource + lappend pkg_objects $ofile + dict set ::thesources $csource ofile $ofile + } + set ILINE "MYINCLUDES=" + foreach ipath $::project(include_paths) { + append ILINE \\\n" -I[::cygrelative $::project(srcdir) $ipath]" + } + puts $fout $ILINE + puts $fout {} + define PKG_OBJECTS [lsort $pkg_objects] + define PKG_SOURCES [lsort $pkg_sources] + + #puts $fout "build/$project(c_file):" + #puts $fout "\t\${TCLSH} scripts/cthulhu.tcl\n" + + foreach {csource cinfo} $::thesources { + if {[dict exists $cinfo ofile]} { + set ofile [dict get $cinfo ofile] + } else { + set ofile {} + } + set hfiles {} + if {[dict exists $cinfo cases]} { + foreach hfile [dict get $cinfo cases] { + puts $fout "$hfile:" + puts $fout "\t\$(TCLSH_PROG) scripts/mktclopts.tcl $csource\n" + lappend hfiles $hfile + } + } + if {[dict exists $cinfo tclscript]} { + puts $fout "$csource:" + puts $fout "\t\$(TCLSH_PROG) [dict get $cinfo tclscript] $csource\n" + if {$ofile != {}} { + puts $fout "$ofile: $hfiles" + puts $fout "\t\$(COMPILE) [dictGetnull $cinfo extra] \$(MYINCLUDES) -c $csource -o \$@\n" + } + } else { + if {$ofile != {}} { + puts $fout "$ofile: $hfiles" + puts $fout "\t\$(COMPILE) [dictGetnull $cinfo extra] \$(MYINCLUDES) -c $csource -o \$@\n" + } + } + } + close $fout +} + +### +# topic: f7eec240dada25d73c1f68a877fa40be +# title: Produce the PROJECT.decls file +# description: Tools for automating the process of building stubs libraries +### +proc cthulhu_mk_stub_decls {pkgname mkhdrfile path} { + set outfile [file join $path/$pkgname.decls] + + ### + # Build the decls file + ### + set fout [open $outfile w] + puts $fout [subst {### + # $outfile + # + # This file was generated by [info script] + ### + + library $pkgname + interface $pkgname + }] + + set fin [open $mkhdrfile r] + set thisline {} + set functcount 0 + while {[gets $fin line]>=0} { + append thisline \n $line + if {![info complete $thisline]} continue + set readline $thisline + set thisline {} + set type [lindex $readline 1] + if { $type ne "f" } continue + + set infodict [lindex $readline end] + if {![dict exists $infodict definition]} continue + set def [dict get $infodict definition] + set def [string trim $def] + set def [string trimright $def \;] + if {![string match "*STUB_EXPORT*" $def]} continue + puts $fout [list declare [incr functcount] $def] + + } + close $fin + close $fout + + ### + # Build [package]Decls.h + ### + set hout [open [file join $path ${pkgname}Decls.h] w] + + close $hout + + set cout [open [file join $path ${pkgname}StubInit.c] w] +puts $cout [string map [list %pkgname% $pkgname %PkgName% [string totitle $pkgname]] { +#ifndef USE_TCL_STUBS +#define USE_TCL_STUBS +#endif +#undef USE_TCL_STUB_PROCS + +#include "tcl.h" +#include "%pkgname%.h" + + /* + ** Ensure that Tdom_InitStubs is built as an exported symbol. The other stub + ** functions should be built as non-exported symbols. + */ + +#undef TCL_STORAGE_CLASS +#define TCL_STORAGE_CLASS DLLEXPORT + +%PkgName%Stubs *%pkgname%StubsPtr; + + /* + **---------------------------------------------------------------------- + ** + ** %PkgName%_InitStubs -- + ** + ** Checks that the correct version of %PkgName% is loaded and that it + ** supports stubs. It then initialises the stub table pointers. + ** + ** Results: + ** The actual version of %PkgName% that satisfies the request, or + ** NULL to indicate that an error occurred. + ** + ** Side effects: + ** Sets the stub table pointers. + ** + **---------------------------------------------------------------------- + */ + +char * +%PkgName%_InitStubs (Tcl_Interp *interp, char *version, int exact) +{ + char *actualVersion; + + actualVersion = Tcl_PkgRequireEx(interp, "%pkgname%", version, exact, + (ClientData *) &%pkgname%StubsPtr); + if (!actualVersion) { + return NULL; + } + + if (!%pkgname%StubsPtr) { + Tcl_SetResult(interp, + "This implementation of %PkgName% does not support stubs", + TCL_STATIC); + return NULL; + } + + return actualVersion; +} +}] + close $cout +} + +### +# topic: ba1d2c7e8eab96029e434d54f917ef5a +### +proc cthulhu_mkhdr_index {hout docfileout} { + global project + set scanlist {} + foreach file $::project(headers) { + lappend scanlist [::realpath [file join $::project(srcdir) $file]] + } + foreach file $::project(scanlist) { + lappend scanlist [::realpath [file join $::project(srcdir) $file]] + } + ldelete scanlist [::realpath $::project(srcdir)/generic/$::project(h_file_int)] + ldelete scanlist [::realpath $::project(srcdir)/generic/$::project(c_file)] + puts "WRITING INTERNAL HEADERS TO $hout" + set fout [open $hout w] +puts $fout "/* +** DO NOT EDIT THIS FILE +** It is automagically generated by scripts/cthulhu.tcl +*/" + fconfigure $fout -translation crlf + foreach file $::project(headers_verbatim) { + puts $fout "/* Verbatim headers */" + set fullname [file join $::project(srcdir) $file] + set type [file type $fullname] + if {$type ne "file"} continue + puts $fout "/*\n *$file \n*/" + set fin [open $fullname r] + puts $fout [read $fin] + close $fin + } + puts $fout "/* FUNCTION DECLARATIONS */" + ### + # Do get around platform line breaks, we output to a tmp file + # and concat in Tcl + ### + set crscanlist {} + foreach file $scanlist { + set crfile $file.cr[file extension $file] + set rawfin [open $file r] + set rawfout [open $crfile w] + fconfigure $rawfout -translation lf + puts $rawfout [read $rawfin] + close $rawfout + close $rawfin + lappend crscanlist $crfile + } + + ::cthulhu_mkhdr -h -- {*}$crscanlist > $hout.cr + set rawfin [open $hout.cr r] + puts $fout [read $rawfin] + close $rawfin + file delete $hout.cr + close $fout + + ::cthulhu_mkhdr -doc -- {*}$scanlist > $docfileout + + foreach file $crscanlist { + file delete $file + } + + foreach {prefix cases} $::project(cases) { + ::codebale_cases_generate $prefix $cases + } + + set fin [open $hout r] + while {[gets $fin line]>=0} { + if {[regexp TCL_MODULE $line] || [regexp DLLEXPORT $line]} { + foreach regexp { + {(.*) ([a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)} + {(.*) (\x2a[a-zA-Z_][a-zA-Z0-9_]*) *\((.*)\)} + } { + if {[regexp $regexp $line all keywords funcname arglist]} { + lappend ::project(modules) $funcname + break + } + } + } + } +} + +proc cthulhu_find_mkhdr {} { + set exename [lindex [find-an-executable mkhdr] 0] + if {$exename ne {}} { + return [list exec [::realpath $exename]] + } + if {[info exists ::odie(mkhdr)]} { + if {[file exists [::realpath $::odie(mkhdr)]]} { + return [list exec [::realpath $::odie(mkhdr)]] + } + } + doexec $::odie(cc) -o mkhdr.o -c $::odie(src_dir)/scripts/mkhdr.c + doexec $::odie(cc) mkhdr.o -o mkhdr$::odie(exe_suffix) + file copy -force mkhdr$::odie(exe_suffix) [::realpath $::odie(mkhdr)] + return [list exec [::realpath $::odie(mkhdr)]] + error {mkhdr not available} +} + + +proc cthulhu_mkhdr args { + set cmd [cthulhu_find_mkhdr] + {*}${cmd} {*}$args +} + +array set ::project { + include_paths {} + sources {} + tcl_sources {} + modules {} +} + ADDED autosetup/lib/default.auto Index: autosetup/lib/default.auto ================================================================== --- /dev/null +++ autosetup/lib/default.auto @@ -0,0 +1,25 @@ +# Copyright (c) 2012 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Auto-load module for 'make' build system integration + +use init + +autosetup_add_init_type make {Simple "make" build system} { + autosetup_check_create auto.def \ +{# Initial auto.def created by 'autosetup --init=make' + +use cc + +# Add any user options here +options { +} + +make-config-header config.h +make-template Makefile.in +} + + if {![file exists Makefile.in]} { + puts "Note: I don't see Makefile.in. You will probably need to create one." + } +} ADDED autosetup/lib/fileutil.tcl Index: autosetup/lib/fileutil.tcl ================================================================== --- /dev/null +++ autosetup/lib/fileutil.tcl @@ -0,0 +1,2082 @@ +# fileutil.tcl -- +# +# Tcl implementations of standard UNIX utilities. +# +# Copyright (c) 1998-2000 by Ajuba Solutions. +# Copyright (c) 2002 by Phil Ehrens (fileType) +# Copyright (c) 2005-2013 by Andreas Kupries +# +# See the file "license.terms" for information on usage and redistribution +# of this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: fileutil.tcl,v 1.78 2010/06/17 04:46:19 andreas_kupries Exp $ + +# @synopsis: +# +# CODEBALE modules adds a jimtcl compadible version of the fileutil package from tcllib +# + +package provide cthulhu-fileutil 1.14.8 + +#namespace eval ::fileutil { +# namespace export \ +# find findByPattern cat touch foreachLine \ +# jail stripPwd stripN stripPath tempdir tempfile \ +# install fileType writeFile appendToFile \ +# insertIntoFile removeFromFile replaceInFile \ +# updateInPlace test tempdirReset +#} + +# ::fileutil_grep -- +# +# Implementation of grep. Adapted from the Tcler's Wiki. +# +# Arguments: +# pattern pattern to search for. +# files list of files to search; if NULL, uses stdin. +# +# Results: +# results list of matches + +proc fileutil_grep {pattern {files {}}} { + set result [list] + if {[llength $files] == 0} { + # read from stdin + set lnum 0 + while {[gets stdin line] >= 0} { + incr lnum + if {[regexp -- $pattern $line]} { + lappend result "${lnum}:${line}" + } + } + } else { + foreach filename $files { + set file [open $filename r] + set lnum 0 + while {[gets $file line] >= 0} { + incr lnum + if {[regexp -- $pattern $line]} { + lappend result "${filename}:${lnum}:${line}" + } + } + close $file + } + } + return $result +} + +# ::fileutil_find == + +# Below is the core command, which is portable across Tcl versions and +# platforms. Functionality which is common or platform and/or Tcl +# version dependent, has been factored out/ encapsulated into separate +# (small) commands. Only these commands may have multiple variant +# implementations per the available features of the Tcl core / +# platform. +# +# These commands are +# +# FADD - Add path result, performs filtering. Portable! +# GLOBF - Return files in a directory. Tcl version/platform dependent. +# GLOBD - Return dirs in a directory. Tcl version/platform dependent. +# ACCESS - Check directory for accessibility. Tcl version/platform dependent. + +proc fileutil_find {{basedir .} {filtercmd {}}} { + set result {} + set filt [string length $filtercmd] + + if {[file isfile $basedir]} { + # The base is a file, and therefore only possible result, + # modulo filtering. + + fileutil_FADD $basedir + + } elseif {[file isdirectory $basedir]} { + + # For a directory as base we do an iterative recursion through + # the directory hierarchy starting at the base. We use a queue + # (Tcl list) of directories we have to check. We access it by + # index, and stop when we have reached beyond the end of the + # list. This is faster than removing elements from the be- + # ginning of the list, as that entails copying down a possibly + # large list of directories, making it O(n*n). The index is + # faster, O(n), at the expense of memory. Nothing is deleted + # from the list until we have processed all directories in the + # hierarchy. + # + # We scan each directory at least twice. First for files, then + # for directories. The scans may internally make several + # passes (normal vs hidden files). + # + # Looped directory structures due to symbolic links are + # handled by _fully_ normalizing directory paths and checking + # if we encountered the normalized form before. The array + # 'known' is our cache where we record the known normalized + # paths. + + set pending [list $basedir] + set at 0 + array set known {} + + while {$at < [llength $pending]} { + # Get next directory not yet processed. + set current [lindex $pending $at] + incr at + + # Is the directory accessible? Continue if not. + fileutil_ACCESS $current + + # Files first, then the sub-directories ... + + foreach f [fileutil_GLOBF $current] { fileutil_FADD $f } + + foreach f [fileutil_GLOBD $current] { + # Ignore current and parent directory, this needs + # explicit filtering outside of the filter command. + if { + [string equal [file tail $f] "."] || + [string equal [file tail $f] ".."] + } continue + + # Extend result, modulo filtering. + fileutil_FADD $f + + # Detection of symlink loops via a portable path + # normalization computing a canonical form of the path + # followed by a check if that canonical form was + # encountered before. If ok, record directory for + # expansion in future iterations. + + set norm [fileutil_fullnormalize $f] + if {[info exists known($norm)]} continue + set known($norm) . + + lappend pending $f + } + } + } else { + return -code error "$basedir does not exist" + } + + return $result +} + +# Helper command for fileutil_find. Performs the filtering of the +# result per a filter command for the candidates found by the +# traversal core, see above. This is portable. + +proc fileutil_FADD {filename} { + upvar 1 result result filt filt filtercmd filtercmd + if {!$filt} { + lappend result $filename + return + } + + set here [pwd] + cd [file dirname $filename] + + if {[uplevel 2 [linsert $filtercmd end [file tail $filename]]]} { + lappend result $filename + } + + cd $here + return +} + +# The next three helper commands for fileutil_find depend strongly on +# the version of Tcl, and partially on the platform. + +# 1. The -directory and -types switches were added to glob in Tcl +# 8.3. This means that we have to emulate them for Tcl 8.2. +# +# 2. In Tcl 8.3 using -types f will return only true files, but not +# links to files. This changed in 8.4+ where links to files are +# returned as well. So for 8.3 we have to handle the links +# separately (-types l) and also filter on our own. +# Note that Windows file links are hard links which are reported by +# -types f, but not -types l, so we can optimize that for the two +# platforms. +# +# Note further that we have to handle broken links on our own. They +# are not returned by glob yet we want them in the output. +# +# 3. In Tcl 8.3 we also have a crashing bug in glob (SIGABRT, "stat on +# a known file") when trying to perform 'glob -types {hidden f}' on +# a directory without e'x'ecute permissions. We code around by +# testing if we can cd into the directory (stat might return enough +# information too (mode), but possibly also not portable). +# +# For Tcl 8.2 and 8.4+ glob simply delivers an empty result +# (-nocomplain), without crashing. For them this command is defined +# so that the bytecode compiler removes it from the bytecode. +# +# This bug made the ACCESS helper necessary. +# We code around the problem by testing if we can cd into the +# directory (stat might return enough information too (mode), but +# possibly also not portable). + +set tclver [package present Tcl] +puts [list TCL VERSION $tclver] +if {$tclver eq {}} { + # jimTcl emulates a pre-namespace tcl + set tclver 7.8 +} +puts [list TCL VERSION $tclver] + +### +# Assume an austere environment +# circa 8.2. +# (Ad 1,2,3) We do not have -directory, nor -types. Full emulation required. +### +proc fileutil_ACCESS {args} {} +if {[string equal $::tcl_platform(platform) windows]} { + # Hidden files cannot be handled by Tcl 8.2 in glob. We have + # to punt. + + proc fileutil_GLOBF {current} { + set current \\[join [split $current {}] \\] + set res {} + foreach x [glob -nocomplain -- [file join $current *]] { + if {[file isdirectory $x]} continue + if {[catch {file type $x}]} continue + # We have now accepted files, links to files, and + # broken links. We may also have accepted a directory + # as well, if the current path was inaccessible. This + # however will cause 'file type' to throw an error, + # hence the second check. + lappend res $x + } + return $res + } + + proc fileutil_GLOBD {current} { + set current \\[join [split $current {}] \\] + set res {} + foreach x [glob -nocomplain -- [file join $current *]] { + if {![file isdirectory $x]} continue + lappend res $x + } + return $res + } +} else { + # Hidden files on Unix are dot-files. We emulate the switch + # '-types hidden' by using an explicit pattern. + + proc fileutil_GLOBF {current} { + set current \\[join [split $current {}] \\] + set res {} + foreach x [glob -nocomplain -- [file join $current *] [file join $current .*]] { + if {[file isdirectory $x]} continue + if {[catch {file type $x}]} continue + # We have now accepted files, links to files, and + # broken links. We may also have accepted a directory + # as well, if the current path was inaccessible. This + # however will cause 'file type' to throw an error, + # hence the second check. + + lappend res $x + } + return $res + } + + proc fileutil_GLOBD {current} { + set current \\[join [split $current {}] \\] + set res {} + foreach x [glob -nocomplain -- $current/* [file join $current .*]] { + if {![file isdirectory $x]} continue + lappend res $x + } + return $res + } +} + + +# ::fileutil_findByPattern -- +# +# Specialization of find. Finds files based on their names, +# which have to match the specified patterns. Options are used +# to specify which type of patterns (regexp-, glob-style) is +# used. +# +# Arguments: +# basedir Directory to start searching from. +# args Options (-glob, -regexp, --) followed by a +# list of patterns to search for. +# +# Results: +# files a list of interesting files. + +proc fileutil_findByPattern {basedir args} { + set pos 0 + set cmd ::fileutil_FindGlob + foreach a $args { + incr pos + switch -glob -- $a { + -- {break} + -regexp {set cmd ::fileutil_FindRegexp} + -glob {set cmd ::fileutil_FindGlob} + -* {return -code error "Unknown option $a"} + default {incr pos -1 ; break} + } + } + + set args [lrange $args $pos end] + + if {[llength $args] != 1} { + set pname [lindex [info level 0] 0] + return -code error \ + "wrong#args for \"$pname\", should be\ + \"$pname basedir ?-regexp|-glob? ?--? patterns\"" + } + + set patterns [lindex $args 0] + return [find $basedir [list $cmd $patterns]] +} + + +# ::fileutil_FindRegexp -- +# +# Internal helper. Filter command used by 'findByPattern' +# to match files based on regular expressions. +# +# Arguments: +# patterns List of regular expressions to match against. +# filename Name of the file to match against the patterns. +# Results: +# interesting A boolean flag. Set to true if the file +# matches at least one of the patterns. + +proc fileutil_FindRegexp {patterns filename} { + foreach p $patterns { + if {[regexp -- $p $filename]} { + return 1 + } + } + return 0 +} + +# ::fileutil_FindGlob -- +# +# Internal helper. Filter command used by 'findByPattern' +# to match files based on glob expressions. +# +# Arguments: +# patterns List of glob expressions to match against. +# filename Name of the file to match against the patterns. +# Results: +# interesting A boolean flag. Set to true if the file +# matches at least one of the patterns. + +proc fileutil_FindGlob {patterns filename} { + foreach p $patterns { + if {[string match $p $filename]} { + return 1 + } + } + return 0 +} + +# ::fileutil_stripPwd -- +# +# If the specified path references is a path in [pwd] (or [pwd] itself) it +# is made relative to [pwd]. Otherwise it is left unchanged. +# In the case of [pwd] itself the result is the string '.'. +# +# Arguments: +# path path to modify +# +# Results: +# path The (possibly) modified path. + +proc fileutil_stripPwd {path} { + + # [file split] is used to generate a canonical form for both + # paths, for easy comparison, and also one which is easy to modify + # using list commands. + + set pwd [pwd] + if {[string equal $pwd $path]} { + return "." + } + + set pwd [file split $pwd] + set npath [file split $path] + + if {[string match ${pwd}* $npath]} { + set path [eval [linsert [lrange $npath [llength $pwd] end] 0 file join ]] + } + return $path +} + +# ::fileutil_stripN -- +# +# Removes N elements from the beginning of the path. +# +# Arguments: +# path path to modify +# n number of elements to strip +# +# Results: +# path The modified path + +proc fileutil_stripN {path n} { + set path [file split $path] + if {$n >= [llength $path]} { + return {} + } else { + return [eval [linsert [lrange $path $n end] 0 file join]] + } +} + +# ::fileutil_stripPath -- +# +# If the specified path references/is a path in prefix (or prefix itself) it +# is made relative to prefix. Otherwise it is left unchanged. +# In the case of it being prefix itself the result is the string '.'. +# +# Arguments: +# prefix prefix to strip from the path. +# path path to modify +# +# Results: +# path The (possibly) modified path. + +if {[string equal $::tcl_platform(platform) windows]} { + + # Windows. While paths are stored with letter-case preserved al + # comparisons have to be done case-insensitive. For reference see + # SF Tcllib Bug 2499641. + + proc fileutil_stripPath {prefix path} { + # [file split] is used to generate a canonical form for both + # paths, for easy comparison, and also one which is easy to modify + # using list commands. + + set prefix [file split $prefix] + set npath [file split $path] + + if {[string equal -nocase $prefix $npath]} { + return "." + } + + if {[string match -nocase "${prefix} *" $npath]} { + set path [eval [linsert [lrange $npath [llength $prefix] end] 0 file join ]] + } + return $path + } +} else { + proc fileutil_stripPath {prefix path} { + # [file split] is used to generate a canonical form for both + # paths, for easy comparison, and also one which is easy to modify + # using list commands. + + set prefix [file split $prefix] + set npath [file split $path] + + if {[string equal $prefix $npath]} { + return "." + } + + if {[string match "${prefix} *" $npath]} { + set path [eval [linsert [lrange $npath [llength $prefix] end] 0 file join ]] + } + return $path + } +} + +# ::fileutil_jail -- +# +# Ensures that the input path 'filename' stays within the the +# directory 'jail'. In this way it preventsuser-supplied paths +# from escaping the jail. +# +# Arguments: +# jail The path to the directory the other must +# not escape from. +# filename The path to prevent from escaping. +# +# Results: +# path The (possibly) modified path surely within +# the confines of the jail. + +proc fileutil_jail {jail filename} { + if {![string equal [file pathtype $filename] "relative"]} { + # Although the path to check is absolute (or volumerelative on + # windows) we cannot perform a simple prefix check to see if + # the path is inside the jail or not. We have to normalize + # both path and jail and then we can check. If the path is + # outside we make the original path relative and prefix it + # with the original jail. We do make the jail pseudo-absolute + # by prefixing it with the current working directory for that. + + # Normalized jail. Fully resolved sym links, if any. Our main + # complication is that normalize does not resolve symlinks in the + # last component of the path given to it, so we add a bogus + # component, resolve, and then strip it off again. That is why the + # code is so large and long. + + set njail [eval [list file join] [lrange [file split \ + [fileutil_Normalize [file join $jail __dummy__]]] 0 end-1]] + + # Normalize filename. Fully resolved sym links, if + # any. S.a. for an explanation of the complication. + + set nfile [eval [list file join] [lrange [file split \ + [fileutil_Normalize [file join $filename __dummy__]]] 0 end-1]] + + if {[string match ${njail}* $nfile]} { + return $filename + } + + # Outside the jail, put it inside. ... We normalize the input + # path lexically for this, to prevent escapes still lurking in + # the original path. (We cannot use the normalized path, + # symlinks may have bent it out of shape in unrecognizable ways. + + return [eval [linsert [lrange [file split \ + [fileutil_lexnormalize $filename]] 1 end] 0 file join [pwd] $jail]] + } else { + # The path is relative, consider it as outside + # implicitly. Normalize it lexically! to prevent escapes, then + # put the jail in front, use PWD to ensure absoluteness. + + return [eval [linsert [file split [fileutil_lexnormalize $filename]] 0 \ + file join [pwd] $jail]] + } +} + + +# ::fileutil_test -- +# +# Simple API to testing various properties of +# a path (read, write, file/dir, existence) +# +# Arguments: +# path path to test +# codes names of the properties to test +# msgvar Name of variable to leave an error +# message in. Optional. +# label Label for error message, optional +# +# Results: +# ok boolean flag, set if the path passes +# all tests. + + +global test +array set test { + read {readable {Read access is denied}} + write {writable {Write access is denied}} + exec {executable {Is not executable}} + exists {exists {Does not exist}} + file {isfile {Is not a file}} + dir {isdirectory {Is not a directory}} +} + + +proc fileutil_test {path codes {msgvar {}} {label {}}} { + global test + + if {[string equal $msgvar ""]} { + set msg "" + } else { + upvar 1 $msgvar msg + } + + if {![string equal $label ""]} {append label { }} + + if {![regexp {^(read|write|exec|exists|file|dir)} $codes]} { + # Translate single characters into proper codes + set codes [string map { + r read w write e exists x exec f file d dir + } [split $codes {}]] + } + + foreach c $codes { + foreach {cmd text} $test($c) break + if {![file $cmd $path]} { + set msg "$label\"$path\": $text" + return 0 + } + } + + return 1 +} + +# ::fileutil_cat -- +# +# Tcl implementation of the UNIX "cat" command. Returns the contents +# of the specified files. +# +# Arguments: +# args names of the files to read, interspersed with options +# to set encodings, translations, or eofchar. +# +# Results: +# data data read from the file. + +proc fileutil_cat {args} { + # Syntax: (?options? file)+ + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + if {![llength $args]} { + # Argument processing stopped with arguments missing. + return -code error \ + "wrong#args: should be\ + [lindex [info level 0] 0] ?-eofchar|-translation|-encoding arg?+ file ..." + } + + # We go through the arguments using foreach and keeping track of + # the index we are at. We do not shift the arguments out to the + # left. That is inherently quadratic, copying everything down. + + set opts {} + set mode maybeopt + set channels {} + + foreach a $args { + if {[string equal $mode optarg]} { + lappend opts $a + set mode maybeopt + continue + } elseif {[string equal $mode maybeopt]} { + if {[string match -* $a]} { + switch -exact -- $a { + -encoding - + -translation - + -eofchar { + lappend opts $a + set mode optarg + continue + } + -- { + set mode file + continue + } + default { + return -code error \ + "Bad option \"$a\",\ + expected one of\ + -encoding, -eofchar,\ + or -translation" + } + } + } + # Not an option, but a file. Change mode and fall through. + set mode file + } + # Process file arguments + + if {[string equal $a -]} { + # Stdin reference is special. + + # Test that the current options are all ok. + # For stdin we have to avoid closing it. + + set old [fconfigure stdin] + set fail [catch { + SetOptions stdin $opts + } msg] ; # {} + SetOptions stdin $old + + if {$fail} { + return -code error $msg + } + + lappend channels [list $a $opts 0] + } else { + if {![file exists $a]} { + return -code error "Cannot read file \"$a\", does not exist" + } elseif {![file isfile $a]} { + return -code error "Cannot read file \"$a\", is not a file" + } elseif {![file readable $a]} { + return -code error "Cannot read file \"$a\", read access is denied" + } + + # Test that the current options are all ok. + set c [open $a r] + set fail [catch { + SetOptions $c $opts + } msg] ; # {} + close $c + if {$fail} { + return -code error $msg + } + + lappend channels [list $a $opts [file size $a]] + } + + # We may have more options and files coming after. + set mode maybeopt + } + + if {![string equal $mode maybeopt]} { + # Argument processing stopped with arguments missing. + return -code error \ + "wrong#args: should be\ + [lindex [info level 0] 0] ?-eofchar|-translation|-encoding arg?+ file ..." + } + + set data "" + foreach c $channels { + foreach {fname opts size} $c break + + if {[string equal $fname -]} { + set old [fconfigure stdin] + SetOptions stdin $opts + append data [read stdin] + SetOptions stdin $old + continue + } + + set c [open $fname r] + SetOptions $c $opts + + if {$size > 0} { + # Used the [file size] command to get the size, which + # preallocates memory, rather than trying to grow it as + # the read progresses. + append data [read $c $size] + } else { + # if the file has zero bytes it is either empty, or + # something where [file size] reports 0 but the file + # actually has data (like the files in the /proc + # filesystem on Linux). + append data [read $c] + } + close $c + } + + return $data +} + +# ::fileutil_writeFile -- +# +# Write the specified data into the named file, +# creating it if necessary. +# +# Arguments: +# options... Options and arguments. +# filename Path to the file to write. +# data The data to write into the file +# +# Results: +# None. + +proc fileutil_writeFile {args} { + # Syntax: ?options? file data + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + Spec Writable $args opts fname data + + # Now perform the requested operation. + + file mkdir [file dirname $fname] + set c [open $fname w] + SetOptions $c $opts + puts -nonewline $c $data + close $c + return +} + +# ::fileutil_appendToFile -- +# +# Append the specified data at the end of the named file, +# creating it if necessary. +# +# Arguments: +# options... Options and arguments. +# filename Path to the file to extend. +# data The data to extend the file with. +# +# Results: +# None. + +proc fileutil_appendToFile {args} { + # Syntax: ?options? file data + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + Spec Writable $args opts fname data + + # Now perform the requested operation. + + file mkdir [file dirname $fname] + set c [open $fname a] + SetOptions $c $opts + set at [tell $c] + puts -nonewline $c $data + close $c + return $at +} + +# ::fileutil_insertIntoFile -- +# +# Insert the specified data into the named file, +# creating it if necessary, at the given locaton. +# +# Arguments: +# options... Options and arguments. +# filename Path to the file to extend. +# data The data to extend the file with. +# +# Results: +# None. + +proc fileutil_insertIntoFile {args} { + + # Syntax: ?options? file at data + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + Spec ReadWritable $args opts fname at data + + set max [file size $fname] + CheckLocation $at $max insertion + + if {[string length $data] == 0} { + # Another degenerate case, inserting nothing. + # Leave the file well enough alone. + return + } + + foreach {c o t} [Open2 $fname $opts] break + + # The degenerate cases of both appending and insertion at the + # beginning of the file allow more optimized implementations of + # the operation. + + if {$at == 0} { + puts -nonewline $o $data + fcopy $c $o + } elseif {$at == $max} { + fcopy $c $o + puts -nonewline $o $data + } else { + fcopy $c $o -size $at + puts -nonewline $o $data + fcopy $c $o + } + + Close2 $fname $t $c $o + return +} + +# ::fileutil_removeFromFile -- +# +# Remove n characters from the named file, +# starting at the given locaton. +# +# Arguments: +# options... Options and arguments. +# filename Path to the file to extend. +# at Location to start the removal from. +# n Number of characters to remove. +# +# Results: +# None. + +proc fileutil_removeFromFile {args} { + + # Syntax: ?options? file at n + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + Spec ReadWritable $args opts fname at n + + set max [file size $fname] + CheckLocation $at $max removal + CheckLength $n $at $max removal + + if {$n == 0} { + # Another degenerate case, removing nothing. + # Leave the file well enough alone. + return + } + + foreach {c o t} [Open2 $fname $opts] break + + # The degenerate cases of both removal from the beginning or end + # of the file allow more optimized implementations of the + # operation. + + if {$at == 0} { + seek $c $n current + fcopy $c $o + } elseif {($at + $n) == $max} { + fcopy $c $o -size $at + # Nothing further to copy. + } else { + fcopy $c $o -size $at + seek $c $n current + fcopy $c $o + } + + Close2 $fname $t $c $o + return +} + +# ::fileutil_replaceInFile -- +# +# Remove n characters from the named file, +# starting at the given locaton, and replace +# it with the given data. +# +# Arguments: +# options... Options and arguments. +# filename Path to the file to extend. +# at Location to start the removal from. +# n Number of characters to remove. +# data The replacement data. +# +# Results: +# None. + +proc fileutil_replaceInFile {args} { + + # Syntax: ?options? file at n data + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + Spec ReadWritable $args opts fname at n data + + set max [file size $fname] + CheckLocation $at $max replacement + CheckLength $n $at $max replacement + + if { + ($n == 0) && + ([string length $data] == 0) + } { + # Another degenerate case, replacing nothing with + # nothing. Leave the file well enough alone. + return + } + + foreach {c o t} [Open2 $fname $opts] break + + # Check for degenerate cases and handle them separately, + # i.e. strip the no-op parts out of the general implementation. + + if {$at == 0} { + if {$n == 0} { + # Insertion instead of replacement. + + puts -nonewline $o $data + fcopy $c $o + + } elseif {[string length $data] == 0} { + # Removal instead of replacement. + + seek $c $n current + fcopy $c $o + + } else { + # General replacement at front. + + seek $c $n current + puts -nonewline $o $data + fcopy $c $o + } + } elseif {($at + $n) == $max} { + if {$n == 0} { + # Appending instead of replacement + + fcopy $c $o + puts -nonewline $o $data + + } elseif {[string length $data] == 0} { + # Truncating instead of replacement + + fcopy $c $o -size $at + # Nothing further to copy. + + } else { + # General replacement at end + + fcopy $c $o -size $at + puts -nonewline $o $data + } + } else { + if {$n == 0} { + # General insertion. + + fcopy $c $o -size $at + puts -nonewline $o $data + fcopy $c $o + + } elseif {[string length $data] == 0} { + # General removal. + + fcopy $c $o -size $at + seek $c $n current + fcopy $c $o + + } else { + # General replacement. + + fcopy $c $o -size $at + seek $c $n current + puts -nonewline $o $data + fcopy $c $o + } + } + + Close2 $fname $t $c $o + return +} + +# ::fileutil_updateInPlace -- +# +# Run command prefix on the contents of the +# file and replace them with the result of +# the command. +# +# Arguments: +# options... Options and arguments. +# filename Path to the file to extend. +# cmd Command prefix to run. +# +# Results: +# None. + +proc fileutil_updateInPlace {args} { + # Syntax: ?options? file cmd + # options = -encoding ENC + # | -translation TRA + # | -eofchar ECH + # | -- + + Spec ReadWritable $args opts fname cmd + + # readFile/cat inlined ... + + set c [open $fname r] + SetOptions $c $opts + set data [read $c] + close $c + + # Transformation. Abort and do not modify the target file if an + # error was raised during this step. + + lappend cmd $data + set code [catch {uplevel 1 $cmd} res] + if {$code} { + return -code $code $res + } + + # writeFile inlined, with careful preservation of old contents + # until we are sure that the write was ok. + + if {[catch { + file rename -force $fname ${fname}.bak + + set o [open $fname w] + SetOptions $o $opts + puts -nonewline $o $res + close $o + + file delete -force ${fname}.bak + } msg]} { + if {[file exists ${fname}.bak]} { + catch { + file rename -force ${fname}.bak $fname + } + return -code error $msg + } + } + return +} + +proc fileutil_Writable {fname mv} { + upvar 1 $mv msg + if {[file exists $fname]} { + if {![file isfile $fname]} { + set msg "Cannot use file \"$fname\", is not a file" + return 0 + } elseif {![file writable $fname]} { + set msg "Cannot use file \"$fname\", write access is denied" + return 0 + } + } + return 1 +} + +proc fileutil_ReadWritable {fname mv} { + upvar 1 $mv msg + if {![file exists $fname]} { + set msg "Cannot use file \"$fname\", does not exist" + return 0 + } elseif {![file isfile $fname]} { + set msg "Cannot use file \"$fname\", is not a file" + return 0 + } elseif {![file writable $fname]} { + set msg "Cannot use file \"$fname\", write access is denied" + return 0 + } elseif {![file readable $fname]} { + set msg "Cannot use file \"$fname\", read access is denied" + return 0 + } + return 1 +} + +proc fileutil_Spec {check alist ov fv args} { + upvar 1 $ov opts $fv fname + + set n [llength $args] ; # Num more args + incr n ; # Count path as well + + set opts {} + set mode maybeopt + + set at 0 + foreach a $alist { + if {[string equal $mode optarg]} { + lappend opts $a + set mode maybeopt + incr at + continue + } elseif {[string equal $mode maybeopt]} { + if {[string match -* $a]} { + switch -exact -- $a { + -encoding - + -translation - + -eofchar { + lappend opts $a + set mode optarg + incr at + continue + } + -- { + # Stop processing. + incr at + break + } + default { + return -code error \ + "Bad option \"$a\",\ + expected one of\ + -encoding, -eofchar,\ + or -translation" + } + } + } + # Not an option, but a file. + # Stop processing. + break + } + } + + if {([llength $alist] - $at) != $n} { + # Argument processing stopped with arguments missing, or too + # many + return -code error \ + "wrong#args: should be\ + [lindex [info level 1] 0] ?-eofchar|-translation|-encoding arg? file $args" + } + + set fname [lindex $alist $at] + incr at + foreach \ + var $args \ + val [lrange $alist $at end] { + upvar 1 $var A + set A $val + } + + # Check given path ... + + if {![eval [linsert $check end $a msg]]} { + return -code error $msg + } + + return +} + +proc fileutil_Open2 {fname opts} { + set c [open $fname r] + set t [tempfile] + set o [open $t w] + + SetOptions $c $opts + SetOptions $o $opts + + return [list $c $o $t] +} + +proc fileutil_Close2 {f temp in out} { + close $in + close $out + + file copy -force $f ${f}.bak + file rename -force $temp $f + file delete -force ${f}.bak + return +} + +proc fileutil_SetOptions {c opts} { + if {![llength $opts]} return + eval [linsert $opts 0 fconfigure $c] + return +} + +proc fileutil_CheckLocation {at max label} { + if {![string is integer -strict $at]} { + return -code error \ + "Expected integer but got \"$at\"" + } elseif {$at < 0} { + return -code error \ + "Bad $label point $at, before start of data" + } elseif {$at > $max} { + return -code error \ + "Bad $label point $at, behind end of data" + } +} + +proc fileutil_CheckLength {n at max label} { + if {![string is integer -strict $n]} { + return -code error \ + "Expected integer but got \"$n\"" + } elseif {$n < 0} { + return -code error \ + "Bad $label size $n" + } elseif {($at + $n) > $max} { + return -code error \ + "Bad $label size $n, going behind end of data" + } +} + +# ::fileutil_foreachLine -- +# +# Executes a script for every line in a file. +# +# Arguments: +# var name of the variable to contain the lines +# filename name of the file to read. +# cmd The script to execute. +# +# Results: +# None. + +proc fileutil_foreachLine {var filename cmd} { + upvar 1 $var line + set fp [open $filename r] + + # -future- Use try/eval from tcllib/control + catch { + set code 0 + set result {} + while {[gets $fp line] >= 0} { + set code [catch {uplevel 1 $cmd} result] + if {($code != 0) && ($code != 4)} {break} + } + } + close $fp + + if {($code == 0) || ($code == 3) || ($code == 4)} { + return $result + } + if {$code == 1} { + global errorCode errorInfo + return \ + -code $code \ + -errorcode $errorCode \ + -errorinfo $errorInfo \ + $result + } + return -code $code $result +} + +# ::fileutil_fileType -- +# +# Do some simple heuristics to determine file type. +# +# +# Arguments: +# filename Name of the file to test. +# +# Results +# type Type of the file. May be a list if multiple tests +# are positive (eg, a file could be both a directory +# and a link). In general, the list proceeds from most +# general (eg, binary) to most specific (eg, gif), so +# the full type for a GIF file would be +# "binary graphic gif" +# +# At present, the following types can be detected: +# +# directory +# empty +# binary +# text +# script +# executable [elf, dos, ne, pe] +# binary graphic [gif, jpeg, png, tiff, bitmap, icns] +# ps, eps, pdf +# html +# xml +# message pgp +# compressed [bzip, gzip, zip, tar] +# audio [mpeg, wave] +# gravity_wave_data_frame +# link +# doctools, doctoc, and docidx documentation files. +# + +proc fileutil_fileType {filename} { + ;## existence test + if { ! [ file exists $filename ] } { + set err "file not found: '$filename'" + return -code error $err + } + ;## directory test + if { [ file isdirectory $filename ] } { + set type directory + if { ! [ catch {file readlink $filename} ] } { + lappend type link + } + return $type + } + ;## empty file test + if { ! [ file size $filename ] } { + set type empty + if { ! [ catch {file readlink $filename} ] } { + lappend type link + } + return $type + } + set bin_rx {[\x00-\x08\x0b\x0e-\x1f]} + + if { [ catch { + set fid [ open $filename r ] + fconfigure $fid -translation binary + fconfigure $fid -buffersize 1024 + fconfigure $fid -buffering full + set test [ read $fid 1024 ] + ::close $fid + } err ] } { + catch { ::close $fid } + return -code error "::fileutil_fileType: $err" + } + + if { [ regexp $bin_rx $test ] } { + set type binary + set binary 1 + } else { + set type text + set binary 0 + } + + # SF Tcllib bug [795585]. Allowing whitespace between #! + # and path of script interpreter + + set metakit 0 + + if { [ regexp {^\#\!\s*(\S+)} $test -> terp ] } { + lappend type script $terp + } elseif {([regexp "\\\[manpage_begin " $test] && + !([regexp -- {--- !doctools ---} $test] || [regexp -- "!tcl\.tk//DSL doctools//EN//" $test])) || + ([regexp -- {--- doctools ---} $test] || [regexp -- "tcl\.tk//DSL doctools//EN//" $test])} { + lappend type doctools + } elseif {([regexp "\\\[toc_begin " $test] && + !([regexp -- {--- !doctoc ---} $test] || [regexp -- "!tcl\.tk//DSL doctoc//EN//" $test])) || + ([regexp -- {--- doctoc ---} $test] || [regexp -- "tcl\.tk//DSL doctoc//EN//" $test])} { + lappend type doctoc + } elseif {([regexp "\\\[index_begin " $test] && + !([regexp -- {--- !docidx ---} $test] || [regexp -- "!tcl\.tk//DSL docidx//EN//" $test])) || + ([regexp -- {--- docidx ---} $test] || [regexp -- "tcl\.tk//DSL docidx//EN//" $test])} { + lappend type docidx + } elseif {[regexp -- "tcl\\.tk//DSL diagram//EN//" $test]} { + lappend type tkdiagram + } elseif { $binary && [ regexp {^[\x7F]ELF} $test ] } { + lappend type executable elf + } elseif { $binary && [string match "MZ*" $test] } { + if { [scan [string index $test 24] %c] < 64 } { + lappend type executable dos + } else { + binary scan [string range $test 60 61] s next + set sig [string range $test $next [expr {$next + 1}]] + if { $sig == "NE" || $sig == "PE" } { + lappend type executable [string tolower $sig] + } else { + lappend type executable dos + } + } + } elseif { $binary && [string match "BZh91AY\&SY*" $test] } { + lappend type compressed bzip + } elseif { $binary && [string match "\x1f\x8b*" $test] } { + lappend type compressed gzip + } elseif { $binary && [string range $test 257 262] == "ustar\x00" } { + lappend type compressed tar + } elseif { $binary && [string match "\x50\x4b\x03\x04*" $test] } { + lappend type compressed zip + } elseif { $binary && [string match "GIF*" $test] } { + lappend type graphic gif + } elseif { $binary && [string match "icns*" $test] } { + lappend type graphic icns bigendian + } elseif { $binary && [string match "snci*" $test] } { + lappend type graphic icns smallendian + } elseif { $binary && [string match "\x89PNG*" $test] } { + lappend type graphic png + } elseif { $binary && [string match "\xFF\xD8\xFF*" $test] } { + binary scan $test x3H2x2a5 marker txt + if { $marker == "e0" && $txt == "JFIF\x00" } { + lappend type graphic jpeg jfif + } elseif { $marker == "e1" && $txt == "Exif\x00" } { + lappend type graphic jpeg exif + } + } elseif { $binary && [string match "MM\x00\**" $test] } { + lappend type graphic tiff + } elseif { $binary && [string match "BM*" $test] && [string range $test 6 9] == "\x00\x00\x00\x00" } { + lappend type graphic bitmap + } elseif { $binary && [string match "\%PDF\-*" $test] } { + lappend type pdf + } elseif { ! $binary && [string match -nocase "*\*" $test] } { + lappend type html + } elseif { [string match "\%\!PS\-*" $test] } { + lappend type ps + if { [string match "* EPSF\-*" $test] } { + lappend type eps + } + } elseif { [string match -nocase "*\<\?xml*" $test] } { + lappend type xml + if { [ regexp -nocase {\<\!DOCTYPE\s+(\S+)} $test -> doctype ] } { + lappend type $doctype + } + } elseif { [string match {*BEGIN PGP MESSAGE*} $test] } { + lappend type message pgp + } elseif { $binary && [string match {IGWD*} $test] } { + lappend type gravity_wave_data_frame + } elseif {[string match "JL\x1a\x00*" $test] && ([file size $filename] >= 27)} { + lappend type metakit smallendian + set metakit 1 + } elseif {[string match "LJ\x1a\x00*" $test] && ([file size $filename] >= 27)} { + lappend type metakit bigendian + set metakit 1 + } elseif { $binary && [string match "RIFF*" $test] && [string range $test 8 11] == "WAVE" } { + lappend type audio wave + } elseif { $binary && [string match "ID3*" $test] } { + lappend type audio mpeg + } elseif { $binary && [binary scan $test S tmp] && [expr {$tmp & 0xFFE0}] == 65504 } { + lappend type audio mpeg + } + + # Additional checks of file contents at the end of the file, + # possibly pointing into the middle too (attached metakit, + # attached zip). + + ## Metakit File format: http://www.equi4.com/metakit/metakit-ff.html + ## Metakit database attached ? ## + + if {!$metakit && ([file size $filename] >= 27)} { + # The offsets in the footer are in always bigendian format + + if { [ catch { + set fid [ open $filename r ] + fconfigure $fid -translation binary + fconfigure $fid -buffersize 1024 + fconfigure $fid -buffering full + seek $fid -16 end + set test [ read $fid 16 ] + ::close $fid + } err ] } { + catch { ::close $fid } + return -code error "::fileutil_fileType: $err" + } + + binary scan $test IIII __ hdroffset __ __ + set hdroffset [expr {[file size $filename] - 16 - $hdroffset}] + + # Further checks iff the offset is actually inside the file. + + if {($hdroffset >= 0) && ($hdroffset < [file size $filename])} { + # Seek to the specified location and try to match a metakit header + # at this location. + + if { [ catch { + set fid [ open $filename r ] + fconfigure $fid -translation binary + fconfigure $fid -buffersize 1024 + fconfigure $fid -buffering full + seek $fid $hdroffset start + set test [ read $fid 16 ] + ::close $fid + } err ] } { + catch { ::close $fid } + return -code error "::fileutil_fileType: $err" + } + + if {[string match "JL\x1a\x00*" $test]} { + lappend type attached metakit smallendian + set metakit 1 + } elseif {[string match "LJ\x1a\x00*" $test]} { + lappend type attached metakit bigendian + set metakit 1 + } + } + } + + ## Zip File Format: http://zziplib.sourceforge.net/zzip-parse.html + ## http://www.pkware.com/products/enterprise/white_papers/appnote.html + + + ;## lastly, is it a link? + if { ! [ catch {file readlink $filename} ] } { + lappend type link + } + return $type +} + +# ::fileutil_tempdir -- +# +# Return the correct directory to use for temporary files. +# Python attempts this sequence, which seems logical: +# +# 1. The directory named by the `TMPDIR' environment variable. +# +# 2. The directory named by the `TEMP' environment variable. +# +# 3. The directory named by the `TMP' environment variable. +# +# 4. A platform-specific location: +# * On Macintosh, the `Temporary Items' folder. +# +# * On Windows, the directories `C:\\TEMP', `C:\\TMP', +# `\\TEMP', and `\\TMP', in that order. +# +# * On all other platforms, the directories `/tmp', +# `/var/tmp', and `/usr/tmp', in that order. +# +# 5. As a last resort, the current working directory. +# +# The code here also does +# +# 0. The directory set by invoking tempdir with an argument. +# If this is present it is used exclusively. +# +# Arguments: +# None. +# +# Side Effects: +# None. +# +# Results: +# The directory for temporary files. + +proc fileutil_tempdir {args} { + if {[llength $args] > 1} { + return -code error {wrong#args: should be "::fileutil_tempdir ?path?"} + } elseif {[llength $args] == 1} { + global tempdir + set tempdir [lindex $args 0] + global tempdirSet + set tempdirSet 1 + return + } + return [fileutil_Normalize [TempDir]] +} + +proc fileutil_tempdirReset {} { + global tempdir + set tempdir {} + global tempdirSet + set tempdirSet 0 + return +} + +proc fileutil_TempDir {} { + global tcl_platform env tempdir tempdirSet + + set attempdirs [list] + set problems {} + + if {$tempdirSet} { + lappend attempdirs $tempdir + lappend problems {User/Application specified tempdir} + } else { + foreach tmp {TMPDIR TEMP TMP} { + if { [info exists env($tmp)] } { + lappend attempdirs $env($tmp) + } else { + lappend problems "No environment variable $tmp" + } + } + + switch $tcl_platform(platform) { + windows { + lappend attempdirs "C:\\TEMP" "C:\\TMP" "\\TEMP" "\\TMP" + } + macintosh { + lappend attempdirs $env(TRASH_FOLDER) ;# a better place? + } + default { + lappend attempdirs \ + [file join / tmp] \ + [file join / var tmp] \ + [file join / usr tmp] + } + } + + lappend attempdirs [pwd] + } + + foreach tmp $attempdirs { + if { [file isdirectory $tmp] && [file writable $tmp] } { + return $tmp + } elseif { ![file isdirectory $tmp] } { + lappend problems "Not a directory: $tmp" + } else { + lappend problems "Not writable: $tmp" + } + } + + # Fail if nothing worked. + return -code error "Unable to determine a proper directory for temporary files\n[join $problems \n]" +} + +set tempdir {} +set tempdirSet 0 + +# ::fileutil_tempfile -- +# +# generate a temporary file name suitable for writing to +# the file name will be unique, writable and will be in the +# appropriate system specific temp directory +# Code taken from http://mini.net/tcl/772 attributed to +# Igor Volobouev and anon. +# +# Arguments: +# prefix - a prefix for the filename, p +# Results: +# returns a file name +# + +proc fileutil_tempfile {{prefix {}}} { + return [fileutil_Normalize [TempFile $prefix]] +} + +proc fileutil_TempFile {prefix} { + set tmpdir [tempdir] + + set chars "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + set nrand_chars 10 + set maxtries 10 + set access [list RDWR CREAT EXCL] + set permission 0600 + set channel "" + set checked_dir_writable 0 + + for {set i 0} {$i < $maxtries} {incr i} { + set newname $prefix + for {set j 0} {$j < $nrand_chars} {incr j} { + append newname [string index $chars \ + [expr {int(rand()*62)}]] + } + set newname [file join $tmpdir $newname] + + if {[catch {open $newname $access $permission} channel]} { + if {!$checked_dir_writable} { + set dirname [file dirname $newname] + if {![file writable $dirname]} { + return -code error "Directory $dirname is not writable" + } + set checked_dir_writable 1 + } + } else { + # Success + close $channel + return $newname + } + + } + if {[string compare $channel ""]} { + return -code error "Failed to open a temporary file: $channel" + } else { + return -code error "Failed to find an unused temporary file name" + } +} + +# ::fileutil_install -- +# +# Tcl version of the 'install' command, which copies files from +# one places to another and also optionally sets some attributes +# such as group, owner, and permissions. +# +# Arguments: +# -m Change the file permissions to the specified +# value. Valid arguments are those accepted by +# file attributes -permissions +# +# Results: +# None. + +# TODO - add options for group/owner manipulation. + +proc fileutil_install {args} { + set options { + {m.arg "" "Set permission mode"} + } + set usage ": [lindex [info level 0] 0]\ +\[options] source destination \noptions:" + array set params [::cmdline::getoptions args $options $usage] + # Args should now just be the source and destination. + if { [llength $args] < 2 } { + return -code error $usage + } + set src [lindex $args 0] + set dst [lindex $args 1] + file copy -force $src $dst + if { $params(m) != "" } { + set targets [::fileutil_find $dst] + foreach fl $targets { + file attributes $fl -permissions $params(m) + } + } +} + +# ### ### ### ######### ######### ######### + +proc fileutil_lexnormalize {sp} { + set spx [file split $sp] + + # Resolution of embedded relative modifiers (., and ..). + + if { + ([lsearch -exact $spx . ] < 0) && + ([lsearch -exact $spx ..] < 0) + } { + # Quick path out if there are no relative modifiers + return $sp + } + + set absolute [expr {![string equal [file pathtype $sp] relative]}] + # A volumerelative path counts as absolute for our purposes. + + set sp $spx + set np {} + set noskip 1 + + while {[llength $sp]} { + set ele [lindex $sp 0] + set sp [lrange $sp 1 end] + set islast [expr {[llength $sp] == 0}] + + if {[string equal $ele ".."]} { + if { + ($absolute && ([llength $np] > 1)) || + (!$absolute && ([llength $np] >= 1)) + } { + # .. : Remove the previous element added to the + # new path, if there actually is enough to remove. + set np [lrange $np 0 end-1] + } + } elseif {[string equal $ele "."]} { + # Ignore .'s, they stay at the current location + continue + } else { + # A regular element. + lappend np $ele + } + } + if {[llength $np] > 0} { + return [eval [linsert $np 0 file join]] + # 8.5: return [file join {*}$np] + } + return {} +} + +# ### ### ### ######### ######### ######### +## Forward compatibility. Some routines require path normalization, +## something we have supported by the builtin 'file' only since Tcl +## 8.4. For versions of Tcl before that, to be supported by the +## module, we implement a normalizer in Tcl itself. Slow, but working. + +if {[package vcompare [package provide Tcl] 8.4] < 0} { + # Pre 8.4. We do not have 'file-normalize'. We create an + # approximation for it based on earlier commands. + + # ... Hm. This is lexical normalization. It does not resolve + # symlinks in the path to their origin. + + proc fileutil_Normalize {sp} { + set sp [file split $sp] + + # Conversion of the incoming path to absolute. + if {[string equal [file pathtype [lindex $sp 0]] "relative"]} { + set sp [file split [eval [list file join [pwd]] $sp]] + } + + # Resolution of symlink components, and embedded relative + # modifiers (., and ..). + + set np {} + set noskip 1 + while {[llength $sp]} { + set ele [lindex $sp 0] + set sp [lrange $sp 1 end] + set islast [expr {[llength $sp] == 0}] + + if {[string equal $ele ".."]} { + if {[llength $np] > 1} { + # .. : Remove the previous element added to the + # new path, if there actually is enough to remove. + set np [lrange $np 0 end-1] + } + } elseif {[string equal $ele "."]} { + # Ignore .'s, they stay at the current location + continue + } else { + # A regular element. If it is not the last component + # then check if the combination is a symlink, and if + # yes, resolve it. + + lappend np $ele + + if {!$islast && $noskip} { + # The flag 'noskip' is technically not required, + # just 'file exists'. However if a path P does not + # exist, then all longer paths starting with P can + # not exist either, and using the flag to store + # this knowledge then saves us a number of + # unnecessary stat calls. IOW this a performance + # optimization. + + set p [eval file join $np] + set noskip [file exists $p] + if {$noskip} { + if {[string equal link [file type $p]]} { + set dst [file readlink $p] + + # We always push the destination in front of + # the source path (in expanded form). So that + # we handle .., .'s, and symlinks inside of + # this path as well. An absolute path clears + # the result, a relative one just removes the + # last, now resolved component. + + set sp [eval [linsert [file split $dst] 0 linsert $sp 0]] + + if {![string equal relative [file pathtype $dst]]} { + # Absolute|volrelative destination, clear + # result, we have to start over. + set np {} + } else { + # Relative link, just remove the resolved + # component again. + set np [lrange $np 0 end-1] + } + } + } + } + } + } + if {[llength $np] > 0} { + return [eval file join $np] + } + return {} + } +} else { + proc fileutil_Normalize {sp} { + file-normalize $sp + } +} + +# ::fileutil_relative -- +# +# Taking two _directory_ paths, a base and a destination, computes the path +# of the destination relative to the base. +# +# Arguments: +# base The path to make the destination relative to. +# dst The destination path +# +# Results: +# The path of the destination, relative to the base. + +proc fileutil_relative {base dst} { + # Ensure that the link to directory 'dst' is properly done relative to + # the directory 'base'. + + if {![string equal [file pathtype $base] [file pathtype $dst]]} { + return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)" + } + + set base [fileutil_lexnormalize [file join [pwd] $base]] + set dst [fileutil_lexnormalize [file join [pwd] $dst]] + + set save $dst + set base [file split $base] + set dst [file split $dst] + + while {[string equal [lindex $dst 0] [lindex $base 0]]} { + set dst [lrange $dst 1 end] + set base [lrange $base 1 end] + if {![llength $dst]} {break} + } + + set dstlen [llength $dst] + set baselen [llength $base] + + if {($dstlen == 0) && ($baselen == 0)} { + # Cases: + # (a) base == dst + + set dst . + } else { + # Cases: + # (b) base is: base/sub = sub + # dst is: base = {} + + # (c) base is: base = {} + # dst is: base/sub = sub + + while {$baselen > 0} { + set dst [linsert $dst 0 ..] + incr baselen -1 + } + # 8.5: set dst [file join {*}$dst] + set dst [eval [linsert $dst 0 file join]] + } + + return $dst +} + +# ::fileutil_relativeUrl -- +# +# Taking two _file_ paths, a base and a destination, computes the path +# of the destination relative to the base, from the inside of the base. +# +# This is how a browser resolves relative links in a file, hence the +# url in the command name. +# +# Arguments: +# base The file path to make the destination relative to. +# dst The destination file path +# +# Results: +# The path of the destination file, relative to the base file. + +proc fileutil_relativeUrl {base dst} { + # Like 'relative', but for links from _inside_ a file to a + # different file. + + if {![string equal [file pathtype $base] [file pathtype $dst]]} { + return -code error "Unable to compute relation for paths of different pathtypes: [file pathtype $base] vs. [file pathtype $dst], ($base vs. $dst)" + } + + set base [fileutil_lexnormalize [file join [pwd] $base]] + set dst [fileutil_lexnormalize [file join [pwd] $dst]] + + set basedir [file dirname $base] + set dstdir [file dirname $dst] + + set dstdir [relative $basedir $dstdir] + + # dstdir == '.' on input => dstdir output has trailing './'. Strip + # this superfluous segment off. + + if {[string equal $dstdir "."]} { + return [file tail $dst] + } elseif {[string equal [file tail $dstdir] "."]} { + return [file join [file dirname $dstdir] [file tail $dst]] + } else { + return [file join $dstdir [file tail $dst]] + } +} + +# ::fileutil_fullnormalize -- +# +# Normalizes a path completely. I.e. a symlink in the last +# element is resolved as well, not only symlinks in the higher +# elements. +# +# Arguments: +# path The path to normalize +# +# Results: +# The input path with all symlinks resolved. + +proc fileutil_fullnormalize {path} { + # When encountering symlinks in a file copy operation Tcl copies + # the link, not the contents of the file it references. There are + # situations there this is not acceptable. For these this command + # resolves all symbolic links in the path, including in the last + # element of the path. A "file copy" using the return value of + # this command copies an actual file, it will not encounter + # symlinks. + + # BUG / WORKAROUND. Using the / instead of the join seems to work + # around a bug in the path handling on windows which can break the + # core 'file-normalize' for symbolic links. This was exposed by + # the find testsuite which could not reproduced outside. I believe + # that there is some deep path bug in the core triggered under + # special circumstances. Use of / likely forces a refresh through + # the string rep and so avoids the problem with the path intrep. + + return [file dirname [fileutil_Normalize $path/__dummy__]] + #return [file dirname [fileutil_Normalize [file join $path __dummy__]]] +} + +set tclver [package present Tcl] +if {$tclver ne {} && [package vsatisfies [package present Tcl] 8.5]} { + # Tcl 8.5+. + # We have to check readability of "current" on our own, glob + # changed to error out instead of returning nothing. + + proc fileutil_ACCESS {args} {} + + proc fileutil_GLOBF {current} { + if {![file readable $current]} { + return {} + } + if {([file type $current] eq "link") && + !([file exists [file readlink $current]] && + [file readable [file readlink $current]])} { + return {} + } + + set res [lsort -unique [concat \ + [glob -nocomplain -directory $current -types f -- *] \ + [glob -nocomplain -directory $current -types {hidden f} -- *]]] + + # Look for broken links (They are reported as neither file nor directory). + foreach l [lsort -unique [concat \ + [glob -nocomplain -directory $current -types l -- *] \ + [glob -nocomplain -directory $current -types {hidden l} -- *]]] { + if {[file isfile $l]} continue + if {[file isdirectory $l]} continue + lappend res $l + } + return [lsort -unique $res] + } + + proc fileutil_GLOBD {current} { + if {![file readable $current]} { + return {} + } + if {([file type $current] eq "link") && + !([file exists [file readlink $current]] && + [file readable [file readlink $current]])} { + return {} + } + + lsort -unique [concat \ + [glob -nocomplain -directory $current -types d -- *] \ + [glob -nocomplain -directory $current -types {hidden d} -- *]] + } + +} ADDED autosetup/lib/formatting.tcl Index: autosetup/lib/formatting.tcl ================================================================== --- /dev/null +++ autosetup/lib/formatting.tcl @@ -0,0 +1,52 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides common text formatting + +# This is designed for documenation which looks like: +# code {...} +# or +# code { +# ... +# ... +# } +# In the second case, we need to work out the indenting +# and strip it from all lines but preserve the remaining indenting. +# Note that all lines need to be indented with the same initial +# spaces/tabs. +# +# Returns a list of lines with the indenting removed. +# +proc parse_code_block {text} { + # If the text begins with newline, take the following text, + # otherwise just return the original + if {![regexp "^\n(.*)" $text -> text]} { + return [list [string trim $text]] + } + + # And trip spaces off the end + set text [string trimright $text] + + set min 100 + # Examine each line to determine the minimum indent + foreach line [split $text \n] { + if {$line eq ""} { + # Ignore empty lines for the indent calculation + continue + } + regexp "^(\[ \t\]*)" $line -> indent + set len [string length $indent] + if {$len < $min} { + set min $len + } + } + + # Now make a list of lines with this indent removed + set lines {} + foreach line [split $text \n] { + lappend lines [string range $line $min end] + } + + # Return the result + return $lines +} ADDED autosetup/lib/getopt.tcl Index: autosetup/lib/getopt.tcl ================================================================== --- /dev/null +++ autosetup/lib/getopt.tcl @@ -0,0 +1,79 @@ +# Copyright (c) 2006 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Simple getopt module + +# Parse everything out of the argv list which looks like an option +# Knows about --enable-thing and --disable-thing as alternatives for --thing=0 or --thing=1 +# Everything which doesn't look like an option, or is after --, is left unchanged +proc getopt {argvname} { + upvar $argvname argv + set nargv {} + + for {set i 0} {$i < [llength $argv]} {incr i} { + set arg [lindex $argv $i] + + #dputs arg=$arg + + if {$arg eq "--"} { + # End of options + incr i + lappend nargv {*}[lrange $argv $i end] + break + } + + if {[regexp {^--([^=][^=]+)=(.*)$} $arg -> name value]} { + lappend opts($name) $value + } elseif {[regexp {^--(enable-|disable-)?([^=]*)$} $arg -> prefix name]} { + if {$prefix eq "disable-"} { + set value 0 + } else { + set value 1 + } + lappend opts($name) $value + } else { + lappend nargv $arg + } + } + + #puts "getopt: argv=[join $argv] => [join $nargv]" + #parray opts + + set argv $nargv + + return [array get opts] +} + +proc opt_val {optarrayname options {default {}}} { + upvar $optarrayname opts + + set result {} + + foreach o $options { + if {[info exists opts($o)]} { + lappend result {*}$opts($o) + } + } + if {[llength $result] == 0} { + return $default + } + return $result +} + +proc opt_bool {optarrayname args} { + upvar $optarrayname opts + + # Support the args being passed as a list + if {[llength $args] == 1} { + set args [lindex $args 0] + } + + foreach o $args { + if {[info exists opts($o)]} { + if {"1" in $opts($o) || "yes" in $opts($o)} { + return 1 + } + } + } + return 0 +} ADDED autosetup/lib/help.tcl Index: autosetup/lib/help.tcl ================================================================== --- /dev/null +++ autosetup/lib/help.tcl @@ -0,0 +1,162 @@ +# Copyright (c) 2010 WorkWare Systems http://workware.net.au/ +# All rights reserved + +# Module which provides usage, help and the command reference + +proc autosetup_help {what} { + use_pager + + puts "Usage: [file tail $::autosetup(exe)] \[options\] \[settings\]\n" + puts "This is [autosetup_version], a build environment \"autoconfigurator\"" + puts "See the documentation online at http://msteveb.github.com/autosetup/\n" + + if {$what eq "local"} { + if {[file exists $::autosetup(autodef)]} { + # This relies on auto.def having a call to 'options' + # which will display options and quit + source $::autosetup(autodef) + } else { + options-show + } + } else { + incr ::autosetup(showhelp) + if {[catch {use $what}]} { + user-error "Unknown module: $what" + } else { + options-show + } + } + exit 0 +} + +# If not already paged and stdout is a tty, pipe the output through the pager +# This is done by reinvoking autosetup with --nopager added +proc use_pager {} { + if {![opt-bool nopager] && [getenv PAGER ""] ne "" && [isatty? stdin] && [isatty? stdout]} { + if {[catch { + exec [info nameofexecutable] $::argv0 --nopager {*}$::argv |& {*}[getenv PAGER] >@stdout <@stdin 2>@stderr + } msg opts] == 1} { + if {[dict get $opts -errorcode] eq "NONE"} { + # an internal/exec error + puts stderr $msg + exit 1 + } + } + exit 0 + } +} + +# Outputs the autosetup references in one of several formats +proc autosetup_reference {{type text}} { + + use_pager + + switch -glob -- $type { + wiki {use wiki-formatting} + ascii* {use asciidoc-formatting} + md - markdown {use markdown-formatting} + default {use text-formatting} + } + + title "[autosetup_version] -- Command Reference" + + section {Introduction} + + p { + See http://msteveb.github.com/autosetup/ for the online documentation for 'autosetup' + } + + p { + 'autosetup' provides a number of built-in commands which + are documented below. These may be used from 'auto.def' to test + for features, define variables, create files from templates and + other similar actions. + } + + automf_command_reference + + exit 0 +} + +proc autosetup_output_block {type lines} { + if {[llength $lines]} { + switch $type { + code { + codelines $lines + } + p { + p [join $lines] + } + list { + foreach line $lines { + bullet $line + } + nl + } + } + } +} + +# Generate a command reference from inline documentation +proc automf_command_reference {} { + lappend files $::autosetup(prog) + lappend files {*}[lsort [glob -nocomplain $::autosetup(libdir)/*.tcl]] + + section "Core Commands" + set type p + set lines {} + set cmd {} + + foreach file $files { + set f [open $file] + while {![eof $f]} { + set line [gets $f] + + # Find lines starting with "# @*" and continuing through the remaining comment lines + if {![regexp {^# @(.*)} $line -> cmd]} { + continue + } + + # Synopsis or command? + if {$cmd eq "synopsis:"} { + section "Module: [file rootname [file tail $file]]" + } else { + subsection $cmd + } + + set lines {} + set type p + + # Now the description + while {![eof $f]} { + set line [gets $f] + + if {![regexp {^#(#)? ?(.*)} $line -> hash cmd]} { + break + } + if {$hash eq "#"} { + set t code + } elseif {[regexp {^- (.*)} $cmd -> cmd]} { + set t list + } else { + set t p + } + + #puts "hash=$hash, oldhash=$oldhash, lines=[llength $lines], cmd=$cmd" + + if {$t ne $type || $cmd eq ""} { + # Finish the current block + autosetup_output_block $type $lines + set lines {} + set type $t + } + if {$cmd ne ""} { + lappend lines $cmd + } + } + + autosetup_output_block $type $lines + } + close $f + } +} ADDED autosetup/lib/init.tcl Index: autosetup/lib/init.tcl ================================================================== --- /dev/null +++ autosetup/lib/init.tcl @@ -0,0 +1,56 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module to help create auto.def and configure + +proc autosetup_init {type} { + set help 0 + if {$type in {? help}} { + incr help + } elseif {![dict exists $::autosetup(inittypes) $type]} { + puts "Unknown type, --init=$type" + incr help + } + if {$help} { + puts "Use one of the following types (e.g. --init=make)\n" + foreach type [lsort [dict keys $::autosetup(inittypes)]] { + lassign [dict get $::autosetup(inittypes) $type] desc + # XXX: Use the options-show code to wrap the description + puts [format "%-10s %s" $type $desc] + } + exit 0 + } + lassign [dict get $::autosetup(inittypes) $type] desc script + + puts "Initialising $type: $desc\n" + + # All initialisations happens in the top level srcdir + cd $::autosetup(srcdir) + + uplevel #0 $script + + exit 0 +} + +proc autosetup_add_init_type {type desc script} { + dict set ::autosetup(inittypes) $type [list $desc $script] +} + +# This is for in creating build-system init scripts +# +# If the file doesn't exist, create it containing $contents +# If the file does exist, only overwrite if --force is specified. +# +proc autosetup_check_create {filename contents} { + if {[file exists $filename]} { + if {!$::autosetup(force)} { + puts "I see $filename already exists." + return + } else { + puts "I will overwrite the existing $filename because you used --force." + } + } else { + puts "I don't see $filename, so I will create it." + } + writefile $filename $contents +} ADDED autosetup/lib/install.tcl Index: autosetup/lib/install.tcl ================================================================== --- /dev/null +++ autosetup/lib/install.tcl @@ -0,0 +1,119 @@ +# Copyright (c) 2006-2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which can install autosetup + +proc autosetup_install {dir} { + if {[catch { + cd $dir + file mkdir autosetup + + set f [open autosetup/autosetup w] + + set publicmodules $::autosetup(libdir)/default.auto + + + # First the main script, but only up until "CUT HERE" + set in [open $::autosetup(dir)/autosetup] + while {[gets $in buf] >= 0} { + if {$buf ne "##-- CUT HERE --##"} { + puts $f $buf + continue + } + + # Insert the static modules here + # i.e. those which don't contain @synopsis: + puts $f "set autosetup(installed) 1" + set buf [readfile $::autosetup(libdir)/core.tcl] + set modname core + puts $f $buf + puts $f "# ----- module $modname -----" + puts $f "\nset modsource($modname) \{" + puts $f "\}\n" + + foreach file [lsort [glob $::autosetup(libdir)/*.tcl]] { + if {[file tail $file] eq "core.tcl"} continue + set buf [readfile $file] + if {[string match "*\n# @synopsis:*" $buf]} { + lappend publicmodules $file + continue + } + set modname [file rootname [file tail $file]] + puts $f "# ----- module $modname -----" + puts $f "\nset modsource($modname) \{" + puts $f $buf + puts $f "\}\n" + } + } + close $in + close $f + exec chmod 755 autosetup/autosetup + + # Install public modules + foreach file $publicmodules { + autosetup_install_file $file autosetup + } + + # Install support files + foreach file {config.guess config.sub jimsh0.c find-tclsh test-tclsh LICENSE} { + autosetup_install_file $::autosetup(dir)/$file autosetup + } + foreach file [glob -nocomplain $::autosetup(dir)/scripts/*] { + autosetup_install_file $::autosetup(dir)/scripts/[file tail $file] autosetup + } + exec chmod 755 autosetup/config.sub autosetup/config.guess autosetup/find-tclsh + + writefile autosetup/README.autosetup \ + "This is [autosetup_version]. See http://msteveb.github.com/autosetup/\n" + + } error]} { + user-error "Failed to install autosetup: $error" + } + puts "Installed [autosetup_version] to autosetup/" + + # Now create 'configure' if necessary + autosetup_create_configure + + exit 0 +} + +proc autosetup_create_configure {} { + if {[file exists configure]} { + if {!$::autosetup(force)} { + # Could this be an autosetup configure? + if {![string match "*\nWRAPPER=*" [readfile configure]]} { + puts "I see configure, but not created by autosetup, so I won't overwrite it." + puts "Remove it or use --force to overwrite." + return + } + } else { + puts "I will overwrite the existing configure because you used --force." + } + } else { + puts "I don't see configure, so I will create it." + } + writefile configure \ +{#!/bin/sh +dir="`dirname "$0"`/autosetup" +WRAPPER="$0"; export WRAPPER; exec "`$dir/find-tclsh`" "$dir/autosetup" "$@" +} + catch {exec chmod 755 configure} +} + +# Append the contents of $file to filehandle $f +proc autosetup_install_append {f file} { + set in [open $file] + puts $f [read $in] + close $in +} + +proc autosetup_install_file {file dir} { + if {![file exists $file]} { + error "Missing installation file '$file'" + } + writefile [file join $dir [file tail $file]] [readfile $file]\n +} + +if {$::autosetup(installed)} { + user-error "autosetup can only be installed from development source, not from installed copy" +} ADDED autosetup/lib/markdown-formatting.tcl Index: autosetup/lib/markdown-formatting.tcl ================================================================== --- /dev/null +++ autosetup/lib/markdown-formatting.tcl @@ -0,0 +1,68 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# markdown format (kramdown syntax) + +use formatting + +proc para {text} { + regsub -all "\[ \t\n\]+" [string trim $text] " " text + regsub -all {([^a-zA-Z])'([^']*)'} $text {\1**`\2`**} text + regsub -all {^'([^']*)'} $text {**`\1`**} text + regsub -all {(http[^ \t\n]*)} $text {[\1](\1)} text + return $text +} +proc title {text} { + underline [para $text] = + nl +} +proc p {text} { + puts [para $text] + nl +} +proc codelines {lines} { + puts "~~~~~~~~~~~~" + foreach line $lines { + puts $line + } + puts "~~~~~~~~~~~~" + nl +} +proc code {text} { + puts "~~~~~~~~~~~~" + foreach line [parse_code_block $text] { + puts $line + } + puts "~~~~~~~~~~~~" + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[para $text]" - + nl +} +proc subsection {text} { + puts "### `$text`" + nl +} +proc bullet {text} { + puts "* [para $text]" +} +proc defn {first args} { + puts "^" + set defn [string trim [join $args \n]] + if {$first ne ""} { + puts "**${first}**" + puts -nonewline ": " + regsub -all "\n\n" $defn "\n: " defn + } + puts "$defn" +} ADDED autosetup/lib/misc.tcl Index: autosetup/lib/misc.tcl ================================================================== --- /dev/null +++ autosetup/lib/misc.tcl @@ -0,0 +1,173 @@ +# Copyright (c) 2007-2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module containing misc procs useful to modules +# Largely for platform compatibility + +set autosetup(istcl) [info exists ::tcl_library] +set autosetup(iswin) [string equal windows $tcl_platform(platform)] + +if {$autosetup(iswin)} { + # mingw/windows separates $PATH with semicolons + # and doesn't have an executable bit + proc split-path {} { + split [getenv PATH .] {;} + } + proc file-isexec {exec} { + # Basic test for windows. We ignore .bat + if {[file isfile $exec] || [file isfile $exec.exe]} { + return 1 + } + return 0 + } +} else { + # unix separates $PATH with colons and has and executable bit + proc split-path {} { + split [getenv PATH .] : + } + proc file-isexec {exec} { + file executable $exec + } +} + +# Assume that exec can return stdout and stderr +proc exec-with-stderr {args} { + exec {*}$args 2>@1 +} + +if {$autosetup(istcl)} { + # Tcl doesn't have the env command + proc getenv {name args} { + if {[info exists ::env($name)]} { + return $::env($name) + } + if {[llength $args]} { + return [lindex $args 0] + } + return -code error "environment variable \"$name\" does not exist" + } + proc isatty? {channel} { + dict exists [fconfigure $channel] -xchar + } +} else { + if {$autosetup(iswin)} { + # On Windows, backslash convert all environment variables + # (Assume that Tcl does this for us) + proc getenv {name args} { + string map {\\ /} [env $name {*}$args] + } + } else { + # Jim on unix is simple + alias getenv env + } + proc isatty? {channel} { + set tty 0 + catch { + # isatty is a recent addition to Jim Tcl + set tty [$channel isatty] + } + return $tty + } +} + +# In case 'file normalize' doesn't exist +# +proc file-normalize {path} { + if {[catch {file normalize $path} result]} { + if {$path eq ""} { + return "" + } + set oldpwd [pwd] + if {[file isdir $path]} { + cd $path + set result [pwd] + } else { + cd [file dirname $path] + set result [file join [pwd] [file tail $path]] + } + cd $oldpwd + } + return $result +} + +# If everything is working properly, the only errors which occur +# should be generated in user code (e.g. auto.def). +# By default, we only want to show the error location in user code. +# We use [info frame] to achieve this, but it works differently on Tcl and Jim. +# +# This is designed to be called for incorrect usage in auto.def, via autosetup-error +# +proc error-location {msg} { + if {$::autosetup(debug)} { + return -code error $msg + } + # Search back through the stack trace for the first error in a .def file + for {set i 1} {$i < [info level]} {incr i} { + if {$::autosetup(istcl)} { + array set info [info frame -$i] + } else { + lassign [info frame -$i] info(caller) info(file) info(line) + } + if {[string match *.def $info(file)]} { + return "[relative-path $info(file)]:$info(line): Error: $msg" + } + #puts "Skipping $info(file):$info(line)" + } + return $msg +} + +# If everything is working properly, the only errors which occur +# should be generated in user code (e.g. auto.def). +# By default, we only want to show the error location in user code. +# We use [info frame] to achieve this, but it works differently on Tcl and Jim. +# +# This is designed to be called for incorrect usage in auto.def, via autosetup-error +# +proc error-stacktrace {msg} { + if {$::autosetup(debug)} { + return -code error $msg + } + # Search back through the stack trace for the first error in a .def file + for {set i 1} {$i < [info level]} {incr i} { + if {$::autosetup(istcl)} { + array set info [info frame -$i] + } else { + lassign [info frame -$i] info(caller) info(file) info(line) + } + if {[string match *.def $info(file)]} { + return "[relative-path $info(file)]:$info(line): Error: $msg" + } + #puts "Skipping $info(file):$info(line)" + } + return $msg +} + +# Given the return from [catch {...} msg opts], returns an appropriate +# error message. A nice one for Jim and a less-nice one for Tcl. +# If 'fulltrace' is set, a full stack trace is provided. +# Otherwise a simple message is provided. +# +# This is designed for developer errors, e.g. in module code or auto.def code +# +# +proc error-dump {msg opts fulltrace} { + if {$::autosetup(istcl)} { + if {$fulltrace} { + return "Error: [dict get $opts -errorinfo]" + } else { + return "Error: $msg" + } + } else { + lassign $opts(-errorinfo) p f l + if {$f ne ""} { + set result "$f:$l: Error: " + } + append result "$msg\n" + if {$fulltrace} { + append result [stackdump $opts(-errorinfo)] + } + + # Remove the trailing newline + string trim $result + } +} ADDED autosetup/lib/odie.tcl Index: autosetup/lib/odie.tcl ================================================================== --- /dev/null +++ autosetup/lib/odie.tcl @@ -0,0 +1,563 @@ +# @synopsis: +# +# ODIE modules adds teacup platform data and integration with +# sherpa +# +use system codebale +# Build procs for this modules + +options { +nodots => "Suppress dots in version numbers in lib names" +pkgdir: => "Where to install the package (default $prefix/lib)" +shlibver:=0.0 => "Shared lib version" +debugbld => "Debug build: symbols, asserts, etc." +nothreads => "Turn off threads" +static => "Build a static library (default off)" +} + +proc odie_tea_init conflist { + array set project $conflist + + set nodots [lindex [opt-val nodots] end] + if {$nodots eq {}} { + if {$::odie(windows)} { + set nodots 1 + } + } elseif {[string is true -strict $nodots]} { + set nodots 1 + } else { + set nodots 0 + } + + set libver $::project(pkgvers) + lassign [regsub {^(\d)\.(\d)\.\d+$} [package provide Tcl] {\1.\2}] tclver + if {[string is true -strict $nodots]} { + set libver [string map {. ""} $libver] + set tclver [string map {. ""} $tclver] + } + set prefix [get-define prefix] + set pkgdir [lindex [opt-val pkgdir] end] + if { $pkgdir eq {}} { + set pkgdir [file join $prefix lib] + } + define pkgdir $pkgdir + define docdir [file join $prefix share doc] + define exadir [file join $prefix share examples] + define datarootdir [file join $prefix share] + + + if {[file exists [file join $project(srcdir) .. odie odieConfig.tcl]]} { + source [file join $project(srcdir) .. odie odieConfig.tcl] + } else { + set prefix [get-define prefix] + if {$prefix eq {}} { + foreach path { + /odie + ~/odie + c:/odie + /opt/local + /opt/odie + /opt/local/odie + /usr/local/odie + } { + set cffile [file join $path sandbox odie odieConfig.tcl] + if {[file exists $cffile]} { + set prefix [file normalize $path] + source $cffile + break + } + } + } + if {$prefix eq {} } { + error "No Odie detected" + } + if {![file exists [file join $prefix sandbox odie odieConfig.tcl]]} { + error "odieConfig.tcl not found" + } + } + + foreach {field} [lsort -dictionary [array names package]] { + define PACKAGE_[string toupper $field] $package($field) + define PKG_[string toupper $field] $package($field) + } + + define PKG_NAME $::project(name) + define PKG_VER $::project(pkgvers) + + set shlibver [lindex [opt-val shlibver 0.0] end] + define SHLIB_VER $shlibver + if {$shlibver ni {0.0 {}}} { + append shlibspec [format [get-define SH_SOEXTVER] $shlibver] + } else { + set shlibspec [get-define SH_SOEXT] + } + define SHLIB_SPEC $shlibspec + + define EXT_INC_SPEC "" + define EXT_LIB_DIR_SPEC "" + define EXT_LIB_SPEC "" + + define TCL_INC_SPEC $::odie_tcl(include_spec) + if {"tk" in $project(libs)} { + define TCL_LIB_SPEC "$::odie_tcl(build_stub_lib_spec) $::odie_tk(build_stub_lib_spec)" + } else { + define TCL_LIB_SPEC $::odie_tcl(build_stub_lib_spec) + } + + set ::odie_package(name) $::project(pkgname) + set ::odie_package(version) $::project(pkgvers) + set ::odie_package(ver) $::project(pkgvers) + set ::odie_package(libfile) lib${::project(name)}$libver[get-define SHLIB_SPEC] + set ::odie_package(lib_file) $::odie_package(libfile) + if {"tk" in $project(libs)} { + set ::odie_package(libs) $::odie_tk(libs) + } else { + set ::odie_package(libs) $::odie_tcl(libs) + } + foreach lib $project(libs) { + if { $lib in {tcl tk} } continue + if { "-l$lib" ni $::odie_package(libs) } { + lappend ::odie_package(libs) "-l$lib" + } + } + set idx 0 + set start 0 + set end 0 + if {"tk" in $project(libs)} { + set str $::odie_tk(defs) + } else { + set str $::odie_tcl(defs) + } + set len [string length $str] + set token {} + set next {} + set item {} + set opts {} + while {$idx < $len} { + ### + # Seek start of opt + ### + if {[string range [string trim $item] end-1 end] != "-D"} { + append item [string index $str $idx] + incr idx + } else { + set end [expr {$idx-3}] + set token [string trim [string range $str $start $end]] + lappend opts $token + set item {} + set start $idx + incr idx + } + } + set token [string trim [string range $str $start end]] + lappend opts $token + + set defs "-DPACKAGE_NAME=\"$::project(pkgname)\" -DPACKAGE_TARNAME=\"$::project(name)\" -DPACKAGE_VERSION=\"$::project(pkgvers)\" -DPACKAGE_STRING=\"$::project(pkgname) $::project(pkgvers)\"" + foreach opt [lrange $opts 4 end] { + append defs " -D$opt" + } + set ::odie_package(defs) $defs + set ::odie_package(cflags) {} + define DEFS $::odie_package(defs) + set cflags { -pipe } + if {[opt-bool debugbld]} { + append cflags {${CFLAGS_DEBUG} ${CFLAGS_WARNING}} + } else { + append cflags {${CFLAGS_DEFAULT} ${CFLAGS_WARNING}} + } + if {[opt-bool static]} { + } else { + append cflags { ${SHLIB_CFLAGS}} + } + define CCFLAGS $cflags + + if {[lindex [opt-val nothreads] end] eq "1"} { + define TH_CFLAGS "" + define TH_LIBS "" + define TH_DEFS "" + } else { + define TH_CFLAGS -pthread + define TH_LIBS "" + define TH_DEFS "-DTCL_THREADS=1 -DUSE_THREAD_ALLOC=1" + } + + set tdefs {} + lappend tdefs -DUSE_TCL_STUBS=1 + if {"tk" in $project(libs)} { + lappend tdefs -DUSE_TK_STUBS=1 + } + if {[lindex [opt-val debugbld] end] eq "1"} { + define DEBUG "" + define NDEBUG "#" + lappend tdefs -DTCL_MEM_DEBUG=1 + } else { + define DEBUG "#" + define NDEBUG "" + } + define TDEFS [join $tdefs] + + set opt_defs {} + define OPT_DEFS [join $opt_defs] + + define CCFLAGS $::odie_tcl(extra_cflags) + define CFLAGS_WARN $::odie_tcl(cflags_warning) + define CFLAGS_OPT $::odie_tcl(cflags_optimize) + define CFLAGS_DEBUG $::odie_tcl(cflags_debug) + + foreach path $::project(include_paths) { + append ::odie_package(includes) " " -I$path + } + + set ::odie_package(headers) $::project(h_file) + + foreach {var val} [array get ::odie_package] { + define PACKAGE_[string toupper $var] $val + define PKG_[string toupper $var] $val + } + + + define LIB lib${::project(name)}$libver[get-define SHLIB_SPEC] + define PKG_LIB lib${::project(name)}$libver[get-define SHLIB_SPEC] + + define PKG_TCL_MODULES_ROOT [file join $::project(srcdir) modules] + define PKG_TCL_SOURCES "" + set modules {} + foreach path [glob -nocomplain [file join $::project(srcdir) modules *]] { + if {[file isdirectory $path]} { + lappend modules [file tail $path] + } + } + define PKG_TCL_MODULES $modules + define PKG_LIB_INIT $::project(name) +} + + +proc odie_mkhdr {} { + ### + # Build mkhdr if we don't have it + ### + if {![file exists [::realpath $::odie(mkhdr)]]} { + cd [::realpath $::odie(src_dir)] + doexec $::odie(cc) -o mkhdr.o -c scripts/mkhdr.c + doexec $::odie(cc) mkhdr.o -o mkhdr$::odie(exe_suffix) + file copy -force mkhdr$::odie(exe_suffix) [::realpath $::odie(mkhdr)] + } +} + +### +# Initialize our picture of the world +### +array set odie_tcl { + config_flags {} + version 8.6 + major_version 8 + minor_version 6 + patch_level .4 + fossil_branch release +} +array set odie_tk { + config_flags {} + version 8.6 + major_version 8 + minor_version 6 + patch_level .4 + fossil_branch release +} +array set odie { + exe_suffix {} + platform unix + tea_platform_dir unix + tcl_platform_dir unix + tcl_config_flags {} + tk_config_flags {} + 64bit {} + windows 0 + system generic + target generic + os generic + os_version {} + teacup_cpu generic + teacup_os generic + cpu {} + window_system {} + fossil_checkout .fslckout + teacup_profile {} + tk_binary_platform {} + mirror_url http://fossil.etoyoc.com/fossil +} + +# Make sure srcdir is fully qualified! +set ::odie(cpu) [exec uname -m] +set ::odie(os) [exec uname -s] +set ::odie(system) ${::odie(os)}-${::odie(cpu)} + +set vfscp {cp -a} +set ::odie(windows) 0 +set ::odie(64bit) [expr {$::odie(cpu) in {amd64 x64 x86_64}}] +set ::odie(teacup_cpu) $::odie(cpu) +set ::odie(ld_flags) {} +### +# Sort out some slight differences between Visual studio +# based builds and mingw/cygwin +### +switch -glob -- [get-define build] { + *-*-ming* - *-*-cygwin - *-*-msys { + ### + # Under mingw, 64 bit is not possible + ### + set ::odie(windows) 1 + set ::odie(os) cygwin + set ::odie(64bit) 0 + set ::odie(teacup_cpu) ix86 + set ::odie(teacup_os) win32 + set ::odie(ld_flags) "-static-libgcc -static-libstdc++" + } + *win32* - *WIN32* { + ### + # With visual studio, 64 bit should be assumed + # but is otherwise to taste + ### + set odie(windows) 1 + set ::odie(os) windows + + } +} + +### +# Build information about the local tools +### +switch -glob -- [string tolower [get-define build]] { + *-*-darwin* { + # Use a native tool + set verdat [exec sw_vers] + foreach line [split $verdat \n] { + if {[lindex $line 0] eq "ProductVersion:"} { + set ::odie(os_version) [lindex $line 1] + } + } + set ::odie(os) macosx + set ::odie(teacup_os) macosx + + ### + # Detect universal or x86_64 + ### + set major [lindex [split $::odie(os_version) .] 1] + if { $major < 4 || $::odie(cpu) != "x86_64"} { + set ::odie(teacup_os) macosx + set ::odie(teacup_profile) macosx-universal + set ::odie(cpu) universal + } else { + set ::odie(teacup_os) macosx10.5 + set ::odie(teacup_profile) macosx10.5-i386-x86_64 + set ::odie(cpu) x86_64 + } + set ::odie(tea_platform_dir) macosx + } + *-*-ming* - *-*-cygwin - *-*-msys - *win32* { + ### + # With visual studio, 64 bit should be assumed + # but is otherwise to taste + ### + set ::odie(platform) windows + set ::odie(system) windows + set ::odie(teacup_os) win32 + set vfscp {cp -a --no-preserve=links} + set ::odie(windows) 1 + set ::odie(fossil_checkout) _FOSSIL_ + set ::odie(tclsrc_dir) win + set ::odie(platform_dir) win + set ::odie(tea_platform_dir) win + set ::odie(tcl_platform_dir) win + if {$::odie(64bit)} { + set ::odie(teacup_profile) win32-ix86 + set ::odie(cpu) ix86 + } else { + set ::odie(teacup_profile) win32-x86_64 + set ::odie(cpu) x86_64 + } + set ::odie(exe_suffix) .exe + } + *-*-linux* { + set glibcver [exec ldd --version] + set major [lindex [split $glibcver .] 0] + set minor [lindex [split $glibcver .] 1] + set ::odie(teacup_os) linux-glibc$major.$minor + set ::odie(system) linux-$::odie(cpu) + set ::odie(os) linux + } +} + +if {[get-define build] ne [get-define host]} { + set ::odie(windows) 0 + ### + # Build information about the target + ### + switch [get-define host] { + darwin - macosx - macosx10.5-i386-x86_64 { + set ::odie(os) macosx + set ::odie(teacup_os) macosx10.5 + set ::odie(teacup_profile) macosx10.5-i386-x86_64 + set ::odie(cpu) x86_64 + set ::odie(tea_platform_dir) macosx + set ::odie(64bit) 1 + } + macosx-universal { + set ::odie(os) macosx + set ::odie(teacup_os) macosx + set ::odie(teacup_profile) macosx-universal + set ::odie(cpu) universal + set ::odie(tea_platform_dir) macosx + } + windows - windows-x86_64 - win32-x86_64 { + set ::odie(platform) windows + set ::odie(system) windows + set ::odie(teacup_os) win32 + set ::odie(windows) 1 + set ::odie(tclsrc_dir) win + set ::odie(platform_dir) win + set ::odie(64bit) 1 + set ::odie(teacup_profile) win32-x86_64 + set ::odie(cpu) x86_64 + set ::odie(exe_suffix) .exe + } + windows-ix86 - win32-ix86 { + set ::odie(platform) windows + set ::odie(system) windows + set ::odie(teacup_os) win32 + set ::odie(windows) 1 + set ::odie(tclsrc_dir) win + set ::odie(platform_dir) win + set ::odie(64bit) 0 + set ::odie(teacup_profile) win32-ix86 + set ::odie(cpu) ix86 + set ::odie(exe_suffix) .exe + } + default { + switch -glob -nocase -- [get-define target] { + *macosx* - *-*-darwin* { + # We don't know the version, so punt to + # modern 64bit ix86 + set ::odie(os) macosx + set ::odie(teacup_os) macosx10.5 + set ::odie(teacup_profile) macosx10.5-i386-x86_64 + set ::odie(cpu) x86_64 + + set ::odie(tea_platform_dir) macosx + } + *-*-ming* - *-*-cygwin - *-*-msys - *win32* { + set ::odie(platform) windows + set ::odie(system) windows + set ::odie(teacup_os) win32 + set ::odie(windows) 1 + set ::odie(tclsrc_dir) win + set ::odie(platform_dir) win + if {$::odie(64bit)} { + set ::odie(teacup_profile) win32-x86_64 + set ::odie(cpu) x86_64 + } else { + set ::odie(teacup_profile) win32-ix86 + set ::odie(cpu) ix86 + } + set ::odie(exe_suffix) .exe + } + *-*-linux* { + # Assume a modern linux found in teacup profiles + set ::odie(teacup_os) linux-glibc2.3 + set ::odie(system) linux-$::odie(cpu) + set ::odie(os) linux + } + } + } + } +} + +if {$::odie(teacup_profile) eq {}} { + set ::odie(teacup_profile) $::odie(teacup_os)-$::odie(cpu) +} +define VFS_CP $vfscp + +if {[opt-val prefix] ne {} || ![info exists ::odie(prefix)]} { + #------------------------------------------------------------------------ + # Handle the --prefix=... option + #------------------------------------------------------------------------ + set prefix [opt-val prefix] + if { $prefix eq {} } { + + + if { $::odie(windows) } { + set prefix c:/odie + } else { + set prefix $::env(HOME)/odie + } + } + set ::odie_config(prefix) $prefix + + set exec_prefix $prefix +} +set ::odie(prefix) $prefix +define prefix $prefix +define exec_prefix $prefix + +### +# Read in tclConfig.sh +### + + +set pathlist [list ../tcl/$::odie(tcl_platform_dir) ../tk/$::odie(tcl_platform_dir) [file join $prefix lib] /usr/local/lib /opt/local/lib c:/tcl c:/tcl/lib] +foreach {file pre array} { + tclConfig.sh tcl ::odie_tcl + tkConfig.sh tk ::odie_tk +} { + set ${array}(config_found) 0 + set l [expr {[string length $pre]+1}] + foreach path $pathlist { + set ffile [file join $path $file] + if {[file exists $ffile]} break + } + if {![file exists $ffile]} continue + set ${array}(config_found) 1 + foreach {field dat} [read_Config.sh $ffile] { + set field [string tolower $field] + if {[string match ${pre}_* $field]} { + set field [string range $field $l end] + } + set ${array}($field) $dat + } +} + +### +# Figure out Tcl +### +if {$::odie(windows)} { + set ::odie(tcl_shell) [file join $prefix bin tclsh${::odie_tcl(major_version)}${::odie_tcl(minor_version)}.exe] + set ::odie(wish_shell) [file join $prefix bin wish${::odie_tk(major_version)}${::odie_tk(minor_version)}.exe] + set ::odie(tclkit) [file join $prefix bin tclkit${::odie_tcl(major_version)}${::odie_tcl(minor_version)}.exe] + set ::odie(wishkit) [file join $prefix bin tclkit${::odie_tcl(major_version)}${::odie_tcl(minor_version)}.exe] + set ::odie(toadkit) [file join $prefix bin toadkit${::odie_tcl(major_version)}${::odie_tcl(minor_version)}.exe] + +} else { + set ::odie(tcl_shell) [file join $prefix bin tclsh${::odie_tcl(major_version)}.${::odie_tcl(minor_version)}] + set ::odie(wish_shell) [file join $prefix bin wish${::odie_tk(major_version)}.${::odie_tk(minor_version)}] + set ::odie(tclkit) [file join $prefix bin tclkit${::odie_tcl(major_version)}.${::odie_tcl(minor_version)}] + set ::odie(wishkit) [file join $prefix bin wishkit${::odie_tcl(major_version)}.${::odie_tcl(minor_version)}] + set ::odie(toadkit) [file join $prefix bin toadkit${::odie_tcl(major_version)}.${::odie_tcl(minor_version)}] +} + +define TCL_SHELL $::odie(tcl_shell) +define WISH_SHELL $::odie(wish_shell) +define TCLSH_PROG [info nameofexecutable] +define BUILD_TCLSH [info nameofexecutable] + +set ::force_check 0 +### +# Under MSYS/Cygwin transform the Cygwinized paths +# pack into proper names for Windows +### +foreach path { + sandbox download src_dir tcl_shell wish_shell build_tclsh + fossil git zip unzip sherpa lib local_repo +} { + if {[info exists ::odie($path)]} { + set ::odie_build($path) [::realpath $::odie($path)] + } +} ADDED autosetup/lib/system.tcl Index: autosetup/lib/system.tcl ================================================================== --- /dev/null +++ autosetup/lib/system.tcl @@ -0,0 +1,271 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# This module supports common system interrogation and options +# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEXT. +# +# It also support the 'feature' naming convention, where searching +# for a feature such as sys/type.h defines HAVE_SYS_TYPES_H +# +module-options { + host:host-alias => {a complete or partial cpu-vendor-opsys for the system where + the application will run (defaults to the same value as --build)} + build:build-alias => {a complete or partial cpu-vendor-opsys for the system + where the application will be built (defaults to the + result of running config.guess)} + prefix:dir => {the target directory for the build (defaults to /usr/local)} + + # These (hidden) options are supported for autoconf/automake compatibility + exec-prefix: + bindir: + sbindir: + includedir: + mandir: + infodir: + libexecdir: + datadir: + libdir: + sysconfdir: + sharedstatedir: + localstatedir: + maintainer-mode=0 + dependency-tracking=0 +} + +# Returns 1 if exists, or 0 if not +# +proc check-feature {name code} { + msg-checking "Checking for $name..." + set r [uplevel 1 $code] + define-feature $name $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + } + return $r +} + +# @have-feature name ?default=0? +# +# Returns the value of the feature if defined, or $default if not. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc have-feature {name {default 0}} { + get-define [feature-define-name $name] $default +} + +# @define-feature name ?value=1? +# +# Sets the feature 'define' to the given value. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc define-feature {name {value 1}} { + define [feature-define-name $name] $value +} + +# @feature-checked name +# +# Returns 1 if the feature has been checked, whether true or not +# +proc feature-checked {name} { + is-defined [feature-define-name $name] +} + +# @feature-define-name name ?prefix=HAVE_? +# +# Converts a name to the corresponding define, +# e.g. sys/stat.h becomes HAVE_SYS_STAT_H. +# +# Converts * to P and all non-alphanumeric to underscore. +# +proc feature-define-name {name {prefix HAVE_}} { + string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _] +} + +# If $file doesn't exist, or it's contents are different than $buf, +# the file is written and $script is executed. +# Otherwise a "file is unchanged" message is displayed. +proc write-if-changed {file buf {script {}}} { + set old [readfile $file ""] + if {$old eq $buf && [file exists $file]} { + msg-result "$file is unchanged" + } else { + writefile $file $buf\n + uplevel 1 $script + } +} + +# @make-template template ?outfile? +# +# Reads the input file /$template and writes the output file $outfile. +# If $outfile is blank/omitted, $template should end with ".in" which +# is removed to create the output file name. +# +# Each pattern of the form @define@ is replaced the the corresponding +# define, if it exists, or left unchanged if not. +# +# The special value @srcdir@ is substituted with the relative +# path to the source directory from the directory where the output +# file is created, while the special value @top_srcdir@ is substituted +# with the relative path to the top level source directory. +# +# Conditional sections may be specified as follows: +## @if name == value +## lines +## @else +## lines +## @endif +# +# Where 'name' is a defined variable name and @else is optional. +# If the expression does not match, all lines through '@endif' are ignored. +# +# The alternative forms may also be used: +## @if name +## @if name != value +# +# Where the first form is true if the variable is defined, but not empty or 0 +# +# Currently these expressions can't be nested. +# +proc make-template {template {out {}}} { + set infile [file join $::autosetup(srcdir) $template] + + if {![file exists $infile]} { + user-error "Template $template is missing" + } + + # Define this as late as possible + define AUTODEPS $::autosetup(deps) + + if {$out eq ""} { + if {[file ext $template] ne ".in"} { + autosetup-error "make_template $template has no target file and can't guess" + } + set out [file rootname $template] + } + + set outdir [file dirname $out] + + # Make sure the directory exists + file mkdir $outdir + + # Set up srcdir and top_srcdir to be relative to the target dir + define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir] + define top_srcdir [relative-path $::autosetup(srcdir) $outdir] + + set mapping {} + foreach {n v} [array get ::define] { + lappend mapping @$n@ $v + } + set result {} + foreach line [split [readfile $infile] \n] { + if {[info exists cond]} { + set l [string trimright $line] + if {$l eq "@endif"} { + unset cond + continue + } + if {$l eq "@else"} { + set cond [expr {!$cond}] + continue + } + if {$cond} { + lappend result $line + } + continue + } + if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} { + lassign $expression equal value + set varval [get-define $name ""] + if {$equal eq ""} { + set cond [expr {$varval ni {"" 0}}] + } else { + set cond [expr {$varval eq $value}] + if {$equal ne "=="} { + set cond [expr {!$cond}] + } + } + continue + } + lappend result $line + } + writefile $out [string map $mapping [join $result \n]]\n + + msg-result "Created [relative-path $out] from [relative-path $template]" +} + +# build/host tuples and cross-compilation prefix +set build [opt-val build] +define build_alias $build +if {$build eq ""} { + define build [config_guess] +} else { + define build [config_sub $build] +} + +set host [opt-val host] +define host_alias $host +if {$host eq ""} { + define host [get-define build] + set cross "" +} else { + define host [config_sub $host] + set cross $host- +} +define cross [get-env CROSS $cross] + +# Do "define defaultprefix myvalue" to set the default prefix *before* the first "use" +set prefix [opt-val prefix [get-define defaultprefix /usr/local]] + +# These are for compatibility with autoconf +define target [get-define host] +define prefix $prefix +define builddir $autosetup(builddir) +define srcdir $autosetup(srcdir) +# Allow this to come from the environment +define top_srcdir [get-env top_srcdir [get-define srcdir]] + +# autoconf supports all of these +set exec_prefix [opt-val exec-prefix $prefix] +define exec_prefix $exec_prefix +foreach {name defpath} { + bindir /bin + sbindir /sbin + libexecdir /libexec + libdir /lib +} { + define $name [opt-val $name $exec_prefix$defpath] +} +foreach {name defpath} { + datadir /share + sysconfdir /etc + sharedstatedir /com + localstatedir /var + infodir /share/info + mandir /share/man + includedir /include +} { + define $name [opt-val $name $prefix$defpath] +} + +define SHELL [get-env SHELL [find-an-executable sh bash ksh]] + +# Windows vs. non-Windows +switch -glob -- [get-define host] { + *-*-ming* - *-*-cygwin - *-*-msys { + define-feature windows + define EXEEXT .exe + } + default { + define EXEEXT "" + } +} + +# Display +msg-result "Host System...[get-define host]" +msg-result "Build System...[get-define build]" ADDED autosetup/lib/text-formatting.tcl Index: autosetup/lib/text-formatting.tcl ================================================================== --- /dev/null +++ autosetup/lib/text-formatting.tcl @@ -0,0 +1,88 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting + +use formatting + +proc wordwrap {text length {firstprefix ""} {nextprefix ""}} { + set len 0 + set space $firstprefix + foreach word [split $text] { + set word [string trim $word] + if {$word == ""} { + continue + } + if {$len && [string length $space$word] + $len >= $length} { + puts "" + set len 0 + set space $nextprefix + } + incr len [string length $space$word] + + # Use man-page conventions for highlighting 'quoted' and *quoted* + # single words. + # Use x^Hx for *bold* and _^Hx for 'underline'. + # + # less and more will both understand this. + # Pipe through 'col -b' to remove them. + if {[regexp {^'(.*)'([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { + regsub -all . $bareword "_\b&" word + append word $dot + } elseif {[regexp {^[*](.*)[*]([^a-zA-Z0-9_]*)$} $word -> bareword dot]} { + regsub -all . $bareword "&\b&" word + append word $dot + } + puts -nonewline $space$word + set space " " + } + if {$len} { + puts "" + } +} +proc title {text} { + underline [string trim $text] = + nl +} +proc p {text} { + wordwrap $text 80 + nl +} +proc codelines {lines} { + foreach line $lines { + puts " $line" + } + nl +} +proc nl {} { + puts "" +} +proc underline {text char} { + regexp "^(\[ \t\]*)(.*)" $text -> indent words + puts $text + puts $indent[string repeat $char [string length $words]] +} +proc section {text} { + underline "[string trim $text]" - + nl +} +proc subsection {text} { + underline "$text" ~ + nl +} +proc bullet {text} { + wordwrap $text 76 " * " " " +} +proc indent {text} { + wordwrap $text 76 " " " " +} +proc defn {first args} { + if {$first ne ""} { + underline " $first" ~ + } + foreach p $args { + if {$p ne ""} { + indent $p + } + } +} ADDED autosetup/lib/wiki-formatting.tcl Index: autosetup/lib/wiki-formatting.tcl ================================================================== --- /dev/null +++ autosetup/lib/wiki-formatting.tcl @@ -0,0 +1,62 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# Module which provides text formatting +# wiki.tcl.tk format output + +use formatting + +proc joinlines {text} { + set lines {} + foreach l [split [string trim $text] \n] { + lappend lines [string trim $l] + } + join $lines +} +proc p {text} { + puts [joinlines $text] + puts "" +} +proc title {text} { + puts "*** [joinlines $text] ***" + puts "" +} +proc codelines {lines} { + puts "======" + foreach line $lines { + puts " $line" + } + puts "======" +} +proc code {text} { + puts "======" + foreach line [parse_code_block $text] { + puts " $line" + } + puts "======" +} +proc nl {} { +} +proc section {text} { + puts "'''$text'''" + puts "" +} +proc subsection {text} { + puts "''$text''" + puts "" +} +proc bullet {text} { + puts " * [joinlines $text]" +} +proc indent {text} { + puts " : [joinlines $text]" +} +proc defn {first args} { + if {$first ne ""} { + indent '''$first''' + } + + foreach p $args { + p $p + } +} ADDED autosetup/migrate-autoconf Index: autosetup/migrate-autoconf ================================================================== --- /dev/null +++ autosetup/migrate-autoconf @@ -0,0 +1,689 @@ +#!/bin/sh +# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: +# \ +dir=`dirname "$0"`; exec "`$dir/find-tclsh`" "$0" "$@" + +# Migrates configure.in or configure.ac to auto.def + +proc dputs {msg} { + # Uncomment this for debugging + #puts $msg +} +proc make-quoted-string {str} { + return \"[string map {\" \\" \[ \\[ \] \\]} $str]\" +} + +# Remove white space and trailing backslash +proc clean-arg {str} { + set str [string trim $str] + if {[string index $str end] eq "\\"} { + set str [string trim [string range $str 0 end-1]] + } + return $str +} + +# Parse m4 macro args into a list, removing brackets +proc split-comma-args {str} { + #dputs "split-comma-args $str" + set args {} + # Step one char at a time and keep track of if we are in a bracketed expression + set inbracket 0 + set inparen 0 + foreach c [split $str {}] { + if {!$inbracket} { + if {$inparen} { + if {$c eq ")"} { + incr inparen -1 + } + } elseif {$c eq "("} { + incr inparen + } elseif {$c eq {[}} { + incr inbracket + continue + } elseif {$c eq ","} { + append arg "" + lappend args [clean-arg $arg] + unset arg + continue + } + } else { + if {$c eq {[}} { + incr inbracket + } elseif {$c eq {]}} { + if {[incr inbracket -1] == 0} { + continue + } + } + } + append arg $c + } + if {[info exists arg]} { + if {[string match "*\\\n" $arg]} { + set arg [string range $arg 0 end-2] + } + lappend args [clean-arg $arg] + } + #dputs "===> $args" + return $args +} + +proc count-chars {str c} { + set i 0 + set n 0 + while {[set i [string first $c $str $i]] >= 0} { + incr i + incr n + } + return $n +} + +proc check-complete {str} { + if {[count-chars $str (] != [count-chars $str )]} { + return 0 + } + if {[count-chars $str \[] != [count-chars $str \]]} { + return 0 + } + return 1 +} + +proc add-complete-statement {n statement} { + if {![regexp {^(.*?)\((.*?)\)$} $statement -> cmd args]} { + # Maybe there is something after ) + if {![regexp {^(.*?)\((.*?)\)(.*)$} $statement -> cmd args rest]} { + puts stderr "*** On line $n, failed to interpret:" + puts stderr $statement + puts stderr "\n*** If this is a nested macro, try indenting embedded macros" + exit 1 + } else { + lappend args [list # $rest] + } + } + if {[string match {*,*} $args] || [string match {*\[*} $args]} { + # Contains brackets and/or commas. + # Need to split on commas and remove brackets + set args [split-comma-args $args] + } else { + set args [list $args] + } + return [list ! $n $cmd $args] +} + +# Converts a list of lines into a "program" +proc parse-autoconf {lines} { + set n 0 + set statement {} + set prog {} + foreach line $lines { + incr n + set line [string trimright $line] + regsub {\mdnl\M.*$} $line "" line + if {$statement eq {}} { + set statement [string trimleft $line] + if {![string match {A[SCMX]_*} $statement]} { + lappend prog [list # $statement] + set statement {} + continue + } + } elseif {[string match {A[SCMX]_*} $line]} { + # Found a macro call in the left column, so assume the previous + # statement is complete + lappend prog [add-complete-statement [expr {$n - 1}] $statement] + set statement $line + } else { + append statement \n $line + } + + if {![string match *(* $statement]} { + lappend prog [list ! $n $statement {}] + set statement {} + continue + } + + # Is this statement complete? + if {![string match *)* $statement]} { + continue + } + + if {[check-complete $statement]} { + lappend prog [add-complete-statement $n $statement] + set statement {} + } + } + if {$statement ne ""} { + dputs "Got some leftover: $statement" + #exit 1 + } + return $prog +} + +proc output {msg} { + puts $::outf "$::indent$msg" +} + +# Finds AC_ARG_WITH and AC_ARG_ENABLE to +# output an appropriate options declaration +proc output-options {prog} { + output "options {" + + # options + foreach l $prog { + set l [lassign $l type n cmd args] + if {$type ne "#" && $cmd eq "AC_ARG_WITH"} { + lassign $args opt help true false + if {![regexp {=(.*?)\s+(.*)} $help -> arg desc]} { + # This is actually a boolean option + set arg "" + set desc $help + regexp {\s+(.*)} $desc -> desc + } else { + set arg :$arg + } + regsub -all {[()]} $desc "" desc + set desc [string map {[ ( ] )} $desc] + output [format "\t%-15s => %s" with-$opt$arg [list $desc]] + continue + } + if {$type ne "#" && $cmd eq "AC_ARG_ENABLE"} { + lassign $args opt help true false + set def 0 + if {[regexp -- {--(enable|disable)-(.*?)\s+(.*)} $help -> ed arg desc]} { + if {$ed eq "disable"} { + set def 1 + } + } else { + set desc $help + } + # Remember the sense of this option + set ::boolopts($opt) $def + regsub -all {[()]} $desc "" desc + set desc [string map {[ ( ] )} $desc] + output [format "\t%-15s => %s" $opt=$def [list $desc]] + } + } + output "}\n" +} + +proc output-unknown {action} { + set lines [lassign [split $action \n] first] + output "# XXX $first" + foreach l $lines { + output "# $l" + } +} + +proc output-auto-def {prog} { + foreach l $prog { + set l [lassign $l type] + if {$type eq "#"} { + lassign $l line + set line [string trim $line] + if {$line eq "" || [string match "#*" $line]} { + output $line + } elseif {[string match "dnl *" $line]} { + output "# [string range $line 4 end]" + } elseif {[regexp {([a-z0-9_]+)=(.*)} $line -> name val]} { + output "set $name $val" + } else { + output-unknown $line + } + } else { + lassign $l n cmd args + dputs "! $n $cmd [llength $args] [join $args |]" + if {[info procs $cmd] eq ""} { + output-unknown [concat $cmd {*}$args] + puts stderr "Unknown: $cmd" + } else { + if {[catch {$cmd {*}$args} msg]} { + puts stderr "At line $n, could understand $cmd" + output-unknown [concat $cmd {*}$args] + } + } + } + } +} + +proc split-comma-fields {str} { + set result {} + foreach i [split $str ,] { + lappend result [string trim $i] + } + return $result +} + +proc incr-level {} { + append ::indent \t +} + +proc decr-level {} { + set ::indent [string range $::indent 0 end-1] +} + +proc output-shell-action {action} { + set prog [parse-autoconf [split $action \n]] + incr-level + output-auto-def $prog + decr-level +} + +proc AC_MSG_NOTICE {args} { + output "msg-result [make-quoted-string [join $args]]" +} + +proc AC_MSG_RESULT {args} { + output "msg-result [make-quoted-string [join $args]]" +} + +proc AC_MSG_WARN {args} { + output "msg-result Warning: [make-quoted-string [join $args]]" +} + +proc AC_MSG_ERROR {args} { + output "user-error [make-quoted-string [join $args]]" +} + +proc AC_MSG_CHECKING {args} { + output "msg-checking [make-quoted-string "Checking [join $args]..."]" +} + +proc AC_CONFIG_FILES {files} { + foreach file $files { + # XXX input file can have a different name + output "make-template $file.in" + } +} + + +proc AC_OUTPUT {{filename {}}} { + AC_CONFIG_FILES $filename + foreach header $::output_headers { + output "make-config-header $header" + } + set ::output_headers {} +} + +proc AC_CONFIG_HEADER {filename} { + lappend ::output_headers $filename +} + +proc AC_CONFIG_HEADERS {{filename config.h} args} { + AC_CONFIG_HEADER $filename +} + +proc AS_MKDIR_P {dir} { + output [list file mkdir $dir] +} + +proc AC_SYS_LARGEFILE {args} { + output "use cc-lib" + output "cc-check-lfs" +} + +proc AC_CHECK_TOOL {define name {false ""}} { + do-true-false "cc-check-tools $name" "" $false +} +proc AC_CHECK_PROG {define name def args} { + output "if {!\[cc-check-progs $name\]} { define $define $def }" +} + +proc AC_PROG_INSTALL {} { + output "cc-check-progs install" +} +proc AC_PROG_LIBTOOL {} { + output "cc-check-progs libtool" +} +proc AC_PROG_RANLIB {} { + output "cc-check-tools ranlib" +} +proc AC_PROG_YACC {} { + output "foreach prog {bison yacc} { if {\[cc-check-progs \$prog\]} { define YACC \$prog; break } }" +} + +proc check-headers {args} { + output "cc-check-includes $args" +} + +proc AC_HEADER_STDC {args} {} +proc AC_HEADER_SYS_WAIT {args} { + check-headers sys/wait.h +} +proc AC_HEADER_DIRENT {args} { + check-headers dirent.h +} +proc AC_HEADER_TIME {args} { + check-headers sys/time.h time.h +} +proc AC_HEADER_STAT {args} { + check-headers sys/stat.h stat.h +} +proc AC_HEADER_STDBOOL {args} { + check-headers stdbool.h +} +proc ac_type_xxx {type} { + output "cc-with {-includes {stdlib.h unistd.h fcntl.h sys/types.h netinet/in.h}} {\n\tcc-check-types $type\n}" +} + +proc AC_CHECK_HEADERS {hdrlist {true {}} {false {}} {decl {}}} { + do-true-false "cc-check-includes $hdrlist" $true $false $decl +} + +proc AC_CHECK_HEADER {header {true {}} {false {}}} { + AC_CHECK_HEADERS $header $true $false +} + +proc AC_TYPE_UID_T {args} { + ac_type_xxx uid_t +} + +proc AC_TYPE_MODE_T {args} { + ac_type_xxx mode_t +} + +proc AC_TYPE_PID_T {args} { + ac_type_xxx pid_t +} + +proc AC_TYPE_SIZE_T {args} { + ac_type_xxx size_t +} + +proc AC_CHECK_MEMBERS {typelist {true {}} {false {}} {decl {}}} { + do-true-false [list cc-check-members {*}[split-comma-fields $typelist]] $true $false $decl +} +proc do-true-false {cmd true false {decl {}}} { + if {$decl ne ""} { + output "cc-with {[examine-cc-decl $decl]} \{" + incr-level + } + if {$true eq "" && $false eq ""} { + output $cmd + } else { + set not "" + if {$true eq ""} { + set not ! + set true $false + set false "" + } + output "if {$not\[$cmd\]} \{" + output-shell-action $true + if {$false ne ""} { + output "\} else \{" + output-shell-action $false + } + output "\}" + } + if {$decl ne ""} { + decr-level + output "\}" + } +} + +proc AC_CHECK_TYPE {types {true ""} {false ""} {decl ""}} { + do-true-false "cc-check-types $types" $true $false $decl +} + +proc AC_CHECK_TYPES {types {true {}} {false {}} {decl {}}} { + AC_CHECK_TYPE [split-comma-fields $types] $true $false $decl +} + +proc AC_CHECK_FUNCS {funcs {true {}} {false {}}} { + do-true-false "cc-check-functions $funcs" $true $false +} + +proc AC_CHECK_DECLS {symbols {true {}} {false {}} {decl {}}} { + do-true-false "cc-check-decls [split-comma-fields $symbols]" $true $false $decl +} + + +proc AC_FUNC_MEMCMP {args} { + output "cc-check-functions memcmp" +} + +proc AC_FUNC_FORK {args} { + output "cc-check-functions fork" +} + +proc AC_CHECK_LIB {libname funcname {true {}} {false {}} {extralibs {}}} { + if {$extralibs ne ""} { + output "cc-with {-libs {$extralibs}} \{" + incr-level + } + do-true-false "cc-check-function-in-lib $funcname $libname" $true $false + if {$extralibs ne ""} { + output "\}" + decr-level + } +} + +proc AC_SEARCH_LIBS {funcname libnames {true {}} {false {}}} { + AC_CHECK_LIB $libnames $funcname $true $false +} + +proc AC_ARG_WITH {opt help true {false {}}} { + output "if {\[opt-val with-$opt\] ne {}} {" + output "\tset withval \[opt-val with-$opt\]" + output-shell-action $true + if {$false ne ""} { + output "\} else \{" + output-shell-action $false + } + output "}" +} + +proc AC_ARG_ENABLE {opt help {true {}} {false {}}} { + set not "" + if {$::boolopts($opt)} { + set not ! + } + output "if {$not\[opt-bool $opt\]} {" + output-shell-action $true + if {$false ne ""} { + output "\} else \{" + output-shell-action $false + } + output "}" +} + +proc AC_CACHE_CHECK {desc var action} { + output-shell-action $action +} +proc AC_COMPILE_IFELSE {action {true {}} {false {}}} { + # The macro definition here is nested, so we need to "unnest" it + set action [split [string map {[[ [ ]] ]} $action] \n] + set prog [parse-autoconf $action] + lassign [lindex $prog 0] type n cmd args + + if {$cmd ne "AC_LANG_PROGRAM"} { + output-unknown "AC_COMPILE_IFELSE $action $true $false" + } else { + lassign $args decl code + AC_TRY_COMPILE $decl $code $true $false + } +} + +proc AC_LINK_IFELSE {action {true {}} {false {}}} { + # The macro definition here is nested, so we need to "unnest" it + set action [split [string map {[[ [ ]] ]} $action] \n] + set prog [parse-autoconf $action] + lassign [lindex $prog 0] type n cmd args + + if {$cmd ne "AC_LANG_PROGRAM"} { + output-unknown "AC_COMPILE_IFELSE $action $true $false" + } else { + lassign $args decl code + AC_TRY_LINK $decl $code $true $false + } +} + +proc AC_CACHE_VAL {var action args} { + output-shell-action $action +} + +proc AC_DEFINE {def args} { + output "define $def" +} + +proc AC_DEFINE_UNQUOTED {def value args} { + output "define $def [make-quoted-string $value ]" +} + +proc AC_CHECK_DECL {def {true {}} {false {}} {decl {}}} { + do-true-false "cc-check-decls $def" $true $false $decl +} + +proc AC_CHECK_SIZEOF {type {def ""}} { + output "cc-check-sizeof [make-quoted-string $type]" +} + +proc AC_FUNC_ALLOCA {} { + output "cc-check-functions alloca" +} +proc AC_FUNC_GETPGRP {} { + output "cc-check-functions getpgrp" +} +proc AC_FUNC_VPRINTF {} { + output "cc-check-functions vprintf" +} +proc AC_FUNC_WAIT3 {} { + output "cc-check-functions wait3" +} +proc AC_FUNC_STRCOLL {} { + output "cc-check-functions strcoll" +} +proc AC_CHECK_FUNC {func {true {}} {false {}}} { + do-true-false "cc-check-functions $func" $true $false +} + +# Examine declarations and try to pull out things like: +# #include +# and +# #ifdef HAVE_ABC_DEF_H +# #include +# #endif +# +# Returns a list like: +# -includes {list} -declare {list} +# +proc examine-cc-decl {decl} { + set omit_endif 0 + set includes {} + set decls {} + foreach line [split $decl \n] { + if {$line eq ""} { + continue + } + if {[regexp {#\s*if(def)?\s+HAVE_} $line]} { + incr omit_endif + continue + } + if {$omit_endif && [string match "*#*endif*" $line]} { + set omit_endif 0 + continue + } + if {[regexp {#\s*include.*<(.*)>} $line -> i]} { + lappend includes $i + continue + } + lappend decls [string trim $line] + } + set result {} + if {[llength $includes]} { + lappend result -includes $includes + } + if {[llength $decls]} { + lappend result -declare [join $decls \n] + } + return $result +} + +proc AC_TRY_LINK {decl code {true {}} {false {}}} { + do-true-false "cctest -link 1 [examine-cc-decl $decl] -code {$code}" $true $false +} + +proc AC_TRY_COMPILE {decl code {true {}} {false {}}} { + do-true-false "cctest [examine-cc-decl $decl] -code {$code}" $true $false +} + +proc AC_LANG_WERROR {args} { + output "define-append CFLAGS -Werror" +} + +proc AC_GNU_SOURCE {args} { + output "define-append CFLAGS -D_GNU_SOURCE" +} + +proc AC_C_BIGENDIAN {args} { + output "cc-check-endian" +} + +set subst_msg 0 +proc AC_SUBST {args} { + if {$::subst_msg == 0} { + incr ::subst_msg + output "# XXX autosetup automatically substitutes all define'd values" + output "# In general, simply 'define' the value rather than using a shell" + output "# variable and AC_SUBST." + output "#" + } + output-unknown [concat AC_SUBST {*}$args] +} + +proc AC_PREREQ {version} {} +proc AC_INIT {filename args} {} +proc AC_PROG_CC {args} {} +proc AC_PROG_MAKE_SET {args} {} +proc AC_CANONICAL_HOST {args} {} +proc AC_C_CONST {args} {} +proc AC_PROG_GCC_TRADITIONAL {args} {} +proc AC_CONFIG_SRCDIR {args} {} +proc AC_CANONICAL_SYSTEM {args} {} +proc AC_EXEEXT {args} {} + +# ------------------------- + +set infile [glob -nocomplain configure.in configure.ac] +switch [llength $infile] { + 0 { + puts stderr "Could not find either configure.in or configure.ac" + exit 1 + } + 2 { + puts stderr "Both configure.in and configure.ac found. Please remove one" + exit 1 + } +} + +lassign $argv autodef +if {$autodef eq ""} { + set autodef auto.def +} + +if {[file exists $autodef]} { + puts stderr "$autodef already exists. Will not overwrite it" + exit 1 +} + +puts "Migrating $infile to $autodef" + +set f [open $infile] +set lines [split [read $f] \n] +close $f + +set prog [parse-autoconf $lines] + +set outf [open $autodef w] + +set indent "" +set output_headers {} + +output "# Created by [file tail $argv0] - fix items marked XXX\n" +output "use cc cc-lib\n" + +output-options $prog + +output-auto-def $prog +close $outf + +puts "Created $autodef. Now edit to resolve items marked XXX" ADDED autosetup/scripts/install.tcl Index: autosetup/scripts/install.tcl ================================================================== --- /dev/null +++ autosetup/scripts/install.tcl @@ -0,0 +1,50 @@ +# @synopsis: +# +# Helper script for Makefiles +# + +proc use args { + foreach pkg $args { + if {[file exists $::here/${pkg}.tcl]} { + source $::here/${pkg}.tcl + } elseif {[file exists $::here/../lib/${pkg}.tcl]} { + source $::here/../lib/${pkg}.tcl + } else { + error "Could not find package $args" + } + } +} + +set ::here [file dirname [file normalize [info script]]] +use fileutil + +proc file-normalize args { + return [file normalize {*}$args] +} +proc _istcl name { + return [string match *.tcl $name] +} + +### +# topic: ea4ac0a84ae990dafee965b995f48e63 +### +proc _istm name { + return [string match *.tm $name] +} + +proc _isdirectory name { + return [file isdirectory $name] +} + +foreach {src dest} $argv { + set src [file normalize $src] + set dest [file normalize $dest] + file mkdir $dest + foreach {file} [fileutil_find $src _istcl] { + set relname [fileutil_relative $src $file] + set destfile [file join $dest $relname] + file mkdir [file dirname $destfile] + file copy -force $file [file join $dest $relname] + } +} + ADDED autosetup/system.tcl Index: autosetup/system.tcl ================================================================== --- /dev/null +++ autosetup/system.tcl @@ -0,0 +1,271 @@ +# Copyright (c) 2010 WorkWare Systems http://www.workware.net.au/ +# All rights reserved + +# @synopsis: +# +# This module supports common system interrogation and options +# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEXT. +# +# It also support the 'feature' naming convention, where searching +# for a feature such as sys/type.h defines HAVE_SYS_TYPES_H +# +module-options { + host:host-alias => {a complete or partial cpu-vendor-opsys for the system where + the application will run (defaults to the same value as --build)} + build:build-alias => {a complete or partial cpu-vendor-opsys for the system + where the application will be built (defaults to the + result of running config.guess)} + prefix:dir => {the target directory for the build (defaults to /usr/local)} + + # These (hidden) options are supported for autoconf/automake compatibility + exec-prefix: + bindir: + sbindir: + includedir: + mandir: + infodir: + libexecdir: + datadir: + libdir: + sysconfdir: + sharedstatedir: + localstatedir: + maintainer-mode=0 + dependency-tracking=0 +} + +# Returns 1 if exists, or 0 if not +# +proc check-feature {name code} { + msg-checking "Checking for $name..." + set r [uplevel 1 $code] + define-feature $name $r + if {$r} { + msg-result "ok" + } else { + msg-result "not found" + } + return $r +} + +# @have-feature name ?default=0? +# +# Returns the value of the feature if defined, or $default if not. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc have-feature {name {default 0}} { + get-define [feature-define-name $name] $default +} + +# @define-feature name ?value=1? +# +# Sets the feature 'define' to the given value. +# See 'feature-define-name' for how the feature name +# is translated into the define name. +# +proc define-feature {name {value 1}} { + define [feature-define-name $name] $value +} + +# @feature-checked name +# +# Returns 1 if the feature has been checked, whether true or not +# +proc feature-checked {name} { + is-defined [feature-define-name $name] +} + +# @feature-define-name name ?prefix=HAVE_? +# +# Converts a name to the corresponding define, +# e.g. sys/stat.h becomes HAVE_SYS_STAT_H. +# +# Converts * to P and all non-alphanumeric to underscore. +# +proc feature-define-name {name {prefix HAVE_}} { + string toupper $prefix[regsub -all {[^a-zA-Z0-9]} [regsub -all {[*]} $name p] _] +} + +# If $file doesn't exist, or it's contents are different than $buf, +# the file is written and $script is executed. +# Otherwise a "file is unchanged" message is displayed. +proc write-if-changed {file buf {script {}}} { + set old [readfile $file ""] + if {$old eq $buf && [file exists $file]} { + msg-result "$file is unchanged" + } else { + writefile $file $buf\n + uplevel 1 $script + } +} + +# @make-template template ?outfile? +# +# Reads the input file /$template and writes the output file $outfile. +# If $outfile is blank/omitted, $template should end with ".in" which +# is removed to create the output file name. +# +# Each pattern of the form @define@ is replaced the the corresponding +# define, if it exists, or left unchanged if not. +# +# The special value @srcdir@ is substituted with the relative +# path to the source directory from the directory where the output +# file is created, while the special value @top_srcdir@ is substituted +# with the relative path to the top level source directory. +# +# Conditional sections may be specified as follows: +## @if name == value +## lines +## @else +## lines +## @endif +# +# Where 'name' is a defined variable name and @else is optional. +# If the expression does not match, all lines through '@endif' are ignored. +# +# The alternative forms may also be used: +## @if name +## @if name != value +# +# Where the first form is true if the variable is defined, but not empty or 0 +# +# Currently these expressions can't be nested. +# +proc make-template {template {out {}}} { + set infile [file join $::autosetup(srcdir) $template] + + if {![file exists $infile]} { + user-error "Template $template is missing" + } + + # Define this as late as possible + define AUTODEPS $::autosetup(deps) + + if {$out eq ""} { + if {[file ext $template] ne ".in"} { + autosetup-error "make_template $template has no target file and can't guess" + } + set out [file rootname $template] + } + + set outdir [file dirname $out] + + # Make sure the directory exists + file mkdir $outdir + + # Set up srcdir and top_srcdir to be relative to the target dir + define srcdir [relative-path [file join $::autosetup(srcdir) $outdir] $outdir] + define top_srcdir [relative-path $::autosetup(srcdir) $outdir] + + set mapping {} + foreach {n v} [array get ::define] { + lappend mapping @$n@ $v + } + set result {} + foreach line [split [readfile $infile] \n] { + if {[info exists cond]} { + set l [string trimright $line] + if {$l eq "@endif"} { + unset cond + continue + } + if {$l eq "@else"} { + set cond [expr {!$cond}] + continue + } + if {$cond} { + lappend result $line + } + continue + } + if {[regexp {^@if\s+(\w+)(.*)} $line -> name expression]} { + lassign $expression equal value + set varval [get-define $name ""] + if {$equal eq ""} { + set cond [expr {$varval ni {"" 0}}] + } else { + set cond [expr {$varval eq $value}] + if {$equal ne "=="} { + set cond [expr {!$cond}] + } + } + continue + } + lappend result $line + } + writefile $out [string map $mapping [join $result \n]]\n + + msg-result "Created [relative-path $out] from [relative-path $template]" +} + +# build/host tuples and cross-compilation prefix +set build [opt-val build] +define build_alias $build +if {$build eq ""} { + define build [config_guess] +} else { + define build [config_sub $build] +} + +set host [opt-val host] +define host_alias $host +if {$host eq ""} { + define host [get-define build] + set cross "" +} else { + define host [config_sub $host] + set cross $host- +} +define cross [get-env CROSS $cross] + +# Do "define defaultprefix myvalue" to set the default prefix *before* the first "use" +set prefix [opt-val prefix [get-define defaultprefix /usr/local]] + +# These are for compatibility with autoconf +define target [get-define host] +define prefix $prefix +define builddir $autosetup(builddir) +define srcdir $autosetup(srcdir) +# Allow this to come from the environment +define top_srcdir [get-env top_srcdir [get-define srcdir]] + +# autoconf supports all of these +set exec_prefix [opt-val exec-prefix $prefix] +define exec_prefix $exec_prefix +foreach {name defpath} { + bindir /bin + sbindir /sbin + libexecdir /libexec + libdir /lib +} { + define $name [opt-val $name $exec_prefix$defpath] +} +foreach {name defpath} { + datadir /share + sysconfdir /etc + sharedstatedir /com + localstatedir /var + infodir /share/info + mandir /share/man + includedir /include +} { + define $name [opt-val $name $prefix$defpath] +} + +define SHELL [get-env SHELL [find-an-executable sh bash ksh]] + +# Windows vs. non-Windows +switch -glob -- [get-define host] { + *-*-ming* - *-*-cygwin - *-*-msys { + define-feature windows + define EXEEXT .exe + } + default { + define EXEEXT "" + } +} + +# Display +msg-result "Host System...[get-define host]" +msg-result "Build System...[get-define build]" ADDED autosetup/test-tclsh Index: autosetup/test-tclsh ================================================================== --- /dev/null +++ autosetup/test-tclsh @@ -0,0 +1,20 @@ +# A small Tcl script to verify that the chosen +# interpreter works. Sometimes we might e.g. pick up +# an interpreter for a different arch. +# Outputs the full path to the interpreter + +if {[catch {info version} version] == 0} { + # This is Jim Tcl + if {$version >= 0.72} { + # Ensure that regexp works + regexp (a.*?) a + puts [info nameofexecutable] + exit 0 + } +} elseif {[catch {info tclversion} version] == 0} { + if {$version >= 8.5 && ![string match 8.5a* [info patchlevel]]} { + puts [info nameofexecutable] + exit 0 + } +} +exit 1 DELETED cmodules/btree/cthulhu.ini Index: cmodules/btree/cthulhu.ini ================================================================== --- cmodules/btree/cthulhu.ini +++ /dev/null @@ -1,3 +0,0 @@ -set here [file dirname [file normalize [info script]]] -::cthulhu::add_directory $here { -} DELETED cmodules/btree/tree.c Index: cmodules/btree/tree.c ================================================================== --- cmodules/btree/tree.c +++ /dev/null @@ -1,491 +0,0 @@ -/* -** This file implements an in-memory balanced binary tree. This code -** was originally brought in to implement an efficient priority queue -** for the Dijkstra's shortest path algorithm in crewroute.c. -** -** This file contains code imported into READI from another project. -** The text of the original header comment follows: -*/ -/* -** A package of routines for handling balanced binary trees. -** Copyright (c) 1990 by D. Richard Hipp -*/ - -#include -#include "odieInt.h" - - -/* Each node in the binary tree is represented by a single instance -** of the following structure -*/ -typedef struct TreeElem TreeElem; -struct TreeElem { - void *data; /* Pointer to the user's data */ - void *key; /* The key associated with this element */ - TreeElem *left; /* Left daughter */ - TreeElem *right; /* Right daughter */ - int weight; /* Weight of this node */ -}; - -/* Turn bulk memory into a Tree structure -*/ -void TreeInit( - Tree *tree, /* Tree object to initialize */ - int (*xCompare)(const void*, const void*), /* Comparison function */ - void *(*xCopy)(const void*), /* Key copy function or NULL */ - void (*xFree)(void*) /* Key delete function or NULL */ -){ - tree->xCompare = xCompare; - tree->xCopy = xCopy; - tree->xFree = xFree; - tree->top = 0; -} - -/* Return the number of elements in the tree. -*/ -int TreeCount(Tree *pTree){ - if( pTree && pTree->top ){ - return pTree->top->weight; - }else{ - return 0; - } -} - -/* Delete a single node of the binary tree and all of its children -*/ -static void TreeClearNode(TreeElem *p, void (*xFree)(void*)){ - if( p==0 ) return; - if( p->left ) TreeClearNode(p->left, xFree); - if( p->right ) TreeClearNode(p->right, xFree); - if( xFree ){ - xFree(p->key); - } - Odie_Free((char *)p); -} - -/* Remove all nodes from a tree -*/ -void TreeClear(Tree *tree){ - if( tree->top ){ - TreeClearNode(tree->top, tree->xFree); - } - tree->top = 0; -} - -/* Find the element of the tree (if any) whose key matches "key". -** Return a pointer to the data for that element. If no match -** is found, return NULL. -*/ -void *TreeFind(Tree *tree, const void *key){ - TreeElem *p; - - p = tree->top; - while( p ){ - int c = tree->xCompare(p->key, key); - if( c==0 ){ - return p->data; - }else if( c<0 ){ - p = p->right; - }else{ - p = p->left; - } - } - return 0; -} - -/* If the node with key "key" is the left-most element of the tree, -** return 0. If it is the second to the left, return 1. And so -** forth. -** -** If there is no node in the tree with the key "key", then return -** the number that would have been returned if such a node were -** inserted. -*/ -int TreeRank(Tree *tree, const void *key){ - TreeElem *p; - int rank = 0; - - p = tree->top; - while( p ){ - int c = tree->xCompare(p->key, key); - if( c==0 ){ - rank += p->left ? p->left->weight: 0; - break; - }else if( c<0 ){ - rank += (p->left ? p->left->weight: 0) + 1; - p = p->right; - }else{ - p = p->left; - } - } - return rank; -} - -/* Return a pointer to the N-th element of a tree. (The left-most -** element is number 0, the next is number 1 and so forth.) -*/ -static TreeElem *TreeFindNthElem(Tree *tree, int n){ - TreeElem *p; - - p = tree->top; - while( p ){ - int c = p->left ? p->left->weight : 0; - if( n==c ){ - return p; - }else if( n>c ){ - n -= c+1; - p = p->right; - }else{ - p = p->left; - } - } - return 0; -} - -/* Return the data associated with the N-th element of the tree. Return -** NULL if there is no N-th element. -*/ -void *TreeData(Tree *tree, int n){ - TreeElem *p = TreeFindNthElem(tree,n); - return p ? p->data : 0; -} - -/* Return the key associated with the N-th element of the tree. Return -** NULL if there is no N-th element. -*/ -const void *TreeKey(Tree *tree, int n){ - TreeElem *p = TreeFindNthElem(tree,n); - if( p ){ - return p->key; - }else{ - return 0; - } -} - -/* -** Definitions: -** WEIGHT -** The weight of a node is the total number of children for the node -** plus 1. Leaf nodes have a weight of 1. The root node has a weight -** which equals the number of nodes in the tree. -** -** BALANCE -** A node is balanced if the weight of the one child is not more than -** twice the weight of the other child. -*/ - -/* The following routine rebalances the tree rooted at *ppElem after -** the insertion or deletion of a single ancestor. -*/ -static void TreeBalance(TreeElem **ppElem){ - TreeElem *n; /* Pointer to self */ - int l,r; /* Weight of left and right daughters */ - int a,b; /* Weights of various nodes */ - - if( ppElem==0 || (n=*ppElem)==0 ) return; - l = n->left ? n->left->weight: 0; - r = n->right ? n->right->weight: 0; - if( l>r*2 ){ /* Too heavy on the left side */ - TreeElem *nl; /* Pointer to left daughter */ - TreeElem *nr; /* Pointer to right daughter */ - int ll, lr; /* Weight of left daughter's left and right daughter */ - nl = n->left; - ll = nl->left ? nl->left->weight: 0; - lr = nl->right ? nl->right->weight: 0; - if( ll>lr || nl->right==0 ){ - /* - ** Convert from: n to: nl - ** / \ / \ - ** nl c a n - ** / \ / \ - ** a b b c - */ - n->left = nl->right; - nl->right = n; - n->weight = a = r + lr + 1; - nl->weight = a + ll + 1; - *ppElem = nl; - }else{ - /* - ** Convert from: n to: nr - ** / \ / \ - ** nl d nl n - ** / \ / \ / \ - ** a nr a b c d - ** / \ - ** b c - */ - int lrl, lrr; /* Weight of Great-granddaughter nodes */ - nr = nl->right; - lrl = nr->left ? nr->left->weight: 0; - lrr = nr->right ? nr->right->weight: 0; - nl->right = nr->left; - nr->left = nl; - n->left = nr->right; - nr->right = n; - n->weight = a = lrr + r + 1; - nl->weight = b = ll + lrl + 1; - nr->weight = a + b + 1; - *ppElem = nr; - } - }else if( r>l*2 ){/* Too deep on the right side */ - TreeElem *nl; /* Pointer to left daughter */ - TreeElem *nr; /* Pointer to right daughter */ - int rl, rr; /* Weight of right daughter's left and right daughter */ - nr = n->right; - rl = nr->left ? nr->left->weight: 0; - rr = nr->right ? nr->right->weight: 0; - if( rr>rl || nr->left==0 ){ - /* - ** Convert from: n to: nr - ** / \ / \ - ** a nr n c - ** / \ / \ - ** b c a b - */ - n->right = nr->left; - nr->left = n; - n->weight = a = l + rl + 1; - nr->weight = a + rr + 1; - *ppElem = nr; - }else{ - /* - ** Convert from: n to: nl - ** / \ / \ - ** a nr n nr - ** / \ / \ / \ - ** nl d a b c d - ** / \ - ** b c - */ - int rll,rlr; /* Weights of great-granddaughter nodes */ - nl = nr->left; - rll = nl->left ? nl->left->weight: 0; - rlr = nl->right ? nl->right->weight: 0; - nr->left = nl->right; - nl->right = nr; - n->right = nl->left; - nl->left = n; - n->weight = a = l + rll + 1; - nr->weight = b = rr + rlr + 1; - nl->weight = a + b + 1; - *ppElem = nl; - } - }else{ /* Node is already balanced. Just recompute its weight. */ - n->weight = l + r + 1; - } -} - -/* This routine either changes the data on an existing node in the tree, -** or inserts a new node. "key" identifies the node. If the data on -** an existing node is changed, then the function returns the old data. -** If a new node is created, NULL is returned. -*/ -static void *TreeInsertElement( - Tree *pTree, /* The root of the tree */ - void *key, /* Insert data at this key */ - void *data /* Data to be inserted */ -){ - TreeElem *n; - void *old = 0; - TreeElem **h[100]; /* Sufficient for a tree with up to 4.0E+17 nodes */ - int level = 0; - - - h[0] = &pTree->top; - level = 1; - n = pTree->top; - while( n ){ - int c; - c = pTree->xCompare(key, n->key); - if( c<0 ){ - h[level++] = &(n->left); - n = n->left; - }else if( c>0 ){ - h[level++] = &(n->right); - n = n->right; - }else{ - old = n->data; - n->data = data; /* Replace data in an existing node */ - break; - } - } - if( n==0 ){ /* Insert a leaf node */ - level--; - n = *h[level] = (TreeElem *)Odie_Alloc( sizeof(TreeElem) ); - if( n==0 ){ - return data; - } - n->data = data; - if( pTree->xCopy ){ - n->key = pTree->xCopy(key); - }else{ - n->key = key; - } - n->left = n->right = 0; - while( level>=0 ) TreeBalance(h[level--]); - } - return old; -} - -/* Unlink the N-th node of the tree and return a pointer to that -** node. (The left-most node is 0, the next node to the right is -** 1 and so forth.) -*/ -static TreeElem *TreeDeleteNthElem(TreeElem **ppTop, int N){ - TreeElem *p; /* For walking the tree */ - int level = 0; /* Depth of the blancing stack */ - TreeElem **h[100]; /* Balance stack. 100 is sufficient for balancing - ** a tree with up to 4.0E+17 nodes */ - - h[0] = ppTop; - level = 1; - p = *ppTop; - while( p ){ - int w; - w = (p->left ? p->left->weight: 0); - if( N>w ){ - h[level++] = &(p->right); - p = p->right; - N -= w+1; - }else if( Nleft); - p = p->left; - }else{ - break; - } - } - if( p ){ - level--; - if( p->left==0 ){ - *h[level] = p->right; - level--; - }else if( p->right==0 ){ - *h[level] = p->left; - level--; - }else{ - TreeElem *x; - x = TreeDeleteNthElem(&(p->right),0); - x->right = p->right; - x->left = p->left; - *h[level] = x; - } - while( level>=0 ) TreeBalance(h[level--]); - } - return p; -} - -/* Unlink the node of the tree corresponding to key and return a pointer -** to that node. -*/ -static TreeElem *TreeDeleteElem(Tree *tree, const void *key){ - TreeElem *p; /* For walking the tree */ - int level = 0; /* Depth of the blancing stack */ - TreeElem **h[100]; /* Balance stack. 100 is sufficient for balancing - ** a tree with up to 4.0E+17 nodes */ - - h[0] = &tree->top; - level = 1; - p = tree->top; - while( p ){ - int w; - w = tree->xCompare(p->key, key); - if( w<0 ){ - h[level++] = &(p->right); - p = p->right; - }else if( w>0 ){ - h[level++] = &(p->left); - p = p->left; - }else{ - break; - } - } - if( p ){ - level--; - if( p->left==0 ){ - *h[level] = p->right; - level--; - }else if( p->right==0 ){ - *h[level] = p->left; - level--; - }else{ - TreeElem *x; - x = TreeDeleteNthElem(&(p->right),0); - x->right = p->right; - x->left = p->left; - *h[level] = x; - } - while( level>=0 ) TreeBalance(h[level--]); - } - return p; -} - -/* Insert new data into a node of the tree. The node is identified -** by "key". -** -** If the new data is NULL, then node is deleted. -** -** If the node aready exists, the new data overwrites the old and -** the old data is returned. If the node doesn't already exist, then -** a new node is created and the function returns NULL. -*/ -void *TreeInsert(Tree *tree, void *key, void *data){ - void *old; - if( data==0 ){ - TreeElem *elem = TreeDeleteElem(tree, key); - if( elem ){ - if( tree->xFree ){ - tree->xFree(elem->key); - } - old = elem->data; - Odie_Free((char *)elem); - }else{ - old = 0; - } - }else{ - old = TreeInsertElement(tree,key,data); - } - return old; -} - -/* Change the data on the n-th node of the tree. The old data -** is returned. -** -** If data==NULL, then the n-th node of the tree is deleted. (The -** data associated with that node is still returned.) -** -** If the value N is out-of-bounds, then no new node is created. -** Instead, the "data" parameter is returned. -*/ -void *TreeChangeNth(Tree *tree, int n, void *data){ - void *old; - if( data==0 ){ - TreeElem *elem = TreeDeleteNthElem(&tree->top,n); - if( elem ){ - if( tree->xFree ){ - tree->xFree(elem->key); - } - old = elem->data; - Odie_Free((char *)elem); - }else{ - old = 0; - } - }else{ - TreeElem *elem = TreeFindNthElem(tree,n); - if( elem ){ - old = elem->data; - elem->data = data; - }else{ - old = data; - } - } - return old; -} - -int DLLEXPORT Tree_Init(Tcl_Interp *interp){ - #if IRM_MEM_DEBUG - Tcl_LinkVar(interp, "module_malloc(tree)", (char*)&nMalloc, - TCL_LINK_INT | TCL_LINK_READ_ONLY); - #endif - return TCL_OK; -} DELETED cmodules/btree/tree.h Index: cmodules/btree/tree.h ================================================================== --- cmodules/btree/tree.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -** Original code by D. Richard Hipp, circa 1990. -** Modified for READI, 2005-11-21. -*/ - -/* A complete binary tree is defined by an instance of the following -** structure -*/ -typedef struct Tree Tree; -struct Tree { - int (*xCompare)(const void*, const void*); /* Comparison function */ - void *(*xCopy)(const void*); /* Key copy function, or NULL */ - void (*xFree)(void*); /* Key delete function */ - struct TreeElem *top; /* The top-most node of the tree */ -}; - -void TreeInit( - Tree *tree, /* Tree object to initialize */ - int (*xCompare)(const void*, const void*), /* Comparison function */ - void *(*xCopy)(const void*), /* Key copy function or NULL */ - void (*xFree)(void*) /* Key delete function or NULL */ -); -void TreeClear(Tree *tree); -void *TreeChangeNth(Tree *tree, int n, void *data); -void *TreeInsert(Tree *tree, void *key, void *data); -void *TreeFind(Tree *tree, const void *key); -int TreeRank(Tree *tree, const void *key); -void *TreeData(Tree *tree, int n); -const void *TreeKey(Tree *tree, int n); -int TreeCount(Tree*); DELETED cmodules/geometry/cthulhu.ini Index: cmodules/geometry/cthulhu.ini ================================================================== --- cmodules/geometry/cthulhu.ini +++ /dev/null @@ -1,5 +0,0 @@ -set here [file dirname [file normalize [info script]]] -foreach file {plotter.c slicer.c wallset.c} { - ::cthulhu::detect_cases [file join $here generic $file] -} -::cthulhu::add_directory [file join $here generic] {} DELETED cmodules/geometry/generic/geometry.c Index: cmodules/geometry/generic/geometry.c ================================================================== --- cmodules/geometry/generic/geometry.c +++ /dev/null @@ -1,375 +0,0 @@ -/* -** Load the entire geometry module -*/ -#include "odieInt.h" - -/* -** Declare our Tcl Obj Types -*/ - -const Tcl_ObjType polygon_tclobjtype = { - "polygon", /* name */ - &PolygonObj_freeIntRepProc, /* freeIntRepProc */ - &PolygonObj_dupIntRepProc, /* dupIntRepProc */ - &PolygonObj_updateStringProc, /* updateStringProc */ - &PolygonObj_setFromAnyProc /* setFromAnyProc */ -}; - -const Tcl_ObjType segmentset_tclobjtype = { - "segmentset", /* name */ - &SegmentSetObj_freeIntRepProc, /* freeIntRepProc */ - &SegmentSetObj_dupIntRepProc, /* dupIntRepProc */ - &SegmentSetObj_updateStringProc, /* updateStringProc */ - &SegmentSetObj_setFromAnyProc /* setFromAnyProc */ -}; - -Tcl_Obj *Odie_NewPolygonObj(Poly *pPoly) { - Tcl_Obj *pResult; - pResult=Tcl_NewObj(); - Tcl_InvalidateStringRep(pResult); - pResult->internalRep.otherValuePtr=pPoly; - pResult->typePtr=&polygon_tclobjtype; - return pResult; -} - -int Odie_GetPolygonFromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,Poly **ptr,int *created) { - Poly *p; - *created=0; - - if(objPtr->typePtr) { - if(objPtr->typePtr==&polygon_tclobjtype && objPtr->internalRep.otherValuePtr) { - /* - ** Object is already of the type requested - */ - *ptr=objPtr->internalRep.otherValuePtr; - return TCL_OK; - } - } - int k,i; - if( Tcl_ListObjLength(interp, objPtr, &k) ) return TCL_ERROR; - if( k<6 ){ - Tcl_AppendResult(interp, "need at least 3 vertices", 0); - return TCL_ERROR; - } - if( k&1 ){ - Tcl_AppendResult(interp, "coordinates should come in pairs", 0); - return TCL_ERROR; - } - p=(Poly *)Odie_Alloc(sizeof(*p)+(k+2)*sizeof(p->v[0])); - p->nVertex=k/2; - for(i=0; inVertex; i++){ - Tcl_Obj *pElem; - double d; - Tcl_ListObjIndex(0, objPtr, i*2, &pElem); - if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail; - p->v[i][X_IDX] = d; - Tcl_ListObjIndex(0, objPtr, i*2+1, &pElem); - if(Tcl_GetDoubleFromObj(interp, pElem, &d)) goto createfail; - p->v[i][Y_IDX] = d; - } - - if(Odie_PolygonComputeArea(interp,p)==TCL_OK) { - *ptr=p; - if(Tcl_IsShared(objPtr)) { - *created=1; - } else { - /* Shimmer this object to the requested type */ - if(objPtr->typePtr && objPtr->typePtr->freeIntRepProc) { - Tcl_FreeInternalRepProc *freeIntRepProc=objPtr->typePtr->freeIntRepProc; - freeIntRepProc(objPtr); - } - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.otherValuePtr=p; - objPtr->typePtr=&polygon_tclobjtype; - } - return TCL_OK; - } - -createfail: - Odie_Free((char *)p); - return TCL_ERROR; -} - -int PolygonObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr) { - if(objPtr->typePtr) { - if(objPtr->typePtr==&polygon_tclobjtype) { - /* - ** Object is already of the type requested - */ - return TCL_OK; - } - } - Poly *p; - int created=0; - if(Odie_GetPolygonFromObj(interp,objPtr,&p,&created)) { - return TCL_ERROR; - } - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.otherValuePtr=p; - objPtr->typePtr=&polygon_tclobjtype; - return TCL_OK; -} - -void PolygonObj_updateStringProc(Tcl_Obj *objPtr) { - char outbuffer[128]; - Tcl_DString result; - Poly *p=objPtr->internalRep.otherValuePtr; - int i,j; - Tcl_DStringInit(&result); - j=p->nVertex-1; - if(p->v[0][X_IDX]==p->v[j][X_IDX] && p->v[0][Y_IDX]==p->v[j][Y_IDX]) { - j=p->nVertex-2; - } - for(i=0; i<=j; i++){ - sprintf(outbuffer,"%g %g",(float)p->v[i][X_IDX],(float)p->v[i][Y_IDX]); - Tcl_DStringAppendElement(&result,outbuffer); - } - objPtr->length=Tcl_DStringLength(&result); - objPtr->bytes=Odie_Alloc(objPtr->length+1); - strcpy(objPtr->bytes,Tcl_DStringValue(&result)); - Tcl_DStringFree(&result); -} - -void PolygonObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr) { - Poly *src=srcPtr->internalRep.otherValuePtr; - int size=sizeof(*src)+src->nVertex*sizeof(src->v[0]); - Poly *copy=(Poly *)Odie_Alloc(size); - - memcpy(copy,src,size); - Tcl_InvalidateStringRep(dupPtr); - dupPtr->typePtr=&polygon_tclobjtype; - dupPtr->internalRep.otherValuePtr=copy; -} - -void PolygonObj_freeIntRepProc(Tcl_Obj *objPtr) { - Odie_Free(objPtr->internalRep.otherValuePtr); - objPtr->internalRep.otherValuePtr=NULL; - objPtr->typePtr=NULL; -} - -void Segset_Insert_Polygon(SegSet *pSet,Poly *p,int fill) { - int i; - if(p->nVertex>0) { - VECTORXY *P; - P=&p->v[0]; - for(i=1; inVertex; i++){ - SegSetInsert(pSet,*P,p->v[i],1); - P=&p->v[i]; - } - SegSetInsert(pSet,*P,p->v[0],1); - } -} - -void SegSetCopy(SegSet *dest,SegSet *src) { - SegSetClear(dest); - memset(dest, 0, sizeof(SegSet)); - - Link *pLoop, *pNext; - for(pLoop=src->pAll; pLoop; pLoop=pNext){ - Segment *pAB; - pAB = pLoop->pLinkNode; - pNext = pLoop->pNext; - SegSetInsert(dest,pAB->from,pAB->to,pAB->isBoundary); - } -} - - -/* -** Find and return the line segment that goes from A to B. Return NULL -** if there is not such line segment -*/ -Segment *SegSetFind(SegSet *pSet, VectorXY A, VectorXY B){ - Link *pX; - Segment *p; - int h; - h = hashVectorXY(A); - for(pX=pSet->hashFrom[h]; pX; pX=pX->pNext){ - p = pX->pLinkNode; - if( sameVectorXY(p->from, A) && sameVectorXY(p->to, B) ){ - return p; - } - } - return 0; -} - -Tcl_Obj *Odie_NewSegmentSetObj(SegSet *pSegSet) { - Tcl_Obj *pResult; - pResult=Tcl_NewObj(); - Tcl_InvalidateStringRep(pResult); - pResult->internalRep.otherValuePtr=pSegSet; - pResult->typePtr=&segmentset_tclobjtype; - return pResult; -} - -int Odie_GetSegmentSetFromObj( - Tcl_Interp *interp, - Tcl_Obj *objPtr, - SegSet **ptr, - int *created -) { - SegSet *pSet=NULL; - - *created=0; - if(objPtr->typePtr && objPtr->typePtr->setFromAnyProc==&SegmentSetObj_setFromAnyProc) { - /* - ** Object is already of the type requested - */ - *ptr=objPtr->internalRep.otherValuePtr; - return TCL_OK; - } - if(objPtr->typePtr && objPtr->typePtr->setFromAnyProc==&PolygonObj_setFromAnyProc) { - *created=1; - /* - ** Convert from a polygon - */ - pSet=(SegSet *)Odie_Alloc(sizeof(SegSet)); - Poly *p=objPtr->internalRep.otherValuePtr; - Segset_Insert_Polygon(pSet,p,1); - *ptr=pSet; - return TCL_OK; - } - - int i,n; - if( Tcl_ListObjLength(interp, objPtr, &n) ) return TCL_ERROR; - if( n%4!=0 ){ - Tcl_AppendResult(interp, "VECTORS argument should contain a multiple of 4 values", 0); - return TCL_ERROR; - } - pSet=(SegSet *)Odie_Alloc(sizeof(SegSet)); - - for(i=0; ipAll; pLoop; pLoop=pNext){ - // Segment *pAB; - // pAB = pLoop->pLinkNode; - // pNext = pLoop->pNext; - // int h = hashPoint(pAB->from); - //} - - *created=1; - *ptr=pSet; - return TCL_OK; - -createfail: - SegSetClear(pSet); - - Odie_Free((char *)pSet); - return TCL_ERROR; -} - -int SegmentSetObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr) { - if(objPtr->typePtr) { - if(objPtr->typePtr==&segmentset_tclobjtype) { - /* - ** Object is already of the type requested - */ - return TCL_OK; - } - } - SegSet *p; - int created=0; - if(Odie_GetSegmentSetFromObj(interp,objPtr,&p,&created)) { - return TCL_ERROR; - } - Tcl_InvalidateStringRep(objPtr); - objPtr->internalRep.otherValuePtr=p; - objPtr->typePtr=&segmentset_tclobjtype; - return TCL_OK; -} - -void SegmentSetObj_updateStringProc(Tcl_Obj *objPtr) { - char outbuffer[128]; - Tcl_DString result; - SegSet *pSet=objPtr->internalRep.otherValuePtr; - Tcl_DStringInit(&result); - Link *pLoop, *pNext; - for(pLoop=pSet->pAll; pLoop; pLoop=pNext){ - Segment *pAB; - pAB = pLoop->pLinkNode; - pNext = pLoop->pNext; - sprintf(outbuffer,"%g %g %g %g %d",(float)pAB->from[X_IDX],(float)pAB->from[Y_IDX],(float)pAB->to[X_IDX],(float)pAB->to[Y_IDX],pAB->isBoundary); - Tcl_DStringAppendElement(&result,outbuffer); - } - objPtr->length=Tcl_DStringLength(&result); - objPtr->bytes=Odie_Alloc(objPtr->length+1); - strcpy(objPtr->bytes,Tcl_DStringValue(&result)); - Tcl_DStringFree(&result); -} - -void SegmentSetObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr) { - SegSet *src=(SegSet*)srcPtr->internalRep.otherValuePtr; - SegSet *dest=(SegSet*)Odie_Alloc(sizeof(SegSet)); - - SegSetCopy(dest,src); - - dupPtr->typePtr=srcPtr->typePtr; - dupPtr->internalRep.otherValuePtr=dest; -} - -void SegmentSetObj_freeIntRepProc(Tcl_Obj *objPtr) { - SegSet *set=(SegSet *)objPtr->internalRep.otherValuePtr; - SegSetClear(set); - Odie_Free(objPtr->internalRep.otherValuePtr); -} - - -int Odie_GetSegmentGetFromVar( - Tcl_Interp *interp, - Tcl_Obj *varName, - SegSet **dest -) { - Tcl_Obj *objPtr=Tcl_ObjGetVar2(interp,varName,NULL,0); - if(!objPtr) { - Tcl_ResetResult(interp); - *dest=(SegSet *)Odie_Alloc(sizeof(SegSet)); - return TCL_OK; - } - int created; - SegSet *src; - if( Odie_GetSegmentSetFromObj(interp, objPtr, &src, &created) ) return TCL_ERROR; - *dest=(SegSet *)Odie_Alloc(sizeof(SegSet)); - SegSetCopy(*dest,src); - return TCL_OK; -} - -DLLEXPORT int Odie_Geometry_Init(Tcl_Interp *interp) { - - Tcl_RegisterObjType(&polygon_tclobjtype); - Tcl_RegisterObjType(&segmentset_tclobjtype); - - if(Odie_Segset_Init(interp)) return TCL_ERROR; - if(Odie_Polygon_Init(interp)) return TCL_ERROR; - if(Odie_Shapes_Init(interp)) return TCL_ERROR; - if(Odie_Mathtools_Init(interp)) return TCL_ERROR; - - Tcl_CreateObjCommand(interp, "plotter", Odie_PlotterCreateProc, 0, 0); - Tcl_CreateObjCommand(interp, "slicer", Odie_SlicerCreateProc, 0, 0); - Tcl_CreateObjCommand(interp, "wallset", Odie_WallsetCreateProc, 0, 0); - return TCL_OK; -} DELETED cmodules/geometry/generic/geometry.h Index: cmodules/geometry/generic/geometry.h ================================================================== --- cmodules/geometry/generic/geometry.h +++ /dev/null @@ -1,165 +0,0 @@ -/* -** A bounding box. -*/ -typedef unsigned char u8; - -/* -** Size of the hash tables -*/ -#define SZ_HASH 419 - -/* -** Grain size for rounding -*/ -#define GRAIN 2.5 - - -/* -** An instance of the following structure is used as an entry in -** a doubly linked list. -*/ -typedef struct Link Link; -struct Link { - Link *pNext, **ppPrev; /* Next and prior nodes on the list */ - void *pLinkNode; /* Structure that this link is a part of */ -}; - -typedef struct Box Box; -struct Box { - double t, b, l, r; -}; - -/* -** Every polygon is an instance of the following structure: -*/ -typedef struct Point Vertex; -typedef struct Point Point; - -struct Point { double x, y; }; - -typedef struct Poly Poly; -struct Poly { - int id; /* Numeric ID of the polygon */ - int nVertex; /* Number of verticies */ - double area; /* Area contained within the polygon */ - Box bbox; /* The bounding box */ - double v[][2]; /* Set of vertices */ -}; - -/* -** Each straight line in the wallset is recorded as an instance in the -** following structure. -** -** Coordinates are always stored as integers in a right-handed coordinate -** system. Multiply external coordinates by Wallset.rXZoom and -** Wallset.rYZoom to get the internal coordinates stored here. Divide -** the coordinates stored here by the zoom factors to get external -** coordinates. -*/ - -typedef struct Segment Segment; -struct Segment { - int id; - double from[2]; /* Beginning coordinate */ - double to[2]; /* Ending coordinate */ - int idLC, idRC; /* ID numbers of compartments to the left and right */ - - Link pAll; /* All segments */ - Link pHash; /* All segments with the same hash on id */ - Link pFrom; /* All segments with the same hash on from */ - Link pTo; /* All segments with the same hash on to */ - Link pSet; /* A temporary subset of segments */ - - double score; /* Candidate vertex score */ - unsigned int notOblique:1; /* True if next segment is not at an oblique angle */ - unsigned int isBoundary:8; /* True if this is a boundary segment */ - unsigned int ignore:1; /* Causes this segment to be ignored on some operations */ - unsigned int midpoint:1; /* Causes this segment to be ignored on some operations */ - int isRight:4; /* -1 isleft - 0 straight - 1 right */ -}; - -/* -** A complete set of segments -*/ -typedef struct SegSet SegSet; -struct SegSet { - int shared; - int nSeg; /* Number of segments in the set */ - Segment *pCurrent; /* Current segment */ - Link *pAll; /* All segments connected by Segment.all */ - Link *hashFrom[SZ_HASH]; /* Hash on Segment.orig */ -}; - -/* -** A boundary consists of three or more segments. Each segment contains -** a direction flag. The following structure holds a single element -** of a boundary. -*/ -typedef struct Boundary Boundary; -struct Boundary { - Segment *pSeg; /* The segment of the boundary */ - int backwards; /* True if the boundary moves backwards on the segment */ -}; - -/* -** Instances of the following structure are used to speed up the -** "WS primary" method. Each instance of this structure records -** a primary wall for a compartment and a rectangular bounding box -** for that compartment. When searching for a compartment that -** contains a point, we can do a quick scan of the bounding boxes -** in linear time. -*/ -typedef struct ComptBox ComptBox; -struct ComptBox { - ComptBox *pNext; /* Next ComptBox in a list of them all */ - Box bbox; /* The bounding box */ - double area; /* Area of the bounding box, used for sorting */ - Boundary prim; /* Primary boundary wall for the compartment */ -}; - -/* -** A wallset is an instance of this structure -*/ -typedef struct Wallset Wallset; -struct Wallset { - int busy; /* Do not delete or insert if true */ - double rXZoom, rYZoom; /* Zoom for input and output */ - ComptBox *pComptBox; /* Cache of compartment boxes */ - Link *pAll; /* Any of the segments in the Segment.all ring */ - Link *hashId[SZ_HASH]; /* Hash table for Segment.id */ - Link *hashFrom[SZ_HASH]; /* Hash table for Segment.x0,Segment.y0 */ - Link *hashTo[SZ_HASH]; /* Hash table for Segment.x1,Segment.y1 */ -}; - -/* -** A slicer is an instance of the following structure. -*/ -typedef struct Slicer Slicer; -struct Slicer { - int nSlice; /* Number of slices */ - struct OneSlice { /* One entry per slice */ - int idx; /* Index of this slice in a[] */ - int did; /* Integer deck id */ - int above; /* Integer deck id above */ - int below; /* Integer deck id below */ - - char *zName; /* Name of this slice */ - double z; /* Z coordinate of this slice */ - int nXZ; /* Number of entries in xz[] */ - double rXShift; /* Change X values by this amount times rZoom */ - double *xz; /* Alternating X and Z profile values */ - double mnX, mxX; /* Min and max Y for the slice (actual coord space) */ - double mnY, mxY; /* Min and max Y for the slice (actual coord space) */ - double top, btm; /* Top and bottom of slice in canvas coords. toppLinkNode !=0 ); - if( p->ppPrev ){ - assert( *p->ppPrev==p ); - *p->ppPrev = p->pNext; - } - if( p->pNext ){ - assert( p->pNext->ppPrev == &p->pNext ); - p->pNext->ppPrev = p->ppPrev; - } - p->pNext = 0; - p->ppPrev = 0; -} - -/* -** Add a link to a list -*/ -CTHULHU_INLINE void LinkInsert(Link **ppRoot, Link *pLink){ - assert( pLink->ppPrev==0 ); - assert( pLink->pNext==0 ); - assert( pLink->pLinkNode!=0 ); - pLink->ppPrev = ppRoot; - pLink->pNext = *ppRoot; - if( pLink->pNext ){ - pLink->pNext->ppPrev = &pLink->pNext; - } - *ppRoot = pLink; -} - -/* -** Return the number of elements on a linked list -*/ - -CTHULHU_INLINE int LinkCount(Link *pRoot){ - int cnt = 0; - while( pRoot ){ - cnt++; - pRoot = pRoot->pNext; - } - return cnt; -} - -/* -** Compute a hash on an integer. -*/ -CTHULHU_INLINE int hashInt(int x){ - return (x & 0x7fffffff) % SZ_HASH; -} - -/* -** Round a coordinate to its nearest grain boundary -*/ -CTHULHU_INLINE long intCoord(double x) { - long idxX = x/GRAIN + (x>0.0 ? 0.5 : -0.5); - return idxX*GRAIN; -} - -/* -** Compute a hash on a point. -*/ -CTHULHU_INLINE int hashPoint(VECTORXY p){ - int idxX = p[X_IDX]/GRAIN; - int idxY = p[Y_IDX]/GRAIN; - return hashInt(idxX+idxY); -} - -CTHULHU_INLINE int hashVectorXY(VECTORXY p){ - int idxX = p[X_IDX]/GRAIN; - int idxY = p[Y_IDX]/GRAIN; - return hashInt(idxX+idxY); -} - - -CTHULHU_INLINE double roundCoord(double x){ - return intCoord(x); -} - -/* -** Compute a hash on a pair of floating point number. -*/ -CTHULHU_INLINE int hashCoord(double x, double y){ - long idxX = intCoord(x); - long idxY = intCoord(y); - return hashInt(idxX+idxY); -} - -/* -** Compare to floating point values and return negative, zero, or -** positive if the first value is less than, equal to, or greater -** than the second. -*/ -CTHULHU_INLINE int floatCompare(double x0, double x1){ - double diff = x1 - x0; - if( diff>-GRAIN && diff1e5) { - use_format="%g"; - } else if(bx>10.0) { - use_format="%.1f"; - } else if (bx>1.0) { - use_format="%.2f"; - } else { - use_format="%.3f"; - } - sprintf(newstring,use_format,ax); - return Tcl_NewStringObj(newstring,-1); -} - -CTHULHU_INLINE int ODIE_Fuzzy_Compare(double avalue,double bvalue) { - /* Handle the simple cases */ - double c=bvalue-avalue; - if(fabs(c) < __FLT_EPSILON__) return 0; - if(avalue>bvalue) return 1; - return -1; -} - -CTHULHU_INLINE int ODIE_Fuzzy_GTE(double avalue,double bvalue) { - /* Handle the simple cases */ - if (avalue==bvalue) return 1; - if (avalue<=ODIE_REAL_TOLERANCE && bvalue>ODIE_REAL_TOLERANCE) return 0; - if (avalue>bvalue) return 1; - - /* Add epsilon to the send */ - avalue+=ODIE_REAL_TOLERANCE; - if (avalue>=bvalue) return 2; - - /* For large quantities, loose the decimal points - if(avalue>100.0 && bvalue>100.0) { - avalue=ceil(avalue); - bvalue=floor(bvalue); - if (avalue>=bvalue) return 2; - } - */ - return 0; -} - -/* Detect of two lines are colinear */ -CTHULHU_INLINE int Odie_IsColinear(double x1,double y1,double x2,double y2,double x3,double y3) { - double c=(x3-x1)*(y2-y1)-(y3-y1)*(x2-x1); - if(fabs(c) < __FLT_EPSILON__) return 1; - return 0; -} - -/* -** Detect the intersection of two lines -** Returns: -** 0 - no overlap -** 1 - AX1 is on line BX1-BY1 -** 2 - AX2 is on line BX1-BY1 -** 4 - BX1 is on line AX1-AX2 -** 8 - BX2 is on line AX1-AX2 -*/ -CTHULHU_INLINE int ODIE_Math_LineLineCoincident( -double ax1, double ay1, -double ax2, double ay2, -double bx1, double by1, -double bx2, double by2) -{ - double denom,numera,numerb; - - denom = (by2-by1) * (ax2-ax1) - (bx2-bx1) * (ay2-ay1); - /* Are the line parallel */ - if (!ODIE_Real_Is_Zero(denom)) { - return 0; - } - numera = (bx2-bx1) * (ay1-by1) - (by2-by1) * (ax1-bx1); - numerb = (ax2-ax1) * (ay1-by1) - (ay2-ay1) * (ax1-bx1); - - if (!ODIE_Real_Is_Zero(numera) || !ODIE_Real_Is_Zero(numerb)) { - return 0; - } - return 1; -#ifdef NEVER - VectorXY A,B,C,D; - A[X_IDX]=ax1; - A[Y_IDX]=ay1; - B[X_IDX]=ax2; - B[Y_IDX]=ay2; - C[X_IDX]=bx1; - C[Y_IDX]=by1; - D[X_IDX]=bx2; - D[Y_IDX]=by2; - - int result=0; - if(ODIE_Math_PointOnSegment(C,D,A)) { - result|=1; - } - if(ODIE_Math_PointOnSegment(C,D,B)) { - result|=2; - } - if(ODIE_Math_PointOnSegment(A,B,C)) { - result|=4; - } - if(ODIE_Math_PointOnSegment(A,B,D)) { - result|=8; - } - return result; -#endif -} - -/* -** Detect the intersection of two lines -** Adapted from: http://paulbourke.net/geometry/lineline2d/pdb.c -*/ -int ODIE_Math_LineLineIntersect( -double ax1, double ay1, -double ax2, double ay2, -double bx1, double by1, -double bx2, double by2, -double *x, double *y) -{ - double mua,mub; - double denom,numera,numerb; - - - denom = (by2-by1) * (ax2-ax1) - (bx2-bx1) * (ay2-ay1); - numera = (bx2-bx1) * (ay1-by1) - (by2-by1) * (ax1-bx1); - numerb = (ax2-ax1) * (ay1-by1) - (ay2-ay1) * (ax1-bx1); - - /* Are the line parallel */ - if (ODIE_Real_Is_Zero(denom)) { - if (ODIE_Real_Is_Zero(numera) && ODIE_Real_Is_Zero(numerb)) { - /* Are the line coincident? */ - int within=1; - if(ax2>ax1) { - if(bx1>ax2 && bx2>ax2) { - within=0; - } else if(bx1ax1 && bx2>ax1) { - within=0; - } else if(bx1ay1) { - if(by1>ay2 && by2>ay2) { - within=0; - } else if(by1ay1 && by2>ay1) { - within=0; - } else if(by1 1 || mub < 0 || mub > 1) { - *x = 0; - *y = 0; - return(0); - } - *x = ax1 + mua * (ax2 - ax1); - *y = ay1 + mua * (ay2 - ay1); - return(1); -} - -/* -** Detect the intersection of a line and a sphere -** Adapted from: http://http://paulbourke.net/geometry/circlesphere/raysphere.c -*/ -int ODIE_Math_LineSphereIntersect( -double p1_x, double p1_y, double p1_z, -double p2_x, double p2_y, double p2_z, -double sc_x, double sc_y, double sc_z, -double r, -double *mu1, double *mu2) -{ - double a,b,c; - double bb4ac; - double dp_x,dp_y,dp_z; - *mu1 = 0; - *mu2 = 0; - - dp_x = p2_x - p1_x; - dp_y = p2_y - p1_y; - dp_z = p2_z - p1_z; - a = dp_x * dp_x + dp_y * dp_y + dp_z * dp_z; - b = 2 * (dp_x * (p1_x - sc_x) + dp_y * (p1_y - sc_y) + dp_z * (p1_z - sc_z)); - c = sc_x * sc_x + sc_y * sc_y + sc_z * sc_z; - c += p1_x * p1_x + p1_y * p1_y + p1_z * p1_z; - c -= 2 * (sc_x * p1_x + sc_y * p1_y + sc_z * p1_z); - c -= r * r; - bb4ac = b * b - 4 * a * c; - if (ODIE_Real_Is_Zero(a) || bb4ac < 0) { - return(0); - } - - *mu1 = (-b + sqrt(bb4ac)) / (2 * a); - *mu2 = (-b - sqrt(bb4ac)) / (2 * a); - - return(1); -} -/* -** Detect the intersection of a line and a circle -** Adapted from: http://http://paulbourke.net/geometry/circlesphere/raysphere.c -*/ -int ODIE_Math_LineCircleIntersect( -double p1_x, double p1_y, -double p2_x, double p2_y, -double sc_x, double sc_y, -double r, -double *mu1, double *mu2) -{ - double a,b,c; - double bb4ac; - double dp_x,dp_y; - *mu1 = 0; - *mu2 = 0; - - dp_x = p2_x - p1_x; - dp_y = p2_y - p1_y; - a = dp_x * dp_x + dp_y * dp_y; - b = 2 * (dp_x * (p1_x - sc_x) + dp_y * (p1_y - sc_y)); - c = sc_x * sc_x + sc_y * sc_y; - c += p1_x * p1_x + p1_y * p1_y; - c -= 2 * (sc_x * p1_x + sc_y * p1_y); - c -= r * r; - bb4ac = b * b - 4 * a * c; - if (ODIE_Real_Is_Zero(a) || bb4ac < 0) { - return(0); - } - - *mu1 = (-b + sqrt(bb4ac)) / (2 * a); - *mu2 = (-b - sqrt(bb4ac)) / (2 * a); - - return(1); -} - -/* -** This file is copyright Test and Evaluation Solutions, LLC -** See license.terms for details of usage -*/ - - -static int odiemath_method_colinear ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - if( objc != 7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "colinear x1 y1 x2 y2 x3 y3"); - return TCL_ERROR; - } - double x1,y1,x2,y2,x3,y3; - if (Tcl_GetDoubleFromObj(interp,objv[1],&x1)) return TCL_ERROR; - if (Tcl_GetDoubleFromObj(interp,objv[2],&y1)) return TCL_ERROR; - if (Tcl_GetDoubleFromObj(interp,objv[3],&x2)) return TCL_ERROR; - if (Tcl_GetDoubleFromObj(interp,objv[4],&y2)) return TCL_ERROR; - if (Tcl_GetDoubleFromObj(interp,objv[5],&x3)) return TCL_ERROR; - if (Tcl_GetDoubleFromObj(interp,objv[6],&y3)) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(Odie_IsColinear(x1,y1,x2,y2,x3,y3))); - return TCL_OK; -} - -/* -** This file implements several math and drawing functions used -** to accellerate the IRM gui -*/ - -static int odiemath_method_double_to_fuzzy ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double ax; - if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) { - Tcl_SetObjResult(interp,objv[1]); - return TCL_OK; - } - Tcl_SetObjResult(interp,ODIE_NewFuzzyObj(ax)); - return TCL_OK; -} - -static int odiemath_method_fuzzy_compare ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int result; - if(objc!=3) { - Tcl_WrongNumArgs(interp, 1, objv, "avalue bvalue"); - } - result=ODIE_Fuzzy_Compare_TclObj(objv[1],objv[2]); - Tcl_SetObjResult(interp,Tcl_NewIntObj(result)); - return TCL_OK; -} - -static int odiemath_method_fuzzy_is_zero ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int result; - if(objc!=2) { - Tcl_WrongNumArgs(interp, 1, objv, "avalue"); - } - double value; - if(Tcl_GetDoubleFromObj(NULL,objv[1],&value)) { - result=0; - } else { - result=ODIE_Real_Is_Zero(value); - } - Tcl_SetObjResult(interp,Tcl_NewBooleanObj(result)); - return TCL_OK; -} - -static int odiemath_method_grid_hex ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double grid, x, y; - int gx,gy; - Tcl_Obj *pResult; - - if( objc != 4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y"); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR; - pResult=Tcl_NewObj(); - gy=(int)round(y/grid); - if(gy%2==1){ - gx=(int)round((x-grid/2)/grid); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx+grid/2)); - } else { - gx=(int)round(x/grid); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gx)); - } - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*gy)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int odiemath_method_grid_square ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double grid; - double x; - double y; - Tcl_Obj *pResult; - if( objc != 4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "gridsize x y"); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[1],&grid)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&x)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&y)) return TCL_ERROR; - pResult=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(x/grid))); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(grid*round(y/grid))); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int odiemath_method_line_circle_intersect ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double ax1,ax2,ay1,ay2; - double bx1,by1,brad; - double ix,iy; - - if(objc<8) { - Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 brad"); - return TCL_ERROR; - } - - if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR; - - if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[7], &brad) ) return TCL_ERROR; - - if(ODIE_Math_LineCircleIntersect(ax1,ay1,ax2,ay2,bx1,by1,brad,&ix,&iy)) { - Tcl_Obj *pResult; - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ix)); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(iy)); - Tcl_SetObjResult(interp, pResult); - } - return TCL_OK; -} - -static int odiemath_method_line_intersect ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double ax1,ax2,ay1,ay2; - double bx1,bx2,by1,by2; - double ix,iy; - - if(objc<9) { - Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 bx2 by2"); - return TCL_ERROR; - } - - if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR; - - if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[7], &bx2) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[8], &by2) ) return TCL_ERROR; - - if(ODIE_Math_LineLineIntersect(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,&ix,&iy)) { - Tcl_Obj *pResult; - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ix)); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(iy)); - Tcl_SetObjResult(interp, pResult); - } - return TCL_OK; -} - -static int odiemath_method_line_overlap ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - Tcl_Obj *pResult; - double ax1,ax2,ay1,ay2; - double bx1,bx2,by1,by2; - - if(objc<9) { - Tcl_WrongNumArgs(interp, 1, objv, "ax1 ay1 ax2 ay2 bx1 by1 bx2 by2"); - return TCL_ERROR; - } - - if( Tcl_GetDoubleFromObj(interp, objv[1], &ax1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &ay1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &ax2) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &ay2) ) return TCL_ERROR; - - if( Tcl_GetDoubleFromObj(interp, objv[5], &bx1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &by1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[7], &bx2) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[8], &by2) ) return TCL_ERROR; - - /* - ** ignore if the segments connect at endpoints - if(ax1==bx1 && ay1==by1) return TCL_OK; - if(ax1==bx2 && ay1==by2) return TCL_OK; - if(ax2==bx1 && ay2==by1) return TCL_OK; - if(ax2==bx2 && ay2==by2) return TCL_OK; - */ - - pResult = Tcl_NewIntObj(ODIE_Math_LineLineCoincident(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2)); - Tcl_SetObjResult(interp, pResult); - - return TCL_OK; -} - -static int odiemath_method_list_round ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int i, n; - double factor; - if(Tcl_GetDoubleFromObj(interp,objv[1],&factor)) return TCL_ERROR; - if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR; - - Tcl_Obj *pResult=Tcl_NewObj(); - for(i=0;ifullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - return TCL_OK; -} - - - - - DELETED cmodules/geometry/generic/plotter.c Index: cmodules/geometry/generic/plotter.c ================================================================== --- cmodules/geometry/generic/plotter.c +++ /dev/null @@ -1,384 +0,0 @@ -/* -** This widget translates 3-D coordinates onto a flat canvas by splitting -** the 3-D space into layers and stacking the layers on the canvas. -** -** The layers are decks of the ship. The highest layer (or deck) is drawn -** at the top of the page. The next layer down is drawn below the top layer. -** and so forth down the canvas. In other words, the 3D object is drawn -** by showing a set of 2D slices where each slice is viewed from above. -** -** The original 3D coordinates are called "actual" coordinates. When -** translated into the 2D canvas they are called "canvas" coordinates. -** -** The actual coordinate system is right-handed. The X axis increases to -** the right. The Y axis increases going up. The Z axis comes out of the -** page at the viewer. The canvas coordinate system is left-handed. The -** X axis increase to the right but the Y axis increases going down. -** -** A plotter is a object with methods. The details of the available -** methods and what each does are described in comments before the -** implementation of each method. -*/ -#include "odieInt.h" -#include -#include -#include -#include -#include - -/* -** A plotter is an instance of the following structure. -*/ -typedef struct Plotter Plotter; -struct Plotter { - double rZoom; /* Multiply canvas coord by this to get actual coord */ - double rXOffset; /* X-Shift amount */ - double rYOffset; /* Y-Shift amount */ -}; - -/* -** This routine is called when a plotter is deleted. All the memory and -** other resources allocated by this plotter is recovered. -*/ -static void destroyPlotter(void *pArg){ - Plotter *p = (Plotter*)pArg; - Odie_Free((char *)p); -} - -static inline double xCanvasToActual(Plotter *p,double cx){ - return (cx+p->rXOffset)*p->rZoom; -} - -static inline double yCanvasToActual(Plotter *p,double cy){ - return -1.0*(cy+p->rYOffset)*p->rZoom; -} - -/* -** Convert a Y coordinate from actual to canvas coordinates for a -** given deck. -*/ -static inline double xActualToCanvas(Plotter *p,double ax){ - return (ax/p->rZoom)-p->rXOffset; -} - -/* -** Convert a Y coordinate from actual to canvas coordinates for a -** given deck. -*/ -static inline double yActualToCanvas(Plotter *p,double ay){ - return -1.0*(ay/p->rZoom)-p->rYOffset; -} - -/* -** This routine runs when a method is executed against a plotter -*/ -static int plotterMethodProc( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Plotter *p = (Plotter*)pArg; - -#if 0 - /* For debugging.... - ** Print each wallset command before it is executed. - */ - { int i; - for(i=0; irZoom - pS->rXShift; - ** ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top); - */ - *(M->matrix+X_IDX)=xCanvasToActual(p,cx); - *(M->matrix+Y_IDX)=yCanvasToActual(p,cy); - - Tcl_ListObjAppendElement(interp, pResult, Matrix_To_TclObj(M)); - } - if( itypePtr==&matrix_tclobjtype) { - singlearg=1; - } else { - if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR; - Tcl_ListObjIndex(0, objv[2], 0, &pObj); - if( Tcl_ListObjLength(interp, pObj, &m) ) return TCL_ERROR; - if(m==1) { - singlearg=1; - } - } - - if(singlearg) { - /* - ** Accept a single vector as an argument - ** Do this to ensure we don't interpret the - ** value as a list - */ - MATOBJ *M; - M=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxy); - if(!M) return TCL_ERROR; - ax=*(M->matrix+X_IDX); - ay=*(M->matrix+Y_IDX); - cx = xActualToCanvas(p,ax); - cy = yActualToCanvas(p,ay); - if(objc==5) { - Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(cx),0); - Tcl_ObjSetVar2(interp,objv[4],NULL,Tcl_NewDoubleObj(cy),0); - } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cx)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cy)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; - } - - if(objc != 5) { - pResult = Tcl_NewObj(); - } - - for(i=0; imatrix+X_IDX); - ay=*(M->matrix+Y_IDX); - cx = xActualToCanvas(p,ax); - cy = yActualToCanvas(p,ay); - if(objc==5) { - Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(cx),0); - Tcl_ObjSetVar2(interp,objv[4],NULL,Tcl_NewDoubleObj(cy),0); - return TCL_OK; - } else { - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cx)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cy)); - } - } - if(error) { - if(pResult) { - Tcl_DecrRefCount(pResult); - } - return TCL_ERROR; - } - if( irefCount, tmp->typePtr); - fflush (stdout); - break; - } - - /* - ** tclmethod: PLOTTER centerset zoom width height - ** title: Set all settings for plotter in one go - ** description: Sets the center of the screen based on the width - ** and height (0,0 = width/2 height/2) - */ - case PLOTTER_CENTERSET: { - double rZoom,rXOffset,rYOffset; - - if(objc!=5) { - printf("%d\n",objc); - Tcl_WrongNumArgs(interp, 2, objv, "ZOOM XOFFSET YOFFSET"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &rZoom) ) return TCL_ERROR; - p->rZoom = rZoom; - if( Tcl_GetDoubleFromObj(interp, objv[3], &rXOffset) ) return TCL_ERROR; - p->rXOffset = -rXOffset/2.0; - if( Tcl_GetDoubleFromObj(interp, objv[4], &rYOffset) ) return TCL_ERROR; - p->rYOffset = -rYOffset/2.0; - return TCL_OK; - } - - /* - ** tclmethod: PLOTTER xoffset ?AMT? - ** title: Change the X-Offset - */ - case PLOTTER_XOFFSET: { - double rXOffset; - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?"); - return TCL_ERROR; - } - if( objc==2 ){ - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rXOffset)); - return TCL_OK; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &rXOffset) ) return TCL_ERROR; - p->rXOffset = rXOffset; - break; - } - - /* - ** tclmethod: PLOTTER yoffset ?AMT? - ** title: Change the Y-Offset - */ - case PLOTTER_YOFFSET: { - double rYOffset; - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?"); - return TCL_ERROR; - } - if( objc==2 ){ - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rYOffset)); - return TCL_OK; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &rYOffset) ) return TCL_ERROR; - p->rYOffset = rYOffset; - break; - } - - /* - ** tclmethod: PLOTTER zoom ?ZOOM? - ** title: Query or change the zoom factor. - */ - case PLOTTER_ZOOM: { - Tcl_Obj *pResult; - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?"); - return TCL_ERROR; - } - if( objc==3 ){ - double r; - if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR; - p->rZoom = r; - } - pResult = Tcl_NewDoubleObj(p->rZoom); - Tcl_SetObjResult(interp, pResult); - break; - } - - /* End of the command methods. The brackets that follow terminate the - ** automatically generated switch. - ****************************************************************************/ - } - } - return TCL_OK; -} - -/* -** tclcmd: plotter PLOTTER -** title: creates a plotter object -** This routine runs when the "plotter" command is invoked to create a -** new plotter. -*/ -int Odie_PlotterCreateProc( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char *zCmd; - Plotter *p; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "PLOTTER"); - return TCL_ERROR; - } - zCmd = Tcl_GetStringFromObj(objv[1], 0); - p = (Plotter *)Odie_Alloc( sizeof(*p) ); - p->rZoom = 1.0; - p->rXOffset = 0.0; - p->rYOffset = 0.0; - Tcl_CreateObjCommand(interp, zCmd, plotterMethodProc, p, destroyPlotter); - return TCL_OK; -} - DELETED cmodules/geometry/generic/plotter_cases.h Index: cmodules/geometry/generic/plotter_cases.h ================================================================== --- cmodules/geometry/generic/plotter_cases.h +++ /dev/null @@ -1,20 +0,0 @@ -/*** Automatically Generated Header File - Do Not Edit ***/ - const static char *PLOTTER_strs[] = { - "actualcoords", "canvascoords", "centerset", - "destroy", "objinfo", "xoffset", - "yoffset", "zoom", 0 - }; - enum PLOTTER_enum { - PLOTTER_ACTUALCOORDS, PLOTTER_CANVASCOORDS,PLOTTER_CENTERSET, - PLOTTER_DESTROY, PLOTTER_OBJINFO, PLOTTER_XOFFSET, - PLOTTER_YOFFSET, PLOTTER_ZOOM, - }; - int index; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "METHOD ?ARG ...?"); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObj(interp, objv[1], PLOTTER_strs, "option", 0, &index)){ - return TCL_ERROR; - } - switch( (enum PLOTTER_enum)index ) DELETED cmodules/geometry/generic/polygon.c Index: cmodules/geometry/generic/polygon.c ================================================================== --- cmodules/geometry/generic/polygon.c +++ /dev/null @@ -1,971 +0,0 @@ - -/* -** This file is machine generated. Changes will -** be overwritten on the next run of cstruct.tcl -*/ -#include "odieInt.h" - -/* -** This file implements a TCL object used for tracking polygons. A -** single new TCL command named "poly" is defined. This command -** has methods for creating, deleting, and taking the intersection -** of 2-D polygons. There are comments on the implementation of each -** method to describe what the method does. -** -** This module was originally developed to aid in computing the -** shared surface area between two compartments on separate decks. -** The shared surface area is needed in initializing the fire model -** since heat conduction between the two compartments is proportional -** to their shared area. -*/ -#include -#include -#include -#include - -/* -** Return the distance between two points -*/ -static inline double dist(double x0, double y0, double x1, double y1){ - double dx = x1 - x0; - double dy = y1 - y0; - return sqrt(dx*dx + dy*dy); -} - -/* -** Return -1, 0, or 1 if the point x,y is outside, on, or within -** the polygon p. -*/ -static inline int within(Poly *p, double x, double y){ - int res, i; - res = -1; - for(i=0; inVertex-1; i++){ - double x0, y0, x1, y1, yP; - x0 = p->v[i][X_IDX]; - y0 = p->v[i][Y_IDX]; - x1 = p->v[i+1][X_IDX]; - y1 = p->v[i+1][Y_IDX]; - if( x0==x1 ){ - if( x0==x && ((y0<=y && y1>=y) || (y1<=y && y0>=y)) ){ - res = 0; - break; - } - continue; - } - if( x0>x1 ){ - int t = x0; - x0 = x1; - x1 = t; - t = y0; - y0 = y1; - y1 = t; - } - if( x>=x1 || x y ){ res = -res; } - } - return res; -} - -int Odie_PolygonComputeArea(Tcl_Interp *interp,Poly *p) { - double area=0.0; - double areacomp=0.0; - int i; - - if( p->v[p->nVertex-1][X_IDX]!=p->v[0][X_IDX] || p->v[p->nVertex-1][Y_IDX]!=p->v[0][Y_IDX] ){ - p->v[p->nVertex][X_IDX] = p->v[0][X_IDX]; - p->v[p->nVertex][Y_IDX] = p->v[0][Y_IDX]; - p->nVertex++; - } - - for(i=0; inVertex-1; i++){ - area += 0.5*(p->v[i][Y_IDX] + p->v[i+1][Y_IDX])*(p->v[i+1][X_IDX] - p->v[i][X_IDX]); - } - if( area<0.0 ){ - int b, e; - for(b=0, e=p->nVertex-1; bv[b][X_IDX]; - p->v[b][X_IDX] = p->v[e][X_IDX]; - p->v[e][X_IDX] = t; - t = p->v[b][Y_IDX]; - p->v[b][Y_IDX] = p->v[e][Y_IDX]; - p->v[e][Y_IDX] = t; - } - area = -area; - } - p->area = area; - p->bbox.l = p->bbox.r = p->v[0][X_IDX]; - p->bbox.t = p->bbox.b = p->v[0][Y_IDX]; - for(i=1; inVertex-1; i++){ - double x, y; - x = p->v[i][X_IDX]; - if( xbbox.l ) p->bbox.l = x; - if( x>p->bbox.r ) p->bbox.r = x; - y = p->v[i][Y_IDX]; - if( y>p->bbox.t ) p->bbox.t = y; - if( ybbox.b ) p->bbox.b = y; - } - areacomp=(p->bbox.r - p->bbox.l)*(p->bbox.t-p->bbox.b)*1.00001; - - if(area<=areacomp) { - return TCL_OK; - } else { - char errstr[256]; - sprintf(errstr,"Area: %g Calculated: %g\n",area,areacomp); - Tcl_AppendResult(interp, "Area of polygon wonky ", errstr, 0); - return TCL_ERROR; - } -} - -static int polygon_method_create ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N"); - return TCL_ERROR; - } - int isnew; - Poly *p; - if( Odie_GetPolygonFromObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR; - if(isnew) { - Tcl_SetObjResult(interp, Odie_NewPolygonObj(p)); - } else { - Tcl_SetObjResult(interp, objv[1]); - } - return TCL_OK; -} - -static int polygon_method_simplify ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N"); - return TCL_ERROR; - } - Poly *pPoly,*pNewPoly; - int i,isnew; - int colinear; - double ax,ay,bx,by,cx,cy; - if( Odie_GetPolygonFromObj(interp, objv[1], &pPoly, &isnew) ) return TCL_ERROR; - - pNewPoly=(Poly *)Odie_Alloc(sizeof(*pNewPoly)+(pPoly->nVertex+2)*sizeof(pNewPoly->v[0])); - pNewPoly->nVertex=0; - - ax=pPoly->v[pPoly->nVertex-1][X_IDX]; - ay=pPoly->v[pPoly->nVertex-1][Y_IDX]; - bx=pPoly->v[0][X_IDX]; - by=pPoly->v[0][Y_IDX]; - if(ax==bx && ay==by) { - ax=pPoly->v[pPoly->nVertex-2][X_IDX]; - ay=pPoly->v[pPoly->nVertex-2][Y_IDX]; - } - for(i=1;inVertex;i++) { - cx=pPoly->v[i][X_IDX]; - cy=pPoly->v[i][Y_IDX]; - colinear=Odie_IsColinear(ax,ay,bx,by,cx,cy); - if(!colinear) { - pNewPoly->v[pNewPoly->nVertex][X_IDX]=bx; - pNewPoly->v[pNewPoly->nVertex][Y_IDX]=by; - pNewPoly->nVertex++; - } - ax=bx; - ay=by; - bx=cx; - by=cy; - } - cx=pPoly->v[0][X_IDX]; - cy=pPoly->v[0][Y_IDX]; - colinear=Odie_IsColinear(ax,ay,bx,by,cx,cy); - if(!Odie_IsColinear(ax,ay,bx,by,cx,cy)) { - pNewPoly->v[pNewPoly->nVertex][X_IDX]=bx; - pNewPoly->v[pNewPoly->nVertex][Y_IDX]=by; - pNewPoly->nVertex++; - } - if( pNewPoly->v[pNewPoly->nVertex-1][X_IDX]!=pNewPoly->v[0][X_IDX] || pNewPoly->v[pNewPoly->nVertex-1][Y_IDX]!=pNewPoly->v[0][Y_IDX] ){ - pNewPoly->v[pNewPoly->nVertex][X_IDX] = pNewPoly->v[0][X_IDX]; - pNewPoly->v[pNewPoly->nVertex][Y_IDX] = pNewPoly->v[0][Y_IDX]; - pNewPoly->nVertex++; - } - Odie_PolygonComputeArea(interp,pNewPoly); - Tcl_SetObjResult(interp, Odie_NewPolygonObj(pNewPoly)); - if(isnew) Odie_Free((char *)pPoly); - return TCL_OK; -} - -static int polygon_method_area ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - Poly *p; - int isnew; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N ?N...?"); - return TCL_ERROR; - } - if( Odie_GetPolygonFromObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR; - double area=p->area; - if(isnew) Odie_Free((char *)p); - int i; - for(i=2;iarea; - if(isnew) Odie_Free((char *)p); - } - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(area)); - return TCL_OK; -} - -static int polygon_method_bbox ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* poly bbox N - ** - ** Return the bounding box for a polygon - */ - Poly *p; - int isnew; - Tcl_Obj *pResult; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N ?N...?"); - return TCL_ERROR; - } - if( Odie_GetPolygonFromObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR; - double left=p->bbox.l; - double top=p->bbox.t; - double right=p->bbox.r; - double bottom=p->bbox.b; - int i; - if(isnew) Odie_Free((char *)p); - for(i=2;ibbox.l < left) left=p->bbox.l; - if(p->bbox.t > top) top=p->bbox.t; - if(p->bbox.r > right) right=p->bbox.r; - if(p->bbox.b < bottom) bottom=p->bbox.b; - if(isnew) Odie_Free((char *)p); - } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(left)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(top)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(right)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(bottom)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int polygon_method_info ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* poly info N - ** - ** Return the coordinates for a polygon - */ - Tcl_Obj *pResult; - Poly *p; - int i,isnew; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N"); - return TCL_ERROR; - } - if( Odie_GetPolygonFromObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR; - pResult = Tcl_NewObj(); - for(i=0; inVertex-1; i++){ - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->v[i][X_IDX])); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(p->v[i][Y_IDX])); - } - if(isnew) Odie_Free((char *)p); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int polygon_method_intersect ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* poly intersect N1 N2 - ** - ** Return a list of 3 elements where the first element is the - ** area of intersection between polygons N1 and N2 and the remaining - ** 3 elements are the X and Y coordinates of a point within both - ** polygons. - ** - ** The current implementation returns an approximation. We might - ** change it to compute the exact intersection later. - */ - Poly *p1, *p2; - int isnew1,isnew2; - double area; - double xInside = 0.0, yInside = 0.0; - Tcl_Obj *pResult; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N1 N2"); - return TCL_ERROR; - } - if( Odie_GetPolygonFromObj(interp, objv[1], &p1, &isnew1) ) return TCL_ERROR; - if( Odie_GetPolygonFromObj(interp, objv[2], &p2, &isnew2) ) { - if(isnew1) Odie_Free((char *)p1); - return TCL_ERROR; - } - if( p1->bbox.r<=p2->bbox.l || p1->bbox.l>=p2->bbox.r - || p1->bbox.t<=p2->bbox.b || p1->bbox.b>=p2->bbox.t ){ - area = 0.0; - }else if( p1->area==0.0 || p2->area==0.0 ){ - area = 0.0; - }else{ - double x0, y0, x1, y1, dx, dy, xP, yP, xC, yC; - int i, j, cnt; - int score, bestScore; - static const int n = 50; - char hit[50][50]; - - /* Compute the overlap of the bounding boxes of the two polygons. */ - x0 = p1->bbox.l < p2->bbox.l ? p2->bbox.l : p1->bbox.l; - y0 = p1->bbox.t > p2->bbox.t ? p2->bbox.t : p1->bbox.t; - x1 = p1->bbox.r > p2->bbox.r ? p2->bbox.r : p1->bbox.r; - y1 = p1->bbox.b < p2->bbox.b ? p2->bbox.b : p1->bbox.b; - - /* Divide the intersection of the bounding boxes into a n-by-n grid - ** and count the number of elements in this grid whose centers fall - ** within both polygons. This will be our approximation for the - ** intersection of the polygons themselves. - */ - dx = (x1-x0)/n; - dy = (y1-y0)/n; - cnt = 0; - xC = yC = 0.0; - for(i=0; i0 && within(p2, xP, yP)>0 ){ - cnt++; - hit[i][j] = 1; - xC += xP; - yC += yP; - }else{ - hit[i][j] = 0; - } - } - } - - /* We need to find a good approximation for the center of the - ** overlap. Begin by computing the center of mass for the - ** overlapping region. Then find the point inside the intersection - ** that is nearest the center of mass. - */ - if( cnt>0 ){ - area = cnt*(x1-x0)*(y0-y1)/(n*n); - xC /= cnt; - yC /= cnt; - bestScore = -1.0; - for(i=0; i=0) { - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1)); - return TCL_OK; - } - } - Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0)); - return TCL_OK; - } -} - -static int polygon_method_segments ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - Tcl_Obj *pResult; - int isnew; - Poly *p; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N"); - return TCL_ERROR; - } - if( Odie_GetPolygonFromObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR; - int i; - double px,py; - pResult=Tcl_NewObj(); - px=p->v[0][X_IDX]; - py=p->v[0][Y_IDX]; - for(i=1; inVertex-1; i++){ - Tcl_Obj *segment=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(px)); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(py)); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[i][X_IDX])); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[i][Y_IDX])); - Tcl_ListObjAppendElement(interp,pResult, segment); - px=p->v[i][X_IDX]; - py=p->v[i][Y_IDX]; - } - Tcl_Obj *segment=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(px)); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(py)); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[0][X_IDX])); - Tcl_ListObjAppendElement(interp,segment, Tcl_NewDoubleObj(p->v[0][Y_IDX])); - Tcl_ListObjAppendElement(interp,pResult, segment); - Tcl_SetObjResult(interp, pResult); - if(isnew) Odie_Free((char *)p); - return TCL_OK; -} - -static int polygon_method_rectangle ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double cx, cy, radx,rady; - Tcl_Obj *pResult=Tcl_NewObj(); - - if( objc != 5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - radx=radx/2.0; - rady=rady/2.0; - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - - -static int polygon_method_vector_place ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* - ** Apply Matrices - */ - Tcl_Obj *pResult=Tcl_NewObj(); - int i; - double zoom; - double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0}; - double centerx,centery,normalx,normaly,angle; - - if( objc < 8 ){ - Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?..."); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],¢erx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],¢ery)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR; - - angle=atan2(normaly,normalx); - matA[0]=cos(angle); - matA[1]=sin(angle); - matA[2]=-sin(angle); - matA[3]=cos(angle); - matA[4]=0.0; - matA[5]=0.0; - - - for(i=6;i0) { - if(Tcl_ListObjIndex(interp, objv[1], 0, &temp)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,temp,&nx)) return TCL_ERROR; - } - if(len>1) { - if(Tcl_ListObjIndex(interp, objv[1], 1, &temp)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,temp,&ny)) return TCL_ERROR; - } - Tcl_ObjSetVar2(interp,objv[2],NULL,Tcl_NewDoubleObj(nx),0); - Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(ny),0); - return TCL_OK; -} - -static int polygon_method_corners ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double cx, cy, radx,rady; - - if( objc != 5 && objc != 9 ){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?x0var y0var x1var y1var?"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - if (objc == 5) { - Tcl_Obj *pResult=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; - } - /* - Replaces - set x0 [expr {$cx-$d}] - set y0 [expr {$cy-$d}] - set x1 [expr {$cx+$d}] - set y1 [expr {$cy+$d}] - */ - - Tcl_ObjSetVar2(interp,objv[5],NULL,Tcl_NewDoubleObj(cx+radx),0); - Tcl_ObjSetVar2(interp,objv[6],NULL,Tcl_NewDoubleObj(cy-rady),0); - Tcl_ObjSetVar2(interp,objv[7],NULL,Tcl_NewDoubleObj(cx-radx),0); - Tcl_ObjSetVar2(interp,objv[8],NULL,Tcl_NewDoubleObj(cy+rady),0); - - return TCL_OK; -} - - - -static int polygon_method_hexgrid_create ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - /* poly hexgrid - ** - ** Reduce the polygons to a series - ** of grid coordinates - */ - Tcl_Obj *pResult; - Poly *p; - int isnew; - pResult = Tcl_NewObj(); - double gridsize=500.0; - double x,y; - - if(objc < 3) { - Tcl_WrongNumArgs(interp, 1, objv, "GRIDSIZE ?POLY ...?"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &gridsize) ) return TCL_ERROR; - - if( Odie_GetPolygonFromObj(interp, objv[2], &p, &isnew) ) return TCL_ERROR; - double left=p->bbox.l; - double top=p->bbox.t; - double right=p->bbox.r; - double bottom=p->bbox.b; - int i; - if(isnew) Odie_Free((char *)p); - for(i=3;ibbox.l < left) left=p->bbox.l; - if(p->bbox.t > top) top=p->bbox.t; - if(p->bbox.r > right) right=p->bbox.r; - if(p->bbox.b < bottom) bottom=p->bbox.b; - if(isnew) Odie_Free((char *)p); - } - - pResult = Tcl_NewObj(); - left-=gridsize; - top+=gridsize; - right+=gridsize; - bottom-=gridsize; - int row=0; - for(y=bottom;y<=top;y+=gridsize) { - double lstartx=left; - double gy=floor(y/gridsize)*gridsize; - row++; - if(row%2==1) { - lstartx-=gridsize/2; - } - for(x=lstartx;x<=right;x+=gridsize) { - double gx=floor(x/gridsize)*gridsize; - int found=0; - for(i=2;i0) { - found=1; - break; - } - } - if(found) { - Tcl_Obj *coord=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gx)); - Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gy)); - Tcl_ListObjAppendElement(interp, pResult, coord); - } - } - } - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - - -static int polygon_method_squaregrid_create ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - /* poly hexgrid - ** - ** Reduce the polygons to a series - ** of grid coordinates - */ - Tcl_Obj *pResult; - Poly *p; - int isnew; - pResult = Tcl_NewObj(); - double gridsize=500.0; - double x,y; - if(objc < 3) { - Tcl_WrongNumArgs(interp, 1, objv, "GRIDSIZE ?POLY ...?"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &gridsize) ) return TCL_ERROR; - - if( Odie_GetPolygonFromObj(interp, objv[2], &p, &isnew) ) return TCL_ERROR; - double left=p->bbox.l; - double top=p->bbox.t; - double right=p->bbox.r; - double bottom=p->bbox.b; - if(isnew) Odie_Free((char *)p); - - int i; - for(i=3;ibbox.l < left) left=p->bbox.l; - if(p->bbox.t > top) top=p->bbox.t; - if(p->bbox.r > right) right=p->bbox.r; - if(p->bbox.b < bottom) bottom=p->bbox.b; - if(isnew) Odie_Free((char *)p); - } - - pResult = Tcl_NewObj(); - left-=gridsize; - top+=gridsize; - right+=gridsize; - bottom-=gridsize; - - for(y=bottom;y<=top;y+=gridsize) { - double gy=floor(y/gridsize)*gridsize; - for(x=left;x<=right;x+=gridsize) { - double gx=floor(x/gridsize)*gridsize; - int found=0; - for(i=2;i0) { - found=1; - break; - } - } - if(found) { - Tcl_Obj *coord=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gx)); - Tcl_ListObjAppendElement(interp, coord, Tcl_NewDoubleObj(gy)); - Tcl_ListObjAppendElement(interp, pResult, coord); - } - } - } - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int polygon_method_grid_nearest ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - return TCL_OK; -} - -int Odie_Polygon_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - modPtr=Tcl_FindNamespace(interp,"polygon",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "polygon", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::polygon::area",(Tcl_ObjCmdProc *)polygon_method_area,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::bbox",(Tcl_ObjCmdProc *)polygon_method_bbox,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::corners",(Tcl_ObjCmdProc *)polygon_method_corners,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::create",(Tcl_ObjCmdProc *)polygon_method_create,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::drawobj_orientation",(Tcl_ObjCmdProc *)polygon_method_drawobj_orientation,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::grid_nearest",(Tcl_ObjCmdProc *)polygon_method_grid_nearest,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::hexgrid_create",(Tcl_ObjCmdProc *)polygon_method_hexgrid_create,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::hexagon",(Tcl_ObjCmdProc *)polygon_method_hexagon,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::info",(Tcl_ObjCmdProc *)polygon_method_info,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::intersect",(Tcl_ObjCmdProc *)polygon_method_intersect,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::poly_place",(Tcl_ObjCmdProc *)polygon_method_poly_place,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::rectangle",(Tcl_ObjCmdProc *)polygon_method_rectangle,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::simplify",(Tcl_ObjCmdProc *)polygon_method_simplify,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::segments",(Tcl_ObjCmdProc *)polygon_method_segments,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::squaregrid_create",(Tcl_ObjCmdProc *)polygon_method_squaregrid_create,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::vector_place",(Tcl_ObjCmdProc *)polygon_method_vector_place,NULL,NULL); - Tcl_CreateObjCommand(interp,"::polygon::within",(Tcl_ObjCmdProc *)polygon_method_within,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - return TCL_OK; -} DELETED cmodules/geometry/generic/segset.c Index: cmodules/geometry/generic/segset.c ================================================================== --- cmodules/geometry/generic/segset.c +++ /dev/null @@ -1,875 +0,0 @@ -#include "odieInt.h" -#include -#include -#include -#include - -#ifndef IRM_EPSILON -#define IRM_EPSILON 1.19E-07 -#endif - -#ifndef M_PI -# define M_PI 3.1415926535898 -#endif - - -/* -** LEFT OFF IMPLEMENTING SEGMENT SET AS A TCL OBJECT -** TODO: Write routine to detect a polygon and convert -** to segset and vice versa -** -*/ - -static Tcl_Interp *local_interp; - -#if 0 -/* -** Print all vectors in the SegSet. Used for debugging purposes only. -*/ -static void SegPrint(Segment *p, const char *zText){ - printf("%s ", zText); - if( p ){ - printf("%g,%g -> %g,%g\n", p->from[X_IDX], p->from[Y_IDX], p->to[X_IDX], p->to[Y_IDX]); - }else{ - printf(" (null)\n"); - } -} -static void SegSetPrint(SegSet *pSet){ - Link *pLink; - printf("%d vectors:\n", pSet->nSeg); - for(pLink=pSet->pAll; pLink; pLink=pLink->pNext){ - SegPrint(pLink->pLinkNode, " "); - } -} -#endif - - -/* -** This section implements code for breaking up compartment floorplans -** into triangles. -** -** A floorplan is defined by vectors (x0,y0,x1,y1) which define the -** parameter of each compartment. The interior of the compartment -** is always to the right of the vector. Thus the outer boundary -** of the compartment rotates clockwise when viewed from above. -** Compartments may contain holes which are interior voids surrounded -** by counter-clockwise rotating boundaries. -*/ - -/* -** Given line segment AB, locate segment BC and return a Vector to -** it. If there is not BC return NULL. If there is more than one -** BC return the one that minimizes the angle ABC. -*/ -static Segment *SegSetNext(SegSet *pSet, Segment *pAB){ - Link *pX; - Segment *pBest = 0; - double angle, bestAngle; - int cnt = 0; - int h; - h = hashVectorXY(pAB->to); - - for(pX=pSet->hashFrom[h]; pX; pX=pX->pNext){ - Segment *pSeg = pX->pLinkNode; - if( !sameVectorXY(pSeg->from,pAB->to) ) continue; - /* if(pAB->isBoundary > 1 && pSeg->isBoundary!=0 && pSeg->isBoundary!=pAB->isBoundary) continue; */ - if( cnt==0 ){ - pBest = pSeg; - bestAngle = fabs(VectorXY_angleOf(pAB->from, pAB->to, pBest->to)); - }else{ - angle = fabs(VectorXY_angleOf(pAB->from, pAB->to, pSeg->to)); - if( anglepAll; pLoop; pLoop=pNext){ - Segment *p; - VectorXY from, to, center; - double vec_dist_sq; - - p = pLoop->pLinkNode; - pNext = pLoop->pNext; - if(p->ignore) continue; - p->ignore=1; - vec_dist_sq = VectorXY_distance_squared(p->from, p->to); - VectorXY_Set(from,p->from); - VectorXY_Set(to,p->to); - center[X_IDX] = rint(0.5*(from[X_IDX] + to[X_IDX])); - center[Y_IDX] = rint(0.5*(from[Y_IDX] + to[Y_IDX])); - - if(vec_dist_sq>(minLen2*3)) { - Segment *q; - /* BISECT */ - p->to[X_IDX]=center[X_IDX]; - p->to[Y_IDX]=center[Y_IDX]; - q=SegSetInsert(pSet,center,to,p->isBoundary); - if(q) { - q->midpoint=1; - q->ignore=1; - } - } else if(vec_dist_sqpAll; pLoop; pLoop=pNext){ - pNext = pLoop->pNext; - p = pLoop->pLinkNode; - if( sameVectorXY(p->to,from) || sameVectorXY(p->to,to) ) { - VectorXY_Set(p->to,center); - } - if( sameVectorXY(p->from,from) || sameVectorXY(p->from,to) ) { - VectorXY_Set(p->from,center); - SegRelink(pSet, p); - } - if( sameVectorXY(p->from,p->to) ) { - SegSetRemove(pSet, p); - Odie_Free((char *)p); - } - } - pNext = pSet->pAll; - } - } -} - -int Segset_Insert_Vectors(Tcl_Interp *interp,SegSet *pSet,int fill,int listLen,Tcl_Obj **listObjPtrs) { - VECTORXY A,B; - int i; - /* Import a flat list, every 4 coordinates x0 y0 x1 y1*/ - if(listLen % 4) { - Tcl_AppendResult(interp, "Could not interpret coordinates", 0); - return TCL_ERROR; - } - for(i=0;ifrom,from); - VectorXY_Set(p->to,to); - - p->isBoundary = isBoundary; - p->notOblique = 0; - LinkInit(p->pAll, p); - LinkInit(p->pFrom, p); - LinkInit(p->pSet, p); - - LinkInsert(&pSet->pAll, &p->pAll); - h = hashPoint(p->from); - LinkInsert(&pSet->hashFrom[h], &p->pFrom); - - pSet->nSeg++; - pSet->pCurrent = p; - return p; -} - -/* -** Remove a segment from the segment set -*/ -CTHULHU_INLINE void SegSetRemove(SegSet *pSet, Segment *p){ - LinkRemove(&p->pAll); - LinkRemove(&p->pFrom); - pSet->nSeg--; - if( pSet->pCurrent==p ){ - pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0; - } -} - -/* -** Call this routine to relink into a segment when the -** Seg.from vector changes. -*/ -CTHULHU_INLINE void SegRelink(SegSet *pSet, Segment *p){ - int h; - LinkRemove(&p->pFrom); - h = hashPoint(p->from); - LinkInsert(&pSet->hashFrom[h], &p->pFrom); -} - -/* -** Remove all segments from a segment set -*/ -CTHULHU_INLINE void SegSetClear(SegSet *pSet){ - while( pSet->pAll ){ - Segment *p; - assert( pSet->nSeg>0 ); - p=pSet->pAll->pLinkNode; - SegSetRemove(pSet, p); - Odie_Free((char *)p); - } - assert( pSet->nSeg==0 ); -} - -/* -** Advance the pSet->pAll pointer so that it is pointing to a different -** segment. -*/ -CTHULHU_INLINE void SegSetStep(SegSet *pSet){ - if( pSet->pCurrent ){ - Link *pNext = pSet->pCurrent->pAll.pNext; - pSet->pCurrent = pNext ? pNext->pLinkNode : 0; - } - if( pSet->pCurrent==0 ){ - pSet->pCurrent = pSet->pAll ? pSet->pAll->pLinkNode : 0; - } -} - -static int segset_method_create ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - local_interp=interp; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N"); - return TCL_ERROR; - } - int isnew; - SegSet *p; - if( Odie_GetSegmentSetFromObj(interp, objv[1], &p, &isnew) ) return TCL_ERROR; - if(isnew) { - Tcl_SetObjResult(interp, Odie_NewSegmentSetObj(p)); - } else { - Tcl_SetObjResult(interp, objv[1]); - } - return TCL_OK; -} - - -static int segset_method_add ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - local_interp=interp; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N X0 Y0 X1 Y1"); - return TCL_ERROR; - } - int i,j; - SegSet *pSet; - VECTORXY A,B; - double x[4]; - - if( Odie_GetSegmentGetFromVar(interp, objv[1], &pSet) ) return TCL_ERROR; - for(i=2;iisBoundary<1) { - found->isBoundary=1; - } - } else { - SegSetInsert(pSet, A, B, 1); - } - } - - Tcl_Obj *objPtr=Odie_NewSegmentSetObj(pSet); - Tcl_ObjSetVar2(interp,objv[1],NULL,objPtr,0); - Tcl_SetObjResult(interp, objPtr); - - return TCL_OK; - -createfail: - if(pSet) { - SegSetClear(pSet); - } - - return TCL_ERROR; -} - -static int segset_method_subtract ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - local_interp=interp; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "N X0 Y0 X1 Y1"); - return TCL_ERROR; - } - int i,j; - SegSet *pSet=NULL; - VECTORXY A,B; - double x[4]; - - if( Odie_GetSegmentGetFromVar(interp, objv[1], &pSet) ) return TCL_ERROR; - for(i=2;iisBoundary<3) { - found->isBoundary=3; - } - } else { - SegSetInsert(pSet, A, B, 3); - } - } - - /* - ** Meander through and clip all segments of isBoundary=1 that touch - ** an isBoundary=3 - */ - - Tcl_Obj *objPtr=Odie_NewSegmentSetObj(pSet); - Tcl_ObjSetVar2(interp,objv[1],NULL,objPtr,0); - Tcl_SetObjResult(interp, objPtr); - return TCL_OK; - -createfail: - if(pSet) { - SegSetClear(pSet); - } - - return TCL_ERROR; -} - - -static int segset_method_difference ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { -#ifdef NEVER - local_interp=interp; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SEG_POSITIVE SEG_NEGATIVE"); - return TCL_ERROR; - } - int created; - int i,j; - SegSet *pSet=NULL; - VECTORXY A,B; - double x[4]; - - Tcl_Obj **varv; - int varc; - if(Odie_GetSegmentSetFromObj(interp,objv[1],&pSet,&created)) return TCL_ERROR; - - if (Tcl_ListObjGetElements(interp, objv[2], &varc, &varv) != TCL_OK) { - goto createfail; - } - if(Segset_Insert_Vectors(interp,pSet,3,varc,varv)) { - goto createfail; - } - Link *pLoop, *pNext; - Link *qLoop, *qNext; - - for(pLoop=pSet->pAll; pLoop; pLoop=pNext){ - Segment *pAB; - pAB = pLoop->pLinkNode; - pNext = pLoop->pNext; - if(pAB->isBoundary>1) continue; - - for(qLoop=pSet->pAll; qLoop; qLoop=pNext){ - Segment *pCD; - int incident=0; - pCD = qLoop->pLinkNode; - qNext = qLoop->pNext; - if(pCD->isBoundary<3) continue; - incident=ODIE_Math_LineLineCoincident( - pAB->from[X_IDX],pAB->from[Y_IDX], - pAB->to[X_IDX],pAB->to[Y_IDX], - pCD->from[X_IDX],pCD->from[Y_IDX], - pCD->to[X_IDX],pCD->to[Y_IDX] - ); - switch(incident) { - case 0: continue; /* No overlap */ - case 3: - /* pAB fits entirely in the range of pBC*/ - SegSetRemove(pSet,pAB); - continue; - case 12: - /* pCD fits entirely in the range of pAB*/ - /* Shorten the first side, and add a stub to represent the other */ - /* THIS CODE IS NOT FINISHED */ - if(VectorXY_distance_squared(pAB->from, pCD->from) < VectorXY_distance_squared(pAB->from, pCD->to)) { - VectorXY_Set(pAB->from,pCD->from); - SegRelink(pSet,pAB); - } else { - VectorXY_Set(pAB->to,pCD->to); - SegSetInsert(pSet,pCD->from,pAB->to,1); - } - break; - case 1: { - /* A is along CD */ - if(VectorXY_distance_squared(pAB->from, pCD->from) < VectorXY_distance_squared(pAB->from, pCD->to)) { - VectorXY_Set(pAB->from,pCD->from); - } else { - VectorXY_Set(pAB->from,pCD->to); - } - SegRelink(pSet,pAB); - break; - } - case 2: { - /* B is along CD */ - /* A is along CD */ - if(VectorXY_distance_squared(pAB->to, pCD->from) < VectorXY_distance_squared(pAB->to, pCD->to)) { - VectorXY_Set(pAB->to,pCD->from); - } else { - VectorXY_Set(pAB->to,pCD->to); - } - break; - } - case 4: { - /* C is along AB */ - if(VectorXY_distance_squared(pCD->from, pAB->from) < VectorXY_distance_squared(pCD->from, pAB->to)) { - VectorXY_Set(pAB->from,pCD->from); - SegRelink(pSet,pAB); - } else { - VectorXY_Set(pAB->to,pCD->from); - } - break; - } - case 8: { - /* D is along AB */ - if(VectorXY_distance_squared(pCD->to, pAB->from) < VectorXY_distance_squared(pCD->to, pAB->to)) { - VectorXY_Set(pAB->from,pCD->to); - SegRelink(pSet,pAB); - } else { - VectorXY_Set(pAB->to,pCD->to); - } - break; - } - } - } - } - - - if(isnew) { - Tcl_SetObjResult(interp, Odie_NewSegmentSetObj(pSet)); - } else { - Tcl_InvalidateStringRep(objv[1]); - Tcl_SetObjResult(interp, objv[1]); - } - return TCL_OK; - -createfail: - if(pSet) { - SegSetClear(pSet); - } - - return TCL_ERROR; -#else - return TCL_OK; -#endif -} - -static int segset_method_rectangle ( - ClientData *dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double cx, cy, radx,rady; - Tcl_Obj *pResult=Tcl_NewObj(); - local_interp=interp; - - if( objc != 5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - radx=radx/2.0; - rady=rady/2.0; - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - - -static int WalkSegments(SegSet *pSet) { - Link *pLoop, *pNext; - int changed=0; - for(pLoop=pSet->pAll; pLoop; pLoop=pNext){ - Segment *pAB, *pBC; - Link *pRight, *pL2; - int c; - /* Find an oblique angle ABC */ - pAB = pLoop->pLinkNode; - pNext = pLoop->pNext; - - /* - ** If we are at an oblique for a non boundary - ** segment, continue - */ - if( pAB->notOblique ) continue; - pBC = SegSetNext(pSet, pAB); - if( pBC==0 ) { - /* - ** Remove an orphan wall - */ - SegSetRemove(pSet, pAB); - Odie_Free((char *)pAB); - changed=1; - continue; - } - - if( (c = VectorXY_rightOf(pAB->from, pAB->to, pBC->to))>=0 ){ - if( c>0 || !sameVectorXY(pAB->from,pBC->to) ){ - pAB->notOblique = 1; - continue; - } - } - - /* If we reach here, it means that ABC is an oblique angle. - ** Locate all vertices to the right of AB. - */ - pRight = 0; - for(pL2=pSet->pAll; pL2; pL2=pL2->pNext){ - Segment *pX = pL2->pLinkNode; - if( VectorXY_strictlyRightOf(pAB->from, pAB->to, pX->from)<0 ) continue; - if( sameVectorXY(pAB->to,pX->from) ) continue; - pX->score = VectorXY_distance_squared(pAB->to, pX->from); - pX->isRight = VectorXY_rightOf(pBC->from, pBC->to, pX->from); - LinkInit(pX->pSet, pX); - LinkInsert(&pRight, &pX->pSet); - } - if( pRight==0 ){ - return TCL_ERROR; - } - - /* pRight is a list of vertices to the right of AB. Find the - ** closest vertex X on this list where the line BX does not intersect - ** any other segment in the polygon. Then add segments BX and XB. - */ - while( pRight ){ - Link *pBest=NULL; - double bestScore; - int bestRight; - Segment *pThis,*pX, *pQ; - - - /* Search for the "best" vertex. The best vertex is the - ** one that is closest. Though if the vertex is to the left - ** of BC (and thus would create another oblique angle) then - ** artificially reduce its score because we would prefer not - ** to use it. - */ - pBest = pRight; - pThis=pBest->pLinkNode; - bestScore = pThis->score; - bestRight = pThis->isRight; - for(pL2=pBest->pNext; pL2; pL2=pL2->pNext){ - int better=0; - pX = pL2->pLinkNode; - if( pX->isRight>0 && bestRight <=0 ) { - better=1; - } else if ( pX->isRight<=0 && bestRight>0 ) { - better=0; - } else if( pX->scorescore; - bestRight = pX->isRight; - pBest = pL2; - } - } - - - - /* The best vertex is pX */ - pX = pBest->pLinkNode; - LinkRemove(pBest); - - /* Check to see if BX intersects any segment. If it does, then - ** go back and search for a different X - */ - for(pL2=pSet->pAll; pL2; pL2=pL2->pNext){ - pQ = pL2->pLinkNode; - if( pQ!=pAB && pQ!=pX - && VectorXY_intersect(pAB->to, pX->from, pQ->from, pQ->to) ){ - break; - } - } - if( pL2 ) continue; - - /* It did not intersect. So add BX and XB to the pSet-> - */ - SegSetInsert(pSet, pAB->to, pX->from, 0); - SegSetInsert(pSet, pX->from, pAB->to, 0); - pRight = 0; - } - changed=1; - if(!pAB->isBoundary) { - pNext = pSet->pAll; - } - } - if(changed) { - return TCL_CONTINUE; - } - return TCL_OK; -} - - -/* -** tclcmd: convex_subpolygons VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ... -** -** VECTORS is a list of floating-VectorXY values. Each group of four values -** forms a vector X0,Y0[X_IDX]1,Y1. The vectors are in no particular order, -** but together they form one or more loops. Space to the right of each -** vector is within the loop and space to the left is outside. -** -** Loops can be nested. The outer boundary is formed by a clockwise loop -** of vectors. Interior holes are formed by counter-clockwise loops. -** -** The output is a list polygons. Each polygon is a list of 3 or more -** X,Y coordinate pairs. All polygons are convex and disjoint and they -** together cover the input polygon. -** -** Optionally, the user can specify a series of polygons to be subtracted -** from the main polygon. These are given as an XY list suitable for -** producing a polygon on the tkcanvas -*/ -TCL_COMMAND int segset_method_decompose ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Obj *pSub; /* A sublist for a single polygon */ - int i, idx, cnt, created; - SegSet *set; - double minLen = 0.0; - local_interp=interp; - - if( objc!=2 && objc!=3 && objc<4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "VECTORS ?MINLENGTH? ?HOLE? ?HOLE? ..."); - return TCL_ERROR; - } - if(Odie_GetSegmentSetFromObj(interp,objv[1],&set,&created)) return TCL_ERROR; - if( objc>2 ){ - if( Tcl_GetDoubleFromObj(interp, objv[2], &minLen) ) return TCL_ERROR; - } - /* - ** Insert the polygons the user specified as - ** the shape of the holes first - */ - for(idx=3;idx0.0 ){ - Segset_Bisect_Edges(set,minLen); - } - - cnt=0; - i=TCL_CONTINUE; - while(i==TCL_CONTINUE) { - i=WalkSegments(set); - cnt++; - if(cnt>10) { - break; - } - } - if(i==TCL_CONTINUE) { - Tcl_AppendResult(interp, "boundary too complex", 0); - SegSetClear(set); - return TCL_ERROR; - } - if(i==TCL_ERROR) { - Tcl_AppendResult(interp, "boundary does not enclose a finite space", 0); - SegSetClear(set); - return TCL_ERROR; - } - - /* Now all polygons should be convex. We just have to generate them. */ - int obtuseangles=0; - Tcl_Obj *pOut=Tcl_NewObj(); /* The output list */ - //Odie_trace_printf(interp,"NSEG %d\n",set->nSeg); - while( set->nSeg ){ - VectorXY start; - - Segment *pAB, *pBC; - int valid = 0; - int cnt = 0; - - pAB = set->pAll->pLinkNode; - start[X_IDX]=pAB->from[X_IDX]; - start[Y_IDX]=pAB->from[Y_IDX]; - - /* - ** Walk along the wallsets, filter out - ** any that do not include one of the - ** vectors given as an input of the first - ** argument - */ - pSub = Tcl_NewObj(); - while( pAB ){ - pBC = SegSetNext(set, pAB); - if(pAB->isBoundary < 2) valid=1; - cnt++; - if( minLen>=1.0 ){ - Tcl_ListObjAppendElement(0, pSub, Tcl_NewIntObj(pAB->to[X_IDX])); - Tcl_ListObjAppendElement(0, pSub, Tcl_NewIntObj(pAB->to[Y_IDX])); - } else { - Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to[X_IDX])); - Tcl_ListObjAppendElement(0, pSub, Tcl_NewDoubleObj(pAB->to[Y_IDX])); - } - SegSetRemove(set, pAB); - if( sameVectorXY(pAB->to,start) ) { - break; - } - Odie_Free((char *)pAB); - pAB = pBC; - } - if( pAB==0 || cnt<3 || !valid){ - Tcl_DecrRefCount(pSub); - }else{ - Tcl_ListObjAppendElement(0, pOut, pSub); - //Odie_trace_printf(local_interp,"NEWPOLY %s\n",Tcl_GetString(pSub)); - } - } - - if(created) { - SegSetClear(set); - Odie_Free((char *)set); - } - - Tcl_SetObjResult(interp, pOut); - return TCL_OK; - -createrror: - SegSetClear(set); - return TCL_ERROR; -} - -int Odie_Segset_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - modPtr=Tcl_FindNamespace(interp,"segset",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "segset", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::segset::add",(Tcl_ObjCmdProc *)segset_method_add,NULL,NULL); - Tcl_CreateObjCommand(interp,"::segset::create",(Tcl_ObjCmdProc *)segset_method_create,NULL,NULL); - Tcl_CreateObjCommand(interp,"::segset::subtract",(Tcl_ObjCmdProc *)segset_method_subtract,NULL,NULL); - //Tcl_CreateObjCommand(interp,"::segset::vectors",(Tcl_ObjCmdProc *)segset_method_vectors,NULL,NULL); - - - Tcl_CreateObjCommand(interp,"::segset::decompose",(Tcl_ObjCmdProc *)segset_method_decompose,NULL,NULL); - Tcl_CreateObjCommand(interp,"::segset::rectangle",(Tcl_ObjCmdProc *)segset_method_rectangle,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - return TCL_OK; -} DELETED cmodules/geometry/generic/shapes.c Index: cmodules/geometry/generic/shapes.c ================================================================== --- cmodules/geometry/generic/shapes.c +++ /dev/null @@ -1,475 +0,0 @@ - -/* -** This file is machine generated. Changes will -** be overwritten on the next run of cstruct.tcl -*/ -#include "odieInt.h" - -/* -** Functions provided by the template -*/ - - -static int shapes_method_corners ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - - double cx, cy, radx,rady; - - if( objc != 5 && objc != 9 ){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?x0var y0var x1var y1var?"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - if (objc == 5) { - Tcl_Obj *pResult=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; - } - /* - Replaces - set x0 [expr {$cx-$d}] - set y0 [expr {$cy-$d}] - set x1 [expr {$cx+$d}] - set y1 [expr {$cy+$d}] - */ - - Tcl_ObjSetVar2(interp,objv[5],NULL,Tcl_NewDoubleObj(cx+radx),0); - Tcl_ObjSetVar2(interp,objv[6],NULL,Tcl_NewDoubleObj(cy-rady),0); - Tcl_ObjSetVar2(interp,objv[7],NULL,Tcl_NewDoubleObj(cx-radx),0); - Tcl_ObjSetVar2(interp,objv[8],NULL,Tcl_NewDoubleObj(cy+rady),0); - - return TCL_OK; -} - -static int shapes_method_drawobj_orientation ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - - Tcl_Obj *temp; - int len; - double nx=100,ny=0; - if( objc !=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "orientation nxvar nyvar"); - return TCL_ERROR; - } - - if(Tcl_ListObjLength(interp,objv[1],&len)) return TCL_ERROR; - if(len>0) { - if(Tcl_ListObjIndex(interp, objv[1], 0, &temp)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,temp,&nx)) return TCL_ERROR; - } - if(len>1) { - if(Tcl_ListObjIndex(interp, objv[1], 1, &temp)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,temp,&ny)) return TCL_ERROR; - } - Tcl_ObjSetVar2(interp,objv[2],NULL,Tcl_NewDoubleObj(nx),0); - Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(ny),0); - return TCL_OK; -} - - -static int shapes_method_poly_hex ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - - int i,flip=0; - double cx, cy, radx,rady; - - Tcl_Obj *pResult=Tcl_NewObj(); - double coords[7][2]= { - {1.00, 0.00} , {0.50, M_SQRT3_2} , - {-0.50, M_SQRT3_2} , {-1.00, -0.00} , - {-0.50, -M_SQRT3_2} , {0.50, -M_SQRT3_2}, - {1.00, 0.00} - }; - if( objc != 5 && objc != 6){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy ?flip?"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - if(objc==6) { - if(Tcl_GetBooleanFromObj(interp,objv[5],&flip)) return TCL_ERROR; - } - radx=radx/2.0; - rady=rady/2.0; - - for(i=0;i<6;i++) { - if(flip) { - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][1])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][0])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][1])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][0])); - } else { - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i][0])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i][1])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx*coords[i+1][0])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady*coords[i+1][1])); - } - } - - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int shapes_method_poly_place ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - - /* - ** Apply Matrices - */ - Tcl_Obj *pResult=Tcl_NewObj(); - int i; - double zoom; - double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0}; - double centerx,centery,normalx,normaly,angle; - - if( objc < 8 ){ - Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?..."); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],¢erx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],¢ery)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR; - - angle=atan2(normaly,normalx); - matA[0]=cos(angle); - matA[1]=sin(angle); - matA[2]=-sin(angle); - matA[3]=cos(angle); - matA[4]=0.0; - matA[5]=0.0; - double startx,starty,prevx,prevy; - - i=6; - { - double x,y,sx,sy,newx,newy; - if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR; - - sx=(x/zoom); - sy=(y/zoom); - newx=matA[0]*sx+matA[1]*sy+matA[4]+centerx; - newy=matA[2]*sx+matA[3]*sy+matA[5]+centery; - - startx=newx; - starty=newy; - prevx=newx; - prevy=newy; - } - - for(i=8;iobjc) break; - if(Tcl_GetDoubleFromObj(interp,objv[i],&x)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[i+1],&y)) return TCL_ERROR; - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(px)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(py)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(x)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(y)); - px=x; - py=y; - } - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(px)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(py)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(fx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(fy)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int shapes_method_rectangle_as_polygon ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - - double cx, cy, radx,rady; - Tcl_Obj *pResult=Tcl_NewObj(); - - if( objc != 5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - radx=radx/2.0; - rady=rady/2.0; - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int shapes_method_rectangle_as_vectors ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - - - double cx, cy, radx,rady; - Tcl_Obj *pResult=Tcl_NewObj(); - - if( objc != 5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "cx cy dimx dimy"); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&cx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&cy)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&radx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&rady)) return TCL_ERROR; - radx=radx/2.0; - rady=rady/2.0; - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx+radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy+rady)); - - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cx-radx)); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(cy-rady)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int shapes_method_vector_place ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* - ** Apply Matrices - */ - Tcl_Obj *pResult=Tcl_NewObj(); - int i; - double zoom; - double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0}; - double centerx,centery,normalx,normaly,angle; - - if( objc < 8 ){ - Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery normalx normaly x1 y1 ?x2 y2?..."); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],¢erx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],¢ery)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&normalx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[5],&normaly)) return TCL_ERROR; - - angle=atan2(normaly,normalx); - matA[0]=cos(angle); - matA[1]=sin(angle); - matA[2]=-sin(angle); - matA[3]=cos(angle); - matA[4]=0.0; - matA[5]=0.0; - - - for(i=6;i7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "zoom centerx centery ?angle?"); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[1],&zoom)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],¢erx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],¢ery)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&width)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&height)) return TCL_ERROR; - if(objc==7) { - if(Tcl_GetDoubleFromObj(interp,objv[4],&angle)) return TCL_ERROR; - - } - matA[0]=cos(angle); - matA[1]=sin(angle); - matA[2]=-sin(angle); - matA[3]=cos(angle); - matA[4]=0.0; - matA[5]=0.0; - - - for(i=6;ifullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - return TCL_OK; -} DELETED cmodules/geometry/generic/slicer.c Index: cmodules/geometry/generic/slicer.c ================================================================== --- cmodules/geometry/generic/slicer.c +++ /dev/null @@ -1,1737 +0,0 @@ -/* -** This widget translates 3-D coordinates onto a flat canvas by splitting -** the 3-D space into layers and stacking the layers on the canvas. -** -** The layers are decks of the ship. The highest layer (or deck) is drawn -** at the top of the page. The next layer down is drawn below the top layer. -** and so forth down the canvas. In other words, the 3D object is drawn -** by showing a set of 2D slices where each slice is viewed from above. -** -** The original 3D coordinates are called "actual" coordinates. When -** translated into the 2D canvas they are called "canvas" coordinates. -** -** The actual coordinate system is right-handed. The X axis increases to -** the right. The Y axis increases going up. The Z axis comes out of the -** page at the viewer. The canvas coordinate system is left-handed. The -** X axis increase to the right but the Y axis increases going down. -** -** A slicer is a object with methods. The details of the available -** methods and what each does are described in comments before the -** implementation of each method. -*/ -#include "odieInt.h" -#include -#include -#include -#include -#include - -/* -** This routine is called when a slicer is deleted. All the memory and -** other resources allocated by this slicer is recovered. -*/ -static void destroySlicer(void *pArg){ - Slicer *p = (Slicer*)pArg; - int i; - for(i=0; inSlice; i++){ - Odie_Free((char *)p->a[i].zName); - Odie_Free((char *)p->a[i].xz); - } - Odie_Free((char *)p->a); - Odie_Free((char *)p); -} - -static int Location_FromTclObj(Tcl_Interp *interp, Tcl_Obj *pList,int *did,double *x,double *y) { - int listlen; - Tcl_Obj **elist; - double z; - if(Tcl_ListObjGetElements(interp,pList,&listlen,&elist)) { - return TCL_ERROR; - } - if(listlen < 3 || listlen > 4) { - Tcl_AppendResult(interp, "Could not interpret location ", Tcl_GetString(pList), 0); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, elist[0], did) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, elist[1], x) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, elist[2], y) ) return TCL_ERROR; - return TCL_OK; -} - - -static double xCanvasToActual(Slicer *p,struct OneSlice *pS, double cx){ - double ax; - if(p->nSlice==1) { - ax = cx*p->rZoom; - } else { - ax = cx*p->rZoom - pS->rXShift; - } - return ax; -} - -static double yCanvasToActual(Slicer *p,struct OneSlice *pS, double cy){ - double ay; - if(p->nSlice==1) { - ay=-cy*p->rZoom; - } else { - ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top); - } - return ay; -} - -/* -** Convert a Y coordinate from actual to canvas coordinates for a -** given deck. -*/ -static double xActualToCanvas(Slicer *p,struct OneSlice *pS, double ax){ - double cx; - if(p->nSlice==1) { - cx = ax/p->rZoom; - } else { - cx = (ax+pS->rXShift)/p->rZoom; - } - return cx; -} - -/* -** Convert a Y coordinate from actual to canvas coordinates for a -** given deck. -*/ -static double yActualToCanvas(Slicer *p,struct OneSlice *pS, double ay){ - double cy; - if(p->nSlice==1) { - cy=-ay/p->rZoom; - } else { - cy = pS->top + (pS->btm-pS->top)*(ay-pS->mxY)/(pS->mnY-pS->mxY); - } - return cy; -} - -/* -** Return the height above baseline for the deck location rX. -*/ -static double deckHeight(struct OneSlice *p, double rX){ - int i; - double *xz; - if(!p) { - return 0.0; - } - if( p->nXZ<4 ){ - return p->z; - } - xz = p->xz; - if( rX<=xz[0] ){ - return xz[1]; - } - for(i=2; inXZ; i+=2){ - if( rX<=xz[i] ){ - assert( xz[i]>xz[i-2] ); - return xz[i-1] + (xz[i+1]-xz[i-1])*(rX-xz[i-2])/(xz[i]-xz[i-2]); - } - } - return xz[p->nXZ-1]; -} - -/* -** Return a pointer to the particular deck at actual coordinates -** X, Z -*/ -static struct OneSlice *deckAt(Slicer *p, double rX, double rZ){ - int i; - struct OneSlice *pBest; - double bestHeight; - if( p->nSlice==0 ) return 0; - pBest = &p->a[0]; - bestHeight = deckHeight(pBest, rX); - for(i=1; inSlice; i++){ - double dh = deckHeight(&p->a[i],rX); - if( dh>bestHeight && dh<=rZ ){ - pBest = &p->a[i]; - bestHeight = dh; - } - } - return pBest; -} - - -/* -** Return a pointer to the deck immediately above the given deck. -** Return NULL if the given deck is topmost. -*/ -static struct OneSlice *deckAbove(Slicer *p, struct OneSlice *pRef){ - int i; - struct OneSlice *pBest = 0; - if( p->nSlice==0 ) return 0; - for(i=0; inSlice; i++){ - struct OneSlice *pTest = &p->a[i]; - if( pTest->z<=pRef->z ) continue; - if( pBest==0 || pBest->z>pTest->z ){ - pBest = pTest; - } - } - return pBest; -} -/* -** Return a pointer to the deck immediately above the given deck. -** Return NULL if the given deck is topmost. -*/ -static struct OneSlice *deckBelow(Slicer *p, struct OneSlice *pRef){ - int i; - struct OneSlice *pBest = 0; - if( p->nSlice==0 ) return 0; - for(i=0; inSlice; i++){ - struct OneSlice *pTest = &p->a[i]; - if( pTest->z>=pRef->z ) continue; - if( pBest==0 || pBest->zz ){ - pBest = pTest; - } - } - return pBest; -} - - -/* -** Recompute the values of p->a[].top and p->a[].btm for all slices in -** the given slicer. -*/ -static void computeTopAndBottom(Slicer *p){ - int i; - double rY = 0.0; - double rBound = -9.9e99; - for(i=p->nSlice-1; i>=0; i--){ - double h = (p->a[i].mxY - p->a[i].mnY)/p->rZoom; - p->a[i].upperbound = rBound; - p->a[i].top = rY; - p->a[i].btm = rY + h; - rY = p->a[i].btm + 0.3*h; - rBound = p->a[i].btm + 0.15*h; - } - - if( p->nSlice==0 ) return; - - /* Calculate the above and below for each deck */ - - for(i=0; inSlice; i++){ - struct OneSlice *pThis = &p->a[i]; - struct OneSlice *pBest = 0; - - pBest=deckAbove(p,pThis); - if(pBest) { - pThis->above=pBest->did; - } else { - pThis->above=0; - } - pBest=deckBelow(p,pThis); - if(pBest) { - pThis->below=pBest->did; - } else { - pThis->below=0; - } - } -} - -/* -** pObj is either the name of a deck or a Z coordinate. If it is a -** deck name, find the deck and write a pointer to it in *ppS. If -** it is a Z coordinate, use that coordinate together with rX to -** find the deck and write it into *ppS. If an error occurs, put -** an error message on the TCL interpreter and return TCL_ERROR. -** Return TCL_OK on success. -*/ -static int getDeck( - Tcl_Interp *interp, /* Put error messages here */ - Slicer *p, /* The slicer */ - double rX, /* X coord used to find deck if pObj is a Z coord */ - Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */ - struct OneSlice **ppS /* Write the slice pointer here */ -){ - double rZ; - const char *zName; - int i; - if(p->nSlice==1) { - *ppS=&p->a[0]; - return TCL_OK; - } - if( Tcl_GetDoubleFromObj(0, pObj, &rZ)==TCL_OK ){ - *ppS = deckAt(p, rX, rZ); - return TCL_OK; - } - zName = Tcl_GetStringFromObj(pObj, 0); - for(i=0; inSlice; i++){ - if( strcmp(zName, p->a[i].zName)==0 ){ - *ppS = &p->a[i]; - return TCL_OK; - } - } - Tcl_AppendResult(interp, "no such deck: ", zName, 0); - return TCL_ERROR; -} - - -/* -** pObj is either the name of a deck or a Z coordinate. If it is a -** deck name, find the deck and write a pointer to it in *ppS. If -** it is a Z coordinate, use that coordinate together with rX to -** find the deck and write it into *ppS. If an error occurs, put -** an error message on the TCL interpreter and return TCL_ERROR. -** Return TCL_OK on success. -*/ -static int getDeckId( - Tcl_Interp *interp, /* Put error messages here */ - Slicer *p, /* The slicer */ - Tcl_Obj *pObj, /* Either a deck name or a Z coordinate */ - struct OneSlice **ppS /* Write the slice pointer here */ -){ - int did; - const char *zName; - int i; - if(p->nSlice==1) { - *ppS=&p->a[0]; - return TCL_OK; - } - if( Tcl_GetIntFromObj(interp, pObj, &did)==TCL_OK ){ - for(i=0; inSlice; i++){ - if( did == p->a[i].did ){ - *ppS = &p->a[i]; - return TCL_OK; - } - } - Tcl_AppendResult(interp, "no such deckid: ", 0); - return TCL_ERROR; - } - zName = Tcl_GetStringFromObj(pObj, 0); - for(i=0; inSlice; i++){ - if( strcmp(zName, p->a[i].zName)==0 ){ - *ppS = &p->a[i]; - return TCL_OK; - } - } - Tcl_AppendResult(interp, "no such deck: ", zName, 0); - return TCL_ERROR; -} - -static inline struct OneSlice *getDeck_FromInt( - Slicer *p, - int did -) { - int i; - if(p->nSlice==1) { - return &p->a[0]; - } - for(i=0; inSlice; i++){ - if( did == p->a[i].did ){ - return &p->a[i]; - } - } - return NULL; -} - -/* -** Methods -*/ - -static int slicer_drawline_do( - Tcl_Interp *interp, - Slicer *p, - Tcl_Obj *canvas, - Tcl_Obj *tagname, - Tcl_Obj *tagname_transdeck, - Tcl_Obj *tagname_penetration, - int coord_count, - int *deckCoord,double *xCoord,double *yCoord, - struct OneSlice **apDeck -) { - int i; - - Tcl_Obj *pVTag; /* The "sNNN" tag added to all line segments */ - const char *zXTag; /* Trans-deck tag (dashed lines) */ - const char *zPTag; /* Deck-penetraction tag */ - Tcl_Obj *aLineArg[20]; /* Element of "create line" TCL command */ - int nLineArg; /* Number of used entries in aLineArg[] */ - Tcl_Obj *aPenArg[20]; /* Cmd to draw deck penetractions */ - int nPenArg; - zXTag = Tcl_GetStringFromObj(tagname_transdeck, 0); - zPTag = Tcl_GetStringFromObj(tagname_penetration, 0); - - aLineArg[0] = canvas; - aLineArg[1] = ODIE_CONSTANT_STRING("create"); - aLineArg[2] = ODIE_CONSTANT_STRING("line"); - for(i=3; i<=6; i++){ - aLineArg[i] = Tcl_NewObj(); - } - aLineArg[7] = ODIE_CONSTANT_STRING("-tags"); - for(i=0; i<=7; i++){ - Tcl_IncrRefCount(aLineArg[i]); - } - nLineArg = 9; - - if( zPTag[0]==0 ){ - nPenArg = 0; - }else{ - aPenArg[0] = canvas; - aPenArg[1] = ODIE_CONSTANT_STRING("create"); - aPenArg[2] = ODIE_CONSTANT_STRING("oval"); - for(i=3; i<=6; i++){ - aPenArg[i] = Tcl_NewObj(); - } - aPenArg[7] = ODIE_CONSTANT_STRING("-tags"); - for(i=0; i<=7; i++){ - Tcl_IncrRefCount(aPenArg[i]); - } - nPenArg = 9; - } - - for(i=1; i(n-4) ) { - if(Location_FromTclObj(interp,deckObj,&deckCoord[j],&xCoord[j],&yCoord[j])) { - goto badRoute; - } - } else { - if(i++ >= n) goto badRoute; - Tcl_ListObjIndex(0, objv[2], i, &xObj); - if(i++ >= n) goto badRoute; - Tcl_ListObjIndex(0, objv[2], i, &yObj); - i++; - if( Tcl_GetDoubleFromObj(interp, xObj, &xCoord[j]) ) goto badRoute; - if( Tcl_GetDoubleFromObj(interp, yObj, &yCoord[j]) ) goto badRoute; - } - if(deckCoord[j]==deckCoord[j-1]) { - apDeck[j]=apDeck[j-1]; - } else { - apDeck[j]=getDeck_FromInt(p,deckCoord[j]); if(!apDeck[j]) goto badRoute; - } - j++; - } - slicer_drawline_do(interp,p,objv[1],objv[3],objv[4],objv[5],j,deckCoord,xCoord,yCoord,apDeck); - Odie_Free((char *)xCoord); - Odie_Free((char *)yCoord); - Odie_Free((char *)deckCoord); - Odie_Free((char *)apDeck); - return TCL_OK; - -badRoute: - Odie_Free((char *)xCoord); - Odie_Free((char *)yCoord); - Odie_Free((char *)deckCoord); - Odie_Free((char *)apDeck); - return TCL_ERROR; -} - - -/* -** tclmethod: SLICER drawline_dxyz START PATH END -** title: Return TK to draw a line on a canvas -*/ -static int slicer_method_link_coords( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Slicer *p = (Slicer*)pArg; - - int i, j=0, totalN, n, mode; - double *xCoord,*yCoord; /* Actual coordinates of line to draw */ - int *deckCoord; - struct OneSlice **apDeck; /* Array of all decks */ - - if( objc!=8 ){ - Tcl_WrongNumArgs(interp, 1, objv, - "START PATH END"); - return TCL_ERROR; - } - if( Tcl_ListObjLength(interp, objv[3], &n) ) return TCL_ERROR; - - totalN=n+2; - xCoord = (double *)Odie_Alloc(sizeof(xCoord[0])*totalN); - yCoord = (double *)Odie_Alloc(sizeof(yCoord[0])*totalN); - deckCoord = (int *)Odie_Alloc(sizeof(deckCoord[0])*(totalN)); - apDeck = (struct OneSlice **)Odie_Alloc(sizeof(apDeck[0])*(totalN)); - - if( xCoord==0 || yCoord == 0 || deckCoord == 0 || apDeck == 0 ) { - return TCL_ERROR; - } - - j=0; - if(Location_FromTclObj(interp,objv[2],&deckCoord[j],&xCoord[j],&yCoord[j])) { - goto badRoute; - } - apDeck[j]=getDeck_FromInt(p,deckCoord[j]); if(!apDeck[j]) goto badRoute; - - j++; - - for(i=0; i(n-4) ) { - if(Location_FromTclObj(interp,deckObj,&deckCoord[j],&xCoord[j],&yCoord[j])) { - goto badRoute; - } - } else { - Tcl_ListObjIndex(0, objv[3], i+1, &xObj); - Tcl_ListObjIndex(0, objv[3], i+2, &yObj); - if( Tcl_GetDoubleFromObj(interp, xObj, &xCoord[j]) ) goto badRoute; - if( Tcl_GetDoubleFromObj(interp, yObj, &yCoord[j]) ) goto badRoute; - i+=3; - } - if(deckCoord[j]==deckCoord[j-1]) { - apDeck[j]=apDeck[j-1]; - } else { - apDeck[j]=getDeck_FromInt(p,deckCoord[j]); if(!apDeck[j]) goto badRoute; - } - j++; - } - - if(Location_FromTclObj(interp,objv[4],&deckCoord[j],&xCoord[j],&yCoord[j])) { - goto badRoute; - } - apDeck[j]=getDeck_FromInt(p,deckCoord[j]); if(!apDeck[j]) goto badRoute; - j++; - slicer_drawline_do(interp,p,objv[1],objv[5],objv[6],objv[7],j,deckCoord,xCoord,yCoord,apDeck); - Odie_Free((char *)xCoord); - Odie_Free((char *)yCoord); - Odie_Free((char *)deckCoord); - Odie_Free((char *)apDeck); - return TCL_OK; - -badRoute: - Odie_Free((char *)xCoord); - Odie_Free((char *)yCoord); - Odie_Free((char *)deckCoord); - Odie_Free((char *)apDeck); - return TCL_ERROR; -} - -static inline double Location_zabs(Slicer *p,struct OneSlice *pS,double x0,double dheight) { - if(dheight >= 0) { - return dheight+deckHeight(pS,x0); - } - struct OneSlice *pAbove; - pAbove=deckAbove(p,pS); - if(pAbove) { - return deckHeight(pAbove,x0)+dheight; - } - return deckHeight(pS,x0)+p->upper_height+dheight; -} - -static inline double Location_zdeck(Slicer *p,struct OneSlice *pS,double x0,double dheight) { - if(dheight >= 0) { - return dheight; - } - struct OneSlice *pAbove; - pAbove=deckAbove(p,pS); - if(pAbove) { - return deckHeight(pAbove,x0)-deckHeight(pS,x0)+dheight; - } - return p->upper_height+dheight; -} - -/* -** This routine runs when a method is executed against a slicer -*/ -static int slicerMethodProc( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Slicer *p = (Slicer*)pArg; - -#if 0 - /* For debugging.... - ** Print each wallset command before it is executed. - */ - { int i; - for(i=0; iabove)); - } else { - Tcl_Obj *pResult=Tcl_NewObj(); - - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(pDeck->above)); - Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[3])); - Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[4])); - if(objc==6) { - Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[5])); - } - Tcl_SetObjResult(interp, pResult); - } - return TCL_OK; - } - - /* tclmethod: SLICER below NAME - ** title: Return the deck below NAME - */ - case SLICER_BELOW: { - struct OneSlice *pDeck; - if( objc!=3 && objc!=5 && objc!=6){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME ?x y? ?zoff?"); - return TCL_ERROR; - } - if( getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR; - if(objc==3) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(pDeck->below)); - } else { - Tcl_Obj *pResult=Tcl_NewObj(); - - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(pDeck->below)); - Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[3])); - Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[4])); - if(objc==6) { - Tcl_ListObjAppendElement(interp, pResult, Tcl_DuplicateObj(objv[5])); - } - Tcl_SetObjResult(interp, pResult); - } - return TCL_OK; - } - case SLICER_DECKID_TO_NAME: { - struct OneSlice *pDeck; - if( objc!=3 ) { - Tcl_WrongNumArgs(interp, 2, objv, "ID"); - return TCL_ERROR; - } - if( getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR; - Tcl_SetObjResult(interp, ODIE_CONSTANT_STRING(pDeck->zName)); - return TCL_OK; - } - case SLICER_DECKNAME_TO_ID: { - struct OneSlice *pDeck; - if( objc!=3 ) { - Tcl_WrongNumArgs(interp, 2, objv, "NAME"); - return TCL_ERROR; - } - if( getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(pDeck->did)); - return TCL_OK; - } - - /* - ** tclmethod: SLICER xyz_to_location X Y Z - ** title: Convert from X Y Z to IRM Coordinates - ** - ** The ABOVE-DECK parameter, if present, is the height above the deck. - */ - case SLICER_XYZ_TO_LOCATION: { - double x0, y0, z0, dheight; - Tcl_Obj *pResult; - struct OneSlice *pS; - int i; - if(objc==2) { - Tcl_SetObjResult(interp, Tcl_NewObj()); - return TCL_OK; - } - if( objc < 5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y Z ?x y z?"); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - pResult = Tcl_NewObj(); - - for(i=2;idid)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x0)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y0)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(dheight)); - } - - Tcl_SetObjResult(interp, pResult); - break; - } - case SLICER_LOCATION_TO_XYZ: { - int i; - double x0, y0, z0, dheight; - Tcl_Obj *pResult; - struct OneSlice *pS,*pAbove; - if(objc==2) { - Tcl_SetObjResult(interp, Tcl_NewObj()); - return TCL_OK; - } - if( objc!= 5 && objc < 6 ){ - Tcl_WrongNumArgs(interp, 2, objv, "DECK X Y ?ZOFF? ..."); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if(objc<7) { - if( getDeckId(interp,p,objv[2],&pS) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &y0) ) return TCL_ERROR; - if(objc==6) { - if( Tcl_GetDoubleFromObj(NULL, objv[5], &dheight) ) { - dheight=0.0; - } - } else { - dheight=0.0; - } - pResult = Tcl_NewObj(); - z0=Location_zabs(p,pS,x0,dheight); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x0)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y0)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(z0)); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; - } - pResult = Tcl_NewObj(); - for(i=2;inSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if( getDeckId(interp,p,objv[2],&pS) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &y0) ) return TCL_ERROR; - if(objc==6) { - if( Tcl_GetDoubleFromObj(NULL, objv[5], &dheight) ) { - dheight=0.0; - } - } else { - dheight=0.0; - } - z0=Location_zabs(p,pS,x0,dheight); - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(z0)); - return TCL_OK; - } - /* - ** tclmethod: SLICER actualcoords CANVAS-COORD-LIST ?ABOVE-DECK? - ** title: Convert from canvas to actual coordinate space - ** - ** The ABOVE-DECK parameter, if present, is the height above the deck. - */ - case SLICER_ACTUALCOORDS: { - int i, n; - double aboveDeck; - Tcl_Obj *pResult; - if( objc!=3 && objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "CANVAS-COORD-LIST ?ABOVE-DECK?"); - return TCL_ERROR; - } - if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR; - if( n%2!=0 ){ - Tcl_AppendResult(interp, "coordinate list must contain a multiple " - "of 2 values", 0); - return TCL_ERROR; - } - if( objc==4 ){ - if( Tcl_GetDoubleFromObj(interp, objv[3], &aboveDeck) ) return TCL_ERROR; - }else{ - aboveDeck = 0.0; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - pResult = Tcl_NewObj(); - for(i=0; inSlice-1 && p->a[j].upperbound>cy; j++){} - pS = &p->a[j]; - - /* Original Formula - ** ax = cx*p->rZoom - pS->rXShift; - ** ay = pS->mxY + (pS->mnY-pS->mxY)*(cy-pS->top)/(pS->btm-pS->top); - */ - ax=xCanvasToActual(p,pS,cx); - ay=yCanvasToActual(p,pS,cy); - - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pS->did)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(round(ax))); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(round(ay))); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(round(aboveDeck))); - } - if( inSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if(objc != 5) { - pResult = Tcl_NewObj(); - } - - for(i=0; irXShift)/p->rZoom; - ** cy = pS->top + (pS->btm-pS->top)*(ay-pS->mxY)/(pS->mnY-pS->mxY); - */ - cx = xActualToCanvas(p,pS,ax); - cy = yActualToCanvas(p,pS,ay); - - if(objc==5) { - Tcl_ObjSetVar2(interp,objv[3],NULL,Tcl_NewDoubleObj(cx),0); - Tcl_ObjSetVar2(interp,objv[4],NULL,Tcl_NewDoubleObj(cy),0); - return TCL_OK; - } else { - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cx)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(cy)); - } - } - if(error) { - if(pResult) { - Tcl_DecrRefCount(pResult); - } - return TCL_ERROR; - } - if( i=mxY ){ - Tcl_AppendResult(interp, "MIN-Y must be less than MAX-Y", 0); - return TCL_ERROR; - } - zName = Odie_Alloc( nName+1 ); - if( zName==0 ) return TCL_ERROR; - memcpy(zName, zNameOrig, nName+1); - for(i=0; inSlice; i++){ - if( p->a[i].did==did ){ - Tcl_AppendResult(interp, "Deckid for slice ", zName, " is the " - "same as existing slice ", p->a[i].zName, 0); - return TCL_ERROR; - } - if( p->a[i].z==z ){ - Tcl_AppendResult(interp, "Z coordinate for slice ", zName, " is the " - "same as existing slice ", p->a[i].zName, 0); - return TCL_ERROR; - } - } - p->nSlice++; - p->a = Odie_Realloc((char *)p->a, sizeof(p->a[0])*p->nSlice); - if( p->a==0 ){ - p->nSlice = 0; - return TCL_ERROR; - } - for(i=p->nSlice-1; i>0 && p->a[i-1].z>z; i--){ - p->a[i] = p->a[i-1]; - p->a[i].idx = i; - } - p->a[i].did = did; - p->a[i].idx = i; - p->a[i].zName = zName; - p->a[i].nXZ = 0; - p->a[i].xz = 0; - p->a[i].z = z; - p->a[i].mnY = mnY; - p->a[i].mxY = mxY; - p->a[i].rXShift = p->rXOffset*z; - computeTopAndBottom(p); - break; - } - - /* tclmethod: SLICER deck X Y Z - ** title: Return the name of the deck at actual coordinates X,Y,Z - ** - ** See also: find - */ - case SLICER_DECK: { - double x0, y0, z0; - Tcl_Obj *pResult; - struct OneSlice *pS; - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y Z"); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &z0) ) return TCL_ERROR; - pResult = Tcl_NewObj(); - pS = deckAt(p, x0, z0); - pResult = ODIE_CONSTANT_STRING(pS->zName); - Tcl_SetObjResult(interp, pResult); - break; - } - - - /* tclmethod: SLICER did X Y Z - ** title: Return the id of the deck at actual coordinates X,Y,Z - ** - ** See also: find - */ - case SLICER_DECKID: - case SLICER_DID: { - double x0, y0, z0; - Tcl_Obj *pResult; - struct OneSlice *pS; - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y Z"); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &z0) ) return TCL_ERROR; - pResult = Tcl_NewObj(); - pS = deckAt(p, x0, z0); - pResult = Tcl_NewIntObj(pS->did); - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: SLICER delete NAME - ** title: Remove a slice from the slicer - */ - case SLICER_DELETE: { - int i, j; - const char *zName; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME"); - return TCL_ERROR; - } - zName = Tcl_GetStringFromObj(objv[2], 0); - for(i=0; inSlice && strcmp(p->a[i].zName,zName)!=0; i++){} - if( inSlice ){ - Odie_Free((char *)p->a[i].zName); - p->nSlice--; - for(j=i; jnSlice; j++){ - p->a[j] = p->a[j+1]; - } - computeTopAndBottom(p); - } - break; - } - - /* - ** tclmethod: SLICER destroy - ** title: Destroy this slicer - */ - case SLICER_DESTROY: { - Tcl_DeleteCommand(interp,Tcl_GetString(objv[0])); - break; - } - - case SLICER_DRAWLINE: { - int result; - result=slicer_method_drawline(pArg,interp,objc-1,objv+1); - return result; - } - - /* - ** tclmethod: SLICER objinfo obj - ** title: Return TK to draw a line on a canvas - */ - case SLICER_OBJINFO: { - Tcl_Obj *tmp; - tmp = objv[2]; - printf("INFO: %s Ref: %d Type: %p \n", Tcl_GetStringFromObj(tmp, NULL), - tmp->refCount, tmp->typePtr); - fflush (stdout); - break; - } - /* - ** tclmethod: SLICER makedlist CANVAS ACTUAL-PATH TAG TRANSDECK-TAG P-TAG ?COLOR? - ** title: Return TK to draw a line on a canvas - */ - case SLICER_MAKEDLIST: { - int i, n; - double *aCoord; /* Actual coordinates of line to draw */ - struct OneSlice **apDeck; /* Array of all decks */ - Tcl_Obj *pVTag; /* The "sNNN" tag added to all line segments */ - const char *zXTag; /* Trans-deck tag (dashed lines) */ - Tcl_Obj *rtnList ; /* List object to return */ - Tcl_Obj *coordList ; /* List of coords to return */ - Tcl_Obj *configList ; /* configuration string to return */ - Tcl_Obj *tmpObj; /* Cheater for filling lists */ - - if( objc!=5 && objc!=6 ){ - Tcl_WrongNumArgs(interp, 2, objv, - "ACTUAL-PATH TAG TRANSDECK-TAG ?COLOR?"); - return TCL_ERROR; - } -// slicer makedlist Path TagList Transdeck-TagList ?COLOR? -// 0 1 2 3 4 5 - - zXTag = Tcl_GetStringFromObj(objv[4], 0); - - if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR; - - if( n%3!=0 || n<6 ){ - Tcl_AppendResult(interp, "coordinate list must contain a multiple " - "of 3 values with a minimum of 6", 0); - return TCL_ERROR; - } - - rtnList = Tcl_NewListObj(0, NULL); - - aCoord = (double *)Odie_Alloc( sizeof(aCoord[0])*n + sizeof(apDeck[0])*(n/3) ); - if( aCoord==0 ){ - return TCL_ERROR; - } - - // Move coords from Tcl objv[3] int "C" aCoord array - - apDeck = (struct OneSlice **)&aCoord[n]; - for(i=0; irXShift)/p->rZoom; - ** x1 = (aCoord[i*3]+apDeck[i]->rXShift)/p->rZoom; - */ - x0 = xActualToCanvas(p,apDeck[i-1],aCoord[i*3-3]); - x1 = xActualToCanvas(p,apDeck[i],aCoord[i*3]); - y0 = yActualToCanvas(p,apDeck[i-1], Y0=aCoord[i*3-2]); - y1 = yActualToCanvas(p,apDeck[i], Y1=aCoord[i*3+1]); - z0 = aCoord[i*3-1]; - z1 = aCoord[i*3+2]; - if( zXTag[0]!=0 ){ - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x0)); - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y0)); - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x1)); - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y1)); - - Tcl_ListObjAppendElement(interp, configList, - ODIE_CONSTANT_STRING("-tags")); - - tmpObj = Tcl_DuplicateObj(objv[4]); - Tcl_ListObjAppendElement(interp, tmpObj, pVTag); - Tcl_ListObjAppendElement(interp, configList, tmpObj); - - } - } else { - /* Old direct formula - ** - ** x0 = (aCoord[i*3-3]+apDeck[i]->rXShift)/p->rZoom; - ** x1 = (aCoord[i*3]+apDeck[i]->rXShift)/p->rZoom; - */ - x0 = xActualToCanvas(p,apDeck[i],aCoord[i*3-3]); - x1 = xActualToCanvas(p,apDeck[i],aCoord[i*3]); - - y0 = yActualToCanvas(p,apDeck[i], aCoord[i*3-2]); - y1 = yActualToCanvas(p,apDeck[i], aCoord[i*3+1]); - - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x0)); - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y0)); - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(x1)); - Tcl_ListObjAppendElement(interp, coordList,Tcl_NewDoubleObj(y1)); - - - Tcl_ListObjAppendElement(interp, configList,\ - ODIE_CONSTANT_STRING("-tags")); - - tmpObj = Tcl_DuplicateObj(objv[3]); - Tcl_ListObjAppendElement(interp, tmpObj, pVTag); - - Tcl_ListObjAppendElement(interp, configList, tmpObj); - - } - if( objc>=6 ) { - Tcl_ListObjAppendElement(interp, configList,\ - ODIE_CONSTANT_STRING("-fill")); - Tcl_ListObjAppendElement(interp, configList,\ - Tcl_DuplicateObj(objv[5])); - } - - - Tcl_ListObjAppendElement(interp, rtnList, coordList); - Tcl_ListObjAppendElement(interp, rtnList, configList); - } - Odie_Free((char *)aCoord); - - Tcl_SetObjResult(interp, rtnList); - - break; - } - - /* tclmethod: SLICER find X Y - ** title: Return the name of the deck at canvas coordinates X,Y - ** - ** The "deck" command works similarly except that it uses actual - ** coordinates as inputs. - */ - case SLICER_FIND: { - int i; - double x0, y0; - Tcl_Obj *pResult; - struct OneSlice *pS; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y"); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - pResult = Tcl_NewObj(); - for(i=0; inSlice-1 && p->a[i].upperbound>y0; i++){} - pS = &p->a[i]; - pResult = ODIE_CONSTANT_STRING(pS->zName); - Tcl_SetObjResult(interp, pResult); - break; - } - - /* tclmethod: SLICER finddid X Y - ** title: Return the name of the deck at canvas coordinates X,Y - ** - ** The "deck" command works similarly except that it uses actual - ** coordinates as inputs. - */ - case SLICER_FINDDID: { - int i; - double x0, y0; - Tcl_Obj *pResult; - struct OneSlice *pS; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y"); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - pResult = Tcl_NewObj(); - for(i=0; inSlice-1 && p->a[i].upperbound>y0; i++){} - pS = &p->a[i]; - pResult = Tcl_NewIntObj(pS->did); - Tcl_SetObjResult(interp, pResult); - break; - } - - /* tclmethod: SLICER height NAME X - ** title: Return the height of slice NAME at actual position X - ** Assuming the deck were flat - ** - ** See also "headroom". - */ - case SLICER_FLATHEIGHT: { - struct OneSlice *ppS; - double x0; - - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME X"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - if( getDeckId(interp,p,objv[2],&ppS) ) return TCL_ERROR; - - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(ppS->z)); - break; - } - - /* tclmethod: SLICER headroom NAME X - ** title: Return the headroom (Z from deck) of slice NAME at actual position X - ** - ** See also "height" - */ - case SLICER_HEADROOM: { - double x0; - struct OneSlice *pDeck, *pAbove; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME X"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - - if( getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR; - pAbove = deckAbove(p, pDeck); - if( pAbove ){ - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(deckHeight(pAbove,x0)-deckHeight(pDeck,x0))); - }else{ - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(p->upper_height)); - } - break; - } - - /* tclmethod: SLICER ceiling NAME X ?DEFAULT? - ** title: Return the Z (absolute) of the ceiling of slice NAME at actual position X - ** - ** See also "height" - */ - case SLICER_CEILING: { - double x0; - struct OneSlice *pDeck, *pAbove; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME X"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - - if( getDeckId(interp,p,objv[2],&pDeck) ) return TCL_ERROR; - pAbove = deckAbove(p, pDeck); - if( pAbove ){ - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(deckHeight(pAbove,x0))); - }else{ - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(deckHeight(pDeck,x0)+p->upper_height)); - } - break; - } - - /* tclmethod: SLICER height NAME X ?zoff? - ** title: Return the height (absolute) of slice NAME at actual position X - ** description: - ** NOTE if the top deck is asked for, and zoff is negative the - ** system will assume a 2000mm ceiling - ** See also "headroom". - */ - case SLICER_HEIGHT: { - struct OneSlice *ppS,*pAbove; - double x0,zoff=0,zresult=0.0; - if( objc!=4 && objc!=5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME X ?ZOFF?"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - if( getDeckId(interp,p,objv[2],&ppS) ) return TCL_ERROR; - if( objc==5 ) { - if( Tcl_GetDoubleFromObj(NULL, objv[4], &zoff) ) { - zoff=0.0; - } - } - if(zoff < 0.0) { - pAbove = deckAbove(p, ppS); - if(pAbove) { - zresult=deckHeight(pAbove,x0)+zoff; - } else { - zresult=deckHeight(ppS,x0)+2000+zoff; - } - } else { - zresult=deckHeight(ppS,x0)+zoff; - } - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(zresult)); - break; - } - - /* tclmethod: SLICER deckheight NAME X ?zoff? - ** title: Return the height (mm from floor) of slice NAME at actual position X - ** description: - ** NOTE if the top deck is asked for, and zoff is negative the - ** system will assume a 2000mm ceiling - ** See also "headroom". - */ - case SLICER_DECKHEIGHT: { - int i; - double x0, z0, dheight; - Tcl_Obj *pResult; - struct OneSlice *pS,*pAbove; - if( objc!= 4 && objc!=5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "DECK X ?ZOFF?"); - return TCL_ERROR; - } - if( p->nSlice<=0 ){ - Tcl_AppendResult(interp, "no slices defined", 0); - return TCL_ERROR; - } - if( getDeckId(interp,p,objv[2],&pS) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &x0) ) return TCL_ERROR; - if(objc==5) { - if( Tcl_GetDoubleFromObj(NULL, objv[4], &dheight) ) { - dheight=0.0; - } - } else { - dheight=0.0; - } - z0=Location_zdeck(p,pS,x0,dheight); - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(z0)); - return TCL_OK; - } - - /* - ** tclmethod: SLICER info NAME - ** title: Return information about a particular slice - */ - case SLICER_INFO: { - struct OneSlice *ppS; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME"); - return TCL_ERROR; - } - if( getDeckId(interp,p,objv[2],&ppS) ) { - return TCL_ERROR; - } else { - Tcl_Obj *pResult = Tcl_NewObj(); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("name")); - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING(ppS->zName)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("did")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewIntObj(ppS->did)); - - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("z")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->z)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("miny")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->mnY)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("maxy")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->mxY)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("top")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->top)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("bottom")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->btm)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("above")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->above)); - - Tcl_ListObjAppendElement(interp, pResult, ODIE_CONSTANT_STRING("below")); - Tcl_ListObjAppendElement(interp, pResult, Tcl_NewDoubleObj(ppS->below)); - - Tcl_SetObjResult(interp, pResult); - } - break; - } - - /* - ** tclmethod: SLICER list - ** title: List the names of all defined slices in the slicer - */ - case SLICER_LIST: { - Tcl_Obj *pResult = Tcl_NewObj(); - int i; - for(i=0; inSlice; i++){ - Tcl_ListObjAppendElement(0, pResult, ODIE_CONSTANT_STRING(p->a[i].zName)); - } - Tcl_SetObjResult(interp, pResult); - break; - } - - - /* - ** tclmethod: SLICER profile DECK ?X Z ...? - ** title: Create an inboard profile for a deck - */ - case SLICER_PROFILE: { - int i, j, min; - struct OneSlice *pS; - if( objc<3 || (objc>3 && objc<7) || (objc & 1)==0 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME ?X Z X Z...?"); - return TCL_ERROR; - } - - if(getDeckId(interp,p,objv[2],&pS)) { - return TCL_ERROR; - } - if( objc==3 ){ - Tcl_Obj *pResult = Tcl_NewObj(); - for(i=0; inXZ; i++){ - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pS->xz[i])); - } - Tcl_SetObjResult(interp, pResult); - }else{ - double *xz; - if( pS->xz ) Odie_Free((char *)pS->xz); - pS->nXZ = objc - 3; - xz = pS->xz = (double *)Odie_Alloc( sizeof(pS->xz[0])*pS->nXZ ); - if( xz==0 ){ - pS->nXZ = 0; - break; - } - for(i=0; inXZ; i++){ - if( Tcl_GetDoubleFromObj(interp, objv[i+3], &xz[i]) ){ - Odie_Free((char *)xz); - pS->nXZ = 0; - pS->xz = 0; - return TCL_ERROR; - } - } - - /* Put the profile in increasing X order. An N**2 sort is used because - ** it is convenient and the list will usually be short. */ - for(i=0; inXZ-2; i+=2){ - for(min=i, j=i+2; jnXZ; j+=2){ - if( xz[j]i ){ - double t = xz[min]; - xz[min] = xz[i]; - xz[i] = t; - t = xz[min+1]; - xz[min+1] = xz[i+1]; - xz[i+1] = t; - } - } - - /* Remove duplidate X coordinates */ - for(i=j=0; inXZ; i+=2){ - if( inXZ-2 && xz[i+2]==xz[i] ){ - /* Ignore the duplicate */ - }else{ - xz[j++] = xz[i]; - xz[j++] = xz[i+1]; - } - } - pS->nXZ = j; - if( j<4 ){ - pS->nXZ = 0; - Odie_Free((char *)pS->xz); - pS->xz = 0; - } - } - break; - } - - /* - ** tclmethod: SLICER xoffset ?AMT? - ** title: Change the X-Offset as a function of deck height - */ - case SLICER_XOFFSET: { - double rXOffset; - int i; - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?"); - return TCL_ERROR; - } - if( objc==2 ){ - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rXOffset)); - return TCL_OK; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &rXOffset) ) return TCL_ERROR; - for(i=0; inSlice; i++){ - p->a[i].rXShift = rXOffset*p->a[i].z; - } - p->rXOffset = rXOffset; - break; - } - - /* - ** tclmethod: SLICER zoom ?ZOOM? - ** title: Query or change the zoom factor. - */ - case SLICER_ZOOM: { - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?"); - return TCL_ERROR; - } - if( objc==3 ){ - double r; - if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR; - p->rZoom = r; - } - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->rZoom)); - computeTopAndBottom(p); - break; - } - - /* - ** tclmethod: SLICER upper_height MM - ** title: Set the headroom on the top level of the slicer (defaults to 2000) - */ - case SLICER_UPPER_HEIGHT: { - if( objc != 2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "Z"); - return TCL_ERROR; - } - if( objc==3 ){ - double r; - if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR; - p->upper_height=r; - } - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(p->upper_height)); - break; - } - - /* End of the command methods. The brackets that follow terminate the - ** automatically generated switch. - ****************************************************************************/ - } - } - return TCL_OK; -} - -/* -** tclcmd: slicer SLICER -** title: creates a slicer object -** This routine runs when the "slicer" command is invoked to create a -** new slicer. -*/ -int Odie_SlicerCreateProc( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char *zCmd; - Slicer *p; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "SLICER"); - return TCL_ERROR; - } - zCmd = Tcl_GetStringFromObj(objv[1], 0); - p = (Slicer *)Odie_Alloc( sizeof(*p) ); - p->rZoom = 100; - p->upper_height=2000; - Tcl_CreateObjCommand(interp, zCmd, slicerMethodProc, p, destroySlicer); - return TCL_OK; -} DELETED cmodules/geometry/generic/slicer_cases.h Index: cmodules/geometry/generic/slicer_cases.h ================================================================== --- cmodules/geometry/generic/slicer_cases.h +++ /dev/null @@ -1,36 +0,0 @@ -/*** Automatically Generated Header File - Do Not Edit ***/ - const static char *SLICER_strs[] = { - "above", "actualcoords", "below", - "canvascoords", "ceiling", "create", - "deck", "deckheight", "deckid", - "deckid_to_name", "deckname_to_id", "delete", - "destroy", "did", "drawline", - "find", "finddid", "flatheight", - "headroom", "height", "info", - "list", "location_to_xyz", "location_z", - "makedlist", "objinfo", "profile", - "upper_height", "xoffset", "xyz_to_location", - "zoom", 0 - }; - enum SLICER_enum { - SLICER_ABOVE, SLICER_ACTUALCOORDS, SLICER_BELOW, - SLICER_CANVASCOORDS, SLICER_CEILING, SLICER_CREATE, - SLICER_DECK, SLICER_DECKHEIGHT, SLICER_DECKID, - SLICER_DECKID_TO_NAME, SLICER_DECKNAME_TO_ID,SLICER_DELETE, - SLICER_DESTROY, SLICER_DID, SLICER_DRAWLINE, - SLICER_FIND, SLICER_FINDDID, SLICER_FLATHEIGHT, - SLICER_HEADROOM, SLICER_HEIGHT, SLICER_INFO, - SLICER_LIST, SLICER_LOCATION_TO_XYZ,SLICER_LOCATION_Z, - SLICER_MAKEDLIST, SLICER_OBJINFO, SLICER_PROFILE, - SLICER_UPPER_HEIGHT, SLICER_XOFFSET, SLICER_XYZ_TO_LOCATION, - SLICER_ZOOM, - }; - int index; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "METHOD ?ARG ...?"); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObj(interp, objv[1], SLICER_strs, "option", 0, &index)){ - return TCL_ERROR; - } - switch( (enum SLICER_enum)index ) DELETED cmodules/geometry/generic/wallset.c Index: cmodules/geometry/generic/wallset.c ================================================================== --- cmodules/geometry/generic/wallset.c +++ /dev/null @@ -1,1577 +0,0 @@ -/* -** This file implements a TCL object that keeps track of the walls and -** bulkheads on a single deck of a ship. -** -** This widget assumes a right-handed coordinate system if zoom is positive -** and a left-handed coordinate system is zoom is negative. The Tk canvas -** widget uses a left-handed coordinate system all the time. The READI -** database uses a right-handed coordinate system all the time. This module -** can be used to translate by setting zoom to +1.0 for database I/O and -** to -$g(zoom) for canvas I/O. -** -** This module uses a purely 2-D model. It can only handle a single -** deck at a time. If a multi-deck model needs to be displayed then -** that multi-deck model should first be flattened into a stack of -** individual decks in the same plane using the separate "slicer" object. -** -** This file implements a single new constructor tcl command named "wallset". -** The wallset command creates a new wallset object. Methods on this -** wallset object are used to manage the object. -** -** The details of the various methods and what they do are provided in -** header comments above the implementation of each method. -*/ -const char wallset_c_version[] = "$Header: /readi/code/tobe/wallset.c,v 1.34 2007/02/22 15:04:04 drh Exp $"; -#include "odieInt.h" -#include -#include -#include -#include -#include - -#ifndef M_PI -# define M_PI 3.1415926535898 -#endif - -/* -** Remove all of the ComptBox entries from the wallset. -*/ -static void clearComptBoxCache(Wallset *pWS){ - ComptBox *p = pWS->pComptBox; - while( p ){ - ComptBox *pNext = p->pNext; - Odie_Free((char *)p); - p = pNext; - } - pWS->pComptBox = 0; -} - -/* -** This routine is invoked when the TCL command that implements a -** wallset is deleted. Free all memory associated with that -** wallset. -*/ -static void destroyWallset(void *pArg){ - Wallset *p = (Wallset*)pArg; - Link *pLink = p->pAll; - clearComptBoxCache(p); - while( pLink ){ - Segment *pSeg = pLink->pLinkNode; - pLink = pSeg->pAll.pNext; - Odie_Free((char *) pSeg ); - } - Odie_Free((char *) p ); -} - -/* -** Clear the Segment.ignore flag on all segments within a wallset. -*/ -static void ignoreNone(Wallset *p){ -#if 0 - Link *pLink; - for(pLink=p->pAll; pLink; pLink=pLink->pNext){ - pLink->pSeg->ignore = 0; - } -#endif -} - -/* -** Return a pointer to the segment with the given ID. Return NULL -** if there is no such segment. -*/ -static Segment *findSegment(Wallset *p, int id){ - int h; - Link *pLink; - - h = hashInt(id); - for(pLink = p->hashId[h]; pLink; pLink=pLink->pNext){ - Segment *pSeg=pLink->pLinkNode; - if( pSeg->id==id ) return pSeg; - } - return 0; -} - -#if 0 /* NOT USED */ -/* -** Make a copy of a string. -*/ -static char *stringDup(const char *z){ - int len = strlen(z); - char *zNew = Odie_Alloc( len+1 ); - if( zNew ){ - memcpy(zNew, z, len+1); - } - return zNew; -} -#endif - -/* -** Scan all segments looking for the vertex or vertices that are nearest -** to x,y. Return a pointer to a Segment.set that is the list of matching -** segments. Also write the nearest point into *pX,*pY. -** -** The returned list uses the Segment.set link. -*/ -static Link *nearestVertex( - Wallset *p, /* The wallset to be scanned */ - double x, double y, /* Search for points near to this point */ - double *pX, double *pY /* Write nearest vertex here */ -){ - double nx, ny; - double min = -1.0; - Link *pList = 0; - Link *pI; - - x = roundCoord(x); - y = roundCoord(y); - for(pI=p->pAll; pI; pI=pI->pNext){ - double dx, dy, dist; - Segment *pSeg = pI->pLinkNode; - dx = x - pSeg->from[X_IDX]; - dy = y - pSeg->from[Y_IDX]; - dist = dx*dx + dy*dy; - if( min<0.0 || dist<=min ){ - if( min<0.0 || nx!=pSeg->from[X_IDX] || ny!=pSeg->from[Y_IDX] ){ - pList = 0; - nx = pSeg->from[X_IDX]; - ny = pSeg->from[Y_IDX]; - min = dist; - } - LinkInit(pSeg->pSet, pSeg); - LinkInsert(&pList, &pSeg->pSet); - } - dx = x - pSeg->to[X_IDX]; - dy = y - pSeg->to[Y_IDX]; - dist = dx*dx + dy*dy; - if( dist<=min ){ - if( nx!=pSeg->to[X_IDX] || ny!=pSeg->to[Y_IDX] ){ - pList = 0; - nx = pSeg->to[X_IDX]; - ny = pSeg->to[Y_IDX]; - min = dist; - } - LinkInit(pSeg->pSet, pSeg); - LinkInsert(&pList, &pSeg->pSet); - } - } - *pX = nx; - *pY = ny; - return pList; -} - -/* -** Scan all segments looking for the point on a segment that is nearest -** to x,y. Return a pointer to a Segment.set that is the list of matching -** segments. This set might contain multiple members if the nearest point -** is actually a vertex shared by two or more segments. Write the nearest -** point into *pX, *pY. -** -** /// Ignore any segment that has its Segment.ignore flag set. -- removed -** -** The returned list uses the Segment.set list. -*/ -static Link *nearestPoint( - Wallset *p, /* The wallset to be scanned */ - double x, double y, /* Search for points near to this point */ - double *pX, double *pY /* Write nearest vertex here */ -){ - double nx, ny; - double min = -1.0; - Link *pList = 0; - Link *pI; - - x = roundCoord(x); - y = roundCoord(y); - for(pI=p->pAll; pI; pI=pI->pNext){ - double dx, dy, dist; - Segment *pSeg; - double acx, acy; /* Vector from x0,y0 to x,y */ - double abx, aby; /* Vector from x0,y0 to x1,y1 */ - double rx, ry; /* Nearest point on x0,y0->to[X_IDX],y1 to x,y */ - double r; - - pSeg = pI->pLinkNode; - /* if( pSeg->ignore ) continue; */ - acx = x - pSeg->from[X_IDX]; - acy = y - pSeg->from[Y_IDX]; - abx = pSeg->to[X_IDX] - pSeg->from[X_IDX]; - aby = pSeg->to[Y_IDX] - pSeg->from[Y_IDX]; - r = (acx*abx + acy*aby)/(abx*abx + aby*aby); - if( r<=0 ){ - rx = pSeg->from[X_IDX]; - ry = pSeg->from[Y_IDX]; - }else if( r>=1 ){ - rx = pSeg->to[X_IDX]; - ry = pSeg->to[Y_IDX]; - }else{ - rx = pSeg->from[X_IDX] + abx*r; - ry = pSeg->from[Y_IDX] + aby*r; - } - rx = roundCoord(rx); - ry = roundCoord(ry); - dx = x - rx; - dy = y - ry; - dist = dx*dx + dy*dy; - if( min<0.0 || dist<=min ){ - if( min<0.0 || nx!=rx || ny!=ry ){ - pList = 0; - nx = rx; - ny = ry; - min = dist; - } - LinkInit(pSeg->pSet, pSeg); - LinkInsert(&pList, &pSeg->pSet); - } - } - *pX = nx; - *pY = ny; - return pList; -} - -/* -** Return TRUE if the value x is in between x1 and x2. -*/ -static int between(double x, double x1, double x2){ - if( x1=x1 && x<=x2; - }else{ - return x>=x2 && x<=x1; - } -} - -/* -** Return TRUE if the given segment is on the given list -*/ -static int segmentOnList(Segment *pSeg, Link *pList){ - while( pList ){ - if( pList->pLinkNode==pSeg ) return 1; - pList = pList->pNext; - } - return 0; -} - -/* -** Return a list of all segments which have an end at the given vertex. -** The returned list uses Segment.set -*/ -static Link *segmentsAtVertex(Wallset *p, double x, double y){ - Link *pList = 0; - Link *pI; - int h; - - x = roundCoord(x); - y = roundCoord(y); - h = hashCoord(x, y); - for(pI=p->hashFrom[h]; pI; pI=pI->pNext){ - Segment *pSeg = pI->pLinkNode; - /* if( pSeg->ignore ) continue; */ - if( floatCompare(x, pSeg->from[X_IDX])==0 && floatCompare(y, pSeg->from[Y_IDX])==0 ){ - assert( !segmentOnList(pSeg, pList) ); - LinkInit(pSeg->pSet, pSeg); - LinkInsert(&pList, &pSeg->pSet); - } - } - for(pI=p->hashTo[h]; pI; pI=pI->pNext){ - Segment *pSeg = pI->pLinkNode; - /* if( pSeg->ignore ) continue; */ - if( floatCompare(x, pSeg->to[X_IDX])==0 && floatCompare(y, pSeg->to[Y_IDX])==0 ){ - assert( !segmentOnList(pSeg, pList) ); - LinkInit(pSeg->pSet, pSeg); - LinkInsert(&pList, &pSeg->pSet); - } - } - return pList; -} - -/* -** The point xV,yV is a vertex in the wallset. This routine locates -** a segment connected to that vertex which is the first segment in -** a clockwise direction from xR,yR->xV,yV. A pointer to the segment -** is written into *ppSeg. If the output segment moves backwards -** (in other words if x1,y1 of the segment is connected at xV,yV) -** then *pfBack is true. -** -** If a suitable segment is found, 0 is returned. Non-zero is returned -** if no suitable segment could be found. -** -** This routine uses the Segment.set list internally. -*/ -static int nextCwSegment( - Wallset *p, /* The wallset */ - double xR, double yR, /* Remote end of input segment */ - double xV, double yV, /* Vertex (near end of input segment) */ - Segment **ppSeg, /* OUT: First segment clockwise from xR,yR->xV,yV */ - int *pfBack /* OUT: True if output segment goes backwards */ -){ - Link *pList, *pI; - double rRef, rBest; - int i, nSeg, iBest; - Segment *pSeg; - struct { - Segment *pSeg; - int isBack; - double rAngle; - } *aSeg, aSegStatic[20]; - - /* Find all segments at xV,yV */ - pList = segmentsAtVertex(p, xV, yV); - for(pI=pList, nSeg=0; pI; nSeg++, pI=pI->pNext){} - if( nSeg==0 ) return 1; - if( nSeg<=sizeof(aSegStatic)/sizeof(aSegStatic[0]) ){ - aSeg = aSegStatic; - }else{ - aSeg = (void *)Odie_Alloc( nSeg*sizeof(*aSeg) ); - } - for(pI=pList, i=0; pI; i++, pI=pI->pNext){ - aSeg[i].pSeg = pSeg = pI->pLinkNode; - aSeg[i].isBack = floatCompare(xV, pSeg->to[X_IDX])==0 - && floatCompare(yV, pSeg->to[Y_IDX])==0; - } - - /* Find the reference angle */ - rRef = atan2(yR-yV, xR-xV)*180.0/M_PI; - - /* Find angles on all segments */ - for(i=0; ifrom[Y_IDX]-pSeg->to[Y_IDX], pSeg->from[X_IDX]-pSeg->to[X_IDX])*180.0/M_PI; - }else{ - aSeg[i].rAngle = atan2(pSeg->to[Y_IDX]-pSeg->from[Y_IDX], pSeg->to[X_IDX]-pSeg->from[X_IDX])*180.0/M_PI; - } - } - - /* Subtract 360 to any segment angle that is less than the reference angle */ - for(i=0; irBest ){ - iBest = i; - rBest = aSeg[i].rAngle; - } - } - *ppSeg = aSeg[iBest].pSeg; - *pfBack = aSeg[iBest].isBack; - if( aSeg!=aSegStatic ){ - Odie_Free((char *) aSeg ); - } - - return 0; -} - -/* -** Consider a line beginning at x0,y0 then going from x1,y1 to x2,y2. -** x1,y1 is an elbow in the line. This routine returns -1 if the -** elbow bends to the right, and +1 if it bends to the left. zero is -** returned if the elbow does not bend at all. -*/ -static int bendDirection( - double x0, double y0, - double x1, double y1, - double x2, double y2 -){ - /* Algorithm: Rotate x0,y0->to[X_IDX],y1 90 degrees counter-clockwise. Take - ** the dot product with x1,y1->x2,y2. The dot produce will be the product - ** of two (non-negative) magnitudes and the cosine of the angle. So if - ** the dot product is positive, the bend is to the left, or to the right if - ** the dot product is negative. - */ - double r = (y0-y1)*(x2-x1) + (x1-x0)*(y2-y1); - return r<0.0 ? +1 : (r>0.0 ? -1 : 0); -} - -/* -** Given an interior point xI,yI, this routine finds a segment on the -** boundary that contains the interior point. That segment is returned -** in *ppSeg. *pfLeft is set to true if the interior point is to the left -** of the segment and false if it is to the right. -** -** Zero is returned on success. Non-zero is returned if no suitable -** boundary could be located. Non-zero might be returned, for example, -** if xI,yI is positioned directly on top of a wall or if there are no -** walls in the wallset. -** -** // Any segment marked with Segment.ignore is ignored for purposes of -** // this routine. -- removed -** -** This routine uses the Segment.set list internally. -*/ -static int firstBoundarySegment( - Wallset *p, /* The wallset */ - double xI, double yI, /* An interior point */ - Segment **ppSeg, /* OUT: A segment on the boundary containing xI,yI */ - int *pfLeft /* OUT: True if xI,yI is to the left side *ppSeg */ -){ - Link *pList; - double xN, yN; - - /* Find nearest point, xN,yN */ - pList = nearestPoint(p, xI, yI, &xN, &yN); - if( pList==0 ) return 1; - if( pList->pNext ){ - /* xN,yN is a vertex... - ** Locate the first segment clockwise from xI,yI->xN,yN and return - */ - return nextCwSegment(p, xI, yI, xN, yN, ppSeg, pfLeft); - }else{ - /* xN,yN is a point on single line segment... - */ - Segment *pSeg; - pSeg = *ppSeg = pList->pLinkNode; - *pfLeft = bendDirection(pSeg->from[X_IDX], pSeg->from[Y_IDX], xN, yN, xI, yI)>0; - } - return 0; -} - -/* -** Fill the given Boundary array with a list of segments (with -** Segment.ignore set to false) that form a closed circuit. The -** first entry in aBound[] has already been filled in by the -** calling function and is used to seed the search. -** -** At most nBound slots in aBound[] will be used. The return value -** is the number of slots in aBound[] that would have been used if those -** slots had been available. A return of 0 indicates that no boundary -** is available. -** -** If the checkIsPrimary flag is true and the aBound[0] entry is not -** the primary segment for the compartment, then the aBound[] is not -** completely filled in and the routine returns 0; -*/ -static int completeBoundary( - Wallset *p, /* The wallset */ - int checkIsPrimary, /* Abort if aBound[0] is not the primary segment */ - int nBound, /* Number of slots available in aBound[] */ - Boundary *aBound /* IN-OUT: Write results into aBound[1...] */ -){ - int cnt = 1; - Segment *pSeg, *pS; - int isLeft; - int isBack; - double xR, yR, xV, yV; - - pS = pSeg = aBound[0].pSeg; - isLeft = aBound[0].backwards; - if( !isLeft ){ - xR = pSeg->from[X_IDX]; - yR = pSeg->from[Y_IDX]; - xV = pSeg->to[X_IDX]; - yV = pSeg->to[Y_IDX]; - }else{ - xV = pSeg->from[X_IDX]; - yV = pSeg->from[Y_IDX]; - xR = pSeg->to[X_IDX]; - yR = pSeg->to[Y_IDX]; - } - while( nextCwSegment(p,xR,yR,xV,yV,&pS,&isBack)==0 && - (isBack!=isLeft || pS!=pSeg) ){ - if( checkIsPrimary ){ - if( pS->idid ) return 0; - if( pS->id==pSeg->id && !isLeft ) return 0; - } - if( isBack ){ - xV = pS->from[X_IDX]; - yV = pS->from[Y_IDX]; - xR = pS->to[X_IDX]; - yR = pS->to[Y_IDX]; - }else{ - xR = pS->from[X_IDX]; - yR = pS->from[Y_IDX]; - xV = pS->to[X_IDX]; - yV = pS->to[Y_IDX]; - } - if( nBound>cnt ){ - aBound[cnt].pSeg = pS; - aBound[cnt].backwards = isBack; - } - cnt++; - if( cnt>1000 /* 00 */ ) return -cnt; /* Avoid an infinite loop */ - } - return cnt; -} - -/* -** Compute the "spin" on a boundary. A positive value means the -** circulation is to counter-clockwise and a negative value means the -** circulation is clockwise. For boundaries, a positive -** value means the region is internal and a negative value means -** the region is external. -*/ -static double spin(Boundary *aBound, int nBound){ - double sum = 0; - int i; - for(i=0; ipSeg; - if( aBound->backwards ){ - x0 = pSeg->to[X_IDX]; - y0 = pSeg->to[Y_IDX]; - x1 = pSeg->from[X_IDX]; - y1 = pSeg->from[Y_IDX]; - }else{ - x0 = pSeg->from[X_IDX]; - y0 = pSeg->from[Y_IDX]; - x1 = pSeg->to[X_IDX]; - y1 = pSeg->to[Y_IDX]; - } - aBound++; - dx = x1-x0; - dy = y1-y0; - sum += x0*dy - y0*dx; - } - return sum; -} - -/* -** The input is two linked lists of ComptBox structures where each -** list is sorted by increasing area. Combine these two lists into -** a single sorted linked list. -*/ -static ComptBox *mergeComptBox(ComptBox *p1, ComptBox *p2){ - ComptBox head; - ComptBox *pTail = &head; - ComptBox *p; - while( p1 && p2 ){ - if( p1->area<=p2->area ){ - p = p1->pNext; - pTail->pNext = p1; - pTail = p1; - p1 = p; - }else{ - p = p2->pNext; - pTail->pNext = p2; - pTail = p2; - p2 = p; - } - } - if( p1 ){ - pTail->pNext = p1; - }else{ - pTail->pNext = p2; - } - return head.pNext; -} - -/* -** Construct the ComptBox cache. For each compartment (where a compartment -** is a closed circuit of Segments) make an entry on the Wallset.pComptBox -** list. -** -** If the ComptBox cache already exists, this routine is a no-op. -*/ -static void buildComptBoxCache(Wallset *p){ - Link *pI; - int i; - ComptBox *aSort[30]; - - /* Return immediately if the cache already exists */ - if( p->pComptBox ) return; - - /* Compute a linked list of all compartment boxes */ - for(pI=p->pAll; pI; pI=pI->pNext){ - int i, j, n; - Boundary aBound[1000]; - - aBound[0].pSeg = pI->pLinkNode; - for(j=0; j<2; j++){ - aBound[0].backwards = j; - n = completeBoundary(p, 1, sizeof(aBound)/sizeof(aBound[0]), aBound); - if( n>0 && spin(aBound,n)>0.0 ){ - double dx, dy; - Segment *pSeg = pI->pLinkNode; - ComptBox *pNew = (ComptBox *)Odie_Alloc( sizeof(*pNew) ); - pNew->pNext = p->pComptBox; - pNew->bbox.l = pNew->bbox.r = pSeg->from[X_IDX]; - pNew->bbox.t = pNew->bbox.b = pSeg->from[Y_IDX]; - pNew->prim = aBound[0]; - for(i=1; ifrom[X_IDX]bbox.l ) pNew->bbox.l = pSeg->from[X_IDX]; - if( pSeg->from[X_IDX]>pNew->bbox.r ) pNew->bbox.r = pSeg->from[X_IDX]; - if( pSeg->from[Y_IDX]bbox.b ) pNew->bbox.b = pSeg->from[Y_IDX]; - if( pSeg->from[Y_IDX]>pNew->bbox.t ) pNew->bbox.t = pSeg->from[Y_IDX]; - if( pSeg->to[X_IDX]bbox.l ) pNew->bbox.l = pSeg->to[X_IDX]; - if( pSeg->to[X_IDX]>pNew->bbox.r ) pNew->bbox.r = pSeg->to[X_IDX]; - if( pSeg->to[Y_IDX]bbox.b ) pNew->bbox.b = pSeg->to[Y_IDX]; - if( pSeg->to[Y_IDX]>pNew->bbox.t ) pNew->bbox.t = pSeg->to[Y_IDX]; - } - dx = pNew->bbox.r - pNew->bbox.l; - dy = pNew->bbox.t - pNew->bbox.b; - pNew->area = sqrt(dx*dx+dy*dy); - p->pComptBox = pNew; - } - } - } - - /* Sort the list into order of increasing area */ - for(i=0; ipComptBox ){ - ComptBox *pBox = p->pComptBox; - p->pComptBox = pBox->pNext; - pBox->pNext = 0; - for(i=0; ipComptBox = mergeComptBox(aSort[i], p->pComptBox); - } -} - -/* -** Test to see if the point x,y is contained within the given -** boundary or is on the outside of the boundary. -*/ -static int pointWithinBoundary( - Boundary *aBound, /* The boundary */ - int nBound, /* Number of segments in the boundary */ - double x, double y /* The point to test */ -){ - int inside = 0; - int i; - for(i=0; ifrom[X_IDX]; - y0 = p->from[Y_IDX]; - x1 = p->to[X_IDX]; - y1 = p->to[Y_IDX]; - if( x0==x1 ) continue; - if( (x0>x && x1>x) || (x0= y ) inside = !inside; - } - return inside; -} - -/* -** Find a boundary which contains xI, yI. If the size of the boundary -** is set to 0, that means no such boundary exists. -*/ -static int findBoundary( - Wallset *p, /* The wallset */ - double xI, double yI, /* A point that the boundary should be near */ - int nBound, /* Number of slots available in aBound[] */ - Boundary *aBound /* OUT: Write results here */ -){ - int n = 0; - ComptBox *pBox; - - buildComptBoxCache(p); - for(pBox=p->pComptBox; pBox; pBox=pBox->pNext){ - if( xIbbox.l || xI>pBox->bbox.r || yIbbox.b || yI>pBox->bbox.t ) continue; - aBound[0] = pBox->prim; - n = completeBoundary(p, 0, nBound, aBound); - if( n>0 && pointWithinBoundary(aBound, n, xI, yI) ) break; - n = 0; - } - return n; -} - - -/* -** Do an check of the integrity of the internal data structures. If -** a problem is found, leave an error message in interp->result and -** return TCL_ERROR. Return TCL_OK if everything is OK. -*/ -static int selfCheck(Tcl_Interp *interp, Wallset *p){ - Link *pLink; - Segment *pSeg; - int h; - char zErr[200]; - - for(pLink=p->pAll; pLink; pLink=pLink->pNext){ - pSeg = pLink->pLinkNode; - h = hashInt(pSeg->id); - if(!segmentOnList(pSeg, p->hashId[h]) ){ - sprintf(zErr, "segment %d missing from hashId[%d]", pSeg->id, h); - Tcl_SetResult(interp, zErr, TCL_VOLATILE); - return TCL_ERROR; - } - h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]); - if(!segmentOnList(pSeg, p->hashFrom[h]) ){ - sprintf(zErr, "segment %d missing from hashFrom[%d]", pSeg->id, h); - Tcl_SetResult(interp, zErr, TCL_VOLATILE); - return TCL_ERROR; - } - h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]); - if(!segmentOnList(pSeg, p->hashTo[h]) ){ - sprintf(zErr, "segment %d missing from hashTo[%d]", pSeg->id, h); - Tcl_SetResult(interp, zErr, TCL_VOLATILE); - return TCL_ERROR; - } - } - return TCL_OK; -} - -/* -** The maximum number of segments in a boundary -*/ -#define MX_BOUND 1000 - - -/* -** This routine runs when a method is executed against a wallset. -*/ -static int wallsetMethodProc( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Wallset *p = (Wallset*)pArg; - Boundary aBound[MX_BOUND]; - -#if 0 - /* For debugging.... - ** Print each wallset command before it is executed. - */ - { int i; - for(i=0; irXZoom, y*p->rYZoom); - while( pList ){ - Segment *pSeg=pList->pLinkNode; - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id)); - pList = pList->pNext; - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET boundary X Y - ** title: Return indices of segments forming a boundary around X Y - */ - case WALLSET_BOUNDARY: { - int nBound; - double x, y; - Tcl_Obj *pResult; - int i; - int showDetail = 0; - - if( objc==5 && strcmp(Tcl_GetStringFromObj(objv[2],0),"-detail")==0 ){ - showDetail = 1; - objc--; - objv++; - } - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?-detail? X Y"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR; - nBound = findBoundary(p, x*p->rXZoom, y*p->rYZoom, MX_BOUND, aBound); - if( nBound>MX_BOUND ) nBound = 0; - pResult = Tcl_NewObj(); - for(i=0; iid)); - if( showDetail ){ - Tcl_ListObjAppendElement(0, pResult, - ODIE_CONSTANT_STRING(aBound[i].backwards ? "right" : "left")); - } - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET closure WALLID BACKWARDS CHECKPRIMARY ?-coords? - ** title: Return the closure of a wall - ** - ** The closure is a path of walls going clockwise from the wall given. - ** The return value is a list consisting of wall IDs alternating with - ** keywords "left" or "right" indicating which side of the wall applies. - ** If the CHECKPRIMARY flag is true and the WALLID/BACKWARDS is not the - ** primary wall id for the closure, then return an empty string. The - ** primary wall id is the wall id with the lowest id number, or if - ** two walls in the closure have the same id, then the one that goes - ** on the right side of the wall. - */ - case WALLSET_CLOSURE: { - int id; - int nBound, i, checkPrim; - Tcl_Obj *pResult; - int coordsFlag = 0; - int noerrFlag = 0; - if( objc!=5 && objc!=6 ){ - Tcl_WrongNumArgs(interp, 2, objv, - "WALLID BACKWARDS CHECKPRIMARY ?-coords? ?-noerr?"); - return TCL_ERROR; - } - if( objc==6 ){ - const char *zOpt = Tcl_GetStringFromObj(objv[5],0); - if( strcmp(zOpt,"-coords")==0 ){ - coordsFlag = 1; - }else if( strcmp(zOpt,"-noerr")==0 ){ - noerrFlag = 1; - }else{ - Tcl_AppendResult(interp, "unknown option: ", zOpt, 0); - return TCL_ERROR; - } - } - if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR; - if( (aBound[0].pSeg = findSegment(p, id))==0 ){ - Tcl_AppendResult(interp, "segment ", - Tcl_GetStringFromObj(objv[2],0), " does not exist", 0); - return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[3], &aBound[0].backwards) ){ - return TCL_ERROR; - } - if( Tcl_GetBooleanFromObj(interp, objv[4], &checkPrim) ){ - return TCL_ERROR; - } - ignoreNone(p); - nBound = completeBoundary(p, checkPrim, MX_BOUND, aBound); - pResult = Tcl_NewObj(); - if( nBound<0 && noerrFlag ) nBound = -nBound; - for(i=0; ito[X_IDX]; - y = pSeg->to[Y_IDX]; - }else{ - x = pSeg->from[X_IDX]; - y = pSeg->from[Y_IDX]; - } - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y/p->rYZoom)); - }else{ - Tcl_ListObjAppendElement(0, pResult, - Tcl_NewIntObj(aBound[i].pSeg->id)); - Tcl_ListObjAppendElement(0, pResult, - ODIE_CONSTANT_STRING(aBound[i].backwards ? "right" : "left")); - } - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET comptlist - ** title: Return a list of all compartments - ** - ** A compartment is a closed circuit of walls. This routine returns - ** a list of all compartments. Each element of the list consists of - ** the primary wall for the compartment followed by a bounding box - ** for the compartment. - */ - case WALLSET_COMPTLIST: { - ComptBox *pBox; - Tcl_Obj *pResult = Tcl_NewObj(); - buildComptBoxCache(p); - for(pBox=p->pComptBox; pBox; pBox=pBox->pNext){ - Tcl_Obj *pElem = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pElem,Tcl_NewIntObj(pBox->prim.pSeg->id)); - Tcl_ListObjAppendElement(0, pElem, Tcl_NewIntObj(pBox->prim.backwards)); - Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox.l/p->rXZoom)); - Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox.b/p->rYZoom)); - Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox.r/p->rXZoom)); - Tcl_ListObjAppendElement(0, pElem, Tcl_NewDoubleObj(pBox->bbox.t/p->rYZoom)); - Tcl_ListObjAppendElement(0, pResult, pElem); - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET primary X Y - ** title: Return the primary segment of the compartment enclosing X,Y - ** - ** The primary segment is the segment with the smallest ID. If the - ** same segment occurs twice on the list (in other words, if the - ** same compartment is on both sides of a wall), then the right side - ** (as measured facing the direction of travel from x0,y0 -> x1,y1) - ** is used. - */ - case WALLSET_PRIMARY: { - int nBound; - double x, y; - int i, sideSmallest; - int idSmallest; - Tcl_Obj *pResult; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR; - nBound = findBoundary(p, x*p->rXZoom, y*p->rYZoom, MX_BOUND, aBound); - if( nBound>0 && nBoundid; - sideSmallest = aBound[0].backwards; - for(i=1; iid>idSmallest ) continue; - if( aBound[i].pSeg->idid; - sideSmallest = aBound[i].backwards; - } - } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(idSmallest)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(sideSmallest)); - Tcl_SetObjResult(interp, pResult); - } - break; - } - - /* - ** tclmethod: WALLSET corners X Y - ** title: Return vertices of compartment containing X,Y - */ - case WALLSET_CORNERS: { - int nBound, i; - double x, y; - Tcl_Obj *pResult; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR; - nBound = findBoundary(p, x*p->rXZoom, y*p->rYZoom, MX_BOUND, aBound); - if( nBound>MX_BOUND ) nBound = 0; - pResult = Tcl_NewObj(); - for(i=0; ito[X_IDX]; - y = pSeg->to[Y_IDX]; - }else{ - x = pSeg->from[X_IDX]; - y = pSeg->from[Y_IDX]; - } - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(x/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(y/p->rYZoom)); - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET delete ID - ** title: Delete a single segment of a wall given by ID - */ - case WALLSET_DELETE: { - int id; - Segment *pSeg; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "ID"); - return TCL_ERROR; - } - if( p->busy ){ - Tcl_AppendResult(interp, "cannot \"delete\" from within a \"foreach\"",0); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR; - if( (pSeg = findSegment(p, id))==0 ){ - Tcl_AppendResult(interp, "segment ", - Tcl_GetStringFromObj(objv[2],0), " does not exist", 0); - return TCL_ERROR; - } - clearComptBoxCache(p); - LinkRemove(&pSeg->pAll); - /* We intentionally do not remove pSeg->pSet because it might not be - ** a well-formed list */ - LinkRemove(&pSeg->pHash); - LinkRemove(&pSeg->pFrom); - LinkRemove(&pSeg->pTo); - Odie_Free((char *)pSeg); - break; - } - - /* - ** tclmethod: WALLSET destroy - ** title: Destroy this wallset - */ - case WALLSET_DESTROY: { - Tcl_DeleteCommand(interp,Tcl_GetString(objv[0])); - break; - } - - /* - ** tclmethod: WALLSET firstboundary X Y - ** title: Find a wall on the boundary of compartment containing X Y - ** - ** Returns a list of two elements on success or an empty list if no - ** suitable boundary could be found. The first element is the ID of a - ** wall that forms part of the boundary for the compartment containing - ** point X,Y. The second element is TRUE if X,Y is to the right of the - ** wall and false if it is to the left. - ** - ** The right/left designation assumes a right-handed coordinate system. - */ - case WALLSET_FIRSTBOUNDARY: { - int isBack; - Segment *pSeg; - double x, y; - int rc; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X Y"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y) ) return TCL_ERROR; - ignoreNone(p); - rc = firstBoundarySegment(p, x*p->rXZoom, y*p->rYZoom, &pSeg, &isBack); - if( rc==0 ){ - Tcl_Obj *pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(isBack)); - Tcl_SetObjResult(interp, pResult); - } - break; - } - - /* - ** tclmethod: WALLSET foreach CODE - ** title: Run CODE for each segment of the wallset - */ - case WALLSET_FOREACH: { - Link *pLink; - int rc = TCL_OK; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "CODE"); - return TCL_ERROR; - } - p->busy++; - for(pLink=p->pAll; pLink && rc==TCL_OK; pLink=pLink->pNext){ - Segment *pSeg = pLink->pLinkNode; - Tcl_SetVar2Ex(interp, "x0", 0, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom), 0); - Tcl_SetVar2Ex(interp, "y0", 0, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom), 0); - Tcl_SetVar2Ex(interp, "x1", 0, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom), 0); - Tcl_SetVar2Ex(interp, "y1", 0, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom), 0); - Tcl_SetVar2Ex(interp, "id", 0, Tcl_NewIntObj(pSeg->id), 0); - Tcl_SetVar2Ex(interp, "lc", 0, Tcl_NewIntObj(pSeg->idLC), 0); - Tcl_SetVar2Ex(interp, "rc", 0, Tcl_NewIntObj(pSeg->idRC), 0); - Tcl_SetVar2Ex(interp, "virtual", 0, Tcl_NewIntObj(pSeg->isBoundary), 0); - rc = Tcl_EvalObjEx(interp, objv[2], 0); - } - if( rc==TCL_BREAK ) rc = TCL_OK; - p->busy--; - return rc; - } - - /* - ** tclmethod: WALLSET info ID - ** title: Return information about a single wall segment - */ - case WALLSET_INFO: { - int id; - Segment *pSeg; - Tcl_Obj *pResult; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "ID"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR; - if( (pSeg = findSegment(p, id))==0 ){ - Tcl_AppendResult(interp, "segment ", - Tcl_GetStringFromObj(objv[2],0), " does not exist", 0); - return TCL_ERROR; - } - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->idLC)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->idRC)); - Tcl_SetObjResult(interp, pResult); - break; - } - - /* tclmethod: WALLSET insert X0 Y0 X1 Y1 ID LC RC VIRTUAL - ** title: Create a new wall within the wallset - */ - case WALLSET_INSERT: { - int id; - int h,virtual=0; - double x0, y0, x1, y1; - int idLC, idRC; - Segment *pSeg; - if( objc!=9 && objc!=10){ - Tcl_WrongNumArgs(interp, 2, objv, "X0 Y0 X1 Y1 ID LC RC ?1|0?"); - return TCL_ERROR; - } - if( p->busy ){ - Tcl_AppendResult(interp, "cannot \"insert\" from within a \"foreach\"",0); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &x1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &y1) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[6], &id) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[7], &idLC) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[8], &idRC) ) return TCL_ERROR; - if(objc==10) { - if( Tcl_GetIntFromObj(interp, objv[8], &virtual) ) return TCL_ERROR; - } - x0 = roundCoord(x0*p->rXZoom); - y0 = roundCoord(y0*p->rYZoom); - x1 = roundCoord(x1*p->rXZoom); - y1 = roundCoord(y1*p->rYZoom); - if( findSegment(p, id) ){ - Tcl_AppendResult(interp, "segment ", - Tcl_GetStringFromObj(objv[6],0), " already exists", 0); - return TCL_ERROR; - } - if( floatCompare(x0,x1)==0 && floatCompare(y0,y1)==0 ){ - /* Tcl_AppendResult(interp, "endpoints must be distinct", 0); */ - /* return TCL_ERROR; */ - return TCL_OK; /* Not an error. Just a no-op. */ - } - clearComptBoxCache(p); - pSeg = (Segment *)Odie_Alloc( sizeof(*pSeg) ); - if( pSeg==0 ) return TCL_ERROR; - pSeg->id = id; - pSeg->idLC = idLC; - pSeg->idRC = idRC; - pSeg->from[X_IDX] = x0; - pSeg->from[Y_IDX] = y0; - pSeg->to[X_IDX] = x1; - pSeg->to[Y_IDX] = y1; - pSeg->isBoundary=virtual; - - LinkInit(pSeg->pAll, pSeg); - LinkInit(pSeg->pSet, pSeg); - LinkInit(pSeg->pHash, pSeg); - LinkInit(pSeg->pFrom, pSeg); - LinkInit(pSeg->pTo, pSeg); - LinkInsert(&p->pAll, &pSeg->pAll); - h = hashInt(id); - LinkInsert(&p->hashId[h], &pSeg->pHash); - h = hashCoord(pSeg->from[X_IDX], pSeg->from[Y_IDX]); - LinkInsert(&p->hashFrom[h], &pSeg->pFrom); - h = hashCoord(pSeg->to[X_IDX], pSeg->to[Y_IDX]); - LinkInsert(&p->hashTo[h], &pSeg->pTo); - break; - } - - /* - ** tclmethod: WALLSET intersect X0 Y0 X1 Y1 - ** title: Find the intersection of X0,Y0->X1,Y1 with a segment - ** - ** Scan all segments in the wallset looking for one that intersects with - ** a line from X0,Y0 to X1,Y1. If the intersection occurs at x0,y0, it - ** is ignored, but intersections at x1,y1 count. If no such intersection - ** exists, return the empty string. If there are one or more intersections, - ** return the ID of the segment and the X and Y coordinates of the nearest - ** intersection to X0,Y0. - */ - case WALLSET_INTERSECT: { - double x0,y0,x1,y1; - double adx, ady; - Link *pI; - int id; - double nx, ny; - double mindist2 = -1.0; - if( objc!=6 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X0 Y0 X1 Y1"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &x1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &y1) ) return TCL_ERROR; - x0 = roundCoord(x0*p->rXZoom); - y0 = roundCoord(y0*p->rYZoom); - x1 = roundCoord(x1*p->rXZoom); - y1 = roundCoord(y1*p->rYZoom); - adx = x1-x0; - ady = y1-y0; - if( adx==0.0 && ady==0.0 ) break; - for(pI=p->pAll; pI; pI=pI->pNext){ - double bdx, bdy, denom, num1; - Segment *pSeg; - pSeg = pI->pLinkNode; - bdx = pSeg->to[X_IDX] - pSeg->from[X_IDX]; - bdy = pSeg->to[Y_IDX] - pSeg->from[Y_IDX]; - denom = adx*bdy - ady*bdx; - num1 = (y0-pSeg->from[Y_IDX])*bdx - (x0-pSeg->from[X_IDX])*bdy; - if( denom==0.0 ){ - /* The reference line and segment are parallel */ - if( num1==0.0 ){ - /* The reference line and segment are colinear */ - if( samePoint(x0,y0,pSeg->from[X_IDX],pSeg->from[Y_IDX]) - && adx*bdx<=0.0 && ady*bdy<=0.0 ){ - continue; - } - if( samePoint(x0,y0,pSeg->to[X_IDX],pSeg->to[Y_IDX]) - && adx*bdx>=0.0 && ady*bdy>=0.0 ){ - continue; - } - if( between(pSeg->from[Y_IDX],y0,y1) && between(pSeg->from[X_IDX],x0,x1) ){ - double dx, dy, dist2; - dx = pSeg->from[X_IDX] - x0; - dy = pSeg->from[Y_IDX] - y0; - dist2 = dx*dx + dy*dy; - if( mindist2<0 || mindist2>dist2 ){ - mindist2 = dist2; - nx = pSeg->from[X_IDX]; - ny = pSeg->from[Y_IDX]; - id = pSeg->id; - } - } - if( between(pSeg->to[Y_IDX],y0,y1) && between(pSeg->to[X_IDX],x0,x1) ){ - double dx, dy, dist2; - dx = pSeg->to[X_IDX] - x0; - dy = pSeg->to[Y_IDX] - y0; - dist2 = dx*dx + dy*dy; - if( mindist2<0 || mindist2>dist2 ){ - mindist2 = dist2; - nx = pSeg->to[X_IDX]; - ny = pSeg->to[Y_IDX]; - id = pSeg->id; - } - } - if( between(y0,pSeg->from[Y_IDX],pSeg->to[Y_IDX]) && between(x0,pSeg->from[X_IDX],pSeg->to[X_IDX]) ){ - if( mindist2<0 || mindist2>0.0 ){ - mindist2 = 0.0; - nx = x0; - ny = y0; - id = pSeg->id; - } - } - } - }else{ - /* The reference line and segment are not parallel */ - double r, s; - r = num1/denom; - s = ((y0-pSeg->from[Y_IDX])*adx - (x0-pSeg->from[X_IDX])*ady)/denom; - if( r>0 && r<=1.0 && s>=0.0 && s<=1.0 ){ - double dx, dy, dist2; - dx = r*adx; - dy = r*ady; - dist2 = dx*dx + dy*dy; - if( dist2>=GRAIN && (mindist2<0 || mindist2>dist2) ){ - mindist2 = dist2; - nx = x0 + dx; - ny = y0 + dy; - id = pSeg->id; - } - } - } - } - if( mindist2>=0.0 ){ - Tcl_Obj *pResult; - pResult = Tcl_NewObj(); - nx = roundCoord(nx); - ny = roundCoord(ny); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(nx/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(ny/p->rYZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(id)); - Tcl_SetObjResult(interp, pResult); - } - break; - } - - /* - ** tclmethod: WALLSET left ID LC - ** title: Change the left compartment of a line segment - */ - case WALLSET_LEFT: { - int id, idLC; - Segment *pSeg; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "ID LC"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &idLC) ) return TCL_ERROR; - if( (pSeg = findSegment(p, id))==0 ){ - Tcl_AppendResult(interp, "segment ", - Tcl_GetStringFromObj(objv[2],0), " does not exist", 0); - return TCL_ERROR; - } - pSeg->idLC = idLC; - break; - } - - /* - ** tclmethod: WALLSET list - ** title: Return a list of all wall segment identifiers - */ - case WALLSET_LIST: { - Link *pLink; - Tcl_Obj *pResult; - pResult = Tcl_NewObj(); - for(pLink=p->pAll; pLink; pLink=pLink->pNext){ - Segment *pSeg=pLink->pLinkNode; - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id)); - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET looseends - ** title: Return a list of walls that are have unconnected ends - ** - ** For each unconnected end, the list contains four elements: - ** 1. The wallid - ** 2. 0 for the "from" end, "1" for the "to" end - ** 3. The X coordinate of the loose end - ** 4. The Y coordinate of the loose end - */ - case WALLSET_LOOSEENDS: { - Segment *pSeg; - Link *pAll, *pList; - Tcl_Obj *pRes = Tcl_NewObj(); - for(pAll=p->pAll; pAll; pAll=pAll->pNext){ - pSeg = pAll->pLinkNode; - pList = segmentsAtVertex(p, pSeg->from[X_IDX], pSeg->from[Y_IDX]); - if( LinkCount(pList)==1 ){ - Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(pSeg->id)); - Tcl_ListObjAppendElement(0, pRes, ODIE_INT_ZERO()); - Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->from[X_IDX]/p->rXZoom)); - Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->from[Y_IDX]/p->rYZoom)); - } - pList = segmentsAtVertex(p, pSeg->to[X_IDX], pSeg->to[Y_IDX]); - if( LinkCount(pList)==1 ){ - Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(pSeg->id)); - Tcl_ListObjAppendElement(0, pRes, ODIE_INT_ONE()); - Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->to[X_IDX]/p->rXZoom)); - Tcl_ListObjAppendElement(0, pRes, Tcl_NewDoubleObj(pSeg->to[Y_IDX]/p->rYZoom)); - } - } - Tcl_SetObjResult(interp, pRes); - break; - } - - /* - ** tclmethod: WALLSET nearest vertex|point X Y - ** title: Find the nearest vertex or point to a point in the plan - */ - case WALLSET_NEAREST: { - int type; - double x, y, near_x, near_y; - static const char *NEAR_strs[] = { "point", "vertex", 0 }; - enum NEAR_enum { NEAR_POINT, NEAR_VERTEX, }; - Link *pLink; - Tcl_Obj *pResult; - double dx, dy, dist; - - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 2, objv, "point|vertex X Y"); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObj(interp, objv[2], NEAR_strs, "option", 0, &type) ){ - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[3], &x) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &y) ) return TCL_ERROR; - x *= p->rXZoom; - y *= p->rYZoom; - ignoreNone(p); - if( type==NEAR_POINT ){ - pLink = nearestPoint(p, x, y, &near_x, &near_y); - }else if( type==NEAR_VERTEX ){ - pLink = nearestVertex(p, x, y, &near_x, &near_y); - }else{ - /* Cannot happen */ return TCL_ERROR; - } - if( pLink==0 ) return TCL_OK; /* There are not segments in the wallset */ - pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(near_x/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(near_y/p->rYZoom)); - dx = x - near_x; - dy = y - near_y; - dist = sqrt(dx*dx + dy*dy); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewDoubleObj(dist/p->rXZoom)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewObj()); - while( pLink ){ - Segment *pSeg=pLink->pLinkNode; - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id)); - pLink = pLink->pNext; - } - Tcl_SetObjResult(interp, pResult); - break; - } - - /* - ** tclmethod: WALLSET nextcwwall X0 Y0 X1 Y1 - ** title: Find a wall on X1,Y1 clockwise from X0,Y0->X1,Y1 - */ - case WALLSET_NEXTCWWALL: { - int isBack; - Segment *pSeg; - double x0, y0, x1, y1; - int rc; - if( objc!=6 ){ - Tcl_WrongNumArgs(interp, 2, objv, "X0 Y0 X1 Y1"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[2], &x0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &y0) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &x1) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &y1) ) return TCL_ERROR; - x0 = roundCoord(x0*p->rXZoom); - y0 = roundCoord(y0*p->rYZoom); - x1 = roundCoord(x1*p->rXZoom); - y1 = roundCoord(y1*p->rYZoom); - rc = nextCwSegment(p, x0, y0, x1, y1, &pSeg, &isBack); - if( rc==0 ){ - Tcl_Obj *pResult = Tcl_NewObj(); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(pSeg->id)); - Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(isBack)); - Tcl_SetObjResult(interp, pResult); - } - break; - } - - /* - ** tclmethod: WALLSET right ID RC - ** title: Change the right compartment of a line segment - */ - case WALLSET_RIGHT: { - int id, idRC; - Segment *pSeg; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 2, objv, "ID RC"); - return TCL_ERROR; - } - if( Tcl_GetIntFromObj(interp, objv[2], &id) ) return TCL_ERROR; - if( Tcl_GetIntFromObj(interp, objv[3], &idRC) ) return TCL_ERROR; - if( (pSeg = findSegment(p, id))==0 ){ - Tcl_AppendResult(interp, "segment ", - Tcl_GetStringFromObj(objv[2],0), " does not exist", 0); - return TCL_ERROR; - } - pSeg->idRC = idRC; - break; - } - - /* - ** tclmethod: WALLSET segments - ** title: Write all wall segments out into the segset native datatype - */ - case WALLSET_SEGMENTS: { - - } - - /* - ** tclmethod: WALLSET selfcheck - ** title: Verify the integrity of internal data structures - */ - case WALLSET_SELFCHECK: { - return selfCheck(interp, p); - } - - /* - ** tclmethod: WALLSET zoom ?ZOOM? - ** title: Query or change the zoom factor. - */ - case WALLSET_ZOOM: { - Tcl_Obj *pResult; - if( objc!=2 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "?ZOOM?"); - return TCL_ERROR; - } - if( objc==3 ){ - double r; - if( Tcl_GetDoubleFromObj(interp, objv[2], &r) ) return TCL_ERROR; - if( r==0.0 ){ - Tcl_AppendResult(interp, "zoom must be non-zero", 0); - return TCL_ERROR; - } - p->rYZoom = r; - p->rXZoom = fabs(r); - } - pResult = Tcl_NewDoubleObj(p->rYZoom); - Tcl_SetObjResult(interp, pResult); - break; - } - - /* End of the command methods. The brackets that follow terminate the - ** automatically generated switch. - ****************************************************************************/ - } - } - -#if 0 - /* Sanity checking for debugging */ - if( selfCheck(interp, p) ){ - return TCL_ERROR; - } -#endif - return TCL_OK; -} - -/* -** tclcmd: wallset WALLSET -** title: Create a new wallset object -** This routine runs when the "wallset" command is invoked to create a -** new wallset. -*/ -int Odie_WallsetCreateProc( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char *zCmd; - Wallset *p; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "WALLSET"); - return TCL_ERROR; - } - zCmd = Tcl_GetStringFromObj(objv[1], 0); - p = (Wallset *)Odie_Alloc( sizeof(*p) ); - p->rXZoom = 100.0; - p->rYZoom = -100.0; - Tcl_CreateObjCommand(interp, zCmd, wallsetMethodProc, p, destroyWallset); - return TCL_OK; -} - DELETED cmodules/geometry/generic/wallset_cases.h Index: cmodules/geometry/generic/wallset_cases.h ================================================================== --- cmodules/geometry/generic/wallset_cases.h +++ /dev/null @@ -1,30 +0,0 @@ -/*** Automatically Generated Header File - Do Not Edit ***/ - const static char *WALLSET_strs[] = { - "atvertex", "boundary", "closure", - "comptlist", "corners", "delete", - "destroy", "firstboundary", "foreach", - "info", "insert", "intersect", - "left", "list", "looseends", - "nearest", "nextcwwall", "primary", - "right", "segments", "selfcheck", - "zoom", 0 - }; - enum WALLSET_enum { - WALLSET_ATVERTEX, WALLSET_BOUNDARY, WALLSET_CLOSURE, - WALLSET_COMPTLIST, WALLSET_CORNERS, WALLSET_DELETE, - WALLSET_DESTROY, WALLSET_FIRSTBOUNDARY,WALLSET_FOREACH, - WALLSET_INFO, WALLSET_INSERT, WALLSET_INTERSECT, - WALLSET_LEFT, WALLSET_LIST, WALLSET_LOOSEENDS, - WALLSET_NEAREST, WALLSET_NEXTCWWALL, WALLSET_PRIMARY, - WALLSET_RIGHT, WALLSET_SEGMENTS, WALLSET_SELFCHECK, - WALLSET_ZOOM, - }; - int index; - if( objc<2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "METHOD ?ARG ...?"); - return TCL_ERROR; - } - if( Tcl_GetIndexFromObj(interp, objv[1], WALLSET_strs, "option", 0, &index)){ - return TCL_ERROR; - } - switch( (enum WALLSET_enum)index ) DELETED cmodules/geometry/geometry.man Index: cmodules/geometry/geometry.man ================================================================== --- cmodules/geometry/geometry.man +++ /dev/null DELETED cmodules/logicset/cthulhu.ini Index: cmodules/logicset/cthulhu.ini ================================================================== --- cmodules/logicset/cthulhu.ini +++ /dev/null @@ -1,3 +0,0 @@ -set here [file dirname [file normalize [info script]]] -::cthulhu::add_directory $here { -} DELETED cmodules/logicset/logicset.c Index: cmodules/logicset/logicset.c ================================================================== --- cmodules/logicset/logicset.c +++ /dev/null @@ -1,1328 +0,0 @@ - -/* -** This file is machine generated. Changes will -** be overwritten on the next run of cstruct.tcl -*/ -#include "odieInt.h" -#include -#include -#define UCHAR(c) ((unsigned char) (c)) -#define TclFormatInt(buf, n) sprintf((buf), "%ld", (long)(n)) - -#define MEM_DEBUG 0 - -/* - * Macros used to cast between pointers and integers (e.g. when storing an int - * in ClientData), on 64-bit architectures they avoid gcc warning about "cast - * to/from pointer from/to integer of different size". - */ - -#if !defined(INT2PTR) && !defined(PTR2INT) -# if defined(HAVE_INTPTR_T) || defined(intptr_t) -# define INT2PTR(p) ((void *)(intptr_t)(p)) -# define PTR2INT(p) ((int)(intptr_t)(p)) -# else -# define INT2PTR(p) ((void *)(p)) -# define PTR2INT(p) ((int)(p)) -# endif -#endif -#if !defined(UINT2PTR) && !defined(PTR2UINT) -# if defined(HAVE_UINTPTR_T) || defined(uintptr_t) -# define UINT2PTR(p) ((void *)(uintptr_t)(p)) -# define PTR2UINT(p) ((unsigned int)(uintptr_t)(p)) -# else -# define UINT2PTR(p) ((void *)(p)) -# define PTR2UINT(p) ((unsigned int)(p)) -# endif -#endif - -#define VERSION "1.0" - -/* -** Internal call required for munging integers -*/ - -/* - * The structure used as the internal representation of Tcl list objects. This - * struct is grown (reallocated and copied) as necessary to hold all the - * list's element pointers. The struct might contain more slots than currently - * used to hold all element pointers. This is done to make append operations - * faster. - */ - -typedef struct List { - int refCount; - int maxElemCount; /* Total number of element array slots. */ - int elemCount; /* Current number of list elements. */ - int canonicalFlag; /* Set if the string representation was - * derived from the list representation. May - * be ignored if there is no string rep at - * all.*/ - Tcl_Obj *elements; /* First list element; the struct is grown to - * accomodate all elements. */ -} List; - -/* - * During execution of the "lsort" command, structures of the following type - * are used to arrange the objects being sorted into a collection of linked - * lists. - */ - -typedef struct SortElement { - union { - char *strValuePtr; - long intValue; - double doubleValue; - Tcl_Obj *objValuePtr; - } index; - Tcl_Obj *objPtr; /* Object being sorted, or its index. */ - struct SortElement *nextPtr;/* Next element in the list, or NULL for end - * of list. */ -} SortElement; - - -typedef struct SortInfo { - int isIncreasing; /* Nonzero means sort in increasing order. */ - int sortMode; /* The sort mode. One of SORTMODE_* values * defined below. */ - Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is - * SORTMODE_COMMAND. Pre-initialized to hold - * base of command. */ - int *indexv; /* If the -index option was specified, this - * holds the indexes contained in the list - * - * supplied as an argument to that option. - * NULL if no indexes supplied, and points to - * singleIndex field when only one - * supplied. - */ - int indexc; /* Number of indexes in indexv array. */ - int singleIndex; /* Static space for common index case. */ - int unique; - int numElements; - Tcl_Interp *interp; /* The interpreter in which the sort is being - * done. - */ - int resultCode; /* Completion code for the lsort command. If - * an error occurs during the sort this is - * changed from TCL_OK to TCL_ERROR. */ -} SortInfo; - -/* - * These function pointer types are used with the "lsearch" and "lsort" - * commands to facilitate the "-nocase" option. - */ - -typedef int (*SortStrCmpFn_t) (const char *, const char *); -typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t); - -/* - * The "lsort" command needs to pass certain information down to the function - * that compares two list elements, and the comparison function needs to pass - * success or failure information back up to the top-level "lsort" command. - * The following structure is used to pass this information. - */ - - -/* - * The "sortMode" field of the SortInfo structure can take on any of the - * following values. - */ - -#define SORTMODE_ASCII 0 -#define SORTMODE_INTEGER 1 -#define SORTMODE_REAL 2 -#define SORTMODE_COMMAND 3 -#define SORTMODE_DICTIONARY 4 -#define SORTMODE_ASCII_NC 8 - -/* - * Magic values for the index field of the SortInfo structure. Note that the - * index "end-1" will be translated to SORTIDX_END-1, etc. - */ - -#define SORTIDX_NONE -1 /* Not indexed; use whole value. */ -#define SORTIDX_END -2 /* Indexed from end. */ - -/* - * Forward declarations for procedures defined in this file: - */ - -static int DictionaryCompare(char *left, char *right); -static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr, - SortInfo *infoPtr); -static int SortCompare(SortElement *firstPtr, SortElement *second, - SortInfo *infoPtr); - -/* - *---------------------------------------------------------------------- - * - * MergeLists - - * - * This procedure combines two sorted lists of SortElement structures - * into a single sorted list. - * - * Results: - * The unified list of SortElement structures. - * - * Side effects: - * If infoPtr->unique is set then infoPtr->numElements may be updated. - * Possibly others, if a user-defined comparison command does something - * weird. - * - * Note: - * If infoPtr->unique is set, the merge assumes that there are no - * "repeated" elements in each of the left and right lists. In that case, - * if any element of the left list is equivalent to one in the right list - * it is omitted from the merged list. - * This simplified mechanism works because of the special way - * our MergeSort creates the sublists to be merged and will fail to - * eliminate all repeats in the general case where they are already - * present in either the left or right list. A general code would need to - * skip adjacent initial repeats in the left and right lists before - * comparing their initial elements, at each step. - *---------------------------------------------------------------------- - */ - -static SortElement * -MergeLists( - SortElement *leftPtr, /* First list to be merged; may be NULL. */ - SortElement *rightPtr, /* Second list to be merged; may be NULL. */ - SortInfo *infoPtr) /* Information needed by the comparison - * operator. */ -{ - SortElement *headPtr, *tailPtr; - int cmp; - - if (leftPtr == NULL) { - return rightPtr; - } - if (rightPtr == NULL) { - return leftPtr; - } - cmp = SortCompare(leftPtr, rightPtr, infoPtr); - if (cmp > 0 || (cmp == 0 && infoPtr->unique)) { - if (cmp == 0) { - infoPtr->numElements--; - leftPtr = leftPtr->nextPtr; - } - tailPtr = rightPtr; - rightPtr = rightPtr->nextPtr; - } else { - tailPtr = leftPtr; - leftPtr = leftPtr->nextPtr; - } - headPtr = tailPtr; - if (!infoPtr->unique) { - while ((leftPtr != NULL) && (rightPtr != NULL)) { - cmp = SortCompare(leftPtr, rightPtr, infoPtr); - if (cmp > 0) { - tailPtr->nextPtr = rightPtr; - tailPtr = rightPtr; - rightPtr = rightPtr->nextPtr; - } else { - tailPtr->nextPtr = leftPtr; - tailPtr = leftPtr; - leftPtr = leftPtr->nextPtr; - } - } - } else { - while ((leftPtr != NULL) && (rightPtr != NULL)) { - cmp = SortCompare(leftPtr, rightPtr, infoPtr); - if (cmp >= 0) { - if (cmp == 0) { - infoPtr->numElements--; - leftPtr = leftPtr->nextPtr; - } - tailPtr->nextPtr = rightPtr; - tailPtr = rightPtr; - rightPtr = rightPtr->nextPtr; - } else { - tailPtr->nextPtr = leftPtr; - tailPtr = leftPtr; - leftPtr = leftPtr->nextPtr; - } - } - } - if (leftPtr != NULL) { - tailPtr->nextPtr = leftPtr; - } else { - tailPtr->nextPtr = rightPtr; - } - return headPtr; -} - -/* - *---------------------------------------------------------------------- - * - * SortCompare -- - * - * This procedure is invoked by MergeLists to determine the proper - * ordering between two elements. - * - * Results: - * A negative results means the the first element comes before the - * second, and a positive results means that the second element should - * come first. A result of zero means the two elements are equal and it - * doesn't matter which comes first. - * - * Side effects: - * None, unless a user-defined comparison command does something weird. - * - *---------------------------------------------------------------------- - */ - -static int -SortCompare( - SortElement *elemPtr1, SortElement *elemPtr2, - /* Values to be compared. */ - SortInfo *infoPtr) /* Information passed from the top-level - * "lsort" command. */ -{ - int order = 0; - - if (infoPtr->sortMode == SORTMODE_ASCII) { - order = strcmp(elemPtr1->index.strValuePtr, - elemPtr2->index.strValuePtr); - } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) { - order = strcasecmp(elemPtr1->index.strValuePtr, - elemPtr2->index.strValuePtr); - } else if (infoPtr->sortMode == SORTMODE_DICTIONARY) { - order = DictionaryCompare(elemPtr1->index.strValuePtr, - elemPtr2->index.strValuePtr); - } else if (infoPtr->sortMode == SORTMODE_INTEGER) { - long a, b; - - a = elemPtr1->index.intValue; - b = elemPtr2->index.intValue; - order = ((a >= b) - (a <= b)); - } else if (infoPtr->sortMode == SORTMODE_REAL) { - double a, b; - - a = elemPtr1->index.doubleValue; - b = elemPtr2->index.doubleValue; - order = ((a >= b) - (a <= b)); - } else { - Tcl_Obj **objv, *paramObjv[2]; - int objc; - Tcl_Obj *objPtr1, *objPtr2; - - if (infoPtr->resultCode != TCL_OK) { - /* - * Once an error has occurred, skip any future comparisons so as - * to preserve the error message in sortInterp->result. - */ - - return 0; - } - - - objPtr1 = elemPtr1->index.objValuePtr; - objPtr2 = elemPtr2->index.objValuePtr; - - paramObjv[0] = objPtr1; - paramObjv[1] = objPtr2; - - /* - * We made space in the command list for the two things to compare. - * Replace them and evaluate the result. - */ - - Tcl_ListObjLength(infoPtr->interp, infoPtr->compareCmdPtr, &objc); - Tcl_ListObjReplace(infoPtr->interp, infoPtr->compareCmdPtr, objc - 2, - 2, 2, paramObjv); - Tcl_ListObjGetElements(infoPtr->interp, infoPtr->compareCmdPtr, - &objc, &objv); - - infoPtr->resultCode = Tcl_EvalObjv(infoPtr->interp, objc, objv, 0); - - if (infoPtr->resultCode != TCL_OK) { - Tcl_AddErrorInfo(infoPtr->interp, - "\n (-compare command)"); - return 0; - } - - /* - * Parse the result of the command. - */ - - if (Tcl_GetIntFromObj(infoPtr->interp, - Tcl_GetObjResult(infoPtr->interp), &order) != TCL_OK) { - Tcl_ResetResult(infoPtr->interp); - Tcl_AppendResult(infoPtr->interp, - "-compare command returned non-integer result", NULL); - infoPtr->resultCode = TCL_ERROR; - return 0; - } - } - if (!infoPtr->isIncreasing) { - order = -order; - } - return order; -} - -/* - *---------------------------------------------------------------------- - * - * DictionaryCompare - * - * This function compares two strings as if they were being used in an - * index or card catalog. The case of alphabetic characters is ignored, - * except to break ties. Thus "B" comes before "b" but after "a". Also, - * integers embedded in the strings compare in numerical order. In other - * words, "x10y" comes after "x9y", not * before it as it would when - * using strcmp(). - * - * Results: - * A negative result means that the first element comes before the - * second, and a positive result means that the second element should - * come first. A result of zero means the two elements are equal and it - * doesn't matter which comes first. - * - * Side effects: - * None. - * - *---------------------------------------------------------------------- - */ - -static int -DictionaryCompare( - char *left, char *right) /* The strings to compare. */ -{ - Tcl_UniChar uniLeft, uniRight, uniLeftLower, uniRightLower; - int diff, zeros; - int secondaryDiff = 0; - - while (1) { - if (isdigit(UCHAR(*right)) /* INTL: digit */ - && isdigit(UCHAR(*left))) { /* INTL: digit */ - /* - * There are decimal numbers embedded in the two strings. Compare - * them as numbers, rather than strings. If one number has more - * leading zeros than the other, the number with more leading - * zeros sorts later, but only as a secondary choice. - */ - - zeros = 0; - while ((*right == '0') && (isdigit(UCHAR(right[1])))) { - right++; - zeros--; - } - while ((*left == '0') && (isdigit(UCHAR(left[1])))) { - left++; - zeros++; - } - if (secondaryDiff == 0) { - secondaryDiff = zeros; - } - - /* - * The code below compares the numbers in the two strings without - * ever converting them to integers. It does this by first - * comparing the lengths of the numbers and then comparing the - * digit values. - */ - - diff = 0; - while (1) { - if (diff == 0) { - diff = UCHAR(*left) - UCHAR(*right); - } - right++; - left++; - if (!isdigit(UCHAR(*right))) { /* INTL: digit */ - if (isdigit(UCHAR(*left))) { /* INTL: digit */ - return 1; - } else { - /* - * The two numbers have the same length. See if their - * values are different. - */ - - if (diff != 0) { - return diff; - } - break; - } - } else if (!isdigit(UCHAR(*left))) { /* INTL: digit */ - return -1; - } - } - continue; - } - - /* - * Convert character to Unicode for comparison purposes. If either - * string is at the terminating null, do a byte-wise comparison and - * bail out immediately. - */ - - if ((*left != '\0') && (*right != '\0')) { - left += Tcl_UtfToUniChar(left, &uniLeft); - right += Tcl_UtfToUniChar(right, &uniRight); - - /* - * Convert both chars to lower for the comparison, because - * dictionary sorts are case insensitve. Covert to lower, not - * upper, so chars between Z and a will sort before A (where most - * other interesting punctuations occur). - */ - - uniLeftLower = Tcl_UniCharToLower(uniLeft); - uniRightLower = Tcl_UniCharToLower(uniRight); - } else { - diff = UCHAR(*left) - UCHAR(*right); - break; - } - - diff = uniLeftLower - uniRightLower; - if (diff) { - return diff; - } - if (secondaryDiff == 0) { - if (Tcl_UniCharIsUpper(uniLeft) && Tcl_UniCharIsLower(uniRight)) { - secondaryDiff = -1; - } else if (Tcl_UniCharIsUpper(uniRight) - && Tcl_UniCharIsLower(uniLeft)) { - secondaryDiff = 1; - } - } - } - if (diff == 0) { - diff = secondaryDiff; - } - return diff; -} - - -static int Odie_SortElement_FromObj( - Tcl_Interp *interp, - int sortMode, - Tcl_Obj *valuePtr, - SortElement *elementPtr -) { - /* - * Determine the "value" of this object for sorting purposes - */ - if (sortMode == SORTMODE_ASCII) { - elementPtr->index.strValuePtr = Tcl_GetString(valuePtr); - } else if (sortMode == SORTMODE_INTEGER) { - long a; - - if (Tcl_GetLongFromObj(interp, valuePtr, &a) != TCL_OK) { - return TCL_ERROR; - } - elementPtr->index.intValue = a; - } else if (sortMode == SORTMODE_REAL) { - double a; - - if (Tcl_GetDoubleFromObj(interp, valuePtr, &a) != TCL_OK) { - return TCL_ERROR; - } - elementPtr->index.doubleValue = a; - } else { - elementPtr->index.objValuePtr = valuePtr; - } - elementPtr->objPtr = valuePtr; - return TCL_OK; -} - -/* -** Converts a linked list of structures into -** a Tcl list object -*/ - -static Tcl_Obj *Odie_MergeList_ToObj(SortElement *elementPtr) { - SortElement *loopPtr; - Tcl_Obj **newArray; - int i,len=0; - loopPtr=elementPtr; - for (len=0; loopPtr != NULL ; loopPtr = loopPtr->nextPtr) { - len++; - } - newArray = (Tcl_Obj **)Odie_Alloc(sizeof(Tcl_Obj *)*len); - loopPtr=elementPtr; - for (i=0; loopPtr != NULL ; loopPtr = loopPtr->nextPtr) { - Tcl_Obj *objPtr = loopPtr->objPtr; - newArray[i] = objPtr; - i++; - //Tcl_IncrRefCount(objPtr); - } - return Tcl_NewListObj(len,newArray); -} - - -STUB_EXPORT int Odie_Lsearch(int listLength,Tcl_Obj **listObjPtrs,Tcl_Obj *element) { - int i; - Tcl_Obj *o; - if(element==NULL) { - return -1; - } - - int matchLen; - char *match=Tcl_GetStringFromObj(element,&matchLen); - - int s2len,found; - const char *s2; - - if(matchLen < 0) { - return -1; - } - - found = 0; - for(i=0;i=0) { - return 1; - } - return 0; -} - -STUB_EXPORT void Logicset_Sanitize_List(char *value,int len) { - int i,skipped=0; - for(i=0;i0x80 || x==0x7D || x==0x7B) { - value[i]=0x20; - continue; - } - skipped--; - } -} - -STUB_EXPORT Tcl_Obj *Logicset_FromObj(Tcl_Obj *rawlist) { - if(!rawlist) { - return NULL; - } - Tcl_Obj *result; - int len; - char *rawvalue=Tcl_GetStringFromObj(rawlist,&len); - if(len==0) { - return NULL; - } - Logicset_Sanitize_List(rawvalue,len); - Tcl_Obj *tempString=Tcl_NewStringObj(rawvalue,len); - - int listLength,i; - Tcl_Obj **listObjPtrs; - if(Tcl_ListObjGetElements(NULL, tempString, &listLength, &listObjPtrs)) { - Tcl_DecrRefCount(tempString); - return NULL; - } - if(listLength <= 0) { - Tcl_DecrRefCount(tempString); - return NULL; - } - Tcl_Obj *listObj=Tcl_NewObj(); - for(i=0;i1) { - int i; - for(i=0;i= NUM_LISTS) { - j = NUM_LISTS-1; - } - subList[j] = elementPtr; - } - - /* - * Merge all sublists - */ - - elementPtr = subList[0]; - for (j=1 ; jfullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - return TCL_OK; -} DELETED cmodules/logicset/logicset.man Index: cmodules/logicset/logicset.man ================================================================== --- cmodules/logicset/logicset.man +++ /dev/null @@ -1,42 +0,0 @@ -[comment {-*- tao -*-}] -[manpage_begin odielib::math n 2.0] -[keywords odielib] -[copyright {2000-2014 Sean Woods }] -[moddesc {The Odielib Accellerated Math Module}] -[titledesc {The Odielib Accellerated Math Module}] -[category {Mathematics}] -[require odielib 2.0] -[description] - -[para] - -The [package logicset] package is included with [package odielib]. It contains -a series of C-accellerated routines for managing logical sets. - -[section COMMANDS] -[list_begin definitions] -[call [cmd affine2d::combine] [arg "transform"] [arg "transform"] [opt [arg "transform..."]]] -Accepts N 3x3 affine matrices, and returns a 3x3 matrix which is the combination of them all. - -[call [cmd affine2d::rotation_from_angle] [arg "theta"] [opt [arg "units"]]] -Computes a 2d affine rotation (a 3x3 matrix) from an angle [arg theta]. -[para] -Valid units r - radians (2pi = one turn), g - gradian (400 = one turn), d - degree (360 = 1 turn) - -[call [cmd affine2d::rotation_from_normal] [arg "normalx"] [arg "normaly"]] -Computes a 2d affine rotation (a 3x3 matrix) from a directional normal, given -my %of travel in X and Y. - - - -[list_end] -[section "REFERENCES"] - - -[section AUTHORS] -Sean Woods - -[vset CATEGORY tao] -[include scripts/feedback.inc] - -[manpage_end] DELETED cmodules/math/cthulhu.ini Index: cmodules/math/cthulhu.ini ================================================================== --- cmodules/math/cthulhu.ini +++ /dev/null @@ -1,4 +0,0 @@ -set here [file dirname [file normalize [info script]]] -::cthulhu::add_directory [file join $here generic] { -build-ignore-cfiles quaternion.c -} DELETED cmodules/math/generic/affine2d.c Index: cmodules/math/generic/affine2d.c ================================================================== --- cmodules/math/generic/affine2d.c +++ /dev/null @@ -1,157 +0,0 @@ -#include "odieInt.h" - -static int affine2d_method_apply ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - Tcl_Obj *pResult=Tcl_NewObj(); - int i; - double matA[6] = {0.0,0.0,0.0,0.0,0.0,0.0}; - - if( objc < 4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "matrix x1 y1 ?x2 y2?..."); - return TCL_ERROR; - } - for(i=0;i<6;i++) { - Tcl_Obj *temp; - if(Tcl_ListObjIndex(interp, objv[1], i, &temp)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,temp,&matA[i])) return TCL_ERROR; - } - - for(i=2;ifullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - return TCL_OK; -} DELETED cmodules/math/generic/affine3d.c Index: cmodules/math/generic/affine3d.c ================================================================== --- cmodules/math/generic/affine3d.c +++ /dev/null @@ -1,359 +0,0 @@ -#include "odieInt.h" - -void affine_Copy(AFFINE A,AFFINE B) -{ - int i,j; - for(i=0;i<4;i++) - for(j=0;j<4;j++) - B[i][j]=A[i][j]; -} - -/* - * Affine Operations - * Must be performed on a 4x4 matrix - */ - -void affine_ZeroMatrix(AFFINE A) -{ - register int i,j; - for (i=0;i<4;i++) - for (j=0;j<4;j++) - A[i][j]=0; - -} - -void affine_IdentityMatrix(AFFINE A) -{ - register int i; - - affine_ZeroMatrix(A); - - for (i=0;i<4;i++) - A[i][i]=1; - -} - -void affine_Translate(VECTOR A,AFFINE B) -{ - affine_IdentityMatrix(B); - B[0][3]=-A[0]; - B[1][3]=-A[1]; - B[2][3]=-A[2]; -} - -void affine_Scale(VECTOR A,AFFINE B) -{ - affine_ZeroMatrix(B); - B[0][0]=A[X_IDX]; - B[1][1]=A[Y_IDX]; - B[2][2]=A[Z_IDX]; - B[3][3]=1.0; -} - -void affine_RotateX(SCALER angle,AFFINE A) -{ - double c,s; - c=cos(angle); - s=sin(angle); - - affine_ZeroMatrix(A); - - A[0][0]=1.0; - A[3][3]=1.0; - - A[1][1]=c; - A[2][2]=c; - A[1][2]=s; - A[2][1]=0.0-s; -} - -void affine_RotateY(SCALER angle,AFFINE A) -{ - double c,s; - c=cos(angle); - s=sin(angle); - - affine_ZeroMatrix(A); - - A[1][1]=1.0; - A[3][3]=1.0; - - A[0][0]=c; - A[2][2]=c; - A[0][2]=0.0-s; - A[2][0]=s; -} - - -void affine_RotateZ(SCALER angle,AFFINE A) -{ - double c,s; - c=cos(angle); - s=sin(angle); - - affine_ZeroMatrix(A); - - A[2][2]=1.0; - A[3][3]=1.0; - - A[0][0]=c; - A[1][1]=c; - A[0][1]=s; - A[1][0]=0.0-s; - -} - - -void affine_Multiply(AFFINE A,AFFINE B,AFFINE R) -{ - int i,j,k; - AFFINE temp_matrix; - for (i=0;i<4;i++) - { - for (j=0;j<4;j++) - { - temp_matrix[i][j]=0.0; - for (k=0;k<4;k++) temp_matrix[i][j]+=A[i][k]*B[k][j]; - } - } - affine_Copy(temp_matrix,R); -} - - -void affine_Rotate(VECTOR rotate,AFFINE R) -{ - AFFINE OP; - - affine_RotateX(rotate[X_IDX],R); - affine_RotateY(rotate[Y_IDX],OP); - - affine_Multiply(OP,R,R); - affine_RotateZ(rotate[Z_IDX],OP); - affine_Multiply(OP,R,R); - -} - -void affine_ComputeTransform(VECTOR trans,VECTOR rotate,AFFINE R) -{ - AFFINE M1,M2,M3,M4,M5,M6,M7,M8,M9; - //VECTOR scale = {1.0, 1.0, 1.0}; - //affine_Scale(scale,M1); - - affine_IdentityMatrix(M1); - - affine_RotateX(rotate[X_IDX],M2); - affine_RotateY(rotate[Y_IDX],M3); - affine_RotateZ(rotate[Z_IDX],M4); - affine_Translate(trans,M5); - - affine_Multiply(M2,M1,M6); - affine_Multiply(M3,M6,M7); - affine_Multiply(M4,M7,M8); - affine_Multiply(M5,M8,M9); - affine_Copy(M9,R); -} - -int affine_Inverse(AFFINE r, AFFINE m) -{ - double d00, d01, d02, d03; - double d10, d11, d12, d13; - double d20, d21, d22, d23; - double d30, d31, d32, d33; - double m00, m01, m02, m03; - double m10, m11, m12, m13; - double m20, m21, m22, m23; - double m30, m31, m32, m33; - double D; - - m00 = m[0][0]; m01 = m[0][1]; m02 = m[0][2]; m03 = m[0][3]; - m10 = m[1][0]; m11 = m[1][1]; m12 = m[1][2]; m13 = m[1][3]; - m20 = m[2][0]; m21 = m[2][1]; m22 = m[2][2]; m23 = m[2][3]; - m30 = m[3][0]; m31 = m[3][1]; m32 = m[3][2]; m33 = m[3][3]; - - d00 = m11*m22*m33 + m12*m23*m31 + m13*m21*m32 - m31*m22*m13 - m32*m23*m11 - m33*m21*m12; - d01 = m10*m22*m33 + m12*m23*m30 + m13*m20*m32 - m30*m22*m13 - m32*m23*m10 - m33*m20*m12; - d02 = m10*m21*m33 + m11*m23*m30 + m13*m20*m31 - m30*m21*m13 - m31*m23*m10 - m33*m20*m11; - d03 = m10*m21*m32 + m11*m22*m30 + m12*m20*m31 - m30*m21*m12 - m31*m22*m10 - m32*m20*m11; - - d10 = m01*m22*m33 + m02*m23*m31 + m03*m21*m32 - m31*m22*m03 - m32*m23*m01 - m33*m21*m02; - d11 = m00*m22*m33 + m02*m23*m30 + m03*m20*m32 - m30*m22*m03 - m32*m23*m00 - m33*m20*m02; - d12 = m00*m21*m33 + m01*m23*m30 + m03*m20*m31 - m30*m21*m03 - m31*m23*m00 - m33*m20*m01; - d13 = m00*m21*m32 + m01*m22*m30 + m02*m20*m31 - m30*m21*m02 - m31*m22*m00 - m32*m20*m01; - - d20 = m01*m12*m33 + m02*m13*m31 + m03*m11*m32 - m31*m12*m03 - m32*m13*m01 - m33*m11*m02; - d21 = m00*m12*m33 + m02*m13*m30 + m03*m10*m32 - m30*m12*m03 - m32*m13*m00 - m33*m10*m02; - d22 = m00*m11*m33 + m01*m13*m30 + m03*m10*m31 - m30*m11*m03 - m31*m13*m00 - m33*m10*m01; - d23 = m00*m11*m32 + m01*m12*m30 + m02*m10*m31 - m30*m11*m02 - m31*m12*m00 - m32*m10*m01; - - d30 = m01*m12*m23 + m02*m13*m21 + m03*m11*m22 - m21*m12*m03 - m22*m13*m01 - m23*m11*m02; - d31 = m00*m12*m23 + m02*m13*m20 + m03*m10*m22 - m20*m12*m03 - m22*m13*m00 - m23*m10*m02; - d32 = m00*m11*m23 + m01*m13*m20 + m03*m10*m21 - m20*m11*m03 - m21*m13*m00 - m23*m10*m01; - d33 = m00*m11*m22 + m01*m12*m20 + m02*m10*m21 - m20*m11*m02 - m21*m12*m00 - m22*m10*m01; - - D = m00*d00 - m01*d01 + m02*d02 - m03*d03; - - - if (D == 0.0) - { - /* MatStack_Error("Singular matrix in MInvers."); */ - return TCL_ERROR; - } - - r[0][0] = d00/D; r[0][1] = -d10/D; r[0][2] = d20/D; r[0][3] = -d30/D; - r[1][0] = -d01/D; r[1][1] = d11/D; r[1][2] = -d21/D; r[1][3] = d31/D; - r[2][0] = d02/D; r[2][1] = -d12/D; r[2][2] = d22/D; r[2][3] = -d32/D; - r[3][0] = -d03/D; r[3][1] = d13/D; r[3][2] = -d23/D; r[3][3] = d33/D; - return TCL_OK; -} - -/* -** description: Pushes an affine identity matrix onto the stack -*/ -static int affine3d_method_identity ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *C; - C=Matrix_NewObj(); - - Matrix_Alloc(C,MATFORM_affine); - affine_IdentityMatrix(C->matrix); - Matrix_Dump(C); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -/* -** description: -** Multiply 2 4x4 matrices. Used to combine 2 affine transformations. -** Note: Some affine transformations need to be performed in a particular -** order to make sense. -*/ -static int affine3d_method_multiply ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_affine); - if(!B) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_affine); - affine_Multiply(A->matrix,B->matrix,C->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -/* -** description: -** Convert a rotation vector (X Y Z) into an affine transformation -*/ -static int affine3d_method_from_euler ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*C; - int i; - int size_a; - int size_b; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "EULER" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler); - if(!A) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_affine); - affine_Rotate(A->matrix,C->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -/* -** description: -** Convert a scale vector (X Y Z) into an affine transformation -*/ -static int affine3d_method_scale ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*C; - int i; - int size_a; - int size_b; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_affine); - affine_Scale(A->matrix,C->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -/* -** description: -** Convert a displacement vector (X Y Z) into an affine transformation -*/ -static int affine3d_method_translation ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*C; - int i; - int size_a; - int size_b; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "VECTORXYZ" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_affine); - affine_Translate(A->matrix,C->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -DLLEXPORT int Affine3d_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - modPtr=Tcl_FindNamespace(interp,"affine3d",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "affine3d", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::affine3d::from_euler",(Tcl_ObjCmdProc *)affine3d_method_from_euler,NULL,NULL); - Tcl_CreateObjCommand(interp,"::affine3d::identity",(Tcl_ObjCmdProc *)affine3d_method_identity,NULL,NULL); - Tcl_CreateObjCommand(interp,"::affine3d::multiply",(Tcl_ObjCmdProc *)affine3d_method_multiply,NULL,NULL); - Tcl_CreateObjCommand(interp,"::affine3d::scale",(Tcl_ObjCmdProc *)affine3d_method_scale,NULL,NULL); - Tcl_CreateObjCommand(interp,"::affine3d::translation",(Tcl_ObjCmdProc *)affine3d_method_translation,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - return TCL_OK; -} DELETED cmodules/math/generic/cmatrix.c Index: cmodules/math/generic/cmatrix.c ================================================================== --- cmodules/math/generic/cmatrix.c +++ /dev/null @@ -1,122 +0,0 @@ -#include "odieInt.h" - - - -void vector_Scale(VECTOR A,SCALER S) -{ - A[X_IDX]*=S; - A[Y_IDX]*=S; - A[Z_IDX]*=S; -} - -void odiemath_cartesian_to_spherical(VECTOR A,VECTOR R) -{ - double S; - /* Work with a copy in case we are writing back to the same pointer */ - double radius,theta,phi; - radius=odiemath_vectorxyz_length(A); - S=sqrt(A[X_IDX]*A[X_IDX]+A[Y_IDX]*A[Y_IDX]); - if (A[X_IDX] > 0.0) { - theta =asin(A[Y_IDX]/S); - } else { - theta =M_PI - asin(A[Y_IDX]/S); - } - phi =asin(A[Z_IDX]/R[RADIUS]); - - R[RADIUS]=radius; - R[THETA]=theta; - R[PHI]=phi; -} - - -void odiemath_spherical_to_cartesian(VECTOR A,VECTOR R) -{ - /* - ** Make a copy of the input matrix in case we are outputing back - ** to the same pointer - */ - double radius,theta,phi; - radius=A[RADIUS]; - theta=A[THETA]; - phi=A[PHI]; - R[X_IDX]=radius*cos(theta)*cos(phi); - R[Y_IDX]=radius*sin(theta)*cos(phi); - R[Z_IDX]=radius*sin(phi); -} - -void odiemath_cylindrical_to_cartesian(VECTOR A,VECTOR R) -{ - /* - ** Make a copy of the input matrix in case we are outputing back - ** to the same pointer - */ - double radius,theta,z; - radius=A[RADIUS]; - theta=A[THETA]; - z=A[Z_IDX]; - R[X_IDX]=radius*cos(theta); - R[Y_IDX]=radius*sin(theta); - R[Z_IDX]=z; -} - -void odiemath_cartesian_to_cylindrical(VECTOR A,VECTOR R) -{ - /* - ** Make a copy of the input matrix in case we are outputing back - ** to the same pointer - */ - double x,y,z; - x=A[X_IDX]; - y=A[Y_IDX]; - z=A[Z_IDX]; - R[RADIUS]=sqrt(x*x + y*y); - R[THETA] =atan2(y,x); - R[Z_IDX] =z; -} - -void odiemath_polar_to_vec2(VECTORXY A,VECTORXY R) { - /* - ** Make a copy of the input matrix in case we are outputing back - ** to the same pointer - */ - double radius,theta; - radius=A[RADIUS]; - theta=A[THETA]; - R[X_IDX]=radius*cos(theta); - R[Y_IDX]=radius*sin(theta); -} - -void odiemath_vec2_to_polar(VECTORXY A,VECTORXY R) -{ - double x,y; - x=A[X_IDX]; - y=A[Y_IDX]; - R[RADIUS]=sqrt(x*x + y*y); - R[THETA] =atan2(y,x); -} - -void Matrix_Dump(MATOBJ *A) -{ - int i,j,idx=0; - //printf("\nRows: %d Cols %d",A->rows,A->cols); - for (i=0;i<4;i++) - { - //printf("\nRow %d:",i); - for (j=0;j<4;j++) - { - //printf(" %f ",*(A->matrix+idx)); - idx++; - } - //printf("\n"); - } - //printf("\n"); -} - -/* - * Tcl List Utilities - */ - - - - - DELETED cmodules/math/generic/cmatrixforms.c Index: cmodules/math/generic/cmatrixforms.c ================================================================== --- cmodules/math/generic/cmatrixforms.c +++ /dev/null @@ -1,460 +0,0 @@ -/* -** This file is automatically generated by the TclVexpr.tcl -** script located in the same directory -*/ - -#include "odieInt.h" - -/* - * Module-Wide Variables - */ - - -const MatrixForm MatrixForms[] = { -{ MATFORM_null, "null", 0 , 0, "A matrix of arbitrary size", NULL }, -{ MATFORM_affine, "affine", 4, 4, "A 4x4 affine matrix", Matrix_To_affine }, -{ MATFORM_cylindrical, "cylindrical", 3, 1, "A 3 dimensional vector: RADIUS THETA Z", Matrix_To_cylindrical }, -{ MATFORM_euler, "euler", 3, 1, "A 3 dimensional rotation: X Y Z", NULL }, -{ MATFORM_heading, "heading", 3, 1, "A 3 dimensional rotation: yaw pitch roll", NULL }, -{ MATFORM_mat2, "mat2", 2, 2, "A 2x2 matrix", NULL }, -{ MATFORM_mat3, "mat3", 3, 3, "A 3x3 matrix", NULL }, -{ MATFORM_mat4, "mat4", 4, 4, "A 4x4 matrix", NULL }, -{ MATFORM_polar, "polar", 2, 1, "A 2 dimensional vector: RADIUS THETA", Matrix_To_cylindrical }, -{ MATFORM_scaler, "scaler", 1, 1, "A scaler (1x1)", NULL }, -{ MATFORM_spherical, "spherical", 3, 1, "A 3 dimensional vector: RADIUS THETA PHI", Matrix_To_cylindrical }, -{ MATFORM_vector_xy, "vector_xy", 2, 1, "A 2 dimensional vector: X Y", Matrix_To_cartesian }, -{ MATFORM_vector_xyz, "vector_xyz", 3, 1, "A 3 dimensional vector: X Y Z", Matrix_To_cartesian }, -{ MATFORM_vector_xyzw, "vector_xyzw", 4, 1, "A 4 dimensional vector: X Y Z W", Matrix_To_cartesian } -}; - -STUB_EXPORT int Odie_Get_AFFINE_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE *ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_affine); - if(!T) return TCL_ERROR; - ptr=T->matrix; - return TCL_OK; -} - -STUB_EXPORT int Odie_Set_AFFINE_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_affine); - if(!T) return TCL_ERROR; - memcpy(ptr,T->matrix,sizeof(AFFINE)); - return TCL_OK; -} - -STUB_EXPORT Tcl_Obj *Odie_New_AFFINE_Obj(AFFINE ptr) { - MATOBJ *C; - Tcl_Obj *result; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_affine); - memcpy(C->matrix,ptr,sizeof(AFFINE)); - result=Matrix_To_TclObj(C); - return result; -} - - -static int matrix_method_to_affine ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_cylindrical ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_cylindrical); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_euler ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_euler); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_heading ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_heading); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_mat2 ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_mat2); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -STUB_EXPORT int Odie_Get_AFFINE3X3_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE3X3 *ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_mat3); - if(!T) return TCL_ERROR; - ptr=T->matrix; - return TCL_OK; -} - -STUB_EXPORT int Odie_Set_AFFINE3X3_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,AFFINE3X3 ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_mat3); - if(!T) return TCL_ERROR; - memcpy(ptr,T->matrix,sizeof(AFFINE3X3)); - return TCL_OK; -} - -STUB_EXPORT Tcl_Obj *Odie_New_AFFINE3X3_Obj(AFFINE3X3 ptr) { - MATOBJ *C; - Tcl_Obj *result; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_mat3); - memcpy(C->matrix,ptr,sizeof(AFFINE3X3)); - result=Matrix_To_TclObj(C); - return result; -} - - -static int matrix_method_to_mat3 ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_mat3); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_mat4 ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_mat4); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_null ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_polar ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_polar); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_scaler ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_scaler); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_spherical ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_spherical); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -STUB_EXPORT int Odie_Get_VECTORXY_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VECTORXY *ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xy); - if(!T) return TCL_ERROR; - ptr=T->matrix; - return TCL_OK; -} - -STUB_EXPORT int Odie_Set_VECTORXY_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VECTORXY ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xy); - if(!T) return TCL_ERROR; - memcpy(ptr,T->matrix,sizeof(VECTORXY)); - return TCL_OK; -} - -STUB_EXPORT Tcl_Obj *Odie_New_VECTORXY_Obj(VECTORXY ptr) { - MATOBJ *C; - Tcl_Obj *result; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vector_xy); - memcpy(C->matrix,ptr,sizeof(VECTORXY)); - result=Matrix_To_TclObj(C); - return result; -} - - -static int matrix_method_to_vector_xy ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vector_xy); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -STUB_EXPORT int Odie_Get_VECTORXYZ_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VECTORXYZ *ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xyz); - if(!T) return TCL_ERROR; - ptr=T->matrix; - return TCL_OK; -} - -STUB_EXPORT int Odie_Set_VECTORXYZ_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,VECTORXYZ ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_vector_xyz); - if(!T) return TCL_ERROR; - memcpy(ptr,T->matrix,sizeof(VECTORXYZ)); - return TCL_OK; -} - -STUB_EXPORT Tcl_Obj *Odie_New_VECTORXYZ_Obj(VECTORXYZ ptr) { - MATOBJ *C; - Tcl_Obj *result; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vector_xyz); - memcpy(C->matrix,ptr,sizeof(VECTORXYZ)); - result=Matrix_To_TclObj(C); - return result; -} - - -static int matrix_method_to_vector_xyz ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vector_xyz); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int matrix_method_to_vector_xyzw ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vector_xyzw); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - -DLLEXPORT int Odie_MatrixForms_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - - modPtr=Tcl_FindNamespace(interp,"matrix",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "matrix", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::matrix::to_affine",(Tcl_ObjCmdProc *)matrix_method_to_affine,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_cylindrical",(Tcl_ObjCmdProc *)matrix_method_to_cylindrical,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_euler",(Tcl_ObjCmdProc *)matrix_method_to_euler,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_heading",(Tcl_ObjCmdProc *)matrix_method_to_heading,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_mat2",(Tcl_ObjCmdProc *)matrix_method_to_mat2,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_mat3",(Tcl_ObjCmdProc *)matrix_method_to_mat3,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_mat4",(Tcl_ObjCmdProc *)matrix_method_to_mat4,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_null",(Tcl_ObjCmdProc *)matrix_method_to_null,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_polar",(Tcl_ObjCmdProc *)matrix_method_to_polar,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_scaler",(Tcl_ObjCmdProc *)matrix_method_to_scaler,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_spherical",(Tcl_ObjCmdProc *)matrix_method_to_spherical,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_vector_xy",(Tcl_ObjCmdProc *)matrix_method_to_vector_xy,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_vector_xyz",(Tcl_ObjCmdProc *)matrix_method_to_vector_xyz,NULL,NULL); - Tcl_CreateObjCommand(interp,"::matrix::to_vector_xyzw",(Tcl_ObjCmdProc *)matrix_method_to_vector_xyzw,NULL,NULL); - Tcl_Obj *varname=Tcl_NewStringObj("math_const",-1); - Tcl_IncrRefCount(varname); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_x_pi",-1),Tcl_NewDoubleObj(M_2_X_PI),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_180",-1),Tcl_NewDoubleObj(M_PI_180),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_360",-1),Tcl_NewDoubleObj(M_PI_360),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_e",-1),Tcl_NewDoubleObj(M_E),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_log2e",-1),Tcl_NewDoubleObj(M_LOG2E),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_log10e",-1),Tcl_NewDoubleObj(M_LOG10E),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_ln2",-1),Tcl_NewDoubleObj(M_LN2),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_ln10",-1),Tcl_NewDoubleObj(M_LN10),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi",-1),Tcl_NewDoubleObj(M_PI),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_2",-1),Tcl_NewDoubleObj(M_PI_2),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_pi_4",-1),Tcl_NewDoubleObj(M_PI_4),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_1_pi",-1),Tcl_NewDoubleObj(M_1_PI),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_pi",-1),Tcl_NewDoubleObj(M_2_PI),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_2_sqrtpi",-1),Tcl_NewDoubleObj(M_2_SQRTPI),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt2",-1),Tcl_NewDoubleObj(M_SQRT2),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt1_2",-1),Tcl_NewDoubleObj(M_SQRT1_2),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt3",-1),Tcl_NewDoubleObj(M_SQRT3),TCL_GLOBAL_ONLY); - Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("m_sqrt3_2",-1),Tcl_NewDoubleObj(M_SQRT3_2),TCL_GLOBAL_ONLY); -Tcl_DecrRefCount(varname); - - return TCL_OK; -} - DELETED cmodules/math/generic/cmatrixforms.h Index: cmodules/math/generic/cmatrixforms.h ================================================================== --- cmodules/math/generic/cmatrixforms.h +++ /dev/null @@ -1,154 +0,0 @@ -/* -** This file is automatically generated by the cmatrixforms.tcl -** script located in the same directory -*/ - -/* Constants */ - -#ifndef M_2_X_PI -#define M_2_X_PI 6.283185307179586476925286766560 /* 2 * PI */ -#endif -#ifndef M_PI_180 -#define M_PI_180 0.01745329251994329576 /* pi / 180 */ -#endif -#ifndef M_PI_360 -#define M_PI_360 0.00872664625997164788 /* pi / 360 */ -#endif -#ifndef M_E -#define M_E 2.71828182845904523536028747135266250 /* e */ -#endif -#ifndef M_LOG2E -#define M_LOG2E 1.44269504088896340735992468100189214 /* log2(e) */ -#endif -#ifndef M_LOG10E -#define M_LOG10E 0.434294481903251827651128918916605082 /* log10(e) */ -#endif -#ifndef M_LN2 -#define M_LN2 0.693147180559945309417232121458176568 /* loge(2) */ -#endif -#ifndef M_LN10 -#define M_LN10 2.30258509299404568401799145468436421 /* loge(10) */ -#endif -#ifndef M_PI -#define M_PI 3.14159265358979323846264338327950288 /* pi */ -#endif -#ifndef M_PI_2 -#define M_PI_2 1.57079632679489661923132169163975144 /* pi/2 */ -#endif -#ifndef M_PI_4 -#define M_PI_4 0.785398163397448309615660845819875721 /* pi/4 */ -#endif -#ifndef M_1_PI -#define M_1_PI 0.318309886183790671537767526745028724 /* 1/pi */ -#endif -#ifndef M_2_PI -#define M_2_PI 0.636619772367581343075535053490057448 /* 2/pi */ -#endif -#ifndef M_2_SQRTPI -#define M_2_SQRTPI 1.12837916709551257389615890312154517 /* 2/sqrt(pi) */ -#endif -#ifndef M_SQRT2 -#define M_SQRT2 1.41421356237309504880168872420969808 /* sqrt(2) */ -#endif -#ifndef M_SQRT1_2 -#define M_SQRT1_2 0.707106781186547524400844362104849039 /* 1/sqrt(2) */ -#endif -#ifndef M_SQRT3 -#define M_SQRT3 1.7320508075688772935 /* */ -#endif -#ifndef M_SQRT3_2 -#define M_SQRT3_2 0.8660254037844387 /* */ -#endif - -/* Vector array elements. */ -#define U 0 -#define V 1 - -#define iX 0 -#define jY 1 -#define kZ 2 -#define W 3 - -#define VX(X) { *(X+0) } -#define VY(X) { *(X+1) } -#define VZ(X) { *(X+2) } - -#define RADIUS 0 -#define THETA 1 -#define PHI 2 - -/* - * Macros - */ - -#define CosD(A) { cos(A * M_PI_180); } -#define SinD(A) { sin(A * M_PI_180); } - -/* - * Structures and Datatypes - */ - -typedef double AFFINE[4][4]; -typedef double AFFINE3X3[3][3]; -typedef double cartesian[4]; -typedef double MATRIX3x3[3][3]; -typedef double SCALER; -typedef double vec2[2]; -typedef double vec3[3]; -typedef double vec4[4]; -typedef double VECTOR[3]; -typedef double VECTORXY[2]; -typedef double VectorXY[2]; -typedef double VECTORXYZ[3]; -typedef double VectorXYZ[3]; - -typedef struct VexprMatrix { - int refCount; - char rows; - char cols; - char form; - char units; - double *matrix; -} MATOBJ; - -typedef struct MatrixForm { - int id; - const char *name; - int rows; - int cols; - const char *description; - const char *(*xConvertToForm)(MATOBJ*,int form); -} MatrixForm; - -#define MATFORM_null 0 -#define MATFORM_affine 1 -#define MATFORM_cylindrical 2 -#define MATFORM_euler 3 -#define MATFORM_heading 4 -#define MATFORM_mat2 5 -#define MATFORM_mat3 6 -#define MATFORM_matrix3x3 6 -#define MATFORM_mat4 7 -#define MATFORM_polar 8 -#define MATFORM_scaler 9 -#define MATFORM_spherical 10 -#define MATFORM_vector_xy 11 -#define MATFORM_vectorxy 11 -#define MATFORM_vec2 11 -#define MATFORM_vector_xyz 12 -#define MATFORM_vector 12 -#define MATFORM_vec3 12 -#define MATFORM_vectorxyz 12 -#define MATFORM_vector_xyzw 13 -#define MATFORM_vec4 13 -#define MATFORM_cartesian 13 - -/* Module wide constants */ -extern const Tcl_ObjType matrix_tclobjtype; -extern const MatrixForm MatrixForms[]; - -extern const Tcl_ObjType *tclListType; -extern const Tcl_ObjType *tclDoubleType; -extern const Tcl_ObjType *NumArrayType; -extern const Tcl_ObjType *odieMatrixType; - DELETED cmodules/math/generic/cmatrixforms.tcl Index: cmodules/math/generic/cmatrixforms.tcl ================================================================== --- cmodules/math/generic/cmatrixforms.tcl +++ /dev/null @@ -1,606 +0,0 @@ -### -# This file contains the definitions and documentation -# for the vexpr opcodes. To add a new opcode, run this -# script and recompile tclVexpr.c -# -# It need only be called if the developer wishes to add -# a new opcode -### - -set ::constants { - 2_X_PI 6.283185307179586476925286766560 { 2 * PI } - PI_180 0.01745329251994329576 { pi / 180 } - PI_360 0.00872664625997164788 { pi / 360 } - E 2.71828182845904523536028747135266250 { e } - LOG2E 1.44269504088896340735992468100189214 { log2(e) } - LOG10E 0.434294481903251827651128918916605082 { log10(e) } - LN2 0.693147180559945309417232121458176568 { loge(2) } - LN10 2.30258509299404568401799145468436421 { loge(10) } - PI 3.14159265358979323846264338327950288 { pi } - PI_2 1.57079632679489661923132169163975144 { pi/2 } - PI_4 0.785398163397448309615660845819875721 { pi/4 } - 1_PI 0.318309886183790671537767526745028724 { 1/pi } - 2_PI 0.636619772367581343075535053490057448 { 2/pi } - 2_SQRTPI 1.12837916709551257389615890312154517 { 2/sqrt(pi) } - SQRT2 1.41421356237309504880168872420969808 { sqrt(2) } - SQRT1_2 0.707106781186547524400844362104849039 { 1/sqrt(2) } - SQRT3 1.7320508075688772935 - SQRT3_2 0.8660254037844387 -} - -set path [file dirname [file normalize [info script]]] -#package require dict - -proc vexpr_argtype_enum name { - return vexpr_arg_[string map {+ plus - minus * star . dot} $name] -} - -proc vexpr_argtype_typedef {name info} { - dict with info {} - if { $rows eq "*"} { - return "double *$name\;" - } - if { $cols eq 1 } { - if { $rows eq 1 } { - return "double $name\;" - } else { - return "double $name\[$rows\]\;" - } - } else { - return "double $name\[$cols\]\[$rows\]\;" - } -} - -proc vexpr_argtype {name info} { - global argtype_cname argtype_aliases argtype_body argtype_info argtype_enum - set argtype_cname($name) $name - set argtype_enum($name) [vexpr_argtype_enum $name] - set argtype_info($name) { - aliases {} - typedef {} - cname {} - rows 1 - cols 1 - description {} - function-convert NULL - opcode {} - } - #dict set argtype_info($name) cname matrix_tclobjtype_$name - foreach {field value} $info { - dict set argtype_info($name) $field $value - switch $field { - aliases { - foreach v $value { - set argtype_cname($v) $name - set argtype_enum($v) [vexpr_argtype_enum $v] - lappend argtype_aliases($name) $v - } - } - } - } - dict with argtype_info($name) {} -} - -vexpr_argtype null { - aliases {} - rows * - cols * - description {A matrix of arbitrary size} - function-convert NULL -} - -vexpr_argtype scaler { - aliases {SCALER} - rows 1 - cols 1 - description {A scaler (1x1)} -} -vexpr_argtype mat2 { - aliases {} - rows 2 - cols 2 - description {A 2x2 matrix} -} -vexpr_argtype mat3 { - aliases {MATRIX3x3} - typedef AFFINE3X3 - rows 3 - cols 3 - description {A 3x3 matrix} -} -vexpr_argtype mat4 { - aliases {} - rows 4 - cols 4 - description {A 4x4 matrix} -} -vexpr_argtype affine { - aliases {AFFINE} - typedef AFFINE - rows 4 - cols 4 - opcode to_affine - description {A 4x4 affine matrix} - function-convert Matrix_To_affine -} -vexpr_argtype cylindrical { - aliases {} - forms {} - rows 3 - cols 1 - units radians - opcode to_cylindrical - description {A 3 dimensional vector: RADIUS THETA Z} - function-convert Matrix_To_cylindrical -} -#vexpr_argtype cylindrical_degrees { -# aliases {} -# forms {} -# rows 3 -# cols 1 -# units degrees -# description {A 3 dimensional vector: RADIUS THETA Z, with theta in degrees} -# function-convert Matrix_To_cylindrical -#} -#vexpr_argtype dual_quaternion { -# aliases {dquat} -# forms {} -# opcode to_dual_quaternion -# typedef {DualQuat dquat;} -# description {A dual quaternion} -#} -vexpr_argtype euler { - aliases {} - forms {} - rows 3 - cols 1 - units radians - description {A 3 dimensional rotation: X Y Z} -} -vexpr_argtype heading { - aliases {} - forms {} - rows 3 - cols 1 - units degrees - description {A 3 dimensional rotation: yaw pitch roll} -} -vexpr_argtype polar { - aliases {} - rows 2 - cols 1 - opcode to_polar - units radians - description {A 2 dimensional vector: RADIUS THETA} - function-convert Matrix_To_cylindrical -} -#vexpr_argtype polar_degrees { -# aliases {} -# rows 2 -# cols 1 -# units degrees -# description {A 2 dimensional vector: RADIUS THETA, theta in degrees} -# function-convert Matrix_To_cylindrical -#} -#vexpr_argtype quaternion { -# aliases {QUATERNION} -# typedef QUATERNION -# forms {} -# rows 4 -# cols 1 -# opcode to_quaternion -# description {A quaternion: W X Y Z} -# function-convert Matrix_To_quaternion -#} - -vexpr_argtype spherical { - aliases {} - forms {} - rows 3 - cols 1 - opcode to_spherical - units radians - description {A 3 dimensional vector: RADIUS THETA PHI} - function-convert Matrix_To_cylindrical -} -#vexpr_argtype spherical_degrees { -# aliases {} -# forms {} -# rows 3 -# cols 1 -# units degrees -# description {A 3 dimensional vector: RADIUS THETA PHI, with THETA and PHI in degrees} -# function-convert Matrix_To_cylindrical -#} -#vexpr_argtype unit_quaternion { -# aliases {} -# forms {} -# rows 4 -# cols 1 -# opcode to_unit_quaternion -# description {A Unit quaternion: W X Y Z} -# function-convert Matrix_To_quaternion -#} -vexpr_argtype vector_xy { - aliases {VECTORXY vec2 VectorXY} - typedef VECTORXY - rows 2 - cols 1 - units meters - opcode to_vector_xy - description {A 2 dimensional vector: X Y} - function-convert Matrix_To_cartesian -} -vexpr_argtype vector_xyz { - aliases {VECTOR vec3 VectorXYZ} - typedef VECTORXYZ - forms {} - rows 3 - cols 1 - units meters - opcode to_cartesian - description {A 3 dimensional vector: X Y Z} - function-convert Matrix_To_cartesian -} -vexpr_argtype vector_xyzw { - aliases {vec4 cartesian} - forms {} - rows 4 - cols 1 - units meters - description {A 4 dimensional vector: X Y Z W} - function-convert Matrix_To_cartesian -} - -### -# With documentation in hand, lets start writing files -### - -### -# Generate the manpage -### -#set manout [open [file join $path .. doc vexpr.n] w] -#puts $manout " -#.\\\" -#.\\\" Copyright (c) 2014 Sean Woods -#.\\\" -#.\\\" See the file \"license.terms\" for information on usage and redistribution -#.\\\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. -#.\\\" -#.so man.macros -#.TH vexpr n 8.7 Tcl \"Tcl Built-In Commands\" -#.BS -#.\\\" Note: do not modify the .SH NAME line immediately below! -#.SH NAME -#vexpr \\- Vector Expression Evaluator -#.SH SYNOPSIS -#\\fBvexpr \\fIarg arg opcode \\fR?\\fIarg opcode...?\\fR -#.BE -#.SH DESCRIPTION -#.PP -#Performs one of several vector operations, depending on the \\fIopcode\\fR. -#Opcodes and arguments are evaluated using reverse-polish notation. -#. -#Example: -#.CS -#\\fBvexpr {1 1 1} {2 2 2} +\\fR -#.CE -#.PP -#Will return \\fB\\{3.0 3.0 3.0}\\fR. -#.PP -#.RE -#The legal \\fIopcode\\fRs: -#" -#foreach opcode [lsort -dictionary [array names opcode_body]] { -# -# puts $manout .TP -# dict with opcode_info($opcode) {} -# puts $manout "\\fB${opcode}\\fR" -# -# puts $manout ".RS 1" -# if {[llength $arguments]} { -# puts $manout "Usage: \\fI$arguments\\fR \\fB${opcode}\\fR" -# } else { -# puts $manout "Usage: \\fB${opcode}\\fR" -# } -# puts $manout .RE -# if { $aliases ne {} } { -# puts $manout ".RS 1" -# puts $manout "Aliases: $aliases" -# puts $manout .RE -# } -# puts $manout ".RS 1" -# if { $result eq {} } { -# puts $manout "Result: (None)" -# } else { -# puts $manout "Result: $result" -# } -# puts $manout .RE -# puts $manout .PP -# puts $manout ".RS 1" -# puts $manout "$description" -# puts $manout .RE -#} -# -#puts $manout { -#.SH "SEE ALSO" -#expr(n) -#.SH KEYWORDS -#vector -#} -#close $manout - -### -# Generate the "cmatrix.h" file -### -set hout [open [file join $path cmatrixforms.h] w] -fconfigure $hout -translation crlf -::cthulhu::add_cheader [file join $path cmatrixforms.h] - -puts $hout {/* -** This file is automatically generated by the cmatrixforms.tcl -** script located in the same directory -*/ - -/* Constants */ -} - -foreach line [split $constants \n] { - if {[string trim $line] eq {}} continue - set const M_[lindex $line 0] - set value [lindex $line 1] - set comment [string trim [lindex $line 2]] - puts $hout "#ifndef $const -#define $const $value /* $comment */ -#endif" -} - -puts $hout { -/* Vector array elements. */ -#define U 0 -#define V 1 - -#define iX 0 -#define jY 1 -#define kZ 2 -#define W 3 - -#define VX(X) { *(X+0) } -#define VY(X) { *(X+1) } -#define VZ(X) { *(X+2) } - -#define RADIUS 0 -#define THETA 1 -#define PHI 2 - -/* - * Macros - */ - -#define CosD(A) { cos(A * M_PI_180); } -#define SinD(A) { sin(A * M_PI_180); } - -/* - * Structures and Datatypes - */ -} - -foreach {name info} [lsort -stride 2 -dictionary [array get argtype_info]] { - dict with info {} - if {[dict get $info typedef] ne {}} { - set alias [dict get $info typedef] - set typedef_aliases($alias) [vexpr_argtype_typedef $alias $info] - } - foreach alias [dict get $info aliases] { - set typedef_aliases($alias) [vexpr_argtype_typedef $alias $info] - } -} -foreach {alias def} [lsort -stride 2 -dictionary [array get typedef_aliases]] { - puts $hout "typedef $def" -} - -set enum_types {} -puts $hout { -typedef struct VexprMatrix { - int refCount; - char rows; - char cols; - char form; - char units; - double *matrix; -} MATOBJ; - -typedef struct MatrixForm { - int id; - const char *name; - int rows; - int cols; - const char *description; - const char *(*xConvertToForm)(MATOBJ*,int form); -} MatrixForm; -} - -set idx 0 -set enum_types {MATFORM_null 0} -foreach {name info} [lsort -stride 2 -dictionary [array get argtype_info]] { - set ntype MATFORM_[string tolower $name] - if { $ntype in $enum_types } continue - lappend enum_types $ntype [incr idx] - foreach alias [dict get $info aliases] { - set ntype MATFORM_[string tolower $alias] - if { $ntype in $enum_types } continue - lappend enum_types $ntype $idx - } -} - -foreach {type idx} $enum_types { - puts $hout "#define $type $idx" -} - -#typedef struct GenMatrix { -# int rows,cols; -# union { -# double *pointer; -# double cells[16]; -# SCALER scaler; -# VECTOR vector; -# QUATERNION quaternion; -# AFFINE affine; -# }; -#} MATOBJ; - -puts $hout { -/* Module wide constants */ -extern const Tcl_ObjType matrix_tclobjtype; -extern const MatrixForm MatrixForms[]; - -extern const Tcl_ObjType *tclListType; -extern const Tcl_ObjType *tclDoubleType; -extern const Tcl_ObjType *NumArrayType; -extern const Tcl_ObjType *odieMatrixType; -} -close $hout - - - - -### -# Generate the main C source file -### -set fout [open [file join $path cmatrixforms.c] w] -fconfigure $fout -translation crlf -::cthulhu::add_csource [file join $path cmatrixforms.c] -::cthulhu::add_dynamic [file join $path cmatrixforms.c] [info script] - -set tcl_cmds {} - -### -# Add in the start of the file -### -puts $fout {/* -** This file is automatically generated by the TclVexpr.tcl -** script located in the same directory -*/ - -#include "odieInt.h" - -/* - * Module-Wide Variables - */ - -} -puts $fout "const MatrixForm MatrixForms\[\] = \{" -set lines {} -foreach {name info} [lsort -stride 2 -dictionary [array get argtype_info null]] { - set rows {} - dict with info {} - set line "\{ MATFORM_[string tolower $name], \"$name\", " - if {![string is integer $rows] && $rows < 1} { - append line "0 , 0" - } else { - append line "$rows, $cols" - } - append line ", \"$description\", ${function-convert} \}" - lappend lines $line -} -foreach {name info} [lsort -stride 2 -dictionary [array get argtype_info]] { - if { $name eq "null" } continue - set rows {} - dict with info {} - set line "\{ MATFORM_[string tolower $name], \"$name\", " - if {![string is integer $rows] && $rows < 1} { - append line "0 , 0" - } else { - append line "$rows, $cols" - } - append line ", \"$description\", ${function-convert} \}" - lappend lines $line -} -puts $fout [join $lines ",\n"] -puts $fout "\}\;" - -foreach {name info} [lsort -stride 2 -dictionary [array get argtype_info]] { - set rows {} - dict with info {} - if { $typedef ne {} } { - puts $fout [string map [list %form% $name %typedef% $typedef] { -STUB_EXPORT int Odie_Get_%typedef%_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,%typedef% *ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_%form%); - if(!T) return TCL_ERROR; - ptr=T->matrix; - return TCL_OK; -} - -STUB_EXPORT int Odie_Set_%typedef%_FromObj(Tcl_Interp *interp,Tcl_Obj *objPtr,%typedef% ptr) { - MATOBJ *T=Odie_GetMatrixFromTclObj(interp,objPtr,MATFORM_%form%); - if(!T) return TCL_ERROR; - memcpy(ptr,T->matrix,sizeof(%typedef%)); - return TCL_OK; -} - -STUB_EXPORT Tcl_Obj *Odie_New_%typedef%_Obj(%typedef% ptr) { - MATOBJ *C; - Tcl_Obj *result; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_%form%); - memcpy(C->matrix,ptr,sizeof(%typedef%)); - result=Matrix_To_TclObj(C); - return result; -} -}] - } - dict set tcl_cmds matrix to_${name} matrix_method_to_${name} - puts $fout [string map [list %form% $name %typedef% $typedef] { -static int matrix_method_to_%form% ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_%form%); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - }] - -} - -puts $fout "DLLEXPORT int Odie_MatrixForms_Init(Tcl_Interp *interp) \{ - Tcl_Namespace *modPtr; -" -set curnspace {} -foreach {nspace dat} [lsort -stride 2 $tcl_cmds] { - puts $fout [string map [list %nspace% $nspace] { - modPtr=Tcl_FindNamespace(interp,"%nspace%",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "%nspace%", NULL, NULL); - } - }] - foreach {procname cfunct} [lsort -stride 2 $dat] { - puts $fout [format { Tcl_CreateObjCommand(interp,"::%s::%s",(Tcl_ObjCmdProc *)%s,NULL,NULL);} $nspace $procname $cfunct] - } -} -puts $fout { Tcl_Obj *varname=Tcl_NewStringObj("math_const",-1); - Tcl_IncrRefCount(varname);} -foreach line [split $constants \n] { - if {[string trim $line] eq {}} continue - set const M_[lindex $line 0] - set value [lindex $line 1] - set comment [string trim [lindex $line 2]] - puts $fout [format { Tcl_ObjSetVar2(interp,varname,Tcl_NewStringObj("%s",-1),Tcl_NewDoubleObj(%s),TCL_GLOBAL_ONLY);} [string tolower $const] $const] -} -puts $fout "Tcl_DecrRefCount(varname);" -puts $fout " - return TCL_OK; -\} -" -close $fout DELETED cmodules/math/generic/objtypes.c Index: cmodules/math/generic/objtypes.c ================================================================== --- cmodules/math/generic/objtypes.c +++ /dev/null @@ -1,455 +0,0 @@ -#include "odieInt.h" - -/* - * Module-Wide Variables - */ -const Tcl_ObjType *tclListType; -const Tcl_ObjType *tclDoubleType; -const Tcl_ObjType *NumArrayType; -const Tcl_ObjType *odieMatrixType; - -const Tcl_ObjType matrix_tclobjtype = { - "odie_matrix", /* name */ - &MatrixObj_freeIntRepProc, /* freeIntRepProc */ - &MatrixObj_dupIntRepProc, /* dupIntRepProc */ - &MatrixObj_updateStringProc, /* updateStringProc */ - &MatrixObj_setFromAnyProc /* setFromAnyProc */ -}; - -MATOBJ *Odie_GetMatrixFromTclObj(Tcl_Interp *interp,Tcl_Obj *tclObj,int form) { - MATOBJ *result=NULL; - if(MatrixObj_setFromAnyProc(interp,tclObj)) { - return NULL; - } - result=tclObj->internalRep.otherValuePtr; - const char *(*xConvertToForm)(MATOBJ*,int)=MatrixForms[form].xConvertToForm; - if(!xConvertToForm) { - return result; - } - const char *error; - error=xConvertToForm(result,form); - if(error) { - Tcl_SetObjResult(interp,Tcl_NewStringObj(error,-1)); - return NULL; - } - return result; -} - -void Matrix_Copy(MATOBJ *dest,MATOBJ *src) { - int size_t; - dest->cols=src->cols; - dest->rows=src->rows; - dest->form=src->form; - size_t=Matrix_Alloc(dest,src->form); - memcpy(dest->matrix,src->matrix,size_t); -} - -void Matrix_Transfer(MATOBJ *dest,MATOBJ *src) { - dest->rows=src->rows; - dest->cols=src->cols; - dest->form=src->form; - dest->matrix=src->matrix; - src->rows=0; - src->cols=0; - src->form=0; - src->matrix=NULL; -} - -MATOBJ *Matrix_NewObj(void) { - MATOBJ *new=(MATOBJ *)Odie_Alloc(sizeof(MATOBJ)); - memset(new,0,sizeof(MATOBJ)); - return new; -} - -void Matrix_Free(MATOBJ *matrix) { - if(matrix->matrix) { - Odie_Free((char *)matrix->matrix); - } - matrix->rows=0; - matrix->cols=0; - matrix->form=0; - matrix->matrix=NULL; -} - -int Matrix_Alloc(MATOBJ *matrix,int form) { - int rows,cols; - if(form) { - rows=MatrixForms[form].rows; - cols=MatrixForms[form].cols; - matrix->cols=cols; - matrix->rows=rows; - } else { - rows=matrix->rows; - cols=matrix->cols; - } - int size_t=rows*cols*sizeof(double); - matrix->form=form; - matrix->matrix=(double*)Odie_Alloc(size_t); - memset(matrix->matrix,0,size_t); - return size_t; -} - -/* Accept any input */ -const char *Matrix_ToAny(MATOBJ *matrix,int form) { - matrix->form=form; - return NULL; -} - -const char *Matrix_To_affine(MATOBJ *matrix,int form) { - if(matrix->form==MATFORM_affine) { - return NULL; - } - if(matrix->form==MATFORM_euler) { - MATOBJ TEMPMATRIX; - Matrix_Alloc(&TEMPMATRIX,MATFORM_affine); - affine_Rotate(matrix->matrix,TEMPMATRIX.matrix); - Matrix_Free(matrix); - Matrix_Transfer(matrix,&TEMPMATRIX); - return NULL; - } - if(matrix->form==MATFORM_vector_xyz) { - MATOBJ TEMPMATRIX; - Matrix_Alloc(&TEMPMATRIX,MATFORM_affine); - affine_Translate(matrix->matrix,TEMPMATRIX.matrix); - Matrix_Free(matrix); - Matrix_Transfer(matrix,&TEMPMATRIX); - return NULL; - } - if(matrix->rows==4 && matrix->cols==4) { - if(matrix->form==MATFORM_null) { - matrix->form=MATFORM_affine; - } - return NULL; - } - return "Cannot convert to affine"; -} - -const char *Matrix_To_vector_xy(MATOBJ *matrix,int form) { - if(matrix->form==form) { - return TCL_OK; - } - switch(matrix->form) { - case MATFORM_vector_xy: - return TCL_OK; - case MATFORM_vector_xyz: { - return NULL; - } - case MATFORM_cylindrical: { - MATOBJ TEMPMATRIX; - Matrix_Alloc(&TEMPMATRIX,MATFORM_vector_xy); - odiemath_vec2_to_polar(matrix->matrix,TEMPMATRIX.matrix); - Matrix_Free(matrix); - Matrix_Transfer(matrix,&TEMPMATRIX); - return NULL; - } - } - if(form==MATFORM_vector_xyz) { - return "Cannot convert to vector_xy"; - } - if(Matrix_To_cartesian(matrix,MATFORM_vector_xy)) { - return "Cannot convert to vector_xy"; - } - return NULL; -} - -const char *Matrix_To_cartesian(MATOBJ *matrix,int form) { - if(matrix->form==form) { - return TCL_OK; - } - switch(matrix->form) { - case MATFORM_vector_xy: - case MATFORM_vector_xyz: - case MATFORM_vector_xyzw: - break; - case MATFORM_spherical: - { - MATOBJ TEMPMATRIX; - Matrix_Alloc(&TEMPMATRIX,MATFORM_cartesian); - odiemath_spherical_to_cartesian(matrix->matrix,TEMPMATRIX.matrix); - Matrix_Free(matrix); - Matrix_Transfer(matrix,&TEMPMATRIX); - break; - } - case MATFORM_polar: - case MATFORM_cylindrical: { - MATOBJ TEMPMATRIX; - Matrix_Alloc(&TEMPMATRIX,MATFORM_cartesian); - odiemath_cylindrical_to_cartesian(matrix->matrix,TEMPMATRIX.matrix); - Matrix_Free(matrix); - Matrix_Transfer(matrix,&TEMPMATRIX); - break; - } - default: { - if(matrix->rows==1) { - int temp=matrix->cols; - matrix->cols=matrix->rows; - matrix->rows=temp; - } - if(matrix->cols != 1) { - return "Cannot convert to cartesian"; - } - if(matrix->rows<3) { - /* Allocate storage for a 4d cartesian */ - MATOBJ TEMPMATRIX; - int i; - Matrix_Alloc(&TEMPMATRIX,MATFORM_cartesian); - for(i=0;irows && i<4;i++) { - *(TEMPMATRIX.matrix+i)=*(matrix->matrix+i); - } - Matrix_Free(matrix); - Matrix_Transfer(matrix,&TEMPMATRIX); - } - } - } - switch(form) { - case MATFORM_vector_xyz: - matrix->form=form; - matrix->rows=3; - matrix->cols=1; - return NULL; - case MATFORM_vector_xy: - matrix->form=form; - matrix->rows=2; - matrix->cols=1; - return NULL; - } - return NULL; -} - -const char *Matrix_To_cylindrical(MATOBJ *matrix,int form) { - if(matrix->form==form) { - return NULL; - } - switch(matrix->form) { - case MATFORM_polar: - case MATFORM_cylindrical: - case MATFORM_vector_xy: - case MATFORM_vector_xyz: - case MATFORM_vector_xyzw: - break; - default: - if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) { - return "Cannot convert to polar"; - } - } - if(matrix->form==MATFORM_cartesian) { - odiemath_cartesian_to_cylindrical(matrix->matrix,matrix->matrix); - } - switch(form) { - case MATFORM_cylindrical: - matrix->form=form; - matrix->rows=3; - matrix->cols=1; - return NULL; - case MATFORM_polar: - matrix->form=form; - matrix->rows=2; - matrix->cols=1; - return NULL; - } - return NULL; -} - -const char *Matrix_To_spherical(MATOBJ *matrix,int form) { - if(matrix->form==form) { - return NULL; - } - if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) { - return "Cannot convert to spherical"; - } - if(matrix->form==MATFORM_cartesian) { - odiemath_cartesian_to_spherical(matrix->matrix,matrix->matrix); - } - matrix->form=form; - matrix->rows=3; - matrix->cols=1; - return NULL; -} - -const char *Matrix_To_quaternion(MATOBJ *matrix,int form) { - if(matrix->form==form) { - return NULL; - } - if(Matrix_To_cartesian(matrix,MATFORM_cartesian)) { - return "Cannot convert to spherical"; - } - if(matrix->form==MATFORM_cartesian) { - odiemath_cartesian_to_spherical(matrix->matrix,matrix->matrix); - } - matrix->form=form; - matrix->rows=3; - matrix->cols=1; - return NULL; -} - -int TclObj_To_Matrix( - Tcl_Interp *interp, - Tcl_Obj *listPtr, - MATOBJ *matrix -) { - Tcl_Obj **rowPtrs; - Tcl_Obj **elemPtrs; - int result; - int rows,cols; - int idx,i,j; - int len; - - /* Step one, Measure the matrix */ - result = Tcl_ListObjGetElements(interp, listPtr, &rows, &rowPtrs); - if (result != TCL_OK) { - return result; - } - if(rows<1) { - Tcl_AppendResult(interp, "Could not interpret matrix", 0); - return TCL_ERROR; - } - result = Tcl_ListObjGetElements(interp, rowPtrs[0], &cols, &elemPtrs); - if (result != TCL_OK) { - return result; - } - /* - ** For NULL form, we pass the rows and cols - ** via the data structure - */ - matrix->rows=rows; - matrix->cols=cols; - Matrix_Alloc(matrix,MATFORM_null); - idx=-1; - for(i=0;imatrix+idx)=(SCALER)temp; - } - } - return TCL_OK; -} - -Tcl_Obj *Matrix_To_TclObj(MATOBJ *matrix) { - Tcl_Obj *dest=Tcl_NewObj(); - dest->typePtr=&matrix_tclobjtype; - dest->internalRep.otherValuePtr=matrix; - Tcl_InvalidateStringRep(dest); - //Tcl_IncrRefCount(dest); - return dest; -} - -int MatrixObj_setFromAnyProc(Tcl_Interp *interp,Tcl_Obj *objPtr) { - if(objPtr->typePtr) { - if(objPtr->typePtr->setFromAnyProc==&MatrixObj_setFromAnyProc) { - /* - ** Object is already of the type requested - */ - return TCL_OK; - } - } - MATOBJ *matrix=Matrix_NewObj(); - if(TclObj_To_Matrix(interp,objPtr,matrix)) { - Odie_Free((char *)matrix); - return TCL_ERROR; - } - objPtr->internalRep.otherValuePtr=matrix; - objPtr->typePtr=&matrix_tclobjtype; - return TCL_OK; -} - -void MatrixObj_updateStringProc(Tcl_Obj *objPtr) { - char outbuffer[128]; - Tcl_DString result; - MATOBJ *matrix=objPtr->internalRep.otherValuePtr; - int rows,cols; - register int j; - /* Step 1, dimension matrix */ - rows = matrix->rows; - cols = matrix->cols; - Tcl_DStringInit(&result); - if(cols==1) { - /* - * Output single-row matrices (i.e. vectors) - * as a single tcl list (rather than nest them - * as a list within a list) - */ - for(j=0;jmatrix+j)); - Tcl_DStringAppendElement(&result,outbuffer); - } - } else if(rows==1) { - /* - * Output single-row matrices (i.e. vectors) - * as a single tcl list (rather than nest them - * as a list within a list) - */ - for(j=0;jmatrix+j)); - Tcl_DStringAppendElement(&result,outbuffer); - } - } else { - register int i,idx=0; - for(i=0;imatrix+idx)); - Tcl_DStringAppendElement(&result,outbuffer); - } - Tcl_DStringEndSublist(&result); - } - } - objPtr->length=Tcl_DStringLength(&result); - objPtr->bytes=Odie_Alloc(objPtr->length+1); - memcpy(objPtr->bytes,Tcl_DStringValue(&result),objPtr->length); - objPtr->bytes[objPtr->length]='\0'; - Tcl_DStringFree(&result); -} - -void MatrixObj_dupIntRepProc(Tcl_Obj *srcPtr,Tcl_Obj *dupPtr) { - MATOBJ *srcmatrix=srcPtr->internalRep.otherValuePtr; - MATOBJ *dupmatrix=Matrix_NewObj(); - int matsize; - - dupPtr->typePtr=srcPtr->typePtr; - dupPtr->internalRep.otherValuePtr=dupmatrix; - - Matrix_Copy(dupmatrix,srcmatrix); - dupmatrix->rows=srcmatrix->rows; - dupmatrix->cols=srcmatrix->cols; - dupmatrix->form=srcmatrix->form; - matsize=sizeof(double)*dupmatrix->rows*dupmatrix->cols; - if(matsize<1) { - matsize=1; - } - dupmatrix->matrix=(double *)Odie_Alloc(matsize); - memcpy(dupmatrix->matrix,srcmatrix->matrix,matsize); -} - -void MatrixObj_freeIntRepProc(Tcl_Obj *objPtr) { - if(!objPtr->internalRep.otherValuePtr) return; - MATOBJ *matrix=objPtr->internalRep.otherValuePtr; - Matrix_Free(matrix); - Odie_Free((char *)matrix); - objPtr->typePtr=NULL; - objPtr->internalRep.otherValuePtr=NULL; -} - -DLLEXPORT int MatrixObjType_Init(Tcl_Interp *interp) { - - Tcl_RegisterObjType(&matrix_tclobjtype); - tclListType=Tcl_GetObjType("list"); - tclDoubleType=Tcl_GetObjType("double"); - - return TCL_OK; -} - - DELETED cmodules/math/generic/quaternion.c Index: cmodules/math/generic/quaternion.c ================================================================== --- cmodules/math/generic/quaternion.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "odieInt.h" - -/* - * Structures and Datatypes - */ - -typedef struct DualQuat { - float quat[4]; - float trans[4]; - - float scale[4][4]; - float scale_weight; -} DualQuat; - -void mul_qt_qtqt(float q[4], const float q1[4], const float q2[4]) -{ - float t0, t1, t2; - - t0 = q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] - q1[3] * q2[3]; - t1 = q1[0] * q2[1] + q1[1] * q2[0] + q1[2] * q2[3] - q1[3] * q2[2]; - t2 = q1[0] * q2[2] + q1[2] * q2[0] + q1[3] * q2[1] - q1[1] * q2[3]; - q[3] = q1[0] * q2[3] + q1[3] * q2[0] + q1[1] * q2[2] - q1[2] * q2[1]; - q[0] = t0; - q[1] = t1; - q[2] = t2; -} - DELETED cmodules/math/generic/vector.c Index: cmodules/math/generic/vector.c ================================================================== --- cmodules/math/generic/vector.c +++ /dev/null @@ -1,393 +0,0 @@ -#include "odieInt.h" - -static int vector_method_list( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int idx,n; - int size_a; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - return TCL_ERROR; - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - size_a=A->rows*A->cols; - Tcl_Obj **pList=NULL; - - pList=Odie_Alloc(sizeof(Tcl_Obj)*size_a); - for(idx=0;idxmatrix+idx)); - } - Tcl_SetObjResult(interp,Tcl_NewListObj(size_a,pList)); - return TCL_OK; -} - - -static int vector_method_index( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i=-1,j=-1,idx,n=0; - int size_a; - Tcl_Obj **pList=NULL; - - if(objc != 3 && objc != 4) { - Tcl_WrongNumArgs( interp, 1, objv, "A i ?j?" ); - return TCL_ERROR; - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - - if(Tcl_GetIntFromObj(interp,objv[2],&i)) return TCL_ERROR; - size_a=A->rows*A->cols; - - if(i<0) { - i=0; - } - if(i>=size_a) { - i=size_a-1; - } - if(objc==3) { - j==i; - } else{ - if(Tcl_GetIntFromObj(interp,objv[3],&j)) return TCL_ERROR; - } - if ( j < 0 ) { - j=size_a-1; - } else if (j<=i) { - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(*(A->matrix+i))); - return TCL_OK; - } - if(j>=size_a) { - j=size_a-1; - } - n=(j-i)+1; - pList=Odie_Alloc(sizeof(Tcl_Obj)*n); - for(idx=i;idx<=j;idx++) { - pList[idx]=Tcl_NewDoubleObj(*(A->matrix+idx)); - } - Tcl_SetObjResult(interp,Tcl_NewListObj(n,pList)); - return TCL_OK; -} - -static int vector_add( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null); - if(!B) return TCL_ERROR; - - size_a=A->rows*A->cols; - size_b=B->rows*B->cols; - C=Matrix_NewObj(); - if(A->rows==B->rows && A->cols==B->cols) { - C->form=A->form; - C->rows=A->rows; - C->cols=A->cols; - if(A->form!=B->form) { - C->form=MATFORM_null; - } - } else if(A->form==B->form && A->form != MATFORM_null) { - C->form=A->form; - C->rows=A->rows; - C->cols=A->cols; - } else if(size_arows=size_b; - C->cols=1; - C->form=MATFORM_null; - } else { - C->rows=size_a; - C->cols=1; - C->form=MATFORM_null; - } - Matrix_Alloc(C,C->form); - for(i=0;imatrix+i) = *(A->matrix+i) + *(B->matrix+i); - } - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -static int vector_subtract( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null); - if(!B) return TCL_ERROR; - - size_a=A->rows*A->cols; - size_b=B->rows*B->cols; - C=Matrix_NewObj(); - if(A->rows==B->rows && A->cols==B->cols) { - C->form=A->form; - C->rows=A->rows; - C->cols=A->cols; - if(A->form!=B->form) { - C->form=MATFORM_null; - } - } else if(A->form==B->form && A->form != MATFORM_null) { - C->form=A->form; - C->rows=A->rows; - C->cols=A->cols; - } else if(size_arows=size_b; - C->cols=1; - C->form=MATFORM_null; - } else { - C->rows=size_a; - C->cols=1; - C->form=MATFORM_null; - } - Matrix_Alloc(C,C->form); - for(i=0;imatrix+i) = *(A->matrix+i) - *(B->matrix+i); - } - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -static int vector_dot_product ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B; - int i; - int size_a; - int size_b; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_null); - if(!B) return TCL_ERROR; - - size_a=A->rows*A->cols; - size_b=B->rows*B->cols; - double result=0; - for(i=0;imatrix+i) * *(B->matrix+i); - } - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -static int vector_to_matrix ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - int i; - int size_a; - int size_b; - if(objc < 2) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - return TCL_ERROR; - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - -static int vector_scale ( - ClientData dummy, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*C; - double scaler; - int i; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - if(!A) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&scaler)) { - return TCL_ERROR; - } - - C=Matrix_NewObj(); - Matrix_Copy(C,A); - int size_a=A->rows*A->cols; - for(i=0;imatrix+i) *= scaler; - } - - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -static int vector_method_length ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int i,size; - MATOBJ *A; - double result,sum=0.0; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A"); - return TCL_ERROR; - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - size=A->rows*A->cols; - result=0.0; - for(i=1;imatrix+1); - sum+=a*a; - } - result=sqrt(sum); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -static int vector_method_length_squared ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int i,size; - MATOBJ *A; - double result,sum=0.0; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A"); - return TCL_ERROR; - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_null); - size=A->rows*A->cols; - result=0.0; - for(i=1;imatrix+1); - sum+=a*a; - } - result=sum; - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -static int vectorN_method_length ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int i; - double result,sum=0.0; - if( objc<1 ){ - Tcl_WrongNumArgs(interp, 1, objv, "x ?y? ?z? ?...?"); - return TCL_ERROR; - } - result=0.0; - for(i=1;i=objc) { - Tcl_AppendResult(interp, "Odd number of arguments",(char*)0); - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[i+1],&b)) return TCL_ERROR; - dx=b-a; - result=result+dx*dx; - } - result=sqrt(result); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -DLLEXPORT int Odie_Vector_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - modPtr=Tcl_FindNamespace(interp,"vector",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "vector", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::vector::add",(Tcl_ObjCmdProc *)vector_add,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::dot_product",(Tcl_ObjCmdProc *)vector_dot_product,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::length",(Tcl_ObjCmdProc *)vector_method_length,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::length_squared",(Tcl_ObjCmdProc *)vector_method_length_squared,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::scale",(Tcl_ObjCmdProc *)vector_scale,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::subtract",(Tcl_ObjCmdProc *)vector_subtract,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::to_matrix",(Tcl_ObjCmdProc *)vector_to_matrix,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::index",(Tcl_ObjCmdProc *)vector_method_index,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vector::to_list",(Tcl_ObjCmdProc *)vector_method_list,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - modPtr=Tcl_FindNamespace(interp,"vectorN",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "vectorN", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::vectorN::distance",(Tcl_ObjCmdProc *)vectorN_method_distance,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorN::length",(Tcl_ObjCmdProc *)vectorN_method_length,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - - return TCL_OK; -} DELETED cmodules/math/generic/vector2d.c Index: cmodules/math/generic/vector2d.c ================================================================== --- cmodules/math/generic/vector2d.c +++ /dev/null @@ -1,313 +0,0 @@ -#include "odieInt.h" - -/* -** Routines in this file are designed to work with double numbers -** directly. Useful for screen operations where X Y lists are used -*/ - -static int vector2d_method_add( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, P; - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &A[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &A[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &B[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &B[Y_IDX]) ) return TCL_ERROR; - VectorXY_Add(P,A,B); - Tcl_Obj *pResult=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX])); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -static int vector2d_method_subtract( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, P; - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1"); - return TCL_ERROR; - } - printf("vector2d_method_subtract\n"); - if( Tcl_GetDoubleFromObj(interp, objv[1], &A[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &A[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &B[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &B[Y_IDX]) ) return TCL_ERROR; - printf("VectorXY_Subtract\n"); - VectorXY_Subtract(P,A,B); - printf("/VectorXY_Subtract\n"); - Tcl_Obj *pResult=Tcl_NewObj(); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[X_IDX])); - Tcl_ListObjAppendElement(interp,pResult,Tcl_NewDoubleObj(P[Y_IDX])); - Tcl_SetObjResult(interp, pResult); - printf("/vector2d_method_subtract\n"); - return TCL_OK; -} - -static int vector2d_method_angle( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, P; - if( objc!=7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &A[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &A[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &B[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &B[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &P[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &P[Y_IDX]) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_angleOf(A, B, P))); - return TCL_OK; -} - -static int vector2d_method_distance ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double result,ax,ay,bx,by,dx,dy; - if( objc!=5 ){ - Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 x1 y1"); - return TCL_ERROR; - } - result=0.0; - if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&ay)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&bx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&by)) return TCL_ERROR; - dx=bx-ax; - dy=by-ay; - - result=sqrt(dx*dx + dy*dy); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -static int vector2d_method_dotproduct( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, P; - if( objc!=7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &A[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &A[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &B[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &B[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &P[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &P[Y_IDX]) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_dotProduct(A, B, P))); - return TCL_OK; -} - -static int vector2d_method_crossproduct( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, P; - if( objc!=7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &A[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &A[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &B[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &B[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &P[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &P[Y_IDX]) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_crossProduct(A, B, P))); - return TCL_OK; -} - -/* -** tclcmd: triag_test_rightof X0 Y0 X1 Y1 X2 Y2 -** -** A TCL command for testing the rightOf() function. -*/ -static int vector2d_method_rightof( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, P; - if( objc!=7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2"); - return TCL_ERROR; - } - if( Tcl_GetDoubleFromObj(interp, objv[1], &A[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[2], &A[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[3], &B[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[4], &B[Y_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[5], &P[X_IDX]) ) return TCL_ERROR; - if( Tcl_GetDoubleFromObj(interp, objv[6], &P[Y_IDX]) ) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXY_rightOf(A, B, P))); - return TCL_OK; -} - -static int vector2d_method_rotate_and_size ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* - ** Apply Matrices - */ - Tcl_Obj *pResult=Tcl_NewObj(); - int i; - double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0}; - double nx,ny,scalex,scaley,angle; - - if( objc < 7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey x1 y1 ?x2 y2?..."); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR; - - angle=atan2(ny,nx); - matA[0]=cos(angle); - matA[1]=sin(angle); - matA[2]=-sin(angle); - matA[3]=cos(angle); - matA[4]=0.0; - matA[5]=0.0; - - scalex*=0.5; - scaley*=0.5; - for(i=5;ifullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - return TCL_OK; -} DELETED cmodules/math/generic/vector3d.c Index: cmodules/math/generic/vector3d.c ================================================================== --- cmodules/math/generic/vector3d.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "odieInt.h" - -/* -** Routines in this file are designed to work with double numbers -** directly. Useful for screen operations where X Y Z lists are used -*/ - -static int vector3d_method_distance ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - double result,ax,ay,az,bx,by,bz,dx,dy,dz; - if( objc!=7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "x0 y0 z0 x1 y1 z1"); - return TCL_ERROR; - } - result=0.0; - if(Tcl_GetDoubleFromObj(interp,objv[1],&ax)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&ay)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&az)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&bx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[5],&by)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[6],&bz)) return TCL_ERROR; - dx=bx-ax; - dy=by-ay; - dz=bz-az; - - result=sqrt(dx*dx + dy*dy + dz*dz); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -DLLEXPORT int Odie_Vector3d_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - modPtr=Tcl_FindNamespace(interp,"vector3d",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "vector3d", NULL, NULL); - } - - Tcl_CreateObjCommand(interp,"::vector3d::distance",(Tcl_ObjCmdProc *)vector3d_method_distance,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - return TCL_OK; -} DELETED cmodules/math/generic/vectorxy.c Index: cmodules/math/generic/vectorxy.c ================================================================== --- cmodules/math/generic/vectorxy.c +++ /dev/null @@ -1,532 +0,0 @@ -#include "odieInt.h" - -/* -** Routines in this file are designed to work with Tcl_Objs formatted -** as 2d vector structures. -*/ - -CTHULHU_INLINE void VectorXY_Add(VECTORXY C,VECTORXY A,VECTORXY B) { - C[X_IDX]=B[X_IDX]+A[X_IDX]; - C[Y_IDX]=B[Y_IDX]+A[Y_IDX]; -} - -CTHULHU_INLINE void VectorXY_Subtract(VECTORXY C,VECTORXY A,VECTORXY B) { - C[X_IDX]=B[X_IDX]-A[X_IDX]; - C[Y_IDX]=B[Y_IDX]-A[Y_IDX]; -} - -CTHULHU_INLINE void VectorXY_Normalize(VECTORXY A) { - double length=sqrt(A[X_IDX]*A[X_IDX]+A[Y_IDX]*A[Y_IDX]); - if(length < __FLT_EPSILON__ ) { - return; - } - A[X_IDX]/=length; - A[Y_IDX]/=length; -} - -CTHULHU_INLINE void VectorXY_Round(VECTORXY A) { - A[X_IDX]=round(A[X_IDX]); - A[Y_IDX]=round(A[Y_IDX]); -} -CTHULHU_INLINE void VectorXY_Set(VECTORXY A,VECTORXY B) { - A[X_IDX]=B[X_IDX]; - A[Y_IDX]=B[Y_IDX]; -} - -CTHULHU_INLINE double VectorXY_crossProduct(VectorXY A, VectorXY B, VectorXY P){ - double r = (A[Y_IDX]-B[Y_IDX])*(P[X_IDX]-B[X_IDX]) + (B[X_IDX]-A[X_IDX])*(P[Y_IDX]-B[Y_IDX]); - if(fabs(r) < __FLT_EPSILON__ ) { - return 0.0; - } - return r; -} - -CTHULHU_INLINE double VectorXY_dotProduct(VectorXY A, VectorXY B,VectorXY C){ - double r=(A[X_IDX]-B[X_IDX])*(C[X_IDX]-B[X_IDX])+(A[Y_IDX]-B[Y_IDX])*(C[Y_IDX]-B[Y_IDX]); - if(fabs(r) < __FLT_EPSILON__ ) { - return 0.0; - } - return r; -} - - -/* -** Consider traveling from VectorXY A to B to P. If you have to make -** a left-turn at B, then this routine returns -1. If P is on the -** same line as A and B then return 0. If you make a right turn -** at B in order to reach P then return +1. -*/ -CTHULHU_INLINE int VectorXY_rightOf(VectorXY A, VectorXY B, VectorXY P){ - /* Algorithm: Rotate AB 90 degrees counter-clockwise. Take - ** the dot product with BP. The dot produce will be the product - ** of two (non-negative) magnitudes and the cosine of the angle. So if - ** the dot product is positive, the bend is to the left, or to the right if - ** the dot product is negative. - */ - double r = (A[Y_IDX]-B[Y_IDX])*(P[X_IDX]-B[X_IDX]) + (B[X_IDX]-A[X_IDX])*(P[Y_IDX]-B[Y_IDX]); - if(fabs(r) < __FLT_EPSILON__ ) { - return 0; - } - if(r>0.0) { - return -1; - } - return 1; -} - -/* -** This is a variation on rightOf(). Return 0 only if BP is a continuation -** of the line AB. If BP doubles back on AB then return -1. -*/ -CTHULHU_INLINE int VectorXY_strictlyRightOf(VectorXY A, VectorXY B, VectorXY P){ - int c = VectorXY_rightOf(A,B,P); - if( c==0 ){ - double r = (A[X_IDX]-B[X_IDX])*(P[X_IDX]-B[X_IDX]) + (A[Y_IDX]-B[Y_IDX])*(P[Y_IDX]-B[Y_IDX]); - c = r<0.0 ? +1 : -1; - } - return c; -} - -/* -** Return TRUE if segments AB and CD intersect -*/ -CTHULHU_INLINE int VectorXY_intersect(VectorXY A, VectorXY B, VectorXY C, VectorXY D){ - return - VectorXY_rightOf(A,B,C)*VectorXY_rightOf(A,B,D)<0 && - VectorXY_rightOf(C,D,A)*VectorXY_rightOf(C,D,B)<0; -} - -/* -** Compute angle ABC measured counter-clockwise from AB. Return the -** result. -** -** This does not need to be a true angular measure as long as it is -** monotonically increasing. -*/ -CTHULHU_INLINE double VectorXY_angleOf(VectorXY A, VectorXY B, VectorXY C){ -#ifdef NEVER - double a1, a2, a3; - //if( sameVectorXY(A,C) ){ - // return M_PI; - //} - a1 = atan2(B[Y_IDX] - A[Y_IDX], B[X_IDX] - A[X_IDX]); - a2 = atan2(C[Y_IDX] - B[Y_IDX], C[X_IDX] - B[X_IDX]); - a3 = a2-a1; - if( a3>0 ) a3 -= 2.0*M_PI; - if( a3<=-(2*M_PI) ) a3 += 2.0*M_PI; - return fabs(a3); -#else - double a1, a2, a3; - if( sameVectorXY(A,C) ){ - return M_PI; - } - a1 = atan2(B[Y_IDX] - A[Y_IDX], B[X_IDX] - A[X_IDX]); - a2 = atan2(C[Y_IDX] - B[Y_IDX], C[X_IDX] - B[X_IDX]); - a3 = a2-a1; - if( a3>M_PI ) a3 -= 2.0*M_PI; - if( a3<=-M_PI ) a3 += 2.0*M_PI; - return a3; -#endif -} - -/* -** Return the squared distance between two VectorXYs. -*/ -CTHULHU_INLINE double VectorXY_distance_squared(VectorXY A, VectorXY B){ - double dx = B[X_IDX] - A[X_IDX]; - double dy = B[Y_IDX] - A[Y_IDX]; - return dx*dx + dy*dy; -} - -/* -** Return the distance between two VectorXYs. -*/ -CTHULHU_INLINE double VectorXY_distance(VectorXY A, VectorXY B){ - double dx = B[X_IDX] - A[X_IDX]; - double dy = B[Y_IDX] - A[Y_IDX]; - return sqrt(dx*dx + dy*dy); -} - -static int vectorxy_method_add( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxy); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxy); - if(!B) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vectorxy); - VectorXY_Add(C->matrix,A->matrix,B->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -static int vectorxy_method_subtract( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - MATOBJ *A,*B,*C; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxy); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxy); - if(!B) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vectorxy); - VectorXY_Subtract(C->matrix,A->matrix,B->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - - -static int vectorxy_method_add_stream( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - int i,n; - Tcl_Obj *pObj,*pResult; - - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A BLIST" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxy); - if(!A) return TCL_ERROR; - if( Tcl_ListObjLength(interp, objv[2], &n) ) return TCL_ERROR; - pResult=Tcl_NewListObj(0,NULL); - for(i=0; imatrix,A->matrix,B->matrix); - Tcl_ListObjAppendElement(0, pResult, Matrix_To_TclObj(C)); - } - Tcl_SetObjResult(interp,pResult); - return TCL_OK; -} - -static int vectorxy_method_angle( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, C; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A B C"); - return TCL_ERROR; - } - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[2],B)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[3],C)) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_angleOf(A, B, C))); - return TCL_OK; -} - -static int vectorxy_method_point_on_segment( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ -#ifdef NEVER - VectorXY A, B, C; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A B P"); - return TCL_ERROR; - } - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[2],B)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[3],C)) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXY_Point_On_Segment(A, B, C))); -#endif - return TCL_OK; -} - -/* -** tclcmd: vectorxy crossproduct A B C -** Return the the cross product of AB*BC -*/ -static int vectorxy_method_crossproduct( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, C; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A B C"); - return TCL_ERROR; - } - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[2],B)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[3],C)) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_crossProduct(A, B, C))); - return TCL_OK; -} - -static int vectorxy_method_distance ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - VECTORXY A,B; - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A B"); - return TCL_ERROR; - } - double result=0.0,dx,dy; - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[2],B)) return TCL_ERROR; - dx=B[X_IDX]-A[X_IDX]; - dy=B[Y_IDX]-A[Y_IDX]; - - result=sqrt(dx*dx + dy*dy); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -static int vectorxy_method_length ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - VECTORXY A; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A"); - return TCL_ERROR; - } - double result=0.0; - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - result=sqrt(A[X_IDX]*A[X_IDX] + A[Y_IDX]*A[Y_IDX]); - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -static int vectorxy_method_normalize ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - VECTORXY A; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A"); - return TCL_ERROR; - } - double result=0.0,dx,dy; - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - VectorXY_Normalize(A); - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - -static int vectorxy_method_dotproduct( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, C; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "A B C"); - return TCL_ERROR; - } - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[2],B)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[3],C)) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewDoubleObj(VectorXY_dotProduct(A, B, C))); - return TCL_OK; -} - - -/* -** tclcmd: triag_test_rightof X0 Y0 X1 Y1 X2 Y2 -** -** A TCL command for testing the rightOf() function. -*/ -static int vectorxy_method_rightof( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - VectorXY A, B, C; - if( objc!=4 ){ - Tcl_WrongNumArgs(interp, 1, objv, "X0 Y0 X1 Y1 X2 Y2"); - return TCL_ERROR; - } - if(Odie_Set_VECTORXY_FromObj(interp,objv[1],A)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[2],B)) return TCL_ERROR; - if(Odie_Set_VECTORXY_FromObj(interp,objv[3],C)) return TCL_ERROR; - Tcl_SetObjResult(interp, Tcl_NewIntObj(VectorXY_rightOf(A, B, C))); - return TCL_OK; -} - -static int vectorxy_method_rotate_and_size ( - ClientData *simulator, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - /* - ** Apply Matrices - */ - Tcl_Obj *pResult=Tcl_NewObj(); - int i; - double matA[6] = {1.0,0.0,0.0,1.0,0.0,0.0}; - double nx,ny,scalex,scaley,angle; - - if( objc < 7 ){ - Tcl_WrongNumArgs(interp, 1, objv, "normalx normaly sizex sizey V ?V?..."); - return TCL_ERROR; - } - - if(Tcl_GetDoubleFromObj(interp,objv[1],&nx)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[2],&ny)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[3],&scalex)) return TCL_ERROR; - if(Tcl_GetDoubleFromObj(interp,objv[4],&scaley)) return TCL_ERROR; - - angle=atan2(ny,nx); - matA[0]=cos(angle); - matA[1]=sin(angle); - matA[2]=-sin(angle); - matA[3]=cos(angle); - matA[4]=0.0; - matA[5]=0.0; - - scalex*=0.5; - scaley*=0.5; - for(i=5;ifullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - - - return TCL_OK; -} DELETED cmodules/math/generic/vectorxyz.c Index: cmodules/math/generic/vectorxyz.c ================================================================== --- cmodules/math/generic/vectorxyz.c +++ /dev/null @@ -1,339 +0,0 @@ -#include "odieInt.h" - -CTHULHU_INLINE void vectorxyz_cross_product(VectorXYZ C,VectorXYZ A,VectorXYZ B) { - C[X_IDX] = A[Y_IDX] * B[Z_IDX] - A[Z_IDX] * B[Y_IDX]; - C[Y_IDX] = A[Z_IDX] * B[X_IDX] - A[X_IDX] * B[Z_IDX]; - C[Z_IDX] = A[X_IDX] * B[Y_IDX] - A[Y_IDX] * B[X_IDX]; -} - - -CTHULHU_INLINE void VectorXYZ_Add(VECTORXY C,VECTORXY A,VECTORXY B) { - C[X_IDX]=B[X_IDX]+A[X_IDX]; - C[Y_IDX]=B[Y_IDX]+A[Y_IDX]; - C[Z_IDX]=B[Z_IDX]+A[Z_IDX]; -} - -CTHULHU_INLINE void VectorXYZ_Subtract(VECTORXY C,VECTORXY A,VECTORXY B) { - C[X_IDX]=B[X_IDX]-A[X_IDX]; - C[Y_IDX]=B[Y_IDX]-A[Y_IDX]; - C[Z_IDX]=B[Z_IDX]-A[Z_IDX]; -} - - -static int vectorxyz_method_create ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - double result; - if(objc != 2 && objc !=4) { - Tcl_WrongNumArgs( interp, 1, objv, "LIST\nor\nx y z" ); - return TCL_ERROR; - } - if(objc==2) { - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - } else { - double x,y,z; - if(Tcl_GetDoubleFromObj(interp,objv[1],&x)) { - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[2],&y)) { - return TCL_ERROR; - } - if(Tcl_GetDoubleFromObj(interp,objv[3],&z)) { - return TCL_ERROR; - } - A=Matrix_NewObj(); - Matrix_Alloc(A,MATFORM_vectorxyz); - *(A->matrix+X_IDX)=x; - *(A->matrix+Y_IDX)=y; - *(A->matrix+Z_IDX)=z; - } - Tcl_SetObjResult(interp,Matrix_To_TclObj(A)); - return TCL_OK; -} - - -static int vectorxyz_method_add( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz); - if(!B) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vectorxyz); - VectorXYZ_Add(C->matrix,A->matrix,B->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - - - -static int vectorxyz_method_subtract( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz); - if(!B) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vectorxyz); - VectorXYZ_Subtract(C->matrix,A->matrix,B->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - - - -static int vectorxyz_method_cross_product ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B,*C; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz); - if(!B) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vectorxyz); - vectorxyz_cross_product(C->matrix,A->matrix,B->matrix); - - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -CTHULHU_INLINE double vectorxyz_dot_product(VectorXYZ A,VectorXYZ B) { - return A[X_IDX] * B[X_IDX] + A[Y_IDX] * B[Y_IDX] + A[Z_IDX] * B[Z_IDX]; -} - -static int vectorxyz_method_dot_product ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*B; - double result; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "A B" ); - return TCL_ERROR; - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - B=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz); - if(!B) return TCL_ERROR; - - result=vectorxyz_dot_product(A->matrix,B->matrix); - - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - - -/* - * A - the vector to be tranformed - * B - the affine tranformation matrix - * R - a place to dump the result - * - * A and R MUST BE DIFFERENT - */ - -CTHULHU_INLINE void vectorxyz_MatrixMultiply(VECTORXYZ R,VECTORXYZ A,AFFINE M) -{ - int i; - - for(i=0;i<3;i++) - { - R[i]=A[X_IDX]*M[0][i] + A[Y_IDX]*M[1][i] + A[Z_IDX]* M[2][i] + M[3][i]; - } -} - -static int vectorxyz_method_transform ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *Affine,*A,*C; - if(objc < 3) { - Tcl_WrongNumArgs( interp, 1, objv, "affine vector ?vector...?" ); - } - - Affine=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_affine); - if(!Affine) return TCL_ERROR; - - if(objc==3) { - A=Odie_GetMatrixFromTclObj(interp,objv[2],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Alloc(C,MATFORM_vectorxyz); - vectorxyz_MatrixMultiply(C->matrix,A->matrix,Affine->matrix); - - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; - } - int i,n; - n=objc-2; - Tcl_Obj **pArray=Odie_Alloc(sizeof(Tcl_Obj)*n); - for(i=0;imatrix,A->matrix,Affine->matrix); - pArray[i]=Matrix_To_TclObj(C); - } - Tcl_SetObjResult(interp,Tcl_NewListObj(n,pArray)); - Odie_Free(pArray); - return TCL_OK; -} - -CTHULHU_INLINE double odiemath_vectorxyz_length(VECTOR A) -{ - double length=(sqrt(A[0]*A[0]+A[1]*A[1]+A[2]*A[2])); - if(length<__FLT_EPSILON__) { - return 0.0; - } - return length; -} - -static int vectorxyz_method_length ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - double result; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - result=odiemath_vectorxyz_length(A->matrix); - - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -CTHULHU_INLINE double odiemath_vectorxyz_lengthInvSqr(VECTOR A) { - double r=A[0]+A[1]+A[2]; - if(fabs(r)<__FLT_EPSILON__) { - return NAN; - } - return (1.0/(A[0]*A[0]+A[1]*A[1]+A[2]*A[2])); -} - -static int vectorxyz_method_length_inv_sqr ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A; - double result; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - result=odiemath_vectorxyz_lengthInvSqr(A->matrix); - - Tcl_SetObjResult(interp,Tcl_NewDoubleObj(result)); - return TCL_OK; -} - -CTHULHU_INLINE void odiemath_vectorxyz_normalize(VectorXYZ A) -{ - double d; - double r=odiemath_vectorxyz_length(A); - if(fabs(r) < __FLT_EPSILON__) { - A[0]=0.0; - A[1]=0.0; - A[3]=0.0; - } else { - d=1.0 / r; - A[0]*=d; - A[1]*=d; - A[2]*=d; - } -} - -static int vectorxyz_method_normalize ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - MATOBJ *A,*C; - double result; - if(objc != 2) { - Tcl_WrongNumArgs( interp, 1, objv, "A" ); - } - A=Odie_GetMatrixFromTclObj(interp,objv[1],MATFORM_vectorxyz); - if(!A) return TCL_ERROR; - - C=Matrix_NewObj(); - Matrix_Copy(C,A); - odiemath_vectorxyz_normalize(C->matrix); - Tcl_SetObjResult(interp,Matrix_To_TclObj(C)); - return TCL_OK; -} - -DLLEXPORT int Odie_VectorXYZ_Init(Tcl_Interp *interp) { - Tcl_Namespace *modPtr; - - modPtr=Tcl_FindNamespace(interp,"vectorxyz",NULL,TCL_NAMESPACE_ONLY); - if(!modPtr) { - modPtr = Tcl_CreateNamespace(interp, "vectorxyz", NULL, NULL); - } - Tcl_CreateObjCommand(interp,"::vectorxyz::add",(Tcl_ObjCmdProc *)vectorxyz_method_add,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::subtract",(Tcl_ObjCmdProc *)vectorxyz_method_subtract,NULL,NULL); - - Tcl_CreateObjCommand(interp,"::vectorxyz::create",(Tcl_ObjCmdProc *)vectorxyz_method_create,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::cross_product",(Tcl_ObjCmdProc *)vectorxyz_method_cross_product,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::dot_product",(Tcl_ObjCmdProc *)vectorxyz_method_dot_product,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::length",(Tcl_ObjCmdProc *)vectorxyz_method_length,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::length_inv_sqr",(Tcl_ObjCmdProc *)vectorxyz_method_length_inv_sqr,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::normalize",(Tcl_ObjCmdProc *)vectorxyz_method_normalize,NULL,NULL); - Tcl_CreateObjCommand(interp,"::vectorxyz::transform",(Tcl_ObjCmdProc *)vectorxyz_method_transform,NULL,NULL); - - Tcl_CreateEnsemble(interp, modPtr->fullName, modPtr, TCL_ENSEMBLE_PREFIX); - Tcl_Export(interp, modPtr, "[a-z]*", 1); - return TCL_OK; -} - DELETED cmodules/math/math.man Index: cmodules/math/math.man ================================================================== --- cmodules/math/math.man +++ /dev/null @@ -1,43 +0,0 @@ -[comment {-*- tao -*-}] -[manpage_begin odielib::math n 2.0] -[keywords odielib] -[copyright {2000-2014 Sean Woods }] -[moddesc {The Odielib Accellerated Math Module}] -[titledesc {The Odielib Accellerated Math Module}] -[category {Mathematics}] -[require odielib 2.0] -[description] - -[para] - -The [package math] package is included with [package odielib]. It contains -a series of C-accellerated routines for matrix math, tailored for graphics -and basic (i.e 3 dimensions and time) physics. - -[section COMMANDS] -[list_begin definitions] -[call [cmd affine2d::combine] [arg "transform"] [arg "transform"] [opt [arg "transform..."]]] -Accepts N 3x3 affine matrices, and returns a 3x3 matrix which is the combination of them all. - -[call [cmd affine2d::rotation_from_angle] [arg "theta"] [opt [arg "units"]]] -Computes a 2d affine rotation (a 3x3 matrix) from an angle [arg theta]. -[para] -Valid units r - radians (2pi = one turn), g - gradian (400 = one turn), d - degree (360 = 1 turn) - -[call [cmd affine2d::rotation_from_normal] [arg "normalx"] [arg "normaly"]] -Computes a 2d affine rotation (a 3x3 matrix) from a directional normal, given -my %of travel in X and Y. - - - -[list_end] -[section "REFERENCES"] - - -[section AUTHORS] -Sean Woods - -[vset CATEGORY tao] -[include scripts/feedback.inc] - -[manpage_end] DELETED cmodules/odieutil/constant.c Index: cmodules/odieutil/constant.c ================================================================== --- cmodules/odieutil/constant.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -** constant.c -** Series of routines to minimize memory usage through the use -** of shared strings -*/ -#include "odieInt.h" - -#include - -Tcl_HashTable constant_strings; -Tcl_Obj *irmStatic[14]; - -typedef struct constObj { - char *string; - Tcl_Obj *tclobj; -} constObj; - -Tcl_Obj *Odie_shared_tclobj(int which) { - if(which > ODIE_STATIC_MAX || which < 0) { - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NULL]); - return irmStatic[ODIE_STATIC_NULL]; - } - Tcl_IncrRefCount(irmStatic[which]); - return irmStatic[which]; -} - -Tcl_Obj *Odie_NewBooleanObj(int value) { - if(value) { - return Odie_shared_tclobj(ODIE_STATIC_ONE); - } - return Odie_shared_tclobj(ODIE_STATIC_ZERO); -} - -Tcl_Obj *Odie_NewIntObj(int value) { - if(value>=0 && value < 10) { - int idx=ODIE_STATIC_ZERO+value; - Tcl_IncrRefCount(irmStatic[idx]); - return irmStatic[idx]; - } - if(value==-1) { - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NEG1]); - return irmStatic[ODIE_STATIC_NEG1]; - } - return Tcl_NewIntObj(value); -} - - -static constObj *Odie_constant(const char *zName,int create) { - int len,isNew=0; - Tcl_HashEntry *pEntry; - constObj *p; - if(zName==NULL) { - return NULL; - } - if(create) { - pEntry=Tcl_CreateHashEntry(&constant_strings,zName,&isNew); - } else { - pEntry=Tcl_FindHashEntry(&constant_strings,zName); - } - if(isNew) { - len = strlen(zName); - p =(constObj*)Odie_Alloc(sizeof(*p)+len+1); - p->string=p+1; - strncpy(p->string, zName, len+1); - p->tclobj=Tcl_NewStringObj(zName,len); - Tcl_IncrRefCount(p->tclobj); - Tcl_SetHashValue(pEntry,(ClientData)p); - return p; - } - if(pEntry) { - p=(constObj*)Tcl_GetHashValue(pEntry); - return p; - } - return NULL; -} - -int Odie_SameString(char *aPtr,char *bPtr) { - if(aPtr==bPtr) { - return 1; - } - if(!bPtr || !aPtr) { - return 0; - } - if(strcmp(aPtr,bPtr)==0) { - return 1; - } - return 0; -} -char *Odie_constant_string(const char *zName) { - constObj *p; - p=Odie_constant(zName,1); - return p->string; -} - - -Tcl_Obj *Odie_constant_tclobj(const char *zName) { - constObj *p; - p=Odie_constant(zName,1); - Tcl_IncrRefCount(p->tclobj); - return p->tclobj; -} - -Tcl_Obj *Odie_NewStringObj(const char *str) { - /* - if(!str) { - return Tcl_NewObj(); - } - return Tcl_NewStringObj(str,-1); - */ - return Odie_constant_tclobj(str); -} - -static int constantMapCmd( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char *newName; - Tcl_Obj *result; - - if(objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "string"); - } - newName=Tcl_GetString(objv[1]); - result=Odie_constant_tclobj(newName); - if (!result) return TCL_ERROR; - Tcl_SetObjResult(interp,result); - return TCL_OK; -} - -DLLEXPORT int Odie_Constant_Init(Tcl_Interp *interp) { - static int once = 1; - - if( once ){ - int i; - once = 0; - - irmStatic[ODIE_STATIC_NULL]=Tcl_NewObj(); - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NULL]); - - irmStatic[ODIE_STATIC_ZERO] = Tcl_NewBooleanObj(0); - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_ZERO]); - - irmStatic[ODIE_STATIC_ONE] = Tcl_NewBooleanObj(1); - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_ONE]); - for(i=2;i<10;i++) { - int idx=ODIE_STATIC_ZERO+i; - irmStatic[idx] = Tcl_NewIntObj(i); - Tcl_IncrRefCount(irmStatic[idx]); - } - - irmStatic[ODIE_STATIC_FZERO] = Tcl_NewDoubleObj(0.0); - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_FZERO]); - - irmStatic[ODIE_STATIC_NEG1] = Tcl_NewIntObj(-1); - Tcl_IncrRefCount(irmStatic[ODIE_STATIC_NEG1]); - - Tcl_InitHashTable(&constant_strings,TCL_STRING_KEYS); - } - - return TCL_OK; -} DELETED cmodules/odieutil/constant.h Index: cmodules/odieutil/constant.h ================================================================== --- cmodules/odieutil/constant.h +++ /dev/null @@ -1,23 +0,0 @@ -enum ODIE_NULL_REPRESENTATION { - ODIE_NULL_NULL, - ODIE_NULL_ZERO, - ODIE_NULL_EMPTY -}; - -enum ODIE_STATIC_OBJS { - ODIE_STATIC_ZERO, - ODIE_STATIC_ONE, - ODIE_STATIC_TWO, - ODIE_STATIC_THREE, - ODIE_STATIC_FOUR, - ODIE_STATIC_FIVE, - ODIE_STATIC_SIX, - ODIE_STATIC_SEVEN, - ODIE_STATIC_EIGHT, - ODIE_STATIC_NINE, - ODIE_STATIC_NULL, - ODIE_STATIC_NEG1, - ODIE_STATIC_FZERO, - ODIE_STATIC_INF, - ODIE_STATIC_MAX -}; DELETED cmodules/odieutil/cthulhu.ini Index: cmodules/odieutil/cthulhu.ini ================================================================== --- cmodules/odieutil/cthulhu.ini +++ /dev/null @@ -1,4 +0,0 @@ -set here [file dirname [file normalize [info script]]] - -::cthulhu::add_directory $here { -} DELETED cmodules/odieutil/listcmd.c Index: cmodules/odieutil/listcmd.c ================================================================== --- cmodules/odieutil/listcmd.c +++ /dev/null @@ -1,204 +0,0 @@ -#include "odieInt.h" - -//const Tcl_ObjType *tclListType; -const Tcl_ObjType *tclIntType; -//const Tcl_ObjType *tclDoubleType; - -/* -** Print a trace message -*/ -void Odie_trace_printf(Tcl_Interp *interp,const char *zFormat, ...){ - int n; - va_list ap; - char zBuf[4000]; - - va_start(ap, zFormat); - strcpy(zBuf, "puts -nonewline {"); - n = strlen(zBuf); - vsnprintf(&zBuf[n], sizeof(zBuf)-5-n, zFormat, ap); - strcat(zBuf, "}\n"); - Tcl_Eval(interp, zBuf); -} - -int Odie_GetIntFromObj(Tcl_Interp *interp,Tcl_Obj *tclObj,int *result) { - if(tclObj->typePtr==tclDoubleType) { - double s=tclObj->internalRep.doubleValue; - *result=(int)round(s); - return TCL_OK; - } - if(tclObj->typePtr==tclIntType) { - *result=tclObj->internalRep.longValue; - return TCL_OK; - } - if(!Tcl_GetIntFromObj(NULL,tclObj,result)) { - return TCL_OK; - } - double s; - if(Tcl_GetDoubleFromObj(interp,tclObj,&s)) return TCL_ERROR; - *result=(int)round(s); - return TCL_OK; -} - -Tcl_Obj *Odie_Obj_To_Int(Tcl_Obj *tclObj) { - if(tclObj->typePtr==tclDoubleType) { - double s=tclObj->internalRep.doubleValue; - return Tcl_NewIntObj((int)round(s)); - } - if(tclIntType->setFromAnyProc(NULL,tclObj)==TCL_OK) { - return tclObj; - } - double s; - if (Tcl_GetDoubleFromObj(NULL,tclObj,&s)) { - return tclObj; - } - return Tcl_NewIntObj((int)round(s)); -} - -static int getCmd( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Tcl_Obj *result; - if(objc != 2) { - Tcl_WrongNumArgs(interp, 1, objv, "varname"); - } - result=Tcl_ObjGetVar2(interp,objv[1],NULL,0); - if(!result) { - Tcl_ResetResult(interp); - result=Odie_shared_tclobj(ODIE_STATIC_NULL); - } - Tcl_SetObjResult(interp,result); - return TCL_OK; -} - -static int listToInt( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - int i; - Tcl_Obj *resultPtr; - if(objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "element ?element"); - } - resultPtr=Tcl_NewObj(); - for(i=1;i2) { - if(Tcl_ListObjReplace(interp,listObj,length,0,(objc-2), (objv+2))) { - return TCL_ERROR; - } - } - resultPtr=Odie_ListObj_Sort(listObj); - Tcl_ObjSetVar2(interp,objv[1],NULL,resultPtr,0); - Tcl_SetObjResult(interp,resultPtr); - return TCL_OK; -} - -/* -** topic: -** command: ldelete -** arglist: variable element ... -** title: Remove all instances of [emph element] from a list stored in [emph variable] -** description: -** If [emph varname] does not exist, an empty list is created. -*/ -static int ldeleteCmd ( - void *pArg, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -) { - int listLength, idx; - Tcl_Obj *resultPtr,*listPtr; - Tcl_Obj **listObjPtrs; - - if (objc < 2) { - Tcl_WrongNumArgs(interp, 1, objv, "variable element ..."); - return TCL_ERROR; - } - listPtr=Tcl_ObjGetVar2(interp,objv[1],NULL,0); - if(!listPtr) { - Tcl_ResetResult(interp); - listPtr=Tcl_NewObj(); - } else { - listPtr=Tcl_DuplicateObj(listPtr); - } - - if(Tcl_ListObjGetElements(interp, listPtr, &listLength, &listObjPtrs)) { - return TCL_ERROR; - } - - resultPtr=Tcl_NewObj(); - for(idx=0;idx -#include "odieInt.h" -#include - -/* - * If compiled on a machine that doesn't have a 32-bit integer, - * you just set "uint32" to the appropriate datatype for an - * unsigned 32-bit integer. For example: - * - * cc -Duint32='unsigned long' md5.c - * - */ -#ifndef uint32 -# define uint32 unsigned int -#endif - -struct Context { - uint32 buf[4]; - uint32 bits[2]; - unsigned char in[64]; -}; -typedef char MD5Context[88]; - -/* - * Note: this code is harmless on little-endian machines. - */ -static void byteReverse (unsigned char *buf, unsigned longs){ - uint32 t; - do { - t = (uint32)((unsigned)buf[3]<<8 | buf[2]) << 16 | - ((unsigned)buf[1]<<8 | buf[0]); - *(uint32 *)buf = t; - buf += 4; - } while (--longs); -} -/* The four core functions - F1 is optimized somewhat */ - -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -/* This is the central step in the MD5 algorithm. */ -#define MD5STEP(f, w, x, y, z, data, s) ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) - -/* - * The core of the MD5 algorithm, this alters an existing MD5 hash to - * reflect the addition of 16 longwords of new data. MD5Update blocks - * the data and converts bytes into longwords for this routine. - */ -static void MD5Transform(uint32 buf[4], const uint32 in[16]){ - register uint32 a, b, c, d; - - a = buf[0]; - b = buf[1]; - c = buf[2]; - d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -/* - * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious - * initialization constants. - */ -static void MD5Init(MD5Context *pCtx){ - struct Context *ctx = (struct Context *)pCtx; - ctx->buf[0] = 0x67452301; - ctx->buf[1] = 0xefcdab89; - ctx->buf[2] = 0x98badcfe; - ctx->buf[3] = 0x10325476; - ctx->bits[0] = 0; - ctx->bits[1] = 0; -} - -/* - * Update context to reflect the concatenation of another buffer full - * of bytes. - */ -static -void MD5Update(MD5Context *pCtx, const unsigned char *buf, unsigned int len){ - struct Context *ctx = (struct Context *)pCtx; - uint32 t; - - /* Update bitcount */ - - t = ctx->bits[0]; - if ((ctx->bits[0] = t + ((uint32)len << 3)) < t) - ctx->bits[1]++; /* Carry from low to high */ - ctx->bits[1] += len >> 29; - - t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ - - /* Handle any leading odd-sized chunks */ - - if ( t ) { - unsigned char *p = (unsigned char *)ctx->in + t; - - t = 64-t; - if (len < t) { - memcpy(p, buf, len); - return; - } - memcpy(p, buf, t); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *)ctx->in); - buf += t; - len -= t; - } - - /* Process data in 64-byte chunks */ - - while (len >= 64) { - memcpy(ctx->in, buf, 64); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *)ctx->in); - buf += 64; - len -= 64; - } - - /* Handle any remaining bytes of data. */ - - memcpy(ctx->in, buf, len); -} - -/* - * Final wrapup - pad to 64-byte boundary with the bit pattern - * 1 0* (64-bit count of bits processed, MSB-first) - */ -static void MD5Final(unsigned char digest[16], MD5Context *pCtx){ - struct Context *ctx = (struct Context *)pCtx; - unsigned count; - unsigned char *p; - - /* Compute number of bytes mod 64 */ - count = (ctx->bits[0] >> 3) & 0x3F; - - /* Set the first char of padding to 0x80. This is safe since there is - always at least one byte free */ - p = ctx->in + count; - *p++ = 0x80; - - /* Bytes of padding needed to make 64 bytes */ - count = 64 - 1 - count; - - /* Pad out to 56 mod 64 */ - if (count < 8) { - /* Two lots of padding: Pad the first block to 64 bytes */ - memset(p, 0, count); - byteReverse(ctx->in, 16); - MD5Transform(ctx->buf, (uint32 *)ctx->in); - - /* Now fill the next block with 56 bytes */ - memset(ctx->in, 0, 56); - } else { - /* Pad block to 56 bytes */ - memset(p, 0, count-8); - } - byteReverse(ctx->in, 14); - - /* Append length in bits and transform */ - ((uint32 *)ctx->in)[ 14 ] = ctx->bits[0]; - ((uint32 *)ctx->in)[ 15 ] = ctx->bits[1]; - - MD5Transform(ctx->buf, (uint32 *)ctx->in); - byteReverse((unsigned char *)ctx->buf, 4); - memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ -} - -/* -** Convert a digest into base-16. digest should be declared as -** "unsigned char digest[16]" in the calling function. The MD5 -** digest is stored in the first 16 bytes. zBuf should -** be "char zBuf[33]". -*/ -static void DigestToBase16(unsigned char *digest, char *zBuf){ - static char const zEncode[] = "0123456789abcdef"; - int i, j; - - for(j=i=0; i<16; i++){ - int a = digest[i]; - zBuf[j++] = zEncode[(a>>4)&0xf]; - zBuf[j++] = zEncode[a & 0xf]; - } - zBuf[j] = 0; -} - -/* -** A TCL command for md5. The argument is the text to be hashed. The -** Result is the hash in base64. -*/ -static int md5_cmd(void*cd, Tcl_Interp *interp, int argc, const char **argv){ - MD5Context ctx; - unsigned char digest[16]; - - if( argc!=2 ){ - Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], - " TEXT\"", 0); - return TCL_ERROR; - } - MD5Init(&ctx); - MD5Update(&ctx, (unsigned char*)argv[1], (unsigned)strlen(argv[1])); - MD5Final(digest, &ctx); - DigestToBase16(digest, Tcl_GetStringResult(interp)); - return TCL_OK; -} - -/* -** A TCL command to take the md5 hash of a file. The argument is the -** name of the file. -*/ -static int md5file_cmd(void*cd, Tcl_Interp*interp, int argc, const char **argv){ - FILE *in; - MD5Context ctx; - unsigned char digest[16]; - char zBuf[10240]; - - if( argc!=2 ){ - Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0], - " FILENAME\"", 0); - return TCL_ERROR; - } - in = fopen(argv[1],"rb"); - if( in==0 ){ - Tcl_AppendResult(interp,"unable to open file \"", argv[1], - "\" for reading", 0); - return TCL_ERROR; - } - MD5Init(&ctx); - for(;;){ - int n; - n = fread(zBuf, 1, sizeof(zBuf), in); - if( n<=0 ) break; - MD5Update(&ctx, (unsigned char*)zBuf, (unsigned)n); - } - fclose(in); - MD5Final(digest, &ctx); - DigestToBase16(digest, Tcl_GetStringResult(interp)); - return TCL_OK; -} - -/* -** Register the two TCL commands above with the TCL interpreter. -*/ -DLLEXPORT int Md5_Init(Tcl_Interp *interp){ - //Tcl_CreateCommand(interp, "md5", (Tcl_CmdProc*)md5_cmd, 0, 0); - Tcl_CreateCommand(interp, "irmmd5", (Tcl_CmdProc*)md5_cmd, 0, 0); - Tcl_CreateCommand(interp, "md5file", (Tcl_CmdProc*)md5file_cmd, 0, 0); - return TCL_OK; -} - DELETED cmodules/odieutil/memory.c Index: cmodules/odieutil/memory.c ================================================================== --- cmodules/odieutil/memory.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "odieInt.h" - -/* -** Memory routines -*/ -int nMalloc=0; - -/* -** Provide wrappers around malloc and free -*/ -char *Odie_Alloc(unsigned int size) { - char *p; - p=Tcl_Alloc(size); - if(p) { - nMalloc++; - memset(p,0,size); - } else { - printf("out of memory\n"); - exit(1); - } - return p; -} - -void Odie_Free(char *ptr) { - if(ptr) { - nMalloc--; - } - Tcl_Free(ptr); -} - -char *Odie_Realloc(char *ptr, unsigned int size) { - return Tcl_Realloc(ptr, size); -} DELETED cmodules/odieutil/mkPassword.tcl Index: cmodules/odieutil/mkPassword.tcl ================================================================== --- cmodules/odieutil/mkPassword.tcl +++ /dev/null @@ -1,49 +0,0 @@ -### -# This TCL script generates a unique password used by this executable -# to encrypt or sign code -# -# Adapted from Dennis LaBelle's Freewrap -## -set here [file dirname [file normalize [info script]]] -set outfile [file join $here password.c] -if {[file exists $outfile]} { - return -} -set curpwd [lindex $argv 0] -set curpwd {} -if { $curpwd eq {} } { - set charset {*+-.0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_} - set maxpos [string length $charset] - set keylen [expr 8 + int(8 * rand())] - set curpwd {} - for {set idx 0} {$idx < $keylen} {incr idx} { - append curpwd [string index $charset [expr int($maxpos * rand())]] - } -} else { - set keylen [string length $curpwd] -} -set fout [open $outfile w] -puts $fout "/* Automatically generated by setinfo.tcl - [clock format [clock seconds]]" -puts $fout {} -puts $fout " This file defines the function that returns the encryption password." -puts $fout " Its contents have been randomly generated to produce a password" -puts $fout " that is difficult to extract from the compiled binary file." -puts $fout "*/" -puts $fout {} -puts $fout {char *getPwdKey(char *keybuf)} -puts $fout "\{" -for {set idx 0} {$idx < $keylen} {incr idx} { - set cval [string index $curpwd $idx] - scan $cval %c ival - puts $fout " keybuf\[$idx\] = $ival;" -} -puts $fout " keybuf\[$keylen\] = 0;" -puts $fout {} -puts $fout " return keybuf;" -puts $fout "\}" -close $fout -set fout [open [file rootname $outfile].txt w] -puts $fout $curpwd -close $fout - - DELETED cmodules/odieutil/rc4.c Index: cmodules/odieutil/rc4.c ================================================================== --- cmodules/odieutil/rc4.c +++ /dev/null @@ -1,497 +0,0 @@ -/* -** Implementation of an RC4 codec for TCL. -*/ -const char rc4_c_version[] = "$Header: /readi/code/tobe/rc4.c,v 1.6 2007/05/08 21:53:56 drh Exp $"; -#include -#include -#include -#include -#include "odieInt.h" - -//#include - -/* -** An RC4 codec is an instance of the following structure. -*/ -typedef struct Rc4Codec Rc4Codec; -struct Rc4Codec { - unsigned char i, j; - unsigned char s[256]; -}; -static Tcl_WideInt next_random_number = 1; - -/* -** Initialize an RC4 codec with the given key sequence. -*/ -static void rc4_init(Rc4Codec *p, int nByte, unsigned char *pKey){ - int k, l; - unsigned char i, j, t, *s; - i = j = p->i = p->j = 0; - s = p->s; - for(k=0; k<256; k++){ - s[k] = k; - } - l = 0; - for(k=0; k<256; k++){ - t = s[k]; - j += t + pKey[l++]; - if( l>=nByte ) l = 0; - s[k] = s[j]; - s[j] = t; - } - - /* Discard the first 1024 bytes of key stream to thwart the - ** Fluhrer-Mantin-Shamir attack. - */ - for(k=0; k<1024; k++){ - t = s[++i]; - j += t; - s[i] = s[j]; - s[j] = t; - } - p->j = j; -} - -/* -** Encode/Decode nBytes bytes of traffic using the given codec. -*/ -static void rc4_coder(Rc4Codec *p, int nByte, unsigned char *pData){ - register unsigned char ti, tj, i, j, *s; - s = p->s; - i = p->i; - j = p->j; - while( nByte-->0 ){ - ti = s[++i]; - j += ti; - tj = s[i] = s[j]; - s[j] = ti; - tj += ti; - *(pData++) ^= s[tj]; - } - p->i = i; - p->j = j; -} - -/* -** Usage: NAME TEXT -** -** There is a separate TCL command created for each rc4 codec instance. -** This is the implementation of that command. Apply the codec to the -** input and return the results. -*/ -static int CodecObjCmd( - void *pCodec, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - unsigned char *data; - int nData; - Tcl_Obj *pResult; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, "TEXT"); - return TCL_ERROR; - } - data = Tcl_GetByteArrayFromObj(objv[1], &nData); - pResult = Tcl_NewByteArrayObj(data, nData); - data = Tcl_GetByteArrayFromObj(pResult, 0); - rc4_coder((Rc4Codec*)pCodec, nData, data); - Tcl_SetObjResult(interp, pResult); - return TCL_OK; -} - -/* -** Destructor for codec. -*/ -static void CodecDestructor(void *pCodec){ - Odie_Free(pCodec); -} - -/* -** Usage: rc4 NAME PASSWORD -** -** Create a new rc4 codec called NAME and initialized using PASSWORD. -*/ -static int Rc4ObjCmd( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - Rc4Codec *pCodec; - const char *zName; - unsigned char *pKey; - int nKey; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "NAME PASSWORD"); - return TCL_ERROR; - } - zName = Tcl_GetStringFromObj(objv[1], 0); - pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey); - pCodec = (Rc4Codec*)Odie_Alloc( sizeof(*pCodec) ); - rc4_init(pCodec, nKey, pKey); - Tcl_CreateObjCommand(interp, zName, CodecObjCmd, pCodec, CodecDestructor); - return TCL_OK; -} - -/* -** The characters used for HTTP base64 encoding. -*/ -static const unsigned char zBase[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~"; - -/* -** Encode a string using a base-64 encoding. -** The encoding can be reversed using the decode64 function. -** -** Space to hold the result comes from Odie_Alloc(). -*/ -static char *encode64(const char *zData, int nData, int *pnOut){ - char *z64; - int i, n; - - if( nData<=0 ){ - nData = strlen(zData); - } - z64 = Odie_Alloc( (nData*4)/3 + 6 ); - for(i=n=0; i+2>2) & 0x3f ]; - z64[n++] = zBase[ ((zData[i]<<4) & 0x30) | ((zData[i+1]>>4) & 0x0f) ]; - z64[n++] = zBase[ ((zData[i+1]<<2) & 0x3c) | ((zData[i+2]>>6) & 0x03) ]; - z64[n++] = zBase[ zData[i+2] & 0x3f ]; - } - if( i+1>2) & 0x3f ]; - z64[n++] = zBase[ ((zData[i]<<4) & 0x30) | ((zData[i+1]>>4) & 0x0f) ]; - z64[n++] = zBase[ ((zData[i+1]<<2) & 0x3c) ]; - }else if( i>2) & 0x3f ]; - z64[n++] = zBase[ ((zData[i]<<4) & 0x30) ]; - } - z64[n] = 0; - if( pnOut ) *pnOut = n; - return z64; -} - -/* -** This function treats its input as a base-64 string and returns the -** decoded value of that string. Characters of input that are not -** valid base-64 characters (such as spaces and newlines) are ignored. -** -** Space to hold the decoded string is obtained from Odie_Alloc(). -*/ -char *decode64(const char *z64, int n64, int *pnOut){ - char *zData; - int i, j; - int a, b, c, d; - static int isInit = 0; - static int trans[128]; - - if( !isInit ){ - for(i=0; i<128; i++){ trans[i] = 0; } - for(i=0; zBase[i]; i++){ trans[zBase[i] & 0x7f] = i; } - isInit = 1; - } - if( n64<0 ){ - n64 = strlen(z64); - } - while( n64>0 && z64[n64-1]=='=' ) n64--; - zData = Odie_Alloc( (n64*3)/4 + 4 ); - for(i=j=0; i+3>4) & 0x03); - zData[j++] = ((b<<4) & 0xf0) | ((c>>2) & 0x0f); - zData[j++] = ((c<<6) & 0xc0) | (d & 0x3f); - } - if( i+2>4) & 0x03); - zData[j++] = ((b<<4) & 0xf0) | ((c>>2) & 0x0f); - }else if( i+1>4) & 0x03); - } - zData[j] = 0; - if( pnOut ) *pnOut = j; - return zData; -} - -static unsigned char randomByte(void) { - char nextbyte,i; - /* RAND_MAX assumed to be 256 */ - char repeat=(next_random_number % 10)+2; - for(i=0;i252 ) nPasswd = 252; - memcpy(&zKey[4], zPasswd, nPasswd); - rc4_init(&codec, nPasswd+4, (unsigned char*)zKey); - zIn = Tcl_GetStringFromObj(objv[2], &nIn); - zBuf = Odie_Alloc( nIn + 5 ); - memcpy(zBuf, zKey, 4); - memcpy(&zBuf[4], zIn, nIn); - rc4_coder(&codec, nIn, (unsigned char*)&zBuf[4]); - zOut = encode64(zBuf, nIn+4, &nOut); - Tcl_SetObjResult(interp, Tcl_NewStringObj(zOut, nOut)); - Odie_Free((char *)zOut); - Odie_Free((char *)zBuf); - return TCL_OK; -} - -/* -** Usage: rc4decrypt PASSWORD CYPHERTEXT -** -** Decrypt CYPHERTEXT using PASSWORD and a nonce found at the beginning of -** the cyphertext. The cyphertext is base64 encoded. -*/ -static int Rc4DecryptObjCmd( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - const char *zPasswd; - int nPasswd; - char *zIn; - int nIn; - char *zOut; - int nOut; - char zKey[256]; - Rc4Codec codec; - - if( objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "PASSWORD TEXT"); - return TCL_ERROR; - } - zPasswd = Tcl_GetStringFromObj(objv[1], &nPasswd); - zIn = Tcl_GetStringFromObj(objv[2], &nIn); - zOut = decode64(zIn, nIn, &nOut); - if( nOut<4 ){ - return TCL_OK; - } - memcpy(zKey, zOut, 4); - if( nPasswd>252 ) nPasswd = 252; - memcpy(&zKey[4], zPasswd, nPasswd); - rc4_init(&codec, nPasswd+4, (unsigned char*)zKey); - rc4_coder(&codec, nOut-4, (unsigned char*)&zOut[4]); - Tcl_SetObjResult(interp, Tcl_NewStringObj(&zOut[4], nOut-4)); - Odie_Free(zOut); - return TCL_OK; -} - - -/* -** Usage: source_encrypt TEXT -** -** Encrypt TEXT using compiled in PASSWORD and a random nonce. Encode the result -** as a single token using base64. -*/ -static int Rc4EncryptSourceObjCmd( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char zPasswd[32]; - int nPasswd; - char *zIn; - int nIn; - char *zBuf; - char *zOut; - int nOut; - char zKey[256]; - Rc4Codec codec; - extern void sqliteRandomness(int,void*); - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, "TEXT"); - return TCL_ERROR; - } - getPwdKey(zPasswd); - nPasswd=strlen(zPasswd); - - rc4_randomness(4, zKey); - if( nPasswd>252 ) nPasswd = 252; - memcpy(&zKey[4], zPasswd, nPasswd); - rc4_init(&codec, nPasswd+4, (unsigned char*)zKey); - zIn = Tcl_GetStringFromObj(objv[1], &nIn); - zBuf = Odie_Alloc( nIn + 5 ); - memcpy(zBuf, zKey, 4); - memcpy(&zBuf[4], zIn, nIn); - rc4_coder(&codec, nIn, (unsigned char*)&zBuf[4]); - zOut = encode64(zBuf, nIn+4, &nOut); - Tcl_SetObjResult(interp, Tcl_NewStringObj(zOut, nOut)); - Odie_Free((char *)zOut); - Odie_Free((char *)zBuf); - return TCL_OK; -} - -/* -** Usage: source_decrypt CYPHERTEXT -** -** Decrypt CYPHERTEXT using compiled in PASSWORD and a nonce -** found at the beginning of -** the cyphertext. The cyphertext is base64 encoded. -*/ -static int Rc4DecryptSourceObjCmd( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char zPasswd[32]; - int nPasswd; - char *zIn; - int nIn; - char *zOut; - int nOut; - char zKey[256]; - Rc4Codec codec; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, "TEXT"); - return TCL_ERROR; - } - getPwdKey(zPasswd); - nPasswd=strlen(zPasswd); - - zIn = Tcl_GetStringFromObj(objv[1], &nIn); - zOut = decode64(zIn, nIn, &nOut); - if( nOut<4 ){ - return TCL_OK; - } - memcpy(zKey, zOut, 4); - if( nPasswd>252 ) nPasswd = 252; - memcpy(&zKey[4], zPasswd, nPasswd); - rc4_init(&codec, nPasswd+4, (unsigned char*)zKey); - rc4_coder(&codec, nOut-4, (unsigned char*)&zOut[4]); - Tcl_SetObjResult(interp, Tcl_NewStringObj(&zOut[4], nOut-4)); - Odie_Free(zOut); - return TCL_OK; -} - -/* -** Usage: eval_decrypt CYPHERTEXT -** -** Decrypt CYPHERTEXT using compiled in PASSWORD and a nonce -** found at the beginning of -** the cyphertext. The cyphertext is base64 encoded. -*/ -static int Rc4DecryptEvalObjCmd( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *CONST objv[] -){ - char zPasswd[32]; - int nPasswd; - char *zIn; - int nIn; - char *zOut; - int nOut; - char zKey[256]; - Rc4Codec codec; - Tcl_Obj *cleartext; - int code=TCL_OK; - - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, "TEXT"); - return TCL_ERROR; - } - getPwdKey(zPasswd); - nPasswd=strlen(zPasswd); - - zIn = Tcl_GetStringFromObj(objv[1], &nIn); - zOut = decode64(zIn, nIn, &nOut); - if( nOut<4 ){ - return TCL_OK; - } - memcpy(zKey, zOut, 4); - if( nPasswd>252 ) nPasswd = 252; - memcpy(&zKey[4], zPasswd, nPasswd); - rc4_init(&codec, nPasswd+4, (unsigned char*)zKey); - rc4_coder(&codec, nOut-4, (unsigned char*)&zOut[4]); - cleartext=Tcl_NewStringObj(&zOut[4], nOut-4); - Tcl_IncrRefCount(cleartext); - code=Tcl_EvalObjEx(interp,cleartext,NULL); - Tcl_DecrRefCount(cleartext); - Odie_Free(zOut); - return code; -} - -/* -** Initialize the rc4 codec subsystem. -*/ -DLLEXPORT int Rc4_Init(Tcl_Interp *interp){ - Tcl_CreateObjCommand(interp, "rc4", Rc4ObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "rc4seed", Rc4SeedObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "rc4encrypt", Rc4EncryptObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "rc4decrypt", Rc4DecryptObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "source_encrypt", Rc4EncryptSourceObjCmd, 0, 0); - //Tcl_CreateObjCommand(interp, "source_decrypt", Rc4DecryptSourceObjCmd, 0, 0); - Tcl_CreateObjCommand(interp, "eval_decrypt", Rc4DecryptEvalObjCmd, 0, 0); - return TCL_OK; -} DELETED cmodules/odieutil/tclextra.c Index: cmodules/odieutil/tclextra.c ================================================================== --- cmodules/odieutil/tclextra.c +++ /dev/null @@ -1,591 +0,0 @@ -/* -** This module implements an assortment of small TCL extensions. -*/ -const char tclextra_c_version[] = "$Header: /readi/code/tobe/tclextra.c,v 1.15 2009/02/06 19:58:25 sdw Exp $"; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "odieInt.h" - -/* -** Determine if we are running under windows or unix and include the -** necessary headers depending on which is being used. -*/ -#if !defined(__WIN32__) && !defined(_WIN32) && !defined(WIN32) -# define UNIX -# include -# include -# include -/* # include */ -#else -# ifndef WIN32 -# define WIN32 1 -# endif -# include -#endif - - -/* -** This routine implements a TCL command that kills off a subprocess. -** The code is different for Unix and Windows. The process is identified -** by the process ID that the Tcl "exec" command returns. -*/ -static int KillSubprocessCmd( - void *NotUsed, - Tcl_Interp *interp, - int argc, - const char **argv -){ - int pid; - int rc = TCL_OK; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PROCESS-ID\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[1], &pid)!=TCL_OK ){ - return TCL_ERROR; - } -#ifdef UNIX - kill(pid,9); -#else - { - HANDLE h; - h = OpenProcess(PROCESS_TERMINATE, TRUE, pid); - if( h==FALSE ){ - Tcl_AppendResult(interp, "OpenProcess failed for pid ", argv[1], 0); - rc = TCL_ERROR; - }else{ - if( TerminateProcess(h,(UINT)0)==FALSE ){ - Tcl_AppendResult(interp, "unable to terminate process ", argv[1], 0); - rc = TCL_ERROR; - } - CloseHandle(h); - } - } -#endif - return rc; -} - -/* -** This routine implements a TCL command that checks to see if a process -** started in the background by the Tcl "exec" command is still running. -** The code is different for Unix and Windows. The process is identified -** by the process ID that the Tcl "exec" command returns. 1 is returned -** if the process exists and 0 if it does not. -*/ -static int SubprocessExistsCmd( - void *NotUsed, - Tcl_Interp *interp, - int argc, - const char **argv -){ - int pid; - int rc = TCL_OK; - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " PROCESS-ID\"", 0); - return TCL_ERROR; - } - if( Tcl_GetInt(interp, argv[1], &pid)!=TCL_OK ){ - return TCL_ERROR; - } -#ifdef UNIX - { - int status; - waitpid(pid, &status, WNOHANG); - Tcl_AppendResult(interp, kill(pid,0)==0 ? "1" : "0", 0); - } -#else - { - HANDLE h; - h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid); - if( h==FALSE ){ - Tcl_AppendResult(interp, "0", 0); - }else{ - DWORD exitCode; - if( !GetExitCodeProcess(h, &exitCode) ){ - Tcl_AppendResult(interp, "0", 0); - }else if( exitCode==STILL_ACTIVE ){ - Tcl_AppendResult(interp, "1", 0); - }else{ - Tcl_AppendResult(interp, "0", 0); - } - CloseHandle(h); - } - } -#endif - return rc; -} - -/* -** Kill off all zombie child processes. This is only helpful under Unix. -** On windows, this is a no-op -*/ -static int HarvestZombieObjCmd( - void *NotUsed, - Tcl_Interp *interp, - int objcc, - Tcl_Obj *const* objv -){ -#ifdef UNIX - int status; - while( waitpid(-1, &status, WNOHANG)>0 ); -#endif - return TCL_OK; -} - -#ifdef NEVER -#ifdef UNIX -/* -** Generate a UUID -*/ -static void uuid_generate(unsigned char v[16]){ - int fd = open("/dev/urandom", O_RDONLY); - read(fd, v, 16); - close(fd); -} -#endif - - -/* -** Compute a Universally Unique IDentifier or UUID. (Also sometimes called -** a Globally Unique IDentifier or GUID.) Return the UUID as a base-64 -** encoded string. -*/ -static int GetUuid64( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *const* objv -){ - unsigned char v[16]; - char zOut[23]; - int i, n; - static const unsigned char zBase[] = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz-"; - - -#ifdef UNIX - uuid_generate(v); -#endif -#ifdef WIN32 - UuidCreate((UUID*)v); -#endif - for(i=n=0; i<15; i+=3){ - zOut[n++] = zBase[ (v[i]>>2) & 0x3f ]; - zOut[n++] = zBase[ ((v[i]<<4) & 0x30) | ((v[i+1]>>4) & 0x0f) ]; - zOut[n++] = zBase[ ((v[i+1]<<2) & 0x3c) | ((v[i+2]>>6) & 0x03) ]; - zOut[n++] = zBase[ v[i+2] & 0x3f ]; - } - zOut[n++] = zBase[ (v[i]>>2) & 0x3f ]; - zOut[n++] = zBase[ ((v[i]<<4) & 0x30) ]; - zOut[n] = 0; - Tcl_SetObjResult(interp, Tcl_NewStringObj(zOut, 22)); - return TCL_OK; -} - -/* -** Compute a Universally Unique IDentifier or UUID. (Also sometimes called -** a Globally Unique IDentifier or GUID.) Return the UUID as 64-bit integer. -*/ -static int GetUuidInt64( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *const* objv -){ - unsigned char v[16]; - Tcl_WideInt w1, w2; - -#ifdef UNIX - uuid_generate(v); -#endif -#ifdef WIN32 - UuidCreate((UUID*)v); -#endif - memcpy(&w1, v, sizeof(w1)); - memcpy(&w2, &v[16-sizeof(w2)], sizeof(w2)); - w1 ^= w2; - if( w1<0 ){ - w1 = -w1; - if( w1<0 ) w1--; - } - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(w1)); - return TCL_OK; -} - -/* -** Compute a Universally Unique IDentifier or UUID. (Also sometimes called -** a Globally Unique IDentifier or GUID.) Return the UUID as a base-32 -** encoded string. -*/ -static int GetUuid32( - void *NotUsed, - Tcl_Interp *interp, - int objc, - Tcl_Obj *const* objv -){ - int nOut; - unsigned char v[16]; - unsigned char zOut[28]; - extern int encode32(const unsigned char*, unsigned char*, int); - if( objc==1 ){ - nOut = 9; - }else{ - if( Tcl_GetIntFromObj(interp, objv[1], &nOut) ) return TCL_ERROR; - if( nOut<=0 || nOut>24 ){ - Tcl_AppendResult(interp, "number of digits should be between 1 and 24", - 0); - return TCL_ERROR; - } - } - -#ifdef UNIX - uuid_generate(v); -#endif -#ifdef WIN32 - UuidCreate((UUID*)v); -#endif - encode32(v, zOut, 15); - Tcl_SetObjResult(interp, Tcl_NewStringObj((char*)zOut, nOut)); - return TCL_OK; -} -#endif -#ifdef UNIX -/* -** This routine returns the size of the currently running program in kilobytes. -** It returns 0 on failure. -*/ -static int GetMemory(void){ - char *zFmt = "/proc/%d/statm"; - char *zFile = ckalloc( strlen(zFmt) + 32 + 1 ); - FILE *pFile; - int progSize = 0; - sprintf(zFile, zFmt, getpid()); - pFile = fopen(zFile, "r"); - ckfree(zFile); - if( pFile ){ - fscanf(pFile, "%d", &progSize); - fclose(pFile); - } - return progSize*4; -} -#endif - -/* -** tclcmd: memory -** title: Return memory statistics for the currently running process -** -** This proc returns the current resident set size of this process. -** Under Windows it throws an error. -*/ -static int MemoryCmd(void *NotUsed, Tcl_Interp *interp, int argc, char **argv){ - char res[33]; - if( argc!=1 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 0); - return TCL_ERROR; - } -#ifdef UNIX - sprintf(res, "%d", GetMemory()); - Tcl_AppendResult(interp, res, 0); - return TCL_OK; -#else - Tcl_AppendResult(interp, "Sorry, memory not available under Windows", 0); - return TCL_ERROR; -#endif -} - -#ifdef WIN32 -/* -** tclcmd: registry_get ROOTKEY KEY DATA -** title: Retrieve a registry setting in windows. -** -** Tcl contains a build-in "registry get" command. But it requires some -** special linking and it is omitted from our library. So we supply the -** following "registry_get" command as an alternative. -** for use by the installer. -*/ -static int registryGet(void *NotUsed, Tcl_Interp *interp, int argc, char **argv){ - HKEY hKey = 0; - DWORD dw = 0; - DWORD dwType; - LONG rc; - HKEY keyClass = 0; - char zBuf[2000]; - if( argc!=3 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " CLASS KEY\"", 0); - return TCL_ERROR; - } - if( strcmp(argv[1],"HKEY_CLASSES_ROOT")==0 ){ - keyClass = HKEY_CLASSES_ROOT; - }else if( strcmp(argv[1],"HKEY_CURRENT_USER")==0 ){ - keyClass = HKEY_CURRENT_USER; - }else if( strcmp(argv[1],"HKEY_LOCAL_MACHINE")==0 ){ - keyClass = HKEY_LOCAL_MACHINE; - }else if( strcmp(argv[1],"HKEY_USERS")==0 ){ - keyClass = HKEY_USERS; - }else if( strcmp(argv[1],"HKEY_CURRENT_CONFIG")==0 ){ - keyClass = HKEY_CURRENT_CONFIG; - }else if( strcmp(argv[1],"HKEY_DYN_DATA")==0 ){ - keyClass = HKEY_DYN_DATA; - }else{ - Tcl_AppendResult(interp, "unknown registry key: ", argv[1], 0); - return TCL_ERROR; - } -#if 0 - rc = RegCreateKeyEx(keyClass, argv[2], - 0, "", REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, NULL, &hKey, &dw); - if( rc!=ERROR_SUCCESS ){ - Tcl_AppendResult(interp, "RegCreateKeyEx() returns an error", 0); - return TCL_ERROR; - } - rc = RegSetValueEx(hKey, NULL, 0, REG_SZ, argv[3], strlen(argv[3])); - RegCloseKey(hKey); -#endif - rc = RegOpenKeyEx(keyClass, argv[2], 0, KEY_ALL_ACCESS, &hKey); - if( rc!=ERROR_SUCCESS ){ - Tcl_AppendResult(interp, "RegOpenKeyEx() returns an error", 0); - return TCL_ERROR; - } - dw = sizeof(zBuf)-1; - dwType = REG_SZ; - rc = RegQueryValueEx(hKey, "", 0, &dwType, zBuf, &dw); - if( rc!=ERROR_SUCCESS ){ - Tcl_AppendResult(interp, "RegQueryValueEx() returns an error", 0); - return TCL_ERROR; - } - zBuf[dw] = 0; - Tcl_AppendResult(interp, zBuf, 0); - return TCL_OK; -} -#endif - -/* -** Encode a string for HTTP. This means converting lots of -** characters into the "%HH" where H is a hex digit. It also -** means converting spaces to "+". -** -** This is the opposite of DeHttpizeString below. -*/ -char *HttpizeString(const char *zIn, int encodeSlash){ - int c; - int i = 0; - int count = 0; - char *zOut; - int other; -# define IsSafeChar(X) \ - (isalnum(X) || (X)=='.' || (X)=='$' || (X)=='-' || (X)=='_' || (X)==other) - - if( zIn==0 ){ - zOut = ckalloc( 4 ); - if( zOut==0 ) return 0; - strcpy(zOut, "%00"); - return zOut; - } - other = encodeSlash ? 'a' : '/'; - while( (c = zIn[i])!=0 ){ - if( IsSafeChar(c) || c==' ' ){ - count++; - }else{ - count += 3; - } - i++; - } - i = 0; - zOut = ckalloc( count+1 ); - if( zOut==0 ) return 0; - while( (c = *zIn)!=0 ){ - if( IsSafeChar(c) ){ - zOut[i++] = c; - }else if( c==' ' ){ - zOut[i++] = '+'; - }else{ - zOut[i++] = '%'; - zOut[i++] = "0123456789ABCDEF"[(c>>4)&0xf]; - zOut[i++] = "0123456789ABCDEF"[c&0xf]; - } - zIn++; - } - zOut[i] = 0; - return zOut; -} - -/* -** This routine returns TRUE if the given time is considered to be a null time. -*/ -int TimeIsNull(double dtime){ - return dtime>=-0.5 && dtime<0.5; -} - -/* -** This routine returns TRUE if the given call time is considered to -** be the ABORT time. -*/ -int CalltimeIsAbort(double dtime){ - return dtime<-0.5; -} - -/* -** For convenience sake, we define the arguments to a Tcl string command. -*/ -#define TCLARGS void*ClientData,Tcl_Interp*interp,int argc,const char**argv -#define TCLOBJS void*ClientData,Tcl_Interp*interp,int objc,Tcl_Obj*CONST*objv - -/* -** tclcmd: httpize TEXT -** title: Escape characters that have special meaning within URLs -** -** This command escapes special characters in an arbitrary piece -** of input text according to the rules of HTTP. Spaces are converted -** to "+" and other special characters are converted into a three-letter -** code consisting of a "%" followed by two hex digits that define the -** ASCII value of the character. The resulting string is safe to -** use as part of a URL. -*/ -static int HttpizeCmd(TCLARGS){ - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " STRING\"", 0); - return TCL_ERROR; - } - Tcl_SetResult(interp, HttpizeString(argv[1],1), TCL_DYNAMIC); - return TCL_OK; -} - -/* -** tclcmd: urlize TEXT -** title: Escape characters that have special meaning within URLs -** -** This command works just like the httpize command except that -** it does not encode the "/" symbol. -*/ -static int UrlizeCmd(TCLARGS){ - if( argc!=2 ){ - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " STRING\"", 0); - return TCL_ERROR; - } - Tcl_SetResult(interp, HttpizeString(argv[1],0), TCL_DYNAMIC); - return TCL_OK; -} - -/* -** Convert a single HEX digit to an integer -*/ -static int AsciiToHex(int c){ - if( c>='a' && c<='f' ){ - c += 10 - 'a'; - }else if( c>='A' && c<='F' ){ - c += 10 - 'A'; - }else if( c>='0' && c<='9' ){ - c -= '0'; - }else{ - c = 0; - } - return c; -} - -/* -** Remove the HTTP encodings from a string and construct a Tcl_Obj to -** hold the result. -*/ -static Tcl_Obj *DeHttpizeString(const char *z, int n){ - int i, j; - char *zNew = ckalloc( n+1 ); - Tcl_Obj *pObj; - i = j = 0; - - while( i/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 - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; 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 - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# 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 - test -z "$as_dir" && as_dir=. - 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 - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# 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'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -as_fn_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="if test -n \"\${ZSH_VERSION+set}\" && (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 - 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 - exitcode=1; echo positional parameters were not saved. -fi -test x\$exitcode = x0 || 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_have_required=no -fi - if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : - -else - 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 - test -z "$as_dir" && as_dir=. - 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_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : - CONFIG_SHELL=$as_shell as_have_required=yes - if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : - break 2 -fi -fi - done;; - esac - as_found=false -done -$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && - { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : - CONFIG_SHELL=$SHELL as_have_required=yes -fi; } -IFS=$as_save_IFS - - - 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'. -$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 -exit 255 -fi - - if test x$as_have_required = xno; then : - $as_echo "$0: This script requires a shell more modern than all" - $as_echo "$0: the shells that I found on your system." - if test x${ZSH_VERSION+set} = xset ; then - $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" - $as_echo "$0: be upgraded to zsh 4.3.4 or later." - else - $as_echo "$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_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=`$as_echo "$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 || -$as_echo 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_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_fn_arith () - { - as_val=`expr "$@" || test $? -eq 1` - } -fi # as_fn_arith - - -# 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 - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$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 || -$as_echo 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" || - { $as_echo "$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 -} - -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 - -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='odielib' -PACKAGE_TARNAME='odielib' -PACKAGE_VERSION='2.1' -PACKAGE_STRING='odielib 2.1' -PACKAGE_BUGREPORT='' -PACKAGE_URL='' - -# Factoring default headers for most tests. -ac_includes_default="\ -#include -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_STRING_H -# if !defined STDC_HEADERS && defined HAVE_MEMORY_H -# include -# endif -# include -#endif -#ifdef HAVE_STRINGS_H -# include -#endif -#ifdef HAVE_INTTYPES_H -# include -#endif -#ifdef HAVE_STDINT_H -# include -#endif -#ifdef HAVE_UNISTD_H -# include -#endif" - -ac_subst_vars='ODIE_ZIPDIR_PATH -ODIE_DOWNLOAD_PATH -ODIE_SANDBOX_PATH -TK_RES -RES -RC -INSTALL_STUB_LIB -DLL_INSTALL_DIR -INSTALL_LIB -MAKE_STUB_LIB -MAKE_LIB -SHLIB_SUFFIX -SHLIB_CFLAGS -SHLIB_LD_LIBS -TK_SHLIB_LD_EXTRAS -TCL_SHLIB_LD_EXTRAS -SHLIB_LD -STLIB_LD -LD_SEARCH_FLAGS -CC_SEARCH_FLAGS -LDFLAGS_OPTIMIZE -LDFLAGS_DEBUG -LDAIX_SRC -PLAT_SRCS -PLAT_OBJS -DL_OBJS -TCL_LIBS -LIBOBJS -AR -RANLIB -CFLAGS_WARNING -CFLAGS_OPTIMIZE -CFLAGS_DEBUG -DL_LIBS -CELIB_DIR -EGREP -GREP -CPP -TCL_THREADS -GIT_PROG -FOSSIL_PROG -FOSSIL_CHECKOUT -STRIP_PROG -UNZIP_PROG -ZIP_PROG -VFS_CP -ODIE_WINDOW_SYSTEM -ODIE_BINARY_PLATFORM -ODIE_CPU -ODIE_TK_CONFIG_FLAGS -ODIE_TCL_CONFIG_FLAGS -ODIE_OS -ODIE_SYSTEM -ODIE_PLATFORM_DIR -ODIE_TCLSRC_DIR -ODIE_PLATFORM -ODIE_BUILD_64BIT -ODIE_BUILD_SYSTEM -ODIE_BUILD_OS -ODIE_TARGET -ODIE_HOST -MKHDR_PROG -TOADKIT_PROG -TKKIT_PROG -TCLKIT_PROG -WISH_PROG -ODIE_SRC_DIR -TCLSH_PROG -CYGPATH -OBJEXT -EXEEXT -ac_ct_CC -CPPFLAGS -LDFLAGS -CFLAGS -CC -TK_FOSSIL_BRANCH -TCL_FOSSIL_BRANCH -TK_PATCH_LEVEL -TK_MINOR_VERSION -TK_MAJOR_VERSION -TK_VERSION -TCL_PATCH_LEVEL -TCL_MINOR_VERSION -TCL_MAJOR_VERSION -TCL_VERSION -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 -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_sandbox -with_download -with_zipdir -with_tclbranch -with_tkbranch -enable_64bit -enable_cocoa -enable_corefoundation -enable_threads -with_encoding -enable_shared -enable_wince -with_celib -enable_64bit_vis -enable_rpath -enable_load -' - 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' -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 - - # Accept the important Cygnus configure options, so we can diagnose typos. - - 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=`$as_echo "$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=`$as_echo "$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 ;; - - -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=`$as_echo "$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=`$as_echo "$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. - $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 - expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && - $as_echo "$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" ;; - *) $as_echo "$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 -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 || -$as_echo 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 odielib 2.1 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] - --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/odielib] - --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 odielib 2.1:";; - 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-64bit enable 64bit support (where applicable) - --enable-cocoa enable cocoa support (where applicable) - --enable-corefoundation enable core foundation support (where applicable) - --enable-threads build with threads (default: on) - --enable-shared build and link with shared libraries (default: on) - --enable-wince enable Win/CE support (where applicable) - --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-corefoundation use CoreFoundation API on MacOSX (default: on) - --enable-load allow dynamic loading and "load" command (default: - on) - -Optional Packages: - --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] - --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) - --with-sandbox Writable location for builds - --with-download Writable location for downloading source - --with-zipdir Writable location for installing packages - --with-tclbranch Branch of the Tcl core to build against - --with-tkbranch Branch of the Tk core to build against - --with-encoding encoding for configuration values (default: - iso8859-1) - --with-celib=DIR use Windows/CE support library from DIR - -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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$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 guested configure. - 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 - $as_echo "$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 -odielib configure 2.1 -generated by GNU Autoconf 2.69 - -Copyright (C) 2012 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 - 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\"" -$as_echo "$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 - $as_echo "$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_echo "$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_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$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\"" -$as_echo "$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 - $as_echo "$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_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#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 () -{ -return $2 (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_func - -# 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\"" -$as_echo "$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 - $as_echo "$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_echo "$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_check_header_mongrel LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if eval \${$3+:} false; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.i conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_mongrel - -# ac_fn_c_try_run LINENO -# ---------------------- -# Try to link 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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; }; then : - ac_retval=0 -else - $as_echo "$as_me: program exited with status $ac_status" >&5 - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_header_compile - -# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES -# --------------------------------------------- -# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR -# accordingly. -ac_fn_c_check_decl () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - as_decl_name=`echo $2|sed 's/ *(.*//'` - as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 -$as_echo_n "checking whether $as_decl_name is declared... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -int -main () -{ -#ifndef $as_decl_name -#ifdef __cplusplus - (void) $as_decl_use; -#else - (void) $as_decl_name; -#endif -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_decl -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 odielib $as_me 2.1, which was -generated by GNU Autoconf 2.69. Invocation command line was - - $ $0 $@ - -_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 - test -z "$as_dir" && as_dir=. - $as_echo "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=`$as_echo "$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=$? - # Save into config.log some information that might help in debugging. - { - echo - - $as_echo "## ---------------- ## -## 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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$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 - - $as_echo "## ----------------- ## -## Output variables. ## -## ----------------- ##" - echo - for ac_var in $ac_subst_vars - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - - if test -n "$ac_subst_files"; then - $as_echo "## ------------------- ## -## File substitutions. ## -## ------------------- ##" - echo - for ac_var in $ac_subst_files - do - eval ac_val=\$$ac_var - case $ac_val in - *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; - esac - $as_echo "$ac_var='\''$ac_val'\''" - done | sort - echo - fi - - if test -s confdefs.h; then - $as_echo "## ----------- ## -## confdefs.h. ## -## ----------- ##" - echo - cat confdefs.h - echo - fi - test "$ac_signal" != 0 && - $as_echo "$as_me: caught signal $ac_signal" - $as_echo "$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 - -$as_echo "/* confdefs.h */" > confdefs.h - -# Predefined preprocessor variables. - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_NAME "$PACKAGE_NAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_TARNAME "$PACKAGE_TARNAME" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_VERSION "$PACKAGE_VERSION" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_STRING "$PACKAGE_STRING" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" -_ACEOF - -cat >>confdefs.h <<_ACEOF -#define PACKAGE_URL "$PACKAGE_URL" -_ACEOF - - -# Let the site file select an alternate cache file if it wants to. -# Prefer an explicitly selected file to automatically selected ones. -ac_site_file1=NONE -ac_site_file2=NONE -if test -n "$CONFIG_SITE"; then - # We do not want a PATH search for config.site. - case $CONFIG_SITE in #(( - -*) ac_site_file1=./$CONFIG_SITE;; - */*) ac_site_file1=$CONFIG_SITE;; - *) ac_site_file1=./$CONFIG_SITE;; - esac -elif test "x$prefix" != xNONE; then - ac_site_file1=$prefix/share/config.site - ac_site_file2=$prefix/etc/config.site -else - ac_site_file1=$ac_default_prefix/share/config.site - ac_site_file2=$ac_default_prefix/etc/config.site -fi -for ac_site_file in "$ac_site_file1" "$ac_site_file2" -do - test "x$ac_site_file" = xNONE && continue - if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 -$as_echo "$as_me: loading site script $ac_site_file" >&6;} - sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" \ - || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 -$as_echo "$as_me: loading cache $cache_file" >&6;} - case $cache_file in - [\\/]* | ?:[\\/]* ) . "$cache_file";; - *) . "./$cache_file";; - esac - fi -else - { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 -$as_echo "$as_me: creating cache $cache_file" >&6;} - >$cache_file -fi - -# 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,) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 -$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} - ac_cache_corrupted=: ;; - ,set) - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 -$as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 -$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} - ac_cache_corrupted=: - else - { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 -$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} - eval $ac_var=\$ac_old_val - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 -$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 -$as_echo "$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=`$as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 -$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error $? "run \`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 - - - - - - - - -TCL_VERSION=8.6 -TCL_MAJOR_VERSION=8 -TCL_MINOR_VERSION=6 -TCL_PATCH_LEVEL=".2" -TK_VERSION=8.6 -TK_MAJOR_VERSION=8 -TK_MINOR_VERSION=6 -TK_PATCH_LEVEL=".2" -VERSION=${TCL_VERSION} - - - - - - - - - - -#------------------------------------------------------------------------ -# Setup configure arguments for bundled packages -#------------------------------------------------------------------------ - -PKG_CFG_ARGS="$ac_configure_args ${PKG_CFG_ARGS}" - -if test -r "$cache_file" -a -f "$cache_file"; then - case $cache_file in - [\\/]* | ?:[\\/]* ) pkg_cache_file=$cache_file ;; - *) pkg_cache_file=../../$cache_file ;; - esac - PKG_CFG_ARGS="${PKG_CFG_ARGS} --cache-file=$pkg_cache_file" -fi - -#------------------------------------------------------------------------ -# Handle the --prefix=... option -#------------------------------------------------------------------------ - -if test "${prefix}" = "NONE"; then - if test "${ODIE_PLATFORM}" = "windows" ; then - prefix=c:/odie - else - prefix=$HOME/odie - fi -fi -if test "${exec_prefix}" = "NONE"; then - exec_prefix=$prefix -fi -ODIE_SANDBOX_PATH=${prefix}/sandbox -ODIE_DOWNLOAD_PATH=${prefix}/download -ODIE_ZIPDIR_PATH=${prefix}/zipdir - - -#---- -# Handle the --sandbox=... option -#--- -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Sandbox location" >&5 -$as_echo_n "checking Sandbox location... " >&6; } - -# Check whether --with-sandbox was given. -if test "${with_sandbox+set}" = set; then : - withval=$with_sandbox; ODIE_SANDBOX_PATH=$withval -else - ODIE_SANDBOX_PATH='${prefix}/sandbox' -fi - - -#---- -# Handle the --download=... option -#--- -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Download location" >&5 -$as_echo_n "checking Download location... " >&6; } - -# Check whether --with-download was given. -if test "${with_download+set}" = set; then : - withval=$with_download; ODIE_DOWNLOAD_PATH=$withval -else - ODIE_DOWNLOAD_PATH='${prefix}/download' -fi - - -#---- -# Handle the --zipdir=... option -#--- -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Zipdir location" >&5 -$as_echo_n "checking Zipdir location... " >&6; } - -# Check whether --with-zipdir was given. -if test "${with_zipdir+set}" = set; then : - withval=$with_zipdir; ODIE_ZIPDIR_PATH=$withval -else - ODIE_ZIPDIR_PATH='${prefix}/zipdir' -fi - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Tcl Fossil Version Tab Branch" >&5 -$as_echo_n "checking Tcl Fossil Version Tab Branch... " >&6; } - -# Check whether --with-tclbranch was given. -if test "${with_tclbranch+set}" = set; then : - withval=$with_tclbranch; TCL_FOSSIL_BRANCH=$withval -else - TCL_FOSSIL_BRANCH=core-8-6-3 -fi - - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking Tk Fossil Version Tab Branch" >&5 -$as_echo_n "checking Tk Fossil Version Tab Branch... " >&6; } - -# Check whether --with-tkbranch was given. -if test "${with_tkbranch+set}" = set; then : - withval=$with_tkbranch; TK_FOSSIL_BRANCH=$withval -else - TK_FOSSIL_BRANCH=${TCL_FOSSIL_BRANCH} -fi - - - -# Make sure srcdir is fully qualified! -srcdir="`cd "$srcdir" ; pwd`" -TCL_SRC_DIR="`cd "$srcdir"/..; pwd`" - - -#------------------------------------------------------------------------ -# Standard compiler checks -#------------------------------------------------------------------------ - -# If the user did not set CFLAGS, set it now to keep -# the AC_PROG_CC macro from adding "-g -O2". -if test "${CFLAGS+set}" != "set" ; then - CFLAGS="" -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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$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. -$as_echo "$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; 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\"" -$as_echo "$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 - $as_echo "$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 () -{ - - ; - 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. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 -$as_echo_n "checking whether the C compiler works... " >&6; } -ac_link_default=`$as_echo "$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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link_default") 2>&5 - ac_status=$? - $as_echo "$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+set}" = set && 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 - ac_file='' -fi -if test -z "$ac_file"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -$as_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$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_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 -$as_echo_n "checking for C compiler default output file name... " >&6; } -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 -$as_echo "$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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 -$as_echo_n "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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$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_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 -$as_echo "$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 () -{ -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. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 -$as_echo_n "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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_link") 2>&5 - ac_status=$? - $as_echo "$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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_try") 2>&5 - ac_status=$? - $as_echo "$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 - { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "cannot run C compiled programs. -If you meant to cross compile, use \`--host'. -See \`config.log' for more details" "$LINENO" 5; } - fi - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 -$as_echo "$cross_compiling" >&6; } - -rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out -ac_clean_files=$ac_clean_files_save -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 -$as_echo_n "checking for suffix of object files... " >&6; } -if ${ac_cv_objext+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - 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\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compile") 2>&5 - ac_status=$? - $as_echo "$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_echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - -{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 -$as_echo "$ac_cv_objext" >&6; } -OBJEXT=$ac_cv_objext -ac_objext=$OBJEXT -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - 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.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; 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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*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 don't provoke an error unfortunately, instead are silently treated - as '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's necessary to write '\x00'==0 to get something - that's 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 **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_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 - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -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 - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 -$as_echo_n "checking for inline... " >&6; } -if ${ac_cv_c_inline+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_c_inline=no -for ac_kw in inline __inline__ __inline; do - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#ifndef __cplusplus -typedef int foo_t; -static $ac_kw foo_t static_foo () {return 0; } -$ac_kw foo_t foo () {return 0; } -#endif - -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_c_inline=$ac_kw -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - test "$ac_cv_c_inline" != no && break -done - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 -$as_echo "$ac_cv_c_inline" >&6; } - -case $ac_cv_c_inline in - inline | yes) ;; - *) - case $ac_cv_c_inline in - no) ac_val=;; - *) ac_val=$ac_cv_c_inline;; - esac - cat >>confdefs.h <<_ACEOF -#ifndef __cplusplus -#define inline $ac_val -#endif -_ACEOF - ;; -esac - - -#-------------------------------------------------------------------- -# Determines the correct executable file extension (.exe) -#-------------------------------------------------------------------- - - - - ### - # Gather and store information about the local OS - ### - VFS_CP="cp -a" - ODIE_SRC_DIR=`pwd` - ODIE_BINARY_PLATFORM="unknown" - ODIE_TEA_CONFIG_FLAGS="" - case "`uname -s`" in - *win32*|*WIN32*|*MINGW32_*) - # Extract the first word of "cygpath", so it can be a program name with args. -set dummy cygpath; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CYGPATH+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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 -w" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 -$as_echo "$CYGPATH" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - EXEEXT=".exe" - ODIE_PLATFORM="windows" - ODIE_SRC_DIR=`pwd -W` - VFS_CP="cp -a --no-preserve=links" - ;; - *CYGWIN_*) - CYGPATH=echo - EXEEXT=".exe" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking platform" >&5 -$as_echo_n "checking platform... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - #ifdef _WIN32 - #error win32 - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ODIE_PLATFORM="unix" -else - ODIE_PLATFORM="windows" - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ODIE_SRC_DIR=`pwd -W` - ;; - *) - CYGPATH=echo - # Maybe we are cross-compiling.... - case ${host_alias} in - *mingw32*) - EXEEXT=".exe" - ODIE_PLATFORM="windows" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 -$as_echo_n "checking for tclsh... " >&6; } - if ${ac_cv_path_tclsh+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${prefix}/bin /opt/local/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - for j in `ls -r $dir/tclsh[8-9]6-9* 2> /dev/null` \ - `ls -r $dir/tclsh* 2> /dev/null` ; do - if test x"$ac_cv_path_tclsh" = x ; then - if test -f "$j" ; then - ac_cv_path_tclsh=$j - break - fi - fi - done - done - -fi - - - if test -f "$ac_cv_path_tclsh" ; then - TCLSH_PROG="$ac_cv_path_tclsh" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TCLSH_PROG" >&5 -$as_echo "$TCLSH_PROG" >&6; } - else - # It is not an error if an installed version of Tcl can't be located. - TCLSH_PROG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: No tclsh found on PATH" >&5 -$as_echo "No tclsh found on PATH" >&6; } - fi - - - ;; - *) - EXEEXT="" - ODIE_PLATFORM="unix" - ;; - esac - ;; - esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ODIE_PLATFORM" >&5 -$as_echo "$ODIE_PLATFORM" >&6; } - - - - - - - ODIE_CPU=`uname -m` - ODIE_BUILD_SYSTEM=`uname -s`-${ODIE_CPU} - # TEA specific: - if test "${ODIE_PLATFORM}" = "windows" ; then - ODIE_SYSTEM=windows - TCLSH_PROG='${exec_prefix}/bin/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}.exe' - WISH_PROG='${exec_prefix}/bin/wish${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}.exe' - TCLKIT_PROG='${exec_prefix}/bin/tclkit${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}.exe' - TKKIT_PROG='${exec_prefix}/bin/tkkit${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}.exe' - TOADKIT_PROG='${exec_prefix}/bin/toadkit${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}.exe' - else - ODIE_SYSTEM=`uname -s`-`uname -r` - TCLSH_PROG='${exec_prefix}/bin/tclsh${TCL_VERSION}' - WISH_PROG='${exec_prefix}/bin/wish${TCL_VERSION}' - TCLKIT_PROG='${exec_prefix}/bin/tclkit${TCL_VERSION}' - TKKIT_PROG='${exec_prefix}/bin/tkkit${TCL_VERSION}' - TOADKIT_PROG='${exec_prefix}/bin/toadkit${TCL_VERSION}' - if test "$?" -ne 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 -$as_echo "$as_me: WARNING: can't find uname command" >&2;} - ODIE_SYSTEM=unknown - else - if test "`uname -s`" = "AIX" ; then - ODIE_SYSTEM=AIX-`uname -v`.`uname -r` - fi - fi - fi - ODIE_OS="generic" - ODIE_TCLSRC_DIR="unix" - ODIE_PLATFORM_DIR="unix" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 -$as_echo_n "checking if 64bit support is requested... " >&6; } - # Check whether --enable-64bit was given. -if test "${enable_64bit+set}" = set; then : - enableval=$enable_64bit; do64bit=$enableval -else - do64bit=detect -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 -$as_echo "$do64bit" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if cocoa support is requested" >&5 -$as_echo_n "checking if cocoa support is requested... " >&6; } - # Check whether --enable-cocoa was given. -if test "${enable_cocoa+set}" = set; then : - enableval=$enable_cocoa; doCocoa=$enableval -else - doCocoa=yes -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doCocoa" >&5 -$as_echo "$doCocoa" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if corefoundation support is requested" >&5 -$as_echo_n "checking if corefoundation support is requested... " >&6; } - # Check whether --enable-corefoundation was given. -if test "${enable_corefoundation+set}" = set; then : - enableval=$enable_corefoundation; doCorefoundation=$enableval -else - doCorefoundation=yes -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doCorefoundation" >&5 -$as_echo "$doCorefoundation" >&6; } - - - ODIE_BUILD_64BIT=$do64bit - case "$do64bit" in - amd64|x64|yes) - ODIE_TCL_CONFIG_FLAGS='--enable-64bit' - ODIE_TK_CONFIG_FLAGS='--enable-64bit' - ;; - 0|no) - if test "${ODIE_CPU}" = "x86_64" ; then - ${ODIE_CPU}="ix86" - fi - ODIE_TCL_CONFIG_FLAGS='--enable-64bit=no' - ODIE_TK_CONFIG_FLAGS='--enable-64bit=no' - ;; - detect) - case "${ODIE_CPU}" in - amd64|x64|x86_64) - ODIE_BUILD_64BIT="yes" - ;; - *) - ODIE_BUILD_64BIT="no" - ;; - esac - ;; - *) - case "${ODIE_CPU}" in - amd64|x64|x86_64) - ODIE_BUILD_64BIT="yes" - ;; - esac - ODIE_TCL_CONFIG_FLAGS= - ODIE_TK_CONFIG_FLAGS= - ;; - esac - - case $ODIE_SYSTEM in - windows*) - ODIE_WINDOW_SYSTEM="windows" - ODIE_OS="windows" - ODIE_TCLSRC_DIR="win" - ODIE_PLATFORM_DIR="win" - ODIE_BUILD_TCLSH= - ODIE_BINARY_PLATFORM="windows-${ODIE_CPU}" - ;; - Linux*) - ODIE_WINDOW_SYSTEM="x11" - ODIE_OS="linux" - ODIE_TCL_CONFIG_FLAGS='' - ODIE_TK_CONFIG_FLAGS=' --enable-xft=no --enable-xss=no' - ODIE_BINARY_PLATFORM="linux-${ODIE_CPU}" - ;; - Darwin-*) - ODIE_OS="macosx" - ODIE_PLATFORM_DIR="macosx" - ODIE_PLATFORM="macosx" - - case "$doCocoa" in - true|1|yes) - ODIE_WINDOW_SYSTEM="cocoa" - ODIE_TK_CONFIG_FLAGS="${ODIE_TK_CONFIG_FLAGS} --enable-aqua=yes" - ;; - *) - ODIE_WINDOW_SYSTEM="x11" - ODIE_TK_CONFIG_FLAGS="${ODIE_TK_CONFIG_FLAGS} --enable-aqua=no" - ;; - esac - case "$doCorefoundation" in - true|1|yes) - ODIE_TCL_CONFIG_FLAGS="${ODIE_TCL_CONFIG_FLAGS} --enable-corefoundation=yes" - ODIE_TK_CONFIG_FLAGS="${ODIE_TK_CONFIG_FLAGS} --enable-corefoundation=yes" - ;; - *) - ODIE_TCL_CONFIG_FLAGS="${ODIE_TCL_CONFIG_FLAGS} --enable-corefoundation=no" - ODIE_TK_CONFIG_FLAGS="${ODIE_TK_CONFIG_FLAGS} --enable-corefoundation=no" - ;; - esac - ODIE_BINARY_PLATFORM="macosx-${ODIE_WINDOW_SYSTEM}-${ODIE_CPU}" - ODIE_TCL_CONFIG_FLAGS="${ODIE_TCL_CONFIG_FLAGS} --enable-framework=no" - ;; - esac - - case $ODIE_BUILD_SYSTEM in - windows*|*win32*|*WIN32*) - FOSSIL_CHECKOUT="_FOSSIL_" - ODIE_BUILD_OS="windows" - ;; - *MINGW32_*|*CYGWIN_*) - FOSSIL_CHECKOUT="_FOSSIL_" - ODIE_BUILD_OS="cygwin" - ;; - Linux*) - ODIE_BUILD_OS="linux" - FOSSIL_CHECKOUT=".fslckout" - ;; - Darwin-*) - ODIE_BUILD_OS="macosx" - FOSSIL_CHECKOUT=".fslckout" - ;; - 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 - TEA_VERSION="3.9" - TEA_PLATFORM=${ODIE_PLATFORM} - ### - # DETECT CROSS COMPILE - ### - ODIE_HOST=$host - ODIE_TARGET=$target - MKHDR_PROG='${exec_prefix}/bin/mkhdr${EXEEXT}' - - - - - - - - - - - - - - - - - - - - - if test "${ODIE_BUILD_OS}" = "cygwin"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking Using ${ODIE_BUILD_OS} zip/unzip" >&5 -$as_echo_n "checking Using ${ODIE_BUILD_OS} zip/unzip... " >&6; } - here=`pwd` - cd /bin ; zipbindir=`pwd -W` ; cd $here - ZIP_PROG=${zipbindir}/zip.exe - UNZIP_PROG=${zipbindir}/unzip.exe - if test ! -f "/bin/zip.exe" ; then - mingw-get.exe install msys-zip - fi - if test ! -f "/bin/unzip.exe" ; then - mingw-get.exe install msys-unzip - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG" >&5 -$as_echo "$ZIP_PROG" >&6; } - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNZIP_PROG" >&5 -$as_echo "$UNZIP_PROG" >&6; } - - else - if ${ac_cv_path_zip+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - for j in `ls -r $dir/zip 2> /dev/null` ; do - if test x"$ac_cv_path_zip" = x ; then - if test -f "$j" ; then - ac_cv_path_zip=$j - break - fi - fi - done - done - -fi - - if ${ac_cv_path_unzip+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - for j in `ls -r $dir/unzip.exe 2> /dev/null` `ls -r $dir/unzip 2> /dev/null` ; do - if test x"$ac_cv_path_unzip" = x ; then - if test -f "$j" ; then - ac_cv_path_unzip=$j - break - fi - fi - done - done - -fi - - if test -f "$ac_cv_path_zip" ; then - ZIP_PROG="$ac_cv_path_zip" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ZIP_PROG" >&5 -$as_echo "$ZIP_PROG" >&6; } - else - # It is not an error if an installed version of Tcl can't be located. - ZIP_PROG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: No zip found on PATH" >&5 -$as_echo "No zip found on PATH" >&6; } - fi - if test -f "$ac_cv_path_unzip" ; then - UNZIP_PROG="$ac_cv_path_unzip" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $UNZIP_PROG" >&5 -$as_echo "$UNZIP_PROG" >&6; } - else - # It is not an error if an installed version of Tcl can't be located. - UNZIP_PROG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: No unzip found on PATH" >&5 -$as_echo "No unzip found on PATH" >&6; } - fi - - - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strip" >&5 -$as_echo_n "checking for strip... " >&6; } - if ${ac_cv_path_strip+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - for j in `ls -r $dir/strip 2> /dev/null` \ - `ls -r $dir/strip.exe 2> /dev/null` ; do - if test x"$ac_cv_path_strip" = x ; then - if test -f "$j" ; then - ac_cv_path_strip=$j - break - fi - fi - done - done - -fi - - - if test -f "$ac_cv_path_strip" ; then - STRIP_PROG="$ac_cv_path_strip" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP_PROG" >&5 -$as_echo "$STRIP_PROG" >&6; } - else - # It is not an error if an installed version of Tcl can't be located. - STRIP_PROG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: No strip found on PATH" >&5 -$as_echo "No strip found on PATH" >&6; } - fi - - - - FOSSIL_CHECKOUT=".fslckout" - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fossil" >&5 -$as_echo_n "checking for fossil... " >&6; } - case `uname -s`-`uname -m` in - windows*|*win32*|*WIN32*|*MINGW32_*|*CYGWIN_*) - FOSSIL_CHECKOUT="_FOSSIL_" - if ${ac_cv_path_fossil+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin c:/odie/bin c:/tcl/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - rdir="`(cd $dir ; pwd -W)`" - for j in `ls -r --append-exe $rdir/fossil 2> /dev/null` ; do - if test x"$ac_cv_path_fossil" = x ; then - if test -f "$j" ; then - ac_cv_path_fossil=$j - break - fi - fi - done - done - -fi - - ;; - *) - FOSSIL_CHECKOUT=".fslckout" - if ${ac_cv_path_fossil+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - for j in `ls -r $dir/fossil 2> /dev/null` \ - `ls -r $dir/fossil.exe 2> /dev/null` ; do - if test x"$ac_cv_path_fossil" = x ; then - if test -f "$j" ; then - ac_cv_path_fossil=$j - break - fi - fi - done - done - -fi - - ;; - esac - - - - - if test -f "$ac_cv_path_fossil" ; then - FOSSIL_PROG="$ac_cv_path_fossil" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FOSSIL_PROG" >&5 -$as_echo "$FOSSIL_PROG" >&6; } - else - # It is not an error if an installed version of Tcl can't be located. - FOSSIL_PROG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: No fossil found on PATH" >&5 -$as_echo "No fossil found on PATH" >&6; } - fi - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for git" >&5 -$as_echo_n "checking for git... " >&6; } - case `uname -s`-`uname -m` in - windows*|*win32*|*WIN32*|*MINGW32_*|*CYGWIN_*) - if ${ac_cv_path_git+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin c:/odie/bin c:/tcl/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - rdir="`(cd $dir ; pwd -W)`" - for j in `ls -r --append-exe $rdir/git 2> /dev/null` ; do - if test x"$ac_cv_path_git" = x ; then - if test -f "$j" ; then - ac_cv_path_git=$j - break - fi - fi - done - done - -fi - - ;; - *) - if ${ac_cv_path_git+:} false; then : - $as_echo_n "(cached) " >&6 -else - - search_path=`echo ${exec_prefix}/bin /opt/local/bin ${PATH} | sed -e 's/:/ /g'` - for dir in $search_path ; do - for j in `ls -r $dir/git 2> /dev/null` \ - `ls -r $dir/git.exe 2> /dev/null` ; do - if test x"$ac_cv_path_git" = x ; then - if test -f "$j" ; then - ac_cv_path_git=$j - break - fi - fi - done - done - -fi - - ;; - esac - - - - - if test -f "$ac_cv_path_git" ; then - GIT_PROG="$ac_cv_path_git" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GIT_PROG" >&5 -$as_echo "$GIT_PROG" >&6; } - else - # It is not an error if an installed version of Tcl can't be located. - GIT_PROG="" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: No git found on PATH" >&5 -$as_echo "No git found on PATH" >&6; } - fi - - - - -#------------------------------------------------------------------------ -# 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" && test -n "$GCC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler understands -pipe" >&5 -$as_echo_n "checking if the compiler understands -pipe... " >&6; } -if ${tcl_cv_cc_pipe+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -pipe" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - tcl_cv_cc_pipe=yes -else - tcl_cv_cc_pipe=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - CFLAGS=$hold_cflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_pipe" >&5 -$as_echo "$tcl_cv_cc_pipe" >&6; } - if test $tcl_cv_cc_pipe = yes; then - CFLAGS="$CFLAGS -pipe" - fi -fi - -#------------------------------------------------------------------------ -# Threads support -#------------------------------------------------------------------------ - - - # Check whether --enable-threads was given. -if test "${enable_threads+set}" = set; then : - enableval=$enable_threads; tcl_ok=$enableval -else - tcl_ok=yes -fi - - - if test "${TCL_THREADS}" = 1; then - tcl_threaded_core=1; - fi - - if test "$tcl_ok" = "yes" -o "${TCL_THREADS}" = 1; then - TCL_THREADS=1 - # USE_THREAD_ALLOC tells us to try the special thread-based - # allocator that significantly reduces lock contention - -$as_echo "#define USE_THREAD_ALLOC 1" >>confdefs.h - - -$as_echo "#define _REENTRANT 1" >>confdefs.h - - if test "`uname -s`" = "SunOS" ; then - -$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h - - fi - -$as_echo "#define _THREAD_SAFE 1" >>confdefs.h - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthread" >&5 -$as_echo_n "checking for pthread_mutex_init in -lpthread... " >&6; } -if ${ac_cv_lib_pthread_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthread_pthread_mutex_init=yes -else - ac_cv_lib_pthread_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_pthread_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_pthread_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - 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] - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __pthread_mutex_init in -lpthread" >&5 -$as_echo_n "checking for __pthread_mutex_init in -lpthread... " >&6; } -if ${ac_cv_lib_pthread___pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char __pthread_mutex_init (); -int -main () -{ -return __pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthread___pthread_mutex_init=yes -else - ac_cv_lib_pthread___pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread___pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_pthread___pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_pthread___pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - fi - - if test "$tcl_ok" = "yes"; then - # The space is needed - THREADS_LIBS=" -lpthread" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lpthreads" >&5 -$as_echo_n "checking for pthread_mutex_init in -lpthreads... " >&6; } -if ${ac_cv_lib_pthreads_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_pthreads_pthread_mutex_init=yes -else - ac_cv_lib_pthreads_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_pthreads_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_pthreads_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = "yes"; then - # The space is needed - THREADS_LIBS=" -lpthreads" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc" >&5 -$as_echo_n "checking for pthread_mutex_init in -lc... " >&6; } -if ${ac_cv_lib_c_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -return pthread_mutex_init (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_c_pthread_mutex_init=yes -else - ac_cv_lib_c_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_pthread_mutex_init" >&5 -$as_echo "$ac_cv_lib_c_pthread_mutex_init" >&6; } -if test "x$ac_cv_lib_c_pthread_mutex_init" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_mutex_init in -lc_r" >&5 -$as_echo_n "checking for pthread_mutex_init in -lc_r... " >&6; } -if ${ac_cv_lib_c_r_pthread_mutex_init+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char pthread_mutex_init (); -int -main () -{ -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 - ac_cv_lib_c_r_pthread_mutex_init=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c_r_pthread_mutex_init" >&5 -$as_echo "$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 - tcl_ok=no -fi - - if test "$tcl_ok" = "yes"; then - # The space is needed - THREADS_LIBS=" -pthread" - else - TCL_THREADS=0 - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&5 -$as_echo "$as_me: WARNING: Don't know how to find pthread lib on your system - you must disable thread support or edit the LIBS in the Makefile..." >&2;} - fi - fi - fi - fi - - # Does the pthread-implementation provide - # 'pthread_attr_setstacksize' ? - - ac_saved_libs=$LIBS - LIBS="$LIBS $THREADS_LIBS" - for ac_func in pthread_attr_setstacksize pthread_atfork -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -if eval test \"x\$"$as_ac_var"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - -fi -done - - LIBS=$ac_saved_libs - else - TCL_THREADS=0 - fi - # Do checking message here to not mess up interleaved configure output - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for building with threads" >&5 -$as_echo_n "checking for building with threads... " >&6; } - if test "${TCL_THREADS}" = 1; then - -$as_echo "#define TCL_THREADS 1" >>confdefs.h - - if test "${tcl_threaded_core}" = 1; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes (threaded core)" >&5 -$as_echo "yes (threaded core)" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - fi - - - - -#------------------------------------------------------------------------ -# Embedded configuration information, encoding to use for the values, TIP #59 -#------------------------------------------------------------------------ - - - -# Check whether --with-encoding was given. -if test "${with_encoding+set}" = set; then : - withval=$with_encoding; with_tcencoding=${withval} -fi - - - if test x"${with_tcencoding}" != x ; then - -cat >>confdefs.h <<_ACEOF -#define TCL_CFGVAL_ENCODING "${with_tcencoding}" -_ACEOF - - else - -$as_echo "#define TCL_CFGVAL_ENCODING \"iso8859-1\"" >>confdefs.h - - fi - - -#-------------------------------------------------------------------- -# Look for libraries that we will need when compiling the Tcl shell -#-------------------------------------------------------------------- - -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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 -$as_echo_n "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 ${ac_cv_prog_CPP+:} false; then : - $as_echo_n "(cached) " >&6 -else - # Double quotes because CPP needs to be expanded - for CPP in "$CC -E" "$CC -E -traditional-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. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # 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. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # 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 - # 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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 -$as_echo "$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. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # 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. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - -else - # 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 - # 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_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$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 - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 -$as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if ${ac_cv_path_GREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 -$as_echo "$ac_cv_path_GREP" >&6; } - GREP="$ac_cv_path_GREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 -$as_echo_n "checking for egrep... " >&6; } -if ${ac_cv_path_EGREP+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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 - $as_echo_n 0123456789 >"conftest.in" - while : - do - cat "conftest.in" "conftest.in" >"conftest.tmp" - mv "conftest.tmp" "conftest.in" - cp "conftest.in" "conftest.nl" - $as_echo '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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 -$as_echo "$ac_cv_path_EGREP" >&6; } - EGREP="$ac_cv_path_EGREP" - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 -$as_echo_n "checking for ANSI C header files... " >&6; } -if ${ac_cv_header_stdc+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#include -#include - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_header_stdc=yes -else - ac_cv_header_stdc=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -if test $ac_cv_header_stdc = yes; then - # SunOS 4.x string.h does not declare mem*, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "memchr" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include - -_ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "free" >/dev/null 2>&1; then : - -else - ac_cv_header_stdc=no -fi -rm -f conftest* - -fi - -if test $ac_cv_header_stdc = yes; then - # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. - if test "$cross_compiling" = yes; then : - : -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include -#if ((' ' & 0x0FF) == 0x020) -# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') -# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) -#else -# define ISLOWER(c) \ - (('a' <= (c) && (c) <= 'i') \ - || ('j' <= (c) && (c) <= 'r') \ - || ('s' <= (c) && (c) <= 'z')) -# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) -#endif - -#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) -int -main () -{ - int i; - for (i = 0; i < 256; i++) - if (XOR (islower (i), ISLOWER (i)) - || toupper (i) != TOUPPER (i)) - return 2; - return 0; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - -else - ac_cv_header_stdc=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 -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 -$as_echo "$ac_cv_header_stdc" >&6; } -if test $ac_cv_header_stdc = yes; then - -$as_echo "#define STDC_HEADERS 1" >>confdefs.h - -fi - -# On IRIX 5.3, sys/types and inttypes.h are conflicting. -for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ - inttypes.h stdint.h unistd.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default -" -if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - - - - #-------------------------------------------------------------------- - # On a few very rare systems, all of the libm.a stuff is - # already in libc.a. Set compiler flags accordingly. - # Also, Linux requires the "ieee" library for math to work - # right (and it must appear before "-lm"). - #-------------------------------------------------------------------- - - ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin" -if test "x$ac_cv_func_sin" = xyes; then : - MATH_LIBS="" -else - MATH_LIBS="-lm" -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lieee" >&5 -$as_echo_n "checking for main in -lieee... " >&6; } -if ${ac_cv_lib_ieee_main+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lieee $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_ieee_main=yes -else - ac_cv_lib_ieee_main=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ieee_main" >&5 -$as_echo "$ac_cv_lib_ieee_main" >&6; } -if test "x$ac_cv_lib_ieee_main" = xyes; then : - MATH_LIBS="-lieee $MATH_LIBS" -fi - - - #-------------------------------------------------------------------- - # Interactive UNIX requires -linet instead of -lsocket, plus it - # needs net/errno.h to define the socket-related error codes. - #-------------------------------------------------------------------- - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -linet" >&5 -$as_echo_n "checking for main in -linet... " >&6; } -if ${ac_cv_lib_inet_main+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-linet $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_inet_main=yes -else - ac_cv_lib_inet_main=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_inet_main" >&5 -$as_echo "$ac_cv_lib_inet_main" >&6; } -if test "x$ac_cv_lib_inet_main" = xyes; then : - LIBS="$LIBS -linet" -fi - - ac_fn_c_check_header_mongrel "$LINENO" "net/errno.h" "ac_cv_header_net_errno_h" "$ac_includes_default" -if test "x$ac_cv_header_net_errno_h" = xyes; then : - - -$as_echo "#define HAVE_NET_ERRNO_H 1" >>confdefs.h - -fi - - - - #-------------------------------------------------------------------- - # Check for the existence of the -lsocket and -lnsl libraries. - # The order here is important, so that they end up in the right - # order in the command line generated by make. Here are some - # special considerations: - # 1. Use "connect" and "accept" to check for -lsocket, and - # "gethostbyname" to check for -lnsl. - # 2. Use each function name only once: can't redo a check because - # autoconf caches the results of the last check and won't redo it. - # 3. Use -lnsl and -lsocket only if they supply procedures that - # aren't already present in the normal libraries. This is because - # IRIX 5.2 has libraries, but they aren't needed and they're - # bogus: they goof up name resolution if used. - # 4. On some SVR4 systems, can't use -lsocket without -lnsl too. - # To get around this problem, check for both libraries together - # if -lsocket doesn't work by itself. - #-------------------------------------------------------------------- - - tcl_checkBoth=0 - ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" -if test "x$ac_cv_func_connect" = xyes; then : - tcl_checkSocket=0 -else - tcl_checkSocket=1 -fi - - if test "$tcl_checkSocket" = 1; then - ac_fn_c_check_func "$LINENO" "setsockopt" "ac_cv_func_setsockopt" -if test "x$ac_cv_func_setsockopt" = xyes; then : - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for setsockopt in -lsocket" >&5 -$as_echo_n "checking for setsockopt in -lsocket... " >&6; } -if ${ac_cv_lib_socket_setsockopt+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lsocket $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. */ -#ifdef __cplusplus -extern "C" -#endif -char setsockopt (); -int -main () -{ -return setsockopt (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_socket_setsockopt=yes -else - ac_cv_lib_socket_setsockopt=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_setsockopt" >&5 -$as_echo "$ac_cv_lib_socket_setsockopt" >&6; } -if test "x$ac_cv_lib_socket_setsockopt" = xyes; then : - LIBS="$LIBS -lsocket" -else - tcl_checkBoth=1 -fi - -fi - - fi - if test "$tcl_checkBoth" = 1; then - tk_oldLibs=$LIBS - LIBS="$LIBS -lsocket -lnsl" - ac_fn_c_check_func "$LINENO" "accept" "ac_cv_func_accept" -if test "x$ac_cv_func_accept" = xyes; then : - tcl_checkNsl=0 -else - LIBS=$tk_oldLibs -fi - - fi - ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" -if test "x$ac_cv_func_gethostbyname" = xyes; then : - -else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 -$as_echo_n "checking for gethostbyname in -lnsl... " >&6; } -if ${ac_cv_lib_nsl_gethostbyname+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lnsl $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. */ -#ifdef __cplusplus -extern "C" -#endif -char gethostbyname (); -int -main () -{ -return gethostbyname (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_nsl_gethostbyname=yes -else - ac_cv_lib_nsl_gethostbyname=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 -$as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } -if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : - LIBS="$LIBS -lnsl" -fi - -fi - - - -# Add the threads support libraries -LIBS="$LIBS$THREADS_LIBS" - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to build libraries" >&5 -$as_echo_n "checking how to build libraries... " >&6; } - # Check whether --enable-shared was given. -if test "${enable_shared+set}" = set; then : - enableval=$enable_shared; tcl_ok=$enableval -else - tcl_ok=yes -fi - - - if test "${enable_shared+set}" = set; then - enableval="$enable_shared" - tcl_ok=$enableval - else - tcl_ok=yes - fi - - if test "$tcl_ok" = "yes" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: shared" >&5 -$as_echo "shared" >&6; } - SHARED_BUILD=1 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5 -$as_echo "static" >&6; } - SHARED_BUILD=0 - -$as_echo "#define STATIC_BUILD 1" >>confdefs.h - - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tclsh" >&5 -$as_echo_n "checking for tclsh... " >&6; } - if test -f "${TCL_BIN_DIR}/Makefile" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Using Tcl in TCL_BIN_DIR $TEA_PLATFORM $ODIE_PLATFORM" >&5 -$as_echo "$as_me: Using Tcl in TCL_BIN_DIR $TEA_PLATFORM $ODIE_PLATFORM" >&6;} - # tclConfig.sh is in Tcl build directory - if test "${ODIE_PLATFORM}" = "windows"; then - TCLSH_PROG="${TCL_BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" - else - TCLSH_PROG="${TCL_BIN_DIR}/tclsh" - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Using Tcl in $prefix/lib $TEA_PLATFORM $ODIE_PLATFORM" >&5 -$as_echo "$as_me: Using Tcl in $prefix/lib $TEA_PLATFORM $ODIE_PLATFORM" >&6;} - # tclConfig.sh is in install location - if test "${ODIE_PLATFORM}" = "windows"; then - TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${TCL_DBGX}${EXEEXT}" - else - TCLSH_PROG="tclsh${TCL_MAJOR_VERSION}.${TCL_MINOR_VERSION}${TCL_DBGX}" - fi - TCLSH_PROG="${exec_prefix}/bin/${TCLSH_PROG}" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${TCLSH_PROG}" >&5 -$as_echo "${TCLSH_PROG}" >&6; } - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wish" >&5 -$as_echo_n "checking for wish... " >&6; } - if test -f "${TK_BIN_DIR}/Makefile" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: Using Tk in TK_BIN_DIR $TEA_PLATFORM $ODIE_PLATFORM" >&5 -$as_echo "$as_me: Using Tk in TK_BIN_DIR $TEA_PLATFORM $ODIE_PLATFORM" >&6;} - # tkConfig.sh is in Tk build directory - if test "${ODIE_PLATFORM}" = "windows"; then - WISH_PROG="${TK_BIN_DIR}/wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" - else - WISH_PROG="${TK_BIN_DIR}/wish" - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: Using Tk in $prefix/lib $TEA_PLATFORM $ODIE_PLATFORM" >&5 -$as_echo "$as_me: Using Tk in $prefix/lib $TEA_PLATFORM $ODIE_PLATFORM" >&6;} - # tkConfig.sh is in install location - if test "${ODIE_PLATFORM}" = "windows"; then - WISH_PROG="wish${TK_MAJOR_VERSION}${TK_MINOR_VERSION}${TK_DBGX}${EXEEXT}" - else - WISH_PROG="wish${TK_MAJOR_VERSION}.${TK_MINOR_VERSION}${TK_DBGX}" - fi - WISH_PROG="${exec_prefix}/bin/${WISH_PROG}" - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${WISH_PROG}" >&5 -$as_echo "${WISH_PROG}" >&6; } - - - -#-------------------------------------------------------------------- -# The statements below define a collection of compile flags. This -# macro depends on the value of SHARED_BUILD, and should be called -# after SC_ENABLE_SHARED checks the configure switches. -#-------------------------------------------------------------------- - -if test "${ODIE_PLATFORM}" = "windows" ; then - - - # Step 0: Enable 64 bit support? - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 -$as_echo_n "checking if 64bit support is requested... " >&6; } - # Check whether --enable-64bit was given. -if test "${enable_64bit+set}" = set; then : - enableval=$enable_64bit; do64bit=$enableval -else - do64bit=no -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 -$as_echo "$do64bit" >&6; } - - # Cross-compiling options for Windows/CE builds - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if Windows/CE build is requested" >&5 -$as_echo_n "checking if Windows/CE build is requested... " >&6; } - # Check whether --enable-wince was given. -if test "${enable_wince+set}" = set; then : - enableval=$enable_wince; doWince=$enableval -else - doWince=no -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doWince" >&5 -$as_echo "$doWince" >&6; } - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows/CE celib directory" >&5 -$as_echo_n "checking for Windows/CE celib directory... " >&6; } - -# Check whether --with-celib was given. -if test "${with_celib+set}" = set; then : - withval=$with_celib; CELIB_DIR=$withval -else - CELIB_DIR=NO_CELIB -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CELIB_DIR" >&5 -$as_echo "$CELIB_DIR" >&6; } - - # Set some defaults (may get changed below) - EXTRA_CFLAGS="" - -$as_echo "#define MODULE_SCOPE extern" >>confdefs.h - - - # Extract the first word of "cygpath", so it can be a program name with args. -set dummy cygpath; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CYGPATH+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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 -w" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CYGPATH" >&5 -$as_echo "$CYGPATH" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - - SHLIB_SUFFIX=".dll" - - # MACHINE is IX86 for LINK, but this is used by the manifest, - # which requires x86|amd64|ia64. - MACHINE="X86" - - if test "$GCC" = "yes"; then - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cross-compile version of gcc" >&5 -$as_echo_n "checking for cross-compile version of gcc... " >&6; } -if ${ac_cv_cross+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #ifndef _WIN32 - #error cross-compiler - #endif - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_cross=no -else - ac_cv_cross=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cross" >&5 -$as_echo "$ac_cv_cross" >&6; } - - if test "$ac_cv_cross" = "yes"; then - case "$do64bit" in - amd64|x64|yes) - CC="x86_64-w64-mingw32-gcc" - LD="x86_64-w64-mingw32-ld" - AR="x86_64-w64-mingw32-ar" - RANLIB="x86_64-w64-mingw32-ranlib" - RC="x86_64-w64-mingw32-windres" - ;; - *) - CC="i686-w64-mingw32-gcc" - LD="i686-w64-mingw32-ld" - AR="i686-w64-mingw32-ar" - RANLIB="i686-w64-mingw32-ranlib" - RC="i686-w64-mingw32-windres" - ;; - esac - fi - fi - - # Check for a bug in gcc's windres that causes the - # compile to fail when a Windows native path is - # passed into windres. The mingw toolchain requires - # Windows native paths while Cygwin should work - # with both. Avoid the bug by passing a POSIX - # path when using the Cygwin toolchain. - - if test "$GCC" = "yes" && test "$CYGPATH" != "echo" ; then - conftest=/tmp/conftest.rc - echo "STRINGTABLE BEGIN" > $conftest - echo "101 \"name\"" >> $conftest - echo "END" >> $conftest - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Windows native path bug in windres" >&5 -$as_echo_n "checking for Windows native path bug in windres... " >&6; } - cyg_conftest=`$CYGPATH $conftest` - if { ac_try='$RC -o conftest.res.o $cyg_conftest' - { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 - (eval $ac_try) 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; } ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - CYGPATH=echo - fi - conftest= - cyg_conftest= - fi - - if test "$CYGPATH" = "echo"; then - DEPARG='"$<"' - else - DEPARG='"$(shell $(CYGPATH) $<)"' - fi - - # set various compiler flags depending on whether we are using gcc or cl - - if test "${GCC}" = "yes" ; then - extra_cflags="-pipe" - extra_ldflags="-pipe -static-libgcc" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mingw32 version of gcc" >&5 -$as_echo_n "checking for mingw32 version of gcc... " >&6; } -if ${ac_cv_win32+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #ifdef _WIN32 - #error win32 - #endif - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_win32=no -else - ac_cv_win32=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_win32" >&5 -$as_echo "$ac_cv_win32" >&6; } - if test "$ac_cv_win32" != "yes"; then - as_fn_error $? "${CC} cannot produce win32 executables." "$LINENO" 5 - fi - - hold_cflags=$CFLAGS; CFLAGS="$CFLAGS -mwindows -municode -Dmain=xxmain" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working -municode linker flag" >&5 -$as_echo_n "checking for working -municode linker flag... " >&6; } -if ${ac_cv_municode+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include - int APIENTRY wWinMain(HINSTANCE a, HINSTANCE b, LPWSTR c, int d) {return 0;} - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_municode=yes -else - ac_cv_municode=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_municode" >&5 -$as_echo "$ac_cv_municode" >&6; } - CFLAGS=$hold_cflags - if test "$ac_cv_municode" = "yes" ; then - extra_ldflags="$extra_ldflags -municode" - else - extra_cflags="$extra_cflags -DTCL_BROKEN_MAINARGS" - fi - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking compiler flags" >&5 -$as_echo_n "checking compiler flags... " >&6; } - if test "${GCC}" = "yes" ; then - SHLIB_LD="" - SHLIB_LD_LIBS='${LIBS}' - LIBS="-lnetapi32 -lkernel32 -luser32 -ladvapi32 -lws2_32" - # mingw needs to link ole32 and oleaut32 for [send], but MSVC doesn't - LIBS_GUI="-lgdi32 -lcomdlg32 -limm32 -lcomctl32 -lshell32 -luuid -lole32 -loleaut32" - STLIB_LD='${AR} cr' - RC_OUT=-o - RC_TYPE= - RC_INCLUDE=--include - RC_DEFINE=--define - RES=res.o - MAKE_LIB="\${STLIB_LD} \$@" - MAKE_STUB_LIB="\${STLIB_LD} \$@" - POST_MAKE_LIB="\${RANLIB} \$@" - MAKE_EXE="\${CC} -o \$@" - LIBPREFIX="lib" - - if test "${SHARED_BUILD}" = "0" ; then - # static - { $as_echo "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5 -$as_echo "using static flags" >&6; } - runtime= - LIBRARIES="\${STATIC_LIBRARIES}" - EXESUFFIX="s\${DBGX}.exe" - else - # dynamic - { $as_echo "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5 -$as_echo "using shared flags" >&6; } - - # ad-hoc check to see if CC supports -shared. - if "${CC}" -shared 2>&1 | egrep ': -shared not supported' >/dev/null; then - as_fn_error $? "${CC} does not support the -shared option. - You will need to upgrade to a newer version of the toolchain." "$LINENO" 5 - fi - - runtime= - # Add SHLIB_LD_LIBS to the Make rule, not here. - - EXESUFFIX="\${DBGX}.exe" - LIBRARIES="\${SHARED_LIBRARIES}" - fi - # Link with gcc since ld does not link to default libs like - # -luser32 and -lmsvcrt by default. - SHLIB_LD='${CC} -shared' - SHLIB_LD_LIBS='${LIBS}' - MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -o \$@ ${extra_ldflags} \ - -Wl,--out-implib,\$(patsubst %.dll,lib%.a,\$@)" - # DLLSUFFIX is separate because it is the building block for - # users of tclConfig.sh that may build shared or static. - DLLSUFFIX="\${DBGX}.dll" - LIBSUFFIX="\${DBGX}.a" - LIBFLAGSUFFIX="\${DBGX}" - SHLIB_SUFFIX=.dll - - EXTRA_CFLAGS="${extra_cflags}" - - CFLAGS_DEBUG=-g - CFLAGS_OPTIMIZE="-O2 -fomit-frame-pointer" - CFLAGS_WARNING="-Wall -Wdeclaration-after-statement" - LDFLAGS_DEBUG= - LDFLAGS_OPTIMIZE= - - # Specify the CC output file names based on the target name - CC_OBJNAME="-o \$@" - CC_EXENAME="-o \$@" - - # Specify linker flags depending on the type of app being - # built -- Console vs. Window. - # - # ORIGINAL COMMENT: - # We need to pass -e _WinMain@16 so that ld will use - # WinMain() instead of main() as the entry point. We can't - # use autoconf to check for this case since it would need - # to run an executable and that does not work when - # cross compiling. Remove this -e workaround once we - # require a gcc that does not have this bug. - # - # MK NOTE: Tk should use a different mechanism. This causes - # interesting problems, such as wish dying at startup. - #LDFLAGS_WINDOW="-mwindows -e _WinMain@16 ${extra_ldflags}" - LDFLAGS_CONSOLE="-mconsole ${extra_ldflags}" - LDFLAGS_WINDOW="-mwindows ${extra_ldflags}" - - case "$do64bit" in - amd64|x64|yes) - MACHINE="AMD64" ; # assume AMD64 as default 64-bit build - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 -$as_echo " Using 64-bit $MACHINE mode" >&6; } - ;; - ia64) - MACHINE="IA64" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 -$as_echo " Using 64-bit $MACHINE mode" >&6; } - ;; - *) - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #ifndef _WIN64 - #error 32-bit - #endif - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - tcl_win_64bit=yes -else - tcl_win_64bit=no - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - if test "$tcl_win_64bit" = "yes" ; then - do64bit=amd64 - MACHINE="AMD64" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 -$as_echo " Using 64-bit $MACHINE mode" >&6; } - fi - ;; - esac - else - if test "${SHARED_BUILD}" = "0" ; then - # static - { $as_echo "$as_me:${as_lineno-$LINENO}: result: using static flags" >&5 -$as_echo "using static flags" >&6; } - runtime=-MT - LIBRARIES="\${STATIC_LIBRARIES}" - EXESUFFIX="s\${DBGX}.exe" - else - # dynamic - { $as_echo "$as_me:${as_lineno-$LINENO}: result: using shared flags" >&5 -$as_echo "using shared flags" >&6; } - runtime=-MD - # Add SHLIB_LD_LIBS to the Make rule, not here. - LIBRARIES="\${SHARED_LIBRARIES}" - EXESUFFIX="\${DBGX}.exe" - fi - MAKE_DLL="\${SHLIB_LD} \$(LDFLAGS) -out:\$@" - # DLLSUFFIX is separate because it is the building block for - # users of tclConfig.sh that may build shared or static. - DLLSUFFIX="\${DBGX}.dll" - LIBSUFFIX="\${DBGX}.lib" - LIBFLAGSUFFIX="\${DBGX}" - - # This is a 2-stage check to make sure we have the 64-bit SDK - # We have to know where the SDK is installed. - # This magic is based on MS Platform SDK for Win2003 SP1 - hobbs - if test "$do64bit" != "no" ; then - if test "x${MSSDK}x" = "xx" ; then - MSSDK="C:/Progra~1/Microsoft Platform SDK" - fi - MSSDK=`echo "$MSSDK" | sed -e 's!\\\!/!g'` - PATH64="" - case "$do64bit" in - amd64|x64|yes) - MACHINE="AMD64" ; # assume AMD64 as default 64-bit build - PATH64="${MSSDK}/Bin/Win64/x86/AMD64" - ;; - ia64) - MACHINE="IA64" - PATH64="${MSSDK}/Bin/Win64" - ;; - esac - if test ! -d "${PATH64}" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&5 -$as_echo "$as_me: WARNING: Could not find 64-bit $MACHINE SDK to enable 64bit mode" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ensure latest Platform SDK is installed" >&5 -$as_echo "$as_me: WARNING: Ensure latest Platform SDK is installed" >&2;} - do64bit="no" - else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using 64-bit $MACHINE mode" >&5 -$as_echo " Using 64-bit $MACHINE mode" >&6; } - fi - fi - - LIBS="netapi32.lib kernel32.lib user32.lib advapi32.lib ws2_32.lib" - if test "$do64bit" != "no" ; then - # The space-based-path will work for the Makefile, but will - # not work if AC_TRY_COMPILE is called. TEA has the - # TEA_PATH_NOSPACE to avoid this issue. - # Check if _WIN64 is already recognized, and if so we don't - # need to modify CC. - ac_fn_c_check_decl "$LINENO" "_WIN64" "ac_cv_have_decl__WIN64" "$ac_includes_default" -if test "x$ac_cv_have_decl__WIN64" = xyes; then : - -else - CC="\"${PATH64}/cl.exe\" -I\"${MSSDK}/Include\" \ - -I\"${MSSDK}/Include/crt\" \ - -I\"${MSSDK}/Include/crt/sys\"" -fi - - RC="\"${MSSDK}/bin/rc.exe\"" - CFLAGS_DEBUG="-nologo -Zi -Od ${runtime}d" - # Do not use -O2 for Win64 - this has proved buggy in code gen. - CFLAGS_OPTIMIZE="-nologo -O1 ${runtime}" - lflags="-nologo -MACHINE:${MACHINE} -LIBPATH:\"${MSSDK}/Lib/${MACHINE}\"" - LINKBIN="\"${PATH64}/link.exe\"" - # Avoid 'unresolved external symbol __security_cookie' errors. - # c.f. http://support.microsoft.com/?id=894573 - LIBS="$LIBS bufferoverflowU.lib" - else - RC="rc" - # -Od - no optimization - # -WX - warnings as errors - CFLAGS_DEBUG="-nologo -Z7 -Od -WX ${runtime}d" - # -O2 - create fast code (/Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy) - CFLAGS_OPTIMIZE="-nologo -O2 ${runtime}" - lflags="-nologo" - LINKBIN="link" - fi - - if test "$doWince" != "no" ; then - # Set defaults for common evc4/PPC2003 setup - # Currently Tcl requires 300+, possibly 420+ for sockets - CEVERSION=420; # could be 211 300 301 400 420 ... - TARGETCPU=ARMV4; # could be ARMV4 ARM MIPS SH3 X86 ... - ARCH=ARM; # could be ARM MIPS X86EM ... - PLATFORM="Pocket PC 2003"; # or "Pocket PC 2002" - if test "$doWince" != "yes"; then - # If !yes then the user specified something - # Reset ARCH to allow user to skip specifying it - ARCH= - eval `echo $doWince | awk -F "," '{ \ - if (length($1)) { printf "CEVERSION=\"%s\"\n", $1; \ - if ($1 < 400) { printf "PLATFORM=\"Pocket PC 2002\"\n" } }; \ - if (length($2)) { printf "TARGETCPU=\"%s\"\n", toupper($2) }; \ - if (length($3)) { printf "ARCH=\"%s\"\n", toupper($3) }; \ - if (length($4)) { printf "PLATFORM=\"%s\"\n", $4 }; \ - }'` - if test "x${ARCH}" = "x" ; then - ARCH=$TARGETCPU; - fi - fi - OSVERSION=WCE$CEVERSION; - if test "x${WCEROOT}" = "x" ; then - WCEROOT="C:/Program Files/Microsoft eMbedded C++ 4.0" - if test ! -d "${WCEROOT}" ; then - WCEROOT="C:/Program Files/Microsoft eMbedded Tools" - fi - fi - if test "x${SDKROOT}" = "x" ; then - SDKROOT="C:/Program Files/Windows CE Tools" - if test ! -d "${SDKROOT}" ; then - SDKROOT="C:/Windows CE Tools" - fi - fi - # The space-based-path will work for the Makefile, but will - # not work if AC_TRY_COMPILE is called. - WCEROOT=`echo "$WCEROOT" | sed -e 's!\\\!/!g'` - SDKROOT=`echo "$SDKROOT" | sed -e 's!\\\!/!g'` - CELIB_DIR=`echo "$CELIB_DIR" | sed -e 's!\\\!/!g'` - if test ! -d "${CELIB_DIR}/inc"; then - as_fn_error $? "Invalid celib directory \"${CELIB_DIR}\"" "$LINENO" 5 - fi - if test ! -d "${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}"\ - -o ! -d "${WCEROOT}/EVC/${OSVERSION}/bin"; then - as_fn_error $? "could not find PocketPC SDK or target compiler to enable WinCE mode $CEVERSION,$TARGETCPU,$ARCH,$PLATFORM" "$LINENO" 5 - else - CEINCLUDE="${SDKROOT}/${OSVERSION}/${PLATFORM}/include" - if test -d "${CEINCLUDE}/${TARGETCPU}" ; then - CEINCLUDE="${CEINCLUDE}/${TARGETCPU}" - fi - CELIBPATH="${SDKROOT}/${OSVERSION}/${PLATFORM}/Lib/${TARGETCPU}" - fi - fi - - if test "$doWince" != "no" ; then - CEBINROOT="${WCEROOT}/EVC/${OSVERSION}/bin" - if test "${TARGETCPU}" = "X86"; then - CC="${CEBINROOT}/cl.exe" - else - CC="${CEBINROOT}/cl${ARCH}.exe" - fi - CC="\"${CC}\" -I\"${CELIB_DIR}/inc\" -I\"${CEINCLUDE}\"" - RC="\"${WCEROOT}/Common/EVC/bin/rc.exe\"" - arch=`echo ${ARCH} | awk '{print tolower($0)}'` - defs="${ARCH} _${ARCH}_ ${arch} PALM_SIZE _MT _DLL _WINDOWS" - for i in $defs ; do - cat >>confdefs.h <<_ACEOF -#define $i 1 -_ACEOF - - done -# if test "${ARCH}" = "X86EM"; then -# AC_DEFINE_UNQUOTED(_WIN32_WCE_EMULATION) -# fi - cat >>confdefs.h <<_ACEOF -#define _WIN32_WCE $CEVERSION -_ACEOF - - cat >>confdefs.h <<_ACEOF -#define UNDER_CE $CEVERSION -_ACEOF - - CFLAGS_DEBUG="-nologo -Zi -Od" - CFLAGS_OPTIMIZE="-nologo -O2" - lversion=`echo ${CEVERSION} | sed -e 's/\(.\)\(..\)/\1\.\2/'` - lflags="-nodefaultlib -MACHINE:${ARCH} -LIBPATH:\"${CELIBPATH}\" -subsystem:windowsce,${lversion} -nologo" - LINKBIN="\"${CEBINROOT}/link.exe\"" - - if test "${CEVERSION}" -lt 400 ; then - LIBS="coredll.lib corelibc.lib winsock.lib" - else - LIBS="coredll.lib corelibc.lib ws2.lib" - fi - # celib currently stuck at wce300 status - #LIBS="$LIBS \${CELIB_DIR}/wince-${ARCH}-pocket-${OSVERSION}-release/celib.lib" - LIBS="$LIBS \"\${CELIB_DIR}/wince-${ARCH}-pocket-wce300-release/celib.lib\"" - LIBS_GUI="commctrl.lib commdlg.lib" - else - LIBS_GUI="gdi32.lib comdlg32.lib imm32.lib comctl32.lib shell32.lib uuid.lib" - fi - - SHLIB_LD="${LINKBIN} -dll -incremental:no ${lflags}" - SHLIB_LD_LIBS='${LIBS}' - # link -lib only works when -lib is the first arg - STLIB_LD="${LINKBIN} -lib ${lflags}" - RC_OUT=-fo - RC_TYPE=-r - RC_INCLUDE=-i - RC_DEFINE=-d - RES=res - MAKE_LIB="\${STLIB_LD} -out:\$@" - MAKE_STUB_LIB="\${STLIB_LD} -nodefaultlib -out:\$@" - POST_MAKE_LIB= - MAKE_EXE="\${CC} -Fe\$@" - LIBPREFIX="" - - CFLAGS_DEBUG="${CFLAGS_DEBUG} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE" - CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE" - - EXTRA_CFLAGS="" - CFLAGS_WARNING="-W3" - LDFLAGS_DEBUG="-debug" - LDFLAGS_OPTIMIZE="-release" - - # Specify the CC output file names based on the target name - CC_OBJNAME="-Fo\$@" - CC_EXENAME="-Fe\"\$(shell \$(CYGPATH) '\$@')\"" - - # Specify linker flags depending on the type of app being - # built -- Console vs. Window. - if test "$doWince" != "no" -a "${TARGETCPU}" != "X86"; then - LDFLAGS_CONSOLE="-link ${lflags}" - LDFLAGS_WINDOW=${LDFLAGS_CONSOLE} - else - LDFLAGS_CONSOLE="-link -subsystem:console ${lflags}" - LDFLAGS_WINDOW="-link -subsystem:windows ${lflags}" - fi - fi - - if test "$do64bit" != "no" ; then - $as_echo "#define TCL_CFG_DO64BIT 1" >>confdefs.h - - fi - - if test "${GCC}" = "yes" ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SEH support in compiler" >&5 -$as_echo_n "checking for SEH support in compiler... " >&6; } -if ${tcl_cv_seh+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - tcl_cv_seh=no -else - 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 - 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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_seh" >&5 -$as_echo "$tcl_cv_seh" >&6; } - if test "$tcl_cv_seh" = "no" ; then - -$as_echo "#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. - # - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for EXCEPTION_DISPOSITION support in include files" >&5 -$as_echo_n "checking for EXCEPTION_DISPOSITION support in include files... " >&6; } -if ${tcl_cv_eh_disposition+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -# define WIN32_LEAN_AND_MEAN -# include -# undef WIN32_LEAN_AND_MEAN - -int -main () -{ - - EXCEPTION_DISPOSITION x; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - tcl_cv_eh_disposition=yes -else - tcl_cv_eh_disposition=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_eh_disposition" >&5 -$as_echo "$tcl_cv_eh_disposition" >&6; } - if test "$tcl_cv_eh_disposition" = "no" ; then - -$as_echo "#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. - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for winnt.h that ignores VOID define" >&5 -$as_echo_n "checking for winnt.h that ignores VOID define... " >&6; } -if ${tcl_cv_winnt_ignore_void+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 () -{ - - CHAR c; - SHORT s; - LONG l; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - tcl_cv_winnt_ignore_void=yes -else - tcl_cv_winnt_ignore_void=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_winnt_ignore_void" >&5 -$as_echo "$tcl_cv_winnt_ignore_void" >&6; } - if test "$tcl_cv_winnt_ignore_void" = "yes" ; then - -$as_echo "#define HAVE_WINNT_IGNORE_VOID 1" >>confdefs.h - - 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. - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 -$as_echo_n "checking for cast to union support... " >&6; } -if ${tcl_cv_cast_to_union+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - 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 - tcl_cv_cast_to_union=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 -$as_echo "$tcl_cv_cast_to_union" >&6; } - if test "$tcl_cv_cast_to_union" = "yes"; then - -$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h - - fi - fi - - # DL_LIBS is empty, but then we match the Unix version - - - - - -else - 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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 -$as_echo "$RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 -$as_echo "$ac_ct_RANLIB" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_RANLIB" = x; then - RANLIB=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$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? - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit support is requested" >&5 -$as_echo_n "checking if 64bit support is requested... " >&6; } - # Check whether --enable-64bit was given. -if test "${enable_64bit+set}" = set; then : - enableval=$enable_64bit; do64bit=$enableval -else - do64bit=no -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bit" >&5 -$as_echo "$do64bit" >&6; } - - # Step 0.b: Enable Solaris 64 bit VIS support? - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if 64bit Sparc VIS support is requested" >&5 -$as_echo_n "checking if 64bit Sparc VIS support is requested... " >&6; } - # Check whether --enable-64bit-vis was given. -if test "${enable_64bit_vis+set}" = set; then : - enableval=$enable_64bit_vis; do64bitVIS=$enableval -else - do64bitVIS=no -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $do64bitVIS" >&5 -$as_echo "$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. - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports visibility \"hidden\"" >&5 -$as_echo_n "checking if compiler supports visibility \"hidden\"... " >&6; } -if ${tcl_cv_cc_visibility_hidden+:} false; then : - $as_echo_n "(cached) " >&6 -else - - 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 () -{ -f(); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_cc_visibility_hidden=yes -else - tcl_cv_cc_visibility_hidden=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CFLAGS=$hold_cflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_visibility_hidden" >&5 -$as_echo "$tcl_cv_cc_visibility_hidden" >&6; } - if test $tcl_cv_cc_visibility_hidden = yes; then : - - -$as_echo "#define MODULE_SCOPE extern __attribute__((__visibility__(\"hidden\")))" >>confdefs.h - - -$as_echo "#define HAVE_HIDDEN 1" >>confdefs.h - - -fi - - # Step 0.d: Disable -rpath support? - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if rpath support is requested" >&5 -$as_echo_n "checking if rpath support is requested... " >&6; } - # Check whether --enable-rpath was given. -if test "${enable_rpath+set}" = set; then : - enableval=$enable_rpath; doRpath=$enableval -else - doRpath=yes -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $doRpath" >&5 -$as_echo "$doRpath" >&6; } - - # Step 1: set the variable "system" to hold the name and version number - # for the system. - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking system version" >&5 -$as_echo_n "checking system version... " >&6; } -if ${tcl_cv_sys_version+:} false; then : - $as_echo_n "(cached) " >&6 -else - - if test -f /usr/lib/NextStep/software_version; then - tcl_cv_sys_version=NEXTSTEP-`awk '/3/,/3/' /usr/lib/NextStep/software_version` - else - tcl_cv_sys_version=`uname -s`-`uname -r` - if test "$?" -ne 0 ; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find uname command" >&5 -$as_echo "$as_me: WARNING: can't find uname command" >&2;} - tcl_cv_sys_version=unknown - else - # Special check for weird MP-RAS system (uname returns weird - # results, and the version is kept in special file). - - if test -r /etc/.relid -a "X`uname -n`" = "X`uname -s`" ; then - tcl_cv_sys_version=MP-RAS-`awk '{print $3}' /etc/.relid` - fi - if test "`uname -s`" = "AIX" ; then - tcl_cv_sys_version=AIX-`uname -v`.`uname -r` - fi - fi - fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_sys_version" >&5 -$as_echo "$tcl_cv_sys_version" >&6; } - system=$tcl_cv_sys_version - - - # Step 2: check for existence of -ldl library. This is needed because - # Linux can use either -ldl or -ldld for dynamic loading. - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 -$as_echo_n "checking for dlopen in -ldl... " >&6; } -if ${ac_cv_lib_dl_dlopen+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $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. */ -#ifdef __cplusplus -extern "C" -#endif -char dlopen (); -int -main () -{ -return dlopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_dlopen=yes -else - ac_cv_lib_dl_dlopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 -$as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = xyes; then : - have_dl=yes -else - have_dl=no -fi - - - # Require ranlib early so we can override it in special cases below. - - - - # Step 3: set configuration options based on system name and version. - - do64bit_ok=no - # default to '{$LIBS}' and set to "" on per-platform necessary basis - SHLIB_LD_LIBS='${LIBS}' - LDFLAGS_ORIG="$LDFLAGS" - # 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="" - TCL_TRIM_DOTS='`echo ${VERSION} | tr -d .`' - ECHO_VERSION='`echo ${VERSION}`' - TCL_LIB_VERSIONS_OK=ok - CFLAGS_DEBUG=-g - if test "$GCC" = yes; then : - - CFLAGS_OPTIMIZE=-O2 - CFLAGS_WARNING="-Wall" - -else - - 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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 -$as_echo "$AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "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 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_AR+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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 - test -z "$as_dir" && as_dir=. - 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" - $as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 -$as_echo "$ac_ct_AR" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_AR" = x; then - AR="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$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" - PLAT_OBJS="" - PLAT_SRCS="" - LDAIX_SRC="" - if test x"${SHLIB_VERSION}" = x; then : - SHLIB_VERSION="1.0" -fi - case $system in - AIX-*) - if test "${TCL_THREADS}" = "1" -a "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using $CC for compiling with threads" >&5 -$as_echo "Using $CC for compiling with threads" >&6; } - -fi - LIBS="$LIBS -lc" - SHLIB_CFLAGS="" - SHLIB_SUFFIX=".so" - - DL_OBJS="tclLoadDl.o" - LD_LIBRARY_PATH_VAR="LIBPATH" - - # ldAix No longer needed with use of -bexpall/-brtl - # but some extensions may still reference it - LDAIX_SRC='$(UNIX_DIR)/ldAix' - - # Check to enable 64-bit flags for compiler/linker - if test "$do64bit" = yes; then : - - if test "$GCC" = yes; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 -$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} - -else - - 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" - # AIX-5 has dl* in libc.so - DL_LIBS="" - if test "$GCC" = yes; then : - - CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' - -else - - CC_SEARCH_FLAGS='-R${LIB_RUNTIME_DIR}' - -fi - LD_SEARCH_FLAGS='-R ${LIB_RUNTIME_DIR}' - -else - - if test "$GCC" = yes; then : - - SHLIB_LD='${CC} -shared -Wl,-bexpall' - -else - - SHLIB_LD="/bin/ld -bhalt:4 -bM:SRE -bexpall -H512 -T512 -bnoentry" - LDFLAGS="$LDFLAGS -brtl" - -fi - SHLIB_LD="${SHLIB_LD} ${SHLIB_LD_FLAGS}" - DL_LIBS="-ldl" - 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" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - - #----------------------------------------------------------- - # 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. - #----------------------------------------------------------- - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lbind" >&5 -$as_echo_n "checking for inet_ntoa in -lbind... " >&6; } -if ${ac_cv_lib_bind_inet_ntoa+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char inet_ntoa (); -int -main () -{ -return inet_ntoa (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_bind_inet_ntoa=yes -else - ac_cv_lib_bind_inet_ntoa=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bind_inet_ntoa" >&5 -$as_echo "$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" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - BSD/OS-4.*) - SHLIB_CFLAGS="-export-dynamic -fPIC" - SHLIB_LD='${CC} -shared' - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - LDFLAGS="$LDFLAGS -export-dynamic" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - CYGWIN_*) - SHLIB_CFLAGS="" - SHLIB_LD='${CC} -shared' - SHLIB_SUFFIX=".dll" - DL_OBJS="tclLoadDl.o" - PLAT_OBJS='${CYGWIN_OBJS}' - PLAT_SRCS='${CYGWIN_SRCS}' - DL_LIBS="-ldl" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - TCL_NEEDS_EXP_FILE=1 - TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' - TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' - TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Cygwin version of gcc" >&5 -$as_echo_n "checking for Cygwin version of gcc... " >&6; } -if ${ac_cv_cygwin+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #ifdef __CYGWIN__ - #error cygwin - #endif - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_cygwin=no -else - ac_cv_cygwin=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cygwin" >&5 -$as_echo "$ac_cv_cygwin" >&6; } - if test "$ac_cv_cygwin" = "no"; then - as_fn_error $? "${CC} is not a cygwin compiler." "$LINENO" 5 - fi - if test "x${TCL_THREADS}" = "x0"; then - as_fn_error $? "CYGWIN compile is only supported with --enable-threads" "$LINENO" 5 - fi - ;; - MINGW32*) - SHLIB_CFLAGS="" - SHLIB_LD='${CC} -shared' - SHLIB_SUFFIX=".dll" - DL_OBJS="tclLoadDl.o" - PLAT_OBJS='${CYGWIN_OBJS}' - PLAT_SRCS='${CYGWIN_SRCS}' - DL_LIBS="-ldl" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - TCL_NEEDS_EXP_FILE=1 - TCL_EXPORT_FILE_SUFFIX='${VERSION}\$\{DBGX\}.dll.a' - TCL_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' - TK_SHLIB_LD_EXTRAS='-Wl,--out-implib,$@.a' - do64bit_ok=yes - ;; - dgux*) - SHLIB_CFLAGS="-K PIC" - SHLIB_LD='${CC} -G' - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - Haiku*) - LDFLAGS="$LDFLAGS -Wl,--export-dynamic" - SHLIB_CFLAGS="-fPIC" - SHLIB_SUFFIX=".so" - SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' - DL_OBJS="tclLoadDl.o" - DL_LIBS="-lroot" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inet_ntoa in -lnetwork" >&5 -$as_echo_n "checking for inet_ntoa in -lnetwork... " >&6; } -if ${ac_cv_lib_network_inet_ntoa+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char inet_ntoa (); -int -main () -{ -return inet_ntoa (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_network_inet_ntoa=yes -else - ac_cv_lib_network_inet_ntoa=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_network_inet_ntoa" >&5 -$as_echo "$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 - -$as_echo "#define _XOPEN_SOURCE_EXTENDED 1" >>confdefs.h - - -$as_echo "#define _XOPEN_SOURCE 1" >>confdefs.h - - LIBS="$LIBS -lxnet" # Use the XOPEN network library - - if test "`uname -m`" = ia64; then : - - SHLIB_SUFFIX=".so" - -else - - SHLIB_SUFFIX=".sl" - -fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 -$as_echo_n "checking for shl_load in -ldld... " >&6; } -if ${ac_cv_lib_dld_shl_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_shl_load=yes -else - ac_cv_lib_dld_shl_load=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 -$as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = yes; then : - - SHLIB_CFLAGS="+z" - SHLIB_LD="ld -b" - DL_OBJS="tclLoadShl.o" - DL_LIBS="-ldld" - 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 - - CFLAGS="$CFLAGS -z" - -fi - - # Users may want PA-RISC 1.1/2.0 portable code - needs HP cc - #CFLAGS="$CFLAGS +DAportable" - - # 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} - ;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 -$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;} - ;; - esac - -else - - do64bit_ok=yes - CFLAGS="$CFLAGS +DD64" - LDFLAGS_ARCH="+DD64" - -fi - -fi ;; - HP-UX-*.08.*|HP-UX-*.09.*|HP-UX-*.10.*) - SHLIB_SUFFIX=".sl" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 -$as_echo_n "checking for shl_load in -ldld... " >&6; } -if ${ac_cv_lib_dld_shl_load+:} false; then : - $as_echo_n "(cached) " >&6 -else - 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. */ -#ifdef __cplusplus -extern "C" -#endif -char shl_load (); -int -main () -{ -return shl_load (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dld_shl_load=yes -else - ac_cv_lib_dld_shl_load=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 -$as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = xyes; then : - tcl_ok=yes -else - tcl_ok=no -fi - - if test "$tcl_ok" = yes; then : - - SHLIB_CFLAGS="+z" - SHLIB_LD="ld -b" - SHLIB_LD_LIBS="" - DL_OBJS="tclLoadShl.o" - DL_LIBS="-ldld" - 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" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - 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" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - 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 - if test "$GCC" = yes; then : - - CFLAGS="$CFLAGS -mabi=n32" - LDFLAGS="$LDFLAGS -mabi=n32" - -else - - 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" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - 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 - - # Check to enable 64-bit flags for compiler/linker - - if test "$do64bit" = yes; then : - - if test "$GCC" = yes; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported by gcc" >&5 -$as_echo "$as_me: WARNING: 64bit mode not supported by gcc" >&2;} - -else - - do64bit_ok=yes - SHLIB_LD="ld -64 -shared -rdata_shared" - CFLAGS="$CFLAGS -64" - LDFLAGS_ARCH="-64" - -fi - -fi - ;; - Linux*|GNU*|NetBSD-Debian) - SHLIB_CFLAGS="-fPIC" - SHLIB_SUFFIX=".so" - - CFLAGS_OPTIMIZE="-O2" - # egcs-2.91.66 on Redhat Linux 6.0 generates lots of warnings - # when you inline the string and math operations. Turn this off to - # get rid of the warnings. - #CFLAGS_OPTIMIZE="${CFLAGS_OPTIMIZE} -D__NO_STRING_INLINES -D__NO_MATH_INLINES" - - SHLIB_LD='${CC} -shared ${CFLAGS} ${LDFLAGS}' - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - LDFLAGS="$LDFLAGS -Wl,--export-dynamic" - 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 : - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -m64 flag" >&5 -$as_echo_n "checking if compiler accepts -m64 flag... " >&6; } -if ${tcl_cv_cc_m64+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_cflags=$CFLAGS - CFLAGS="$CFLAGS -m64" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_cc_m64=yes -else - tcl_cv_cc_m64=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CFLAGS=$hold_cflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_m64" >&5 -$as_echo "$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' - DL_OBJS="tclLoadDl.o" - DL_LIBS="-mshared -ldl" - 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 - ;; - MP-RAS-02*) - SHLIB_CFLAGS="-K PIC" - SHLIB_LD='${CC} -G' - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - MP-RAS-*) - SHLIB_CFLAGS="-K PIC" - SHLIB_LD='${CC} -G' - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - LDFLAGS="$LDFLAGS -Wl,-Bexport" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - OpenBSD-*) - arch=`arch -s` - case "$arch" in - vax) - # Equivalent using configure option --disable-load - # Step 4 will set the necessary variables - DL_OBJS="" - SHLIB_LD_LIBS="" - LDFLAGS="" - ;; - *) - SHLIB_CFLAGS="-fPIC" - SHLIB_LD='${CC} -shared ${SHLIB_CFLAGS}' - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - 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="-Wl,-export-dynamic" - ;; - esac - case "$arch" in - vax) - CFLAGS_OPTIMIZE="-O1" - ;; - sh) - CFLAGS_OPTIMIZE="-O0" - ;; - *) - CFLAGS_OPTIMIZE="-O2" - ;; - esac - if test "${TCL_THREADS}" = "1"; then : - - # On OpenBSD: Compile with -pthread - # Don't link with -lpthread - LIBS=`echo $LIBS | sed s/-lpthread//` - CFLAGS="$CFLAGS -pthread" - -fi - # 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} -shared ${SHLIB_CFLAGS}' - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - LDFLAGS="$LDFLAGS -export-dynamic" - if test $doRpath = yes; then : - - CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' -fi - LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} - if test "${TCL_THREADS}" = "1"; then : - - # The -pthread needs to go in the CFLAGS, not LIBS - LIBS=`echo $LIBS | sed s/-pthread//` - CFLAGS="$CFLAGS -pthread" - LDFLAGS="$LDFLAGS -pthread" - -fi - ;; - FreeBSD-*) - # This configuration from FreeBSD Ports. - SHLIB_CFLAGS="-fPIC" - SHLIB_LD="${CC} -shared" - TCL_SHLIB_LD_EXTRAS="-Wl,-soname=\$@" - TK_SHLIB_LD_EXTRAS="-Wl,-soname,\$@" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - LDFLAGS="" - if test $doRpath = yes; then : - - CC_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' - LD_SEARCH_FLAGS='-Wl,-rpath,${LIB_RUNTIME_DIR}' -fi - 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 - # Version numbers are dot-stripped by system policy. - TCL_TRIM_DOTS=`echo ${VERSION} | tr -d .` - UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' - SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}\$\{DBGX\}.so.1' - TCL_LIB_VERSIONS_OK=nodots - ;; - 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) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch ppc64 flag" >&5 -$as_echo_n "checking if compiler accepts -arch ppc64 flag... " >&6; } -if ${tcl_cv_cc_arch_ppc64+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_cflags=$CFLAGS - CFLAGS="$CFLAGS -arch ppc64 -mpowerpc64 -mcpu=G5" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_cc_arch_ppc64=yes -else - tcl_cv_cc_arch_ppc64=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CFLAGS=$hold_cflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_ppc64" >&5 -$as_echo "$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) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler accepts -arch x86_64 flag" >&5 -$as_echo_n "checking if compiler accepts -arch x86_64 flag... " >&6; } -if ${tcl_cv_cc_arch_x86_64+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_cflags=$CFLAGS - CFLAGS="$CFLAGS -arch x86_64" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_cc_arch_x86_64=yes -else - tcl_cv_cc_arch_x86_64=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CFLAGS=$hold_cflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cc_arch_x86_64" >&5 -$as_echo "$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;; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&5 -$as_echo "$as_me: WARNING: Don't know how enable 64-bit on architecture \`arch\`" >&2;};; - esac - -else - - # 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 - SHLIB_LD='${CC} -dynamiclib ${CFLAGS} ${LDFLAGS}' - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -single_module flag" >&5 -$as_echo_n "checking if ld accepts -single_module flag... " >&6; } -if ${tcl_cv_ld_single_module+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_ldflags=$LDFLAGS - LDFLAGS="$LDFLAGS -dynamiclib -Wl,-single_module" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -int i; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_ld_single_module=yes -else - tcl_cv_ld_single_module=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$hold_ldflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_single_module" >&5 -$as_echo "$tcl_cv_ld_single_module" >&6; } - if test $tcl_cv_ld_single_module = yes; then : - - SHLIB_LD="${SHLIB_LD} -Wl,-single_module" - -fi - SHLIB_SUFFIX=".dylib" - DL_OBJS="tclLoadDyld.o" - DL_LIBS="" - # Don't use -prebind when building for Mac OS X 10.4 or later only: - if test "`echo "${MACOSX_DEPLOYMENT_TARGET}" | awk -F '10\\.' '{print int($2)}'`" -lt 4 -a \ - "`echo "${CPPFLAGS}" | awk -F '-mmacosx-version-min=10\\.' '{print int($2)}'`" -lt 4; then : - - LDFLAGS="$LDFLAGS -prebind" -fi - LDFLAGS="$LDFLAGS -headerpad_max_install_names" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if ld accepts -search_paths_first flag" >&5 -$as_echo_n "checking if ld accepts -search_paths_first flag... " >&6; } -if ${tcl_cv_ld_search_paths_first+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_ldflags=$LDFLAGS - LDFLAGS="$LDFLAGS -Wl,-search_paths_first" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -int i; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_ld_search_paths_first=yes -else - tcl_cv_ld_search_paths_first=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$hold_ldflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_search_paths_first" >&5 -$as_echo "$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 : - - -$as_echo "#define MODULE_SCOPE __private_extern__" >>confdefs.h - - -fi - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - LD_LIBRARY_PATH_VAR="DYLD_LIBRARY_PATH" - -$as_echo "#define MAC_OSX_TCL 1" >>confdefs.h - - PLAT_OBJS='${MAC_OSX_OBJS}' - PLAT_SRCS='${MAC_OSX_SRCS}' - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use CoreFoundation" >&5 -$as_echo_n "checking whether to use CoreFoundation... " >&6; } - # Check whether --enable-corefoundation was given. -if test "${enable_corefoundation+set}" = set; then : - enableval=$enable_corefoundation; tcl_corefoundation=$enableval -else - tcl_corefoundation=yes -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_corefoundation" >&5 -$as_echo "$tcl_corefoundation" >&6; } - if test $tcl_corefoundation = yes; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CoreFoundation.framework" >&5 -$as_echo_n "checking for CoreFoundation.framework... " >&6; } -if ${tcl_cv_lib_corefoundation+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_libs=$LIBS - if test "$fat_32_64" = yes; then : - - for v in CFLAGS CPPFLAGS LDFLAGS; do - # On Tiger there is no 64-bit CF, so remove 64-bit - # archs from CFLAGS et al. while testing for - # presence of CF. 64-bit CF is disabled in - # tclUnixPort.h if necessary. - eval 'hold_'$v'="$'$v'";'$v'="`echo "$'$v' "|sed -e "s/-arch ppc64 / /g" -e "s/-arch x86_64 / /g"`"' - done -fi - LIBS="$LIBS -framework CoreFoundation" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -CFBundleRef b = CFBundleGetMainBundle(); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_lib_corefoundation=yes -else - tcl_cv_lib_corefoundation=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - if test "$fat_32_64" = yes; then : - - for v in CFLAGS CPPFLAGS LDFLAGS; do - eval $v'="$hold_'$v'"' - done -fi - LIBS=$hold_libs -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation" >&5 -$as_echo "$tcl_cv_lib_corefoundation" >&6; } - if test $tcl_cv_lib_corefoundation = yes; then : - - LIBS="$LIBS -framework CoreFoundation" - -$as_echo "#define HAVE_COREFOUNDATION 1" >>confdefs.h - - -else - tcl_corefoundation=no -fi - if test "$fat_32_64" = yes -a $tcl_corefoundation = yes; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit CoreFoundation" >&5 -$as_echo_n "checking for 64-bit CoreFoundation... " >&6; } -if ${tcl_cv_lib_corefoundation_64+:} false; then : - $as_echo_n "(cached) " >&6 -else - - 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 - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ -CFBundleRef b = CFBundleGetMainBundle(); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_lib_corefoundation_64=yes -else - tcl_cv_lib_corefoundation_64=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - for v in CFLAGS CPPFLAGS LDFLAGS; do - eval $v'="$hold_'$v'"' - done -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_lib_corefoundation_64" >&5 -$as_echo "$tcl_cv_lib_corefoundation_64" >&6; } - if test $tcl_cv_lib_corefoundation_64 = no; then : - - -$as_echo "#define NO_COREFOUNDATION_64 1" >>confdefs.h - - LDFLAGS="$LDFLAGS -Wl,-no_arch_warnings" - -fi - -fi - -fi - ;; - NEXTSTEP-*) - SHLIB_CFLAGS="" - SHLIB_LD='${CC} -nostdlib -r' - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadNext.o" - DL_LIBS="" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - OS/390-*) - SHLIB_LD_LIBS="" - CFLAGS_OPTIMIZE="" # Optimizer is buggy - -$as_echo "#define _OE_SOCKETS 1" >>confdefs.h - - ;; - OSF1-1.0|OSF1-1.1|OSF1-1.2) - # OSF/1 1.[012] from OSF, and derivatives, including Paragon OSF/1 - SHLIB_CFLAGS="" - # Hack: make package name same as library name - SHLIB_LD='ld -R -export :' - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadOSF.o" - DL_LIBS="" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - OSF1-1.*) - # OSF/1 1.3 from OSF using ELF, and derivatives, including AD2 - SHLIB_CFLAGS="-fPIC" - if test "$SHARED_BUILD" = 1; then : - SHLIB_LD="ld -shared" -else - - SHLIB_LD="ld -non_shared" - -fi - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - OSF1-V*) - # Digital OSF/1 - SHLIB_CFLAGS="" - if test "$SHARED_BUILD" = 1; then : - - SHLIB_LD='ld -shared -expect_unresolved "*"' - -else - - SHLIB_LD='ld -non_shared -expect_unresolved "*"' - -fi - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - 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 - - CFLAGS="$CFLAGS -DHAVE_TZSET -std1 -ieee" -fi - # see pthread_intro(3) for pthread support on osf1, k.furukawa - if test "${TCL_THREADS}" = 1; then : - - 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 - - CFLAGS="$CFLAGS -pthread" - LDFLAGS="$LDFLAGS -pthread" - -fi - -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" - DL_OBJS="tclLoadDl.o" - # dlopen is in -lc on QNX - DL_LIBS="" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - SCO_SV-3.2*) - # Note, dlopen is available only on SCO 3.2.5 and greater. However, - # this test works, since "uname -s" was non-standard in 3.2.4 and - # below. - if test "$GCC" = yes; then : - - SHLIB_CFLAGS="-fPIC -melf" - LDFLAGS="$LDFLAGS -melf -Wl,-Bexport" - -else - - SHLIB_CFLAGS="-Kpic -belf" - LDFLAGS="$LDFLAGS -belf -Wl,-Bexport" - -fi - SHLIB_LD="ld -G" - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - SINIX*5.4*) - SHLIB_CFLAGS="-K PIC" - SHLIB_LD='${CC} -G' - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - ;; - SunOS-4*) - SHLIB_CFLAGS="-PIC" - SHLIB_LD="ld" - SHLIB_LD_LIBS="" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - CC_SEARCH_FLAGS='-L${LIB_RUNTIME_DIR}' - LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} - - # SunOS can't handle version numbers with dots in them in library - # specs, like -ltcl7.5, so use -ltcl75 instead. Also, it - # requires an extra version number at the end of .so file names. - # So, the library has to have a name like libtcl75.so.1.0 - - SHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.so.${SHLIB_VERSION}' - UNSHARED_LIB_SUFFIX='${TCL_TRIM_DOTS}.a' - TCL_LIB_VERSIONS_OK=nodots - ;; - 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. - - -$as_echo "#define _REENTRANT 1" >>confdefs.h - - -$as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h - - - SHLIB_CFLAGS="-KPIC" - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - if test "$GCC" = yes; then : - - SHLIB_LD='${CC} -shared' - CC_SEARCH_FLAGS='-Wl,-R,${LIB_RUNTIME_DIR}' - LD_SEARCH_FLAGS=${CC_SEARCH_FLAGS} - -else - - 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. - - -$as_echo "#define _REENTRANT 1" >>confdefs.h - - -$as_echo "#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 : - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&5 -$as_echo "$as_me: WARNING: 64bit mode not supported with GCC < 3.2 on $system" >&2;} - -else - - do64bit_ok=yes - CFLAGS="$CFLAGS -m64 -mcpu=v9" - LDFLAGS="$LDFLAGS -m64 -mcpu=v9" - SHLIB_CFLAGS="-fPIC" - -fi - -else - - do64bit_ok=yes - if test "$do64bitVIS" = yes; then : - - CFLAGS="$CFLAGS -xarch=v9a" - LDFLAGS_ARCH="-xarch=v9a" - -else - - 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 - 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";; - *) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported with GCC on $system" >&5 -$as_echo "$as_me: WARNING: 64bit mode not supported with GCC on $system" >&2;};; - esac - -else - - 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_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit mode not supported for $arch" >&5 -$as_echo "$as_me: WARNING: 64bit mode not supported for $arch" >&2;} -fi -fi - -fi - - #-------------------------------------------------------------------- - # On Solaris 5.x i386 with the sunpro compiler we need to link - # with sunmath to get floating point rounding control - #-------------------------------------------------------------------- - if test "$GCC" = yes; then : - use_sunmath=no -else - - arch=`isainfo` - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use -lsunmath for fp rounding control" >&5 -$as_echo_n "checking whether to use -lsunmath for fp rounding control... " >&6; } - if test "$arch" = "amd64 i386" -o "$arch" = "i386"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - MATH_LIBS="-lsunmath $MATH_LIBS" - ac_fn_c_check_header_mongrel "$LINENO" "sunmath.h" "ac_cv_header_sunmath_h" "$ac_includes_default" -if test "x$ac_cv_header_sunmath_h" = xyes; then : - -fi - - - use_sunmath=yes - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - use_sunmath=no - -fi - -fi - SHLIB_SUFFIX=".so" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - 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. - 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 - if test "$arch" = "amd64 i386"; then : - - SHLIB_LD="$SHLIB_LD -m64 -static-libgcc" - -fi -fi - -fi - -else - - if test "$use_sunmath" = yes; then : - textmode=textoff -else - textmode=text -fi - case $system in - SunOS-5.[1-9][0-9]*|SunOS-5.[7-9]) - SHLIB_LD="\${CC} -G -z $textmode \${LDFLAGS}";; - *) - SHLIB_LD="/usr/ccs/bin/ld -G -z $textmode";; - 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" - DL_OBJS="tclLoadDl.o" - DL_LIBS="-ldl" - # Some UNIX_SV* systems (unixware 1.1.2 for example) have linkers - # that don't grok the -Bexport option. Test that it does. - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld accepts -Bexport flag" >&5 -$as_echo_n "checking for ld accepts -Bexport flag... " >&6; } -if ${tcl_cv_ld_Bexport+:} false; then : - $as_echo_n "(cached) " >&6 -else - - hold_ldflags=$LDFLAGS - LDFLAGS="$LDFLAGS -Wl,-Bexport" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -int i; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - tcl_cv_ld_Bexport=yes -else - tcl_cv_ld_Bexport=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$hold_ldflags -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_ld_Bexport" >&5 -$as_echo "$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 : - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 64bit support being disabled -- don't know magic for this platform" >&5 -$as_echo "$as_me: WARNING: 64bit support being disabled -- don't know magic for this platform" >&2;} - -fi - - if test "$do64bit" = yes -a "$do64bit_ok" = yes; then : - - -$as_echo "#define TCL_CFG_DO64BIT 1" >>confdefs.h - - -fi - - - - # Step 4: disable dynamic loading if requested via a command-line switch. - - # Check whether --enable-load was given. -if test "${enable_load+set}" = set; then : - enableval=$enable_load; tcl_ok=$enableval -else - tcl_ok=yes -fi - - if test "$tcl_ok" = no; then : - DL_OBJS="" -fi - - if test "x$DL_OBJS" != x; then : - BUILD_DLTEST="\$(DLTEST_TARGETS)" -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&5 -$as_echo "$as_me: WARNING: Can't figure out how to do dynamic loading or shared libraries on this system." >&2;} - SHLIB_CFLAGS="" - SHLIB_LD="" - SHLIB_SUFFIX="" - DL_OBJS="tclLoadNone.o" - DL_LIBS="" - LDFLAGS="$LDFLAGS_ORIG" - CC_SEARCH_FLAGS="" - LD_SEARCH_FLAGS="" - BUILD_DLTEST="" - -fi - 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 "$DL_OBJS" != "tclLoadNone.o" -a "$GCC" = yes; then : - - case $system in - AIX-*) ;; - BSD/OS*) ;; - CYGWIN_*|MINGW32_*) ;; - IRIX*) ;; - NetBSD-*|FreeBSD-*|OpenBSD-*) ;; - Darwin-*) ;; - SCO_SV-3.2*) ;; - *) SHLIB_CFLAGS="-fPIC" ;; - esac -fi - - if test "$tcl_cv_cc_visibility_hidden" != yes; then : - - -$as_echo "#define MODULE_SCOPE extern" >>confdefs.h - - -fi - - if test "$SHARED_LIB_SUFFIX" = ""; then : - - SHARED_LIB_SUFFIX='${VERSION}${SHLIB_SUFFIX}' -fi - if test "$UNSHARED_LIB_SUFFIX" = ""; then : - - UNSHARED_LIB_SUFFIX='${VERSION}.a' -fi - DLL_INSTALL_DIR="\$(LIB_INSTALL_DIR)" - - if test "${SHARED_BUILD}" = 1 -a "${SHLIB_SUFFIX}" != ""; then : - - LIB_SUFFIX=${SHARED_LIB_SUFFIX} - MAKE_LIB='${SHLIB_LD} -o $@ ${OBJS} ${TCL_SHLIB_LD_EXTRAS} ${SHLIB_LD_LIBS} ${TK_SHLIB_LD_EXTRAS} ${LD_SEARCH_FLAGS}' - if test "${SHLIB_SUFFIX}" = ".dll"; then : - - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(BIN_INSTALL_DIR)/$(LIB_FILE)"' - DLL_INSTALL_DIR="\$(BIN_INSTALL_DIR)" - -else - - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' - -fi - -else - - LIB_SUFFIX=${UNSHARED_LIB_SUFFIX} - - if test "$RANLIB" = ""; then : - - MAKE_LIB='$(STLIB_LD) $@ ${OBJS}' - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)"' - -else - - MAKE_LIB='${STLIB_LD} $@ ${OBJS} ; ${RANLIB} $@' - INSTALL_LIB='$(INSTALL_LIBRARY) $(LIB_FILE) "$(LIB_INSTALL_DIR)/$(LIB_FILE)" ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(LIB_FILE))' - -fi - -fi - - # Stub lib does not depend on shared/static configuration - if test "$RANLIB" = ""; then : - - MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS}' - INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)"' - -else - - MAKE_STUB_LIB='${STLIB_LD} $@ ${STUB_LIB_OBJS} ; ${RANLIB} $@' - INSTALL_STUB_LIB='$(INSTALL_LIBRARY) $(STUB_LIB_FILE) "$(LIB_INSTALL_DIR)/$(STUB_LIB_FILE)" ; (cd "$(LIB_INSTALL_DIR)" ; $(RANLIB) $(STUB_LIB_FILE))' - -fi - - # Define TCL_LIBS now that we know what DL_LIBS is. - # The trick here is that we don't want to change the value of TCL_LIBS if - # it is already set when tclConfig.sh had been loaded by Tk. - if test "x${TCL_LIBS}" = x; then : - - TCL_LIBS="${DL_LIBS} ${LIBS} ${MATH_LIBS}" -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. - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cast to union support" >&5 -$as_echo_n "checking for cast to union support... " >&6; } -if ${tcl_cv_cast_to_union+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - 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 - tcl_cv_cast_to_union=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcl_cv_cast_to_union" >&5 -$as_echo "$tcl_cv_cast_to_union" >&6; } - if test "$tcl_cv_cast_to_union" = "yes"; then - -$as_echo "#define HAVE_CAST_TO_UNION 1" >>confdefs.h - - fi - - # FIXME: This subst was left in only because the TCL_DL_LIBS - # entry in tclConfig.sh uses it. It is not clear why someone - # would use TCL_DL_LIBS instead of TCL_LIBS. - - - - - - - - - - - - - - - - - - - - - - - - - -cat >>confdefs.h <<_ACEOF -#define TCL_SHLIB_EXT "${SHLIB_SUFFIX}" -_ACEOF - - - - - - - - - - RC= - RES= - TK_RES= - - - -fi - -#ODIE components - - - - - - -ac_config_files="$ac_config_files odieConfig.sh:odieConfig.sh.in odieConfig.tcl:odieConfig.tcl.in" - -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_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 -$as_echo "$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+set}" = set || &/ - 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 - { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 -$as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 -$as_echo "$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` - - - -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" -{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 -$as_echo "$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 -if test -n "${ZSH_VERSION+set}" && (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 - case `(set -o) 2>/dev/null` in #( - *posix*) : - set -o posix ;; #( - *) : - ;; -esac -fi - - -as_nl=' -' -export as_nl -# Printing a long string crashes Solaris 7 /usr/bin/printf. -as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo -as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo -# Prefer a ksh shell builtin over an external printf program on Solaris, -# but without wasting forks for bash or zsh. -if test -z "$BASH_VERSION$ZSH_VERSION" \ - && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='print -r --' - as_echo_n='print -rn --' -elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then - as_echo='printf %s\n' - as_echo_n='printf %s' -else - if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then - as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' - as_echo_n='/usr/ucb/echo -n' - else - as_echo_body='eval expr "X$1" : "X\\(.*\\)"' - as_echo_n_body='eval - arg=$1; - case $arg in #( - *"$as_nl"*) - expr "X$arg" : "X\\(.*\\)$as_nl"; - arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; - esac; - expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" - ' - export as_echo_n_body - as_echo_n='sh -c $as_echo_n_body as_echo' - fi - export as_echo_body - as_echo='sh -c $as_echo_body as_echo' -fi - -# The user is always right. -if test "${PATH_SEPARATOR+set}" != set; 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 - - -# IFS -# We need space, tab and new line, in precisely that order. Quoting is -# there to prevent editors from complaining about space-tab. -# (If _AS_PATH_WALK were called with IFS unset, it would disable word -# splitting by setting IFS to empty value.) -IFS=" "" $as_nl" - -# 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 - test -z "$as_dir" && as_dir=. - 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 - $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 - exit 1 -fi - -# Unset variables that we do not need and which cause bugs (e.g. in -# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" -# suppresses any "Segmentation fault" message there. '((' could -# trigger a bug in pdksh 5.2.14. -for as_var in BASH_ENV ENV MAIL MAILPATH -do eval test x\${$as_var+set} = xset \ - && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : -done -PS1='$ ' -PS2='> ' -PS4='+ ' - -# NLS nuisances. -LC_ALL=C -export LC_ALL -LANGUAGE=C -export LANGUAGE - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - - -# 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 - $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 - fi - $as_echo "$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_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_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 || -$as_echo 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 - -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 - -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=`$as_echo "$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 || -$as_echo 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 odielib $as_me 2.1, which was -generated by GNU Autoconf 2.69. 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 -cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" -ac_cs_version="\\ -odielib config.status 2.1 -configured by $0, generated by GNU Autoconf 2.69, - with options \\"\$ac_cs_config\\" - -Copyright (C) 2012 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 ) - $as_echo "$ac_cs_version"; exit ;; - --config | --confi | --conf | --con | --co | --c ) - $as_echo "$ac_cs_config"; exit ;; - --debug | --debu | --deb | --de | --d | -d ) - debug=: ;; - --file | --fil | --fi | --f ) - $ac_shift - case $ac_optarg in - *\'*) ac_optarg=`$as_echo "$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 ) - $as_echo "$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 - \$as_echo "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 - $as_echo "$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 - "odieConfig.sh") CONFIG_FILES="$CONFIG_FILES odieConfig.sh:odieConfig.sh.in" ;; - "odieConfig.tcl") CONFIG_FILES="$CONFIG_FILES odieConfig.tcl:odieConfig.tcl.in" ;; - - *) 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+set}" = set || 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=`$as_echo "$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 '` - $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' - `' by configure.' - if test x"$ac_file" != x-; then - configure_input="$ac_file. $configure_input" - { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 -$as_echo "$as_me: creating $ac_file" >&6;} - fi - # Neutralize special characters interpreted by sed in replacement strings. - case $configure_input in #( - *\&* | *\|* | *\\* ) - ac_sed_conf_input=`$as_echo "$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 || -$as_echo 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=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` - # A ".." for each directory in $ac_dir_suffix. - ac_top_builddir_sub=`$as_echo "$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@*) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 -$as_echo "$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"; } && - { $as_echo "$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 -$as_echo "$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 - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 -$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} -fi - - +#!/bin/sh + +dir=`dirname "$0"` +tclsh=`$dir/autosetup/find-tclsh` +echo tclsh $tclsh +$tclsh $dir/autosetup/autosetup "$@" Index: odie.komodoproject ================================================================== --- odie.komodoproject +++ odie.komodoproject @@ -2,8 +2,8 @@ *.*~;*.bak;*.tmp;CVS;.#*;*.pyo;*.pyc;.svn;*%*;tmp*.html;.DS_Store;.fslckout;cthulhu.rc;*.vfs;embedded - *.c;Makefile*;*.tcl;*.h;cthulhu*;*.in;*.3;*.n;*.html;*.man;*.sh;*.m4;*.sql + auto.def;autosetup;*.c;Makefile*;*.tcl;*.h;cthulhu*;*.in;*.3;*.n;*.html;*.man;*.sh;*.m4;*.sql Index: odieConfig.sh.in ================================================================== --- odieConfig.sh.in +++ odieConfig.sh.in @@ -15,10 +15,11 @@ # The values specified here may be overridden at configure-time with the # --exec-prefix and --prefix options to the "configure" script. The *dir vars # are standard configure substitutions that are based off prefix and # exec_prefix. SHELL=@SHELL@ +ODIE_BUILD_TCLSH=@ODIE_BUILD_TCLSH@ prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ libdir=@libdir@ @@ -29,84 +30,58 @@ # The following definition can be set to non-null for special systems like AFS # with replication. It allows the pathnames used for installation to be # different than those used for actually reference files at run-time. # INSTALL_ROOT is prepended to $prefix and $exec_prefix when installing files. INSTALL_ROOT=${DESTDIR} -ODIE_SRC_DIR=@ODIE_SRC_DIR@ -TCL_VERSION=@TCL_VERSION@ -TCL_MAJOR_VERSION=@TCL_MAJOR_VERSION@ -TCL_MINOR_VERSION=@TCL_MINOR_VERSION@ -TCL_FULL_VERSION=@TCL_VERSION@@TCL_PATCH_LEVEL@ -TCL_FOSSIL_BRANCH=@TCL_FOSSIL_BRANCH@ -TK_VERSION=@TCL_VERSION@ -TK_MAJOR_VERSION=@TCL_MAJOR_VERSION@ -TK_MINOR_VERSION=@TCL_MINOR_VERSION@ -TK_FULL_VERSION=@TK_VERSION@@TK_PATCH_LEVEL@ -TK_FOSSIL_BRANCH=@TK_FOSSIL_BRANCH@ -ODIE_TCL_CONFIG_FLAGS='@ODIE_TCL_CONFIG_FLAGS@' -ODIE_TK_CONFIG_FLAGS='@ODIE_TK_CONFIG_FLAGS@' + ODIE_ROOT=@prefix@ LOCAL_REPO=@prefix@ -ODIE_PLATFORM=@ODIE_PLATFORM@ -ODIE_CPU=@ODIE_PLATFORM@ - -ODIE_TCLSRC_DIR=@ODIE_TCLSRC_DIR@ -ODIE_PLATFORM_DIR=@ODIE_PLATFORM_DIR@ -ODIE_SYSTEM=@ODIE_SYSTEM@ -ODIE_OS=@ODIE_OS@ -FOSSIL_CHECKOUT=@FOSSIL_CHECKOUT@ +FOSSIL_CHECKOUT=@ODIE_FOSSIL_CHECKOUT@ PLATFORM=${ODIE_PLATFORM} -ODIE_HOST=@ODIE_HOST@ -ODIE_TARGET=@ODIE_TARGET@ -ODIE_BUILD_SYSTEM=@ODIE_BUILD_SYSTEM@ -ODIE_BUILD_OS=@ODIE_BUILD_OS@ -ODIE_BUILD_64BIT=@ODIE_BUILD_64BIT@ -ODIE_BINARY_PLATFORM=@ODIE_BINARY_PLATFORM@ -ODIE_WINDOW_SYSTEM=@ODIE_WINDOW_SYSTEM@ + RC=@RC@ RES=@RES@ TK_RES=@TK_RES@ ### -# Variables needed by build systems +# Backward compadible names needed by build systems ### -ODIE_SANDBOX_PATH=@ODIE_SANDBOX_PATH@ -SANDBOX=${ODIE_SANDBOX_PATH} -ODIE_DOWNLOAD_PATH=@ODIE_DOWNLOAD_PATH@ -DOWNLOAD=${ODIE_DOWNLOAD_PATH} - -ODIEMIRRORURL=http://fossil.etoyoc.com/fossil +SANDBOX=@ODIE_SANDBOX_PATH@ +DOWNLOAD=@ODIE_DOWNLOAD_PATH@ +ODIEMIRRORURL=@ODIE_MIRROR_URL@ # ODIE_TCLSH is the name of a tclsh executable produced # my make tcltk EXE_SUFFIX=@EXEEXT@ EXE=${EXE_SUFFIX} TCL_EXE=tclsh${EXE_SUFFIX} TCLTEST_EXE=tcltest${EXE_SUFFIX} -ODIE_BUILD_TCLSH=@BUILD_TCLSH@ -ODIE_TCLSH=@TCLSH_PROG@ -ODIE_WISH=@WISH_PROG@ +ODIE_TCLSH=@ODIE_TCL_SHELL@ +ODIE_WISH=@ODIE_WISH_SHELL@ TCLSH=${ODIE_TCLSH} -TCL_SHELL=${ODIE_TCLSH} +TCL_SHELL=${ODIE_BUILD_TCLSH} CC=@CC@ #CC=purify -best-effort @CC@ -DPURIFY -ODIE_WISHKIT=@TCLKIT_PROG@ -ODIE_TCLKIT=@TCLKIT_PROG@ -ODIE_TOADKIT=@TOADKIT_PROG@ -ODIE_ZIPKIT=${exec_prefix}/bin/zipkit.zip ODIE_STATIC_TCLLIB=${exec_prefix}/lib/tclstaticlib.a ODIE_STATIC_TKLIB=${exec_prefix}/lib/tkstaticlib.a -TOADKIT=${ODIE_TOADKIT} +TOADKIT=@ODIE_TOADKIT@ ODIE_MKHDR=${exec_prefix}/bin/mkhdr${EXE_SUFFIX} ZIPSETUP=${exec_prefix}/bin/zzipsetupstub${EXE_SUFFIX} -SHERPA=${exec_prefix}/bin/sherpa${EXE_SUFFIX} -KETTLE="${ODIE_TCLSH} ${exec_prefix}/bin/kettle" + GIT_PROG=@GIT_PROG@ FOSSIL=@FOSSIL_PROG@ MKHDR=@MKHDR_PROG@ ZIP=@ZIP_PROG@ UNZIP=@UNZIP_PROG@ -ODIE_RM="${ODIE_TCLSH} ${ODIE_SRC_DIR}/scripts/rmdir.tcl" -#VFS_CP=@VFS_CP@ +ODIE_RM=${ODIE_BUILD_TCLSH} +ODIE_RM+=${ODIE_SRC_DIR}/scripts/rmdir.tcl +SHERPA=${ODIE_BUILD_TCLSH} +SHERPA+=@ODIE_SANDBOX_PATH@/sherpa/sherpa.tcl +KETTLE=${ODIE_BUILD_TCLSH} +KETTLE+=${exec_prefix}/bin/kettle + +### +# Bits generated by autosetup +### Index: odieConfig.tcl.in ================================================================== --- odieConfig.tcl.in +++ odieConfig.tcl.in @@ -15,11 +15,11 @@ set TCL_MINOR_VERSION @TCL_MINOR_VERSION@ set TK_VERSION @TK_VERSION@ set TK_MAJOR_VERSION @TK_MAJOR_VERSION@ set TK_MINOR_VERSION @TK_MINOR_VERSION@ set ODIE_BINARY_PLATFORM @ODIE_BINARY_PLATFORM@ -set ODIEMIRRORURL http://fossil.etoyoc.com/fossil +set ODIEMIRRORURL @ODIE_MIRROR_URL@ set EXEEXT "@EXEEXT@" package require platform set ::odie(local_repo) $prefix set ::odie(platform_build) [::platform::generic] @@ -50,11 +50,10 @@ odie_binary_platform "@ODIE_BINARY_PLATFORM@" odie_cpu "@ODIE_CPU@" odie_window_system "@ODIE_WINDOW_SYSTEM@" tcl_fossil_branch "@TCL_FOSSIL_BRANCH@" tk_fossil_branch "@TK_FOSSIL_BRANCH@" - fskckout "@FOSSIL_CHECKOUT@" cc "@CC@" shell "@MAKEFILE_SHELL@" exe_suffix "@EXEEXT@" shlib_suffix "@SHLIB_SUFFIX@" zip "@ZIP_PROG@" @@ -67,11 +66,11 @@ wish_shell "@WISH_PROG@" zzetup "${exec_prefix}/bin/zzipsetupstub@EXEEXT@" wish_kit "@TKKIT_PROG@" tcl_kit "@TCLKIT_PROG@" toad_kit "@TOADKIT_PROG@" - sherpa "${exec_prefix}/bin/sherpa@EXEEXT@" + sherpa "@ODIE_BUILD_TCLSH@ @ODIE_SANDBOX_PATH@/sherpa/sherpa.tcl" kettle "${exec_prefix}/bin/kettle" zip_kit "${exec_prefix}/bin/zipkit.zip" lib "$prefix/lib" rc "@RC@" res "@RES@" ADDED scripts/common.tcl Index: scripts/common.tcl ================================================================== --- /dev/null +++ scripts/common.tcl @@ -0,0 +1,260 @@ +### +# Common suite of routines for the odie boostrap process +### +set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] +if {[file exists [file join $path odieConfig.tcl]]} { + source [file join $path odieConfig.tcl] +} +lappend ::auto_path [file join $::odie(prefix) lib] +set ::autosetup(exe) $::argv0 +set ::autosetup(istcl) 1 +set ::autosetup(start) [clock millis] +set ::autosetup(installed) 0 +set ::autosetup(msg-checking) 0 +set ::autosetup(msg-quiet) 0 +set ::autosetup(msg-timing) 0 +set ::autosetup(dir) [file join $path autosetup] +set ::autosetup(builddir) [file join $path] +set ::autosetup(srcdir) [file join $path] +set ::autosetup(libdir) [file join $path autosetup lib] +set ::autosetup(debug) 1 +set ::autosetup(cmdline) {} +set ::autosetup(options) {} +set ::autosetup(optionhelp) {} +set ::autosetup(showhelp) 0 + +foreach file { + core.tcl formatting.tcl getopt.tcl misc.tcl +} { + source [file join $::autosetup(libdir) $file] +} + +proc ::noop args {} + +namespace eval ::sherpa_bootstrap {} + +proc ::sherpa_bootstrap::download_fossil {pkg} { + variable distribution + set PKG_SRCPATH [sandbox_path $pkg] + set fosdb [fossil_db $pkg] + if {![file exists $fosdb]} { + puts "Fossil clone $pkg" + set fossil_url {} + if {[dict exists $distribution $pkg fossil_url]} { + set fossil_url [dict get $distribution $pkg fossil_url] + } + if {$fossil_url eq {}} { + set fossil_url $::odie(mirror_url)/$pkg + } + doexec $::odie(fossil) clone $fossil_url $fosdb + } + + if {![file exists ${PKG_SRCPATH}/$::odie(fossil_checkout)]} { + puts "Fossil open $pkg" + file mkdir ${PKG_SRCPATH} + cd ${PKG_SRCPATH} + doexec $::odie(fossil) open $fosdb + } + cd ${PKG_SRCPATH} + if {[dict exists $distribution $pkg fossil_branch]} { + doexec $::odie(fossil) update [dict get $distribution $pkg fossil_branch] + } else { + doexec $::odie(fossil) update + } + return ${PKG_SRCPATH} +} + +proc ::sherpa_bootstrap::fossil_db pkg { + if {[file exists [file join $::odie(download) $pkg.fossil]]} { + return [file join $::odie(download) $pkg.fossil] + } + return [file join $::odie(download) $pkg.fos] +} + + +proc ::sherpa_bootstrap::sandbox_path pkg { + return [file join $::odie(sandbox) $pkg] +} + +proc ::sherpa_bootstrap::build_gnumake {pkg action} { + puts "BUILD GNUMAKE $pkg $action" + if {$action eq "install"} { + set PKG_SRCPATH [sandbox_path $pkg] + cd ${PKG_SRCPATH} + doexec $::odie(fossil) update + set args [list --prefix=$::odie(local_repo)] + if {$::odie(host) != $::odie(target)} { + lappend args --host=$::odie(host) + } + if {[file exists ${PKG_SRCPATH}/auto.def]} { + doexec [info nameofexecutable] $::odie(odie_src_dir)/autosetup/autosetup {*}$args + } elseif {![file exists ${PKG_SRCPATH}/Makefile]} { + lappend args --libdir=$::odie(local_repo)/lib + doexec sh ./configure {*}$args + } + if [catch { + domake install + } err] { + puts "Died on $err" + exit 1 + } + } else { + set PKG_SRCPATH [sandbox_path $pkg] + cd ${PKG_SRCPATH} + if [catch { + domake $action + } err] { + puts "Died on $err" + exit 1 + } + } +} + +proc ::sherpa_bootstrap::build_sak {pkg action} { + if {$action eq "install"} { + set PKG_SRCPATH [sandbox_path $pkg] + doexec $::odie(build_tclsh) [file join $PKG_SRCPATH installer.tcl] \ + -app-path $::odie(prefix)/bin -pkg-path $::odie(prefix)/lib/$pkg \ + -no-examples -no-nroff -no-html \ + -no-wait -no-gui + } +} + +proc ::sherpa_bootstrap::build_kettle {pkg action} { + set PKG_SRCPATH [sandbox_path $pkg] + if {$pkg eq "kettle"} { + doexec $::odie(build_tclsh) [file join $PKG_SRCPATH kettle] -f [file join $PKG_SRCPATH build.tcl] $action + } else { + doexec $::odie(build_tclsh) $::odie(kettle) -f [file join $PKG_SRCPATH build.tcl] $action + } +} + +proc ::sherpa_bootstrap::build_sqlite {pkg action} { + ### + # Sqlite + ### + puts "INSTALLING SQLITE" + set SQLITE_VERSION 3.8.7.2 + set SQLITE_TFNAME sqlite-autoconf-3080704 + set SQLITE_SRCPATH $::odie(sandbox)/sqlite + set SQLITE_URL http://sqlite.org/2014/${SQLITE_TFNAME}.tar.gz + # In MSYS, tar may not understand the prefix + set download_msys [::cygpath [pwd]] + set SQLITE_TARBALL [file join [::realpath $::odie(download)] sqlite${SQLITE_VERSION}.tar.gz] + cd [::realpath $::odie(src_dir)] + if {![file exists $SQLITE_TARBALL]} { + doexec $::odie(build_tclsh) scripts/url-get.tcl ${SQLITE_URL} ${SQLITE_TARBALL} + } + if {![file exists ${SQLITE_SRCPATH}/README]} { + file delete -force ${SQLITE_SRCPATH} + cd $::odie(sandbox) + doexec tar xfz [::cygpath ${SQLITE_TARBALL}] + file rename -force ${SQLITE_TFNAME} ${SQLITE_SRCPATH} + } + cd ${SQLITE_SRCPATH}/tea + if {![file exists ${SQLITE_SRCPATH}/tea/Makefile]} { + doexec sh ./configure --prefix=[::cygpath $::odie(local_repo)] --libdir=[::cygpath $::odie(local_repo)/lib] --host=$::odie(host) + } + doexec make install +} + +proc ::sherpa_bootstrap::install_package package { + variable distribution + set pkginfo [dict get $distribution $package] + puts [list $package $pkginfo] + set download [dict get $pkginfo get_proc] + $download $package + set build [dict get $pkginfo build_proc] + $build $package install +} + +proc ::sherpa_bootstrap::distribution {name properties} { + variable distribution + foreach {field value} $properties { + + dict set distribution $name $field $value + } + if {![dict exists $distribution $name get_proc]} { + dict set distribution $name get_proc ::noop + } + if {![dict exists $distribution $name build_proc]} { + dict set distribution $name build_proc ::noop + } +} + +::sherpa_bootstrap::distribution sqlite { + get_proc ::noop + build_proc build_sqlite + #build_proc ::noop +} + +if {!$::odie(windows)} { + ::sherpa_bootstrap::distribution tclx { + get_proc download_fossil + build_proc build_gnumake + } +if 0 { + ::sherpa_bootstrap::distribution kettle { + get_proc download_fossil + requires {tclx tcllib tklib} + build_proc build_kettle + } +} +} +::sherpa_bootstrap::distribution tclvfs { + get_proc download_fossil + requires tcllib + build_proc build_gnumake +} +::sherpa_bootstrap::distribution taolib { + get_proc download_fossil + requires {sqlite tcllib tklib} + build_proc build_sak +} +::sherpa_bootstrap::distribution tcllib { + get_proc download_fossil + fossil_branch odie + build_proc build_sak +} +::sherpa_bootstrap::distribution tklib { + get_proc download_fossil + requires tcllib + build_proc build_sak +} + +::sherpa_bootstrap::distribution odielib { + get_proc download_fossil + fossil_branch autosetup + requires {tcllib sqlite} + build_proc build_gnumake +} + +::sherpa_bootstrap::distribution sherpa { + get_proc download_fossil + fossil_branch trunk + requires {tcllib odielib taolib sqlite} + build_proc build_gnumake +} + +proc ::doexec args { + exec {*}$args >&@ stdout +} + +### +# Make sure the odielib toolkit is downloaded +### +if {![file exists [file join $::odie(sandbox) odielib modules odie index.tcl]]} { + ::sherpa_bootstrap::download_fossil odielib +} +source [file join $path .. odielib modules odie index.tcl] +source [file join $path .. odielib modules cmdline cmdline.tcl] +source [file join $path .. odielib modules fileutil index.tcl] +source [file join $path .. odielib modules codebale index.tcl] + + + +#::sherpa_bootstrap::distribution sherpa { +# get_proc download_fossil +# requires {taolib tcllib odielib kettle} +# build_proc build_kettle +#} DELETED scripts/common.tcl.in Index: scripts/common.tcl.in ================================================================== --- scripts/common.tcl.in +++ /dev/null @@ -1,11 +0,0 @@ -set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] - -set ::odielib(srcroot) $path -set ::odielib(modules) {@PKG_TCL_MODULES@} -set ::odielib(libfile) {@PKG_LIB_FILE@} - -if {[file exists [file join $path odieConfig.tcl]]} { - source [file join $path odieConfig.tcl] -} -source [file join $path modules odie index.tcl] -source [file join $path modules codebale index.tcl] Index: scripts/make_basekit.tcl ================================================================== --- scripts/make_basekit.tcl +++ scripts/make_basekit.tcl @@ -1,26 +1,28 @@ #!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: # \ -exec tclsh "$0" ${1+"$@"} +dir=`dirname "$0"`; exec "`$dir/../autosetup/find-tclsh`" "$0" "$@" set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] -source [file join $path odieConfig.tcl] -source [file join $::odie(sandbox) odielib modules odie index.tcl] -source [file join $::odie(sandbox) odielib modules codebale index.tcl] +source [file join $path scripts common.tcl] puts "BUILDING ZipVFS KITS" set toadkits odie # Only needed for pre-zipvfs enable Tcl/Tk set TCL_STATIC_SRCPATH $::odie(sandbox)/tcl/$::odie(tcl_src_dir) set TK_STATIC_SRCPATH $::odie(sandbox)/tk/$::odie(tcl_src_dir) -if {$::odie(tk_fossil_branch) ne "none"} { +if {$::odie(window_system) ne "none"} { if { $::odie(platform) eq "windows" } { cd [::realpath ${TK_STATIC_SRCPATH}] - doexec make tk.res.o - doexec make wish.res.o + domake tk.res.o + domake wish.res.o } } -cd [::realpath $::odie(sandbox)/odie/src/toadkit] -puts "Building kits" -doexec make -C $::odie(sandbox)/odie/src/toadkit clean -doexec make -C $::odie(sandbox)/odie/src/toadkit install +cd [::realpath $::odie(src_dir)/src/toadkit] +puts "Building kits in [pwd]" +source configure.tcl +domake clean +domake install DELETED scripts/make_core.tcl Index: scripts/make_core.tcl ================================================================== --- scripts/make_core.tcl +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/sh -# \ -exec tclsh "$0" ${1+"$@"} - -set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] -source [file join $path odieConfig.tcl] - -proc ::doexec args { - exec {*}$args >&@ stdout -} - -proc get_distro {pkg} { - set PKG_SRCPATH $::odie(sandbox)/$pkg - if {![file exists $::odie(download)/$pkg.fos]} { - puts "Fossil clone $pkg" - doexec $::odie(fossil) clone $::odie(mirror)/$pkg $::odie(download)/$pkg.fos - } - - if {![file exists ${PKG_SRCPATH}/$::odie(fskckout)]} { - puts "Fossil open $pkg" - file mkdir ${PKG_SRCPATH} - cd ${PKG_SRCPATH} - doexec $::odie(fossil) open $::odie(download)/$pkg.fos - } - cd ${PKG_SRCPATH} - doexec $::odie(fossil) update - return ${PKG_SRCPATH} -} - -### -# Download odielib -### -#get_distro odielib -#source [file join $::odie(sandbox) odielib modules odie index.tcl] -#source [file join $::odie(sandbox) odielib modules codebale index.tcl] - -foreach {pkg} { - tclx - tclvfs -} { - get_distro $pkg - set PKG_SRCPATH [get_distro $pkg] - cd ${PKG_SRCPATH} - doexec $::odie(fossil) update - if {![file exists ${PKG_SRCPATH}/Makefile]} { - doexec sh ./configure --prefix=$::odie(local_repo) --libdir=$::odie(local_repo)/lib --host=$::odie(host) - } - doexec make install -} - -foreach {pkg} { - tcllib taolib tklib -} { - ### - # Get and install Tcllib - ### - get_distro $pkg - doexec $::odie(tcl_shell) [file join $::odie(sandbox) $pkg installer.tcl] \ - -no-examples -no-nroff \ - -no-wait -no-gui -no-apps -} - -get_distro kettle -doexec $::odie(tcl_shell) [file join $::odie(sandbox) kettle kettle] -f [file join $::odie(sandbox) kettle build.tcl] install - -# continue - -### -# Build odielib -### -#set ODIELIB_SRCPATH [file join $::build(odie_src_dir) src odielib] -# Make sure we have mkhdr built - -#cd ${ODIELIB_SRCPATH} -#if {![file exists ${ODIELIB_SRCPATH}/Makefile]} { -# doexec $::odie(fossil) update -# doexec sh ./configure --prefix=$::odie(local_repo) --libdir=$::odie(local_repo)/lib --host=$::odie(host) --enable-shared=yes -#} -#source [file join $::build(odie_src_dir) src odielib configure.tcl] -#cd ${ODIELIB_SRCPATH} -#file mkdir build -#if {![file exists ${ODIELIB_SRCPATH}/cthulhu.mk]} { -# doexec $::build(tcl_shell) configure.tcl -#} -#doexec make install Index: scripts/make_distclean.sh ================================================================== --- scripts/make_distclean.sh +++ scripts/make_distclean.sh @@ -5,14 +5,14 @@ rm -rf autom4te.cache rm -rf build rm -rf config.* helpdoc.* librarypkgindex.tcl rm -rf cthulhu.mk mkhdr* -cd ${ODIE_SANDBOX_PATH}/tcl/${ODIE_TCLSRC_DIR} ; make distclean -cd ${ODIE_SANDBOX_PATH}/tk/${ODIE_TCLSRC_DIR} ; make distclean -cd ${ODIE_SANDBOX_PATH}/tcl-static/${ODIE_TCLSRC_DIR} ; make distclean -cd ${ODIE_SANDBOX_PATH}/tk-static/${ODIE_TCLSRC_DIR} ; make distclean +cd ${ODIE_SANDBOX_PATH}/tcl/${ODIE_TCL_PLATFORM_DIR} ; make distclean +cd ${ODIE_SANDBOX_PATH}/tk/${ODIE_TCL_PLATFORM_DIR} ; make distclean +cd ${ODIE_SANDBOX_PATH}/tcl-static/${ODIE_TCL_PLATFORM_DIR} ; make distclean +cd ${ODIE_SANDBOX_PATH}/tk-static/${ODIE_TCL_PLATFORM_DIR} ; make distclean cd ${ODIE_SANDBOX_PATH}/sqlite/tea ; make distclean cd ${ODIE_SANDBOX_PATH}/tclvfs ; make distclean cd ${ODIE_SANDBOX_PATH}/tcllib ; make distclean cd ${ODIE_SRC_DIR}/apps/sherpa ; make clean cd ${ODIE_SRC_DIR}/src/toadkit ; make clean Index: scripts/make_sherpa.tcl ================================================================== --- scripts/make_sherpa.tcl +++ scripts/make_sherpa.tcl @@ -1,44 +1,49 @@ #!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: # \ -exec tclsh "$0" ${1+"$@"} - -set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] -source [file join $path odieConfig.tcl] +dir=`dirname "$0"`; exec "`$dir/../autosetup/find-tclsh`" "$0" "$@" +set path [file dirname [file normalize [info script]]] proc ::doexec args { exec {*}$args >&@ stdout } -proc get_distro {pkg} { +source $path/../odieConfig.tcl + +proc get_distro {pkg {tag trunk}} { set PKG_SRCPATH $::odie(sandbox)/$pkg if {![file exists $::odie(download)/$pkg.fos]} { puts "Fossil clone $pkg" - doexec $::odie(fossil) clone $::odie(mirror)/$pkg $::odie(download)/$pkg.fos + doexec $::odie(fossil) clone $::odie(mirror_url)/$pkg $::odie(download)/$pkg.fos } - if {![file exists ${PKG_SRCPATH}/$::odie(fskckout)]} { + if {![file exists ${PKG_SRCPATH}/$::odie(fossil_checkout)]} { puts "Fossil open $pkg" file mkdir ${PKG_SRCPATH} cd ${PKG_SRCPATH} doexec $::odie(fossil) open $::odie(download)/$pkg.fos } cd ${PKG_SRCPATH} - doexec $::odie(fossil) update + doexec $::odie(fossil) update $tag return ${PKG_SRCPATH} } -get_distro odielib +get_distro tcllib odie get_distro sherpa -source [file join $path .. odielib modules odie index.tcl] -source [file join $path .. odielib modules codebale index.tcl] - ### # Build supporting libraries needed by Sherpa ## # Rebuild sherpa -set SHERPA_SRCPATH $::odie(odie_src_dir)/apps/sherpa -cd ${SHERPA_SRCPATH} -doexec make clean -doexec make install +set SHERPA_SRCPATH $::odie(src_dir)/../sherpa +if {$::tcl_platform(platform) eq "windows"} { + file copy -force ${SHERPA_SRCPATH}/sherpa.cmd $::odie(prefix)/bin/sherpa.cmd + file copy -force ${SHERPA_SRCPATH}/sherpa.tcl $::odie(prefix)/bin/sherpa.tcl + file copy -force ${SHERPA_SRCPATH}/sherpa.tcl $::odie(prefix)/bin/sherpa +} else { + file delete $::odie(prefix)/bin/sherpa + file link ${SHERPA_SRCPATH}/sherpa.tcl $::odie(prefix)/bin/sherpa +} Index: scripts/make_skel.sh ================================================================== --- scripts/make_skel.sh +++ scripts/make_skel.sh @@ -36,6 +36,6 @@ # Build and install the mkhdr binary ### cd ${ODIE_SRC_DIR} ${CC} -o mkhdr.o -c scripts/mkhdr.c ${CC} mkhdr.o -o mkhdr${EXEEXT} -cp -af mkhdr${EXEEXT} ${MKHDR} +cp -af mkhdr${EXEEXT} ${LOCAL_REPO}/bin/mkhdr${EXEEXT} Index: scripts/make_sqlite.tcl ================================================================== --- scripts/make_sqlite.tcl +++ scripts/make_sqlite.tcl @@ -1,13 +1,14 @@ #!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: # \ -exec tclsh "$0" ${1+"$@"} +dir=`dirname "$0"`; exec "`$dir/../autosetup/find-tclsh`" "$0" "$@" set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] -source [file join $path odieConfig.tcl] -source [file join $::odie(sandbox) odielib modules odie index.tcl] -source [file join $::odie(sandbox) odielib modules codebale index.tcl] +source [file join $path scripts common.tcl] ### # Sqlite ### set SQLITE_VERSION 3.8.7.4 @@ -15,13 +16,13 @@ set SQLITE_SRCPATH $::odie(sandbox)/sqlite set SQLITE_URL http://sqlite.org/2014/${SQLITE_TFNAME}.tar.gz # In MSYS, tar may not understand the prefix set download_msys [exec pwd] set SQLITE_TARBALL [file join [::realpath $::odie(download)] sqlite${SQLITE_VERSION}.tar.gz] -cd [::realpath $::odie(odie_src_dir)] +cd [::realpath $::odie(src_dir)] if {![file exists $SQLITE_TARBALL]} { - doexec $::odie(tcl_shell) scripts/url-get.tcl ${SQLITE_URL} ${SQLITE_TARBALL} + doexec $::odie(build_tclsh) scripts/url-get.tcl ${SQLITE_URL} ${SQLITE_TARBALL} } if {![file exists ${SQLITE_SRCPATH}/README]} { file delete -force ${SQLITE_SRCPATH} cd $::odie(sandbox) doexec tar xfz [::cygpath ${SQLITE_TARBALL}] Index: scripts/make_tcl.sh ================================================================== --- scripts/make_tcl.sh +++ scripts/make_tcl.sh @@ -1,19 +1,21 @@ #! /bin/bash source odieConfig.sh -TCL_SRCPATH=${SANDBOX}/tcl/${ODIE_TCLSRC_DIR} -TK_SRCPATH=${SANDBOX}/tk/${ODIE_TCLSRC_DIR} +TCL_SRCPATH=${SANDBOX}/tcl/${ODIE_TCL_PLATFORM_DIR} +TK_SRCPATH=${SANDBOX}/tk/${ODIE_TCL_PLATFORM_DIR} ODIE_SRCPATH=${SANDBOX}/odie echo DOWNLOAD $DOWNLOAD echo "Building Local Tcl" if [ ! -f "${DOWNLOAD}/tcl.fos" ]; then echo ${FOSSIL} clone ${ODIEMIRRORURL}/tcl ${DOWNLOAD}/tcl.fos ${FOSSIL} clone ${ODIEMIRRORURL}/tcl ${DOWNLOAD}/tcl.fos fi +echo $ODIE_HOST +echo $ODIE_TARGET if [ ! -f "${SANDBOX}/tcl/${FOSSIL_CHECKOUT}" ]; then mkdir -p ${SANDBOX}/tcl cd ${SANDBOX}/tcl ${FOSSIL} open ${DOWNLOAD}/tcl.fos @@ -21,36 +23,35 @@ cd ${SANDBOX}/tcl ${FOSSIL} update ${TCL_FOSSIL_BRANCH} cd ${TCL_SRCPATH} # Build Tcl twice. Once statically, once dynamically echo Build Static Tcl -sh ./configure --enable-shared=no --with-tzdata --host=${ODIE_HOST} ${ODIE_TCL_CONFIG_FLAGS} +if [ "${ODIE_HOST}" != "${ODIE_TARGET}" ] ; then + sh ./configure --enable-shared=no --with-tzdata --host=${ODIE_TARGET} ${TCL_CONFIG_FLAGS} +else + sh ./configure --enable-shared=no --with-tzdata ${TCL_CONFIG_FLAGS} +fi make clean make binaries echo "COPYING STATIC LIBRARY" source tclConfig.sh cp -f $TCL_LIB_FILE ${ODIE_STATIC_TCLLIB} cp -f tclConfig.sh ${exec_prefix}/lib/tclkitConfig.sh -cd ${ODIE_SRCPATH}/src/odielib -echo "BUILDING STATIC ODIELIB `pwd`" -sh ./configure --enable-shared=no --host=${ODIE_HOST} --with-tcl=${TCL_SRCPATH} -$(ODIE_TCLSH) configure.tcl -make clean -make depend -make static -cp -f odielib.a ${exec_prefix}/lib/odielib.a -make distclean - cd ${TCL_SRCPATH} echo Build Dynamic Tcl -sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib --with-tzdata --host=${ODIE_HOST} ${ODIE_TCL_CONFIG_FLAGS} +if [ "${ODIE_HOST}" != "${ODIE_TARGET}" ] ; then + sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib --with-tzdata --host=${ODIE_TARGET} ${TCL_CONFIG_FLAGS} +else + sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib --with-tzdata ${TCL_CONFIG_FLAGS} +fi make clean +make binaries make install if [ "${TK_FOSSIL_BRANCH}" != "none" ] ; then - TK_SRCPATH=${SANDBOX}/tk/${ODIE_TCLSRC_DIR} + TK_SRCPATH=${SANDBOX}/tk/${ODIE_TCL_PLATFORM_DIR} echo "Building Local Tk" if [ ! -f "${DOWNLOAD}/tk.fos" ] ; then ${FOSSIL} clone ${ODIEMIRRORURL}/tk ${DOWNLOAD}/tk.fos fi @@ -61,31 +62,25 @@ fi cd ${SANDBOX}/tk ${FOSSIL} update ${TK_FOSSIL_BRANCH} cd ${TK_SRCPATH} echo Build Dynamic Tk - sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib --host=${ODIE_HOST} ${ODIE_TK_CONFIG_FLAGS} + if [ "${ODIE_OS}" == "macosx" ] ; then + if [ "${ODIE_CONFIG_WINDOWSYSTEM}" == "x11" ] ; then + export CPPFLAGS=-I/opt/X11/include + fi + fi + if [ "${ODIE_HOST}" != "${ODIE_TARGET}" ] ; then + sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib --host=${ODIE_TARGET} ${TK_CONFIG_FLAGS} + else + sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib ${TK_CONFIG_FLAGS} + fi make clean + make binaries make install fi ### -# Install Tcllib +# Re-run our configure to learn new things from Tcl ### -TCLLIB_SRCPATH=${SANDBOX}/tcllib -echo "Building Tcllib" -if [ ! -f "${DOWNLOAD}/tcllib.fos" ]; then - ${FOSSIL} clone ${ODIEMIRRORURL}/tcllib ${DOWNLOAD}/tcllib.fos -fi - -if [ ! -f "${TCLLIB_SRCPATH}/${FOSSIL_CHECKOUT}" ]; then - mkdir -p ${TCLLIB_SRCPATH} - cd ${TCLLIB_SRCPATH} - ${FOSSIL} open ${DOWNLOAD}/tcllib.fos -fi -${FOSSIL} update odie -cd ${TCLLIB_SRCPATH} -${ODIE_TCLSH} ${TCLLIB_SRCPATH}/installer.tcl -no-gui -no-wait -no-examples -#if [ ! -f "${TCLLIB_SRCPATH}/Makefile" ] ; then -# sh ./configure --prefix=${LOCAL_REPO} --libdir=${LOCAL_REPO}/lib --host=${ODIE_HOST} -#fi -#make -C ${TCLLIB_SRCPATH} install +cd ${ODIE_SRCPATH} +make reconfig ADDED scripts/mingw_cross_compile.sh Index: scripts/mingw_cross_compile.sh ================================================================== --- /dev/null +++ scripts/mingw_cross_compile.sh @@ -0,0 +1,14 @@ +# +# Install tools on the mac +# sudo port install i386-mingw32-binutils i386-mingw32-gcc i386-mingw32-libunicows i386-mingw32-runtime i386-mingw32-w32api + + +CC=/opt/local/bin/i386-mingw32-gcc +CXX=/opt/local/bin/i386-mingw32-g++ +MINGWFLAGS="-mwin32 -mconsole -march=i686 " +CFLAGS="$MINGWFLAGS" +CXXFLAGS="$MINGWFLAGS" + +# +# Later configure with: +# ./configure CC=$CC CXX=$CXX --target=ix86-pc-windows ADDED scripts/sherpa.tcl Index: scripts/sherpa.tcl ================================================================== --- /dev/null +++ scripts/sherpa.tcl @@ -0,0 +1,81 @@ +#!/bin/sh +# Copyright (c) 2006-2011 WorkWare Systems http://www.workware.net.au/ +# All rights reserved +# vim:se syntax=tcl: +# \ +dir=`dirname "$0"`; exec "`$dir/../autosetup/find-tclsh`" "$0" "$@" + +### +# Micronized version of sherpa for bootstrapping Odie +### + +set path [file normalize [file join [file dirname [file normalize [info script]]] ..]] +source [file join $path scripts common.tcl] + +namespace eval ::command {} + +proc ::command::help {} { + foreach command [lsort -dictionary [info command ::command::*]] { + puts " * [namespace tail $command]" + } +} + +proc ::command::package-list {} { + foreach distro [lsort -dictionary [dict keys $::sherpa_bootstrap::distribution]] { + puts " * $distro" + } +} + +proc ::command::install {package} { + if {$package eq "all"} { + install-all + return + } + ::sherpa_bootstrap::install_package $package +} + +proc ::command::install-all {} { + set info $::sherpa_bootstrap::distribution + set allpkgs [lsort -dictionary [dict keys $info]] + set installed {} + foreach item $allpkgs { + if {[dict exists $info $item requires]} { + set requires($item) [dict get $info $item requires] + } else { + set requires($item) {} + } + } + + for {set i 0} {$i < [llength $allpkgs]} {incr i} { + foreach item $allpkgs { + if { $item in $installed } continue + set needs {} + foreach req $requires($item) { + if { $req ni $installed } { + lappend needs $req + } + } + if {[llength $needs]} { + puts [list $item needs $needs] + continue + } + lappend installed $item + } + } + foreach item $installed { + puts "INSTALLING $item" + } + foreach item $installed { + ::sherpa_bootstrap::install_package $item + } +} + +set method [lindex $argv 0] +if { [info command ::command::$method] eq {} } { + puts stderr "Invalid command: $method." + ::command::help + exit 1 +} +::command::$method {*}[lrange $argv 1 end] +update +exit 0 Index: scripts/upload.tcl ================================================================== --- scripts/upload.tcl +++ scripts/upload.tcl @@ -48,11 +48,11 @@ set fout [open index.html w] puts $fout "" puts $fout "Back to the top

" -puts $fout "Binaries tailored to $::odie(odie_binary_platform)" +puts $fout "Binaries tailored to $::odie(teacup_profile)" puts $fout "

Built and uploaded on [clock format [clock seconds]]

" set path /var/www/download/$::odie(platform)/$::odie(odie_binary_platform) ssh ${server} mkdir -p $path puts $fout "" Index: src/odielib/configure.tcl ================================================================== --- src/odielib/configure.tcl +++ src/odielib/configure.tcl @@ -2,14 +2,14 @@ # This file assembles the machine-generated portions of this # extension #### set path [file normalize [file dirname [info script]]] -set ::project(src) $path +set ::project(srcdir) $path set ::project(path) [file normalize [file dirname [file dirname $path]]] source [file join $::project(path) odieConfig.tcl] -source [file join $::odie(sandbox) odielib modules odie index.tcl] +source [file join $::project(path) ] source [file join $::odie(sandbox) odielib modules codebale index.tcl] set ::project(name) odie set ::project(pkgname) odielib set ::project(pkgvers) 2.1 @@ -24,15 +24,15 @@ /* ** This file is machine generated by the [info script] file */ }] -::cthulhu::init -::cthulhu::add_cheader_verbatim [file join $::project(path) scripts cthulhu.h] +cthulhu_init +cthulhu_add_cheader_verbatim [file join $::project(path) scripts cthulhu.h] -if {![file exists [file join $::project(src) build]]} { - file mkdir [file join $::project(src) build] +if {![file exists [file join $::project(srcdir) build]]} { + file mkdir [file join $::project(srcdir) build] } foreach file [glob -nocomplain build/*] { file delete $file } @@ -43,22 +43,22 @@ dict set config cthulhu-ignore-cfiles [list $::project(c_file) tree.c] #dict set config cthulhu-ignore-cfiles {} dict set config_module math build-ignore-cfiles quaternion.c -::cthulhu::add_directory [file join $::project(src) build] $config -::cthulhu::add_directory [file join $::project(src) generic] $config +cthulhu_add_directory [file join $::project(srcdir) build] $config +cthulhu_add_directory [file join $::project(srcdir) generic] $config if {$::tcl_platform(platform) eq "unix"} { - ::cthulhu::add_directory [file join $::project(src) unix] $config + cthulhu_add_directory [file join $::project(srcdir) unix] $config } foreach path [lsort -dictionary [glob [file join $::project(path) cmodules *]]] { if {[file exists [file join $path cthulhu.ini]]} { source [file join $path cthulhu.ini] } } -if {[file mtime [file join $::project(src) configure.in]] < [file mtime [file join $::project(path) cthulhu.ini]]} { +if {[file mtime [file join $::project(srcdir) configure.in]] < [file mtime [file join $::project(path) cthulhu.ini]]} { ### # If the cthulhu.ini file is modified, it's a tipoff that # our configuration could have changed ### ::codebale::rewrite_autoconf @@ -66,35 +66,25 @@ if {[file exists [file join $::project(path) build $::project(declfile)]]} { ### # Build our stubs definitions ### - file mkdir $::project(src)/build - ::cthulhu::mk_stub_decls $::project(pkgname) $docfileout $::project(src)/build - doexec [info nameofexecutable] [file join $::project(path) .. tcl tools genStubs.tcl] $::project(src)/build [file join $::project(path) build $::project(declfile)] -} - -### -# Build mkhdr if we don't have it -### -if {![file exists [::realpath $::odie(mkhdr)]]} { - cd $::build(odie_src_dir) - doexec $::odie(cc) -o mkhdr.o -c scripts/mkhdr.c - doexec $::odie(cc) mkhdr.o -o mkhdr$::odie(exe_suffix) - file copy -force mkhdr$::odie(exe_suffix) [::realpath ${exec_prefix}/bin/mkhdr$::odie(exe_suffix)] + file mkdir $::project(srcdir)/build + cthulhu_mk_stub_decls $::project(pkgname) $docfileout $::project(srcdir)/build + doexec [info nameofexecutable] [file join $::project(path) .. tcl tools genStubs.tcl] $::project(srcdir)/build [file join $::project(path) build $::project(declfile)] } ### # Build our libinit.c file and internal.h file ### -set hout $::project(src)/generic/$::project(h_file_int) -set docfileout $::project(src)/build/cthulhu.rc -cd $::project(src) -::cthulhu::mkhdr_index $hout $docfileout -::cthulhu::mk_lib_init.c [file join $::project(src) generic $::project(c_file)] -::cthulhu::add_dynamic [file join $::project(src) generic $::project(c_file)] [file join $::project(src) configure.tcl] -::cthulhu::add_csource [file join $::project(src) generic $::project(c_file)] +set hout $::project(srcdir)/generic/$::project(h_file_int) +set docfileout $::project(srcdir)/build/cthulhu.rc +cd $::project(srcdir) +cthulhu_mkhdr_index $hout $docfileout +cthulhu_mk_lib_init.c [file join $::project(srcdir) generic $::project(c_file)] +cthulhu_add_dynamic [file join $::project(srcdir) generic $::project(c_file)] [file join $::project(srcdir) configure.tcl] +cthulhu_add_csource [file join $::project(srcdir) generic $::project(c_file)] ### # Build our cthulhu.mk file ### -::cthulhu::mk_sources [file join $::project(src) cthulhu.mk] +cthulhu_mk_sources build [file join $::project(srcdir) cthulhu.mk] DELETED src/toadkit/Makefile Index: src/toadkit/Makefile ================================================================== --- src/toadkit/Makefile +++ /dev/null @@ -1,129 +0,0 @@ - -include ../../odieConfig.sh - -TCL_SRCROOT=${SANDBOX}/tcl -TCL_SRCPATH=${SANDBOX}/tcl/${ODIE_TCLSRC_DIR} -TK_SRCROOT=${SANDBOX}/tk -TK_SRCPATH=${SANDBOX}/tk/${ODIE_TCLSRC_DIR} -ZIPSRC_SRC = ${ODIE_SRC_DIR}/src/zip30 -PWD=${ODIE_SRC_DIR}/src/toadkit -ZLIB_DIR = ${TCL_SRCROOT}/compat/zlib -ALLPROD=tclkit${EXE} zipkit.zip -TOADKIT_EXTRA_OBJS= -include ${exec_prefix}/lib/tclkitConfig.sh -ifneq ($(TK_FOSSIL_BRANCH),none) - include ${SANDBOX}/tk/${ODIE_TCLSRC_DIR}/tkConfig.sh - ifeq ($(ODIE_PLATFORM),windows) - TK_DYLIB=${TK_DLL_FILE} - else - TK_DYLIB=${TK_LIB_FILE} - endif -endif -TK_FULL_VERSION="$(strip $(subst ', , $(TK_VERSION)))$(strip $(subst ', , $(TK_PATCH_LEVEL)))" - -builddir=build - -CC=$(subst ', , $(TCL_CC)) -CCSWITCHES=-I -KIT_INCLUDE_SPEC=-I generic -I ${ZLIB_DIR} -I ${TCL_SRCROOT}/generic -I ${TCL_SRCROOT}/${ODIE_TCLSRC_DIR} -WKIT_INCLUDE_SPEC=-I ${TK_SRCROOT}/generic -I ${TK_SRCROOT}/${ODIE_TCLSRC_DIR} -KIT_DEFS=-DTCL_USE_STATIC_PACKAGES -DSTATIC_BUILD=1 -UUSE_TCL_STUBS -# Normal -#TCL_CC_SWITCHES = $(subst ', , $(TCL_CFLAGS_OPTIMIZE) $(TCL_EXTRA_CFLAGS) $(TCL_CFLAGS_WARNING) $(TCL_SHLIB_CFLAGS) $(TCL_INCLUDE_SPEC) ${KIT_INCLUDE_SPEC} $(TCL_DEFS) $(KIT_DEFS) -Igeneric -I${ODIE_TCLSRC_DIR}) -# Debugging -TCL_CC_SWITCHES = $(subst ', , $(TCL_CFLAGS_DEBUG) $(TCL_EXTRA_CFLAGS) $(TCL_CFLAGS_WARNING) $(TCL_SHLIB_CFLAGS) $(TCL_INCLUDE_SPEC) ${KIT_INCLUDE_SPEC} $(TCL_DEFS) $(KIT_DEFS) -Igeneric -I${ODIE_TCLSRC_DIR}) - -CFLAGS=$(subst ', , $(TCL_CFLAGS_DEBUG)) -#CFLAGS=-pipe $(subst ', , ${TCL_CFLAGS_OPTIMIZE}) -DEFS=$(KIT_DEFS) -COMPILE = $(CC) $(DEFS) $(INCLUDES) $(KIT_INCLUDE_SPEC) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) - - -ZLIB_OBJS = Zadler32.o Zcompress.o Zcrc32.o Zdeflate.o Zinfback.o \ - Zinffast.o Zinflate.o Zinftrees.o Ztrees.o Zuncompr.o Zzutil.o -ZIPVFS_OBJS = $(ZLIB_OBJS) zvfs.o zvfsboot.o - -#ZIPVFS_OBJS = $(ZLIB_OBJS) zvfs.o zipmain.o \ -# crypt.o fileio.o globals.o \ -# ttyio.o util.o zbz2err.o zipfile.o zipup.o - -#ZIPVFS_OBJS = $(ZLIB_OBJS) zvfs.o zipmain.o \ -# crc32.o crypt.o deflate.o fileio.o globals.o trees.o \ -# ttyio.o util.o zbz2err.o zipfile.o zipup.o - -KIT_LIBS= - -ifeq ($(ODIE_PLATFORM),windows) - TOADKIT_EXTRA_OBJS+=$(TK_SRCPATH)/tk.res.o - TOADKIT_EXTRA_OBJS+=$(TK_SRCPATH)/wish.res.o - #ZIPVFS_OBJS += nt.o win32.o win32zip.o win32i64.o -endif - -all: ${ALLPROD} - -clean: - eval ${ODIE_RM} ${TCL_LIB_FILE} ${builddir} cthulhu.mk *.exe *.zip *.o *.c toadConfig.sh tclkit_bare${EXE} tclkit${EXE} tclkit.zip *.vfs zipkit* zzipsetup* - mkdir -p ${builddir} - -install: ${ALLPROD} - cp -f zipkit.zip ${ODIE_ZIPKIT} - cp -f tclkit${EXE} ${ODIE_TCLKIT} - -cthulhu.mk: - $(ODIE_TCLSH) configure.tcl - -include cthulhu.mk - -null.zip: - touch .empty - zip null.zip .empty - -tclkit_bare_OLD${EXE}: $(PKG_OBJECTS) - echo Built against ${TCL_FULL_VERSION} - echo KIT_LIBS $(KIT_LIBS) - $(CC) $(strip \ - $(subst ', , $(CFLAGS) $(TCL_EXTRA_CFLAGS) $(DEFS) $(TCL_LD_FLAGS)) \ - $(PKG_OBJECTS) \ - ${libdir}/${TCL_STUB_LIB_FILE} \ - ${ODIE_STATIC_TCLLIB} \ - $(subst ', , $(KIT_LIBS) $(TCL_LIBS) $(TCL_CC_SEARCH_FLAGS)) \ - $(TOADKIT_EXTRA_OBJS) \ - -o tclkit_bare${EXE}) - -tclkit_bare${EXE}: $(PKG_OBJECTS) - echo Built against ${TCL_FULL_VERSION} - echo KIT_LIBS $(KIT_LIBS) - $(CC) $(strip \ - $(subst ', , $(CFLAGS) $(TCL_EXTRA_CFLAGS) $(TCL_LD_FLAGS)) \ - $(PKG_OBJECTS) \ - ${ODIE_STATIC_TCLLIB} \ - ${libdir}/${TCL_STUB_LIB_FILE} \ - $(subst ', , $(KIT_LIBS) $(TCL_LIBS) $(TCL_CC_SEARCH_FLAGS)) \ - $(TOADKIT_EXTRA_OBJS) \ - -o tclkit_bare${EXE}) - -tclkit.vfs: -ifneq ($(TK_FOSSIL_BRANCH),none) - $(ODIE_TCLSH) mkVfs.tcl ${ODIE_PLATFORM} "$(PWD)/tclkit.vfs/boot" "$(TCL_SRCROOT)" "$(TK_SRCROOT)" "$(TK_FULL_VERSION)" "$(TK_DYLIB)" -else - $(ODIE_TCLSH) mkVfs.tcl ${ODIE_PLATFORM} "$(PWD)/tclkit.vfs/boot" "$(TCL_SRCROOT)" -endif - - -tclkit${EXE}: tclkit_bare${EXE} null.zip tclkit.vfs - cp tclkit_bare${EXE} tclkit.zip - cat null.zip >> tclkit.zip - cd $(PWD)/tclkit.vfs ; ${ZIP} -rAq ${PWD}/tclkit.zip . - mv tclkit.zip tclkit${EXE} - chmod a+x tclkit${EXE} - -zipkit.zip: - eval ${ODIE_RM} zipkit.vfs zipkit.tmp - mkdir -p zipkit.vfs - # Add files in the future... - touch zipkit.vfs/_ - cd zipkit.vfs ; $(ZIP) -rAq ../zipkit.tmp . - cp kitstrap.tcl zipkit.zip - cat zipkit.tmp >> zipkit.zip - rm zipkit.tmp - ADDED src/toadkit/Makefile.in Index: src/toadkit/Makefile.in ================================================================== --- /dev/null +++ src/toadkit/Makefile.in @@ -0,0 +1,133 @@ +include ../../odieConfig.sh + +NAME = @PKG_NAME@ +VER = @PKG_VER@ + +PKG_OBJECTS = @PKG_OBJECTS@ +PKG_SOURCES = @PKG_SOURCES@ + +TCL_SRCROOT=${SANDBOX}/tcl +TCL_SRCPATH=${SANDBOX}/tcl/${ODIE_TCL_PLATFORM_DIR} +TK_SRCROOT=${SANDBOX}/tk +TK_SRCPATH=${SANDBOX}/tk/${ODIE_TCL_PLATFORM_DIR} +ZIPSRC_SRC = ${ODIE_SRC_DIR}/src/zip30 +PWD=${ODIE_SRC_DIR}/src/toadkit +ZLIB_DIR = ${TCL_SRCROOT}/compat/zlib +ALLPROD=tclkit${EXE} zipkit.zip +TOADKIT_EXTRA_OBJS= +include ${exec_prefix}/lib/tclkitConfig.sh +ifneq ($(TK_FOSSIL_BRANCH),none) + include ${SANDBOX}/tk/${ODIE_TCL_PLATFORM_DIR}/tkConfig.sh + ifeq ($(ODIE_PLATFORM),windows) + TK_DYLIB=${TK_DLL_FILE} + else + TK_DYLIB=${TK_LIB_FILE} + endif +endif +TK_FULL_VERSION="$(strip $(subst ', , $(TK_VERSION)))$(strip $(subst ', , $(TK_PATCH_LEVEL)))" + +builddir=build + +CC=$(subst ', , $(TCL_CC)) +CCSWITCHES=-I +KIT_INCLUDE_SPEC=-I generic -I ${ZLIB_DIR} -I ${TCL_SRCROOT}/generic -I ${TCL_SRCROOT}/${ODIE_TCL_PLATFORM_DIR} +WKIT_INCLUDE_SPEC=-I ${TK_SRCROOT}/generic -I ${TK_SRCROOT}/${ODIE_TCL_PLATFORM_DIR} +KIT_DEFS=-DTCL_USE_STATIC_PACKAGES -DSTATIC_BUILD=1 -UUSE_TCL_STUBS +# Normal +#TCL_CC_SWITCHES = $(subst ', , $(TCL_CFLAGS_OPTIMIZE) $(TCL_EXTRA_CFLAGS) $(TCL_CFLAGS_WARNING) $(TCL_SHLIB_CFLAGS) $(TCL_INCLUDE_SPEC) ${KIT_INCLUDE_SPEC} $(TCL_DEFS) $(KIT_DEFS) -Igeneric -I${ODIE_TCL_PLATFORM_DIR}) +# Debugging +TCL_CC_SWITCHES = $(subst ', , $(TCL_CFLAGS_DEBUG) $(TCL_EXTRA_CFLAGS) $(TCL_CFLAGS_WARNING) $(TCL_SHLIB_CFLAGS) $(TCL_INCLUDE_SPEC) ${KIT_INCLUDE_SPEC} $(TCL_DEFS) $(KIT_DEFS) -Igeneric -I${ODIE_TCL_PLATFORM_DIR}) + +CFLAGS=$(subst ', , $(TCL_CFLAGS_DEBUG)) +#CFLAGS=-pipe $(subst ', , ${TCL_CFLAGS_OPTIMIZE}) +DEFS=$(KIT_DEFS) +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(KIT_INCLUDE_SPEC) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + + +ZLIB_OBJS = Zadler32.o Zcompress.o Zcrc32.o Zdeflate.o Zinfback.o \ + Zinffast.o Zinflate.o Zinftrees.o Ztrees.o Zuncompr.o Zzutil.o +ZIPVFS_OBJS = $(ZLIB_OBJS) zvfs.o zvfsboot.o + +#ZIPVFS_OBJS = $(ZLIB_OBJS) zvfs.o zipmain.o \ +# crypt.o fileio.o globals.o \ +# ttyio.o util.o zbz2err.o zipfile.o zipup.o + +#ZIPVFS_OBJS = $(ZLIB_OBJS) zvfs.o zipmain.o \ +# crc32.o crypt.o deflate.o fileio.o globals.o trees.o \ +# ttyio.o util.o zbz2err.o zipfile.o zipup.o + +KIT_LIBS= + +ifeq ($(ODIE_PLATFORM),windows) + TOADKIT_EXTRA_OBJS+=$(TK_SRCPATH)/tk.res.o + TOADKIT_EXTRA_OBJS+=$(TK_SRCPATH)/wish.res.o + #ZIPVFS_OBJS += nt.o win32.o win32zip.o win32i64.o +endif + +all: ${ALLPROD} + +clean: + eval ${ODIE_RM} ${TCL_LIB_FILE} ${builddir} cthulhu.mk *.exe *.zip *.o *.c toadConfig.sh tclkit_bare${EXE} tclkit${EXE} tclkit.zip *.vfs zipkit* zzipsetup* + mkdir -p ${builddir} + +install: ${ALLPROD} + cp -f tclkit${EXE} ${ODIE_TCLKIT} + +cthulhu.mk: + $(ODIE_BUILD_TCLSH) configure.tcl + +include cthulhu.mk + +null.zip: + touch .empty + zip null.zip .empty + +tclkit_bare_OLD${EXE}: $(PKG_OBJECTS) + echo Built against ${TCL_FULL_VERSION} + echo KIT_LIBS $(KIT_LIBS) + $(CC) $(strip \ + $(subst ', , $(CFLAGS) $(TCL_EXTRA_CFLAGS) $(DEFS) $(TCL_LD_FLAGS) $(ODIE_LD_FLAGS)) \ + $(PKG_OBJECTS) \ + ${libdir}/${TCL_STUB_LIB_FILE} \ + ${ODIE_STATIC_TCLLIB} \ + $(subst ', , $(KIT_LIBS) $(TCL_LIBS) $(TCL_CC_SEARCH_FLAGS)) \ + $(TOADKIT_EXTRA_OBJS) \ + -o tclkit_bare${EXE}) + +tclkit_bare${EXE}: $(PKG_OBJECTS) + echo Built against ${TCL_FULL_VERSION} + echo KIT_LIBS $(KIT_LIBS) + $(CC) $(strip \ + $(subst ', , $(CFLAGS) $(TCL_EXTRA_CFLAGS) $(TCL_LD_FLAGS) $(ODIE_LD_FLAGS)) \ + $(PKG_OBJECTS) \ + ${ODIE_STATIC_TCLLIB} \ + ${libdir}/${TCL_STUB_LIB_FILE} \ + $(subst ', , $(KIT_LIBS) $(TCL_LIBS) $(TCL_CC_SEARCH_FLAGS)) \ + $(TOADKIT_EXTRA_OBJS) \ + -o tclkit_bare${EXE}) + +tclkit.vfs: +ifneq ($(TK_FOSSIL_BRANCH),none) + $(ODIE_BUILD_TCLSH) mkVfs.tcl ${ODIE_PLATFORM} "$(PWD)/tclkit.vfs/boot" "$(TCL_SRCROOT)" "$(TK_SRCROOT)" "$(TK_FULL_VERSION)" "$(TK_DYLIB)" +else + $(ODIE_BUILD_TCLSH) mkVfs.tcl ${ODIE_PLATFORM} "$(PWD)/tclkit.vfs/boot" "$(TCL_SRCROOT)" +endif + + +tclkit${EXE}: tclkit_bare${EXE} null.zip tclkit.vfs + cp tclkit_bare${EXE} tclkit.zip + cat null.zip >> tclkit.zip + cd $(PWD)/tclkit.vfs ; ${ZIP} -rAq ${PWD}/tclkit.zip . + mv tclkit.zip tclkit${EXE} + chmod a+x tclkit${EXE} + +zipkit.zip: + eval ${ODIE_RM} zipkit.vfs zipkit.tmp + mkdir -p zipkit.vfs + # Add files in the future... + touch zipkit.vfs/_ + cd zipkit.vfs ; $(ZIP) -rAq ../zipkit.tmp . + cp kitstrap.tcl zipkit.zip + cat zipkit.tmp >> zipkit.zip + rm zipkit.tmp + Index: src/toadkit/configure.tcl ================================================================== --- src/toadkit/configure.tcl +++ src/toadkit/configure.tcl @@ -2,44 +2,46 @@ # This file assembles the machine-generated portions of this # extension #### set path [file normalize [file dirname [info script]]] -set ::project(src) $path +set ::project(srcdir) $path set ::project(path) [file normalize [file join $path .. ..]] -source [file join $::project(path) odieConfig.tcl] -source [file join $::odie(sandbox) odielib modules odie index.tcl] -source [file join $::odie(sandbox) odielib modules codebale index.tcl] -source [file join $::project(path) cthulhu.ini] +if {![info exists ::odie(host)]} { + source [file join $::project(path) scripts common.tcl] + puts "CALLED EXTERNALLY" +} +use cc system cthulhu -if {$::odie(platform) eq "windows"} { +if {$::odie(windows)} { set ::project(name) odie_static set ::project(pkgname) odielib_static } else { set ::project(name) odie set ::project(pkgname) odielib } +set ::project(pkgvers) 2.1 set ::project(h_file) $::project(name).h set ::project(h_file_int) $::project(name)Int.h -set ::project(c_file) lib${project(name)}.c -set ::project(init_funct) [string totitle ${project(name)}lib]_Init +set ::project(c_file) lib${::project(name)}.c +set ::project(init_funct) [string totitle ${::project(name)}lib]_Init set ::project(target) static -parray project +parray ::project set ::project(standard_header) [subst { /* ** This file is machine generated by the [info script] file */ }] -::cthulhu::init +cthulhu_init set ::project(h_file_int) odieInt.h -if {![file exists [file join $::project(src) build]]} { - file mkdir [file join $::project(src) build] +if {![file exists [file join $::project(srcdir) build]]} { + file mkdir [file join $::project(srcdir) build] } -::cthulhu::add_cheader_verbatim [file join $::project(path) scripts cthulhu.h] -::cthulhu::add_cheader_verbatim [file join $::project(src) generic _macros.h] +cthulhu_add_cheader_verbatim [file join $::project(path) scripts cthulhu.h] +cthulhu_add_cheader_verbatim [file join $::project(srcdir) generic _macros.h] foreach file [glob -nocomplain build/*] { file delete $file } set config {} @@ -49,93 +51,85 @@ dict set config cthulhu-ignore-cfiles [list $::project(c_file) tree.c] #dict set config cthulhu-ignore-cfiles {} dict set config_module math build-ignore-cfiles quaternion.c -#::cthulhu::add_directory [file join $::project(src) build] $config -#::cthulhu::add_directory [file join $::project(src) generic] $config +#cthulhu_add_directory [file join $::project(srcdir) build] $config +#cthulhu_add_directory [file join $::project(srcdir) generic] $config #if {$::tcl_platform(platform) eq "unix"} { -# ::cthulhu::add_directory [file join $::project(src) unix] $config +# cthulhu_add_directory [file join $::project(srcdir) unix] $config #} -#foreach path [lsort -dictionary [glob [file join $::project(path) cmodules *]]] { +#foreach path [lsort -dictionary [glob [file join $::odie(sandbox) odielib cmodules *]]] { # if {[file exists [file join $path cthulhu.ini]]} { # source [file join $path cthulhu.ini] # } #} #foreach dir {logicset odieutil} { -# set path [file join $::project(path) cmodules $dir] +# set path [file join $::odie(sandbox) odielib cmodules $dir] # if {[file exists [file join $path cthulhu.ini]]} { # source [file join $path cthulhu.ini] # } #} ### # Add our Zip file system functions ### -::cthulhu::add_csource [file join $::project(src) generic zvfs.c] {scan 0} -::cthulhu::add_csource [file join $::project(src) generic zvfsboot.c] {scan 0} +cthulhu_add_csource [file join $::project(srcdir) generic zvfs.c] {scan 0} +cthulhu_add_csource [file join $::project(srcdir) generic zvfsboot.c] {scan 0} foreach zfile { adler32.c compress.c crc32.c deflate.c infback.c inffast.c inflate.c inftrees.c trees.c uncompr.c zutil.c } { - ::cthulhu::add_csource [file join $::build(sandbox) tcl compat zlib $zfile] {scan 0} -} - -#::cthulhu::include_directory [file join $::build(sandbox) tcl compat zlib] -#::cthulhu::include_directory [file join $::build(sandbox) tcl generic] - -::cthulhu::add_csource [file join $::project(src) generic tclkit_init.c] {scan 0} -if {$::odie(platform) eq "windows"} { - #::cthulhu::include_directory [file join $::build(sandbox) tcl win] - ::cthulhu::add_csource [file join $::project(src) win tclsh_packages.c] {scan 0} - ::cthulhu::add_csource [file join $::build(sandbox) tcl win tclAppInit.c] {scan 0 extra {-DTCL_LOCAL_APPINIT=Toadkit_AppInit -DTCL_LOCAL_MAIN_HOOK=Toadkit_MainHook}} - #::cthulhu::add_csource [file join $::build(sandbox) tcl win tclWinDde.c] - ::cthulhu::add_csource [file join $::build(sandbox) tcl win tclWinReg.c] -} else { - #::cthulhu::include_directory [file join $::build(sandbox) tcl unix] - ::cthulhu::add_csource [file join $::project(src) unix tclsh_packages.c] {scan 0} - ::cthulhu::add_csource [file join $::build(sandbox) tcl unix tclAppInit.c] {scan 0 extra {-DTCL_LOCAL_APPINIT=Toadkit_AppInit -DTCL_LOCAL_MAIN_HOOK=Toadkit_MainHook}} -} -if {$::odie(platform) eq "windows"} { - if {![file exists [file join $::project(path) cmodules odieutil password.c]]} { - puts "BUILDING PASSWORD (toadkit)" - source [file join $::project(path) cmodules odieutil mkPassword.tcl] - } - ::cthulhu::add_csource [file join $::project(path) cmodules odieutil password.c] - ::cthulhu::add_csource [file join $::project(path) cmodules odieutil memory.c] - ::cthulhu::add_csource [file join $::project(path) cmodules odieutil md5.c] - ::cthulhu::add_csource [file join $::project(path) cmodules odieutil rc4.c] - ::cthulhu::add_csource [file join $::project(path) cmodules odieutil tclextra.c] -} else { - foreach path [lsort -dictionary [glob [file join $::project(path) cmodules *]]] { + cthulhu_add_csource [file join $::odie(sandbox) tcl compat zlib $zfile] {scan 0} +} + +#cthulhu_include_directory [file join $::odie_build(sandbox) tcl compat zlib] +#cthulhu_include_directory [file join $::odie_build(sandbox) tcl generic] + +cthulhu_add_csource [file join $::project(srcdir) generic tclkit_init.c] {scan 0} +if {$::odie(windows)} { + #cthulhu_include_directory [file join $::odie_build(sandbox) tcl win] + cthulhu_add_csource [file join $::project(srcdir) win tclsh_packages.c] {scan 0} + cthulhu_add_csource [file join $::odie(sandbox) tcl win tclAppInit.c] {scan 0 extra {-DTCL_LOCAL_APPINIT=Toadkit_AppInit -DTCL_LOCAL_MAIN_HOOK=Toadkit_MainHook}} + #cthulhu_add_csource [file join $::odie_build(sandbox) tcl win tclWinDde.c] + cthulhu_add_csource [file join $::odie(sandbox) tcl win tclWinReg.c] +} else { + #cthulhu_include_directory [file join $::odie_build(sandbox) tcl unix] + cthulhu_add_csource [file join $::project(srcdir) unix tclsh_packages.c] {scan 0} + cthulhu_add_csource [file join $::odie(sandbox) tcl unix tclAppInit.c] {scan 0 extra {-DTCL_LOCAL_APPINIT=Toadkit_AppInit -DTCL_LOCAL_MAIN_HOOK=Toadkit_MainHook}} +} +if {$::odie(windows)} { + if {![file exists [file join $::odie(sandbox) odielib cmodules odieutil password.c]]} { + puts "BUILDING PASSWORD (toadkit)" + source [file join $::odie(sandbox) odielib cmodules odieutil mkPassword.tcl] + } + cthulhu_add_csource [file join $::odie(sandbox) odielib cmodules odieutil password.c] + cthulhu_add_csource [file join $::odie(sandbox) odielib cmodules odieutil memory.c] + cthulhu_add_csource [file join $::odie(sandbox) odielib cmodules odieutil md5.c] + cthulhu_add_csource [file join $::odie(sandbox) odielib cmodules odieutil rc4.c] + cthulhu_add_csource [file join $::odie(sandbox) odielib cmodules odieutil tclextra.c] +} else { + foreach path [lsort -dictionary [glob [file join $::odie(sandbox) odielib cmodules *]]] { if {[file exists [file join $path cthulhu.ini]]} { source [file join $path cthulhu.ini] } } } -### -# Build mkhdr if we don't have it -### -if {![file exists [::realpath $::odie(mkhdr)]]} { - cd $::build(odie_src_dir) - doexec $::odie(cc) -o mkhdr.o -c scripts/mkhdr.c - doexec $::odie(cc) mkhdr.o -o mkhdr$::odie(exe_suffix) - file copy -force mkhdr$::odie(exe_suffix) [::realpath ${exec_prefix}/bin/mkhdr$::odie(exe_suffix)] -} ### # Build our libinit.c file and internal.h file ### -set hout $::project(src)/generic/$::project(h_file_int) -set docfileout $::project(src)/build/cthulhu.rc -cd $::project(src) -::cthulhu::mkhdr_index $hout $docfileout -::cthulhu::mk_app_init.c [file join $::project(src) generic $::project(c_file)] -::cthulhu::add_dynamic [file join $::project(src) generic $::project(c_file)] [file join $::project(src) configure.tcl] -::cthulhu::add_csource [file join $::project(src) generic $::project(c_file)] {scan 0} +set hout $::project(srcdir)/generic/$::project(h_file_int) +set docfileout $::project(srcdir)/build/cthulhu.rc +cd $::project(srcdir) +cthulhu_mkhdr_index $hout $docfileout +cthulhu_mk_app_init.c [file join $::project(srcdir) generic $::project(c_file)] +cthulhu_add_dynamic [file join $::project(srcdir) generic $::project(c_file)] [file join $::project(srcdir) configure.tcl] +cthulhu_add_csource [file join $::project(srcdir) generic $::project(c_file)] {scan 0} ### # Build our cthulhu.mk file ### -::cthulhu::mk_sources [file join $::project(src) cthulhu.mk] +cthulhu_mk_sources build [file join $::project(srcdir) cthulhu.mk] +make-template [file join $::project(srcdir) Makefile.in]